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