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