Merge pull request #14256 from greenpeace-cee/innodb-log-tables
[civicrm-core.git] / CRM / Event / Form / Registration / Confirm.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 5 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2019 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
9 | |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
13 | |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
18 | |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
26 */
27
28 /**
29 * @package CRM
30 * @copyright CiviCRM LLC (c) 2004-2019
31 */
32
33 /**
34 * This class generates form components for processing Event.
35 */
36 class CRM_Event_Form_Registration_Confirm extends CRM_Event_Form_Registration {
37 use CRM_Financial_Form_FrontEndPaymentFormTrait;
38
39 /**
40 * The values for the contribution db object.
41 *
42 * @var array
43 */
44 public $_values;
45
46 /**
47 * The total amount.
48 *
49 * @var float
50 */
51 public $_totalAmount;
52
53 public $submitOnce = TRUE;
54
55 /**
56 * Monetary fields that may be submitted.
57 *
58 * These should get a standardised format in the beginPostProcess function.
59 *
60 * These fields are common to many forms. Some may override this.
61 * @var array
62 */
63 protected $submittableMoneyFields = ['total_amount', 'net_amount', 'non_deductible_amount', 'fee_amount', 'tax_amount', 'amount'];
64
65 /**
66 * Set variables up before form is built.
67 */
68 public function preProcess() {
69 parent::preProcess();
70
71 // lineItem isn't set until Register postProcess
72 $this->_lineItem = $this->get('lineItem');
73
74 $this->_params = $this->get('params');
75 $this->_params[0]['tax_amount'] = $this->get('tax_amount');
76
77 $this->_params[0]['is_pay_later'] = $this->get('is_pay_later');
78 $this->assign('is_pay_later', $this->_params[0]['is_pay_later']);
79 if ($this->_params[0]['is_pay_later']) {
80 $this->assign('pay_later_receipt', $this->_values['event']['pay_later_receipt']);
81 }
82
83 CRM_Utils_Hook::eventDiscount($this, $this->_params);
84
85 if (!empty($this->_params[0]['discount']) && !empty($this->_params[0]['discount']['applied'])) {
86 $this->set('hookDiscount', $this->_params[0]['discount']);
87 $this->assign('hookDiscount', $this->_params[0]['discount']);
88 }
89
90 if (!$this->preProcessExpress()) {
91 //process only primary participant params.
92 $registerParams = $this->_params[0];
93 if (isset($registerParams["billing_state_province_id-{$this->_bltID}"])
94 && $registerParams["billing_state_province_id-{$this->_bltID}"]
95 ) {
96 $registerParams["billing_state_province-{$this->_bltID}"] = CRM_Core_PseudoConstant::stateProvinceAbbreviation($registerParams["billing_state_province_id-{$this->_bltID}"]);
97 }
98
99 if (isset($registerParams["billing_country_id-{$this->_bltID}"]) && $registerParams["billing_country_id-{$this->_bltID}"]) {
100 $registerParams["billing_country-{$this->_bltID}"] = CRM_Core_PseudoConstant::countryIsoCode($registerParams["billing_country_id-{$this->_bltID}"]);
101 }
102 if (isset($registerParams['credit_card_exp_date'])) {
103 $registerParams['year'] = CRM_Core_Payment_Form::getCreditCardExpirationYear($registerParams);
104 $registerParams['month'] = CRM_Core_Payment_Form::getCreditCardExpirationMonth($registerParams);
105 }
106 if ($this->_values['event']['is_monetary']) {
107 $registerParams['ip_address'] = CRM_Utils_System::ipAddress();
108 $registerParams['currencyID'] = $this->_params[0]['currencyID'];
109 }
110 //assign back primary participant params.
111 $this->_params[0] = $registerParams;
112 }
113
114 if ($this->_values['event']['is_monetary']) {
115 $this->_params[0]['invoiceID'] = $this->get('invoiceID');
116 }
117 $this->assign('defaultRole', FALSE);
118 if (CRM_Utils_Array::value('defaultRole', $this->_params[0]) == 1) {
119 $this->assign('defaultRole', TRUE);
120 }
121
122 if (empty($this->_params[0]['participant_role_id']) &&
123 $this->_values['event']['default_role_id']
124 ) {
125 $this->_params[0]['participant_role_id'] = $this->_values['event']['default_role_id'];
126 }
127
128 if (isset($this->_values['event']['confirm_title'])) {
129 CRM_Utils_System::setTitle($this->_values['event']['confirm_title']);
130 }
131
132 // Personal campaign page
133 if ($this->_pcpId) {
134 $params = CRM_Contribute_Form_Contribution_Confirm::processPcp($this, $this->_params[0]);
135 $this->_params[0] = $params;
136 }
137
138 $this->set('params', $this->_params);
139 }
140
141 /**
142 * Pre process function for Paypal Express confirm.
143 * @todo this is just a step in refactor as payment processor specific code does not belong in generic forms
144 *
145 * @return bool
146 * @throws \CRM_Core_Exception
147 */
148 private function preProcessExpress() {
149 if ($this->_contributeMode !== 'express') {
150 return FALSE;
151 }
152 $params = [];
153 // rfp == redirect from paypal
154 // @fixme rfp is probably not required - the getPreApprovalDetails should deal with any payment-processor specific 'stuff'
155 $rfp = CRM_Utils_Request::retrieve('rfp', 'Boolean', CRM_Core_DAO::$_nullObject, FALSE, NULL, 'GET');
156
157 //we lost rfp in case of additional participant. So set it explicitly.
158 if ($rfp || CRM_Utils_Array::value('additional_participants', $this->_params[0], FALSE)) {
159 if (!empty($this->_paymentProcessor) && $this->_paymentProcessor['object']->supports('preApproval')) {
160 $preApprovalParams = $this->_paymentProcessor['object']->getPreApprovalDetails($this->get('pre_approval_parameters'));
161 $params = array_merge($this->_params, $preApprovalParams);
162 }
163 CRM_Core_Payment_Form::mapParams($this->_bltID, $params, $params, FALSE);
164
165 // set a few other parameters that are not really specific to this method because we don't know what
166 // will break if we change this.
167 $params['amount'] = $this->_params[0]['amount'];
168 if (!empty($this->_params[0]['discount'])) {
169 $params['discount'] = $this->_params[0]['discount'];
170 $params['discountAmount'] = $this->_params[0]['discountAmount'];
171 $params['discountMessage'] = $this->_params[0]['discountMessage'];
172 }
173
174 $params['amount_level'] = $this->_params[0]['amount_level'];
175 $params['currencyID'] = $this->_params[0]['currencyID'];
176
177 // also merge all the other values from the profile fields
178 $values = $this->controller->exportValues('Register');
179 $skipFields = [
180 'amount',
181 "street_address-{$this->_bltID}",
182 "city-{$this->_bltID}",
183 "state_province_id-{$this->_bltID}",
184 "postal_code-{$this->_bltID}",
185 "country_id-{$this->_bltID}",
186 ];
187
188 foreach ($values as $name => $value) {
189 // skip amount field
190 if (!in_array($name, $skipFields)) {
191 $params[$name] = $value;
192 }
193 if (substr($name, 0, 6) == 'price_') {
194 $params[$name] = $this->_params[0][$name];
195 }
196 }
197 $this->set('getExpressCheckoutDetails', $params);
198 }
199 $this->_params[0] = array_merge($this->_params[0], $params);
200 $this->_params[0]['is_primary'] = 1;
201 return TRUE;
202 }
203
204 /**
205 * Overwrite action, since we are only showing elements in frozen mode no help display needed.
206 *
207 * @return int
208 */
209 public function getAction() {
210 if ($this->_action & CRM_Core_Action::PREVIEW) {
211 return CRM_Core_Action::VIEW | CRM_Core_Action::PREVIEW;
212 }
213 else {
214 return CRM_Core_Action::VIEW;
215 }
216 }
217
218 /**
219 * Build the form object.
220 */
221 public function buildQuickForm() {
222 $this->assignToTemplate();
223
224 if ($this->_values['event']['is_monetary'] &&
225 ($this->_params[0]['amount'] || $this->_params[0]['amount'] == 0) &&
226 !$this->_requireApproval
227 ) {
228 $this->_amount = [];
229
230 $taxAmount = 0;
231 foreach ($this->_params as $k => $v) {
232 if ($v == 'skip') {
233 continue;
234 }
235 $individualTaxAmount = 0;
236 //display tax amount on confirmation page
237 $taxAmount += $v['tax_amount'];
238 if (is_array($v)) {
239 $this->cleanMoneyFields($v);
240 foreach ([
241 'first_name',
242 'last_name',
243 ] as $name) {
244 if (isset($v['billing_' . $name]) &&
245 !isset($v[$name])
246 ) {
247 $v[$name] = $v['billing_' . $name];
248 }
249 }
250
251 if (!empty($v['first_name']) && !empty($v['last_name'])) {
252 $append = $v['first_name'] . ' ' . $v['last_name'];
253 }
254 else {
255 //use an email if we have one
256 foreach ($v as $v_key => $v_val) {
257 if (substr($v_key, 0, 6) == 'email-') {
258 $append = $v[$v_key];
259 }
260 }
261 }
262
263 $this->_amount[$k]['amount'] = $v['amount'];
264 if (!empty($v['discountAmount'])) {
265 $this->_amount[$k]['amount'] -= $v['discountAmount'];
266 }
267
268 $this->_amount[$k]['label'] = preg_replace('/\ 1/', '', $v['amount_level']) . ' - ' . $append;
269 $this->_part[$k]['info'] = CRM_Utils_Array::value('first_name', $v) . ' ' . CRM_Utils_Array::value('last_name', $v);
270 if (empty($v['first_name'])) {
271 $this->_part[$k]['info'] = $append;
272 }
273
274 /*CRM-16320 */
275 $individual[$k]['totalAmtWithTax'] = $this->_amount[$k]['amount'];
276 $individual[$k]['totalTaxAmt'] = $individualTaxAmount + $v['tax_amount'];
277 $this->_totalAmount = $this->_totalAmount + $this->_amount[$k]['amount'];
278 if (!empty($v['is_primary'])) {
279 $this->set('primaryParticipantAmount', $this->_amount[$k]['amount']);
280 }
281 }
282 }
283
284 $invoiceSettings = Civi::settings()->get('contribution_invoice_settings');
285 $taxTerm = CRM_Utils_Array::value('tax_term', $invoiceSettings);
286 $invoicing = CRM_Utils_Array::value('invoicing', $invoiceSettings);
287 if ($invoicing) {
288 $this->assign('totalTaxAmount', $taxAmount);
289 $this->assign('taxTerm', $taxTerm);
290 $this->assign('individual', $individual);
291 $this->set('individual', $individual);
292 }
293
294 $this->assign('part', $this->_part);
295 $this->set('part', $this->_part);
296 $this->assign('amounts', $this->_amount);
297 $this->assign('totalAmount', $this->_totalAmount);
298 $this->set('totalAmount', $this->_totalAmount);
299 }
300
301 if ($this->_priceSetId && !CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceSet', $this->_priceSetId, 'is_quick_config')) {
302 $lineItemForTemplate = [];
303 if (!empty($this->_lineItem) && is_array($this->_lineItem)) {
304 foreach ($this->_lineItem as $key => $value) {
305 if (!empty($value)) {
306 $lineItemForTemplate[$key] = $value;
307 }
308 }
309 }
310 if (!empty($lineItemForTemplate)) {
311 $this->assignLineItemsToTemplate($lineItemForTemplate);
312 }
313 }
314
315 //display additional participants profile.
316 self::assignProfiles($this);
317
318 //consider total amount.
319 $this->assign('isAmountzero', ($this->_totalAmount <= 0) ? TRUE : FALSE);
320
321 $contribButton = ts('Continue');
322 $this->addButtons([
323 [
324 'type' => 'back',
325 'name' => ts('Go Back'),
326 ],
327 [
328 'type' => 'next',
329 'name' => $contribButton,
330 'isDefault' => TRUE,
331 ],
332 ]);
333
334 $defaults = [];
335 $fields = [];
336 if (!empty($this->_fields)) {
337 foreach ($this->_fields as $name => $dontCare) {
338 $fields[$name] = 1;
339 }
340 }
341 $fields["billing_state_province-{$this->_bltID}"] = $fields["billing_country-{$this->_bltID}"] = $fields["email-{$this->_bltID}"] = 1;
342 foreach ($fields as $name => $dontCare) {
343 if (isset($this->_params[0][$name])) {
344 $defaults[$name] = $this->_params[0][$name];
345 if (substr($name, 0, 7) == 'custom_') {
346 $timeField = "{$name}_time";
347 if (isset($this->_params[0][$timeField])) {
348 $defaults[$timeField] = $this->_params[0][$timeField];
349 }
350 if (isset($this->_params[0]["{$name}_id"])) {
351 $defaults["{$name}_id"] = $this->_params[0]["{$name}_id"];
352 }
353 }
354 elseif (in_array($name, CRM_Contact_BAO_Contact::$_greetingTypes)
355 && !empty($this->_params[0][$name . '_custom'])
356 ) {
357 $defaults[$name . '_custom'] = $this->_params[0][$name . '_custom'];
358 }
359 }
360 }
361
362 $this->setDefaults($defaults);
363 $this->freeze();
364
365 //lets give meaningful status message, CRM-4320.
366 $this->assign('isOnWaitlist', $this->_allowWaitlist);
367 $this->assign('isRequireApproval', $this->_requireApproval);
368
369 // Assign Participant Count to Lineitem Table
370 $this->assign('pricesetFieldsCount', CRM_Price_BAO_PriceSet::getPricesetCount($this->_priceSetId));
371 $this->addFormRule(['CRM_Event_Form_Registration_Confirm', 'formRule'], $this);
372 }
373
374 /**
375 * Apply form rule.
376 *
377 * @param array $fields
378 * @param array $files
379 * @param CRM_Core_Form $self
380 *
381 * @return array|bool
382 */
383 public static function formRule($fields, $files, $self) {
384 $errors = [];
385 $eventFull = CRM_Event_BAO_Participant::eventFull($self->_eventId, FALSE, CRM_Utils_Array::value('has_waitlist', $self->_values['event']));
386 if ($eventFull && empty($self->_allowConfirmation)) {
387 if (empty($self->_allowWaitlist)) {
388 CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/event/register', "reset=1&id={$self->_eventId}", FALSE, NULL, FALSE, TRUE));
389 }
390 }
391 $self->_feeBlock = $self->_values['fee'];
392 CRM_Event_Form_Registration_Register::formatFieldsForOptionFull($self);
393
394 if (!empty($self->_priceSetId) &&
395 !$self->_requireApproval && !$self->_allowWaitlist
396 ) {
397 $priceSetErrors = self::validatePriceSet($self, $self->_params);
398 if (!empty($priceSetErrors)) {
399 CRM_Core_Session::setStatus(ts('You have been returned to the start of the registration process and any sold out events have been removed from your selections. You will not be able to continue until you review your booking and select different events if you wish.'), ts('Unfortunately some of your options have now sold out for one or more participants.'), 'error');
400 CRM_Core_Session::setStatus(ts('Please note that the options which are marked or selected are sold out for participant being viewed.'), ts('Sold out:'), 'error');
401 CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/event/register', "_qf_Register_display=true&qfKey={$fields['qfKey']}"));
402 }
403 }
404
405 return empty($priceSetErrors) ? TRUE : $priceSetErrors;
406 }
407
408 /**
409 * Process the form submission.
410 */
411 public function postProcess() {
412 $now = date('YmdHis');
413
414 $this->_params = $this->get('params');
415 $this->cleanMoneyFields($this->_params);
416
417 if (!empty($this->_params[0]['contact_id'])) {
418 // unclear when this would be set & whether it could be checked in getContactID.
419 // perhaps it relates to when cid is in the url
420 //@todo someone who knows add comments on the various contactIDs in this form
421 $contactID = $this->_params[0]['contact_id'];
422 }
423 else {
424 $contactID = $this->getContactID();
425 }
426
427 // if a discount has been applied, lets now deduct it from the amount
428 // and fix the fee level
429 if (!empty($this->_params[0]['discount']) && !empty($this->_params[0]['discount']['applied'])) {
430 foreach ($this->_params as $k => $v) {
431 if (CRM_Utils_Array::value('amount', $this->_params[$k]) > 0 && !empty($this->_params[$k]['discountAmount'])) {
432 $this->_params[$k]['amount'] -= $this->_params[$k]['discountAmount'];
433 $this->_params[$k]['amount_level'] .= CRM_Utils_Array::value('discountMessage', $this->_params[$k]);
434 }
435 }
436 $this->set('params', $this->_params);
437 }
438
439 // CRM-4320, lets build array of cancelled additional participant ids
440 // those are drop or skip by primary at the time of confirmation.
441 // get all in and then unset those we want to process.
442 $cancelledIds = $this->_additionalParticipantIds;
443
444 $params = $this->_params;
445 if ($this->_values['event']['is_monetary']) {
446 $this->set('finalAmount', $this->_amount);
447 }
448 $participantCount = [];
449 $taxAmount = $totalTaxAmount = 0;
450
451 //unset the skip participant from params.
452 //build the $participantCount array.
453 //maintain record for all participants.
454 foreach ($params as $participantNum => $record) {
455 if ($record == 'skip') {
456 unset($params[$participantNum]);
457 $participantCount[$participantNum] = 'skip';
458 }
459 elseif ($participantNum) {
460 $participantCount[$participantNum] = 'participant';
461 }
462 $totalTaxAmount += CRM_Utils_Array::value('tax_amount', $record, 0);
463 if (CRM_Utils_Array::value('is_primary', $record)) {
464 $taxAmount = &$params[$participantNum]['tax_amount'];
465 }
466 //lets get additional participant id to cancel.
467 if ($this->_allowConfirmation && is_array($cancelledIds)) {
468 $additonalId = CRM_Utils_Array::value('participant_id', $record);
469 if ($additonalId && $key = array_search($additonalId, $cancelledIds)) {
470 unset($cancelledIds[$key]);
471 }
472 }
473 }
474 $taxAmount = $totalTaxAmount;
475 $payment = $registerByID = $primaryCurrencyID = $contribution = NULL;
476 $paymentObjError = ts('The system did not record payment details for this payment and so could not process the transaction. Please report this error to the site administrator.');
477
478 $this->participantIDS = [];
479 $fields = [];
480 foreach ($params as $key => $value) {
481 CRM_Event_Form_Registration_Confirm::fixLocationFields($value, $fields, $this);
482 //unset the billing parameters if it is pay later mode
483 //to avoid creation of billing location
484 // @todo - the reasoning for this is unclear - elsewhere we check what fields are provided by
485 // the form & if billing fields exist we create the address, relying on the form to collect
486 // only information we intend to store.
487 if ($this->_allowWaitlist
488 || $this->_requireApproval
489 || (!empty($value['is_pay_later']) && !$this->_isBillingAddressRequiredForPayLater)
490 || empty($value['is_primary'])
491 ) {
492 $billingFields = [
493 "email-{$this->_bltID}",
494 'billing_first_name',
495 'billing_middle_name',
496 'billing_last_name',
497 "billing_street_address-{$this->_bltID}",
498 "billing_city-{$this->_bltID}",
499 "billing_state_province-{$this->_bltID}",
500 "billing_state_province_id-{$this->_bltID}",
501 "billing_postal_code-{$this->_bltID}",
502 "billing_country-{$this->_bltID}",
503 "billing_country_id-{$this->_bltID}",
504 "address_name-{$this->_bltID}",
505 ];
506 foreach ($billingFields as $field) {
507 unset($value[$field]);
508 }
509 if (!empty($value['is_pay_later'])) {
510 $this->_values['params']['is_pay_later'] = TRUE;
511 }
512 }
513
514 //Unset ContactID for additional participants and set RegisterBy Id.
515 if (empty($value['is_primary'])) {
516 $contactID = CRM_Utils_Array::value('contact_id', $value);
517 $registerByID = $this->get('registerByID');
518 if ($registerByID) {
519 $value['registered_by_id'] = $registerByID;
520 }
521 }
522 else {
523 $value['amount'] = $this->_totalAmount;
524 }
525
526 $contactID = CRM_Event_Form_Registration_Confirm::updateContactFields($contactID, $value, $fields, $this);
527
528 // lets store the contactID in the session
529 // we dont store in userID in case the user is doing multiple
530 // transactions etc
531 // for things like tell a friend
532 if (!$this->getContactID() && !empty($value['is_primary'])) {
533 CRM_Core_Session::singleton()->set('transaction.userID', $contactID);
534 }
535
536 $value['description'] = ts('Online Event Registration') . ': ' . $this->_values['event']['title'];
537 $value['accountingCode'] = CRM_Utils_Array::value('accountingCode',
538 $this->_values['event']
539 );
540
541 $pending = FALSE;
542 if ($this->_allowWaitlist || $this->_requireApproval) {
543 //get the participant statuses.
544 $waitingStatuses = CRM_Event_PseudoConstant::participantStatus(NULL, "class = 'Waiting'");
545 if ($this->_allowWaitlist) {
546 $value['participant_status_id'] = $value['participant_status'] = array_search('On waitlist', $waitingStatuses);
547 }
548 else {
549 $value['participant_status_id'] = $value['participant_status'] = array_search('Awaiting approval', $waitingStatuses);
550 }
551
552 //there might be case user selected pay later and
553 //now becomes part of run time waiting list.
554 $value['is_pay_later'] = FALSE;
555 }
556 elseif ($this->_values['event']['is_monetary']) {
557 // required only if paid event
558 if (is_array($this->_paymentProcessor)) {
559 $payment = $this->_paymentProcessor['object'];
560 }
561 if (!empty($this->_paymentProcessor) && $this->_paymentProcessor['object']->supports('preApproval')) {
562 $preApprovalParams = $this->_paymentProcessor['object']->getPreApprovalDetails($this->get('pre_approval_parameters'));
563 $value = array_merge($value, $preApprovalParams);
564 }
565 $result = NULL;
566
567 if (!empty($value['is_pay_later']) ||
568 $value['amount'] == 0 ||
569 // The concept of contributeMode is deprecated.
570 $this->_contributeMode == 'checkout' ||
571 $this->_contributeMode == 'notify'
572 ) {
573 if ($value['amount'] != 0) {
574 $pending = TRUE;
575 //get the participant statuses.
576 $pendingStatuses = CRM_Event_PseudoConstant::participantStatus(NULL, "class = 'Pending'");
577 $status = !empty($value['is_pay_later']) ? 'Pending from pay later' : 'Pending from incomplete transaction';
578 $value['participant_status_id'] = $value['participant_status'] = array_search($status, $pendingStatuses);
579 }
580 }
581 elseif (!empty($value['is_primary'])) {
582 CRM_Core_Payment_Form::mapParams($this->_bltID, $value, $value, TRUE);
583 // payment email param can be empty for _bltID mapping
584 // thus provide mapping for it with a different email value
585 if (empty($value['email'])) {
586 $value['email'] = CRM_Utils_Array::valueByRegexKey('/^email-/', $value);
587 }
588
589 if (is_object($payment)) {
590 // Not quite sure why we don't just user $value since it contains the data
591 // from result
592 // @todo ditch $result & retest.
593 list($result, $value) = $this->processPayment($payment, $value);
594 }
595 else {
596 CRM_Core_Error::fatal($paymentObjError);
597 }
598 }
599
600 $value['receive_date'] = $now;
601 if ($this->_allowConfirmation) {
602 $value['participant_register_date'] = $this->_values['participant']['register_date'];
603 }
604
605 $createContrib = ($value['amount'] != 0) ? TRUE : FALSE;
606 // force to create zero amount contribution, CRM-5095
607 if (!$createContrib && ($value['amount'] == 0)
608 && $this->_priceSetId && $this->_lineItem
609 ) {
610 $createContrib = TRUE;
611 }
612
613 if ($createContrib && !empty($value['is_primary']) &&
614 !$this->_allowWaitlist && !$this->_requireApproval
615 ) {
616 // if paid event add a contribution record
617 //if primary participant contributing additional amount
618 //append (multiple participants) to its fee level. CRM-4196.
619 $isAdditionalAmount = FALSE;
620 if (count($params) > 1) {
621 $isAdditionalAmount = TRUE;
622 }
623
624 //passing contribution id is already registered.
625 $contribution = self::processContribution($this, $value, $result, $contactID, $pending, $isAdditionalAmount, $this->_paymentProcessor);
626 $value['contributionID'] = $contribution->id;
627 $value['contributionTypeID'] = $contribution->financial_type_id;
628 $value['receive_date'] = $contribution->receive_date;
629 $value['trxn_id'] = $contribution->trxn_id;
630 $value['contributionID'] = $contribution->id;
631 $value['contributionTypeID'] = $contribution->financial_type_id;
632 }
633 $value['contactID'] = $contactID;
634 $value['eventID'] = $this->_eventId;
635 $value['item_name'] = $value['description'];
636 }
637
638 if (!empty($value['contributionID'])) {
639 $this->_values['contributionId'] = $value['contributionID'];
640 }
641
642 //CRM-4453.
643 if (!empty($value['is_primary'])) {
644 $primaryCurrencyID = CRM_Utils_Array::value('currencyID', $value);
645 }
646 if (empty($value['currencyID'])) {
647 $value['currencyID'] = $primaryCurrencyID;
648 }
649
650 // CRM-11182 - Confirmation page might not be monetary
651 if ($this->_values['event']['is_monetary']) {
652 if (!$pending && !empty($value['is_primary']) &&
653 !$this->_allowWaitlist && !$this->_requireApproval
654 ) {
655 // transactionID & receive date required while building email template
656 $this->assign('trxn_id', CRM_Utils_Array::value('trxn_id', $value));
657 $this->assign('receive_date', CRM_Utils_Date::mysqlToIso(CRM_Utils_Array::value('receive_date', $value)));
658 $this->set('receiveDate', CRM_Utils_Date::mysqlToIso(CRM_Utils_Array::value('receive_date', $value)));
659 $this->set('trxnId', CRM_Utils_Array::value('trxn_id', $value));
660 }
661 }
662
663 $value['fee_amount'] = CRM_Utils_Array::value('amount', $value);
664 $this->set('value', $value);
665
666 // handle register date CRM-4320
667 if ($this->_allowConfirmation) {
668 $registerDate = CRM_Utils_Array::value('participant_register_date', $params);
669 }
670 elseif (!empty($params['participant_register_date']) &&
671 is_array($params['participant_register_date']) &&
672 !empty($params['participant_register_date'])
673 ) {
674 $registerDate = CRM_Utils_Date::format($params['participant_register_date']);
675 }
676 else {
677 $registerDate = date('YmdHis');
678 }
679 $this->assign('register_date', $registerDate);
680
681 $this->confirmPostProcess($contactID, $contribution, $payment);
682 }
683
684 //handle if no additional participant.
685 if (!$registerByID) {
686 $registerByID = $this->get('registerByID');
687 }
688
689 $this->set('participantIDs', $this->_participantIDS);
690
691 // create line items, CRM-5313
692 if ($this->_priceSetId &&
693 !empty($this->_lineItem)
694 ) {
695 // take all processed participant ids.
696 $allParticipantIds = $this->_participantIDS;
697
698 // when participant re-walk wizard.
699 if ($this->_allowConfirmation &&
700 !empty($this->_additionalParticipantIds)
701 ) {
702 $allParticipantIds = array_merge([$registerByID], $this->_additionalParticipantIds);
703 }
704
705 $entityTable = 'civicrm_participant';
706 $invoiceSettings = Civi::settings()->get('contribution_invoice_settings');
707 $invoicing = CRM_Utils_Array::value('invoicing', $invoiceSettings);
708 $totalTaxAmount = 0;
709 $dataArray = [];
710 foreach ($this->_lineItem as $key => $value) {
711 if ($value == 'skip') {
712 continue;
713 }
714 if ($entityId = CRM_Utils_Array::value($key, $allParticipantIds)) {
715 // do cleanup line items if participant re-walking wizard.
716 if ($this->_allowConfirmation) {
717 CRM_Price_BAO_LineItem::deleteLineItems($entityId, $entityTable);
718 }
719 $lineItem[$this->_priceSetId] = $value;
720 CRM_Price_BAO_LineItem::processPriceSet($entityId, $lineItem, $contribution, $entityTable);
721 }
722 if ($invoicing) {
723 foreach ($value as $line) {
724 if (isset($line['tax_amount']) && isset($line['tax_rate'])) {
725 $totalTaxAmount = $line['tax_amount'] + $totalTaxAmount;
726 if (isset($dataArray[$line['tax_rate']])) {
727 $dataArray[$line['tax_rate']] = $dataArray[$line['tax_rate']] + CRM_Utils_Array::value('tax_amount', $line);
728 }
729 else {
730 $dataArray[$line['tax_rate']] = CRM_Utils_Array::value('tax_amount', $line);
731 }
732 }
733 }
734 }
735 }
736 if ($invoicing) {
737 $this->assign('dataArray', $dataArray);
738 $this->assign('totalTaxAmount', $totalTaxAmount);
739 }
740 }
741
742 //update status and send mail to cancelled additional participants, CRM-4320
743 if ($this->_allowConfirmation && is_array($cancelledIds) && !empty($cancelledIds)) {
744 $cancelledId = array_search('Cancelled',
745 CRM_Event_PseudoConstant::participantStatus(NULL, "class = 'Negative'")
746 );
747 CRM_Event_BAO_Participant::transitionParticipants($cancelledIds, $cancelledId);
748 }
749
750 $isTest = FALSE;
751 if ($this->_action & CRM_Core_Action::PREVIEW) {
752 $isTest = TRUE;
753 }
754
755 // for Transfer checkout.
756 // The concept of contributeMode is deprecated.
757 if (($this->_contributeMode == 'checkout' ||
758 $this->_contributeMode == 'notify'
759 ) && empty($params[0]['is_pay_later']) &&
760 !$this->_allowWaitlist && !$this->_requireApproval &&
761 $this->_totalAmount > 0
762 ) {
763
764 $primaryParticipant = $this->get('primaryParticipant');
765
766 if (empty($primaryParticipant['participantID'])) {
767 $primaryParticipant['participantID'] = $registerByID;
768 }
769
770 //build an array of custom profile and assigning it to template
771 $customProfile = CRM_Event_BAO_Event::buildCustomProfile($registerByID, $this->_values, NULL, $isTest);
772 if (count($customProfile)) {
773 $this->assign('customProfile', $customProfile);
774 $this->set('customProfile', $customProfile);
775 }
776
777 // do a transfer only if a monetary payment greater than 0
778 if ($this->_values['event']['is_monetary'] && $primaryParticipant) {
779 if ($payment && is_object($payment)) {
780 //CRM 14512 provide line items of all participants to payment gateway
781 $primaryContactId = $this->get('primaryContactId');
782
783 //build an array of cId/pId of participants
784 $additionalIDs = CRM_Event_BAO_Event::buildCustomProfile($registerByID, NULL, $primaryContactId, $isTest, TRUE);
785
786 //need to copy, since we are unsetting on the way.
787 $copyParticipantCountLines = $participantCount;
788
789 //lets carry all participant params w/ values.
790 foreach ($additionalIDs as $participantID => $contactId) {
791 $participantNum = NULL;
792 $participantNum = $participantID;
793 if ($participantID == $registerByID) {
794 // This is the is primary participant.
795 $participantNum = 0;
796 }
797 else {
798 if ($participantNum = array_search('participant', $copyParticipantCountLines)) {
799 //if no participant found break.
800 if ($participantNum === NULL) {
801 break;
802 }
803 //unset current participant so we don't check them again
804 unset($copyParticipantCountLines[$participantNum]);
805 }
806 }
807 // get values of line items
808 if ($this->_amount) {
809 $amount = [];
810 $amount[$participantNum]['label'] = preg_replace('/\ 1/', '', $params[$participantNum]['amount_level']);
811 $amount[$participantNum]['amount'] = $params[$participantNum]['amount'];
812 $params[$participantNum]['amounts'] = $amount;
813 }
814
815 if (!empty($this->_lineItem)) {
816 $lineItems = $this->_lineItem;
817 $lineItem = [];
818 if ($lineItemValue = CRM_Utils_Array::value($participantNum, $lineItems)) {
819 $lineItem[] = $lineItemValue;
820 }
821 $params[$participantNum]['lineItem'] = $lineItem;
822 }
823
824 //only add additional particpants and not the primary particpant as we already have that
825 //added to $primaryParticipant so that this change doesn't break or require changes to
826 //existing gateway implementations
827 $primaryParticipant['participants_info'][$participantID] = $params[$participantNum];
828 }
829
830 //get event custom field information
831 $groupTree = CRM_Core_BAO_CustomGroup::getTree('Event', NULL, $this->_eventId, 0, $this->_values['event']['event_type_id']);
832 $primaryParticipant['eventCustomFields'] = $groupTree;
833
834 // call postprocess hook before leaving
835 $this->postProcessHook();
836
837 $this->processPayment($payment, $primaryParticipant);
838 }
839 else {
840 CRM_Core_Error::fatal($paymentObjError);
841 }
842 }
843 }
844 else {
845 //otherwise send mail Confirmation/Receipt
846 $primaryContactId = $this->get('primaryContactId');
847
848 //build an array of cId/pId of participants
849 $additionalIDs = CRM_Event_BAO_Event::buildCustomProfile($registerByID,
850 NULL, $primaryContactId, $isTest,
851 TRUE
852 );
853 //let's send mails to all with meaningful text, CRM-4320.
854 $this->assign('isOnWaitlist', $this->_allowWaitlist);
855 $this->assign('isRequireApproval', $this->_requireApproval);
856
857 //need to copy, since we are unsetting on the way.
858 $copyParticipantCount = $participantCount;
859
860 //let's carry all participant params w/ values.
861 foreach ($additionalIDs as $participantID => $contactId) {
862 $participantNum = NULL;
863 if ($participantID == $registerByID) {
864 $participantNum = 0;
865 }
866 else {
867 if ($participantNum = array_search('participant', $copyParticipantCount)) {
868 unset($copyParticipantCount[$participantNum]);
869 }
870 }
871 if ($participantNum === NULL) {
872 break;
873 }
874
875 //carry the participant submitted values.
876 $this->_values['params'][$participantID] = $params[$participantNum];
877 }
878
879 foreach ($additionalIDs as $participantID => $contactId) {
880 $participantNum = 0;
881 if ($participantID == $registerByID) {
882 //set as Primary Participant
883 $this->assign('isPrimary', 1);
884 //build an array of custom profile and assigning it to template.
885 $customProfile = CRM_Event_BAO_Event::buildCustomProfile($participantID, $this->_values, NULL, $isTest);
886
887 if (count($customProfile)) {
888 $this->assign('customProfile', $customProfile);
889 $this->set('customProfile', $customProfile);
890 }
891 $this->_values['params']['additionalParticipant'] = FALSE;
892 }
893 else {
894 //take the Additional participant number.
895 if ($participantNum = array_search('participant', $participantCount)) {
896 unset($participantCount[$participantNum]);
897 }
898 // Change $this->_values['participant'] to include additional participant values
899 $ids = $participantValues = [];
900 $participantParams = ['id' => $participantID];
901 CRM_Event_BAO_Participant::getValues($participantParams, $participantValues, $ids);
902 $this->_values['participant'] = $participantValues[$participantID];
903
904 $this->assign('isPrimary', 0);
905 $this->assign('customProfile', NULL);
906 //Additional Participant should get only it's payment information
907 if (!empty($this->_amount)) {
908 $amount = [];
909 $params = $this->get('params');
910 $amount[$participantNum]['label'] = preg_replace('/\ 1/', '', $params[$participantNum]['amount_level']);
911 $amount[$participantNum]['amount'] = $params[$participantNum]['amount'];
912 $this->assign('amounts', $amount);
913 }
914 if ($this->_lineItem) {
915 $lineItems = $this->_lineItem;
916 $lineItem = [];
917 if ($lineItemValue = CRM_Utils_Array::value($participantNum, $lineItems)) {
918 $lineItem[] = $lineItemValue;
919 }
920 if ($invoicing) {
921 $individual = $this->get('individual');
922 $dataArray[key($dataArray)] = $individual[$participantNum]['totalTaxAmt'];
923 $this->assign('dataArray', $dataArray);
924 $this->assign('totalAmount', $individual[$participantNum]['totalAmtWithTax']);
925 $this->assign('totalTaxAmount', $individual[$participantNum]['totalTaxAmt']);
926 $this->assign('individual', [$individual[$participantNum]]);
927 }
928 $this->assign('lineItem', $lineItem);
929 }
930 $this->_values['params']['additionalParticipant'] = TRUE;
931 $this->assign('isAdditionalParticipant', $this->_values['params']['additionalParticipant']);
932 }
933
934 //pass these variables since these are run time calculated.
935 $this->_values['params']['isOnWaitlist'] = $this->_allowWaitlist;
936 $this->_values['params']['isRequireApproval'] = $this->_requireApproval;
937
938 //send mail to primary as well as additional participants.
939 $this->assign('contactID', $contactId);
940 $this->assign('participantID', $participantID);
941 CRM_Event_BAO_Event::sendMail($contactId, $this->_values, $participantID, $isTest);
942 }
943 }
944 }
945
946 /**
947 * Process the contribution.
948 *
949 * @param CRM_Core_Form $form
950 * @param array $params
951 * @param array $result
952 * @param int $contactID
953 * @param bool $pending
954 * @param bool $isAdditionalAmount
955 * @param array $paymentProcessor
956 *
957 * @return \CRM_Contribute_BAO_Contribution
958 * @throws \CRM_Core_Exception
959 */
960 public static function processContribution(
961 &$form, $params, $result, $contactID,
962 $pending = FALSE, $isAdditionalAmount = FALSE,
963 $paymentProcessor = NULL
964 ) {
965 $transaction = new CRM_Core_Transaction();
966
967 $now = date('YmdHis');
968 $receiptDate = NULL;
969
970 if (!empty($form->_values['event']['is_email_confirm'])) {
971 $receiptDate = $now;
972 }
973 //CRM-4196
974 if ($isAdditionalAmount) {
975 $params['amount_level'] = $params['amount_level'] . ts(' (multiple participants)') . CRM_Core_DAO::VALUE_SEPARATOR;
976 }
977
978 // CRM-20264: fetch CC type ID and number (last 4 digit) and assign it back to $params
979 CRM_Contribute_Form_AbstractEditPayment::formatCreditCardDetails($params);
980
981 $contribParams = [
982 'contact_id' => $contactID,
983 'financial_type_id' => !empty($form->_values['event']['financial_type_id']) ? $form->_values['event']['financial_type_id'] : $params['financial_type_id'],
984 'receive_date' => $now,
985 'total_amount' => $params['amount'],
986 'tax_amount' => $params['tax_amount'],
987 'amount_level' => $params['amount_level'],
988 'invoice_id' => $params['invoiceID'],
989 'currency' => $params['currencyID'],
990 'source' => !empty($params['participant_source']) ? $params['participant_source'] : $params['description'],
991 'is_pay_later' => CRM_Utils_Array::value('is_pay_later', $params, 0),
992 'campaign_id' => CRM_Utils_Array::value('campaign_id', $params),
993 'card_type_id' => CRM_Utils_Array::value('card_type_id', $params),
994 'pan_truncation' => CRM_Utils_Array::value('pan_truncation', $params),
995 ];
996
997 if ($paymentProcessor) {
998 $contribParams['payment_instrument_id'] = $paymentProcessor['payment_instrument_id'];
999 $contribParams['payment_processor'] = $paymentProcessor['id'];
1000 }
1001
1002 if (!$pending && $result) {
1003 $contribParams += [
1004 'fee_amount' => CRM_Utils_Array::value('fee_amount', $result),
1005 'net_amount' => CRM_Utils_Array::value('net_amount', $result, $params['amount']),
1006 'trxn_id' => $result['trxn_id'],
1007 'receipt_date' => $receiptDate,
1008 ];
1009 }
1010
1011 $allStatuses = CRM_Contribute_PseudoConstant::contributionStatus(NULL, 'name');
1012 $contribParams['contribution_status_id'] = array_search('Completed', $allStatuses);
1013 if ($pending) {
1014 $contribParams['contribution_status_id'] = array_search('Pending', $allStatuses);
1015 }
1016
1017 $contribParams['is_test'] = 0;
1018 if ($form->_action & CRM_Core_Action::PREVIEW || CRM_Utils_Array::value('mode', $params) == 'test') {
1019 $contribParams['is_test'] = 1;
1020 }
1021
1022 if (!empty($contribParams['invoice_id'])) {
1023 $contribParams['id'] = CRM_Core_DAO::getFieldValue('CRM_Contribute_DAO_Contribution',
1024 $contribParams['invoice_id'],
1025 'id',
1026 'invoice_id'
1027 );
1028 }
1029
1030 if (Civi::settings()->get('deferred_revenue_enabled')) {
1031 $eventStartDate = CRM_Utils_Array::value(
1032 'start_date',
1033 CRM_Utils_Array::value(
1034 'event',
1035 $form->_values
1036 )
1037 );
1038 if (strtotime($eventStartDate) > strtotime(date('Ymt'))) {
1039 $contribParams['revenue_recognition_date'] = date('Ymd', strtotime($eventStartDate));
1040 }
1041 }
1042 //create an contribution address
1043 // The concept of contributeMode is deprecated. Elsewhere we use the function processBillingAddress() - although
1044 // currently that is only inherited by back-office forms.
1045 if ($form->_contributeMode != 'notify' && empty($params['is_pay_later'])) {
1046 $contribParams['address_id'] = CRM_Contribute_BAO_Contribution::createAddress($params, $form->_bltID);
1047 }
1048
1049 $contribParams['skipLineItem'] = 1;
1050 $contribParams['skipCleanMoney'] = 1;
1051 // create contribution record
1052 $contribution = CRM_Contribute_BAO_Contribution::add($contribParams);
1053 // CRM-11124
1054 CRM_Event_BAO_Participant::createDiscountTrxn($form->_eventId, $contribParams, NULL, CRM_Price_BAO_PriceSet::parseFirstPriceSetValueIDFromParams($params));
1055
1056 // process soft credit / pcp pages
1057 if (!empty($params['pcp_made_through_id'])) {
1058 CRM_Contribute_BAO_ContributionSoft::formatSoftCreditParams($params, $form);
1059 CRM_Contribute_BAO_ContributionSoft::processSoftContribution($params, $contribution);
1060 }
1061
1062 $transaction->commit();
1063
1064 return $contribution;
1065 }
1066
1067 /**
1068 * Fix the Location Fields.
1069 *
1070 * @todo Reconcile with the contribution method formatParamsForPaymentProcessor
1071 * rather than adding different logic to check when to keep the billing
1072 * fields. There might be a difference in handling guest/multiple
1073 * participants though.
1074 *
1075 * @param array $params
1076 * @param array $fields
1077 * @param CRM_Core_Form $form
1078 */
1079 public static function fixLocationFields(&$params, &$fields, &$form) {
1080 if (!empty($form->_fields)) {
1081 foreach ($form->_fields as $name => $dontCare) {
1082 $fields[$name] = 1;
1083 }
1084 }
1085
1086 // If there's no 'first_name' in the profile then overwrite the names from
1087 // the billing fields (if they are set)
1088 if (is_array($fields)) {
1089 if (!array_key_exists('first_name', $fields)) {
1090 $nameFields = ['first_name', 'middle_name', 'last_name'];
1091 foreach ($nameFields as $name) {
1092 $fields[$name] = 1;
1093 if (array_key_exists("billing_$name", $params)) {
1094 $params[$name] = $params["billing_{$name}"];
1095 $params['preserveDBName'] = TRUE;
1096 }
1097 }
1098 }
1099 }
1100
1101 // Add the billing names to the billing address, if a billing name is set
1102 if (!empty($params['billing_first_name'])) {
1103 $params["address_name-{$form->_bltID}"] = CRM_Utils_Array::value('billing_first_name', $params) . ' ' . CRM_Utils_Array::value('billing_middle_name', $params) . ' ' . CRM_Utils_Array::value('billing_last_name', $params);
1104 $fields["address_name-{$form->_bltID}"] = 1;
1105 }
1106
1107 $fields["email-{$form->_bltID}"] = 1;
1108 $fields['email-Primary'] = 1;
1109
1110 //if its pay later or additional participant set email address as primary.
1111 if ((!empty($params['is_pay_later']) || empty($params['is_primary']) ||
1112 !$form->_values['event']['is_monetary'] ||
1113 $form->_allowWaitlist ||
1114 $form->_requireApproval
1115 ) && !empty($params["email-{$form->_bltID}"])
1116 ) {
1117 $params['email-Primary'] = $params["email-{$form->_bltID}"];
1118 }
1119 }
1120
1121 /**
1122 * Update contact fields.
1123 *
1124 * @param int $contactID
1125 * @param array $params
1126 * @param array $fields
1127 * @param CRM_Core_Form $form
1128 *
1129 * @return int
1130 */
1131 public static function updateContactFields($contactID, $params, $fields, &$form) {
1132 //add the contact to group, if add to group is selected for a
1133 //particular uf group
1134
1135 // get the add to groups
1136 $addToGroups = [];
1137
1138 if (!empty($form->_fields)) {
1139 foreach ($form->_fields as $key => $value) {
1140 if (!empty($value['add_to_group_id'])) {
1141 $addToGroups[$value['add_to_group_id']] = $value['add_to_group_id'];
1142 }
1143 }
1144 }
1145
1146 // check for profile double opt-in and get groups to be subscribed
1147 $subscribeGroupIds = CRM_Core_BAO_UFGroup::getDoubleOptInGroupIds($params, $contactID);
1148
1149 foreach ($addToGroups as $k) {
1150 if (array_key_exists($k, $subscribeGroupIds)) {
1151 unset($addToGroups[$k]);
1152 }
1153 }
1154
1155 // since we are directly adding contact to group lets unset it from mailing
1156 if (!empty($addToGroups)) {
1157 foreach ($addToGroups as $groupId) {
1158 if (isset($subscribeGroupIds[$groupId])) {
1159 unset($subscribeGroupIds[$groupId]);
1160 }
1161 }
1162 }
1163 if ($contactID) {
1164 $ctype = CRM_Core_DAO::getFieldValue(
1165 'CRM_Contact_DAO_Contact',
1166 $contactID,
1167 'contact_type'
1168 );
1169
1170 if (array_key_exists('contact_id', $params) && empty($params['contact_id'])) {
1171 // we unset this here because the downstream function ignores the contactID we give it
1172 // if it is set & it is difficult to understand the implications of 'fixing' this downstream
1173 // but if we are passing a contact id into this function it's reasonable to assume we don't
1174 // want it ignored
1175 unset($params['contact_id']);
1176 }
1177
1178 $contactID = CRM_Contact_BAO_Contact::createProfileContact(
1179 $params,
1180 $fields,
1181 $contactID,
1182 $addToGroups,
1183 NULL,
1184 $ctype,
1185 TRUE
1186 );
1187 }
1188 else {
1189
1190 foreach (CRM_Contact_BAO_Contact::$_greetingTypes as $greeting) {
1191 if (!isset($params[$greeting . '_id'])) {
1192 $params[$greeting . '_id'] = CRM_Contact_BAO_Contact_Utils::defaultGreeting('Individual', $greeting);
1193 }
1194 }
1195
1196 $contactID = CRM_Contact_BAO_Contact::createProfileContact($params,
1197 $fields,
1198 NULL,
1199 $addToGroups,
1200 NULL,
1201 NULL,
1202 TRUE
1203 );
1204 $form->set('contactID', $contactID);
1205 }
1206
1207 //get email primary first if exist
1208 $subscribtionEmail = ['email' => CRM_Utils_Array::value('email-Primary', $params)];
1209 if (!$subscribtionEmail['email']) {
1210 $subscribtionEmail['email'] = CRM_Utils_Array::value("email-{$form->_bltID}", $params);
1211 }
1212 // subscribing contact to groups
1213 if (!empty($subscribeGroupIds) && $subscribtionEmail['email']) {
1214 CRM_Mailing_Event_BAO_Subscribe::commonSubscribe($subscribeGroupIds, $subscribtionEmail, $contactID);
1215 }
1216
1217 return $contactID;
1218 }
1219
1220 /**
1221 * Assign Profiles.
1222 *
1223 * @param CRM_Core_Form $form
1224 */
1225 public static function assignProfiles(&$form) {
1226 $participantParams = $form->_params;
1227 $formattedValues = $profileFields = [];
1228 $count = 1;
1229 foreach ($participantParams as $participantNum => $participantValue) {
1230 if ($participantNum) {
1231 $prefix1 = 'additional';
1232 $prefix2 = 'additional_';
1233 }
1234 else {
1235 $prefix1 = '';
1236 $prefix2 = '';
1237 }
1238 if ($participantValue != 'skip') {
1239 //get the customPre profile info
1240 if (!empty($form->_values[$prefix2 . 'custom_pre_id'])) {
1241 $values = $groupName = [];
1242 CRM_Event_BAO_Event::displayProfile($participantValue,
1243 $form->_values[$prefix2 . 'custom_pre_id'],
1244 $groupName,
1245 $values,
1246 $profileFields
1247 );
1248
1249 if (count($values)) {
1250 $formattedValues[$count][$prefix1 . 'CustomPre'] = $values;
1251 }
1252 $formattedValues[$count][$prefix1 . 'CustomPreGroupTitle'] = CRM_Utils_Array::value('groupTitle', $groupName);
1253 }
1254 //get the customPost profile info
1255 if (!empty($form->_values[$prefix2 . 'custom_post_id'])) {
1256 $values = $groupName = [];
1257 foreach ($form->_values[$prefix2 . 'custom_post_id'] as $gids) {
1258 $val = [];
1259 CRM_Event_BAO_Event::displayProfile($participantValue,
1260 $gids,
1261 $group,
1262 $val,
1263 $profileFields
1264 );
1265 $values[$gids] = $val;
1266 $groupName[$gids] = $group;
1267 }
1268
1269 if (count($values)) {
1270 $formattedValues[$count][$prefix1 . 'CustomPost'] = $values;
1271 }
1272
1273 if (isset($formattedValues[$count][$prefix1 . 'CustomPre'])) {
1274 $formattedValues[$count][$prefix1 . 'CustomPost'] = array_diff_assoc($formattedValues[$count][$prefix1 . 'CustomPost'],
1275 $formattedValues[$count][$prefix1 . 'CustomPre']
1276 );
1277 }
1278
1279 $formattedValues[$count][$prefix1 . 'CustomPostGroupTitle'] = $groupName;
1280 }
1281 $count++;
1282 }
1283 $form->_fields = $profileFields;
1284 }
1285 if (!empty($formattedValues)) {
1286 $form->assign('primaryParticipantProfile', $formattedValues[1]);
1287 $form->set('primaryParticipantProfile', $formattedValues[1]);
1288 if ($count > 2) {
1289 unset($formattedValues[1]);
1290 $form->assign('addParticipantProfile', $formattedValues);
1291 $form->set('addParticipantProfile', $formattedValues);
1292 }
1293 }
1294 }
1295
1296 /**
1297 * Submit in test mode.
1298 *
1299 * @param $params
1300 */
1301 public static function testSubmit($params) {
1302 $form = new CRM_Event_Form_Registration_Confirm();
1303 // This way the mocked up controller ignores the session stuff.
1304 $_SERVER['REQUEST_METHOD'] = 'GET';
1305 $_REQUEST['id'] = $form->_eventId = $params['id'];
1306 $form->controller = new CRM_Event_Controller_Registration();
1307 $form->_params = $params['params'];
1308 // This happens in buildQuickForm so emulate here.
1309 $form->_amount = $form->_totalAmount = CRM_Utils_Rule::cleanMoney(CRM_Utils_Array::value('totalAmount', $params));
1310 $form->set('params', $params['params']);
1311 $form->_values['custom_pre_id'] = [];
1312 $form->_values['custom_post_id'] = [];
1313 $form->_values['event'] = CRM_Utils_Array::value('event', $params);
1314 $form->_contributeMode = $params['contributeMode'];
1315 $eventParams = ['id' => $params['id']];
1316 CRM_Event_BAO_Event::retrieve($eventParams, $form->_values['event']);
1317 $form->set('registerByID', $params['registerByID']);
1318 if (!empty($params['paymentProcessorObj'])) {
1319 $form->_paymentProcessor = $params['paymentProcessorObj'];
1320 }
1321 $form->postProcess();
1322 }
1323
1324 /**
1325 * Process the payment, redirecting back to the page on error.
1326 *
1327 * @param $payment
1328 * @param $value
1329 *
1330 * @return array
1331 */
1332 private function processPayment($payment, $value) {
1333 try {
1334 $result = $payment->doPayment($value, 'event');
1335 return [$result, $value];
1336 }
1337 catch (\Civi\Payment\Exception\PaymentProcessorException $e) {
1338 Civi::log()->error('Payment processor exception: ' . $e->getMessage());
1339 CRM_Core_Session::singleton()->setStatus($e->getMessage());
1340 CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/event/register', "id={$this->_eventId}"));
1341 }
1342 return [];
1343 }
1344
1345 /**
1346 * Clean money fields from the form.
1347 *
1348 * @param array $params
1349 */
1350 protected function cleanMoneyFields(&$params) {
1351 foreach ($this->submittableMoneyFields as $moneyField) {
1352 foreach ($params as $index => $paramField) {
1353 if (isset($paramField[$moneyField])) {
1354 $params[$index][$moneyField] = CRM_Utils_Rule::cleanMoney($paramField[$moneyField]);
1355 }
1356 }
1357 }
1358 }
1359
1360 }