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