Fix js syntax error CRM-12149
[civicrm-core.git] / CRM / Event / Form / Registration / Register.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.3 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2013 |
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-2013
33 * $Id$
34 *
35 */
36
37/**
38 * This class generates form components for processing Event
39 *
40 */
41class CRM_Event_Form_Registration_Register extends CRM_Event_Form_Registration {
42
43 /**
44 * The fields involved in this page
45 *
46 */
47 public $_fields;
48
49 /**
50 * The defaults involved in this page
51 *
52 */
53 public $_defaults;
54
55 /**
56 * The status message that user view.
57 *
58 */
59 protected $_waitlistMsg = NULL;
60 protected $_requireApprovalMsg = NULL;
61
62 public $_quickConfig = NULL;
63
64 /**
65 * Allow deveopera to use hook_civicrm_buildForm()
66 * to override the registration dupe check
67 * CRM-7604
68 */
69 public $_skipDupeRegistrationCheck = FALSE;
70
7bf9cde2
CW
71 public $_ppType;
72 public $_snippet;
6a488035
TO
73
74 /**
75 * Function to set variables up before form is built
76 *
77 * @return void
78 * @access public
79 */
80 function preProcess() {
81 parent::preProcess();
7bf9cde2
CW
82
83 CRM_Contribute_Form_Contribution_Main::preProcessPaymentOptions($this);
84 if ($this->_snippet) {
85 return;
6a488035
TO
86 }
87
88 //CRM-4320.
89 //here we can't use parent $this->_allowWaitlist as user might
90 //walk back and we maight set this value in this postProcess.
91 //(we set when spaces < group count and want to allow become part of waiting )
92
93 $eventFull = CRM_Event_BAO_Participant::eventFull($this->_eventId, FALSE, CRM_Utils_Array::value('has_waitlist', $this->_values['event']));
94
95 $this->_allowWaitlist = FALSE;
96 if ($eventFull && !$this->_allowConfirmation &&
97 CRM_Utils_Array::value('has_waitlist', $this->_values['event'])
98 ) {
99 $this->_allowWaitlist = TRUE;
100 $this->_waitlistMsg = CRM_Utils_Array::value('waitlist_text', $this->_values['event']);
101 if (!$this->_waitlistMsg) {
102 $this->_waitlistMsg = ts('This event is currently full. However you can register now and get added to a waiting list. You will be notified if spaces become available.');
103 }
104 }
105 $this->set('allowWaitlist', $this->_allowWaitlist);
106
107 //To check if the user is already registered for the event(CRM-2426)
108 if (!$this->_skipDupeRegistrationCheck) {
109 self::checkRegistration(NULL, $this);
110 }
111
112 $this->assign('availableRegistrations', $this->_availableRegistrations);
113
114 // get the participant values from EventFees.php, CRM-4320
115 if ($this->_allowConfirmation) {
116 CRM_Event_Form_EventFees::preProcess($this);
117 }
6a488035
TO
118 }
119
120 /**
121 * This function sets the default values for the form. For edit/view mode
122 * the default values are retrieved from the database
c4c5b5fe 123 * Adding discussion from CRM-11915 as code comments
124 * When multiple payment processors are configured for a event and user does any selection changes for them on online event registeration page :
125 * The 'Register' page gets loaded through ajax and following happens :
126 * the setDefaults function is called with the variable _ppType set with selected payment processor type,
127 * so in the 'if' condition checked whether the selected payment processor's billing mode is of 'billing form mode'. If its not, don't setDefaults for billing form and return instead.
128 *- For payment processors of billing mode 'Notify' - return from setDefaults before the code for billing profile population execution .
129 * (done this is because for payment processors with 'Notify' mode billing profile form doesn't get rendered on UI)
6a488035
TO
130 *
131 * @access public
132 *
133 * @return None
134 */
135 function setDefaultValues() {
7bf9cde2 136 if ($this->_ppType && $this->_snippet && !($this->_paymentProcessor['billing_mode'] & CRM_Core_Payment::BILLING_MODE_FORM)) {
c4c5b5fe 137 // see function comment block for explanation of this
6a488035
TO
138 return;
139 }
140
141 $contactID = parent::getContactID();
142 if ($contactID) {
c4c5b5fe 143 //@todo CRM-11915 I observed that even when the billing block is not present the routine to retrieve the billing defaults is still called - which seems a bit redundant.
6a488035
TO
144 $names = array(
145 'first_name', 'middle_name', 'last_name',
146 "street_address-{$this->_bltID}", "city-{$this->_bltID}", "postal_code-{$this->_bltID}",
147 "country_id-{$this->_bltID}", "state_province_id-{$this->_bltID}",
148 );
149
150 foreach ($names as $name) {
151 $fields[$name] = 1;
152 }
153 $fields["state_province-{$this->_bltID}"] = 1;
154 $fields["country-{$this->_bltID}"] = 1;
155 $fields["email-{$this->_bltID}"] = 1;
156 $fields['email-Primary'] = 1;
157
158 CRM_Core_BAO_UFGroup::setProfileDefaults($contactID, $fields, $this->_defaults);
159
160 // use primary email address if billing email address is empty
161 if (empty($this->_defaults["email-{$this->_bltID}"]) &&
162 !empty($this->_defaults['email-Primary'])
163 ) {
164 $this->_defaults["email-{$this->_bltID}"] = $this->_defaults['email-Primary'];
165 }
166
167 foreach ($names as $name) {
168 if (isset($this->_defaults[$name])) {
169 $this->_defaults['billing_' . $name] = $this->_defaults[$name];
170 }
171 }
172 }
173 $config = CRM_Core_Config::singleton();
174 // set default country from config if no country set
175 if (!CRM_Utils_Array::value("billing_country_id-{$this->_bltID}", $this->_defaults)) {
176 $this->_defaults["billing_country_id-{$this->_bltID}"] = $config->defaultContactCountry;
177 }
178
179 // now fix all state country selectors
180 CRM_Core_BAO_Address::fixAllStateSelects($this, $this->_defaults);
181
ba0cb925 182 if ($this->_snippet) {
6a488035
TO
183 return $this->_defaults;
184 }
185
186 if ($contactID) {
187 $options = array();
188 $fields = array();
189
190 if (!empty($this->_fields)) {
191 $removeCustomFieldTypes = array('Participant');
192 foreach ($this->_fields as $name => $dontCare) {
193 if (substr($name, 0, 7) == 'custom_') {
194 $id = substr($name, 7);
195 if (!$this->_allowConfirmation &&
196 !CRM_Core_BAO_CustomGroup::checkCustomField($id, $removeCustomFieldTypes)
197 ) {
198 continue;
199 }
200 // ignore component fields
201 }
202 elseif ((substr($name, 0, 12) == 'participant_')) {
203 continue;
204 }
205 $fields[$name] = 1;
206 }
207 }
208 }
3feb567a
DL
209
210 if (!empty($fields)) {
211 CRM_Core_BAO_UFGroup::setProfileDefaults($contactID, $fields, $this->_defaults);
212 }
213
13ac605f
DG
214 // Set default payment processor as default payment_processor radio button value
215 if (!empty($this->_paymentProcessors)) {
216 foreach ($this->_paymentProcessors as $pid => $value) {
217 if (CRM_Utils_Array::value('is_default', $value)) {
218 $this->_defaults['payment_processor'] = $pid;
219 }
220 }
221 }
222
6a488035
TO
223 //if event is monetary and pay later is enabled and payment
224 //processor is not available then freeze the pay later checkbox with
225 //default check
226 if (CRM_Utils_Array::value('is_pay_later', $this->_values['event']) &&
227 !is_array($this->_paymentProcessor)
228 ) {
229 $this->_defaults['is_pay_later'] = 1;
230 }
231
232 //set custom field defaults
233 if (!empty($this->_fields)) {
234 //load default campaign from page.
235 if (array_key_exists('participant_campaign_id', $this->_fields)) {
236 $this->_defaults['participant_campaign_id'] = CRM_Utils_Array::value('campaign_id',
237 $this->_values['event']
238 );
239 }
240
241 foreach ($this->_fields as $name => $field) {
242 if ($customFieldID = CRM_Core_BAO_CustomField::getKeyID($name)) {
243 // fix for CRM-1743
244 if (!isset($this->_defaults[$name])) {
245 CRM_Core_BAO_CustomField::setProfileDefaults($customFieldID, $name, $this->_defaults,
246 NULL, CRM_Profile_Form::MODE_REGISTER
247 );
248 }
249 }
250 }
251 }
252
253 //fix for CRM-3088, default value for discount set.
254 $discountId = NULL;
255 if (!empty($this->_values['discount'])) {
256 $discountId = CRM_Core_BAO_Discount::findSet($this->_eventId, 'civicrm_event');
257 if ($discountId) {
258 if (isset($this->_values['event']['default_discount_fee_id'])) {
259 $discountKey = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_OptionValue',
260 $this->_values['event']['default_discount_fee_id'],
261 'weight', 'id'
262 );
263
264 $this->_defaults['amount'] = key(array_slice($this->_values['discount'][$discountId],
265 $discountKey - 1, $discountKey, TRUE
266 ));
267 }
268 }
269 }
270
271 // add this event's default participant role to defaults array
272 // (for cases where participant_role field is included in form via profile)
273 if ($this->_values['event']['default_role_id']) {
274 $this->_defaults['participant_role'] =
275 $this->_defaults['participant_role_id'] = $this->_values['event']['default_role_id'];
276 }
277 if ($this->_priceSetId && !empty($this->_feeBlock)) {
278 foreach ($this->_feeBlock as $key => $val) {
279 foreach ($val['options'] as $keys => $values) {
280 if ($values['is_default'] &&
281 !CRM_Utils_Array::value('is_full', $values)
282 ) {
283
284 if ($val['html_type'] == 'CheckBox') {
285 $this->_defaults["price_{$key}"][$keys] = 1;
286 }
287 else {
288 $this->_defaults["price_{$key}"] = $keys;
289 }
290 }
291 }
292 }
293 }
294
295 //set default participant fields, CRM-4320.
296 $hasAdditionalParticipants = FALSE;
297 if ($this->_allowConfirmation) {
298 $this->_contactId = $contactID;
299 $this->_discountId = $discountId;
300 $forcePayLater = CRM_Utils_Array::value('is_pay_later', $this->_defaults, FALSE);
301 $this->_defaults = array_merge($this->_defaults, CRM_Event_Form_EventFees::setDefaultValues($this));
302 $this->_defaults['is_pay_later'] = $forcePayLater;
303
304 if ($this->_additionalParticipantIds) {
305 $hasAdditionalParticipants = TRUE;
306 $this->_defaults['additional_participants'] = count($this->_additionalParticipantIds);
307 }
308 }
309 $this->assign('hasAdditionalParticipants', $hasAdditionalParticipants);
310
311 // //hack to simplify credit card entry for testing
312 // $this->_defaults['credit_card_type'] = 'Visa';
313 // $this->_defaults['credit_card_number'] = '4807731747657838';
314 // $this->_defaults['cvv2'] = '000';
315 // $this->_defaults['credit_card_exp_date'] = array( 'Y' => '2010', 'M' => '05' );
316
317 // to process Custom data that are appended to URL
318 $getDefaults = CRM_Core_BAO_CustomGroup::extractGetParams($this, "'Contact', 'Individual', 'Contribution', 'Participant'");
319 if (!empty($getDefaults)) {
320 $this->_defaults = array_merge($this->_defaults, $getDefaults);
321 }
322
323 return $this->_defaults;
324 }
325
326 /**
327 * Function to build the form
328 *
329 * @return None
330 * @access public
331 */
332 public function buildQuickForm() {
7bf9cde2 333 // Build payment processor form
6a488035 334 if ($this->_ppType) {
7bf9cde2
CW
335 CRM_Core_Payment_ProcessorForm::buildQuickForm($this);
336 // Return if we are in an ajax callback
337 if ($this->_snippet) {
338 return;
339 }
6a488035
TO
340 }
341
342 $contactID = parent::getContactID();
343 $this->assign('contact_id', $contactID);
178073d6 344 $this->assign('display_name', CRM_Contact_BAO_Contact::displayName($contactID));
6a488035
TO
345
346 $config = CRM_Core_Config::singleton();
347 $this->add('hidden', 'scriptFee', NULL);
348 $this->add('hidden', 'scriptArray', NULL);
349
350 $bypassPayment = $allowGroupOnWaitlist = $isAdditionalParticipants = FALSE;
351 if ($this->_values['event']['is_multiple_registrations']) {
352 // don't allow to add additional during confirmation if not preregistered.
353 if (!$this->_allowConfirmation || $this->_additionalParticipantIds) {
354 // Hardcode maximum number of additional participants here for now. May need to make this configurable per event.
355 // Label is value + 1, since the code sees this is ADDITIONAL participants (in addition to "self")
356 $additionalOptions = array('' => ts('1'), 1 => ts('2'), 2 => ts('3'), 3 => ts('4'), 4 => ts('5'),
357 5 => ts('6'), 6 => ts('7'), 7 => ts('8'), 8 => ts('9'), 9 => ts('10'),
358 );
359 $element = $this->add('select', 'additional_participants',
360 ts('How many people are you registering?'),
361 $additionalOptions,
362 NULL,
363 array('onChange' => "allowParticipant()")
364 );
365 $isAdditionalParticipants = TRUE;
366 }
367 }
368
369 //hack to allow group to register w/ waiting
370 if ((CRM_Utils_Array::value('is_multiple_registrations', $this->_values['event']) ||
371 $this->_priceSetId
372 ) &&
373 !$this->_allowConfirmation &&
374 is_numeric($this->_availableRegistrations)
375 && CRM_Utils_Array::value('has_waitlist', $this->_values['event'])
376 ) {
377 $bypassPayment = TRUE;
378 //case might be group become as a part of waitlist.
379 //If not waitlist then they require admin approve.
380 $allowGroupOnWaitlist = TRUE;
381 $this->_waitlistMsg = ts("This event has only %1 space(s) left. If you continue and register more than %1 people (including yourself ), the whole group will be wait listed. Or, you can reduce the number of people you are registering to %1 to avoid being put on the waiting list.", array(1 => $this->_availableRegistrations));
382
383 if ($this->_requireApproval) {
384 $this->_requireApprovalMsg = CRM_Utils_Array::value('approval_req_text', $this->_values['event'],
385 ts('Registration for this event requires approval. Once your registration(s) have been reviewed, you will receive an email with a link to a web page where you can complete the registration process.')
386 );
387 }
388 }
389
390 //case where only approval needed - no waitlist.
391 if ($this->_requireApproval &&
392 !$this->_allowWaitlist && !$bypassPayment
393 ) {
394 $this->_requireApprovalMsg = CRM_Utils_Array::value('approval_req_text', $this->_values['event'],
395 ts('Registration for this event requires approval. Once your registration has been reviewed, you will receive an email with a link to a web page where you can complete the registration process.')
396 );
397 }
398
399 //lets display status to primary page only.
400 $this->assign('waitlistMsg', $this->_waitlistMsg);
401 $this->assign('requireApprovalMsg', $this->_requireApprovalMsg);
402 $this->assign('allowGroupOnWaitlist', $allowGroupOnWaitlist);
403 $this->assign('isAdditionalParticipants', $isAdditionalParticipants);
404
405 $this->buildCustom($this->_values['custom_pre_id'], 'customPre');
406 $this->buildCustom($this->_values['custom_post_id'], 'customPost');
407
408 //lets get js on two different qf elements.
409 $showHidePayfieldName = NULL;
410 $showHidePaymentInformation = FALSE;
411 if ($this->_values['event']['is_monetary']) {
412 self::buildAmount($this);
413 }
414
415 $pps = NULL;
416 $this->_paymentProcessors = $this->get('paymentProcessors');
417 if (!empty($this->_paymentProcessors)) {
418 $pps = $this->_paymentProcessors;
419 foreach ($pps as $key => & $name) {
420 $pps[$key] = $name['name'];
421 }
422 }
423
424 if (CRM_Utils_Array::value('is_pay_later', $this->_values['event']) &&
425 ($this->_allowConfirmation || (!$this->_requireApproval && !$this->_allowWaitlist))
426 ) {
427 $pps[0] = $this->_values['event']['pay_later_text'];
428 }
429
430 if ($this->_values['event']['is_monetary']) {
431 if (count($pps) > 1) {
432 $this->addRadio('payment_processor', ts('Payment Method'), $pps,
433 NULL, "&nbsp;", TRUE
434 );
435 }
436 elseif (!empty($pps)) {
437 $ppKeys = array_keys($pps);
438 $currentPP = array_pop($ppKeys);
439 $this->addElement('hidden', 'payment_processor', $currentPP);
440 }
441 }
442
443 //lets add some qf element to bypass payment validations, CRM-4320
444 if ($bypassPayment) {
445 $this->addElement('hidden', 'bypass_payment', NULL, array('id' => 'bypass_payment'));
446 }
447 $this->assign('bypassPayment', $bypassPayment);
448 $this->assign('showHidePaymentInformation', $showHidePaymentInformation);
449
450 $userID = parent::getContactID();
451
452 if (!$userID) {
453 $createCMSUser = FALSE;
454
455 if ($this->_values['custom_pre_id']) {
456 $profileID = $this->_values['custom_pre_id'];
457 $createCMSUser = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_UFGroup', $profileID, 'is_cms_user');
458 }
459
460 if (!$createCMSUser &&
461 $this->_values['custom_post_id']
462 ) {
463 if (!is_array($this->_values['custom_post_id'])) {
464 $profileIDs = array($this->_values['custom_post_id']);
465 }
466 else {
467 $profileIDs = $this->_values['custom_post_id'];
468 }
469 foreach ($profileIDs as $pid) {
470 if (CRM_Core_DAO::getFieldValue('CRM_Core_DAO_UFGroup', $pid, 'is_cms_user')) {
471 $profileID = $pid;
472 $createCMSUser = TRUE;
473 break;
474 }
475 }
476 }
477
478 if ($createCMSUser) {
479 CRM_Core_BAO_CMSUser::buildForm($this, $profileID, TRUE);
480 }
481 }
482
483 //we have to load confirm contribution button in template
484 //when multiple payment processor as the user
485 //can toggle with payment processor selection
486 $billingModePaymentProcessors = 0;
487 if (!CRM_Utils_System::isNull($this->_paymentProcessors)) {
488 foreach ($this->_paymentProcessors as $key => $values) {
489 if ($values['billing_mode'] == CRM_Core_Payment::BILLING_MODE_BUTTON) {
490 $billingModePaymentProcessors++;
491 }
492 }
493 }
494
495 if ($billingModePaymentProcessors && count($this->_paymentProcessors) == $billingModePaymentProcessors) {
496 $allAreBillingModeProcessors = TRUE;
497 } else {
498 $allAreBillingModeProcessors = FALSE;
499 }
500
501 if (!$allAreBillingModeProcessors ||
502 CRM_Utils_Array::value('is_pay_later', $this->_values['event']) || $bypassPayment
503 ) {
504
505 //freeze button to avoid multiple calls.
506 $js = NULL;
507
508 if (!CRM_Utils_Array::value('is_monetary', $this->_values['event'])) {
509 $js = array('onclick' => "return submitOnce(this,'" . $this->_name . "','" . ts('Processing') . "');");
510 }
511 $this->addButtons(array(
512 array(
513 'type' => 'upload',
514 'name' => ts('Continue >>'),
515 'spacing' => '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;',
516 'isDefault' => TRUE,
517 'js' => $js,
518 ),
519 )
520 );
521 }
522
523 $this->addFormRule(array('CRM_Event_Form_Registration_Register', 'formRule'), $this);
524
525 // add pcp fields
526 if ($this->_pcpId) {
527 CRM_PCP_BAO_PCP::buildPcp($this->_pcpId, $this);
528 }
529 }
530
531 /**
532 * build the radio/text form elements for the amount field
533 *
534 * @param object $form form object
535 * @param boolean $required true if you want to add formRule
536 * @param int $discountId discount id for the event
537 *
538 * @return void
539 * @access public
540 * @static
541 */
542 static public function buildAmount(&$form, $required = TRUE, $discountId = NULL) {
543 //if payment done, no need to build the fee block.
7bf9cde2 544 if (!empty($form->_paymentId)) {
6a488035
TO
545 //fix to diaplay line item in update mode.
546 $form->assign('priceSet', isset($form->_priceSet) ? $form->_priceSet : NULL);
547 return;
548 }
549
550 $feeFields = CRM_Utils_Array::value('fee', $form->_values);
551
552 if (is_array($feeFields)) {
553 $form->_feeBlock = &$form->_values['fee'];
554 }
555
556 //check for discount.
557 $discountedFee = CRM_Utils_Array::value('discount', $form->_values);
558 if (is_array($discountedFee) && !empty($discountedFee)) {
559 if (!$discountId) {
560 $form->_discountId = $discountId = CRM_Core_BAO_Discount::findSet($form->_eventId, 'civicrm_event');
561 }
562 if ($discountId) {
563 $form->_feeBlock = &$form->_values['discount'][$discountId];
564 }
565 }
566 if (!is_array($form->_feeBlock)) {
567 $form->_feeBlock = array();
568 }
569
570 //its time to call the hook.
571 CRM_Utils_Hook::buildAmount('event', $form, $form->_feeBlock);
572
573 //reset required if participant is skipped.
574 $button = substr($form->controller->getButtonName(), -4);
575 if ($required && $button == 'skip') {
576 $required = FALSE;
577 }
578
579 $className = CRM_Utils_System::getClassName($form);
580
581 //build the priceset fields.
582 if (isset($form->_priceSetId) && $form->_priceSetId) {
583
584 //format price set fields across option full.
585 self::formatFieldsForOptionFull($form);
586
587 if (CRM_Utils_Array::value('is_quick_config', $form->_priceSet)) {
588 $form->_quickConfig = $form->_priceSet['is_quick_config'];
589 }
590 $form->add('hidden', 'priceSetId', $form->_priceSetId);
591
592 foreach ($form->_feeBlock as $field) {
593 if (CRM_Utils_Array::value('visibility', $field) == 'public' ||
594 $className == 'CRM_Event_Form_Participant'
595 ) {
596 $fieldId = $field['id'];
597 $elementName = 'price_' . $fieldId;
598
599 $isRequire = CRM_Utils_Array::value('is_required', $field);
600 if ($button == 'skip') {
601 $isRequire = FALSE;
602 }
603
604 //user might modified w/ hook.
605 $options = CRM_Utils_Array::value('options', $field);
606 if (!is_array($options)) {
607 continue;
608 }
609
610 $optionFullIds = CRM_Utils_Array::value('option_full_ids', $field, array());
611
612 //soft suppress required rule when option is full.
613 if (!empty($optionFullIds) && (count($options) == count($optionFullIds))) {
614 $isRequire = FALSE;
615 }
616
617 //build the element.
618 CRM_Price_BAO_Field::addQuickFormElement($form,
619 $elementName,
620 $fieldId,
621 FALSE,
622 $isRequire,
623 NULL,
624 $options,
625 $optionFullIds
626 );
627 }
628 }
629 $form->assign('priceSet', $form->_priceSet);
630 }
631 else {
632 $eventFeeBlockValues = array();
633 foreach ($form->_feeBlock as $fee) {
634 if (is_array($fee)) {
635
636 //CRM-7632, CRM-6201
637 $totalAmountJs = NULL;
638 if ($className == 'CRM_Event_Form_Participant') {
639 $totalAmountJs = array('onClick' => "fillTotalAmount(" . $fee['value'] . ")");
640 }
641
642 $eventFeeBlockValues['amount_id_' . $fee['amount_id']] = $fee['value'];
643 $elements[] = &$form->createElement('radio', NULL, '',
644 CRM_Utils_Money::format($fee['value']) . ' ' .
645 $fee['label'],
646 $fee['amount_id'],
647 $totalAmountJs
648 );
649 }
650 }
651 $form->assign('eventFeeBlockValues', json_encode($eventFeeBlockValues));
652
653 $form->_defaults['amount'] = CRM_Utils_Array::value('default_fee_id', $form->_values['event']);
654 $element = &$form->addGroup($elements, 'amount', ts('Event Fee(s)'), '<br />');
655 if (isset($form->_online) && $form->_online) {
656 $element->freeze();
657 }
658 if ($required) {
659 $form->addRule('amount', ts('Fee Level is a required field.'), 'required');
660 }
661 }
662 }
663
664 public static function formatFieldsForOptionFull(&$form) {
665 $priceSet = $form->get('priceSet');
666 $priceSetId = $form->get('priceSetId');
667 if (!$priceSetId ||
668 !is_array($priceSet) ||
669 empty($priceSet) ||
670 !CRM_Utils_Array::value('optionsMaxValueTotal', $priceSet)
671 ) {
672 return;
673 }
674
675 $skipParticipants = $formattedPriceSetDefaults = array();
676 if ($form->_allowConfirmation && (isset($form->_pId) || isset($form->_additionalParticipantId))) {
677 $participantId = isset($form->_pId) ? $form->_pId : $form->_additionalParticipantId;
678 $pricesetDefaults = CRM_Event_Form_EventFees::setDefaultPriceSet($participantId,
679 $form->_eventId
680 );
681 // modify options full to respect the selected fields
682 // options on confirmation.
683 $formattedPriceSetDefaults = self::formatPriceSetParams($form, $pricesetDefaultOptions);
684
685 // to skip current registered participants fields option count on confirmation.
686 $skipParticipants[] = $form->_participantId;
687 if (!empty($form->_additionalParticipantIds)) {
688 $skipParticipants = array_merge($skipParticipants, $form->_additionalParticipantIds);
689 }
690 }
691
692 $className = CRM_Utils_System::getClassName($form);
693
694 //get the current price event price set options count.
695 $currentOptionsCount = self::getPriceSetOptionCount($form);
696 $recordedOptionsCount = CRM_Event_BAO_Participant::priceSetOptionsCount($form->_eventId, $skipParticipants);
697
698 foreach ($form->_feeBlock as & $field) {
699 $optionFullIds = array();
700 $fieldId = $field['id'];
701 if (!is_array($field['options'])) {
702 continue;
703 }
704 foreach ($field['options'] as & $option) {
705 $optId = $option['id'];
706 $count = CRM_Utils_Array::value('count', $option, 0);
707 $maxValue = CRM_Utils_Array::value('max_value', $option, 0);
708 $dbTotalCount = CRM_Utils_Array::value($optId, $recordedOptionsCount, 0);
709 $currentTotalCount = CRM_Utils_Array::value($optId, $currentOptionsCount, 0);
710
711 // Do not consider current count for select field,
712 // since we are not going to freeze the options.
713 if ($field['html_type'] == 'Select') {
714 $totalCount = $dbTotalCount;
715 }
716 else {
717 $totalCount = $currentTotalCount + $dbTotalCount;
718 }
719
720 $isFull = FALSE;
721 if ($maxValue &&
722 (($totalCount >= $maxValue) || ($totalCount + $count > $maxValue))
723 ) {
724 $isFull = TRUE;
725 $optionFullIds[$optId] = $optId;
726 }
727
728 //here option is not full,
729 //but we don't want to allow participant to increase
730 //seats at the time of re-walking registration.
731 if ($count &&
732 $form->_allowConfirmation &&
733 !empty($formattedPriceSetDefaults)
734 ) {
735 if (!CRM_Utils_Array::value("price_{$field}", $formattedPriceSetDefaults) ||
736 !CRM_Utils_Array::value($opId, $formattedPriceSetDefaults["price_{$fieldId}"])
737 ) {
738 $optionFullIds[$optId] = $optId;
739 $isFull = TRUE;
740 }
741 }
742 $option['is_full'] = $isFull;
743 $option['db_total_count'] = $dbTotalCount;
744 $option['total_option_count'] = $dbTotalCount + $currentTotalCount;
745 }
746
747 //ignore option full for offline registration.
748 if ($className == 'CRM_Event_Form_Participant') {
749 $optionFullIds = array();
750 }
751
752 //finally get option ids in.
753 $field['option_full_ids'] = $optionFullIds;
754 }
755 }
756
757 /**
758 * global form rule
759 *
760 * @param array $fields the input form values
761 * @param array $files the uploaded files if any
762 * @param array $options additional user data
763 *
764 * @return true if no errors, else array of errors
765 * @access public
766 * @static
767 */
768 static function formRule($fields, $files, $self) {
769 $errors = array();
770 //check that either an email or firstname+lastname is included in the form(CRM-9587)
771 self::checkProfileComplete($fields, $errors, $self->_eventId);
772 //To check if the user is already registered for the event(CRM-2426)
773 if (!$self->_skipDupeRegistrationCheck) {
168e792f 774 self::checkRegistration($fields, $self);
6a488035
TO
775 }
776 //check for availability of registrations.
777 if (!$self->_allowConfirmation &&
778 !CRM_Utils_Array::value('bypass_payment', $fields) &&
779 is_numeric($self->_availableRegistrations) &&
780 CRM_Utils_Array::value('additional_participants', $fields) >= $self->_availableRegistrations
781 ) {
782 $errors['additional_participants'] = ts("There is only enough space left on this event for %1 participant(s).", array(1 => $self->_availableRegistrations));
783 }
784
785 // during confirmation don't allow to increase additional participants, CRM-4320
786 if ($self->_allowConfirmation &&
787 CRM_Utils_Array::value('additional_participants', $fields) &&
788 is_array($self->_additionalParticipantIds) &&
789 $fields['additional_participants'] > count($self->_additionalParticipantIds)
790 ) {
791 $errors['additional_participants'] = ts("Oops. It looks like you are trying to increase the number of additional people you are registering for. You can confirm registration for a maximum of %1 additional people.", array(1 => count($self->_additionalParticipantIds)));
792 }
793
794 //don't allow to register w/ waiting if enough spaces available.
795 if (CRM_Utils_Array::value('bypass_payment', $fields)) {
796 if (!is_numeric($self->_availableRegistrations) ||
797 (!CRM_Utils_Array::value('priceSetId', $fields) && CRM_Utils_Array::value('additional_participants', $fields) < $self->_availableRegistrations)
798 ) {
799 $errors['bypass_payment'] = ts("Oops. There are enough available spaces in this event. You can not add yourself to the waiting list.");
800 }
801 }
802
803 if (CRM_Utils_Array::value('additional_participants', $fields) &&
804 !CRM_Utils_Rule::positiveInteger($fields['additional_participants'])
805 ) {
806 $errors['additional_participants'] = ts('Please enter a whole number for Number of additional people.');
807 }
808
809 // priceset validations
810 if (CRM_Utils_Array::value('priceSetId', $fields)) {
811 //format params.
812 $formatted = self::formatPriceSetParams($self, $fields);
813 $ppParams = array($formatted);
814 $priceSetErrors = self::validatePriceSet($self, $ppParams);
815 $primaryParticipantCount = self::getParticipantCount($self, $ppParams);
816
817 //get price set fields errors in.
818 $errors = array_merge($errors, CRM_Utils_Array::value(0, $priceSetErrors, array()));
819
820 $totalParticipants = $primaryParticipantCount;
821 if (CRM_Utils_Array::value('additional_participants', $fields)) {
822 $totalParticipants += $fields['additional_participants'];
823 }
824
825 if (!CRM_Utils_Array::value('bypass_payment', $fields) &&
826 !$self->_allowConfirmation &&
827 is_numeric($self->_availableRegistrations) &&
828 $self->_availableRegistrations < $totalParticipants
829 ) {
830 $errors['_qf_default'] = ts("Only %1 Registrations available.", array(1 => $self->_availableRegistrations));
831 }
832
833 $lineItem = array();
834 CRM_Price_BAO_Set::processAmount($self->_values['fee'], $fields, $lineItem);
835 if ($fields['amount'] < 0) {
836 $errors['_qf_default'] = ts('Event Fee(s) can not be less than zero. Please select the options accordingly');
837 }
838 }
839
840 if ($self->_values['event']['is_monetary']) {
841 if (is_array($self->_paymentProcessor)) {
842 $payment = CRM_Core_Payment::singleton($self->_mode, $self->_paymentProcessor, $this);
843 $error = $payment->checkConfig($self->_mode);
844 if ($error) {
845 $errors['_qf_default'] = $error;
846 }
847 }
848 // return if this is express mode
849 $config = CRM_Core_Config::singleton();
f92fc7eb
CW
850 if ($self->_paymentProcessor &&
851 $self->_paymentProcessor['billing_mode'] & CRM_Core_Payment::BILLING_MODE_BUTTON
852 ) {
6a488035
TO
853 if (CRM_Utils_Array::value($self->_expressButtonName . '_x', $fields) ||
854 CRM_Utils_Array::value($self->_expressButtonName . '_y', $fields) ||
855 CRM_Utils_Array::value($self->_expressButtonName, $fields)
856 ) {
857 return empty($errors) ? TRUE : $errors;
858 }
859 }
860
861 $isZeroAmount = $skipPayementValidation = FALSE;
862 if (CRM_Utils_Array::value('priceSetId', $fields)) {
863 if (CRM_Utils_Array::value('amount', $fields) == 0) {
864 $isZeroAmount = TRUE;
865 }
866 }
867 elseif (CRM_Utils_Array::value('amount', $fields) &&
868 (isset($self->_values['discount'][$fields['amount']])
869 && CRM_Utils_Array::value('value', $self->_values['discount'][$fields['amount']]) == 0
870 )
871 ) {
872 $isZeroAmount = TRUE;
873 }
874 elseif (CRM_Utils_Array::value('amount', $fields) &&
875 (isset($self->_values['fee'][$fields['amount']])
876 && CRM_Utils_Array::value('value', $self->_values['fee'][$fields['amount']]) == 0
877 )
878 ) {
879 $isZeroAmount = TRUE;
880 }
881
882 if ($isZeroAmount && !($self->_forcePayement && CRM_Utils_Array::value('additional_participants', $fields))) {
883 $skipPayementValidation = TRUE;
884 }
885
886 // also return if paylater mode or zero fees for valid members
887 if (CRM_Utils_Array::value('is_pay_later', $fields) ||
888 CRM_Utils_Array::value('bypass_payment', $fields) ||
889 $skipPayementValidation ||
890 (!$self->_allowConfirmation && ($self->_requireApproval || $self->_allowWaitlist))
891 ) {
892 return empty($errors) ? TRUE : $errors;
893 }
7cb3d4f0
CW
894 if (!empty($self->_paymentFields)) {
895 CRM_Core_Form::validateMandatoryFields($self->_paymentFields, $fields, $errors);
6a488035 896 }
7cb3d4f0 897 CRM_Core_Payment_Form::validateCreditCard($fields, $errors);
6a488035 898 }
6a488035 899
6a488035
TO
900 foreach (CRM_Contact_BAO_Contact::$_greetingTypes as $greeting) {
901 if ($greetingType = CRM_Utils_Array::value($greeting, $fields)) {
902 $customizedValue = CRM_Core_OptionGroup::getValue($greeting, 'Customized', 'name');
903 if ($customizedValue == $greetingType && empty($fields[$greeting . '_custom'])) {
904 $errors[$customizedGreeting] = ts('Custom %1 is a required field if %1 is of type Customized.',
905 array(1 => ucwords(str_replace('_', ' ', $greeting)))
906 );
907 }
908 }
909 }
910 return empty($errors) ? TRUE : $errors;
911 }
912
913 /**
914 * Check if profiles are complete when event registration occurs(CRM-9587)
915 *
916 */
917 static function checkProfileComplete($fields, &$errors, $eventId) {
918 $email = '';
919 foreach ($fields as $fieldname => $fieldvalue) {
920 if (substr($fieldname, 0, 6) == 'email-' && $fieldvalue) {
921 $email = $fieldvalue;
922 }
923 }
924
925 if (!$email && !(CRM_Utils_Array::value('first_name', $fields) &&
926 CRM_Utils_Array::value('last_name', $fields)
927 )) {
928 $defaults = $params = array('id' => $eventId);
929 CRM_Event_BAO_Event::retrieve($params, $defaults);
930 $message = ts("Mandatory fields (first name and last name, OR email address) are missing from this form.");
931 $errors['_qf_default'] = $message;
932 }
933 }
934
935 /**
936 * Function to process the form
937 *
938 * @access public
939 *
940 * @return None
941 */
942 public function postProcess() {
943 // get the submitted form values.
944 $params = $this->controller->exportValues($this->_name);
945
946 //set as Primary participant
947 $params['is_primary'] = 1;
948
949 if ($this->_values['event']['is_pay_later'] && !array_key_exists('hidden_processor', $params)) {
950 $params['is_pay_later'] = 1;
951 }
952 else {
953 $params['is_pay_later'] = 0;
954 }
955
956 $this->set('is_pay_later', $params['is_pay_later']);
957
958 // assign pay later stuff
959 $this->_params['is_pay_later'] = CRM_Utils_Array::value('is_pay_later', $params, FALSE);
960 $this->assign('is_pay_later', $params['is_pay_later']);
961 if ($params['is_pay_later']) {
962 $this->assign('pay_later_text', $this->_values['event']['pay_later_text']);
963 $this->assign('pay_later_receipt', $this->_values['event']['pay_later_receipt']);
964 }
6a488035 965
168e792f
DL
966 if (!$this->_allowConfirmation) {
967 // check if the participant is already registered
968 if (!$this->_skipDupeRegistrationCheck) {
969 $params['contact_id'] = self::checkRegistration($params, $this, FALSE, TRUE, TRUE);
970 }
971 }
972
6a488035
TO
973 if (CRM_Utils_Array::value('image_URL', $params)) {
974 CRM_Contact_BAO_Contact::processImageParams($params);
975 }
976
977 //carry campaign to partcipants.
978 if (array_key_exists('participant_campaign_id', $params)) {
979 $params['campaign_id'] = $params['participant_campaign_id'];
980 }
981 else {
982 $params['campaign_id'] = CRM_Utils_Array::value('campaign_id', $this->_values['event']);
983 }
984
985 //hack to allow group to register w/ waiting
986 $primaryParticipantCount = self::getParticipantCount($this, $params);
987
988 $totalParticipants = $primaryParticipantCount;
989 if (CRM_Utils_Array::value('additional_participants', $params)) {
990 $totalParticipants += $params['additional_participants'];
991 }
992 if (!$this->_allowConfirmation &&
993 CRM_Utils_Array::value('bypass_payment', $params) &&
994 is_numeric($this->_availableRegistrations) &&
995 $totalParticipants > $this->_availableRegistrations
996 ) {
997 $this->_allowWaitlist = TRUE;
998 $this->set('allowWaitlist', TRUE);
999 }
1000
1001 //carry participant id if pre-registered.
1002 if ($this->_allowConfirmation && $this->_participantId) {
1003 $params['participant_id'] = $this->_participantId;
1004 }
1005
1006 $params['defaultRole'] = 1;
1007 if (array_key_exists('participant_role', $params)) {
1008 $params['participant_role_id'] = $params['participant_role'];
1009 }
1010
1011 if (array_key_exists('participant_role_id', $params)) {
1012 $params['defaultRole'] = 0;
1013 }
1014 if (!CRM_Utils_Array::value('participant_role_id', $params) &&
1015 $this->_values['event']['default_role_id']
1016 ) {
1017 $params['participant_role_id'] = $this->_values['event']['default_role_id'];
1018 }
1019
1020 $config = CRM_Core_Config::singleton();
1021 $params['currencyID'] = $config->defaultCurrency;
1022
1023 if ($this->_values['event']['is_monetary']) {
1024 // we first reset the confirm page so it accepts new values
1025 $this->controller->resetPage('Confirm');
1026
1027 //added for discount
1028 $discountId = CRM_Core_BAO_Discount::findSet($this->_eventId, 'civicrm_event');
1029
1030 if (!empty($this->_values['discount'][$discountId])) {
1031 $params['discount_id'] = $discountId;
1032 $params['amount_level'] = $this->_values['discount'][$discountId][$params['amount']]['label'];
1033
1034 $params['amount'] = $this->_values['discount'][$discountId][$params['amount']]['value'];
1035 }
1036 elseif (empty($params['priceSetId'])) {
1037 $params['amount_level'] = $this->_values['fee'][$params['amount']]['label'];
1038 $params['amount'] = $this->_values['fee'][$params['amount']]['value'];
1039 }
1040 else {
1041 $lineItem = array();
1042 CRM_Price_BAO_Set::processAmount($this->_values['fee'], $params, $lineItem);
1043 $this->set('lineItem', array($lineItem));
1044 $this->set('lineItemParticipantsCount', array($primaryParticipantCount));
1045 }
1046
1047 $this->set('amount', $params['amount']);
1048 $this->set('amount_level', $params['amount_level']);
1049
1050 // generate and set an invoiceID for this transaction
1051 $invoiceID = md5(uniqid(rand(), TRUE));
1052 $this->set('invoiceID', $invoiceID);
1053
1054 if (is_array($this->_paymentProcessor)) {
1055 $payment = CRM_Core_Payment::singleton($this->_mode, $this->_paymentProcessor, $this);
1056 }
1057 // default mode is direct
1058 $this->set('contributeMode', 'direct');
1059
1060 if (isset($params["state_province_id-{$this->_bltID}"]) &&
1061 $params["state_province_id-{$this->_bltID}"]
1062 ) {
1063 $params["state_province-{$this->_bltID}"] = CRM_Core_PseudoConstant::stateProvinceAbbreviation($params["state_province_id-{$this->_bltID}"]);
1064 }
1065
1066 if (isset($params["country_id-{$this->_bltID}"]) &&
1067 $params["country_id-{$this->_bltID}"]
1068 ) {
1069 $params["country-{$this->_bltID}"] = CRM_Core_PseudoConstant::countryIsoCode($params["country_id-{$this->_bltID}"]);
1070 }
1071 if (isset($params['credit_card_exp_date'])) {
1072 $params['year'] = CRM_Core_Payment_Form::getCreditCardExpirationYear($params);
1073 $params['month'] = CRM_Core_Payment_Form::getCreditCardExpirationMonth($params);
1074 }
1075 if ($this->_values['event']['is_monetary']) {
1076 $params['ip_address'] = CRM_Utils_System::ipAddress();
1077 $params['currencyID'] = $config->defaultCurrency;
1078 $params['payment_action'] = 'Sale';
1079 $params['invoiceID'] = $invoiceID;
1080 }
1081
1082 $this->_params = array();
1083 $this->_params[] = $params;
1084 $this->set('params', $this->_params);
1085
f92fc7eb
CW
1086 if ($this->_paymentProcessor &&
1087 $this->_paymentProcessor['billing_mode'] & CRM_Core_Payment::BILLING_MODE_BUTTON
1088 ) {
6a488035
TO
1089 //get the button name
1090 $buttonName = $this->controller->getButtonName();
1091 if (in_array($buttonName,
1092 array(
1093 $this->_expressButtonName,
1094 $this->_expressButtonName . '_x',
1095 $this->_expressButtonName . '_y',
1096 )
1097 ) &&
1098 !CRM_Utils_Array::value('is_pay_later', $params) &&
1099 !$this->_allowWaitlist &&
1100 !$this->_requireApproval
1101 ) {
1102 $this->set('contributeMode', 'express');
1103
1104 // Send Event Name & Id in Params
1105 $params['eventName'] = $this->_values['event']['title'];
1106 $params['eventId'] = $this->_values['event']['id'];
1107
1108 $params['cancelURL'] = CRM_Utils_System::url('civicrm/event/register',
1109 "_qf_Register_display=1&qfKey={$this->controller->_key}",
1110 TRUE, NULL, FALSE
1111 );
1112 if (CRM_Utils_Array::value('additional_participants', $params, FALSE)) {
1113 $urlArgs = "_qf_Participant_1_display=1&rfp=1&qfKey={$this->controller->_key}";
1114 }
1115 else {
1116 $urlArgs = "_qf_Confirm_display=1&rfp=1&qfKey={$this->controller->_key}";
1117 }
1118 $params['returnURL'] = CRM_Utils_System::url('civicrm/event/register',
1119 $urlArgs,
1120 TRUE, NULL, FALSE
1121 );
1122 $params['invoiceID'] = $invoiceID;
1123
1124 //default action is Sale
1125 $params['payment_action'] = 'Sale';
1126
1127 $token = $payment->setExpressCheckout($params);
1128 if (is_a($token, 'CRM_Core_Error')) {
1129 CRM_Core_Error::displaySessionError($token);
1130 CRM_Utils_System::redirect($params['cancelURL']);
1131 }
1132
1133 $this->set('token', $token);
1134
1135 $paymentURL = $this->_paymentProcessor['url_site'] . "/cgi-bin/webscr?cmd=_express-checkout&token=$token";
1136
1137 CRM_Utils_System::redirect($paymentURL);
1138 }
1139 }
f92fc7eb
CW
1140 elseif ($this->_paymentProcessor &&
1141 $this->_paymentProcessor['billing_mode'] & CRM_Core_Payment::BILLING_MODE_NOTIFY
1142 ) {
6a488035
TO
1143 $this->set('contributeMode', 'notify');
1144 }
1145 }
1146 else {
1147 $session = CRM_Core_Session::singleton();
1148 $params['description'] = ts('Online Event Registration') . ' ' . $this->_values['event']['title'];
1149
1150 $this->_params = array();
1151 $this->_params[] = $params;
1152 $this->set('params', $this->_params);
1153
1154 if (!CRM_Utils_Array::value('additional_participants', $params)) {
1155 self::processRegistration($this->_params);
1156 }
1157 }
1158
1159 // If registering > 1 participant, give status message
1160 if (CRM_Utils_Array::value('additional_participants', $params, FALSE)) {
1161 $statusMsg = ts('Registration information for participant 1 has been saved.');
1162 CRM_Core_Session::setStatus($statusMsg, ts('Saved'), 'success');
1163 }
1164 }
1165 //end of function
1166
1167 /*
168e792f 1168 * Function to process Registration of free event
6a488035 1169 *
168e792f
DL
1170 * @param array $param Form valuess
1171 * @param int contactID
6a488035 1172 *
168e792f
DL
1173 * @return None
1174 * access public
6a488035
TO
1175 *
1176 */
1177 public function processRegistration($params, $contactID = NULL) {
1178 $session = CRM_Core_Session::singleton();
1179 $this->_participantInfo = array();
1180
1181 // CRM-4320, lets build array of cancelled additional participant ids
1182 // those are drop or skip by primary at the time of confirmation.
1183 // get all in and then unset those are confirmed.
1184 $cancelledIds = $this->_additionalParticipantIds;
1185
1186 $participantCount = array();
1187 foreach ($params as $participantNum => $record) {
1188 if ($record == 'skip') {
1189 $participantCount[$participantNum] = 'skip';
1190 }
1191 elseif ($participantNum) {
1192 $participantCount[$participantNum] = 'participant';
1193 }
1194 }
1195
1196 $registerByID = NULL;
1197 foreach ($params as $key => $value) {
1198 if ($value != 'skip') {
1199 $fields = NULL;
1200
1201 // setting register by Id and unset contactId.
1202 if (!CRM_Utils_Array::value('is_primary', $value)) {
1203 $contactID = NULL;
1204 $registerByID = $this->get('registerByID');
1205 if ($registerByID) {
1206 $value['registered_by_id'] = $registerByID;
1207 }
1208 // get an email if one exists for the participant
1209 $participantEmail = '';
1210 foreach (array_keys($value) as $valueName) {
1211 if (substr($valueName, 0, 6) == 'email-') {
1212 $participantEmail = $value[$valueName];
1213 }
1214 }
1215 if ($participantEmail) {
1216 $this->_participantInfo[] = $participantEmail;
1217 }
1218 else {
1219 $this->_participantInfo[] = $value['first_name'] . ' ' . $value['last_name'];
1220 }
1221 }
1222 elseif (CRM_Utils_Array::value('contact_id', $value)) {
1223 $contactID = $value['contact_id'];
1224 }
1225 else {
1226 $contactID = parent::getContactID();
1227 }
1228
1229 CRM_Event_Form_Registration_Confirm::fixLocationFields($value, $fields);
1230 //for free event or additional participant, dont create billing email address.
1231 if (!CRM_Utils_Array::value('is_primary', $value) || !$this->_values['event']['is_monetary']) {
1232 unset($value["email-{$this->_bltID}"]);
1233 }
1234
1235 $contactID = CRM_Event_Form_Registration_Confirm::updateContactFields($contactID, $value, $fields);
1236
1237 // lets store the contactID in the session
1238 // we dont store in userID in case the user is doing multiple
1239 // transactions etc
1240 // for things like tell a friend
1241 if (!parent::getContactID() && CRM_Utils_Array::value('is_primary', $value)) {
1242 $session->set('transaction.userID', $contactID);
1243 }
1244
1245 //lets get the status if require approval or waiting.
1246
1247 $waitingStatuses = CRM_Event_PseudoConstant::participantStatus(NULL, "class = 'Waiting'");
1248 if ($this->_allowWaitlist && !$this->_allowConfirmation) {
1249 $value['participant_status_id'] = $value['participant_status'] = array_search('On waitlist', $waitingStatuses);
1250 }
1251 elseif ($this->_requireApproval && !$this->_allowConfirmation) {
1252 $value['participant_status_id'] = $value['participant_status'] = array_search('Awaiting approval', $waitingStatuses);
1253 }
1254
1255 $this->set('value', $value);
1256 $this->confirmPostProcess($contactID, NULL, NULL);
1257
1258 //lets get additional participant id to cancel.
1259 if ($this->_allowConfirmation && is_array($cancelledIds)) {
1260 $additonalId = CRM_Utils_Array::value('participant_id', $value);
1261 if ($additonalId && $key = array_search($additonalId, $cancelledIds)) {
1262 unset($cancelledIds[$key]);
1263 }
1264 }
1265 }
1266 }
1267
1268 // update status and send mail to cancelled additonal participants, CRM-4320
1269 if ($this->_allowConfirmation && is_array($cancelledIds) && !empty($cancelledIds)) {
1270 $cancelledId = array_search('Cancelled',
1271 CRM_Event_PseudoConstant::participantStatus(NULL, "class = 'Negative'")
1272 );
1273 CRM_Event_BAO_Participant::transitionParticipants($cancelledIds, $cancelledId);
1274 }
1275
1276 //set information about additional participants if exists
1277 if (count($this->_participantInfo)) {
1278 $this->set('participantInfo', $this->_participantInfo);
1279 }
1280
1281 //send mail Confirmation/Receipt
1282 if ($this->_contributeMode != 'checkout' ||
1283 $this->_contributeMode != 'notify'
1284 ) {
1285 $isTest = FALSE;
1286 if ($this->_action & CRM_Core_Action::PREVIEW) {
1287 $isTest = TRUE;
1288 }
1289
1290 //handle if no additional participant.
1291 if (!$registerByID) {
1292 $registerByID = $this->get('registerByID');
1293 }
1294 $primaryContactId = $this->get('primaryContactId');
1295
1296 //build an array of custom profile and assigning it to template.
1297 $additionalIDs = CRM_Event_BAO_Event::buildCustomProfile($registerByID, NULL,
1298 $primaryContactId, $isTest, TRUE
1299 );
1300
1301 //lets carry all paticipant params w/ values.
1302 foreach ($additionalIDs as $participantID => $contactId) {
1303 $participantNum = NULL;
1304 if ($participantID == $registerByID) {
1305 $participantNum = 0;
1306 }
1307 else {
1308 if ($participantNum = array_search('participant', $participantCount)) {
1309 unset($participantCount[$participantNum]);
1310 }
1311 }
1312
1313 if ($participantNum === NULL) {
1314 break;
1315 }
1316
1317 //carry the participant submitted values.
1318 $this->_values['params'][$participantID] = $params[$participantNum];
1319 }
1320
1321 //lets send mails to all with meanigful text, CRM-4320.
1322 $this->assign('isOnWaitlist', $this->_allowWaitlist);
1323 $this->assign('isRequireApproval', $this->_requireApproval);
1324
1325 foreach ($additionalIDs as $participantID => $contactId) {
1326 if ($participantID == $registerByID) {
1327 //set as Primary Participant
1328 $this->assign('isPrimary', 1);
1329
1330 $customProfile = CRM_Event_BAO_Event::buildCustomProfile($participantID, $this->_values, NULL, $isTest);
1331
1332 if (count($customProfile)) {
1333 $this->assign('customProfile', $customProfile);
1334 $this->set('customProfile', $customProfile);
1335 }
1336 }
1337 else {
1338 $this->assign('isPrimary', 0);
1339 $this->assign('customProfile', NULL);
1340 }
1341
1342 //send Confirmation mail to Primary & additional Participants if exists
1343 CRM_Event_BAO_Event::sendMail($contactId, $this->_values, $participantID, $isTest);
1344 }
1345 }
1346 }
1347
1348 /**
1349 * Method to check if the user is already registered for the event
1350 * and if result found redirect to the event info page
1351 *
1352 * @param array $fields the input form values(anonymous user)
1353 * @param array $self event data
168e792f
DL
1354 * @param boolean $isAdditional treat isAdditional participants a bit differently
1355 * @param boolean $returnContactId just find and return the contactID match to use
1356 * @param boolean $useDedupeRules force usage of dedupe rules
6a488035
TO
1357 *
1358 * @return void
1359 * @access public
1360 */
178073d6 1361 static function checkRegistration($fields, &$self, $isAdditional = FALSE, $returnContactId = FALSE, $useDedupeRules = FALSE) {
6a488035
TO
1362 // CRM-3907, skip check for preview registrations
1363 // CRM-4320 participant need to walk wizard
1364 if (!$returnContactId &&
1365 ($self->_mode == 'test' || $self->_allowConfirmation)
1366 ) {
1367 return FALSE;
1368 }
1369
1370 $contactID = NULL;
1371 $session = CRM_Core_Session::singleton();
1372 if (!$isAdditional) {
1373 $contactID = parent::getContactID();
1374 }
1375
178073d6 1376 if (!$contactID && is_array($fields) && $fields) {
6a488035
TO
1377
1378 //CRM-6996
1379 //as we are allowing w/ same email address,
1380 //lets check w/ other contact params.
1381 if ($self->_values['event']['allow_same_participant_emails']) {
1382 $params = $fields;
1383 $level = ($isAdditional) ? 'Supervised' : 'Unsupervised';
1384
1385 $dedupeParams = CRM_Dedupe_Finder::formatParams($params, 'Individual');
1386
1387 // disable permission based on cache since event registration is public page/feature.
1388 $dedupeParams['check_permission'] = FALSE;
1389 $ids = CRM_Dedupe_Finder::dupesByParams($dedupeParams, 'Individual', $level);
1390 $contactID = CRM_Utils_Array::value(0, $ids);
1391 }
1392 else {
1393 foreach ($fields as $fieldname => $fieldvalue) {
1394 if (substr($fieldname, 0, 6) == 'email-') {
1395 $emailString = trim($fieldvalue);
1396 if (!empty($emailString)) {
1397 $match = CRM_Contact_BAO_Contact::matchContactOnEmail($emailString, 'Individual');
1398 if (!empty($match)) {
1399 $contactID = $match->contact_id;
1400 }
1401 }
1402 }
1403 }
1404 }
1405 }
1406
1407 if ($returnContactId) {
1408 // CRM-7377
1409 // return contactID if contact already exists
1410 return $contactID;
1411 }
1412
1413 if ($contactID) {
1414 $participant = new CRM_Event_BAO_Participant();
1415 $participant->contact_id = $contactID;
1416 $participant->event_id = $self->_values['event']['id'];
1417 if (!empty($fields['participant_role']) && is_numeric($fields['participant_role'])) {
1418 $participant->role_id = $fields['participant_role'];
1419 }
1420 else {
1421 $participant->role_id = $self->_values['event']['default_role_id'];
1422 }
1423 $participant->is_test = 0;
1424 $participant->find();
1425 $statusTypes = CRM_Event_PseudoConstant::participantStatus(NULL, 'is_counted = 1');
1426 while ($participant->fetch()) {
1427 if (array_key_exists($participant->status_id, $statusTypes)) {
1428 if (!$isAdditional && !$self->_values['event']['allow_same_participant_emails']) {
1429 $registerUrl = CRM_Utils_System::url('civicrm/event/register',
1430 "reset=1&id={$self->_values['event']['id']}&cid=0"
1431 );
1432 if ($self->_pcpId) {
1433 $registerUrl .= '&pcpId=' . $self->_pcpId;
1434 }
1435
1436 $status = ts("It looks like you are already registered for this event. If you want to change your registration, or you feel that you've gotten this message in error, please contact the site administrator.") . ' ' . ts('You can also <a href="%1">register another participant</a>.', array(1 => $registerUrl));
1437 $session->setStatus($status, ts('Oops.'), 'alert');
1438 $url = CRM_Utils_System::url('civicrm/event/info',
1439 "reset=1&id={$self->_values['event']['id']}&noFullMsg=true"
1440 );
1441 if ($self->_action & CRM_Core_Action::PREVIEW) {
1442 $url .= '&action=preview';
1443 }
1444
1445 if ($self->_pcpId) {
1446 $url .= '&pcpId=' . $self->_pcpId;
1447 }
1448
1449 CRM_Utils_System::redirect($url);
1450 }
1451
1452 if ($isAdditional) {
1453 $status = ts("It looks like this participant is already registered for this event. If you want to change your registration, or you feel that you've gotten this message in error, please contact the site administrator.");
1454 $session->setStatus($status, ts('Oops.'), 'alert');
1455 return $participant->id;
1456 }
1457 }
1458 }
1459 }
1460 }
1461}
1462