Merge pull request #16759 from eileenmcnaughton/fatal2
[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 CRM_Utils_System::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) ? TRUE : FALSE);
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 = CRM_Utils_Array::value('participant_id', $record);
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 //unset the billing parameters if it is pay later mode
443 //to avoid creation of billing location
444 // @todo - the reasoning for this is unclear - elsewhere we check what fields are provided by
445 // the form & if billing fields exist we create the address, relying on the form to collect
446 // only information we intend to store.
447 if ($this->_allowWaitlist
448 || $this->_requireApproval
449 || (!empty($value['is_pay_later']) && !$this->_isBillingAddressRequiredForPayLater)
450 || empty($value['is_primary'])
451 ) {
452 $billingFields = [
453 "email-{$this->_bltID}",
454 'billing_first_name',
455 'billing_middle_name',
456 'billing_last_name',
457 "billing_street_address-{$this->_bltID}",
458 "billing_city-{$this->_bltID}",
459 "billing_state_province-{$this->_bltID}",
460 "billing_state_province_id-{$this->_bltID}",
461 "billing_postal_code-{$this->_bltID}",
462 "billing_country-{$this->_bltID}",
463 "billing_country_id-{$this->_bltID}",
464 "address_name-{$this->_bltID}",
465 ];
466 foreach ($billingFields as $field) {
467 unset($value[$field]);
468 }
469 if (!empty($value['is_pay_later'])) {
470 $this->_values['params']['is_pay_later'] = TRUE;
471 }
472 }
473
474 //Unset ContactID for additional participants and set RegisterBy Id.
475 if (empty($value['is_primary'])) {
476 $contactID = CRM_Utils_Array::value('contact_id', $value);
477 $registerByID = $this->get('registerByID');
478 if ($registerByID) {
479 $value['registered_by_id'] = $registerByID;
480 }
481 }
482 else {
483 $value['amount'] = $this->_totalAmount;
484 }
485
486 $contactID = CRM_Event_Form_Registration_Confirm::updateContactFields($contactID, $value, $fields, $this);
487
488 // lets store the contactID in the session
489 // we dont store in userID in case the user is doing multiple
490 // transactions etc
491 // for things like tell a friend
492 if (!$this->getContactID() && !empty($value['is_primary'])) {
493 CRM_Core_Session::singleton()->set('transaction.userID', $contactID);
494 }
495
496 $value['description'] = ts('Online Event Registration') . ': ' . $this->_values['event']['title'];
497 $value['accountingCode'] = CRM_Utils_Array::value('accountingCode',
498 $this->_values['event']
499 );
500
501 $pending = FALSE;
502 if ($this->_allowWaitlist || $this->_requireApproval) {
503 //get the participant statuses.
504 $waitingStatuses = CRM_Event_PseudoConstant::participantStatus(NULL, "class = 'Waiting'");
505 if ($this->_allowWaitlist) {
506 $value['participant_status_id'] = $value['participant_status'] = array_search('On waitlist', $waitingStatuses);
507 }
508 else {
509 $value['participant_status_id'] = $value['participant_status'] = array_search('Awaiting approval', $waitingStatuses);
510 }
511
512 //there might be case user selected pay later and
513 //now becomes part of run time waiting list.
514 $value['is_pay_later'] = FALSE;
515 }
516 elseif ($this->_values['event']['is_monetary']) {
517 // required only if paid event
518 if (is_array($this->_paymentProcessor)) {
519 $payment = $this->_paymentProcessor['object'];
520 }
521 if (!empty($this->_paymentProcessor) && $this->_paymentProcessor['object']->supports('preApproval')) {
522 $preApprovalParams = $this->_paymentProcessor['object']->getPreApprovalDetails($this->get('pre_approval_parameters'));
523 $value = array_merge($value, $preApprovalParams);
524 }
525 $result = NULL;
526
527 if (!empty($value['is_pay_later']) ||
528 $value['amount'] == 0 ||
529 // The concept of contributeMode is deprecated.
530 $this->_contributeMode == 'checkout' ||
531 $this->_contributeMode == 'notify'
532 ) {
533 if ($value['amount'] != 0) {
534 $pending = TRUE;
535 //get the participant statuses.
536 $pendingStatuses = CRM_Event_PseudoConstant::participantStatus(NULL, "class = 'Pending'");
537 $status = !empty($value['is_pay_later']) ? 'Pending from pay later' : 'Pending from incomplete transaction';
538 $value['participant_status_id'] = $value['participant_status'] = array_search($status, $pendingStatuses);
539 }
540 }
541 elseif (!empty($value['is_primary'])) {
542 CRM_Core_Payment_Form::mapParams($this->_bltID, $value, $value, TRUE);
543 // payment email param can be empty for _bltID mapping
544 // thus provide mapping for it with a different email value
545 if (empty($value['email'])) {
546 $value['email'] = CRM_Utils_Array::valueByRegexKey('/^email-/', $value);
547 }
548
549 if (is_object($payment)) {
550 // Not quite sure why we don't just user $value since it contains the data
551 // from result
552 // @todo ditch $result & retest.
553 list($result, $value) = $this->processPayment($payment, $value);
554 }
555 else {
556 throw new CRM_Core_Exception($paymentObjError);
557 }
558 }
559
560 $value['receive_date'] = $now;
561 if ($this->_allowConfirmation) {
562 $value['participant_register_date'] = $this->_values['participant']['register_date'];
563 }
564
565 $createContrib = ($value['amount'] != 0) ? TRUE : FALSE;
566 // force to create zero amount contribution, CRM-5095
567 if (!$createContrib && ($value['amount'] == 0)
568 && $this->_priceSetId && $this->_lineItem
569 ) {
570 $createContrib = TRUE;
571 }
572
573 if ($createContrib && !empty($value['is_primary']) &&
574 !$this->_allowWaitlist && !$this->_requireApproval
575 ) {
576 // if paid event add a contribution record
577 //if primary participant contributing additional amount
578 //append (multiple participants) to its fee level. CRM-4196.
579 if (count($params) > 1) {
580 $value['amount_level'] .= ts(' (multiple participants)') . CRM_Core_DAO::VALUE_SEPARATOR;
581 }
582
583 //passing contribution id is already registered.
584 $contribution = $this->processContribution($this, $value, $result, $contactID, $pending, $this->_paymentProcessor);
585 $value['contributionID'] = $contribution->id;
586 $value['contributionTypeID'] = $contribution->financial_type_id;
587 $value['receive_date'] = $contribution->receive_date;
588 $value['trxn_id'] = $contribution->trxn_id;
589 $value['contributionID'] = $contribution->id;
590 $value['contributionTypeID'] = $contribution->financial_type_id;
591 }
592 $value['contactID'] = $contactID;
593 $value['eventID'] = $this->_eventId;
594 $value['item_name'] = $value['description'];
595 }
596
597 if (!empty($value['contributionID'])) {
598 $this->_values['contributionId'] = $value['contributionID'];
599 }
600
601 //CRM-4453.
602 if (!empty($value['is_primary'])) {
603 $primaryCurrencyID = CRM_Utils_Array::value('currencyID', $value);
604 }
605 if (empty($value['currencyID'])) {
606 $value['currencyID'] = $primaryCurrencyID;
607 }
608
609 // CRM-11182 - Confirmation page might not be monetary
610 if ($this->_values['event']['is_monetary']) {
611 if (!$pending && !empty($value['is_primary']) &&
612 !$this->_allowWaitlist && !$this->_requireApproval
613 ) {
614 // transactionID & receive date required while building email template
615 $this->assign('trxn_id', CRM_Utils_Array::value('trxn_id', $value));
616 $this->assign('receive_date', CRM_Utils_Date::mysqlToIso(CRM_Utils_Array::value('receive_date', $value)));
617 $this->set('receiveDate', CRM_Utils_Date::mysqlToIso(CRM_Utils_Array::value('receive_date', $value)));
618 $this->set('trxnId', CRM_Utils_Array::value('trxn_id', $value));
619 }
620 }
621
622 $value['fee_amount'] = CRM_Utils_Array::value('amount', $value);
623 $this->set('value', $value);
624
625 // handle register date CRM-4320
626 if ($this->_allowConfirmation) {
627 $registerDate = CRM_Utils_Array::value('participant_register_date', $params);
628 }
629 elseif (!empty($params['participant_register_date']) &&
630 is_array($params['participant_register_date'])
631 ) {
632 $registerDate = CRM_Utils_Date::format($params['participant_register_date']);
633 }
634 else {
635 $registerDate = date('YmdHis');
636 }
637 $this->assign('register_date', $registerDate);
638
639 $this->confirmPostProcess($contactID, $contribution);
640 }
641
642 //handle if no additional participant.
643 if (!$registerByID) {
644 $registerByID = $this->get('registerByID');
645 }
646
647 $this->set('participantIDs', $this->_participantIDS);
648
649 // create line items, CRM-5313
650 if ($this->_priceSetId &&
651 !empty($this->_lineItem)
652 ) {
653 // take all processed participant ids.
654 $allParticipantIds = $this->_participantIDS;
655
656 // when participant re-walk wizard.
657 if ($this->_allowConfirmation &&
658 !empty($this->_additionalParticipantIds)
659 ) {
660 $allParticipantIds = array_merge([$registerByID], $this->_additionalParticipantIds);
661 }
662
663 $entityTable = 'civicrm_participant';
664 $totalTaxAmount = 0;
665 $dataArray = [];
666 foreach ($this->_lineItem as $key => $value) {
667 if ($value == 'skip') {
668 continue;
669 }
670 if ($entityId = CRM_Utils_Array::value($key, $allParticipantIds)) {
671 // do cleanup line items if participant re-walking wizard.
672 if ($this->_allowConfirmation) {
673 CRM_Price_BAO_LineItem::deleteLineItems($entityId, $entityTable);
674 }
675 $lineItem[$this->_priceSetId] = $value;
676 CRM_Price_BAO_LineItem::processPriceSet($entityId, $lineItem, $contribution, $entityTable);
677 }
678 if (CRM_Invoicing_Utils::isInvoicingEnabled()) {
679 foreach ($value as $line) {
680 if (isset($line['tax_amount']) && isset($line['tax_rate'])) {
681 $totalTaxAmount = $line['tax_amount'] + $totalTaxAmount;
682 if (isset($dataArray[$line['tax_rate']])) {
683 $dataArray[$line['tax_rate']] = $dataArray[$line['tax_rate']] + CRM_Utils_Array::value('tax_amount', $line);
684 }
685 else {
686 $dataArray[$line['tax_rate']] = CRM_Utils_Array::value('tax_amount', $line);
687 }
688 }
689 }
690 }
691 }
692 $this->assign('dataArray', $dataArray);
693 $this->assign('totalTaxAmount', $totalTaxAmount);
694 }
695
696 //update status and send mail to cancelled additional participants, CRM-4320
697 if ($this->_allowConfirmation && is_array($cancelledIds) && !empty($cancelledIds)) {
698 $cancelledId = array_search('Cancelled',
699 CRM_Event_PseudoConstant::participantStatus(NULL, "class = 'Negative'")
700 );
701 CRM_Event_BAO_Participant::transitionParticipants($cancelledIds, $cancelledId);
702 }
703
704 $isTest = FALSE;
705 if ($this->_action & CRM_Core_Action::PREVIEW) {
706 $isTest = TRUE;
707 }
708
709 $primaryParticipant = $this->get('primaryParticipant');
710
711 if (empty($primaryParticipant['participantID'])) {
712 CRM_Core_Error::deprecatedFunctionWarning('This line is not logically reachable.');
713 $primaryParticipant['participantID'] = $registerByID;
714 }
715 //otherwise send mail Confirmation/Receipt
716 $primaryContactId = $this->get('primaryContactId');
717
718 // for Transfer checkout.
719 // The concept of contributeMode is deprecated.
720 if (($this->_contributeMode == 'checkout' ||
721 $this->_contributeMode == 'notify'
722 ) && empty($params[0]['is_pay_later']) &&
723 !$this->_allowWaitlist && !$this->_requireApproval &&
724 $this->_totalAmount > 0
725 ) {
726
727 //build an array of custom profile and assigning it to template
728 $customProfile = CRM_Event_BAO_Event::buildCustomProfile($registerByID, $this->_values, NULL, $isTest);
729 if (count($customProfile)) {
730 $this->assign('customProfile', $customProfile);
731 $this->set('customProfile', $customProfile);
732 }
733
734 // do a transfer only if a monetary payment greater than 0
735 if ($this->_values['event']['is_monetary'] && $primaryParticipant) {
736 if ($payment && is_object($payment)) {
737 //CRM 14512 provide line items of all participants to payment gateway
738 $primaryContactId = $this->get('primaryContactId');
739
740 //build an array of cId/pId of participants
741 $additionalIDs = CRM_Event_BAO_Event::buildCustomProfile($registerByID, NULL, $primaryContactId, $isTest, TRUE);
742
743 //need to copy, since we are unsetting on the way.
744 $copyParticipantCountLines = $participantCount;
745
746 //lets carry all participant params w/ values.
747 foreach ($additionalIDs as $participantID => $contactId) {
748 $participantNum = $participantID;
749 if ($participantID == $registerByID) {
750 // This is the is primary participant.
751 $participantNum = 0;
752 }
753 else {
754 if ($participantNum = array_search('participant', $copyParticipantCountLines)) {
755 //if no participant found break.
756 if ($participantNum === NULL) {
757 break;
758 }
759 //unset current participant so we don't check them again
760 unset($copyParticipantCountLines[$participantNum]);
761 }
762 }
763 // get values of line items
764 if ($this->_amount) {
765 $amount = [];
766 $amount[$participantNum]['label'] = preg_replace('/\ 1/', '', $params[$participantNum]['amount_level']);
767 $amount[$participantNum]['amount'] = $params[$participantNum]['amount'];
768 $params[$participantNum]['amounts'] = $amount;
769 }
770
771 if (!empty($this->_lineItem)) {
772 $lineItems = $this->_lineItem;
773 $lineItem = [];
774 if ($lineItemValue = CRM_Utils_Array::value($participantNum, $lineItems)) {
775 $lineItem[] = $lineItemValue;
776 }
777 $params[$participantNum]['lineItem'] = $lineItem;
778 }
779
780 //only add additional particpants and not the primary particpant as we already have that
781 //added to $primaryParticipant so that this change doesn't break or require changes to
782 //existing gateway implementations
783 $primaryParticipant['participants_info'][$participantID] = $params[$participantNum];
784 }
785
786 //get event custom field information
787 $groupTree = CRM_Core_BAO_CustomGroup::getTree('Event', NULL, $this->_eventId, 0, $this->_values['event']['event_type_id']);
788 $primaryParticipant['eventCustomFields'] = $groupTree;
789
790 // call postprocess hook before leaving
791 $this->postProcessHook();
792
793 $this->processPayment($payment, $primaryParticipant);
794 }
795 else {
796 throw new CRM_Core_Exception($paymentObjError);
797 }
798 }
799 }
800 else {
801
802 //build an array of cId/pId of participants
803 $additionalIDs = CRM_Event_BAO_Event::buildCustomProfile($registerByID,
804 NULL, $primaryContactId, $isTest,
805 TRUE
806 );
807 //let's send mails to all with meaningful text, CRM-4320.
808 $this->assign('isOnWaitlist', $this->_allowWaitlist);
809 $this->assign('isRequireApproval', $this->_requireApproval);
810
811 //need to copy, since we are unsetting on the way.
812 $copyParticipantCount = $participantCount;
813
814 //let's carry all participant params w/ values.
815 foreach ($additionalIDs as $participantID => $contactId) {
816 $participantNum = NULL;
817 if ($participantID == $registerByID) {
818 $participantNum = 0;
819 }
820 else {
821 if ($participantNum = array_search('participant', $copyParticipantCount)) {
822 unset($copyParticipantCount[$participantNum]);
823 }
824 }
825 if ($participantNum === NULL) {
826 break;
827 }
828
829 //carry the participant submitted values.
830 $this->_values['params'][$participantID] = $params[$participantNum];
831 }
832
833 foreach ($additionalIDs as $participantID => $contactId) {
834 $participantNum = 0;
835 if ($participantID == $registerByID) {
836 //set as Primary Participant
837 $this->assign('isPrimary', 1);
838 //build an array of custom profile and assigning it to template.
839 $customProfile = CRM_Event_BAO_Event::buildCustomProfile($participantID, $this->_values, NULL, $isTest);
840
841 if (count($customProfile)) {
842 $this->assign('customProfile', $customProfile);
843 $this->set('customProfile', $customProfile);
844 }
845 $this->_values['params']['additionalParticipant'] = FALSE;
846 }
847 else {
848 //take the Additional participant number.
849 if ($participantNum = array_search('participant', $participantCount)) {
850 unset($participantCount[$participantNum]);
851 }
852 // Change $this->_values['participant'] to include additional participant values
853 $ids = $participantValues = [];
854 $participantParams = ['id' => $participantID];
855 CRM_Event_BAO_Participant::getValues($participantParams, $participantValues, $ids);
856 $this->_values['participant'] = $participantValues[$participantID];
857
858 $this->assign('isPrimary', 0);
859 $this->assign('customProfile', NULL);
860 //Additional Participant should get only it's payment information
861 if (!empty($this->_amount)) {
862 $amount = [];
863 $params = $this->get('params');
864 $amount[$participantNum]['label'] = preg_replace('/\ 1/', '', $params[$participantNum]['amount_level']);
865 $amount[$participantNum]['amount'] = $params[$participantNum]['amount'];
866 $this->assign('amounts', $amount);
867 }
868 if ($this->_lineItem) {
869 $lineItems = $this->_lineItem;
870 $lineItem = [];
871 if ($lineItemValue = CRM_Utils_Array::value($participantNum, $lineItems)) {
872 $lineItem[] = $lineItemValue;
873 }
874 if (CRM_Invoicing_Utils::isInvoicingEnabled()) {
875 $individual = $this->get('individual');
876 $dataArray[key($dataArray)] = $individual[$participantNum]['totalTaxAmt'];
877 $this->assign('dataArray', $dataArray);
878 $this->assign('totalAmount', $individual[$participantNum]['totalAmtWithTax']);
879 $this->assign('totalTaxAmount', $individual[$participantNum]['totalTaxAmt']);
880 $this->assign('individual', [$individual[$participantNum]]);
881 }
882 $this->assign('lineItem', $lineItem);
883 }
884 $this->_values['params']['additionalParticipant'] = TRUE;
885 $this->assign('isAdditionalParticipant', $this->_values['params']['additionalParticipant']);
886 }
887
888 //pass these variables since these are run time calculated.
889 $this->_values['params']['isOnWaitlist'] = $this->_allowWaitlist;
890 $this->_values['params']['isRequireApproval'] = $this->_requireApproval;
891
892 //send mail to primary as well as additional participants.
893 CRM_Event_BAO_Event::sendMail($contactId, $this->_values, $participantID, $isTest);
894 }
895 }
896 }
897
898 /**
899 * Process the contribution.
900 *
901 * @param CRM_Core_Form $form
902 * @param array $params
903 * @param array $result
904 * @param int $contactID
905 * @param bool $pending
906 * @param array $paymentProcessor
907 *
908 * @return \CRM_Contribute_BAO_Contribution
909 *
910 * @throws \CRM_Core_Exception
911 * @throws \CiviCRM_API3_Exception
912 */
913 protected function processContribution(
914 &$form, $params, $result, $contactID,
915 $pending = FALSE,
916 $paymentProcessor = NULL
917 ) {
918 // Note this used to be shared with the backoffice form & no longer is, some code may no longer be required.
919 $transaction = new CRM_Core_Transaction();
920
921 $now = date('YmdHis');
922 $receiptDate = NULL;
923
924 if (!empty($form->_values['event']['is_email_confirm'])) {
925 $receiptDate = $now;
926 }
927
928 // CRM-20264: fetch CC type ID and number (last 4 digit) and assign it back to $params
929 CRM_Contribute_Form_AbstractEditPayment::formatCreditCardDetails($params);
930
931 $contribParams = [
932 'contact_id' => $contactID,
933 'financial_type_id' => !empty($form->_values['event']['financial_type_id']) ? $form->_values['event']['financial_type_id'] : $params['financial_type_id'],
934 'receive_date' => $now,
935 'total_amount' => $params['amount'],
936 'tax_amount' => $params['tax_amount'],
937 'amount_level' => $params['amount_level'],
938 'invoice_id' => $params['invoiceID'],
939 'currency' => $params['currencyID'],
940 'source' => !empty($params['participant_source']) ? $params['participant_source'] : $params['description'],
941 'is_pay_later' => CRM_Utils_Array::value('is_pay_later', $params, 0),
942 'campaign_id' => $params['campaign_id'] ?? NULL,
943 'card_type_id' => $params['card_type_id'] ?? NULL,
944 'pan_truncation' => $params['pan_truncation'] ?? NULL,
945 ];
946
947 if ($paymentProcessor) {
948 $contribParams['payment_instrument_id'] = $paymentProcessor['payment_instrument_id'];
949 $contribParams['payment_processor'] = $paymentProcessor['id'];
950 }
951
952 if (!$pending && $result) {
953 $contribParams += [
954 'fee_amount' => $result['fee_amount'] ?? NULL,
955 'trxn_id' => $result['trxn_id'],
956 'receipt_date' => $receiptDate,
957 ];
958 }
959
960 $allStatuses = CRM_Contribute_PseudoConstant::contributionStatus(NULL, 'name');
961 $contribParams['contribution_status_id'] = array_search('Completed', $allStatuses);
962 if ($pending) {
963 $contribParams['contribution_status_id'] = array_search('Pending', $allStatuses);
964 }
965
966 $contribParams['is_test'] = 0;
967 if ($form->_action & CRM_Core_Action::PREVIEW || CRM_Utils_Array::value('mode', $params) == 'test') {
968 $contribParams['is_test'] = 1;
969 }
970
971 if (!empty($contribParams['invoice_id'])) {
972 $contribParams['id'] = CRM_Core_DAO::getFieldValue('CRM_Contribute_DAO_Contribution',
973 $contribParams['invoice_id'],
974 'id',
975 'invoice_id'
976 );
977 }
978
979 if (Civi::settings()->get('deferred_revenue_enabled')) {
980 $eventStartDate = CRM_Utils_Array::value(
981 'start_date',
982 CRM_Utils_Array::value(
983 'event',
984 $form->_values
985 )
986 );
987 if (strtotime($eventStartDate) > strtotime(date('Ymt'))) {
988 $contribParams['revenue_recognition_date'] = date('Ymd', strtotime($eventStartDate));
989 }
990 }
991 //create an contribution address
992 // The concept of contributeMode is deprecated. Elsewhere we use the function processBillingAddress() - although
993 // currently that is only inherited by back-office forms.
994 if ($form->_contributeMode != 'notify' && empty($params['is_pay_later'])) {
995 $contribParams['address_id'] = CRM_Contribute_BAO_Contribution::createAddress($params, $form->_bltID);
996 }
997
998 $contribParams['skipLineItem'] = 1;
999 $contribParams['skipCleanMoney'] = 1;
1000 // create contribution record
1001 $contribution = CRM_Contribute_BAO_Contribution::add($contribParams);
1002 // CRM-11124
1003 CRM_Event_BAO_Participant::createDiscountTrxn($form->_eventId, $contribParams, NULL, CRM_Price_BAO_PriceSet::parseFirstPriceSetValueIDFromParams($params));
1004
1005 // process soft credit / pcp pages
1006 if (!empty($params['pcp_made_through_id'])) {
1007 CRM_Contribute_BAO_ContributionSoft::formatSoftCreditParams($params, $form);
1008 CRM_Contribute_BAO_ContributionSoft::processSoftContribution($params, $contribution);
1009 }
1010
1011 $transaction->commit();
1012
1013 return $contribution;
1014 }
1015
1016 /**
1017 * Fix the Location Fields.
1018 *
1019 * @todo Reconcile with the contribution method formatParamsForPaymentProcessor
1020 * rather than adding different logic to check when to keep the billing
1021 * fields. There might be a difference in handling guest/multiple
1022 * participants though.
1023 *
1024 * @param array $params
1025 * @param array $fields
1026 * @param CRM_Core_Form $form
1027 */
1028 public static function fixLocationFields(&$params, &$fields, &$form) {
1029 if (!empty($form->_fields)) {
1030 foreach ($form->_fields as $name => $dontCare) {
1031 $fields[$name] = 1;
1032 }
1033 }
1034
1035 // If there's no 'first_name' in the profile then overwrite the names from
1036 // the billing fields (if they are set)
1037 if (is_array($fields)) {
1038 if (!array_key_exists('first_name', $fields)) {
1039 $nameFields = ['first_name', 'middle_name', 'last_name'];
1040 foreach ($nameFields as $name) {
1041 $fields[$name] = 1;
1042 if (array_key_exists("billing_$name", $params)) {
1043 $params[$name] = $params["billing_{$name}"];
1044 $params['preserveDBName'] = TRUE;
1045 }
1046 }
1047 }
1048 }
1049
1050 // Add the billing names to the billing address, if a billing name is set
1051 if (!empty($params['billing_first_name'])) {
1052 $params["address_name-{$form->_bltID}"] = CRM_Utils_Array::value('billing_first_name', $params) . ' ' . CRM_Utils_Array::value('billing_middle_name', $params) . ' ' . CRM_Utils_Array::value('billing_last_name', $params);
1053 $fields["address_name-{$form->_bltID}"] = 1;
1054 }
1055
1056 $fields["email-{$form->_bltID}"] = 1;
1057 $fields['email-Primary'] = 1;
1058
1059 //if its pay later or additional participant set email address as primary.
1060 if ((!empty($params['is_pay_later']) || empty($params['is_primary']) ||
1061 !$form->_values['event']['is_monetary'] ||
1062 $form->_allowWaitlist ||
1063 $form->_requireApproval
1064 ) && !empty($params["email-{$form->_bltID}"])
1065 ) {
1066 $params['email-Primary'] = $params["email-{$form->_bltID}"];
1067 }
1068 }
1069
1070 /**
1071 * Update contact fields.
1072 *
1073 * @param int $contactID
1074 * @param array $params
1075 * @param array $fields
1076 * @param CRM_Core_Form $form
1077 *
1078 * @return int
1079 */
1080 public static function updateContactFields($contactID, $params, $fields, &$form) {
1081 //add the contact to group, if add to group is selected for a
1082 //particular uf group
1083
1084 // get the add to groups
1085 $addToGroups = [];
1086
1087 if (!empty($form->_fields)) {
1088 foreach ($form->_fields as $key => $value) {
1089 if (!empty($value['add_to_group_id'])) {
1090 $addToGroups[$value['add_to_group_id']] = $value['add_to_group_id'];
1091 }
1092 }
1093 }
1094
1095 // check for profile double opt-in and get groups to be subscribed
1096 $subscribeGroupIds = CRM_Core_BAO_UFGroup::getDoubleOptInGroupIds($params, $contactID);
1097
1098 foreach ($addToGroups as $k) {
1099 if (array_key_exists($k, $subscribeGroupIds)) {
1100 unset($addToGroups[$k]);
1101 }
1102 }
1103
1104 // since we are directly adding contact to group lets unset it from mailing
1105 if (!empty($addToGroups)) {
1106 foreach ($addToGroups as $groupId) {
1107 if (isset($subscribeGroupIds[$groupId])) {
1108 unset($subscribeGroupIds[$groupId]);
1109 }
1110 }
1111 }
1112 if ($contactID) {
1113 $ctype = CRM_Core_DAO::getFieldValue(
1114 'CRM_Contact_DAO_Contact',
1115 $contactID,
1116 'contact_type'
1117 );
1118
1119 if (array_key_exists('contact_id', $params) && empty($params['contact_id'])) {
1120 // we unset this here because the downstream function ignores the contactID we give it
1121 // if it is set & it is difficult to understand the implications of 'fixing' this downstream
1122 // but if we are passing a contact id into this function it's reasonable to assume we don't
1123 // want it ignored
1124 unset($params['contact_id']);
1125 }
1126
1127 $contactID = CRM_Contact_BAO_Contact::createProfileContact(
1128 $params,
1129 $fields,
1130 $contactID,
1131 $addToGroups,
1132 NULL,
1133 $ctype,
1134 TRUE
1135 );
1136 }
1137 else {
1138
1139 foreach (CRM_Contact_BAO_Contact::$_greetingTypes as $greeting) {
1140 if (!isset($params[$greeting . '_id'])) {
1141 $params[$greeting . '_id'] = CRM_Contact_BAO_Contact_Utils::defaultGreeting('Individual', $greeting);
1142 }
1143 }
1144
1145 $contactID = CRM_Contact_BAO_Contact::createProfileContact($params,
1146 $fields,
1147 NULL,
1148 $addToGroups,
1149 NULL,
1150 NULL,
1151 TRUE
1152 );
1153 $form->set('contactID', $contactID);
1154 }
1155
1156 //get email primary first if exist
1157 $subscriptionEmail = ['email' => CRM_Utils_Array::value('email-Primary', $params)];
1158 if (!$subscriptionEmail['email']) {
1159 $subscriptionEmail['email'] = CRM_Utils_Array::value("email-{$form->_bltID}", $params);
1160 }
1161 // subscribing contact to groups
1162 if (!empty($subscribeGroupIds) && $subscriptionEmail['email']) {
1163 CRM_Mailing_Event_BAO_Subscribe::commonSubscribe($subscribeGroupIds, $subscriptionEmail, $contactID);
1164 }
1165
1166 return $contactID;
1167 }
1168
1169 /**
1170 * Assign Profiles to the template.
1171 *
1172 * @param CRM_Event_Form_Registration_Confirm $form
1173 *
1174 * @throws \Exception
1175 */
1176 public static function assignProfiles($form) {
1177 $participantParams = $form->_params;
1178 $formattedValues = $profileFields = [];
1179 $count = 1;
1180 foreach ($participantParams as $participantNum => $participantValue) {
1181 if ($participantNum) {
1182 $prefix1 = 'additional';
1183 $prefix2 = 'additional_';
1184 }
1185 else {
1186 $prefix1 = '';
1187 $prefix2 = '';
1188 }
1189 if ($participantValue !== 'skip') {
1190 //get the customPre profile info
1191 if (!empty($form->_values[$prefix2 . 'custom_pre_id'])) {
1192 $values = $groupName = [];
1193 CRM_Event_BAO_Event::displayProfile($participantValue,
1194 $form->_values[$prefix2 . 'custom_pre_id'],
1195 $groupName,
1196 $values,
1197 $profileFields
1198 );
1199
1200 if (count($values)) {
1201 $formattedValues[$count][$prefix1 . 'CustomPre'] = $values;
1202 }
1203 $formattedValues[$count][$prefix1 . 'CustomPreGroupTitle'] = CRM_Utils_Array::value('groupTitle', $groupName);
1204 }
1205 //get the customPost profile info
1206 if (!empty($form->_values[$prefix2 . 'custom_post_id'])) {
1207 $values = $groupName = [];
1208 foreach ($form->_values[$prefix2 . 'custom_post_id'] as $gids) {
1209 $val = [];
1210 CRM_Event_BAO_Event::displayProfile($participantValue,
1211 $gids,
1212 $group,
1213 $val,
1214 $profileFields
1215 );
1216 $values[$gids] = $val;
1217 $groupName[$gids] = $group;
1218 }
1219
1220 if (count($values)) {
1221 $formattedValues[$count][$prefix1 . 'CustomPost'] = $values;
1222 }
1223
1224 if (isset($formattedValues[$count][$prefix1 . 'CustomPre'])) {
1225 $formattedValues[$count][$prefix1 . 'CustomPost'] = array_diff_assoc($formattedValues[$count][$prefix1 . 'CustomPost'],
1226 $formattedValues[$count][$prefix1 . 'CustomPre']
1227 );
1228 }
1229
1230 $formattedValues[$count][$prefix1 . 'CustomPostGroupTitle'] = $groupName;
1231 }
1232 $count++;
1233 }
1234 $form->_fields = $profileFields;
1235 }
1236 if (!empty($formattedValues)) {
1237 $form->assign('primaryParticipantProfile', $formattedValues[1]);
1238 $form->set('primaryParticipantProfile', $formattedValues[1]);
1239 if ($count > 2) {
1240 unset($formattedValues[1]);
1241 $form->assign('addParticipantProfile', $formattedValues);
1242 $form->set('addParticipantProfile', $formattedValues);
1243 }
1244 }
1245 }
1246
1247 /**
1248 * Submit in test mode.
1249 *
1250 * @param $params
1251 */
1252 public static function testSubmit($params) {
1253 $form = new CRM_Event_Form_Registration_Confirm();
1254 // This way the mocked up controller ignores the session stuff.
1255 $_SERVER['REQUEST_METHOD'] = 'GET';
1256 $_REQUEST['id'] = $form->_eventId = $params['id'];
1257 $form->controller = new CRM_Event_Controller_Registration();
1258 $form->_params = $params['params'];
1259 // This happens in buildQuickForm so emulate here.
1260 $form->_amount = $form->_totalAmount = CRM_Utils_Rule::cleanMoney(CRM_Utils_Array::value('totalAmount', $params));
1261 $form->set('params', $params['params']);
1262 $form->_values['custom_pre_id'] = CRM_Utils_Array::value('custom_pre_id', $params);
1263 $form->_values['custom_post_id'] = CRM_Utils_Array::value('custom_post_id', $params);
1264 $form->_values['event'] = CRM_Utils_Array::value('event', $params);
1265 $form->_contributeMode = $params['contributeMode'];
1266 $eventParams = ['id' => $params['id']];
1267 CRM_Event_BAO_Event::retrieve($eventParams, $form->_values['event']);
1268 $form->set('registerByID', $params['registerByID']);
1269 if (!empty($params['paymentProcessorObj'])) {
1270 $form->_paymentProcessor = $params['paymentProcessorObj'];
1271 }
1272 $form->postProcess();
1273 }
1274
1275 /**
1276 * Process the payment, redirecting back to the page on error.
1277 *
1278 * @param \CRM_Core_Payment $payment
1279 * @param $value
1280 *
1281 * @return array
1282 */
1283 private function processPayment($payment, $value) {
1284 try {
1285 $params = $this->prepareParamsForPaymentProcessor($value);
1286 $result = $payment->doPayment($params, 'event');
1287 return [$result, $value];
1288 }
1289 catch (\Civi\Payment\Exception\PaymentProcessorException $e) {
1290 Civi::log()->error('Payment processor exception: ' . $e->getMessage());
1291 CRM_Core_Session::singleton()->setStatus($e->getMessage());
1292 CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/event/register', "id={$this->_eventId}"));
1293 }
1294 return [];
1295 }
1296
1297 /**
1298 * Clean money fields from the form.
1299 *
1300 * @param array $params
1301 */
1302 protected function cleanMoneyFields(&$params) {
1303 foreach ($this->submittableMoneyFields as $moneyField) {
1304 foreach ($params as $index => $paramField) {
1305 if (isset($paramField[$moneyField])) {
1306 $params[$index][$moneyField] = CRM_Utils_Rule::cleanMoney($paramField[$moneyField]);
1307 }
1308 }
1309 }
1310 }
1311
1312 }