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