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