Merge pull request #5057 from cividesk/CRM-15901-4.5
[civicrm-core.git] / CRM / Event / Form / Registration / Confirm.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.5 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2014 |
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 *
30 *
31 * @package CRM
32 * @copyright CiviCRM LLC (c) 2004-2014
33 * $Id$
34 *
35 */
36
37 /**
38 * This class generates form components for processing Event
39 *
40 */
41 class CRM_Event_Form_Registration_Confirm extends CRM_Event_Form_Registration {
42
43 /**
44 * the values for the contribution db object
45 *
46 * @var array
47 * @protected
48 */
49 public $_values;
50
51 /**
52 * the total amount
53 *
54 * @var float
55 * @public
56 */
57 public $_totalAmount;
58
59 /**
60 * Function to set variables up before form is built
61 *
62 * @return void
63 * @access public
64 */
65 function preProcess() {
66 parent::preProcess();
67
68 // lineItem isn't set until Register postProcess
69 $this->_lineItem = $this->get('lineItem');
70
71 $this->_params = $this->get('params');
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 if ($this->_contributeMode == 'express') {
87 $params = array();
88 // rfp == redirect from paypal
89 $rfp = CRM_Utils_Request::retrieve('rfp', 'Boolean',
90 CRM_Core_DAO::$_nullObject, FALSE, NULL, 'GET'
91 );
92
93 //we lost rfp in case of additional participant. So set it explicitly.
94 if ($rfp || CRM_Utils_Array::value('additional_participants', $this->_params[0], FALSE)) {
95 $payment = CRM_Core_Payment::singleton($this->_mode, $this->_paymentProcessor, $this);
96 $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.');
97 if (is_object($payment))
98 $expressParams = $payment->getExpressCheckoutDetails($this->get('token'));
99 else
100 CRM_Core_Error::fatal($paymentObjError);
101
102 $params['payer'] = CRM_Utils_Array::value('payer', $expressParams);
103 $params['payer_id'] = $expressParams['payer_id'];
104 $params['payer_status'] = $expressParams['payer_status'];
105
106 CRM_Core_Payment_Form::mapParams($this->_bltID, $expressParams, $params, FALSE);
107
108 // fix state and country id if present
109 if (isset($params["billing_state_province_id-{$this->_bltID}"])) {
110 $params["billing_state_province-{$this->_bltID}"] = CRM_Core_PseudoConstant::stateProvinceAbbreviation($params["billing_state_province_id-{$this->_bltID}"]);
111 }
112 if (isset($params['billing_country_id'])) {
113 $params["billing_country-{$this->_bltID}"] = CRM_Core_PseudoConstant::countryIsoCode($params["billing_country_id-{$this->_bltID}"]);
114 }
115
116 // set a few other parameters for PayPal
117 $params['token'] = $this->get('token');
118 $params['amount'] = $this->_params[0]['amount'];
119 if (!empty($this->_params[0]['discount'])) {
120 $params['discount'] = $this->_params[0]['discount'];
121 $params['discountAmount'] = $this->_params[0]['discountAmount'];
122 $params['discountMessage'] = $this->_params[0]['discountMessage'];
123 }
124 if (!empty($this->_params[0]['amount_priceset_level_radio'])) {
125 $params['amount_priceset_level_radio'] = $this->_params[0]['amount_priceset_level_radio'];
126 }
127 $params['amount_level'] = $this->_params[0]['amount_level'];
128 $params['currencyID'] = $this->_params[0]['currencyID'];
129 $params['payment_action'] = 'Sale';
130
131 // also merge all the other values from the profile fields
132 $values = $this->controller->exportValues('Register');
133 $skipFields = array(
134 'amount',
135 "street_address-{$this->_bltID}",
136 "city-{$this->_bltID}",
137 "state_province_id-{$this->_bltID}",
138 "postal_code-{$this->_bltID}",
139 "country_id-{$this->_bltID}",
140 );
141
142 foreach ($values as $name => $value) {
143 // skip amount field
144 if (!in_array($name, $skipFields)) {
145 $params[$name] = $value;
146 }
147 }
148 $this->set('getExpressCheckoutDetails', $params);
149 }
150 else {
151 $params = $this->get('getExpressCheckoutDetails');
152 }
153 $this->_params[0] = $params;
154 $this->_params[0]['is_primary'] = 1;
155 }
156 else {
157 //process only primary participant params.
158 $registerParams = $this->_params[0];
159 if (isset($registerParams["billing_state_province_id-{$this->_bltID}"])
160 && $registerParams["billing_state_province_id-{$this->_bltID}"]
161 ) {
162 $registerParams["billing_state_province-{$this->_bltID}"] = CRM_Core_PseudoConstant::stateProvinceAbbreviation($registerParams["billing_state_province_id-{$this->_bltID}"]);
163 }
164
165 if (isset($registerParams["billing_country_id-{$this->_bltID}"]) && $registerParams["billing_country_id-{$this->_bltID}"]) {
166 $registerParams["billing_country-{$this->_bltID}"] = CRM_Core_PseudoConstant::countryIsoCode($registerParams["billing_country_id-{$this->_bltID}"]);
167 }
168 if (isset($registerParams['credit_card_exp_date'])) {
169 $registerParams['year'] = CRM_Core_Payment_Form::getCreditCardExpirationYear($registerParams);
170 $registerParams['month'] = CRM_Core_Payment_Form::getCreditCardExpirationMonth($registerParams);
171 }
172 if ($this->_values['event']['is_monetary']) {
173 $registerParams['ip_address'] = CRM_Utils_System::ipAddress();
174 $registerParams['currencyID'] = $this->_params[0]['currencyID'];
175 $registerParams['payment_action'] = 'Sale';
176 }
177 //assign back primary participant params.
178 $this->_params[0] = $registerParams;
179 }
180
181 if ($this->_values['event']['is_monetary']) {
182 $this->_params[0]['invoiceID'] = $this->get('invoiceID');
183 }
184 $this->assign('defaultRole', FALSE);
185 if (CRM_Utils_Array::value('defaultRole', $this->_params[0]) == 1) {
186 $this->assign('defaultRole', TRUE);
187 }
188
189 if (empty($this->_params[0]['participant_role_id']) &&
190 $this->_values['event']['default_role_id']
191 ) {
192 $this->_params[0]['participant_role_id'] = $this->_values['event']['default_role_id'];
193 }
194
195 if (isset($this->_values['event']['confirm_title'])) {
196 CRM_Utils_System::setTitle($this->_values['event']['confirm_title']);
197 }
198
199 if ($this->_pcpId) {
200 $params = CRM_Contribute_Form_Contribution_Confirm::processPcp($this, $this->_params[0]);
201 $this->_params[0] = $params;
202 }
203
204 $this->set('params', $this->_params);
205 }
206
207 /**
208 * overwrite action, since we are only showing elements in frozen mode
209 * no help display needed
210 *
211 * @return int
212 * @access public
213 */
214 function getAction() {
215 if ($this->_action & CRM_Core_Action::PREVIEW) {
216 return CRM_Core_Action::VIEW | CRM_Core_Action::PREVIEW;
217 }
218 else {
219 return CRM_Core_Action::VIEW;
220 }
221 }
222
223 /**
224 * Function to build the form
225 *
226 * @return void
227 * @access public
228 */
229 public function buildQuickForm() {
230 $this->assignToTemplate();
231
232 if ($this->_values['event']['is_monetary'] &&
233 ($this->_params[0]['amount'] || $this->_params[0]['amount'] == 0)
234 ) {
235 $this->_amount = array();
236
237 foreach ($this->_params as $k => $v) {
238 if (is_array($v)) {
239 foreach (array(
240 'first_name', 'last_name') as $name) {
241 if (isset($v['billing_' . $name]) &&
242 !isset($v[$name])
243 ) {
244 $v[$name] = $v['billing_' . $name];
245 }
246 }
247
248 if (!empty($v['first_name']) && !empty($v['last_name'])) {
249 $append = $v['first_name'] . ' ' . $v['last_name'];
250 }
251 else {
252 //use an email if we have one
253 foreach ($v as $v_key => $v_val) {
254 if (substr($v_key, 0, 6) == 'email-') {
255 $append = $v[$v_key];
256 }
257 }
258 }
259
260 $this->_amount[$k]['amount'] = $v['amount'];
261 if (!empty($v['discountAmount'])) {
262 $this->_amount[$k]['amount'] -= $v['discountAmount'];
263 }
264
265 $this->_amount[$k]['label'] = preg_replace('/\ 1/', '', $v['amount_level']) . ' - ' . $append;
266 $this->_part[$k]['info'] = CRM_Utils_Array::value('first_name', $v) . ' ' . CRM_Utils_Array::value('last_name', $v);
267 if (empty($v['first_name'])) {
268 $this->_part[$k]['info'] = $append;
269 }
270 $this->_totalAmount = $this->_totalAmount + $this->_amount[$k]['amount'];
271 if (!empty($v['is_primary'])) {
272 $this->set('primaryParticipantAmount', $this->_amount[$k]['amount']);
273 }
274 }
275 }
276
277 $this->assign('part', $this->_part);
278 $this->set('part', $this->_part);
279 $this->assign('amounts', $this->_amount);
280 $this->assign('totalAmount', $this->_totalAmount);
281 $this->set('totalAmount', $this->_totalAmount);
282 }
283
284 if ($this->_priceSetId && !CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceSet', $this->_priceSetId, 'is_quick_config')) {
285 $lineItemForTemplate = array();
286 foreach ($this->_lineItem as $key => $value) {
287 if (!empty($value)) {
288 $lineItemForTemplate[$key] = $value;
289 }
290 }
291 if (!empty($lineItemForTemplate)) {
292 $this->assign('lineItem', $lineItemForTemplate);
293 }
294 }
295
296 //display additional participants profile.
297 self::assignProfiles($this);
298
299 //consider total amount.
300 $this->assign('isAmountzero', ($this->_totalAmount <= 0) ? TRUE : FALSE);
301
302 if ($this->_paymentProcessor['payment_processor_type'] == 'Google_Checkout' && empty($this->_params[0]['is_pay_later']) && !($this->_params[0]['amount'] == 0) &&
303 !$this->_allowWaitlist && !$this->_requireApproval
304 ) {
305 $this->_checkoutButtonName = $this->getButtonName('next', 'checkout');
306 $this->add('image',
307 $this->_checkoutButtonName,
308 $this->_paymentProcessor['url_button'],
309 array('class' => 'crm-form-submit')
310 );
311
312 $this->addButtons(array(
313 array(
314 'type' => 'back',
315 'name' => ts('<< Go Back'),
316 ),
317 )
318 );
319 }
320 else {
321 $contribButton = ts('Continue >>');
322 $this->addButtons(array(
323 array(
324 'type' => 'back',
325 'name' => ts('<< Go Back'),
326 ),
327 array(
328 'type' => 'next',
329 'name' => $contribButton,
330 'isDefault' => TRUE,
331 'js' => array('onclick' => "return submitOnce(this,'" . $this->_name . "','" . ts('Processing') . "');"),
332 ),
333 )
334 );
335 }
336
337 $defaults = array();
338 $fields = array();
339 if (!empty($this->_fields)) {
340 foreach ($this->_fields as $name => $dontCare) {
341 $fields[$name] = 1;
342 }
343 }
344 $fields["billing_state_province-{$this->_bltID}"] = $fields["billing_country-{$this->_bltID}"] = $fields["email-{$this->_bltID}"] = 1;
345 foreach ($fields as $name => $dontCare) {
346 if (isset($this->_params[0][$name])) {
347 $defaults[$name] = $this->_params[0][$name];
348 if (substr($name, 0, 7) == 'custom_') {
349 $timeField = "{$name}_time";
350 if (isset($this->_params[0][$timeField])) {
351 $defaults[$timeField] = $this->_params[0][$timeField];
352 }
353 if (isset($this->_params[0]["{$name}_id"])) {
354 $defaults["{$name}_id"] = $this->_params[0]["{$name}_id"];
355 }
356 }
357 elseif (in_array($name, CRM_Contact_BAO_Contact::$_greetingTypes)
358 && !empty($this->_params[0][$name . '_custom'])
359 ) {
360 $defaults[$name . '_custom'] = $this->_params[0][$name . '_custom'];
361 }
362 }
363 }
364
365 $this->setDefaults($defaults);
366 $this->freeze();
367
368 //lets give meaningful status message, CRM-4320.
369 $this->assign('isOnWaitlist', $this->_allowWaitlist);
370 $this->assign('isRequireApproval', $this->_requireApproval);
371
372 // Assign Participant Count to Lineitem Table
373 $this->assign('pricesetFieldsCount', CRM_Price_BAO_PriceSet::getPricesetCount($this->_priceSetId));
374 }
375
376 /**
377 * Function to process the form
378 *
379 * @access public
380 *
381 * @return void
382 */
383 public function postProcess() {
384 $now = date('YmdHis');
385
386 $this->_params = $this->get('params');
387 if (!empty($this->_params[0]['contact_id'])) {
388 // unclear when this would be set & whether it could be checked in getContactID.
389 // perhaps it relates to when cid is in the url
390 //@todo someone who knows add comments on the various contactIDs in this form
391 $contactID = $this->_params[0]['contact_id'];
392 }
393 else {
394 $contactID = $this->getContactID();
395 }
396
397 // if a discount has been applied, lets now deduct it from the amount
398 // and fix the fee level
399 if (!empty($this->_params[0]['discount']) && !empty($this->_params[0]['discount']['applied'])) {
400 foreach ($this->_params as $k => $v) {
401 if (CRM_Utils_Array::value('amount', $this->_params[$k]) > 0 && !empty($this->_params[$k]['discountAmount'])) {
402 $this->_params[$k]['amount'] -= $this->_params[$k]['discountAmount'];
403 $this->_params[$k]['amount_level'] .= CRM_Utils_Array::value('discountMessage', $this->_params[$k]);
404 }
405 }
406 $this->set('params', $this->_params);
407 }
408
409 // CRM-4320, lets build array of cancelled additional participant ids
410 // those are drop or skip by primary at the time of confirmation.
411 // get all in and then unset those we want to process.
412 $cancelledIds = $this->_additionalParticipantIds;
413
414 $params = $this->_params;
415 if ($this->_values['event']['is_monetary']) {
416 $this->set('finalAmount', $this->_amount);
417 }
418 $participantCount = array();
419
420 //unset the skip participant from params.
421 //build the $participantCount array.
422 //maintain record for all participants.
423 foreach ($params as $participantNum => $record) {
424 if ($record == 'skip') {
425 unset($params[$participantNum]);
426 $participantCount[$participantNum] = 'skip';
427 }
428 elseif ($participantNum) {
429 $participantCount[$participantNum] = 'participant';
430 }
431
432 //lets get additional participant id to cancel.
433 if ($this->_allowConfirmation && is_array($cancelledIds)) {
434 $additonalId = CRM_Utils_Array::value('participant_id', $record);
435 if ($additonalId && $key = array_search($additonalId, $cancelledIds)) {
436 unset($cancelledIds[$key]);
437 }
438 }
439 }
440
441 $payment = $registerByID = $primaryCurrencyID = $contribution = NULL;
442 $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.');
443
444 $this->participantIDS = array();
445 $fields = array();
446 foreach ($params as $key => $value) {
447 CRM_Event_Form_Registration_Confirm::fixLocationFields($value, $fields, $this);
448 //unset the billing parameters if it is pay later mode
449 //to avoid creation of billing location
450 if ($this->_allowWaitlist || $this->_requireApproval || !empty($value['is_pay_later']) || empty($value['is_primary'])) {
451 $billingFields = array(
452 "email-{$this->_bltID}",
453 'billing_first_name',
454 'billing_middle_name',
455 'billing_last_name',
456 "billing_street_address-{$this->_bltID}",
457 "billing_city-{$this->_bltID}",
458 "billing_state_province-{$this->_bltID}",
459 "billing_state_province_id-{$this->_bltID}",
460 "billing_postal_code-{$this->_bltID}",
461 "billing_country-{$this->_bltID}",
462 "billing_country_id-{$this->_bltID}",
463 "address_name-{$this->_bltID}",
464 );
465 foreach ($billingFields as $field) {
466 unset($value[$field]);
467 }
468 if (!empty($value['is_pay_later'])) {
469 $this->_values['params']['is_pay_later'] = TRUE;
470 }
471 }
472
473 //Unset ContactID for additional participants and set RegisterBy Id.
474 if (empty($value['is_primary'])) {
475 $contactID = CRM_Utils_Array::value('contact_id', $value);
476 $registerByID = $this->get('registerByID');
477 if ($registerByID) {
478 $value['registered_by_id'] = $registerByID;
479 }
480 }
481 else {
482 $value['amount'] = $this->_totalAmount;
483 }
484
485 $contactID = CRM_Event_Form_Registration_Confirm::updateContactFields($contactID, $value, $fields, $this);
486
487 // lets store the contactID in the session
488 // we dont store in userID in case the user is doing multiple
489 // transactions etc
490 // for things like tell a friend
491 if (!$this->getContactID() && !empty($value['is_primary'])) {
492 $session = CRM_Core_Session::singleton();
493 $session->set('transaction.userID', $contactID);
494 }
495
496 $value['description'] = ts('Online Event Registration') . ': ' . $this->_values['event']['title'];
497 $value['accountingCode'] = CRM_Utils_Array::value('accountingCode',
498 $this->_values['event']
499 );
500
501 // required only if paid event
502 if ($this->_values['event']['is_monetary']) {
503 if (is_array($this->_paymentProcessor)) {
504 $payment = CRM_Core_Payment::singleton($this->_mode, $this->_paymentProcessor, $this);
505 }
506 $pending = FALSE;
507 $result = NULL;
508
509 if ($this->_allowWaitlist || $this->_requireApproval) {
510 //get the participant statuses.
511 $waitingStatuses = CRM_Event_PseudoConstant::participantStatus(NULL, "class = 'Waiting'");
512 if ($this->_allowWaitlist) {
513 $value['participant_status_id'] = $value['participant_status'] = array_search('On waitlist', $waitingStatuses);
514 }
515 else {
516 $value['participant_status_id'] = $value['participant_status'] = array_search('Awaiting approval', $waitingStatuses);
517 }
518
519 //there might be case user seleted pay later and
520 //now becomes part of run time waiting list.
521 $value['is_pay_later'] = FALSE;
522 }
523 elseif (!empty($value['is_pay_later']) ||
524 $value['amount'] == 0 ||
525 $this->_contributeMode == 'checkout' ||
526 $this->_contributeMode == 'notify'
527 ) {
528 if ($value['amount'] != 0) {
529 $pending = TRUE;
530 //get the participant statuses.
531 $pendingStatuses = CRM_Event_PseudoConstant::participantStatus(NULL, "class = 'Pending'");
532 $status = !empty($value['is_pay_later']) ? 'Pending from pay later' : 'Pending from incomplete transaction';
533 $value['participant_status_id'] = $value['participant_status'] = array_search($status, $pendingStatuses);
534 }
535 }
536 elseif ($this->_contributeMode == 'express' && !empty($value['is_primary'])) {
537 if (is_object($payment))
538 $result = $payment->doExpressCheckout($value);
539 else
540 CRM_Core_Error::fatal($paymentObjError);
541 }
542 elseif (!empty($value['is_primary'])) {
543 CRM_Core_Payment_Form::mapParams($this->_bltID, $value, $value, TRUE);
544 // payment email param can be empty for _bltID mapping
545 // thus provide mapping for it with a different email value
546 if (empty($value['email'])) {
547 $value['email'] = CRM_Utils_Array::valueByRegexKey('/^email-/', $value);
548 }
549
550 if (is_object($payment)) {
551 $result = $payment->doDirectPayment($value);
552 }
553 else {
554 CRM_Core_Error::fatal($paymentObjError);
555 }
556 }
557
558 if (is_a($result, 'CRM_Core_Error')) {
559 CRM_Core_Error::displaySessionError($result);
560 CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/event/register', "id={$this->_eventId}"));
561 }
562
563 if ($result) {
564 $value = array_merge($value, $result);
565 }
566
567 $value['receive_date'] = $now;
568 if ($this->_allowConfirmation) {
569 $value['participant_register_date'] = $this->_values['participant']['register_date'];
570 }
571
572 $createContrib = ($value['amount'] != 0) ? TRUE : FALSE;
573 // force to create zero amount contribution, CRM-5095
574 if (!$createContrib && ($value['amount'] == 0)
575 && $this->_priceSetId && $this->_lineItem
576 ) {
577 $createContrib = TRUE;
578 }
579
580 if ($createContrib && !empty($value['is_primary']) &&
581 !$this->_allowWaitlist && !$this->_requireApproval
582 ) {
583 // if paid event add a contribution record
584 //if primary participant contributing additional amount
585 //append (multiple participants) to its fee level. CRM-4196.
586 $isAdditionalAmount = FALSE;
587 if (count($params) > 1) {
588 $isAdditionalAmount = TRUE;
589 }
590
591 //passing contribution id is already registered.
592 $contribution =
593 self::processContribution($this, $value, $result, $contactID, $pending, $isAdditionalAmount);
594 $value['contributionID'] = $contribution->id;
595 $value['contributionTypeID'] = $contribution->financial_type_id;
596 $value['receive_date'] = $contribution->receive_date;
597 $value['trxn_id'] = $contribution->trxn_id;
598 $value['contributionID'] = $contribution->id;
599 $value['contributionTypeID'] = $contribution->financial_type_id;
600 }
601 $value['contactID'] = $contactID;
602 $value['eventID'] = $this->_eventId;
603 $value['item_name'] = $value['description'];
604 }
605
606 //CRM-4453.
607 if (!empty($value['is_primary'])) {
608 $primaryCurrencyID = CRM_Utils_Array::value('currencyID', $value);
609 }
610 if (empty($value['currencyID'])) {
611 $value['currencyID'] = $primaryCurrencyID;
612 }
613
614 // CRM-11182 - Confirmation page might not be monetary
615 if ($this->_values['event']['is_monetary']) {
616 if (!$pending && !empty($value['is_primary']) &&
617 !$this->_allowWaitlist && !$this->_requireApproval
618 ) {
619 // transactionID & receive date required while building email template
620 $this->assign('trxn_id', $value['trxn_id']);
621 $this->assign('receive_date', CRM_Utils_Date::mysqlToIso($value['receive_date']));
622 $this->set('receiveDate', CRM_Utils_Date::mysqlToIso($value['receive_date']));
623 $this->set('trxnId', CRM_Utils_Array::value('trxn_id', $value));
624 }
625 }
626
627 $value['fee_amount'] = CRM_Utils_Array::value('amount', $value);
628 $this->set('value', $value);
629
630 // handle register date CRM-4320
631 if ($this->_allowConfirmation) {
632 $registerDate = CRM_Utils_Array::value( 'participant_register_date', $params );
633 }
634 elseif (!empty($params['participant_register_date']) &&
635 is_array($params['participant_register_date']) &&
636 !empty($params['participant_register_date'])
637 ) {
638 $registerDate = CRM_Utils_Date::format($params['participant_register_date']);
639 }
640 else {
641 $registerDate = date('YmdHis');
642 }
643 $this->assign('register_date', $registerDate);
644
645 $this->confirmPostProcess($contactID, $contribution, $payment);
646 }
647
648 //handle if no additional participant.
649 if (!$registerByID) {
650 $registerByID = $this->get('registerByID');
651 }
652
653 $this->set('participantIDs', $this->_participantIDS);
654
655 // create line items, CRM-5313
656 if ($this->_priceSetId &&
657 !empty($this->_lineItem)
658 ) {
659 // take all processed participant ids.
660 $allParticipantIds = $this->_participantIDS;
661
662 // when participant re-walk wizard.
663 if ($this->_allowConfirmation &&
664 !empty($this->_additionalParticipantIds)
665 ) {
666 $allParticipantIds = array_merge(array($registerByID), $this->_additionalParticipantIds);
667 }
668
669 $entityTable = 'civicrm_participant';
670 foreach ($this->_lineItem as $key => $value) {
671 if (($value != 'skip') &&
672 ($entityId = CRM_Utils_Array::value($key, $allParticipantIds))
673 ) {
674
675 // do cleanup line items if participant re-walking wizard.
676 if ($this->_allowConfirmation) {
677 CRM_Price_BAO_LineItem::deleteLineItems($entityId, $entityTable);
678 }
679 $lineItem[$this->_priceSetId] = $value;
680 CRM_Price_BAO_LineItem::processPriceSet($entityId, $lineItem, $contribution, $entityTable);
681 }
682 }
683 }
684
685 //update status and send mail to cancelled additonal participants, CRM-4320
686 if ($this->_allowConfirmation && is_array($cancelledIds) && !empty($cancelledIds)) {
687 $cancelledId = array_search('Cancelled',
688 CRM_Event_PseudoConstant::participantStatus(NULL, "class = 'Negative'")
689 );
690 CRM_Event_BAO_Participant::transitionParticipants($cancelledIds, $cancelledId);
691 }
692
693 $isTest = FALSE;
694 if ($this->_action & CRM_Core_Action::PREVIEW) {
695 $isTest = TRUE;
696 }
697
698 // for Transfer checkout.
699 if (($this->_contributeMode == 'checkout' ||
700 $this->_contributeMode == 'notify'
701 ) && empty($params[0]['is_pay_later']) &&
702 !$this->_allowWaitlist && !$this->_requireApproval &&
703 $this->_totalAmount > 0
704 ) {
705
706 $primaryParticipant = $this->get('primaryParticipant');
707
708 if (empty($primaryParticipant['participantID'])) {
709 $primaryParticipant['participantID'] = $registerByID;
710 }
711
712 //build an array of custom profile and assigning it to template
713 $customProfile = CRM_Event_BAO_Event::buildCustomProfile($registerByID, $this->_values, NULL, $isTest);
714 if (count($customProfile)) {
715 $this->assign('customProfile', $customProfile);
716 $this->set('customProfile', $customProfile);
717 }
718
719 // do a transfer only if a monetary payment greater than 0
720 if ($this->_values['event']['is_monetary'] && $primaryParticipant) {
721 if ($payment && is_object($payment)) {
722 // call postprocess hook before leaving
723 $this->postProcessHook();
724 // this does not return
725 $payment->doTransferCheckout($primaryParticipant, 'event');
726 }
727 else {
728 CRM_Core_Error::fatal($paymentObjError);
729 }
730 }
731 }
732 else {
733 //otherwise send mail Confirmation/Receipt
734 $primaryContactId = $this->get('primaryContactId');
735
736 //build an array of cId/pId of participants
737 $additionalIDs = CRM_Event_BAO_Event::buildCustomProfile($registerByID,
738 NULL, $primaryContactId, $isTest,
739 TRUE
740 );
741 //lets send mails to all with meaningful text, CRM-4320.
742 $this->assign('isOnWaitlist', $this->_allowWaitlist);
743 $this->assign('isRequireApproval', $this->_requireApproval);
744
745 //need to copy, since we are unsetting on the way.
746 $copyParticipantCount = $participantCount;
747
748 //lets carry all paticipant params w/ values.
749 foreach ($additionalIDs as $participantID => $contactId) {
750 $participantNum = NULL;
751 if ($participantID == $registerByID) {
752 $participantNum = 0;
753 }
754 else {
755 if ($participantNum = array_search('participant', $copyParticipantCount)) {
756 unset($copyParticipantCount[$participantNum]);
757 }
758 }
759 if ($participantNum === NULL)
760 break;
761
762 //carry the participant submitted values.
763 $this->_values['params'][$participantID] = $params[$participantNum];
764 }
765
766 foreach ($additionalIDs as $participantID => $contactId) {
767 $participantNum = 0;
768 if ($participantID == $registerByID) {
769 //set as Primary Participant
770 $this->assign('isPrimary', 1);
771 //build an array of custom profile and assigning it to template.
772 $customProfile = CRM_Event_BAO_Event::buildCustomProfile($participantID, $this->_values, NULL, $isTest);
773
774 if (count($customProfile)) {
775 $this->assign('customProfile', $customProfile);
776 $this->set('customProfile', $customProfile);
777 }
778 $this->_values['params']['additionalParticipant'] = FALSE;
779 }
780 else {
781 //take the Additional participant number.
782 if ($participantNum = array_search('participant', $participantCount)) {
783 unset($participantCount[$participantNum]);
784 }
785 $this->assign('isPrimary', 0);
786 $this->assign('customProfile', NULL);
787 //Additional Participant should get only it's payment information
788 if (!empty($this->_amount)) {
789 $amount = array();
790 $params = $this->get('params');
791 $amount[$participantNum]['label'] = preg_replace('/\ 1/', '', $params[$participantNum]['amount_level']);
792 $amount[$participantNum]['amount'] = $params[$participantNum]['amount'];
793 $this->assign('amounts', $amount);
794 }
795 if ($this->_lineItem) {
796 $lineItems = $this->_lineItem;
797 $lineItem = array();
798 if ($lineItemValue = CRM_Utils_Array::value($participantNum, $lineItems)) {
799 $lineItem[] = $lineItemValue;
800 }
801 $this->assign('lineItem', $lineItem);
802 }
803 $this->_values['params']['additionalParticipant'] = TRUE;
804 $this->assign('isAdditionalParticipant', $this->_values['params']['additionalParticipant']);
805 }
806
807 //pass these variables since these are run time calculated.
808 $this->_values['params']['isOnWaitlist'] = $this->_allowWaitlist;
809 $this->_values['params']['isRequireApproval'] = $this->_requireApproval;
810
811 //send mail to primary as well as additional participants.
812 $this->assign('contactID', $contactId);
813 $this->assign('participantID', $participantID);
814 CRM_Event_BAO_Event::sendMail($contactId, $this->_values, $participantID, $isTest);
815 }
816 }
817 }
818 //end of function
819
820 /**
821 * Process the contribution
822 *
823 * @param $form
824 * @param $params
825 * @param $result
826 * @param $contactID
827 * @param bool $pending
828 * @param bool $isAdditionalAmount
829 *
830 * @return void
831 * @access public
832 */
833 static function processContribution(&$form, $params, $result, $contactID,
834 $pending = FALSE, $isAdditionalAmount = FALSE
835 ) {
836 $transaction = new CRM_Core_Transaction();
837
838 $now = date('YmdHis');
839 $receiptDate = NULL;
840
841 if (!empty($form->_values['event']['is_email_confirm'])) {
842 $receiptDate = $now;
843 }
844 //CRM-4196
845 if ($isAdditionalAmount) {
846 $params['amount_level'] = $params['amount_level'] . ts(' (multiple participants)') . CRM_Core_DAO::VALUE_SEPARATOR;
847 }
848
849 $contribParams = array(
850 'contact_id' => $contactID,
851 'financial_type_id' => !empty($form->_values['event']['financial_type_id']) ?
852 $form->_values['event']['financial_type_id'] : $params['financial_type_id'],
853 'receive_date' => $now,
854 'total_amount' => $params['amount'],
855 'amount_level' => $params['amount_level'],
856 'invoice_id' => $params['invoiceID'],
857 'currency' => $params['currencyID'],
858 'source' => $params['description'],
859 'is_pay_later' => CRM_Utils_Array::value('is_pay_later', $params, 0),
860 'campaign_id' => CRM_Utils_Array::value('campaign_id', $params),
861 );
862
863 if (empty($params['is_pay_later'])) {
864 $contribParams['payment_instrument_id'] = 1;
865 }
866
867 if (!$pending && $result) {
868 $contribParams += array(
869 'fee_amount' => CRM_Utils_Array::value('fee_amount', $result),
870 'net_amount' => CRM_Utils_Array::value('net_amount', $result, $params['amount']),
871 'trxn_id' => $result['trxn_id'],
872 'receipt_date' => $receiptDate,
873 );
874 }
875
876 $allStatuses = CRM_Contribute_PseudoConstant::contributionStatus(NULL, 'name');
877 $contribParams['contribution_status_id'] = array_search('Completed', $allStatuses);
878 if ($pending) {
879 $contribParams['contribution_status_id'] = array_search('Pending', $allStatuses);
880 }
881
882 $contribParams['is_test'] = 0;
883 if ($form->_action & CRM_Core_Action::PREVIEW || CRM_Utils_Array::value('mode', $params) == 'test') {
884 $contribParams['is_test'] = 1;
885 }
886
887 $contribID = NULL;
888 if (!empty($contribParams['invoice_id'])) {
889 $contribID = CRM_Core_DAO::getFieldValue('CRM_Contribute_DAO_Contribution',
890 $contribParams['invoice_id'],
891 'id',
892 'invoice_id'
893 );
894 }
895
896 $ids = array();
897 if ($contribID) {
898 $ids['contribution'] = $contribID;
899 $contribParams['id'] = $contribID;
900 }
901
902 //create an contribution address
903 if ($form->_contributeMode != 'notify' && empty($params['is_pay_later'])) {
904 $contribParams['address_id'] = CRM_Contribute_BAO_Contribution::createAddress($params, $form->_bltID);
905 }
906
907 // Prepare soft contribution due to pcp or Submit Credit / Debit Card Contribution by admin.
908 if (!empty($params['pcp_made_through_id']) || !empty($params['soft_credit_to'])) {
909
910 // if its due to pcp
911 if (!empty($params['pcp_made_through_id'])) {
912 $contribSoftContactId = CRM_Core_DAO::getFieldValue('CRM_PCP_DAO_PCP',
913 $params['pcp_made_through_id'],
914 'contact_id'
915 );
916 }
917 else {
918 $contribSoftContactId = CRM_Utils_Array::value('soft_credit_to', $params);
919 }
920
921 // Pass these details onto with the contribution to make them
922 // available at hook_post_process, CRM-8908
923 $contribParams['soft_credit_to'] = $params['soft_credit_to'] = $contribSoftContactId;
924 }
925 $contribParams['payment_processor'] = CRM_Utils_Array::value('payment_processor', $params);
926 $contribParams['skipLineItem'] = 1;
927 // create contribution record
928 $contribution = CRM_Contribute_BAO_Contribution::add($contribParams, $ids);
929 // CRM-11124
930 CRM_Event_BAO_Participant::createDiscountTrxn($form->_eventId, $contribParams, CRM_Utils_Array::value('amount_priceset_level_radio', $params, NULL));
931
932 // process soft credit / pcp pages
933 CRM_Contribute_Form_Contribution_Confirm::processPcpSoft($params, $contribution);
934
935 $transaction->commit();
936
937 return $contribution;
938 }
939
940 /**
941 * Fix the Location Fields
942 *
943 * @param $params
944 * @param $fields
945 * @param $form
946 *
947 * @return void
948 * @access public
949 */
950 public static function fixLocationFields(&$params, &$fields, &$form) {
951 if (!empty($form->_fields)) {
952 foreach ($form->_fields as $name => $dontCare) {
953 $fields[$name] = 1;
954 }
955 }
956
957 if (is_array($fields)) {
958 if (!array_key_exists('first_name', $fields)) {
959 $nameFields = array('first_name', 'middle_name', 'last_name');
960 foreach ($nameFields as $name) {
961 $fields[$name] = 1;
962 if (array_key_exists("billing_$name", $params)) {
963 $params[$name] = $params["billing_{$name}"];
964 $params['preserveDBName'] = TRUE;
965 }
966 }
967 }
968 }
969
970 // also add location name to the array
971 if ($form->_values['event']['is_monetary']) {
972 $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);
973 $fields["address_name-{$form->_bltID}"] = 1;
974 }
975 $fields["email-{$form->_bltID}"] = 1;
976 $fields['email-Primary'] = 1;
977
978 //if its pay later or additional participant set email address as primary.
979 if ((!empty($params['is_pay_later']) || empty($params['is_primary']) ||
980 !$form->_values['event']['is_monetary'] ||
981 $form->_allowWaitlist ||
982 $form->_requireApproval
983 ) && !empty($params["email-{$form->_bltID}"])) {
984 $params['email-Primary'] = $params["email-{$form->_bltID}"];
985 }
986 }
987
988 /**
989 * function to update contact fields
990 *
991 * @param $contactID
992 * @param $params
993 * @param $fields
994 * @param $form
995 *
996 * @return void
997 * @access public
998 */
999 public static function updateContactFields($contactID, $params, $fields, &$form) {
1000 //add the contact to group, if add to group is selected for a
1001 //particular uf group
1002
1003 // get the add to groups
1004 $addToGroups = array();
1005
1006 if (!empty($form->_fields)) {
1007 foreach ($form->_fields as $key => $value) {
1008 if (!empty($value['add_to_group_id'])) {
1009 $addToGroups[$value['add_to_group_id']] = $value['add_to_group_id'];
1010 }
1011 }
1012 }
1013
1014 // check for profile double opt-in and get groups to be subscribed
1015 $subscribeGroupIds = CRM_Core_BAO_UFGroup::getDoubleOptInGroupIds($params, $contactID);
1016
1017 foreach ($addToGroups as $k) {
1018 if (array_key_exists($k, $subscribeGroupIds)) {
1019 unset($addToGroups[$k]);
1020 }
1021 }
1022
1023 // since we are directly adding contact to group lets unset it from mailing
1024 if (!empty($addToGroups)) {
1025 foreach ($addToGroups as $groupId) {
1026 if (isset($subscribeGroupIds[$groupId])) {
1027 unset($subscribeGroupIds[$groupId]);
1028 }
1029 }
1030 }
1031 if ($contactID) {
1032 $ctype = CRM_Core_DAO::getFieldValue(
1033 'CRM_Contact_DAO_Contact',
1034 $contactID,
1035 'contact_type'
1036 );
1037
1038 if(array_key_exists('contact_id', $params) && empty($params['contact_id'])) {
1039 // we unset this here because the downstream function ignores the contactID we give it
1040 // if it is set & it is difficult to understand the implications of 'fixing' this downstream
1041 // but if we are passing a contact id into this function it's reasonable to assume we don't
1042 // want it ignored
1043 unset($params['contact_id']);
1044 }
1045
1046 $contactID = CRM_Contact_BAO_Contact::createProfileContact(
1047 $params,
1048 $fields,
1049 $contactID,
1050 $addToGroups,
1051 NULL,
1052 $ctype,
1053 TRUE
1054 );
1055 }
1056 else {
1057
1058 foreach (CRM_Contact_BAO_Contact::$_greetingTypes as $greeting) {
1059 if (!isset($params[$greeting . '_id'])) {
1060 $params[$greeting . '_id'] = CRM_Contact_BAO_Contact_Utils::defaultGreeting('Individual', $greeting);
1061 }
1062 }
1063
1064 $contactID = CRM_Contact_BAO_Contact::createProfileContact($params,
1065 $fields,
1066 NULL,
1067 $addToGroups,
1068 NULL,
1069 NULL,
1070 TRUE
1071 );
1072 $form->set('contactID', $contactID);
1073 }
1074
1075 //get email primary first if exist
1076 $subscribtionEmail = array('email' => CRM_Utils_Array::value('email-Primary', $params));
1077 if (!$subscribtionEmail['email']) {
1078 $subscribtionEmail['email'] = CRM_Utils_Array::value("email-{$form->_bltID}", $params);
1079 }
1080 // subscribing contact to groups
1081 if (!empty($subscribeGroupIds) && $subscribtionEmail['email']) {
1082 CRM_Mailing_Event_BAO_Subscribe::commonSubscribe($subscribeGroupIds, $subscribtionEmail, $contactID);
1083 }
1084
1085 return $contactID;
1086 }
1087
1088 /**
1089 * @param $form
1090 */
1091 public static function assignProfiles(&$form) {
1092 $participantParams = $form->_params;
1093 $formattedValues = $profileFields = array();
1094 $count = 1;
1095 foreach ($participantParams as $participantNum => $participantValue) {
1096 if ($participantNum) {
1097 $prefix1 = 'additional';
1098 $prefix2 = 'additional_';
1099 } else {
1100 $prefix1 = '';
1101 $prefix2 = '';
1102 }
1103 if ($participantValue != 'skip') {
1104 //get the customPre profile info
1105 if (!empty($form->_values[$prefix2 . 'custom_pre_id'])) {
1106 $values = $groupName = array();
1107 CRM_Event_BAO_Event::displayProfile($participantValue,
1108 $form->_values[ $prefix2 . 'custom_pre_id'],
1109 $groupName,
1110 $values,
1111 $profileFields
1112 );
1113
1114 if (count($values)) {
1115 $formattedValues[$count][$prefix1 . 'CustomPre'] = $values;
1116 }
1117 $formattedValues[$count][$prefix1 . 'CustomPreGroupTitle'] = CRM_Utils_Array::value('groupTitle', $groupName);
1118 }
1119 //get the customPost profile info
1120 if (!empty($form->_values[$prefix2 . 'custom_post_id'])) {
1121 $values = $groupName = array();
1122 foreach ($form->_values[$prefix2 . 'custom_post_id'] as $gids) {
1123 $val = array();
1124 CRM_Event_BAO_Event::displayProfile($participantValue,
1125 $gids,
1126 $group,
1127 $val,
1128 $profileFields
1129 );
1130 $values[$gids] = $val;
1131 $groupName[$gids] = $group;
1132 }
1133
1134 if (count($values)) {
1135 $formattedValues[$count][$prefix1 . 'CustomPost'] = $values;
1136 }
1137
1138 if (isset($formattedValues[$count][$prefix1 . 'CustomPre'])) {
1139 $formattedValues[$count][$prefix1 . 'CustomPost'] = array_diff_assoc($formattedValues[$count][$prefix1 . 'CustomPost'],
1140 $formattedValues[$count][$prefix1 . 'CustomPre']
1141 );
1142 }
1143
1144 $formattedValues[$count][$prefix1 . 'CustomPostGroupTitle'] = $groupName;
1145 }
1146 $count++;
1147 }
1148 $form->_fields = $profileFields;
1149 }
1150 if (!empty($formattedValues) ) {
1151 $form->assign('primaryParticipantProfile', $formattedValues[1]);
1152 $form->set('primaryParticipantProfile', $formattedValues[1]);
1153 if ($count > 2) {
1154 unset($formattedValues[1]);
1155 $form->assign('addParticipantProfile', $formattedValues);
1156 $form->set('addParticipantProfile', $formattedValues);
1157 }
1158 }
1159 }
1160 }