3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.7 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2015 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
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. |
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. |
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 +--------------------------------------------------------------------+
30 * @copyright CiviCRM LLC (c) 2004-2015
34 * This class generates form components for processing Event.
36 class CRM_Event_Form_Registration_Confirm
extends CRM_Event_Form_Registration
{
39 * The values for the contribution db object.
53 * Set variables up before form is built.
55 public function preProcess() {
58 // lineItem isn't set until Register postProcess
59 $this->_lineItem
= $this->get('lineItem');
61 $this->_params
= $this->get('params');
62 $this->_params
[0]['tax_amount'] = $this->get('tax_amount');
64 $this->_params
[0]['is_pay_later'] = $this->get('is_pay_later');
65 $this->assign('is_pay_later', $this->_params
[0]['is_pay_later']);
66 if ($this->_params
[0]['is_pay_later']) {
67 $this->assign('pay_later_receipt', $this->_values
['event']['pay_later_receipt']);
70 CRM_Utils_Hook
::eventDiscount($this, $this->_params
);
72 if (!empty($this->_params
[0]['discount']) && !empty($this->_params
[0]['discount']['applied'])) {
73 $this->set('hookDiscount', $this->_params
[0]['discount']);
74 $this->assign('hookDiscount', $this->_params
[0]['discount']);
77 // The concept of contributeMode is deprecated.
78 if ($this->_contributeMode
== 'express') {
80 // rfp == redirect from paypal
81 // rfp is probably not required - the getPreApprovalDetails should deal with any payment-processor specific 'stuff'
82 $rfp = CRM_Utils_Request
::retrieve('rfp', 'Boolean',
83 CRM_Core_DAO
::$_nullObject, FALSE, NULL, 'GET'
86 //we lost rfp in case of additional participant. So set it explicitly.
87 if ($rfp || CRM_Utils_Array
::value('additional_participants', $this->_params
[0], FALSE)) {
88 if (!empty($this->_paymentProcessor
) && $this->_paymentProcessor
['object']->supports('preApproval')) {
89 $preApprovalParams = $this->_paymentProcessor
['object']->getPreApprovalDetails($this->get('pre_approval_parameters'));
90 $params = array_merge($this->_params
, $preApprovalParams);
92 CRM_Core_Payment_Form
::mapParams($this->_bltID
, $params, $params, FALSE);
94 // set a few other parameters that are not really specific to this method because we don't know what
95 // will break if we change this.
96 $params['amount'] = $this->_params
[0]['amount'];
97 if (!empty($this->_params
[0]['discount'])) {
98 $params['discount'] = $this->_params
[0]['discount'];
99 $params['discountAmount'] = $this->_params
[0]['discountAmount'];
100 $params['discountMessage'] = $this->_params
[0]['discountMessage'];
102 if (!empty($this->_params
[0]['amount_priceset_level_radio'])) {
103 $params['amount_priceset_level_radio'] = $this->_params
[0]['amount_priceset_level_radio'];
105 $params['amount_level'] = $this->_params
[0]['amount_level'];
106 $params['currencyID'] = $this->_params
[0]['currencyID'];
108 // also merge all the other values from the profile fields
109 $values = $this->controller
->exportValues('Register');
112 "street_address-{$this->_bltID}",
113 "city-{$this->_bltID}",
114 "state_province_id-{$this->_bltID}",
115 "postal_code-{$this->_bltID}",
116 "country_id-{$this->_bltID}",
119 foreach ($values as $name => $value) {
121 if (!in_array($name, $skipFields)) {
122 $params[$name] = $value;
124 if (substr($name, 0, 6) == 'price_') {
125 $params[$name] = $this->_params
[0][$name];
128 $this->set('getExpressCheckoutDetails', $params);
130 $this->_params
[0] = array_merge($this->_params
[0], $params);
131 $this->_params
[0]['is_primary'] = 1;
134 //process only primary participant params.
135 $registerParams = $this->_params
[0];
136 if (isset($registerParams["billing_state_province_id-{$this->_bltID}"])
137 && $registerParams["billing_state_province_id-{$this->_bltID}"]
139 $registerParams["billing_state_province-{$this->_bltID}"] = CRM_Core_PseudoConstant
::stateProvinceAbbreviation($registerParams["billing_state_province_id-{$this->_bltID}"]);
142 if (isset($registerParams["billing_country_id-{$this->_bltID}"]) && $registerParams["billing_country_id-{$this->_bltID}"]) {
143 $registerParams["billing_country-{$this->_bltID}"] = CRM_Core_PseudoConstant
::countryIsoCode($registerParams["billing_country_id-{$this->_bltID}"]);
145 if (isset($registerParams['credit_card_exp_date'])) {
146 $registerParams['year'] = CRM_Core_Payment_Form
::getCreditCardExpirationYear($registerParams);
147 $registerParams['month'] = CRM_Core_Payment_Form
::getCreditCardExpirationMonth($registerParams);
149 if ($this->_values
['event']['is_monetary']) {
150 $registerParams['ip_address'] = CRM_Utils_System
::ipAddress();
151 $registerParams['currencyID'] = $this->_params
[0]['currencyID'];
153 //assign back primary participant params.
154 $this->_params
[0] = $registerParams;
157 if ($this->_values
['event']['is_monetary']) {
158 $this->_params
[0]['invoiceID'] = $this->get('invoiceID');
160 $this->assign('defaultRole', FALSE);
161 if (CRM_Utils_Array
::value('defaultRole', $this->_params
[0]) == 1) {
162 $this->assign('defaultRole', TRUE);
165 if (empty($this->_params
[0]['participant_role_id']) &&
166 $this->_values
['event']['default_role_id']
168 $this->_params
[0]['participant_role_id'] = $this->_values
['event']['default_role_id'];
171 if (isset($this->_values
['event']['confirm_title'])) {
172 CRM_Utils_System
::setTitle($this->_values
['event']['confirm_title']);
176 $params = CRM_Contribute_Form_Contribution_Confirm
::processPcp($this, $this->_params
[0]);
177 $this->_params
[0] = $params;
180 $this->set('params', $this->_params
);
184 * Overwrite action, since we are only showing elements in frozen mode no help display needed.
188 public function getAction() {
189 if ($this->_action
& CRM_Core_Action
::PREVIEW
) {
190 return CRM_Core_Action
::VIEW | CRM_Core_Action
::PREVIEW
;
193 return CRM_Core_Action
::VIEW
;
198 * Build the form object.
200 public function buildQuickForm() {
201 $this->assignToTemplate();
203 if ($this->_values
['event']['is_monetary'] &&
204 ($this->_params
[0]['amount'] ||
$this->_params
[0]['amount'] == 0)
206 $this->_amount
= array();
209 foreach ($this->_params
as $k => $v) {
210 $individualTaxAmount = 0;
211 //display tax amount on confirmation page
212 $taxAmount +
= $v['tax_amount'];
218 if (isset($v['billing_' . $name]) &&
221 $v[$name] = $v['billing_' . $name];
225 if (!empty($v['first_name']) && !empty($v['last_name'])) {
226 $append = $v['first_name'] . ' ' . $v['last_name'];
229 //use an email if we have one
230 foreach ($v as $v_key => $v_val) {
231 if (substr($v_key, 0, 6) == 'email-') {
232 $append = $v[$v_key];
237 $this->_amount
[$k]['amount'] = $v['amount'];
238 if (!empty($v['discountAmount'])) {
239 $this->_amount
[$k]['amount'] -= $v['discountAmount'];
242 $this->_amount
[$k]['label'] = preg_replace('/\ 1/', '', $v['amount_level']) . ' - ' . $append;
243 $this->_part
[$k]['info'] = CRM_Utils_Array
::value('first_name', $v) . ' ' . CRM_Utils_Array
::value('last_name', $v);
244 if (empty($v['first_name'])) {
245 $this->_part
[$k]['info'] = $append;
249 $individual[$k]['totalAmtWithTax'] = $this->_amount
[$k]['amount'];
250 $individual[$k]['totalTaxAmt'] = $individualTaxAmount +
$v['tax_amount'];
251 $this->_totalAmount
= $this->_totalAmount +
$this->_amount
[$k]['amount'];
252 if (!empty($v['is_primary'])) {
253 $this->set('primaryParticipantAmount', $this->_amount
[$k]['amount']);
258 $invoiceSettings = CRM_Core_BAO_Setting
::getItem(CRM_Core_BAO_Setting
::CONTRIBUTE_PREFERENCES_NAME
, 'contribution_invoice_settings');
259 $taxTerm = CRM_Utils_Array
::value('tax_term', $invoiceSettings);
260 $invoicing = CRM_Utils_Array
::value('invoicing', $invoiceSettings);
262 $this->assign('totalTaxAmount', $taxAmount);
263 $this->assign('taxTerm', $taxTerm);
264 $this->assign('individual', $individual);
265 $this->set('individual', $individual);
268 $this->assign('part', $this->_part
);
269 $this->set('part', $this->_part
);
270 $this->assign('amounts', $this->_amount
);
271 $this->assign('totalAmount', $this->_totalAmount
);
272 $this->set('totalAmount', $this->_totalAmount
);
275 if ($this->_priceSetId
&& !CRM_Core_DAO
::getFieldValue('CRM_Price_DAO_PriceSet', $this->_priceSetId
, 'is_quick_config')) {
276 $lineItemForTemplate = array();
277 $getTaxDetails = FALSE;
278 if (!empty($this->_lineItem
) && is_array($this->_lineItem
)) {
279 foreach ($this->_lineItem
as $key => $value) {
280 if (!empty($value)) {
281 $lineItemForTemplate[$key] = $value;
284 foreach ($value as $v) {
285 if (isset($v['tax_rate'])) {
286 $getTaxDetails = TRUE;
292 if (!empty($lineItemForTemplate)) {
293 $this->assign('lineItem', $lineItemForTemplate);
295 $this->assign('getTaxDetails', $getTaxDetails);
298 //display additional participants profile.
299 self
::assignProfiles($this);
301 //consider total amount.
302 $this->assign('isAmountzero', ($this->_totalAmount
<= 0) ?
TRUE : FALSE);
304 // @todo this needs to GO! We are getting rid of references to processor types in the code base in favour of
305 // over-ride-able functions on them.
306 // The processor effectively has a 'buildForm' hook it can use if it needs to.
307 // The tricky thing is that we have no way of testing this code out - perhaps it hasn't worked for years!
308 if ($this->_paymentProcessor
['payment_processor_type'] == 'Google_Checkout' && empty($this->_params
[0]['is_pay_later']) && !($this->_params
[0]['amount'] == 0) &&
309 !$this->_allowWaitlist
&& !$this->_requireApproval
311 $this->_checkoutButtonName
= $this->getButtonName('next', 'checkout');
313 $this->_checkoutButtonName
,
314 $this->_paymentProcessor
['url_button'],
315 array('class' => 'crm-form-submit')
318 $this->addButtons(array(
321 'name' => ts('Go Back'),
327 $contribButton = ts('Continue');
328 $this->addButtons(array(
331 'name' => ts('Go Back'),
335 'name' => $contribButton,
337 'js' => array('onclick' => "return submitOnce(this,'" . $this->_name
. "','" . ts('Processing') . "');"),
345 if (!empty($this->_fields
)) {
346 foreach ($this->_fields
as $name => $dontCare) {
350 $fields["billing_state_province-{$this->_bltID}"] = $fields["billing_country-{$this->_bltID}"] = $fields["email-{$this->_bltID}"] = 1;
351 foreach ($fields as $name => $dontCare) {
352 if (isset($this->_params
[0][$name])) {
353 $defaults[$name] = $this->_params
[0][$name];
354 if (substr($name, 0, 7) == 'custom_') {
355 $timeField = "{$name}_time";
356 if (isset($this->_params
[0][$timeField])) {
357 $defaults[$timeField] = $this->_params
[0][$timeField];
359 if (isset($this->_params
[0]["{$name}_id"])) {
360 $defaults["{$name}_id"] = $this->_params
[0]["{$name}_id"];
363 elseif (in_array($name, CRM_Contact_BAO_Contact
::$_greetingTypes)
364 && !empty($this->_params
[0][$name . '_custom'])
366 $defaults[$name . '_custom'] = $this->_params
[0][$name . '_custom'];
371 $this->setDefaults($defaults);
374 //lets give meaningful status message, CRM-4320.
375 $this->assign('isOnWaitlist', $this->_allowWaitlist
);
376 $this->assign('isRequireApproval', $this->_requireApproval
);
378 // Assign Participant Count to Lineitem Table
379 $this->assign('pricesetFieldsCount', CRM_Price_BAO_PriceSet
::getPricesetCount($this->_priceSetId
));
380 $this->addFormRule(array('CRM_Event_Form_Registration_Confirm', 'formRule'), $this);
386 * @param array $fields
387 * @param array $files
388 * @param CRM_Core_Form $self
392 public static function formRule($fields, $files, $self) {
394 $eventFull = CRM_Event_BAO_Participant
::eventFull($self->_eventId
, FALSE, CRM_Utils_Array
::value('has_waitlist', $self->_values
['event']));
395 if ($eventFull && empty($self->_allowConfirmation
)) {
396 if (empty($self->_allowWaitlist
)) {
397 CRM_Utils_System
::redirect(CRM_Utils_System
::url('civicrm/event/register', "reset=1&id={$self->_eventId}", FALSE, NULL, FALSE, TRUE));
400 $self->_feeBlock
= $self->_values
['fee'];
401 CRM_Event_Form_Registration_Register
::formatFieldsForOptionFull($self);
403 if (!empty($self->_priceSetId
) &&
404 !$self->_requireApproval
&& !$self->_allowWaitlist
406 $priceSetErrors = self
::validatePriceSet($self, $self->_params
);
407 if (!empty($priceSetErrors)) {
408 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');
409 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');
410 CRM_Utils_System
::redirect(CRM_Utils_System
::url('civicrm/event/register', "_qf_Register_display=true&qfKey={$fields['qfKey']}"));
414 return empty($priceSetErrors) ?
TRUE : $priceSetErrors;
418 * Process the form submission.
420 public function postProcess() {
421 $now = date('YmdHis');
423 $this->_params
= $this->get('params');
424 if (!empty($this->_params
[0]['contact_id'])) {
425 // unclear when this would be set & whether it could be checked in getContactID.
426 // perhaps it relates to when cid is in the url
427 //@todo someone who knows add comments on the various contactIDs in this form
428 $contactID = $this->_params
[0]['contact_id'];
431 $contactID = $this->getContactID();
434 // if a discount has been applied, lets now deduct it from the amount
435 // and fix the fee level
436 if (!empty($this->_params
[0]['discount']) && !empty($this->_params
[0]['discount']['applied'])) {
437 foreach ($this->_params
as $k => $v) {
438 if (CRM_Utils_Array
::value('amount', $this->_params
[$k]) > 0 && !empty($this->_params
[$k]['discountAmount'])) {
439 $this->_params
[$k]['amount'] -= $this->_params
[$k]['discountAmount'];
440 $this->_params
[$k]['amount_level'] .= CRM_Utils_Array
::value('discountMessage', $this->_params
[$k]);
443 $this->set('params', $this->_params
);
446 // CRM-4320, lets build array of cancelled additional participant ids
447 // those are drop or skip by primary at the time of confirmation.
448 // get all in and then unset those we want to process.
449 $cancelledIds = $this->_additionalParticipantIds
;
451 $params = $this->_params
;
452 if ($this->_values
['event']['is_monetary']) {
453 $this->set('finalAmount', $this->_amount
);
455 $participantCount = array();
457 //unset the skip participant from params.
458 //build the $participantCount array.
459 //maintain record for all participants.
460 foreach ($params as $participantNum => $record) {
461 if ($record == 'skip') {
462 unset($params[$participantNum]);
463 $participantCount[$participantNum] = 'skip';
465 elseif ($participantNum) {
466 $participantCount[$participantNum] = 'participant';
469 //lets get additional participant id to cancel.
470 if ($this->_allowConfirmation
&& is_array($cancelledIds)) {
471 $additonalId = CRM_Utils_Array
::value('participant_id', $record);
472 if ($additonalId && $key = array_search($additonalId, $cancelledIds)) {
473 unset($cancelledIds[$key]);
478 $payment = $registerByID = $primaryCurrencyID = $contribution = NULL;
479 $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.');
481 $this->participantIDS
= array();
483 foreach ($params as $key => $value) {
484 CRM_Event_Form_Registration_Confirm
::fixLocationFields($value, $fields, $this);
485 //unset the billing parameters if it is pay later mode
486 //to avoid creation of billing location
487 // @todo - the reasoning for this is unclear - elsewhere we check what fields are provided by
488 // the form & if billing fields exist we create the address, relying on the form to collect
489 // only information we intend to store.
490 if ($this->_allowWaitlist
491 ||
$this->_requireApproval
492 ||
(!empty($value['is_pay_later']) && !$this->_isBillingAddressRequiredForPayLater
)
493 ||
empty($value['is_primary'])
495 $billingFields = array(
496 "email-{$this->_bltID}",
497 'billing_first_name',
498 'billing_middle_name',
500 "billing_street_address-{$this->_bltID}",
501 "billing_city-{$this->_bltID}",
502 "billing_state_province-{$this->_bltID}",
503 "billing_state_province_id-{$this->_bltID}",
504 "billing_postal_code-{$this->_bltID}",
505 "billing_country-{$this->_bltID}",
506 "billing_country_id-{$this->_bltID}",
507 "address_name-{$this->_bltID}",
509 foreach ($billingFields as $field) {
510 unset($value[$field]);
512 if (!empty($value['is_pay_later'])) {
513 $this->_values
['params']['is_pay_later'] = TRUE;
517 //Unset ContactID for additional participants and set RegisterBy Id.
518 if (empty($value['is_primary'])) {
519 $contactID = CRM_Utils_Array
::value('contact_id', $value);
520 $registerByID = $this->get('registerByID');
522 $value['registered_by_id'] = $registerByID;
526 $value['amount'] = $this->_totalAmount
;
529 $contactID = CRM_Event_Form_Registration_Confirm
::updateContactFields($contactID, $value, $fields, $this);
531 // lets store the contactID in the session
532 // we dont store in userID in case the user is doing multiple
534 // for things like tell a friend
535 if (!$this->getContactID() && !empty($value['is_primary'])) {
536 $session = CRM_Core_Session
::singleton();
537 $session->set('transaction.userID', $contactID);
540 $value['description'] = ts('Online Event Registration') . ': ' . $this->_values
['event']['title'];
541 $value['accountingCode'] = CRM_Utils_Array
::value('accountingCode',
542 $this->_values
['event']
546 if ($this->_allowWaitlist ||
$this->_requireApproval
) {
547 //get the participant statuses.
548 $waitingStatuses = CRM_Event_PseudoConstant
::participantStatus(NULL, "class = 'Waiting'");
549 if ($this->_allowWaitlist
) {
550 $value['participant_status_id'] = $value['participant_status'] = array_search('On waitlist', $waitingStatuses);
553 $value['participant_status_id'] = $value['participant_status'] = array_search('Awaiting approval', $waitingStatuses);
556 //there might be case user seleted pay later and
557 //now becomes part of run time waiting list.
558 $value['is_pay_later'] = FALSE;
561 // required only if paid event
562 if ($this->_values
['event']['is_monetary'] && !($this->_allowWaitlist ||
$this->_requireApproval
)) {
563 if (is_array($this->_paymentProcessor
)) {
564 $payment = $this->_paymentProcessor
['object'];
566 if (!empty($this->_paymentProcessor
) && $this->_paymentProcessor
['object']->supports('preApproval')) {
567 $preApprovalParams = $this->_paymentProcessor
['object']->getPreApprovalDetails($this->get('pre_approval_parameters'));
568 $value = array_merge($value, $preApprovalParams);
572 if (!empty($value['is_pay_later']) ||
573 $value['amount'] == 0 ||
574 // The concept of contributeMode is deprecated.
575 $this->_contributeMode
== 'checkout' ||
576 $this->_contributeMode
== 'notify'
578 if ($value['amount'] != 0) {
580 //get the participant statuses.
581 $pendingStatuses = CRM_Event_PseudoConstant
::participantStatus(NULL, "class = 'Pending'");
582 $status = !empty($value['is_pay_later']) ?
'Pending from pay later' : 'Pending from incomplete transaction';
583 $value['participant_status_id'] = $value['participant_status'] = array_search($status, $pendingStatuses);
586 elseif (!empty($value['is_primary'])) {
587 CRM_Core_Payment_Form
::mapParams($this->_bltID
, $value, $value, TRUE);
588 // payment email param can be empty for _bltID mapping
589 // thus provide mapping for it with a different email value
590 if (empty($value['email'])) {
591 $value['email'] = CRM_Utils_Array
::valueByRegexKey('/^email-/', $value);
594 if (is_object($payment)) {
596 $result = $payment->doPayment($value);
597 $value = array_merge($value, $result);
599 catch (\Civi\Payment\Exception\PaymentProcessorException
$e) {
600 CRM_Core_Session
::singleton()->setStatus($e->getMessage());
601 CRM_Utils_System
::redirect(CRM_Utils_System
::url('civicrm/event/register', "id={$this->_eventId}"));
605 CRM_Core_Error
::fatal($paymentObjError);
609 $value['receive_date'] = $now;
610 if ($this->_allowConfirmation
) {
611 $value['participant_register_date'] = $this->_values
['participant']['register_date'];
614 $createContrib = ($value['amount'] != 0) ?
TRUE : FALSE;
615 // force to create zero amount contribution, CRM-5095
616 if (!$createContrib && ($value['amount'] == 0)
617 && $this->_priceSetId
&& $this->_lineItem
619 $createContrib = TRUE;
622 if ($createContrib && !empty($value['is_primary']) &&
623 !$this->_allowWaitlist
&& !$this->_requireApproval
625 // if paid event add a contribution record
626 //if primary participant contributing additional amount
627 //append (multiple participants) to its fee level. CRM-4196.
628 $isAdditionalAmount = FALSE;
629 if (count($params) > 1) {
630 $isAdditionalAmount = TRUE;
633 //passing contribution id is already registered.
634 $contribution = self
::processContribution($this, $value, $result, $contactID, $pending, $isAdditionalAmount);
635 $value['contributionID'] = $contribution->id
;
636 $value['contributionTypeID'] = $contribution->financial_type_id
;
637 $value['receive_date'] = $contribution->receive_date
;
638 $value['trxn_id'] = $contribution->trxn_id
;
639 $value['contributionID'] = $contribution->id
;
640 $value['contributionTypeID'] = $contribution->financial_type_id
;
642 $value['contactID'] = $contactID;
643 $value['eventID'] = $this->_eventId
;
644 $value['item_name'] = $value['description'];
647 if (!empty($value['contributionID'])) {
648 $this->_values
['contributionId'] = $value['contributionID'];
652 if (!empty($value['is_primary'])) {
653 $primaryCurrencyID = CRM_Utils_Array
::value('currencyID', $value);
655 if (empty($value['currencyID'])) {
656 $value['currencyID'] = $primaryCurrencyID;
659 // CRM-11182 - Confirmation page might not be monetary
660 if ($this->_values
['event']['is_monetary']) {
661 if (!$pending && !empty($value['is_primary']) &&
662 !$this->_allowWaitlist
&& !$this->_requireApproval
664 // transactionID & receive date required while building email template
665 $this->assign('trxn_id', $value['trxn_id']);
666 $this->assign('receive_date', CRM_Utils_Date
::mysqlToIso($value['receive_date']));
667 $this->set('receiveDate', CRM_Utils_Date
::mysqlToIso($value['receive_date']));
668 $this->set('trxnId', CRM_Utils_Array
::value('trxn_id', $value));
672 $value['fee_amount'] = CRM_Utils_Array
::value('amount', $value);
673 $this->set('value', $value);
675 // handle register date CRM-4320
676 if ($this->_allowConfirmation
) {
677 $registerDate = CRM_Utils_Array
::value('participant_register_date', $params);
679 elseif (!empty($params['participant_register_date']) &&
680 is_array($params['participant_register_date']) &&
681 !empty($params['participant_register_date'])
683 $registerDate = CRM_Utils_Date
::format($params['participant_register_date']);
686 $registerDate = date('YmdHis');
688 $this->assign('register_date', $registerDate);
690 $this->confirmPostProcess($contactID, $contribution, $payment);
693 //handle if no additional participant.
694 if (!$registerByID) {
695 $registerByID = $this->get('registerByID');
698 $this->set('participantIDs', $this->_participantIDS
);
700 // create line items, CRM-5313
701 if ($this->_priceSetId
&&
702 !empty($this->_lineItem
)
704 // take all processed participant ids.
705 $allParticipantIds = $this->_participantIDS
;
707 // when participant re-walk wizard.
708 if ($this->_allowConfirmation
&&
709 !empty($this->_additionalParticipantIds
)
711 $allParticipantIds = array_merge(array($registerByID), $this->_additionalParticipantIds
);
714 $entityTable = 'civicrm_participant';
715 $invoiceSettings = CRM_Core_BAO_Setting
::getItem(CRM_Core_BAO_Setting
::CONTRIBUTE_PREFERENCES_NAME
, 'contribution_invoice_settings');
716 $invoicing = CRM_Utils_Array
::value('invoicing', $invoiceSettings);
718 $dataArray = array();
719 foreach ($this->_lineItem
as $key => $value) {
720 if (($value != 'skip') &&
721 ($entityId = CRM_Utils_Array
::value($key, $allParticipantIds))
724 // do cleanup line items if participant re-walking wizard.
725 if ($this->_allowConfirmation
) {
726 CRM_Price_BAO_LineItem
::deleteLineItems($entityId, $entityTable);
728 $lineItem[$this->_priceSetId
] = $value;
729 CRM_Price_BAO_LineItem
::processPriceSet($entityId, $lineItem, $contribution, $entityTable);
732 foreach ($value as $line) {
733 if (isset($line['tax_amount']) && isset($line['tax_rate'])) {
734 $totalTaxAmount = $line['tax_amount'] +
$totalTaxAmount;
735 if (isset($dataArray[$line['tax_rate']])) {
736 $dataArray[$line['tax_rate']] = $dataArray[$line['tax_rate']] + CRM_Utils_Array
::value('tax_amount', $line);
739 $dataArray[$line['tax_rate']] = CRM_Utils_Array
::value('tax_amount', $line);
746 $this->assign('dataArray', $dataArray);
747 $this->assign('totalTaxAmount', $totalTaxAmount);
751 //update status and send mail to cancelled additional participants, CRM-4320
752 if ($this->_allowConfirmation
&& is_array($cancelledIds) && !empty($cancelledIds)) {
753 $cancelledId = array_search('Cancelled',
754 CRM_Event_PseudoConstant
::participantStatus(NULL, "class = 'Negative'")
756 CRM_Event_BAO_Participant
::transitionParticipants($cancelledIds, $cancelledId);
760 if ($this->_action
& CRM_Core_Action
::PREVIEW
) {
764 // for Transfer checkout.
765 // The concept of contributeMode is deprecated.
766 if (($this->_contributeMode
== 'checkout' ||
767 $this->_contributeMode
== 'notify'
768 ) && empty($params[0]['is_pay_later']) &&
769 !$this->_allowWaitlist
&& !$this->_requireApproval
&&
770 $this->_totalAmount
> 0
773 $primaryParticipant = $this->get('primaryParticipant');
775 if (empty($primaryParticipant['participantID'])) {
776 $primaryParticipant['participantID'] = $registerByID;
779 //build an array of custom profile and assigning it to template
780 $customProfile = CRM_Event_BAO_Event
::buildCustomProfile($registerByID, $this->_values
, NULL, $isTest);
781 if (count($customProfile)) {
782 $this->assign('customProfile', $customProfile);
783 $this->set('customProfile', $customProfile);
786 // do a transfer only if a monetary payment greater than 0
787 if ($this->_values
['event']['is_monetary'] && $primaryParticipant) {
788 if ($payment && is_object($payment)) {
789 //CRM 14512 provide line items of all participants to payment gateway
790 $primaryContactId = $this->get('primaryContactId');
792 //build an array of cId/pId of participants
793 $additionalIDs = CRM_Event_BAO_Event
::buildCustomProfile($registerByID, NULL, $primaryContactId, $isTest, TRUE);
795 //need to copy, since we are unsetting on the way.
796 $copyParticipantCountLines = $participantCount;
798 //lets carry all participant params w/ values.
799 foreach ($additionalIDs as $participantID => $contactId) {
800 $participantNum = NULL;
801 $participantNum = $participantID;
802 if ($participantID == $registerByID) {
803 // This is the is primary participant.
807 if ($participantNum = array_search('participant', $copyParticipantCountLines)) {
808 //if no participant found break.
809 if ($participantNum === NULL) {
812 //unset current particpant so we don't check them again
813 unset($copyParticipantCountLines[$participantNum]);
816 // get values of line items
817 if ($this->_amount
) {
819 $amount[$participantNum]['label'] = preg_replace('/\ 1/', '', $params[$participantNum]['amount_level']);
820 $amount[$participantNum]['amount'] = $params[$participantNum]['amount'];
821 $params[$participantNum]['amounts'] = $amount;
824 if (!empty($this->_lineItem
)) {
825 $lineItems = $this->_lineItem
;
827 if ($lineItemValue = CRM_Utils_Array
::value($participantNum, $lineItems)) {
828 $lineItem[] = $lineItemValue;
830 $params[$participantNum]['lineItem'] = $lineItem;
833 //only add additional particpants and not the primary particpant as we already have that
834 //added to $primaryParticipant so that this change doesn't break or require changes to
835 //existing gateway implementations
836 $primaryParticipant['participants_info'][$participantID] = $params[$participantNum];
839 //get event custom field information
840 $groupTree = CRM_Core_BAO_CustomGroup
::getTree('Event', $this, $this->_eventId
, 0, $this->_values
['event']['event_type_id']);
841 $primaryParticipant['eventCustomFields'] = $groupTree;
843 // call postprocess hook before leaving
844 $this->postProcessHook();
845 // this does not return
846 $payment->doPayment($primaryParticipant, 'event');
849 CRM_Core_Error
::fatal($paymentObjError);
854 //otherwise send mail Confirmation/Receipt
855 $primaryContactId = $this->get('primaryContactId');
857 //build an array of cId/pId of participants
858 $additionalIDs = CRM_Event_BAO_Event
::buildCustomProfile($registerByID,
859 NULL, $primaryContactId, $isTest,
862 //lets send mails to all with meaningful text, CRM-4320.
863 $this->assign('isOnWaitlist', $this->_allowWaitlist
);
864 $this->assign('isRequireApproval', $this->_requireApproval
);
866 //need to copy, since we are unsetting on the way.
867 $copyParticipantCount = $participantCount;
869 //lets carry all paticipant params w/ values.
870 foreach ($additionalIDs as $participantID => $contactId) {
871 $participantNum = NULL;
872 if ($participantID == $registerByID) {
876 if ($participantNum = array_search('participant', $copyParticipantCount)) {
877 unset($copyParticipantCount[$participantNum]);
880 if ($participantNum === NULL) {
884 //carry the participant submitted values.
885 $this->_values
['params'][$participantID] = $params[$participantNum];
888 foreach ($additionalIDs as $participantID => $contactId) {
890 if ($participantID == $registerByID) {
891 //set as Primary Participant
892 $this->assign('isPrimary', 1);
893 //build an array of custom profile and assigning it to template.
894 $customProfile = CRM_Event_BAO_Event
::buildCustomProfile($participantID, $this->_values
, NULL, $isTest);
896 if (count($customProfile)) {
897 $this->assign('customProfile', $customProfile);
898 $this->set('customProfile', $customProfile);
900 $this->_values
['params']['additionalParticipant'] = FALSE;
903 //take the Additional participant number.
904 if ($participantNum = array_search('participant', $participantCount)) {
905 unset($participantCount[$participantNum]);
907 $this->assign('isPrimary', 0);
908 $this->assign('customProfile', NULL);
909 //Additional Participant should get only it's payment information
910 if (!empty($this->_amount
)) {
912 $params = $this->get('params');
913 $amount[$participantNum]['label'] = preg_replace('/\ 1/', '', $params[$participantNum]['amount_level']);
914 $amount[$participantNum]['amount'] = $params[$participantNum]['amount'];
915 $this->assign('amounts', $amount);
917 if ($this->_lineItem
) {
918 $lineItems = $this->_lineItem
;
920 if ($lineItemValue = CRM_Utils_Array
::value($participantNum, $lineItems)) {
921 $lineItem[] = $lineItemValue;
924 $individual = $this->get('individual');
925 $dataArray[key($dataArray)] = $individual[$participantNum]['totalTaxAmt'];
926 $this->assign('dataArray', $dataArray);
927 $this->assign('totalAmount', $individual[$participantNum]['totalAmtWithTax']);
928 $this->assign('totalTaxAmount', $individual[$participantNum]['totalTaxAmt']);
929 $this->assign('individual', array($individual[$participantNum]));
931 $this->assign('lineItem', $lineItem);
933 $this->_values
['params']['additionalParticipant'] = TRUE;
934 $this->assign('isAdditionalParticipant', $this->_values
['params']['additionalParticipant']);
937 //pass these variables since these are run time calculated.
938 $this->_values
['params']['isOnWaitlist'] = $this->_allowWaitlist
;
939 $this->_values
['params']['isRequireApproval'] = $this->_requireApproval
;
941 //send mail to primary as well as additional participants.
942 $this->assign('contactID', $contactId);
943 $this->assign('participantID', $participantID);
944 CRM_Event_BAO_Event
::sendMail($contactId, $this->_values
, $participantID, $isTest);
950 * Process the contribution.
952 * @param CRM_Core_Form $form
953 * @param array $params
954 * @param array $result
955 * @param int $contactID
956 * @param bool $pending
957 * @param bool $isAdditionalAmount
959 * @return \CRM_Contribute_BAO_Contribution
961 public static function processContribution(
962 &$form, $params, $result, $contactID,
963 $pending = FALSE, $isAdditionalAmount = FALSE
965 $transaction = new CRM_Core_Transaction();
967 $now = date('YmdHis');
970 if (!empty($form->_values
['event']['is_email_confirm'])) {
974 if ($isAdditionalAmount) {
975 $params['amount_level'] = $params['amount_level'] . ts(' (multiple participants)') . CRM_Core_DAO
::VALUE_SEPARATOR
;
978 $contribParams = array(
979 'contact_id' => $contactID,
980 'financial_type_id' => !empty($form->_values
['event']['financial_type_id']) ?
$form->_values
['event']['financial_type_id'] : $params['financial_type_id'],
981 'receive_date' => $now,
982 'total_amount' => $params['amount'],
983 'tax_amount' => $params['tax_amount'],
984 'amount_level' => $params['amount_level'],
985 'invoice_id' => $params['invoiceID'],
986 'currency' => $params['currencyID'],
987 'source' => !empty($params['participant_source']) ?
$params['participant_source'] : $params['description'],
988 'is_pay_later' => CRM_Utils_Array
::value('is_pay_later', $params, 0),
989 'campaign_id' => CRM_Utils_Array
::value('campaign_id', $params),
992 if (empty($params['is_pay_later'])) {
993 $contribParams['payment_instrument_id'] = 1;
996 if (!$pending && $result) {
997 $contribParams +
= array(
998 'fee_amount' => CRM_Utils_Array
::value('fee_amount', $result),
999 'net_amount' => CRM_Utils_Array
::value('net_amount', $result, $params['amount']),
1000 'trxn_id' => $result['trxn_id'],
1001 'receipt_date' => $receiptDate,
1005 $allStatuses = CRM_Contribute_PseudoConstant
::contributionStatus(NULL, 'name');
1006 $contribParams['contribution_status_id'] = array_search('Completed', $allStatuses);
1008 $contribParams['contribution_status_id'] = array_search('Pending', $allStatuses);
1011 $contribParams['is_test'] = 0;
1012 if ($form->_action
& CRM_Core_Action
::PREVIEW || CRM_Utils_Array
::value('mode', $params) == 'test') {
1013 $contribParams['is_test'] = 1;
1017 if (!empty($contribParams['invoice_id'])) {
1018 $contribID = CRM_Core_DAO
::getFieldValue('CRM_Contribute_DAO_Contribution',
1019 $contribParams['invoice_id'],
1027 $ids['contribution'] = $contribID;
1028 $contribParams['id'] = $contribID;
1031 //create an contribution address
1032 // The concept of contributeMode is deprecated. Elsewhere we use the function processBillingAddress() - although
1033 // currently that is only inherited by back-office forms.
1034 if ($form->_contributeMode
!= 'notify' && empty($params['is_pay_later'])) {
1035 $contribParams['address_id'] = CRM_Contribute_BAO_Contribution
::createAddress($params, $form->_bltID
);
1038 $contribParams['payment_processor'] = CRM_Utils_Array
::value('payment_processor', $params);
1039 $contribParams['skipLineItem'] = 1;
1040 // create contribution record
1041 $contribution = CRM_Contribute_BAO_Contribution
::add($contribParams, $ids);
1043 CRM_Event_BAO_Participant
::createDiscountTrxn($form->_eventId
, $contribParams, CRM_Utils_Array
::value('amount_priceset_level_radio', $params, NULL));
1045 // process soft credit / pcp pages
1046 if (!empty($params['pcp_made_through_id'])) {
1047 CRM_Contribute_Form_Contribution_Confirm
::formatSoftCreditParams($params, $form);
1048 CRM_Contribute_BAO_ContributionSoft
::processSoftContribution($params, $contribution);
1051 $transaction->commit();
1053 return $contribution;
1057 * Fix the Location Fields.
1059 * @param array $params
1060 * @param array $fields
1061 * @param CRM_Core_Form $form
1063 public static function fixLocationFields(&$params, &$fields, &$form) {
1064 if (!empty($form->_fields
)) {
1065 foreach ($form->_fields
as $name => $dontCare) {
1070 if (is_array($fields)) {
1071 if (!array_key_exists('first_name', $fields)) {
1072 $nameFields = array('first_name', 'middle_name', 'last_name');
1073 foreach ($nameFields as $name) {
1075 if (array_key_exists("billing_$name", $params)) {
1076 $params[$name] = $params["billing_{$name}"];
1077 $params['preserveDBName'] = TRUE;
1083 // also add location name to the array
1084 if ($form->_values
['event']['is_monetary']) {
1085 $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);
1086 $fields["address_name-{$form->_bltID}"] = 1;
1088 $fields["email-{$form->_bltID}"] = 1;
1089 $fields['email-Primary'] = 1;
1091 //if its pay later or additional participant set email address as primary.
1092 if ((!empty($params['is_pay_later']) ||
empty($params['is_primary']) ||
1093 !$form->_values
['event']['is_monetary'] ||
1094 $form->_allowWaitlist ||
1095 $form->_requireApproval
1096 ) && !empty($params["email-{$form->_bltID}"])
1098 $params['email-Primary'] = $params["email-{$form->_bltID}"];
1103 * Update contact fields.
1105 * @param int $contactID
1106 * @param array $params
1107 * @param array $fields
1108 * @param CRM_Core_Form $form
1112 public static function updateContactFields($contactID, $params, $fields, &$form) {
1113 //add the contact to group, if add to group is selected for a
1114 //particular uf group
1116 // get the add to groups
1117 $addToGroups = array();
1119 if (!empty($form->_fields
)) {
1120 foreach ($form->_fields
as $key => $value) {
1121 if (!empty($value['add_to_group_id'])) {
1122 $addToGroups[$value['add_to_group_id']] = $value['add_to_group_id'];
1127 // check for profile double opt-in and get groups to be subscribed
1128 $subscribeGroupIds = CRM_Core_BAO_UFGroup
::getDoubleOptInGroupIds($params, $contactID);
1130 foreach ($addToGroups as $k) {
1131 if (array_key_exists($k, $subscribeGroupIds)) {
1132 unset($addToGroups[$k]);
1136 // since we are directly adding contact to group lets unset it from mailing
1137 if (!empty($addToGroups)) {
1138 foreach ($addToGroups as $groupId) {
1139 if (isset($subscribeGroupIds[$groupId])) {
1140 unset($subscribeGroupIds[$groupId]);
1145 $ctype = CRM_Core_DAO
::getFieldValue(
1146 'CRM_Contact_DAO_Contact',
1151 if (array_key_exists('contact_id', $params) && empty($params['contact_id'])) {
1152 // we unset this here because the downstream function ignores the contactID we give it
1153 // if it is set & it is difficult to understand the implications of 'fixing' this downstream
1154 // but if we are passing a contact id into this function it's reasonable to assume we don't
1156 unset($params['contact_id']);
1159 $contactID = CRM_Contact_BAO_Contact
::createProfileContact(
1171 foreach (CRM_Contact_BAO_Contact
::$_greetingTypes as $greeting) {
1172 if (!isset($params[$greeting . '_id'])) {
1173 $params[$greeting . '_id'] = CRM_Contact_BAO_Contact_Utils
::defaultGreeting('Individual', $greeting);
1177 $contactID = CRM_Contact_BAO_Contact
::createProfileContact($params,
1185 $form->set('contactID', $contactID);
1188 //get email primary first if exist
1189 $subscribtionEmail = array('email' => CRM_Utils_Array
::value('email-Primary', $params));
1190 if (!$subscribtionEmail['email']) {
1191 $subscribtionEmail['email'] = CRM_Utils_Array
::value("email-{$form->_bltID}", $params);
1193 // subscribing contact to groups
1194 if (!empty($subscribeGroupIds) && $subscribtionEmail['email']) {
1195 CRM_Mailing_Event_BAO_Subscribe
::commonSubscribe($subscribeGroupIds, $subscribtionEmail, $contactID);
1204 * @param CRM_Core_Form $form
1206 public static function assignProfiles(&$form) {
1207 $participantParams = $form->_params
;
1208 $formattedValues = $profileFields = array();
1210 foreach ($participantParams as $participantNum => $participantValue) {
1211 if ($participantNum) {
1212 $prefix1 = 'additional';
1213 $prefix2 = 'additional_';
1219 if ($participantValue != 'skip') {
1220 //get the customPre profile info
1221 if (!empty($form->_values
[$prefix2 . 'custom_pre_id'])) {
1222 $values = $groupName = array();
1223 CRM_Event_BAO_Event
::displayProfile($participantValue,
1224 $form->_values
[$prefix2 . 'custom_pre_id'],
1230 if (count($values)) {
1231 $formattedValues[$count][$prefix1 . 'CustomPre'] = $values;
1233 $formattedValues[$count][$prefix1 . 'CustomPreGroupTitle'] = CRM_Utils_Array
::value('groupTitle', $groupName);
1235 //get the customPost profile info
1236 if (!empty($form->_values
[$prefix2 . 'custom_post_id'])) {
1237 $values = $groupName = array();
1238 foreach ($form->_values
[$prefix2 . 'custom_post_id'] as $gids) {
1240 CRM_Event_BAO_Event
::displayProfile($participantValue,
1246 $values[$gids] = $val;
1247 $groupName[$gids] = $group;
1250 if (count($values)) {
1251 $formattedValues[$count][$prefix1 . 'CustomPost'] = $values;
1254 if (isset($formattedValues[$count][$prefix1 . 'CustomPre'])) {
1255 $formattedValues[$count][$prefix1 . 'CustomPost'] = array_diff_assoc($formattedValues[$count][$prefix1 . 'CustomPost'],
1256 $formattedValues[$count][$prefix1 . 'CustomPre']
1260 $formattedValues[$count][$prefix1 . 'CustomPostGroupTitle'] = $groupName;
1264 $form->_fields
= $profileFields;
1266 if (!empty($formattedValues)) {
1267 $form->assign('primaryParticipantProfile', $formattedValues[1]);
1268 $form->set('primaryParticipantProfile', $formattedValues[1]);
1270 unset($formattedValues[1]);
1271 $form->assign('addParticipantProfile', $formattedValues);
1272 $form->set('addParticipantProfile', $formattedValues);