Merge pull request #13188 from JMAConsulting/core-563
[civicrm-core.git] / CRM / Event / Form / Registration / Confirm.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
fee14197 4 | CiviCRM version 5 |
6a488035 5 +--------------------------------------------------------------------+
8c9251b3 6 | Copyright CiviCRM LLC (c) 2004-2018 |
6a488035
TO
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
9 | |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
13 | |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
18 | |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
d25dd0ee 26 */
6a488035
TO
27
28/**
6a488035 29 * @package CRM
8c9251b3 30 * @copyright CiviCRM LLC (c) 2004-2018
6a488035
TO
31 */
32
33/**
3bdf1f3a 34 * This class generates form components for processing Event.
6a488035
TO
35 */
36class CRM_Event_Form_Registration_Confirm extends CRM_Event_Form_Registration {
37
38 /**
66f9e52b 39 * The values for the contribution db object.
6a488035
TO
40 *
41 * @var array
6a488035
TO
42 */
43 public $_values;
44
45 /**
66f9e52b 46 * The total amount.
6a488035
TO
47 *
48 * @var float
6a488035
TO
49 */
50 public $_totalAmount;
51
3ae1b2f4 52 /**
53 * Monetary fields that may be submitted.
54 *
55 * These should get a standardised format in the beginPostProcess function.
56 *
57 * These fields are common to many forms. Some may override this.
58 */
59 protected $submittableMoneyFields = ['total_amount', 'net_amount', 'non_deductible_amount', 'fee_amount', 'tax_amount', 'amount'];
60
6a488035 61 /**
66f9e52b 62 * Set variables up before form is built.
6a488035 63 */
00be9182 64 public function preProcess() {
6a488035
TO
65 parent::preProcess();
66
67 // lineItem isn't set until Register postProcess
68 $this->_lineItem = $this->get('lineItem');
69
70 $this->_params = $this->get('params');
d91b8b33 71 $this->_params[0]['tax_amount'] = $this->get('tax_amount');
6a488035
TO
72
73 $this->_params[0]['is_pay_later'] = $this->get('is_pay_later');
74 $this->assign('is_pay_later', $this->_params[0]['is_pay_later']);
75 if ($this->_params[0]['is_pay_later']) {
76 $this->assign('pay_later_receipt', $this->_values['event']['pay_later_receipt']);
77 }
78
79 CRM_Utils_Hook::eventDiscount($this, $this->_params);
80
8cc574cf 81 if (!empty($this->_params[0]['discount']) && !empty($this->_params[0]['discount']['applied'])) {
6a488035
TO
82 $this->set('hookDiscount', $this->_params[0]['discount']);
83 $this->assign('hookDiscount', $this->_params[0]['discount']);
84 }
85
0f2b049e 86 // The concept of contributeMode is deprecated.
6a488035
TO
87 if ($this->_contributeMode == 'express') {
88 $params = array();
89 // rfp == redirect from paypal
9a1b1b8e 90 // rfp is probably not required - the getPreApprovalDetails should deal with any payment-processor specific 'stuff'
6a488035
TO
91 $rfp = CRM_Utils_Request::retrieve('rfp', 'Boolean',
92 CRM_Core_DAO::$_nullObject, FALSE, NULL, 'GET'
93 );
94
95 //we lost rfp in case of additional participant. So set it explicitly.
96 if ($rfp || CRM_Utils_Array::value('additional_participants', $this->_params[0], FALSE)) {
9a1b1b8e 97 if (!empty($this->_paymentProcessor) && $this->_paymentProcessor['object']->supports('preApproval')) {
98 $preApprovalParams = $this->_paymentProcessor['object']->getPreApprovalDetails($this->get('pre_approval_parameters'));
99 $params = array_merge($this->_params, $preApprovalParams);
0479b4c8 100 }
9a1b1b8e 101 CRM_Core_Payment_Form::mapParams($this->_bltID, $params, $params, FALSE);
6a488035 102
9a1b1b8e 103 // set a few other parameters that are not really specific to this method because we don't know what
104 // will break if we change this.
6a488035 105 $params['amount'] = $this->_params[0]['amount'];
a7488080 106 if (!empty($this->_params[0]['discount'])) {
6a488035
TO
107 $params['discount'] = $this->_params[0]['discount'];
108 $params['discountAmount'] = $this->_params[0]['discountAmount'];
109 $params['discountMessage'] = $this->_params[0]['discountMessage'];
110 }
362bd1b7 111
6a488035
TO
112 $params['amount_level'] = $this->_params[0]['amount_level'];
113 $params['currencyID'] = $this->_params[0]['currencyID'];
6a488035
TO
114
115 // also merge all the other values from the profile fields
116 $values = $this->controller->exportValues('Register');
117 $skipFields = array(
118 'amount',
119 "street_address-{$this->_bltID}",
120 "city-{$this->_bltID}",
121 "state_province_id-{$this->_bltID}",
122 "postal_code-{$this->_bltID}",
123 "country_id-{$this->_bltID}",
124 );
125
126 foreach ($values as $name => $value) {
127 // skip amount field
128 if (!in_array($name, $skipFields)) {
129 $params[$name] = $value;
130 }
bb2240a2 131 if (substr($name, 0, 6) == 'price_') {
b5b712c1 132 $params[$name] = $this->_params[0][$name];
bb2240a2 133 }
6a488035
TO
134 }
135 $this->set('getExpressCheckoutDetails', $params);
136 }
9a1b1b8e 137 $this->_params[0] = array_merge($this->_params[0], $params);
6a488035
TO
138 $this->_params[0]['is_primary'] = 1;
139 }
140 else {
141 //process only primary participant params.
142 $registerParams = $this->_params[0];
143 if (isset($registerParams["billing_state_province_id-{$this->_bltID}"])
144 && $registerParams["billing_state_province_id-{$this->_bltID}"]
145 ) {
146 $registerParams["billing_state_province-{$this->_bltID}"] = CRM_Core_PseudoConstant::stateProvinceAbbreviation($registerParams["billing_state_province_id-{$this->_bltID}"]);
147 }
148
149 if (isset($registerParams["billing_country_id-{$this->_bltID}"]) && $registerParams["billing_country_id-{$this->_bltID}"]) {
150 $registerParams["billing_country-{$this->_bltID}"] = CRM_Core_PseudoConstant::countryIsoCode($registerParams["billing_country_id-{$this->_bltID}"]);
151 }
152 if (isset($registerParams['credit_card_exp_date'])) {
353ffa53 153 $registerParams['year'] = CRM_Core_Payment_Form::getCreditCardExpirationYear($registerParams);
6a488035
TO
154 $registerParams['month'] = CRM_Core_Payment_Form::getCreditCardExpirationMonth($registerParams);
155 }
156 if ($this->_values['event']['is_monetary']) {
157 $registerParams['ip_address'] = CRM_Utils_System::ipAddress();
158 $registerParams['currencyID'] = $this->_params[0]['currencyID'];
6a488035
TO
159 }
160 //assign back primary participant params.
161 $this->_params[0] = $registerParams;
162 }
163
164 if ($this->_values['event']['is_monetary']) {
165 $this->_params[0]['invoiceID'] = $this->get('invoiceID');
166 }
167 $this->assign('defaultRole', FALSE);
168 if (CRM_Utils_Array::value('defaultRole', $this->_params[0]) == 1) {
169 $this->assign('defaultRole', TRUE);
170 }
171
a7488080 172 if (empty($this->_params[0]['participant_role_id']) &&
6a488035
TO
173 $this->_values['event']['default_role_id']
174 ) {
175 $this->_params[0]['participant_role_id'] = $this->_values['event']['default_role_id'];
176 }
177
178 if (isset($this->_values['event']['confirm_title'])) {
179 CRM_Utils_System::setTitle($this->_values['event']['confirm_title']);
180 }
181
182 if ($this->_pcpId) {
183 $params = CRM_Contribute_Form_Contribution_Confirm::processPcp($this, $this->_params[0]);
184 $this->_params[0] = $params;
185 }
186
187 $this->set('params', $this->_params);
188 }
189
190 /**
3bdf1f3a 191 * Overwrite action, since we are only showing elements in frozen mode no help display needed.
6a488035
TO
192 *
193 * @return int
6a488035 194 */
00be9182 195 public function getAction() {
6a488035
TO
196 if ($this->_action & CRM_Core_Action::PREVIEW) {
197 return CRM_Core_Action::VIEW | CRM_Core_Action::PREVIEW;
198 }
199 else {
200 return CRM_Core_Action::VIEW;
201 }
202 }
203
204 /**
66f9e52b 205 * Build the form object.
6a488035
TO
206 */
207 public function buildQuickForm() {
208 $this->assignToTemplate();
1909126f 209
210 if ($this->_values['event']['is_monetary'] &&
ef27a9b6
AS
211 ($this->_params[0]['amount'] || $this->_params[0]['amount'] == 0) &&
212 !$this->_requireApproval
1909126f 213 ) {
6a488035
TO
214 $this->_amount = array();
215
79d001a2 216 $taxAmount = 0;
6a488035 217 foreach ($this->_params as $k => $v) {
3ae1b2f4 218 $this->cleanMoneyFields($v);
7bde3600 219 if ($v == 'skip') {
220 continue;
221 }
75b065ce 222 $individualTaxAmount = 0;
79d001a2
PB
223 //display tax amount on confirmation page
224 $taxAmount += $v['tax_amount'];
6a488035
TO
225 if (is_array($v)) {
226 foreach (array(
353ffa53 227 'first_name',
317fceb4 228 'last_name',
353ffa53 229 ) as $name) {
6a488035
TO
230 if (isset($v['billing_' . $name]) &&
231 !isset($v[$name])
232 ) {
233 $v[$name] = $v['billing_' . $name];
234 }
235 }
236
8cc574cf 237 if (!empty($v['first_name']) && !empty($v['last_name'])) {
6a488035
TO
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'];
a7488080 250 if (!empty($v['discountAmount'])) {
6a488035
TO
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);
a7488080 256 if (empty($v['first_name'])) {
6a488035
TO
257 $this->_part[$k]['info'] = $append;
258 }
75b065ce 259
260 /*CRM-16320 */
261 $individual[$k]['totalAmtWithTax'] = $this->_amount[$k]['amount'];
262 $individual[$k]['totalTaxAmt'] = $individualTaxAmount + $v['tax_amount'];
6a488035 263 $this->_totalAmount = $this->_totalAmount + $this->_amount[$k]['amount'];
a7488080 264 if (!empty($v['is_primary'])) {
6a488035
TO
265 $this->set('primaryParticipantAmount', $this->_amount[$k]['amount']);
266 }
267 }
268 }
269
aaffa79f 270 $invoiceSettings = Civi::settings()->get('contribution_invoice_settings');
03b412ae
PB
271 $taxTerm = CRM_Utils_Array::value('tax_term', $invoiceSettings);
272 $invoicing = CRM_Utils_Array::value('invoicing', $invoiceSettings);
03b412ae
PB
273 if ($invoicing) {
274 $this->assign('totalTaxAmount', $taxAmount);
d9e4ebe7 275 $this->assign('taxTerm', $taxTerm);
75b065ce 276 $this->assign('individual', $individual);
277 $this->set('individual', $individual);
03b412ae 278 }
75b065ce 279
6a488035
TO
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
9da8dc8c 287 if ($this->_priceSetId && !CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceSet', $this->_priceSetId, 'is_quick_config')) {
6a488035 288 $lineItemForTemplate = array();
03b412ae 289 $getTaxDetails = FALSE;
26fe6f4c 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 }
03b412ae
PB
300 }
301 }
302 }
6a488035
TO
303 }
304 if (!empty($lineItemForTemplate)) {
305 $this->assign('lineItem', $lineItemForTemplate);
306 }
d9e4ebe7 307 $this->assign('getTaxDetails', $getTaxDetails);
6a488035
TO
308 }
309
310 //display additional participants profile.
5bdcb00b 311 self::assignProfiles($this);
6a488035
TO
312
313 //consider total amount.
314 $this->assign('isAmountzero', ($this->_totalAmount <= 0) ? TRUE : FALSE);
315
229159bf
CW
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 );
6a488035
TO
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
6a488035
TO
359 $this->setDefaults($defaults);
360 $this->freeze();
361
362 //lets give meaningful status message, CRM-4320.
363 $this->assign('isOnWaitlist', $this->_allowWaitlist);
364 $this->assign('isRequireApproval', $this->_requireApproval);
365
366 // Assign Participant Count to Lineitem Table
9da8dc8c 367 $this->assign('pricesetFieldsCount', CRM_Price_BAO_PriceSet::getPricesetCount($this->_priceSetId));
79b152ac 368 $this->addFormRule(array('CRM_Event_Form_Registration_Confirm', 'formRule'), $this);
6a488035
TO
369 }
370
ca87146b 371 /**
3bdf1f3a 372 * Apply form rule.
373 *
374 * @param array $fields
375 * @param array $files
376 * @param CRM_Core_Form $self
ca87146b
EM
377 *
378 * @return array|bool
379 */
00be9182 380 public static function formRule($fields, $files, $self) {
79b152ac 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)) {
0479b4c8 385 CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/event/register', "reset=1&id={$self->_eventId}", FALSE, NULL, FALSE, TRUE));
79b152ac 386 }
387 }
388 $self->_feeBlock = $self->_values['fee'];
389 CRM_Event_Form_Registration_Register::formatFieldsForOptionFull($self);
390
0dc0b759 391 if (!empty($self->_priceSetId) &&
392 !$self->_requireApproval && !$self->_allowWaitlist
393 ) {
79b152ac 394 $priceSetErrors = self::validatePriceSet($self, $self->_params);
0dc0b759 395 if (!empty($priceSetErrors)) {
2ae4d103 396 CRM_Core_Session::setStatus(ts('You have been returned to the start of the registration process and any sold out events have been removed from your selections. You will not be able to continue until you review your booking and select different events if you wish.'), ts('Unfortunately some of your options have now sold out for one or more participants.'), 'error');
0dc0b759 397 CRM_Core_Session::setStatus(ts('Please note that the options which are marked or selected are sold out for participant being viewed.'), ts('Sold out:'), 'error');
398 CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/event/register', "_qf_Register_display=true&qfKey={$fields['qfKey']}"));
399 }
79b152ac 400 }
401
0dc0b759 402 return empty($priceSetErrors) ? TRUE : $priceSetErrors;
79b152ac 403 }
353ffa53 404
6a488035 405 /**
66f9e52b 406 * Process the form submission.
6a488035
TO
407 */
408 public function postProcess() {
353ffa53 409 $now = date('YmdHis');
af72b8c7 410
6a488035 411 $this->_params = $this->get('params');
3ae1b2f4 412 $this->cleanMoneyFields($this->_params);
413
a7488080 414 if (!empty($this->_params[0]['contact_id'])) {
e1ce628e 415 // unclear when this would be set & whether it could be checked in getContactID.
416 // perhaps it relates to when cid is in the url
417 //@todo someone who knows add comments on the various contactIDs in this form
6a488035
TO
418 $contactID = $this->_params[0]['contact_id'];
419 }
420 else {
5c280496 421 $contactID = $this->getContactID();
6a488035
TO
422 }
423
424 // if a discount has been applied, lets now deduct it from the amount
425 // and fix the fee level
8cc574cf 426 if (!empty($this->_params[0]['discount']) && !empty($this->_params[0]['discount']['applied'])) {
6a488035 427 foreach ($this->_params as $k => $v) {
8cc574cf 428 if (CRM_Utils_Array::value('amount', $this->_params[$k]) > 0 && !empty($this->_params[$k]['discountAmount'])) {
6a488035
TO
429 $this->_params[$k]['amount'] -= $this->_params[$k]['discountAmount'];
430 $this->_params[$k]['amount_level'] .= CRM_Utils_Array::value('discountMessage', $this->_params[$k]);
431 }
432 }
433 $this->set('params', $this->_params);
434 }
435
436 // CRM-4320, lets build array of cancelled additional participant ids
437 // those are drop or skip by primary at the time of confirmation.
438 // get all in and then unset those we want to process.
439 $cancelledIds = $this->_additionalParticipantIds;
440
441 $params = $this->_params;
1909126f 442 if ($this->_values['event']['is_monetary']) {
443 $this->set('finalAmount', $this->_amount);
444 }
6a488035 445 $participantCount = array();
b6c8057d 446 $taxAmount = $totalTaxAmount = 0;
6a488035
TO
447
448 //unset the skip participant from params.
449 //build the $participantCount array.
450 //maintain record for all participants.
451 foreach ($params as $participantNum => $record) {
452 if ($record == 'skip') {
453 unset($params[$participantNum]);
454 $participantCount[$participantNum] = 'skip';
455 }
456 elseif ($participantNum) {
457 $participantCount[$participantNum] = 'participant';
458 }
b6c8057d
PN
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 }
6a488035
TO
463 //lets get additional participant id to cancel.
464 if ($this->_allowConfirmation && is_array($cancelledIds)) {
465 $additonalId = CRM_Utils_Array::value('participant_id', $record);
466 if ($additonalId && $key = array_search($additonalId, $cancelledIds)) {
467 unset($cancelledIds[$key]);
468 }
469 }
470 }
b6c8057d 471 $taxAmount = $totalTaxAmount;
6a488035
TO
472 $payment = $registerByID = $primaryCurrencyID = $contribution = NULL;
473 $paymentObjError = ts('The system did not record payment details for this payment and so could not process the transaction. Please report this error to the site administrator.');
474
475 $this->participantIDS = array();
476 $fields = array();
477 foreach ($params as $key => $value) {
a9f7d48b 478 CRM_Event_Form_Registration_Confirm::fixLocationFields($value, $fields, $this);
6a488035
TO
479 //unset the billing parameters if it is pay later mode
480 //to avoid creation of billing location
0b05b9a9 481 // @todo - the reasoning for this is unclear - elsewhere we check what fields are provided by
482 // the form & if billing fields exist we create the address, relying on the form to collect
483 // only information we intend to store.
8ae4d0d3 484 if ($this->_allowWaitlist
485 || $this->_requireApproval
486 || (!empty($value['is_pay_later']) && !$this->_isBillingAddressRequiredForPayLater)
487 || empty($value['is_primary'])
488 ) {
6a488035
TO
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 }
a7488080 506 if (!empty($value['is_pay_later'])) {
6a488035
TO
507 $this->_values['params']['is_pay_later'] = TRUE;
508 }
509 }
510
511 //Unset ContactID for additional participants and set RegisterBy Id.
a7488080 512 if (empty($value['is_primary'])) {
6a488035
TO
513 $contactID = CRM_Utils_Array::value('contact_id', $value);
514 $registerByID = $this->get('registerByID');
515 if ($registerByID) {
516 $value['registered_by_id'] = $registerByID;
517 }
518 }
519 else {
520 $value['amount'] = $this->_totalAmount;
521 }
522
a9f7d48b 523 $contactID = CRM_Event_Form_Registration_Confirm::updateContactFields($contactID, $value, $fields, $this);
6a488035
TO
524
525 // lets store the contactID in the session
526 // we dont store in userID in case the user is doing multiple
527 // transactions etc
528 // for things like tell a friend
8cc574cf 529 if (!$this->getContactID() && !empty($value['is_primary'])) {
af72b8c7 530 $session = CRM_Core_Session::singleton();
6a488035
TO
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
752f450d 539 $pending = FALSE;
67c8322d
J
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
6a488035 555 // required only if paid event
67c8322d 556 if ($this->_values['event']['is_monetary'] && !($this->_allowWaitlist || $this->_requireApproval)) {
6a488035 557 if (is_array($this->_paymentProcessor)) {
077017db 558 $payment = $this->_paymentProcessor['object'];
6a488035 559 }
ec022878 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 }
6a488035
TO
564 $result = NULL;
565
67c8322d 566 if (!empty($value['is_pay_later']) ||
6a488035 567 $value['amount'] == 0 ||
0f2b049e 568 // The concept of contributeMode is deprecated.
6a488035
TO
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'");
0d8afee2 576 $status = !empty($value['is_pay_later']) ? 'Pending from pay later' : 'Pending from incomplete transaction';
6a488035
TO
577 $value['participant_status_id'] = $value['participant_status'] = array_search($status, $pendingStatuses);
578 }
579 }
a7488080 580 elseif (!empty($value['is_primary'])) {
6a488035 581 CRM_Core_Payment_Form::mapParams($this->_bltID, $value, $value, TRUE);
bd7b39e7
PJ
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
6a488035 588 if (is_object($payment)) {
55f9f634 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);
6a488035
TO
593 }
594 else {
595 CRM_Core_Error::fatal($paymentObjError);
596 }
597 }
598
6a488035
TO
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
8cc574cf 612 if ($createContrib && !empty($value['is_primary']) &&
6a488035
TO
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.
632196ea 624 $contribution = self::processContribution($this, $value, $result, $contactID, $pending, $isAdditionalAmount, $this->_paymentProcessor);
6a488035
TO
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;
353ffa53 633 $value['eventID'] = $this->_eventId;
6a488035
TO
634 $value['item_name'] = $value['description'];
635 }
9a32a8fc
GC
636
637 if (!empty($value['contributionID'])) {
638 $this->_values['contributionId'] = $value['contributionID'];
639 }
6a488035
TO
640
641 //CRM-4453.
a7488080 642 if (!empty($value['is_primary'])) {
6a488035
TO
643 $primaryCurrencyID = CRM_Utils_Array::value('currencyID', $value);
644 }
a7488080 645 if (empty($value['currencyID'])) {
6a488035
TO
646 $value['currencyID'] = $primaryCurrencyID;
647 }
648
1909126f 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
bcdf9664
PN
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)));
1909126f 658 $this->set('trxnId', CRM_Utils_Array::value('trxn_id', $value));
659 }
6a488035 660 }
f55dc004 661
ffcec972 662 $value['fee_amount'] = CRM_Utils_Array::value('amount', $value);
6a488035
TO
663 $this->set('value', $value);
664
665 // handle register date CRM-4320
666 if ($this->_allowConfirmation) {
481a74f4 667 $registerDate = CRM_Utils_Array::value('participant_register_date', $params);
6a488035 668 }
a7488080 669 elseif (!empty($params['participant_register_date']) &&
6a488035
TO
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';
aaffa79f 705 $invoiceSettings = Civi::settings()->get('contribution_invoice_settings');
03b412ae 706 $invoicing = CRM_Utils_Array::value('invoicing', $invoiceSettings);
79d001a2
PB
707 $totalTaxAmount = 0;
708 $dataArray = array();
6a488035 709 foreach ($this->_lineItem as $key => $value) {
e189cf22 710 if ($value == 'skip') {
711 continue;
712 }
713 if ($entityId = CRM_Utils_Array::value($key, $allParticipantIds)) {
6a488035
TO
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 }
03b412ae
PB
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 }
79d001a2
PB
731 }
732 }
733 }
6a488035 734 }
03b412ae
PB
735 if ($invoicing) {
736 $this->assign('dataArray', $dataArray);
737 $this->assign('totalTaxAmount', $totalTaxAmount);
738 }
6a488035
TO
739 }
740
b44e3f84 741 //update status and send mail to cancelled additional participants, CRM-4320
6a488035
TO
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.
0f2b049e 755 // The concept of contributeMode is deprecated.
6a488035
TO
756 if (($this->_contributeMode == 'checkout' ||
757 $this->_contributeMode == 'notify'
8cc574cf 758 ) && empty($params[0]['is_pay_later']) &&
6a488035
TO
759 !$this->_allowWaitlist && !$this->_requireApproval &&
760 $this->_totalAmount > 0
761 ) {
762
763 $primaryParticipant = $this->get('primaryParticipant');
764
a7488080 765 if (empty($primaryParticipant['participantID'])) {
6a488035
TO
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)) {
03665663 779 //CRM 14512 provide line items of all participants to payment gateway
780 $primaryContactId = $this->get('primaryContactId');
fb3b1f9a 781
03665663 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) {
3bdf1f3a 793 // This is the is primary participant.
794 $participantNum = 0;
03665663 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)) {
353ffa53
TO
815 $lineItems = $this->_lineItem;
816 $lineItem = array();
03665663 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
0b330e6d 830 $groupTree = CRM_Core_BAO_CustomGroup::getTree('Event', NULL, $this->_eventId, 0, $this->_values['event']['event_type_id']);
03665663 831 $primaryParticipant['eventCustomFields'] = $groupTree;
fb3b1f9a 832
6a488035
TO
833 // call postprocess hook before leaving
834 $this->postProcessHook();
835 // this does not return
55f9f634 836
837 $this->processPayment($payment, $primaryParticipant);
6a488035
TO
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 }
0479b4c8
TO
871 if ($participantNum === NULL) {
872 break;
873 }
6a488035
TO
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 }
4abc4ee1 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
6a488035
TO
904 $this->assign('isPrimary', 0);
905 $this->assign('customProfile', NULL);
906 //Additional Participant should get only it's payment information
1909126f 907 if (!empty($this->_amount)) {
6a488035
TO
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) {
353ffa53
TO
915 $lineItems = $this->_lineItem;
916 $lineItem = array();
6a488035
TO
917 if ($lineItemValue = CRM_Utils_Array::value($participantNum, $lineItems)) {
918 $lineItem[] = $lineItemValue;
919 }
75b065ce 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 }
6a488035
TO
928 $this->assign('lineItem', $lineItem);
929 }
930 $this->_values['params']['additionalParticipant'] = TRUE;
7d92d486 931 $this->assign('isAdditionalParticipant', $this->_values['params']['additionalParticipant']);
6a488035
TO
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 }
6a488035
TO
945
946 /**
66f9e52b 947 * Process the contribution.
6a488035 948 *
c490a46a
CW
949 * @param CRM_Core_Form $form
950 * @param array $params
3bdf1f3a 951 * @param array $result
100fef9d 952 * @param int $contactID
dd244018
EM
953 * @param bool $pending
954 * @param bool $isAdditionalAmount
955 *
3bdf1f3a 956 * @return \CRM_Contribute_BAO_Contribution
6a488035 957 */
317fceb4 958 public static function processContribution(
ddca8f33 959 &$form, $params, $result, $contactID,
632196ea 960 $pending = FALSE, $isAdditionalAmount = FALSE,
961 $paymentProcessor = NULL
6a488035
TO
962 ) {
963 $transaction = new CRM_Core_Transaction();
964
353ffa53 965 $now = date('YmdHis');
6a488035
TO
966 $receiptDate = NULL;
967
bf2c70af 968 if (!empty($form->_values['event']['is_email_confirm'])) {
6a488035
TO
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
a7f2d5fd 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
6a488035
TO
979 $contribParams = array(
980 'contact_id' => $contactID,
353ffa53 981 'financial_type_id' => !empty($form->_values['event']['financial_type_id']) ? $form->_values['event']['financial_type_id'] : $params['financial_type_id'],
6a488035
TO
982 'receive_date' => $now,
983 'total_amount' => $params['amount'],
d91b8b33 984 'tax_amount' => $params['tax_amount'],
6a488035
TO
985 'amount_level' => $params['amount_level'],
986 'invoice_id' => $params['invoiceID'],
987 'currency' => $params['currencyID'],
13bb29e4 988 'source' => !empty($params['participant_source']) ? $params['participant_source'] : $params['description'],
6a488035
TO
989 'is_pay_later' => CRM_Utils_Array::value('is_pay_later', $params, 0),
990 'campaign_id' => CRM_Utils_Array::value('campaign_id', $params),
5d3a2b9f 991 'card_type_id' => CRM_Utils_Array::value('card_type_id', $params),
992 'pan_truncation' => CRM_Utils_Array::value('pan_truncation', $params),
6a488035
TO
993 );
994
632196ea 995 if ($paymentProcessor) {
996 $contribParams['payment_instrument_id'] = $paymentProcessor['payment_instrument_id'];
dcc0e041 997 $contribParams['payment_processor'] = $paymentProcessor['id'];
6a488035
TO
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;
a7488080 1021 if (!empty($contribParams['invoice_id'])) {
6a488035
TO
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
8cf6bd83
PN
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 );
a493ffb6 1043 if (strtotime($eventStartDate) > strtotime(date('Ymt'))) {
8cf6bd83
PN
1044 $contribParams['revenue_recognition_date'] = date('Ymd', strtotime($eventStartDate));
1045 }
1046 }
6a488035 1047 //create an contribution address
0f2b049e 1048 // The concept of contributeMode is deprecated. Elsewhere we use the function processBillingAddress() - although
1049 // currently that is only inherited by back-office forms.
8cc574cf 1050 if ($form->_contributeMode != 'notify' && empty($params['is_pay_later'])) {
6a488035
TO
1051 $contribParams['address_id'] = CRM_Contribute_BAO_Contribution::createAddress($params, $form->_bltID);
1052 }
1053
6a488035 1054 $contribParams['skipLineItem'] = 1;
3ae1b2f4 1055 $contribParams['skipCleanMoney'] = 1;
6a488035 1056 // create contribution record
66ea9833 1057 $contribution = CRM_Contribute_BAO_Contribution::add($contribParams);
6a488035 1058 // CRM-11124
362bd1b7 1059 CRM_Event_BAO_Participant::createDiscountTrxn($form->_eventId, $contribParams, NULL, CRM_Price_BAO_PriceSet::parseFirstPriceSetValueIDFromParams($params));
6a488035
TO
1060
1061 // process soft credit / pcp pages
7a13735b 1062 if (!empty($params['pcp_made_through_id'])) {
03b0e225 1063 CRM_Contribute_BAO_ContributionSoft::formatSoftCreditParams($params, $form);
7a13735b 1064 CRM_Contribute_BAO_ContributionSoft::processSoftContribution($params, $contribution);
1065 }
6a488035
TO
1066
1067 $transaction->commit();
1068
1069 return $contribution;
1070 }
1071
1072 /**
66f9e52b 1073 * Fix the Location Fields.
6a488035 1074 *
b7a83c2c
J
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 *
c490a46a 1080 * @param array $params
3bdf1f3a 1081 * @param array $fields
c490a46a 1082 * @param CRM_Core_Form $form
6a488035 1083 */
4fb756af 1084 public static function fixLocationFields(&$params, &$fields, &$form) {
a9f7d48b
AS
1085 if (!empty($form->_fields)) {
1086 foreach ($form->_fields as $name => $dontCare) {
6a488035
TO
1087 $fields[$name] = 1;
1088 }
1089 }
1090
08318d90
J
1091 // If there's no 'first_name' in the profile then overwrite the names from
1092 // the billing fields (if they are set)
6a488035
TO
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
08318d90 1106 // Add the billing names to the billing address, if a billing name is set
5329bf02 1107 if (!empty($params['billing_first_name'])) {
a9f7d48b
AS
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;
6a488035 1110 }
08318d90 1111
a9f7d48b 1112 $fields["email-{$form->_bltID}"] = 1;
6a488035
TO
1113 $fields['email-Primary'] = 1;
1114
1115 //if its pay later or additional participant set email address as primary.
8cc574cf 1116 if ((!empty($params['is_pay_later']) || empty($params['is_primary']) ||
a9f7d48b
AS
1117 !$form->_values['event']['is_monetary'] ||
1118 $form->_allowWaitlist ||
1119 $form->_requireApproval
353ffa53
TO
1120 ) && !empty($params["email-{$form->_bltID}"])
1121 ) {
a9f7d48b 1122 $params['email-Primary'] = $params["email-{$form->_bltID}"];
6a488035
TO
1123 }
1124 }
1125
1126 /**
66f9e52b 1127 * Update contact fields.
6a488035 1128 *
100fef9d 1129 * @param int $contactID
c490a46a 1130 * @param array $params
3bdf1f3a 1131 * @param array $fields
c490a46a 1132 * @param CRM_Core_Form $form
dd244018 1133 *
3bdf1f3a 1134 * @return int
6a488035 1135 */
4fb756af 1136 public static function updateContactFields($contactID, $params, $fields, &$form) {
6a488035
TO
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
a9f7d48b
AS
1143 if (!empty($form->_fields)) {
1144 foreach ($form->_fields as $key => $value) {
a7488080 1145 if (!empty($value['add_to_group_id'])) {
6a488035
TO
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 );
e1ce628e 1174
22e263ad 1175 if (array_key_exists('contact_id', $params) && empty($params['contact_id'])) {
e1ce628e 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
6a488035
TO
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 );
a9f7d48b 1209 $form->set('contactID', $contactID);
6a488035
TO
1210 }
1211
1212 //get email primary first if exist
1213 $subscribtionEmail = array('email' => CRM_Utils_Array::value('email-Primary', $params));
1214 if (!$subscribtionEmail['email']) {
a9f7d48b 1215 $subscribtionEmail['email'] = CRM_Utils_Array::value("email-{$form->_bltID}", $params);
6a488035
TO
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 }
5bdcb00b 1224
0cf587a7 1225 /**
3bdf1f3a 1226 * Assign Profiles.
1227 *
1228 * @param CRM_Core_Form $form
0cf587a7 1229 */
5bdcb00b 1230 public static function assignProfiles(&$form) {
5bdcb00b
PJ
1231 $participantParams = $form->_params;
1232 $formattedValues = $profileFields = array();
353ffa53 1233 $count = 1;
5bdcb00b
PJ
1234 foreach ($participantParams as $participantNum => $participantValue) {
1235 if ($participantNum) {
0479b4c8
TO
1236 $prefix1 = 'additional';
1237 $prefix2 = 'additional_';
0db6c3e1
TO
1238 }
1239 else {
0479b4c8
TO
1240 $prefix1 = '';
1241 $prefix2 = '';
5bdcb00b
PJ
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,
0479b4c8 1248 $form->_values[$prefix2 . 'custom_pre_id'],
5bdcb00b
PJ
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 }
481a74f4 1290 if (!empty($formattedValues)) {
5bdcb00b 1291 $form->assign('primaryParticipantProfile', $formattedValues[1]);
0479b4c8 1292 $form->set('primaryParticipantProfile', $formattedValues[1]);
5bdcb00b
PJ
1293 if ($count > 2) {
1294 unset($formattedValues[1]);
1295 $form->assign('addParticipantProfile', $formattedValues);
0479b4c8 1296 $form->set('addParticipantProfile', $formattedValues);
5bdcb00b
PJ
1297 }
1298 }
1299 }
96025800 1300
632196ea 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'];
3ae1b2f4 1313 // This happens in buildQuickForm so emulate here.
1314 $form->_amount = $form->_totalAmount = CRM_Utils_Rule::cleanMoney(CRM_Utils_Array::value('totalAmount', $params));
632196ea 1315 $form->set('params', $params['params']);
1316 $form->_values['custom_pre_id'] = array();
1317 $form->_values['custom_post_id'] = array();
6704d983 1318 $form->_values['event'] = CRM_Utils_Array::value('event', $params);
632196ea 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']);
5e40de84 1323 if (!empty($params['paymentProcessorObj'])) {
1324 $form->_paymentProcessor = $params['paymentProcessorObj'];
1325 }
632196ea 1326 $form->postProcess();
1327 }
1328
55f9f634 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) {
22f9da80 1343 Civi::log()->error('Payment processor exception: ' . $e->getMessage());
55f9f634 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
3ae1b2f4 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
6a488035 1365}