Merge pull request #13106 from seamuslee001/5.8
[civicrm-core.git] / CRM / Event / Form / Registration / Confirm.php
... / ...
CommitLineData
1<?php
2/*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 5 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2018 |
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 +--------------------------------------------------------------------+
26 */
27
28/**
29 * @package CRM
30 * @copyright CiviCRM LLC (c) 2004-2018
31 */
32
33/**
34 * This class generates form components for processing Event.
35 */
36class CRM_Event_Form_Registration_Confirm extends CRM_Event_Form_Registration {
37
38 /**
39 * The values for the contribution db object.
40 *
41 * @var array
42 */
43 public $_values;
44
45 /**
46 * The total amount.
47 *
48 * @var float
49 */
50 public $_totalAmount;
51
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
61 /**
62 * Set variables up before form is built.
63 */
64 public function preProcess() {
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');
71 $this->_params[0]['tax_amount'] = $this->get('tax_amount');
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
81 if (!empty($this->_params[0]['discount']) && !empty($this->_params[0]['discount']['applied'])) {
82 $this->set('hookDiscount', $this->_params[0]['discount']);
83 $this->assign('hookDiscount', $this->_params[0]['discount']);
84 }
85
86 // The concept of contributeMode is deprecated.
87 if ($this->_contributeMode == 'express') {
88 $params = array();
89 // rfp == redirect from paypal
90 // rfp is probably not required - the getPreApprovalDetails should deal with any payment-processor specific 'stuff'
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)) {
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);
100 }
101 CRM_Core_Payment_Form::mapParams($this->_bltID, $params, $params, FALSE);
102
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.
105 $params['amount'] = $this->_params[0]['amount'];
106 if (!empty($this->_params[0]['discount'])) {
107 $params['discount'] = $this->_params[0]['discount'];
108 $params['discountAmount'] = $this->_params[0]['discountAmount'];
109 $params['discountMessage'] = $this->_params[0]['discountMessage'];
110 }
111
112 $params['amount_level'] = $this->_params[0]['amount_level'];
113 $params['currencyID'] = $this->_params[0]['currencyID'];
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 }
131 if (substr($name, 0, 6) == 'price_') {
132 $params[$name] = $this->_params[0][$name];
133 }
134 }
135 $this->set('getExpressCheckoutDetails', $params);
136 }
137 $this->_params[0] = array_merge($this->_params[0], $params);
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'])) {
153 $registerParams['year'] = CRM_Core_Payment_Form::getCreditCardExpirationYear($registerParams);
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'];
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
172 if (empty($this->_params[0]['participant_role_id']) &&
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 /**
191 * Overwrite action, since we are only showing elements in frozen mode no help display needed.
192 *
193 * @return int
194 */
195 public function getAction() {
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 /**
205 * Build the form object.
206 */
207 public function buildQuickForm() {
208 $this->assignToTemplate();
209
210 if ($this->_values['event']['is_monetary'] &&
211 ($this->_params[0]['amount'] || $this->_params[0]['amount'] == 0) &&
212 !$this->_requireApproval
213 ) {
214 $this->_amount = array();
215
216 $taxAmount = 0;
217 foreach ($this->_params as $k => $v) {
218 $this->cleanMoneyFields($v);
219 if ($v == 'skip') {
220 continue;
221 }
222 $individualTaxAmount = 0;
223 //display tax amount on confirmation page
224 $taxAmount += $v['tax_amount'];
225 if (is_array($v)) {
226 foreach (array(
227 'first_name',
228 'last_name',
229 ) as $name) {
230 if (isset($v['billing_' . $name]) &&
231 !isset($v[$name])
232 ) {
233 $v[$name] = $v['billing_' . $name];
234 }
235 }
236
237 if (!empty($v['first_name']) && !empty($v['last_name'])) {
238 $append = $v['first_name'] . ' ' . $v['last_name'];
239 }
240 else {
241 //use an email if we have one
242 foreach ($v as $v_key => $v_val) {
243 if (substr($v_key, 0, 6) == 'email-') {
244 $append = $v[$v_key];
245 }
246 }
247 }
248
249 $this->_amount[$k]['amount'] = $v['amount'];
250 if (!empty($v['discountAmount'])) {
251 $this->_amount[$k]['amount'] -= $v['discountAmount'];
252 }
253
254 $this->_amount[$k]['label'] = preg_replace('/\ 1/', '', $v['amount_level']) . ' - ' . $append;
255 $this->_part[$k]['info'] = CRM_Utils_Array::value('first_name', $v) . ' ' . CRM_Utils_Array::value('last_name', $v);
256 if (empty($v['first_name'])) {
257 $this->_part[$k]['info'] = $append;
258 }
259
260 /*CRM-16320 */
261 $individual[$k]['totalAmtWithTax'] = $this->_amount[$k]['amount'];
262 $individual[$k]['totalTaxAmt'] = $individualTaxAmount + $v['tax_amount'];
263 $this->_totalAmount = $this->_totalAmount + $this->_amount[$k]['amount'];
264 if (!empty($v['is_primary'])) {
265 $this->set('primaryParticipantAmount', $this->_amount[$k]['amount']);
266 }
267 }
268 }
269
270 $invoiceSettings = Civi::settings()->get('contribution_invoice_settings');
271 $taxTerm = CRM_Utils_Array::value('tax_term', $invoiceSettings);
272 $invoicing = CRM_Utils_Array::value('invoicing', $invoiceSettings);
273 if ($invoicing) {
274 $this->assign('totalTaxAmount', $taxAmount);
275 $this->assign('taxTerm', $taxTerm);
276 $this->assign('individual', $individual);
277 $this->set('individual', $individual);
278 }
279
280 $this->assign('part', $this->_part);
281 $this->set('part', $this->_part);
282 $this->assign('amounts', $this->_amount);
283 $this->assign('totalAmount', $this->_totalAmount);
284 $this->set('totalAmount', $this->_totalAmount);
285 }
286
287 if ($this->_priceSetId && !CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceSet', $this->_priceSetId, 'is_quick_config')) {
288 $lineItemForTemplate = array();
289 $getTaxDetails = FALSE;
290 if (!empty($this->_lineItem) && is_array($this->_lineItem)) {
291 foreach ($this->_lineItem as $key => $value) {
292 if (!empty($value)) {
293 $lineItemForTemplate[$key] = $value;
294 }
295 if ($invoicing) {
296 foreach ($value as $v) {
297 if (isset($v['tax_rate'])) {
298 $getTaxDetails = TRUE;
299 }
300 }
301 }
302 }
303 }
304 if (!empty($lineItemForTemplate)) {
305 $this->assign('lineItem', $lineItemForTemplate);
306 }
307 $this->assign('getTaxDetails', $getTaxDetails);
308 }
309
310 //display additional participants profile.
311 self::assignProfiles($this);
312
313 //consider total amount.
314 $this->assign('isAmountzero', ($this->_totalAmount <= 0) ? TRUE : FALSE);
315
316 $contribButton = ts('Continue');
317 $this->addButtons(array(
318 array(
319 'type' => 'back',
320 'name' => ts('Go Back'),
321 ),
322 array(
323 'type' => 'next',
324 'name' => $contribButton,
325 'isDefault' => TRUE,
326 'js' => array('onclick' => "return submitOnce(this,'" . $this->_name . "','" . ts('Processing') . "');"),
327 ),
328 )
329 );
330
331 $defaults = array();
332 $fields = array();
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
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
367 $this->assign('pricesetFieldsCount', CRM_Price_BAO_PriceSet::getPricesetCount($this->_priceSetId));
368 $this->addFormRule(array('CRM_Event_Form_Registration_Confirm', 'formRule'), $this);
369 }
370
371 /**
372 * Apply form rule.
373 *
374 * @param array $fields
375 * @param array $files
376 * @param CRM_Core_Form $self
377 *
378 * @return array|bool
379 */
380 public static function formRule($fields, $files, $self) {
381 $errors = array();
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)) {
385 CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/event/register', "reset=1&id={$self->_eventId}", FALSE, NULL, FALSE, TRUE));
386 }
387 }
388 $self->_feeBlock = $self->_values['fee'];
389 CRM_Event_Form_Registration_Register::formatFieldsForOptionFull($self);
390
391 if (!empty($self->_priceSetId) &&
392 !$self->_requireApproval && !$self->_allowWaitlist
393 ) {
394 $priceSetErrors = self::validatePriceSet($self, $self->_params);
395 if (!empty($priceSetErrors)) {
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');
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 }
400 }
401
402 return empty($priceSetErrors) ? TRUE : $priceSetErrors;
403 }
404
405 /**
406 * Process the form submission.
407 */
408 public function postProcess() {
409 $now = date('YmdHis');
410
411 $this->_params = $this->get('params');
412 $this->cleanMoneyFields($this->_params);
413
414 if (!empty($this->_params[0]['contact_id'])) {
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
418 $contactID = $this->_params[0]['contact_id'];
419 }
420 else {
421 $contactID = $this->getContactID();
422 }
423
424 // if a discount has been applied, lets now deduct it from the amount
425 // and fix the fee level
426 if (!empty($this->_params[0]['discount']) && !empty($this->_params[0]['discount']['applied'])) {
427 foreach ($this->_params as $k => $v) {
428 if (CRM_Utils_Array::value('amount', $this->_params[$k]) > 0 && !empty($this->_params[$k]['discountAmount'])) {
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;
442 if ($this->_values['event']['is_monetary']) {
443 $this->set('finalAmount', $this->_amount);
444 }
445 $participantCount = array();
446 $taxAmount = $totalTaxAmount = 0;
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 }
459 $totalTaxAmount += CRM_Utils_Array::value('tax_amount', $record, 0);
460 if (CRM_Utils_Array::value('is_primary', $record)) {
461 $taxAmount = &$params[$participantNum]['tax_amount'];
462 }
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 }
471 $taxAmount = $totalTaxAmount;
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
475 $this->participantIDS = array();
476 $fields = array();
477 foreach ($params as $key => $value) {
478 CRM_Event_Form_Registration_Confirm::fixLocationFields($value, $fields, $this);
479 //unset the billing parameters if it is pay later mode
480 //to avoid creation of billing location
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.
484 if ($this->_allowWaitlist
485 || $this->_requireApproval
486 || (!empty($value['is_pay_later']) && !$this->_isBillingAddressRequiredForPayLater)
487 || empty($value['is_primary'])
488 ) {
489 $billingFields = array(
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}",
502 );
503 foreach ($billingFields as $field) {
504 unset($value[$field]);
505 }
506 if (!empty($value['is_pay_later'])) {
507 $this->_values['params']['is_pay_later'] = TRUE;
508 }
509 }
510
511 //Unset ContactID for additional participants and set RegisterBy Id.
512 if (empty($value['is_primary'])) {
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
523 $contactID = CRM_Event_Form_Registration_Confirm::updateContactFields($contactID, $value, $fields, $this);
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
529 if (!$this->getContactID() && !empty($value['is_primary'])) {
530 $session = CRM_Core_Session::singleton();
531 $session->set('transaction.userID', $contactID);
532 }
533
534 $value['description'] = ts('Online Event Registration') . ': ' . $this->_values['event']['title'];
535 $value['accountingCode'] = CRM_Utils_Array::value('accountingCode',
536 $this->_values['event']
537 );
538
539 $pending = FALSE;
540 if ($this->_allowWaitlist || $this->_requireApproval) {
541 //get the participant statuses.
542 $waitingStatuses = CRM_Event_PseudoConstant::participantStatus(NULL, "class = 'Waiting'");
543 if ($this->_allowWaitlist) {
544 $value['participant_status_id'] = $value['participant_status'] = array_search('On waitlist', $waitingStatuses);
545 }
546 else {
547 $value['participant_status_id'] = $value['participant_status'] = array_search('Awaiting approval', $waitingStatuses);
548 }
549
550 //there might be case user seleted pay later and
551 //now becomes part of run time waiting list.
552 $value['is_pay_later'] = FALSE;
553 }
554
555 // required only if paid event
556 if ($this->_values['event']['is_monetary'] && !($this->_allowWaitlist || $this->_requireApproval)) {
557 if (is_array($this->_paymentProcessor)) {
558 $payment = $this->_paymentProcessor['object'];
559 }
560 if (!empty($this->_paymentProcessor) && $this->_paymentProcessor['object']->supports('preApproval')) {
561 $preApprovalParams = $this->_paymentProcessor['object']->getPreApprovalDetails($this->get('pre_approval_parameters'));
562 $value = array_merge($value, $preApprovalParams);
563 }
564 $result = NULL;
565
566 if (!empty($value['is_pay_later']) ||
567 $value['amount'] == 0 ||
568 // The concept of contributeMode is deprecated.
569 $this->_contributeMode == 'checkout' ||
570 $this->_contributeMode == 'notify'
571 ) {
572 if ($value['amount'] != 0) {
573 $pending = TRUE;
574 //get the participant statuses.
575 $pendingStatuses = CRM_Event_PseudoConstant::participantStatus(NULL, "class = 'Pending'");
576 $status = !empty($value['is_pay_later']) ? 'Pending from pay later' : 'Pending from incomplete transaction';
577 $value['participant_status_id'] = $value['participant_status'] = array_search($status, $pendingStatuses);
578 }
579 }
580 elseif (!empty($value['is_primary'])) {
581 CRM_Core_Payment_Form::mapParams($this->_bltID, $value, $value, TRUE);
582 // payment email param can be empty for _bltID mapping
583 // thus provide mapping for it with a different email value
584 if (empty($value['email'])) {
585 $value['email'] = CRM_Utils_Array::valueByRegexKey('/^email-/', $value);
586 }
587
588 if (is_object($payment)) {
589 // Not quite sure why we don't just user $value since it contains the data
590 // from result
591 // @todo ditch $result & retest.
592 list($result, $value) = $this->processPayment($payment, $value);
593 }
594 else {
595 CRM_Core_Error::fatal($paymentObjError);
596 }
597 }
598
599 $value['receive_date'] = $now;
600 if ($this->_allowConfirmation) {
601 $value['participant_register_date'] = $this->_values['participant']['register_date'];
602 }
603
604 $createContrib = ($value['amount'] != 0) ? TRUE : FALSE;
605 // force to create zero amount contribution, CRM-5095
606 if (!$createContrib && ($value['amount'] == 0)
607 && $this->_priceSetId && $this->_lineItem
608 ) {
609 $createContrib = TRUE;
610 }
611
612 if ($createContrib && !empty($value['is_primary']) &&
613 !$this->_allowWaitlist && !$this->_requireApproval
614 ) {
615 // if paid event add a contribution record
616 //if primary participant contributing additional amount
617 //append (multiple participants) to its fee level. CRM-4196.
618 $isAdditionalAmount = FALSE;
619 if (count($params) > 1) {
620 $isAdditionalAmount = TRUE;
621 }
622
623 //passing contribution id is already registered.
624 $contribution = self::processContribution($this, $value, $result, $contactID, $pending, $isAdditionalAmount, $this->_paymentProcessor);
625 $value['contributionID'] = $contribution->id;
626 $value['contributionTypeID'] = $contribution->financial_type_id;
627 $value['receive_date'] = $contribution->receive_date;
628 $value['trxn_id'] = $contribution->trxn_id;
629 $value['contributionID'] = $contribution->id;
630 $value['contributionTypeID'] = $contribution->financial_type_id;
631 }
632 $value['contactID'] = $contactID;
633 $value['eventID'] = $this->_eventId;
634 $value['item_name'] = $value['description'];
635 }
636
637 if (!empty($value['contributionID'])) {
638 $this->_values['contributionId'] = $value['contributionID'];
639 }
640
641 //CRM-4453.
642 if (!empty($value['is_primary'])) {
643 $primaryCurrencyID = CRM_Utils_Array::value('currencyID', $value);
644 }
645 if (empty($value['currencyID'])) {
646 $value['currencyID'] = $primaryCurrencyID;
647 }
648
649 // CRM-11182 - Confirmation page might not be monetary
650 if ($this->_values['event']['is_monetary']) {
651 if (!$pending && !empty($value['is_primary']) &&
652 !$this->_allowWaitlist && !$this->_requireApproval
653 ) {
654 // transactionID & receive date required while building email template
655 $this->assign('trxn_id', CRM_Utils_Array::value('trxn_id', $value));
656 $this->assign('receive_date', CRM_Utils_Date::mysqlToIso(CRM_Utils_Array::value('receive_date', $value)));
657 $this->set('receiveDate', CRM_Utils_Date::mysqlToIso(CRM_Utils_Array::value('receive_date', $value)));
658 $this->set('trxnId', CRM_Utils_Array::value('trxn_id', $value));
659 }
660 }
661
662 $value['fee_amount'] = CRM_Utils_Array::value('amount', $value);
663 $this->set('value', $value);
664
665 // handle register date CRM-4320
666 if ($this->_allowConfirmation) {
667 $registerDate = CRM_Utils_Array::value('participant_register_date', $params);
668 }
669 elseif (!empty($params['participant_register_date']) &&
670 is_array($params['participant_register_date']) &&
671 !empty($params['participant_register_date'])
672 ) {
673 $registerDate = CRM_Utils_Date::format($params['participant_register_date']);
674 }
675 else {
676 $registerDate = date('YmdHis');
677 }
678 $this->assign('register_date', $registerDate);
679
680 $this->confirmPostProcess($contactID, $contribution, $payment);
681 }
682
683 //handle if no additional participant.
684 if (!$registerByID) {
685 $registerByID = $this->get('registerByID');
686 }
687
688 $this->set('participantIDs', $this->_participantIDS);
689
690 // create line items, CRM-5313
691 if ($this->_priceSetId &&
692 !empty($this->_lineItem)
693 ) {
694 // take all processed participant ids.
695 $allParticipantIds = $this->_participantIDS;
696
697 // when participant re-walk wizard.
698 if ($this->_allowConfirmation &&
699 !empty($this->_additionalParticipantIds)
700 ) {
701 $allParticipantIds = array_merge(array($registerByID), $this->_additionalParticipantIds);
702 }
703
704 $entityTable = 'civicrm_participant';
705 $invoiceSettings = Civi::settings()->get('contribution_invoice_settings');
706 $invoicing = CRM_Utils_Array::value('invoicing', $invoiceSettings);
707 $totalTaxAmount = 0;
708 $dataArray = array();
709 foreach ($this->_lineItem as $key => $value) {
710 if ($value == 'skip') {
711 continue;
712 }
713 if ($entityId = CRM_Utils_Array::value($key, $allParticipantIds)) {
714 // do cleanup line items if participant re-walking wizard.
715 if ($this->_allowConfirmation) {
716 CRM_Price_BAO_LineItem::deleteLineItems($entityId, $entityTable);
717 }
718 $lineItem[$this->_priceSetId] = $value;
719 CRM_Price_BAO_LineItem::processPriceSet($entityId, $lineItem, $contribution, $entityTable);
720 }
721 if ($invoicing) {
722 foreach ($value as $line) {
723 if (isset($line['tax_amount']) && isset($line['tax_rate'])) {
724 $totalTaxAmount = $line['tax_amount'] + $totalTaxAmount;
725 if (isset($dataArray[$line['tax_rate']])) {
726 $dataArray[$line['tax_rate']] = $dataArray[$line['tax_rate']] + CRM_Utils_Array::value('tax_amount', $line);
727 }
728 else {
729 $dataArray[$line['tax_rate']] = CRM_Utils_Array::value('tax_amount', $line);
730 }
731 }
732 }
733 }
734 }
735 if ($invoicing) {
736 $this->assign('dataArray', $dataArray);
737 $this->assign('totalTaxAmount', $totalTaxAmount);
738 }
739 }
740
741 //update status and send mail to cancelled additional participants, CRM-4320
742 if ($this->_allowConfirmation && is_array($cancelledIds) && !empty($cancelledIds)) {
743 $cancelledId = array_search('Cancelled',
744 CRM_Event_PseudoConstant::participantStatus(NULL, "class = 'Negative'")
745 );
746 CRM_Event_BAO_Participant::transitionParticipants($cancelledIds, $cancelledId);
747 }
748
749 $isTest = FALSE;
750 if ($this->_action & CRM_Core_Action::PREVIEW) {
751 $isTest = TRUE;
752 }
753
754 // for Transfer checkout.
755 // The concept of contributeMode is deprecated.
756 if (($this->_contributeMode == 'checkout' ||
757 $this->_contributeMode == 'notify'
758 ) && empty($params[0]['is_pay_later']) &&
759 !$this->_allowWaitlist && !$this->_requireApproval &&
760 $this->_totalAmount > 0
761 ) {
762
763 $primaryParticipant = $this->get('primaryParticipant');
764
765 if (empty($primaryParticipant['participantID'])) {
766 $primaryParticipant['participantID'] = $registerByID;
767 }
768
769 //build an array of custom profile and assigning it to template
770 $customProfile = CRM_Event_BAO_Event::buildCustomProfile($registerByID, $this->_values, NULL, $isTest);
771 if (count($customProfile)) {
772 $this->assign('customProfile', $customProfile);
773 $this->set('customProfile', $customProfile);
774 }
775
776 // do a transfer only if a monetary payment greater than 0
777 if ($this->_values['event']['is_monetary'] && $primaryParticipant) {
778 if ($payment && is_object($payment)) {
779 //CRM 14512 provide line items of all participants to payment gateway
780 $primaryContactId = $this->get('primaryContactId');
781
782 //build an array of cId/pId of participants
783 $additionalIDs = CRM_Event_BAO_Event::buildCustomProfile($registerByID, NULL, $primaryContactId, $isTest, TRUE);
784
785 //need to copy, since we are unsetting on the way.
786 $copyParticipantCountLines = $participantCount;
787
788 //lets carry all participant params w/ values.
789 foreach ($additionalIDs as $participantID => $contactId) {
790 $participantNum = NULL;
791 $participantNum = $participantID;
792 if ($participantID == $registerByID) {
793 // This is the is primary participant.
794 $participantNum = 0;
795 }
796 else {
797 if ($participantNum = array_search('participant', $copyParticipantCountLines)) {
798 //if no participant found break.
799 if ($participantNum === NULL) {
800 break;
801 }
802 //unset current particpant so we don't check them again
803 unset($copyParticipantCountLines[$participantNum]);
804 }
805 }
806 // get values of line items
807 if ($this->_amount) {
808 $amount = array();
809 $amount[$participantNum]['label'] = preg_replace('/\ 1/', '', $params[$participantNum]['amount_level']);
810 $amount[$participantNum]['amount'] = $params[$participantNum]['amount'];
811 $params[$participantNum]['amounts'] = $amount;
812 }
813
814 if (!empty($this->_lineItem)) {
815 $lineItems = $this->_lineItem;
816 $lineItem = array();
817 if ($lineItemValue = CRM_Utils_Array::value($participantNum, $lineItems)) {
818 $lineItem[] = $lineItemValue;
819 }
820 $params[$participantNum]['lineItem'] = $lineItem;
821 }
822
823 //only add additional particpants and not the primary particpant as we already have that
824 //added to $primaryParticipant so that this change doesn't break or require changes to
825 //existing gateway implementations
826 $primaryParticipant['participants_info'][$participantID] = $params[$participantNum];
827 }
828
829 //get event custom field information
830 $groupTree = CRM_Core_BAO_CustomGroup::getTree('Event', NULL, $this->_eventId, 0, $this->_values['event']['event_type_id']);
831 $primaryParticipant['eventCustomFields'] = $groupTree;
832
833 // call postprocess hook before leaving
834 $this->postProcessHook();
835 // this does not return
836
837 $this->processPayment($payment, $primaryParticipant);
838 }
839 else {
840 CRM_Core_Error::fatal($paymentObjError);
841 }
842 }
843 }
844 else {
845 //otherwise send mail Confirmation/Receipt
846 $primaryContactId = $this->get('primaryContactId');
847
848 //build an array of cId/pId of participants
849 $additionalIDs = CRM_Event_BAO_Event::buildCustomProfile($registerByID,
850 NULL, $primaryContactId, $isTest,
851 TRUE
852 );
853 //lets send mails to all with meaningful text, CRM-4320.
854 $this->assign('isOnWaitlist', $this->_allowWaitlist);
855 $this->assign('isRequireApproval', $this->_requireApproval);
856
857 //need to copy, since we are unsetting on the way.
858 $copyParticipantCount = $participantCount;
859
860 //lets carry all paticipant params w/ values.
861 foreach ($additionalIDs as $participantID => $contactId) {
862 $participantNum = NULL;
863 if ($participantID == $registerByID) {
864 $participantNum = 0;
865 }
866 else {
867 if ($participantNum = array_search('participant', $copyParticipantCount)) {
868 unset($copyParticipantCount[$participantNum]);
869 }
870 }
871 if ($participantNum === NULL) {
872 break;
873 }
874
875 //carry the participant submitted values.
876 $this->_values['params'][$participantID] = $params[$participantNum];
877 }
878
879 foreach ($additionalIDs as $participantID => $contactId) {
880 $participantNum = 0;
881 if ($participantID == $registerByID) {
882 //set as Primary Participant
883 $this->assign('isPrimary', 1);
884 //build an array of custom profile and assigning it to template.
885 $customProfile = CRM_Event_BAO_Event::buildCustomProfile($participantID, $this->_values, NULL, $isTest);
886
887 if (count($customProfile)) {
888 $this->assign('customProfile', $customProfile);
889 $this->set('customProfile', $customProfile);
890 }
891 $this->_values['params']['additionalParticipant'] = FALSE;
892 }
893 else {
894 //take the Additional participant number.
895 if ($participantNum = array_search('participant', $participantCount)) {
896 unset($participantCount[$participantNum]);
897 }
898 // Change $this->_values['participant'] to include additional participant values
899 $ids = $participantValues = array();
900 $participantParams = array('id' => $participantID);
901 CRM_Event_BAO_Participant::getValues($participantParams, $participantValues, $ids);
902 $this->_values['participant'] = $participantValues[$participantID];
903
904 $this->assign('isPrimary', 0);
905 $this->assign('customProfile', NULL);
906 //Additional Participant should get only it's payment information
907 if (!empty($this->_amount)) {
908 $amount = array();
909 $params = $this->get('params');
910 $amount[$participantNum]['label'] = preg_replace('/\ 1/', '', $params[$participantNum]['amount_level']);
911 $amount[$participantNum]['amount'] = $params[$participantNum]['amount'];
912 $this->assign('amounts', $amount);
913 }
914 if ($this->_lineItem) {
915 $lineItems = $this->_lineItem;
916 $lineItem = array();
917 if ($lineItemValue = CRM_Utils_Array::value($participantNum, $lineItems)) {
918 $lineItem[] = $lineItemValue;
919 }
920 if ($invoicing) {
921 $individual = $this->get('individual');
922 $dataArray[key($dataArray)] = $individual[$participantNum]['totalTaxAmt'];
923 $this->assign('dataArray', $dataArray);
924 $this->assign('totalAmount', $individual[$participantNum]['totalAmtWithTax']);
925 $this->assign('totalTaxAmount', $individual[$participantNum]['totalTaxAmt']);
926 $this->assign('individual', array($individual[$participantNum]));
927 }
928 $this->assign('lineItem', $lineItem);
929 }
930 $this->_values['params']['additionalParticipant'] = TRUE;
931 $this->assign('isAdditionalParticipant', $this->_values['params']['additionalParticipant']);
932 }
933
934 //pass these variables since these are run time calculated.
935 $this->_values['params']['isOnWaitlist'] = $this->_allowWaitlist;
936 $this->_values['params']['isRequireApproval'] = $this->_requireApproval;
937
938 //send mail to primary as well as additional participants.
939 $this->assign('contactID', $contactId);
940 $this->assign('participantID', $participantID);
941 CRM_Event_BAO_Event::sendMail($contactId, $this->_values, $participantID, $isTest);
942 }
943 }
944 }
945
946 /**
947 * Process the contribution.
948 *
949 * @param CRM_Core_Form $form
950 * @param array $params
951 * @param array $result
952 * @param int $contactID
953 * @param bool $pending
954 * @param bool $isAdditionalAmount
955 *
956 * @return \CRM_Contribute_BAO_Contribution
957 */
958 public static function processContribution(
959 &$form, $params, $result, $contactID,
960 $pending = FALSE, $isAdditionalAmount = FALSE,
961 $paymentProcessor = NULL
962 ) {
963 $transaction = new CRM_Core_Transaction();
964
965 $now = date('YmdHis');
966 $receiptDate = NULL;
967
968 if (!empty($form->_values['event']['is_email_confirm'])) {
969 $receiptDate = $now;
970 }
971 //CRM-4196
972 if ($isAdditionalAmount) {
973 $params['amount_level'] = $params['amount_level'] . ts(' (multiple participants)') . CRM_Core_DAO::VALUE_SEPARATOR;
974 }
975
976 // CRM-20264: fetch CC type ID and number (last 4 digit) and assign it back to $params
977 CRM_Contribute_Form_AbstractEditPayment::formatCreditCardDetails($params);
978
979 $contribParams = array(
980 'contact_id' => $contactID,
981 'financial_type_id' => !empty($form->_values['event']['financial_type_id']) ? $form->_values['event']['financial_type_id'] : $params['financial_type_id'],
982 'receive_date' => $now,
983 'total_amount' => $params['amount'],
984 'tax_amount' => $params['tax_amount'],
985 'amount_level' => $params['amount_level'],
986 'invoice_id' => $params['invoiceID'],
987 'currency' => $params['currencyID'],
988 'source' => !empty($params['participant_source']) ? $params['participant_source'] : $params['description'],
989 'is_pay_later' => CRM_Utils_Array::value('is_pay_later', $params, 0),
990 'campaign_id' => CRM_Utils_Array::value('campaign_id', $params),
991 'card_type_id' => CRM_Utils_Array::value('card_type_id', $params),
992 'pan_truncation' => CRM_Utils_Array::value('pan_truncation', $params),
993 );
994
995 if ($paymentProcessor) {
996 $contribParams['payment_instrument_id'] = $paymentProcessor['payment_instrument_id'];
997 $contribParams['payment_processor'] = $paymentProcessor['id'];
998 }
999
1000 if (!$pending && $result) {
1001 $contribParams += array(
1002 'fee_amount' => CRM_Utils_Array::value('fee_amount', $result),
1003 'net_amount' => CRM_Utils_Array::value('net_amount', $result, $params['amount']),
1004 'trxn_id' => $result['trxn_id'],
1005 'receipt_date' => $receiptDate,
1006 );
1007 }
1008
1009 $allStatuses = CRM_Contribute_PseudoConstant::contributionStatus(NULL, 'name');
1010 $contribParams['contribution_status_id'] = array_search('Completed', $allStatuses);
1011 if ($pending) {
1012 $contribParams['contribution_status_id'] = array_search('Pending', $allStatuses);
1013 }
1014
1015 $contribParams['is_test'] = 0;
1016 if ($form->_action & CRM_Core_Action::PREVIEW || CRM_Utils_Array::value('mode', $params) == 'test') {
1017 $contribParams['is_test'] = 1;
1018 }
1019
1020 $contribID = NULL;
1021 if (!empty($contribParams['invoice_id'])) {
1022 $contribID = CRM_Core_DAO::getFieldValue('CRM_Contribute_DAO_Contribution',
1023 $contribParams['invoice_id'],
1024 'id',
1025 'invoice_id'
1026 );
1027 }
1028
1029 $ids = array();
1030 if ($contribID) {
1031 $ids['contribution'] = $contribID;
1032 $contribParams['id'] = $contribID;
1033 }
1034
1035 if (CRM_Contribute_BAO_Contribution::checkContributeSettings('deferred_revenue_enabled')) {
1036 $eventStartDate = CRM_Utils_Array::value(
1037 'start_date',
1038 CRM_Utils_Array::value(
1039 'event',
1040 $form->_values
1041 )
1042 );
1043 if (strtotime($eventStartDate) > strtotime(date('Ymt'))) {
1044 $contribParams['revenue_recognition_date'] = date('Ymd', strtotime($eventStartDate));
1045 }
1046 }
1047 //create an contribution address
1048 // The concept of contributeMode is deprecated. Elsewhere we use the function processBillingAddress() - although
1049 // currently that is only inherited by back-office forms.
1050 if ($form->_contributeMode != 'notify' && empty($params['is_pay_later'])) {
1051 $contribParams['address_id'] = CRM_Contribute_BAO_Contribution::createAddress($params, $form->_bltID);
1052 }
1053
1054 $contribParams['skipLineItem'] = 1;
1055 $contribParams['skipCleanMoney'] = 1;
1056 // create contribution record
1057 $contribution = CRM_Contribute_BAO_Contribution::add($contribParams);
1058 // CRM-11124
1059 CRM_Event_BAO_Participant::createDiscountTrxn($form->_eventId, $contribParams, NULL, CRM_Price_BAO_PriceSet::parseFirstPriceSetValueIDFromParams($params));
1060
1061 // process soft credit / pcp pages
1062 if (!empty($params['pcp_made_through_id'])) {
1063 CRM_Contribute_BAO_ContributionSoft::formatSoftCreditParams($params, $form);
1064 CRM_Contribute_BAO_ContributionSoft::processSoftContribution($params, $contribution);
1065 }
1066
1067 $transaction->commit();
1068
1069 return $contribution;
1070 }
1071
1072 /**
1073 * Fix the Location Fields.
1074 *
1075 * @todo Reconcile with the contribution method formatParamsForPaymentProcessor
1076 * rather than adding different logic to check when to keep the billing
1077 * fields. There might be a difference in handling guest/multiple
1078 * participants though.
1079 *
1080 * @param array $params
1081 * @param array $fields
1082 * @param CRM_Core_Form $form
1083 */
1084 public static function fixLocationFields(&$params, &$fields, &$form) {
1085 if (!empty($form->_fields)) {
1086 foreach ($form->_fields as $name => $dontCare) {
1087 $fields[$name] = 1;
1088 }
1089 }
1090
1091 // If there's no 'first_name' in the profile then overwrite the names from
1092 // the billing fields (if they are set)
1093 if (is_array($fields)) {
1094 if (!array_key_exists('first_name', $fields)) {
1095 $nameFields = array('first_name', 'middle_name', 'last_name');
1096 foreach ($nameFields as $name) {
1097 $fields[$name] = 1;
1098 if (array_key_exists("billing_$name", $params)) {
1099 $params[$name] = $params["billing_{$name}"];
1100 $params['preserveDBName'] = TRUE;
1101 }
1102 }
1103 }
1104 }
1105
1106 // Add the billing names to the billing address, if a billing name is set
1107 if (!empty($params['billing_first_name'])) {
1108 $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);
1109 $fields["address_name-{$form->_bltID}"] = 1;
1110 }
1111
1112 $fields["email-{$form->_bltID}"] = 1;
1113 $fields['email-Primary'] = 1;
1114
1115 //if its pay later or additional participant set email address as primary.
1116 if ((!empty($params['is_pay_later']) || empty($params['is_primary']) ||
1117 !$form->_values['event']['is_monetary'] ||
1118 $form->_allowWaitlist ||
1119 $form->_requireApproval
1120 ) && !empty($params["email-{$form->_bltID}"])
1121 ) {
1122 $params['email-Primary'] = $params["email-{$form->_bltID}"];
1123 }
1124 }
1125
1126 /**
1127 * Update contact fields.
1128 *
1129 * @param int $contactID
1130 * @param array $params
1131 * @param array $fields
1132 * @param CRM_Core_Form $form
1133 *
1134 * @return int
1135 */
1136 public static function updateContactFields($contactID, $params, $fields, &$form) {
1137 //add the contact to group, if add to group is selected for a
1138 //particular uf group
1139
1140 // get the add to groups
1141 $addToGroups = array();
1142
1143 if (!empty($form->_fields)) {
1144 foreach ($form->_fields as $key => $value) {
1145 if (!empty($value['add_to_group_id'])) {
1146 $addToGroups[$value['add_to_group_id']] = $value['add_to_group_id'];
1147 }
1148 }
1149 }
1150
1151 // check for profile double opt-in and get groups to be subscribed
1152 $subscribeGroupIds = CRM_Core_BAO_UFGroup::getDoubleOptInGroupIds($params, $contactID);
1153
1154 foreach ($addToGroups as $k) {
1155 if (array_key_exists($k, $subscribeGroupIds)) {
1156 unset($addToGroups[$k]);
1157 }
1158 }
1159
1160 // since we are directly adding contact to group lets unset it from mailing
1161 if (!empty($addToGroups)) {
1162 foreach ($addToGroups as $groupId) {
1163 if (isset($subscribeGroupIds[$groupId])) {
1164 unset($subscribeGroupIds[$groupId]);
1165 }
1166 }
1167 }
1168 if ($contactID) {
1169 $ctype = CRM_Core_DAO::getFieldValue(
1170 'CRM_Contact_DAO_Contact',
1171 $contactID,
1172 'contact_type'
1173 );
1174
1175 if (array_key_exists('contact_id', $params) && empty($params['contact_id'])) {
1176 // we unset this here because the downstream function ignores the contactID we give it
1177 // if it is set & it is difficult to understand the implications of 'fixing' this downstream
1178 // but if we are passing a contact id into this function it's reasonable to assume we don't
1179 // want it ignored
1180 unset($params['contact_id']);
1181 }
1182
1183 $contactID = CRM_Contact_BAO_Contact::createProfileContact(
1184 $params,
1185 $fields,
1186 $contactID,
1187 $addToGroups,
1188 NULL,
1189 $ctype,
1190 TRUE
1191 );
1192 }
1193 else {
1194
1195 foreach (CRM_Contact_BAO_Contact::$_greetingTypes as $greeting) {
1196 if (!isset($params[$greeting . '_id'])) {
1197 $params[$greeting . '_id'] = CRM_Contact_BAO_Contact_Utils::defaultGreeting('Individual', $greeting);
1198 }
1199 }
1200
1201 $contactID = CRM_Contact_BAO_Contact::createProfileContact($params,
1202 $fields,
1203 NULL,
1204 $addToGroups,
1205 NULL,
1206 NULL,
1207 TRUE
1208 );
1209 $form->set('contactID', $contactID);
1210 }
1211
1212 //get email primary first if exist
1213 $subscribtionEmail = array('email' => CRM_Utils_Array::value('email-Primary', $params));
1214 if (!$subscribtionEmail['email']) {
1215 $subscribtionEmail['email'] = CRM_Utils_Array::value("email-{$form->_bltID}", $params);
1216 }
1217 // subscribing contact to groups
1218 if (!empty($subscribeGroupIds) && $subscribtionEmail['email']) {
1219 CRM_Mailing_Event_BAO_Subscribe::commonSubscribe($subscribeGroupIds, $subscribtionEmail, $contactID);
1220 }
1221
1222 return $contactID;
1223 }
1224
1225 /**
1226 * Assign Profiles.
1227 *
1228 * @param CRM_Core_Form $form
1229 */
1230 public static function assignProfiles(&$form) {
1231 $participantParams = $form->_params;
1232 $formattedValues = $profileFields = array();
1233 $count = 1;
1234 foreach ($participantParams as $participantNum => $participantValue) {
1235 if ($participantNum) {
1236 $prefix1 = 'additional';
1237 $prefix2 = 'additional_';
1238 }
1239 else {
1240 $prefix1 = '';
1241 $prefix2 = '';
1242 }
1243 if ($participantValue != 'skip') {
1244 //get the customPre profile info
1245 if (!empty($form->_values[$prefix2 . 'custom_pre_id'])) {
1246 $values = $groupName = array();
1247 CRM_Event_BAO_Event::displayProfile($participantValue,
1248 $form->_values[$prefix2 . 'custom_pre_id'],
1249 $groupName,
1250 $values,
1251 $profileFields
1252 );
1253
1254 if (count($values)) {
1255 $formattedValues[$count][$prefix1 . 'CustomPre'] = $values;
1256 }
1257 $formattedValues[$count][$prefix1 . 'CustomPreGroupTitle'] = CRM_Utils_Array::value('groupTitle', $groupName);
1258 }
1259 //get the customPost profile info
1260 if (!empty($form->_values[$prefix2 . 'custom_post_id'])) {
1261 $values = $groupName = array();
1262 foreach ($form->_values[$prefix2 . 'custom_post_id'] as $gids) {
1263 $val = array();
1264 CRM_Event_BAO_Event::displayProfile($participantValue,
1265 $gids,
1266 $group,
1267 $val,
1268 $profileFields
1269 );
1270 $values[$gids] = $val;
1271 $groupName[$gids] = $group;
1272 }
1273
1274 if (count($values)) {
1275 $formattedValues[$count][$prefix1 . 'CustomPost'] = $values;
1276 }
1277
1278 if (isset($formattedValues[$count][$prefix1 . 'CustomPre'])) {
1279 $formattedValues[$count][$prefix1 . 'CustomPost'] = array_diff_assoc($formattedValues[$count][$prefix1 . 'CustomPost'],
1280 $formattedValues[$count][$prefix1 . 'CustomPre']
1281 );
1282 }
1283
1284 $formattedValues[$count][$prefix1 . 'CustomPostGroupTitle'] = $groupName;
1285 }
1286 $count++;
1287 }
1288 $form->_fields = $profileFields;
1289 }
1290 if (!empty($formattedValues)) {
1291 $form->assign('primaryParticipantProfile', $formattedValues[1]);
1292 $form->set('primaryParticipantProfile', $formattedValues[1]);
1293 if ($count > 2) {
1294 unset($formattedValues[1]);
1295 $form->assign('addParticipantProfile', $formattedValues);
1296 $form->set('addParticipantProfile', $formattedValues);
1297 }
1298 }
1299 }
1300
1301 /**
1302 * Submit in test mode.
1303 *
1304 * @param $params
1305 */
1306 public static function testSubmit($params) {
1307 $form = new CRM_Event_Form_Registration_Confirm();
1308 // This way the mocked up controller ignores the session stuff.
1309 $_SERVER['REQUEST_METHOD'] = 'GET';
1310 $_REQUEST['id'] = $form->_eventId = $params['id'];
1311 $form->controller = new CRM_Event_Controller_Registration();
1312 $form->_params = $params['params'];
1313 // This happens in buildQuickForm so emulate here.
1314 $form->_amount = $form->_totalAmount = CRM_Utils_Rule::cleanMoney(CRM_Utils_Array::value('totalAmount', $params));
1315 $form->set('params', $params['params']);
1316 $form->_values['custom_pre_id'] = array();
1317 $form->_values['custom_post_id'] = array();
1318 $form->_values['event'] = CRM_Utils_Array::value('event', $params);
1319 $form->_contributeMode = $params['contributeMode'];
1320 $eventParams = array('id' => $params['id']);
1321 CRM_Event_BAO_Event::retrieve($eventParams, $form->_values['event']);
1322 $form->set('registerByID', $params['registerByID']);
1323 if (!empty($params['paymentProcessorObj'])) {
1324 $form->_paymentProcessor = $params['paymentProcessorObj'];
1325 }
1326 $form->postProcess();
1327 }
1328
1329 /**
1330 * Process the payment, redirecting back to the page on error.
1331 *
1332 * @param $payment
1333 * @param $value
1334 *
1335 * @return array
1336 */
1337 private function processPayment($payment, $value) {
1338 try {
1339 $result = $payment->doPayment($value, 'event');
1340 return array($result, $value);
1341 }
1342 catch (\Civi\Payment\Exception\PaymentProcessorException $e) {
1343 Civi::log()->error('Payment processor exception: ' . $e->getMessage());
1344 CRM_Core_Session::singleton()->setStatus($e->getMessage());
1345 CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/event/register', "id={$this->_eventId}"));
1346 }
1347 return array();
1348 }
1349
1350 /**
1351 * Clean money fields from the form.
1352 *
1353 * @param array $params
1354 */
1355 protected function cleanMoneyFields(&$params) {
1356 foreach ($this->submittableMoneyFields as $moneyField) {
1357 foreach ($params as $index => $paramField) {
1358 if (isset($paramField[$moneyField])) {
1359 $params[$index][$moneyField] = CRM_Utils_Rule::cleanMoney($paramField[$moneyField]);
1360 }
1361 }
1362 }
1363 }
1364
1365}