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