Merge pull request #12208 from JMAConsulting/access-3-datepicker
[civicrm-core.git] / CRM / Event / Form / Registration / Confirm.php
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 */
36 class 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 ) {
213 $this->_amount = array();
214
215 $taxAmount = 0;
216 foreach ($this->_params as $k => $v) {
217 $this->cleanMoneyFields($v);
218 if ($v == 'skip') {
219 continue;
220 }
221 $individualTaxAmount = 0;
222 //display tax amount on confirmation page
223 $taxAmount += $v['tax_amount'];
224 if (is_array($v)) {
225 foreach (array(
226 'first_name',
227 'last_name',
228 ) as $name) {
229 if (isset($v['billing_' . $name]) &&
230 !isset($v[$name])
231 ) {
232 $v[$name] = $v['billing_' . $name];
233 }
234 }
235
236 if (!empty($v['first_name']) && !empty($v['last_name'])) {
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'];
249 if (!empty($v['discountAmount'])) {
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);
255 if (empty($v['first_name'])) {
256 $this->_part[$k]['info'] = $append;
257 }
258
259 /*CRM-16320 */
260 $individual[$k]['totalAmtWithTax'] = $this->_amount[$k]['amount'];
261 $individual[$k]['totalTaxAmt'] = $individualTaxAmount + $v['tax_amount'];
262 $this->_totalAmount = $this->_totalAmount + $this->_amount[$k]['amount'];
263 if (!empty($v['is_primary'])) {
264 $this->set('primaryParticipantAmount', $this->_amount[$k]['amount']);
265 }
266 }
267 }
268
269 $invoiceSettings = Civi::settings()->get('contribution_invoice_settings');
270 $taxTerm = CRM_Utils_Array::value('tax_term', $invoiceSettings);
271 $invoicing = CRM_Utils_Array::value('invoicing', $invoiceSettings);
272 if ($invoicing) {
273 $this->assign('totalTaxAmount', $taxAmount);
274 $this->assign('taxTerm', $taxTerm);
275 $this->assign('individual', $individual);
276 $this->set('individual', $individual);
277 }
278
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
286 if ($this->_priceSetId && !CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceSet', $this->_priceSetId, 'is_quick_config')) {
287 $lineItemForTemplate = array();
288 $getTaxDetails = FALSE;
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 }
299 }
300 }
301 }
302 }
303 if (!empty($lineItemForTemplate)) {
304 $this->assign('lineItem', $lineItemForTemplate);
305 }
306 $this->assign('getTaxDetails', $getTaxDetails);
307 }
308
309 //display additional participants profile.
310 self::assignProfiles($this);
311
312 //consider total amount.
313 $this->assign('isAmountzero', ($this->_totalAmount <= 0) ? TRUE : FALSE);
314
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 );
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
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
366 $this->assign('pricesetFieldsCount', CRM_Price_BAO_PriceSet::getPricesetCount($this->_priceSetId));
367 $this->addFormRule(array('CRM_Event_Form_Registration_Confirm', 'formRule'), $this);
368 }
369
370 /**
371 * Apply form rule.
372 *
373 * @param array $fields
374 * @param array $files
375 * @param CRM_Core_Form $self
376 *
377 * @return array|bool
378 */
379 public static function formRule($fields, $files, $self) {
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)) {
384 CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/event/register', "reset=1&id={$self->_eventId}", FALSE, NULL, FALSE, TRUE));
385 }
386 }
387 $self->_feeBlock = $self->_values['fee'];
388 CRM_Event_Form_Registration_Register::formatFieldsForOptionFull($self);
389
390 if (!empty($self->_priceSetId) &&
391 !$self->_requireApproval && !$self->_allowWaitlist
392 ) {
393 $priceSetErrors = self::validatePriceSet($self, $self->_params);
394 if (!empty($priceSetErrors)) {
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');
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 }
399 }
400
401 return empty($priceSetErrors) ? TRUE : $priceSetErrors;
402 }
403
404 /**
405 * Process the form submission.
406 */
407 public function postProcess() {
408 $now = date('YmdHis');
409
410 $this->_params = $this->get('params');
411 $this->cleanMoneyFields($this->_params);
412
413 if (!empty($this->_params[0]['contact_id'])) {
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
417 $contactID = $this->_params[0]['contact_id'];
418 }
419 else {
420 $contactID = $this->getContactID();
421 }
422
423 // if a discount has been applied, lets now deduct it from the amount
424 // and fix the fee level
425 if (!empty($this->_params[0]['discount']) && !empty($this->_params[0]['discount']['applied'])) {
426 foreach ($this->_params as $k => $v) {
427 if (CRM_Utils_Array::value('amount', $this->_params[$k]) > 0 && !empty($this->_params[$k]['discountAmount'])) {
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;
441 if ($this->_values['event']['is_monetary']) {
442 $this->set('finalAmount', $this->_amount);
443 }
444 $participantCount = array();
445 $taxAmount = $totalTaxAmount = 0;
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 }
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 }
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 }
470 $taxAmount = $totalTaxAmount;
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) {
477 CRM_Event_Form_Registration_Confirm::fixLocationFields($value, $fields, $this);
478 //unset the billing parameters if it is pay later mode
479 //to avoid creation of billing location
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.
483 if ($this->_allowWaitlist
484 || $this->_requireApproval
485 || (!empty($value['is_pay_later']) && !$this->_isBillingAddressRequiredForPayLater)
486 || empty($value['is_primary'])
487 ) {
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 }
505 if (!empty($value['is_pay_later'])) {
506 $this->_values['params']['is_pay_later'] = TRUE;
507 }
508 }
509
510 //Unset ContactID for additional participants and set RegisterBy Id.
511 if (empty($value['is_primary'])) {
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
522 $contactID = CRM_Event_Form_Registration_Confirm::updateContactFields($contactID, $value, $fields, $this);
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
528 if (!$this->getContactID() && !empty($value['is_primary'])) {
529 $session = CRM_Core_Session::singleton();
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
538 $pending = FALSE;
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
554 // required only if paid event
555 if ($this->_values['event']['is_monetary'] && !($this->_allowWaitlist || $this->_requireApproval)) {
556 if (is_array($this->_paymentProcessor)) {
557 $payment = $this->_paymentProcessor['object'];
558 }
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 }
563 $result = NULL;
564
565 if (!empty($value['is_pay_later']) ||
566 $value['amount'] == 0 ||
567 // The concept of contributeMode is deprecated.
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'");
575 $status = !empty($value['is_pay_later']) ? 'Pending from pay later' : 'Pending from incomplete transaction';
576 $value['participant_status_id'] = $value['participant_status'] = array_search($status, $pendingStatuses);
577 }
578 }
579 elseif (!empty($value['is_primary'])) {
580 CRM_Core_Payment_Form::mapParams($this->_bltID, $value, $value, TRUE);
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
587 if (is_object($payment)) {
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);
592 }
593 else {
594 CRM_Core_Error::fatal($paymentObjError);
595 }
596 }
597
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
611 if ($createContrib && !empty($value['is_primary']) &&
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.
623 $contribution = self::processContribution($this, $value, $result, $contactID, $pending, $isAdditionalAmount, $this->_paymentProcessor);
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;
632 $value['eventID'] = $this->_eventId;
633 $value['item_name'] = $value['description'];
634 }
635
636 if (!empty($value['contributionID'])) {
637 $this->_values['contributionId'] = $value['contributionID'];
638 }
639
640 //CRM-4453.
641 if (!empty($value['is_primary'])) {
642 $primaryCurrencyID = CRM_Utils_Array::value('currencyID', $value);
643 }
644 if (empty($value['currencyID'])) {
645 $value['currencyID'] = $primaryCurrencyID;
646 }
647
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
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)));
657 $this->set('trxnId', CRM_Utils_Array::value('trxn_id', $value));
658 }
659 }
660
661 $value['fee_amount'] = CRM_Utils_Array::value('amount', $value);
662 $this->set('value', $value);
663
664 // handle register date CRM-4320
665 if ($this->_allowConfirmation) {
666 $registerDate = CRM_Utils_Array::value('participant_register_date', $params);
667 }
668 elseif (!empty($params['participant_register_date']) &&
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';
704 $invoiceSettings = Civi::settings()->get('contribution_invoice_settings');
705 $invoicing = CRM_Utils_Array::value('invoicing', $invoiceSettings);
706 $totalTaxAmount = 0;
707 $dataArray = array();
708 foreach ($this->_lineItem as $key => $value) {
709 if ($value == 'skip') {
710 continue;
711 }
712 if ($entityId = CRM_Utils_Array::value($key, $allParticipantIds)) {
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 }
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 }
730 }
731 }
732 }
733 }
734 if ($invoicing) {
735 $this->assign('dataArray', $dataArray);
736 $this->assign('totalTaxAmount', $totalTaxAmount);
737 }
738 }
739
740 //update status and send mail to cancelled additional participants, CRM-4320
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.
754 // The concept of contributeMode is deprecated.
755 if (($this->_contributeMode == 'checkout' ||
756 $this->_contributeMode == 'notify'
757 ) && empty($params[0]['is_pay_later']) &&
758 !$this->_allowWaitlist && !$this->_requireApproval &&
759 $this->_totalAmount > 0
760 ) {
761
762 $primaryParticipant = $this->get('primaryParticipant');
763
764 if (empty($primaryParticipant['participantID'])) {
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)) {
778 //CRM 14512 provide line items of all participants to payment gateway
779 $primaryContactId = $this->get('primaryContactId');
780
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) {
792 // This is the is primary participant.
793 $participantNum = 0;
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)) {
814 $lineItems = $this->_lineItem;
815 $lineItem = array();
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
829 $groupTree = CRM_Core_BAO_CustomGroup::getTree('Event', NULL, $this->_eventId, 0, $this->_values['event']['event_type_id']);
830 $primaryParticipant['eventCustomFields'] = $groupTree;
831
832 // call postprocess hook before leaving
833 $this->postProcessHook();
834 // this does not return
835
836 $this->processPayment($payment, $primaryParticipant);
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 }
870 if ($participantNum === NULL) {
871 break;
872 }
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 }
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
903 $this->assign('isPrimary', 0);
904 $this->assign('customProfile', NULL);
905 //Additional Participant should get only it's payment information
906 if (!empty($this->_amount)) {
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) {
914 $lineItems = $this->_lineItem;
915 $lineItem = array();
916 if ($lineItemValue = CRM_Utils_Array::value($participantNum, $lineItems)) {
917 $lineItem[] = $lineItemValue;
918 }
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 }
927 $this->assign('lineItem', $lineItem);
928 }
929 $this->_values['params']['additionalParticipant'] = TRUE;
930 $this->assign('isAdditionalParticipant', $this->_values['params']['additionalParticipant']);
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 }
944
945 /**
946 * Process the contribution.
947 *
948 * @param CRM_Core_Form $form
949 * @param array $params
950 * @param array $result
951 * @param int $contactID
952 * @param bool $pending
953 * @param bool $isAdditionalAmount
954 *
955 * @return \CRM_Contribute_BAO_Contribution
956 */
957 public static function processContribution(
958 &$form, $params, $result, $contactID,
959 $pending = FALSE, $isAdditionalAmount = FALSE,
960 $paymentProcessor = NULL
961 ) {
962 $transaction = new CRM_Core_Transaction();
963
964 $now = date('YmdHis');
965 $receiptDate = NULL;
966
967 if (!empty($form->_values['event']['is_email_confirm'])) {
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
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
978 $contribParams = array(
979 'contact_id' => $contactID,
980 'financial_type_id' => !empty($form->_values['event']['financial_type_id']) ? $form->_values['event']['financial_type_id'] : $params['financial_type_id'],
981 'receive_date' => $now,
982 'total_amount' => $params['amount'],
983 'tax_amount' => $params['tax_amount'],
984 'amount_level' => $params['amount_level'],
985 'invoice_id' => $params['invoiceID'],
986 'currency' => $params['currencyID'],
987 'source' => !empty($params['participant_source']) ? $params['participant_source'] : $params['description'],
988 'is_pay_later' => CRM_Utils_Array::value('is_pay_later', $params, 0),
989 'campaign_id' => CRM_Utils_Array::value('campaign_id', $params),
990 'card_type_id' => CRM_Utils_Array::value('card_type_id', $params),
991 'pan_truncation' => CRM_Utils_Array::value('pan_truncation', $params),
992 );
993
994 if ($paymentProcessor) {
995 $contribParams['payment_instrument_id'] = $paymentProcessor['payment_instrument_id'];
996 $contribParams['payment_processor'] = $paymentProcessor['id'];
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;
1020 if (!empty($contribParams['invoice_id'])) {
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
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 );
1042 if (strtotime($eventStartDate) > strtotime(date('Ymt'))) {
1043 $contribParams['revenue_recognition_date'] = date('Ymd', strtotime($eventStartDate));
1044 }
1045 }
1046 //create an contribution address
1047 // The concept of contributeMode is deprecated. Elsewhere we use the function processBillingAddress() - although
1048 // currently that is only inherited by back-office forms.
1049 if ($form->_contributeMode != 'notify' && empty($params['is_pay_later'])) {
1050 $contribParams['address_id'] = CRM_Contribute_BAO_Contribution::createAddress($params, $form->_bltID);
1051 }
1052
1053 $contribParams['skipLineItem'] = 1;
1054 $contribParams['skipCleanMoney'] = 1;
1055 // create contribution record
1056 $contribution = CRM_Contribute_BAO_Contribution::add($contribParams);
1057 // CRM-11124
1058 CRM_Event_BAO_Participant::createDiscountTrxn($form->_eventId, $contribParams, NULL, CRM_Price_BAO_PriceSet::parseFirstPriceSetValueIDFromParams($params));
1059
1060 // process soft credit / pcp pages
1061 if (!empty($params['pcp_made_through_id'])) {
1062 CRM_Contribute_BAO_ContributionSoft::formatSoftCreditParams($params, $form);
1063 CRM_Contribute_BAO_ContributionSoft::processSoftContribution($params, $contribution);
1064 }
1065
1066 $transaction->commit();
1067
1068 return $contribution;
1069 }
1070
1071 /**
1072 * Fix the Location Fields.
1073 *
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 *
1079 * @param array $params
1080 * @param array $fields
1081 * @param CRM_Core_Form $form
1082 */
1083 public static function fixLocationFields(&$params, &$fields, &$form) {
1084 if (!empty($form->_fields)) {
1085 foreach ($form->_fields as $name => $dontCare) {
1086 $fields[$name] = 1;
1087 }
1088 }
1089
1090 // If there's no 'first_name' in the profile then overwrite the names from
1091 // the billing fields (if they are set)
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
1105 // Add the billing names to the billing address, if a billing name is set
1106 if (!empty($params['billing_first_name'])) {
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;
1109 }
1110
1111 $fields["email-{$form->_bltID}"] = 1;
1112 $fields['email-Primary'] = 1;
1113
1114 //if its pay later or additional participant set email address as primary.
1115 if ((!empty($params['is_pay_later']) || empty($params['is_primary']) ||
1116 !$form->_values['event']['is_monetary'] ||
1117 $form->_allowWaitlist ||
1118 $form->_requireApproval
1119 ) && !empty($params["email-{$form->_bltID}"])
1120 ) {
1121 $params['email-Primary'] = $params["email-{$form->_bltID}"];
1122 }
1123 }
1124
1125 /**
1126 * Update contact fields.
1127 *
1128 * @param int $contactID
1129 * @param array $params
1130 * @param array $fields
1131 * @param CRM_Core_Form $form
1132 *
1133 * @return int
1134 */
1135 public static function updateContactFields($contactID, $params, $fields, &$form) {
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
1142 if (!empty($form->_fields)) {
1143 foreach ($form->_fields as $key => $value) {
1144 if (!empty($value['add_to_group_id'])) {
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 );
1173
1174 if (array_key_exists('contact_id', $params) && empty($params['contact_id'])) {
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
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 );
1208 $form->set('contactID', $contactID);
1209 }
1210
1211 //get email primary first if exist
1212 $subscribtionEmail = array('email' => CRM_Utils_Array::value('email-Primary', $params));
1213 if (!$subscribtionEmail['email']) {
1214 $subscribtionEmail['email'] = CRM_Utils_Array::value("email-{$form->_bltID}", $params);
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 }
1223
1224 /**
1225 * Assign Profiles.
1226 *
1227 * @param CRM_Core_Form $form
1228 */
1229 public static function assignProfiles(&$form) {
1230 $participantParams = $form->_params;
1231 $formattedValues = $profileFields = array();
1232 $count = 1;
1233 foreach ($participantParams as $participantNum => $participantValue) {
1234 if ($participantNum) {
1235 $prefix1 = 'additional';
1236 $prefix2 = 'additional_';
1237 }
1238 else {
1239 $prefix1 = '';
1240 $prefix2 = '';
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,
1247 $form->_values[$prefix2 . 'custom_pre_id'],
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 }
1289 if (!empty($formattedValues)) {
1290 $form->assign('primaryParticipantProfile', $formattedValues[1]);
1291 $form->set('primaryParticipantProfile', $formattedValues[1]);
1292 if ($count > 2) {
1293 unset($formattedValues[1]);
1294 $form->assign('addParticipantProfile', $formattedValues);
1295 $form->set('addParticipantProfile', $formattedValues);
1296 }
1297 }
1298 }
1299
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'];
1312 // This happens in buildQuickForm so emulate here.
1313 $form->_amount = $form->_totalAmount = CRM_Utils_Rule::cleanMoney(CRM_Utils_Array::value('totalAmount', $params));
1314 $form->set('params', $params['params']);
1315 $form->_values['custom_pre_id'] = array();
1316 $form->_values['custom_post_id'] = array();
1317 $form->_values['event'] = CRM_Utils_Array::value('event', $params);
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']);
1322 if (!empty($params['paymentProcessorObj'])) {
1323 $form->_paymentProcessor = $params['paymentProcessorObj'];
1324 }
1325 $form->postProcess();
1326 }
1327
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) {
1342 Civi::log()->error('Payment processor exception: ' . $e->getMessage());
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
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
1364 }