Merge pull request #320 from colemanw/event-snippet
[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();
850 if ($self->_paymentProcessor['billing_mode'] & CRM_Core_Payment::BILLING_MODE_BUTTON) {
851 if (CRM_Utils_Array::value($self->_expressButtonName . '_x', $fields) ||
852 CRM_Utils_Array::value($self->_expressButtonName . '_y', $fields) ||
853 CRM_Utils_Array::value($self->_expressButtonName, $fields)
854 ) {
855 return empty($errors) ? TRUE : $errors;
856 }
857 }
858
859 $isZeroAmount = $skipPayementValidation = FALSE;
860 if (CRM_Utils_Array::value('priceSetId', $fields)) {
861 if (CRM_Utils_Array::value('amount', $fields) == 0) {
862 $isZeroAmount = TRUE;
863 }
864 }
865 elseif (CRM_Utils_Array::value('amount', $fields) &&
866 (isset($self->_values['discount'][$fields['amount']])
867 && CRM_Utils_Array::value('value', $self->_values['discount'][$fields['amount']]) == 0
868 )
869 ) {
870 $isZeroAmount = TRUE;
871 }
872 elseif (CRM_Utils_Array::value('amount', $fields) &&
873 (isset($self->_values['fee'][$fields['amount']])
874 && CRM_Utils_Array::value('value', $self->_values['fee'][$fields['amount']]) == 0
875 )
876 ) {
877 $isZeroAmount = TRUE;
878 }
879
880 if ($isZeroAmount && !($self->_forcePayement && CRM_Utils_Array::value('additional_participants', $fields))) {
881 $skipPayementValidation = TRUE;
882 }
883
884 // also return if paylater mode or zero fees for valid members
885 if (CRM_Utils_Array::value('is_pay_later', $fields) ||
886 CRM_Utils_Array::value('bypass_payment', $fields) ||
887 $skipPayementValidation ||
888 (!$self->_allowConfirmation && ($self->_requireApproval || $self->_allowWaitlist))
889 ) {
890 return empty($errors) ? TRUE : $errors;
891 }
892 if (property_exists($self, '_paymentFields') && !empty($self->_paymentFields )) {
893 foreach ($self->_paymentFields as $name => $fld) {
894 if ($fld['is_required'] &&
895 CRM_Utils_System::isNull(CRM_Utils_Array::value($name, $fields))
896 ) {
897 $errors[$name] = ts('%1 is a required field.', array(1 => $fld['title']));
898 }
899 }
900 }
901 }
902 // make sure that credit card number and cvv are valid
903 if (CRM_Utils_Array::value('credit_card_type', $fields)) {
904 if (CRM_Utils_Array::value('credit_card_number', $fields) &&
905 !CRM_Utils_Rule::creditCardNumber($fields['credit_card_number'], $fields['credit_card_type'])
906 ) {
907 $errors['credit_card_number'] = ts('Please enter a valid Credit Card Number');
908 }
909
910 if (CRM_Utils_Array::value('cvv2', $fields) &&
911 !CRM_Utils_Rule::cvv($fields['cvv2'], $fields['credit_card_type'])
912 ) {
913 $errors['cvv2'] = ts('Please enter a valid Credit Card Verification Number');
914 }
915 }
916 foreach (CRM_Contact_BAO_Contact::$_greetingTypes as $greeting) {
917 if ($greetingType = CRM_Utils_Array::value($greeting, $fields)) {
918 $customizedValue = CRM_Core_OptionGroup::getValue($greeting, 'Customized', 'name');
919 if ($customizedValue == $greetingType && empty($fields[$greeting . '_custom'])) {
920 $errors[$customizedGreeting] = ts('Custom %1 is a required field if %1 is of type Customized.',
921 array(1 => ucwords(str_replace('_', ' ', $greeting)))
922 );
923 }
924 }
925 }
926 return empty($errors) ? TRUE : $errors;
927 }
928
929 /**
930 * Check if profiles are complete when event registration occurs(CRM-9587)
931 *
932 */
933 static function checkProfileComplete($fields, &$errors, $eventId) {
934 $email = '';
935 foreach ($fields as $fieldname => $fieldvalue) {
936 if (substr($fieldname, 0, 6) == 'email-' && $fieldvalue) {
937 $email = $fieldvalue;
938 }
939 }
940
941 if (!$email && !(CRM_Utils_Array::value('first_name', $fields) &&
942 CRM_Utils_Array::value('last_name', $fields)
943 )) {
944 $defaults = $params = array('id' => $eventId);
945 CRM_Event_BAO_Event::retrieve($params, $defaults);
946 $message = ts("Mandatory fields (first name and last name, OR email address) are missing from this form.");
947 $errors['_qf_default'] = $message;
948 }
949 }
950
951 /**
952 * Function to process the form
953 *
954 * @access public
955 *
956 * @return None
957 */
958 public function postProcess() {
959 // get the submitted form values.
960 $params = $this->controller->exportValues($this->_name);
961
962 //set as Primary participant
963 $params['is_primary'] = 1;
964
965 if ($this->_values['event']['is_pay_later'] && !array_key_exists('hidden_processor', $params)) {
966 $params['is_pay_later'] = 1;
967 }
968 else {
969 $params['is_pay_later'] = 0;
970 }
971
972 $this->set('is_pay_later', $params['is_pay_later']);
973
974 // assign pay later stuff
975 $this->_params['is_pay_later'] = CRM_Utils_Array::value('is_pay_later', $params, FALSE);
976 $this->assign('is_pay_later', $params['is_pay_later']);
977 if ($params['is_pay_later']) {
978 $this->assign('pay_later_text', $this->_values['event']['pay_later_text']);
979 $this->assign('pay_later_receipt', $this->_values['event']['pay_later_receipt']);
980 }
6a488035 981
168e792f
DL
982 if (!$this->_allowConfirmation) {
983 // check if the participant is already registered
984 if (!$this->_skipDupeRegistrationCheck) {
985 $params['contact_id'] = self::checkRegistration($params, $this, FALSE, TRUE, TRUE);
986 }
987 }
988
6a488035
TO
989 if (CRM_Utils_Array::value('image_URL', $params)) {
990 CRM_Contact_BAO_Contact::processImageParams($params);
991 }
992
993 //carry campaign to partcipants.
994 if (array_key_exists('participant_campaign_id', $params)) {
995 $params['campaign_id'] = $params['participant_campaign_id'];
996 }
997 else {
998 $params['campaign_id'] = CRM_Utils_Array::value('campaign_id', $this->_values['event']);
999 }
1000
1001 //hack to allow group to register w/ waiting
1002 $primaryParticipantCount = self::getParticipantCount($this, $params);
1003
1004 $totalParticipants = $primaryParticipantCount;
1005 if (CRM_Utils_Array::value('additional_participants', $params)) {
1006 $totalParticipants += $params['additional_participants'];
1007 }
1008 if (!$this->_allowConfirmation &&
1009 CRM_Utils_Array::value('bypass_payment', $params) &&
1010 is_numeric($this->_availableRegistrations) &&
1011 $totalParticipants > $this->_availableRegistrations
1012 ) {
1013 $this->_allowWaitlist = TRUE;
1014 $this->set('allowWaitlist', TRUE);
1015 }
1016
1017 //carry participant id if pre-registered.
1018 if ($this->_allowConfirmation && $this->_participantId) {
1019 $params['participant_id'] = $this->_participantId;
1020 }
1021
1022 $params['defaultRole'] = 1;
1023 if (array_key_exists('participant_role', $params)) {
1024 $params['participant_role_id'] = $params['participant_role'];
1025 }
1026
1027 if (array_key_exists('participant_role_id', $params)) {
1028 $params['defaultRole'] = 0;
1029 }
1030 if (!CRM_Utils_Array::value('participant_role_id', $params) &&
1031 $this->_values['event']['default_role_id']
1032 ) {
1033 $params['participant_role_id'] = $this->_values['event']['default_role_id'];
1034 }
1035
1036 $config = CRM_Core_Config::singleton();
1037 $params['currencyID'] = $config->defaultCurrency;
1038
1039 if ($this->_values['event']['is_monetary']) {
1040 // we first reset the confirm page so it accepts new values
1041 $this->controller->resetPage('Confirm');
1042
1043 //added for discount
1044 $discountId = CRM_Core_BAO_Discount::findSet($this->_eventId, 'civicrm_event');
1045
1046 if (!empty($this->_values['discount'][$discountId])) {
1047 $params['discount_id'] = $discountId;
1048 $params['amount_level'] = $this->_values['discount'][$discountId][$params['amount']]['label'];
1049
1050 $params['amount'] = $this->_values['discount'][$discountId][$params['amount']]['value'];
1051 }
1052 elseif (empty($params['priceSetId'])) {
1053 $params['amount_level'] = $this->_values['fee'][$params['amount']]['label'];
1054 $params['amount'] = $this->_values['fee'][$params['amount']]['value'];
1055 }
1056 else {
1057 $lineItem = array();
1058 CRM_Price_BAO_Set::processAmount($this->_values['fee'], $params, $lineItem);
1059 $this->set('lineItem', array($lineItem));
1060 $this->set('lineItemParticipantsCount', array($primaryParticipantCount));
1061 }
1062
1063 $this->set('amount', $params['amount']);
1064 $this->set('amount_level', $params['amount_level']);
1065
1066 // generate and set an invoiceID for this transaction
1067 $invoiceID = md5(uniqid(rand(), TRUE));
1068 $this->set('invoiceID', $invoiceID);
1069
1070 if (is_array($this->_paymentProcessor)) {
1071 $payment = CRM_Core_Payment::singleton($this->_mode, $this->_paymentProcessor, $this);
1072 }
1073 // default mode is direct
1074 $this->set('contributeMode', 'direct');
1075
1076 if (isset($params["state_province_id-{$this->_bltID}"]) &&
1077 $params["state_province_id-{$this->_bltID}"]
1078 ) {
1079 $params["state_province-{$this->_bltID}"] = CRM_Core_PseudoConstant::stateProvinceAbbreviation($params["state_province_id-{$this->_bltID}"]);
1080 }
1081
1082 if (isset($params["country_id-{$this->_bltID}"]) &&
1083 $params["country_id-{$this->_bltID}"]
1084 ) {
1085 $params["country-{$this->_bltID}"] = CRM_Core_PseudoConstant::countryIsoCode($params["country_id-{$this->_bltID}"]);
1086 }
1087 if (isset($params['credit_card_exp_date'])) {
1088 $params['year'] = CRM_Core_Payment_Form::getCreditCardExpirationYear($params);
1089 $params['month'] = CRM_Core_Payment_Form::getCreditCardExpirationMonth($params);
1090 }
1091 if ($this->_values['event']['is_monetary']) {
1092 $params['ip_address'] = CRM_Utils_System::ipAddress();
1093 $params['currencyID'] = $config->defaultCurrency;
1094 $params['payment_action'] = 'Sale';
1095 $params['invoiceID'] = $invoiceID;
1096 }
1097
1098 $this->_params = array();
1099 $this->_params[] = $params;
1100 $this->set('params', $this->_params);
1101
1102 if ($this->_paymentProcessor['billing_mode'] & CRM_Core_Payment::BILLING_MODE_BUTTON) {
1103 //get the button name
1104 $buttonName = $this->controller->getButtonName();
1105 if (in_array($buttonName,
1106 array(
1107 $this->_expressButtonName,
1108 $this->_expressButtonName . '_x',
1109 $this->_expressButtonName . '_y',
1110 )
1111 ) &&
1112 !CRM_Utils_Array::value('is_pay_later', $params) &&
1113 !$this->_allowWaitlist &&
1114 !$this->_requireApproval
1115 ) {
1116 $this->set('contributeMode', 'express');
1117
1118 // Send Event Name & Id in Params
1119 $params['eventName'] = $this->_values['event']['title'];
1120 $params['eventId'] = $this->_values['event']['id'];
1121
1122 $params['cancelURL'] = CRM_Utils_System::url('civicrm/event/register',
1123 "_qf_Register_display=1&qfKey={$this->controller->_key}",
1124 TRUE, NULL, FALSE
1125 );
1126 if (CRM_Utils_Array::value('additional_participants', $params, FALSE)) {
1127 $urlArgs = "_qf_Participant_1_display=1&rfp=1&qfKey={$this->controller->_key}";
1128 }
1129 else {
1130 $urlArgs = "_qf_Confirm_display=1&rfp=1&qfKey={$this->controller->_key}";
1131 }
1132 $params['returnURL'] = CRM_Utils_System::url('civicrm/event/register',
1133 $urlArgs,
1134 TRUE, NULL, FALSE
1135 );
1136 $params['invoiceID'] = $invoiceID;
1137
1138 //default action is Sale
1139 $params['payment_action'] = 'Sale';
1140
1141 $token = $payment->setExpressCheckout($params);
1142 if (is_a($token, 'CRM_Core_Error')) {
1143 CRM_Core_Error::displaySessionError($token);
1144 CRM_Utils_System::redirect($params['cancelURL']);
1145 }
1146
1147 $this->set('token', $token);
1148
1149 $paymentURL = $this->_paymentProcessor['url_site'] . "/cgi-bin/webscr?cmd=_express-checkout&token=$token";
1150
1151 CRM_Utils_System::redirect($paymentURL);
1152 }
1153 }
1154 elseif ($this->_paymentProcessor['billing_mode'] & CRM_Core_Payment::BILLING_MODE_NOTIFY) {
1155 $this->set('contributeMode', 'notify');
1156 }
1157 }
1158 else {
1159 $session = CRM_Core_Session::singleton();
1160 $params['description'] = ts('Online Event Registration') . ' ' . $this->_values['event']['title'];
1161
1162 $this->_params = array();
1163 $this->_params[] = $params;
1164 $this->set('params', $this->_params);
1165
1166 if (!CRM_Utils_Array::value('additional_participants', $params)) {
1167 self::processRegistration($this->_params);
1168 }
1169 }
1170
1171 // If registering > 1 participant, give status message
1172 if (CRM_Utils_Array::value('additional_participants', $params, FALSE)) {
1173 $statusMsg = ts('Registration information for participant 1 has been saved.');
1174 CRM_Core_Session::setStatus($statusMsg, ts('Saved'), 'success');
1175 }
1176 }
1177 //end of function
1178
1179 /*
168e792f 1180 * Function to process Registration of free event
6a488035 1181 *
168e792f
DL
1182 * @param array $param Form valuess
1183 * @param int contactID
6a488035 1184 *
168e792f
DL
1185 * @return None
1186 * access public
6a488035
TO
1187 *
1188 */
1189 public function processRegistration($params, $contactID = NULL) {
1190 $session = CRM_Core_Session::singleton();
1191 $this->_participantInfo = array();
1192
1193 // CRM-4320, lets build array of cancelled additional participant ids
1194 // those are drop or skip by primary at the time of confirmation.
1195 // get all in and then unset those are confirmed.
1196 $cancelledIds = $this->_additionalParticipantIds;
1197
1198 $participantCount = array();
1199 foreach ($params as $participantNum => $record) {
1200 if ($record == 'skip') {
1201 $participantCount[$participantNum] = 'skip';
1202 }
1203 elseif ($participantNum) {
1204 $participantCount[$participantNum] = 'participant';
1205 }
1206 }
1207
1208 $registerByID = NULL;
1209 foreach ($params as $key => $value) {
1210 if ($value != 'skip') {
1211 $fields = NULL;
1212
1213 // setting register by Id and unset contactId.
1214 if (!CRM_Utils_Array::value('is_primary', $value)) {
1215 $contactID = NULL;
1216 $registerByID = $this->get('registerByID');
1217 if ($registerByID) {
1218 $value['registered_by_id'] = $registerByID;
1219 }
1220 // get an email if one exists for the participant
1221 $participantEmail = '';
1222 foreach (array_keys($value) as $valueName) {
1223 if (substr($valueName, 0, 6) == 'email-') {
1224 $participantEmail = $value[$valueName];
1225 }
1226 }
1227 if ($participantEmail) {
1228 $this->_participantInfo[] = $participantEmail;
1229 }
1230 else {
1231 $this->_participantInfo[] = $value['first_name'] . ' ' . $value['last_name'];
1232 }
1233 }
1234 elseif (CRM_Utils_Array::value('contact_id', $value)) {
1235 $contactID = $value['contact_id'];
1236 }
1237 else {
1238 $contactID = parent::getContactID();
1239 }
1240
1241 CRM_Event_Form_Registration_Confirm::fixLocationFields($value, $fields);
1242 //for free event or additional participant, dont create billing email address.
1243 if (!CRM_Utils_Array::value('is_primary', $value) || !$this->_values['event']['is_monetary']) {
1244 unset($value["email-{$this->_bltID}"]);
1245 }
1246
1247 $contactID = CRM_Event_Form_Registration_Confirm::updateContactFields($contactID, $value, $fields);
1248
1249 // lets store the contactID in the session
1250 // we dont store in userID in case the user is doing multiple
1251 // transactions etc
1252 // for things like tell a friend
1253 if (!parent::getContactID() && CRM_Utils_Array::value('is_primary', $value)) {
1254 $session->set('transaction.userID', $contactID);
1255 }
1256
1257 //lets get the status if require approval or waiting.
1258
1259 $waitingStatuses = CRM_Event_PseudoConstant::participantStatus(NULL, "class = 'Waiting'");
1260 if ($this->_allowWaitlist && !$this->_allowConfirmation) {
1261 $value['participant_status_id'] = $value['participant_status'] = array_search('On waitlist', $waitingStatuses);
1262 }
1263 elseif ($this->_requireApproval && !$this->_allowConfirmation) {
1264 $value['participant_status_id'] = $value['participant_status'] = array_search('Awaiting approval', $waitingStatuses);
1265 }
1266
1267 $this->set('value', $value);
1268 $this->confirmPostProcess($contactID, NULL, NULL);
1269
1270 //lets get additional participant id to cancel.
1271 if ($this->_allowConfirmation && is_array($cancelledIds)) {
1272 $additonalId = CRM_Utils_Array::value('participant_id', $value);
1273 if ($additonalId && $key = array_search($additonalId, $cancelledIds)) {
1274 unset($cancelledIds[$key]);
1275 }
1276 }
1277 }
1278 }
1279
1280 // update status and send mail to cancelled additonal participants, CRM-4320
1281 if ($this->_allowConfirmation && is_array($cancelledIds) && !empty($cancelledIds)) {
1282 $cancelledId = array_search('Cancelled',
1283 CRM_Event_PseudoConstant::participantStatus(NULL, "class = 'Negative'")
1284 );
1285 CRM_Event_BAO_Participant::transitionParticipants($cancelledIds, $cancelledId);
1286 }
1287
1288 //set information about additional participants if exists
1289 if (count($this->_participantInfo)) {
1290 $this->set('participantInfo', $this->_participantInfo);
1291 }
1292
1293 //send mail Confirmation/Receipt
1294 if ($this->_contributeMode != 'checkout' ||
1295 $this->_contributeMode != 'notify'
1296 ) {
1297 $isTest = FALSE;
1298 if ($this->_action & CRM_Core_Action::PREVIEW) {
1299 $isTest = TRUE;
1300 }
1301
1302 //handle if no additional participant.
1303 if (!$registerByID) {
1304 $registerByID = $this->get('registerByID');
1305 }
1306 $primaryContactId = $this->get('primaryContactId');
1307
1308 //build an array of custom profile and assigning it to template.
1309 $additionalIDs = CRM_Event_BAO_Event::buildCustomProfile($registerByID, NULL,
1310 $primaryContactId, $isTest, TRUE
1311 );
1312
1313 //lets carry all paticipant params w/ values.
1314 foreach ($additionalIDs as $participantID => $contactId) {
1315 $participantNum = NULL;
1316 if ($participantID == $registerByID) {
1317 $participantNum = 0;
1318 }
1319 else {
1320 if ($participantNum = array_search('participant', $participantCount)) {
1321 unset($participantCount[$participantNum]);
1322 }
1323 }
1324
1325 if ($participantNum === NULL) {
1326 break;
1327 }
1328
1329 //carry the participant submitted values.
1330 $this->_values['params'][$participantID] = $params[$participantNum];
1331 }
1332
1333 //lets send mails to all with meanigful text, CRM-4320.
1334 $this->assign('isOnWaitlist', $this->_allowWaitlist);
1335 $this->assign('isRequireApproval', $this->_requireApproval);
1336
1337 foreach ($additionalIDs as $participantID => $contactId) {
1338 if ($participantID == $registerByID) {
1339 //set as Primary Participant
1340 $this->assign('isPrimary', 1);
1341
1342 $customProfile = CRM_Event_BAO_Event::buildCustomProfile($participantID, $this->_values, NULL, $isTest);
1343
1344 if (count($customProfile)) {
1345 $this->assign('customProfile', $customProfile);
1346 $this->set('customProfile', $customProfile);
1347 }
1348 }
1349 else {
1350 $this->assign('isPrimary', 0);
1351 $this->assign('customProfile', NULL);
1352 }
1353
1354 //send Confirmation mail to Primary & additional Participants if exists
1355 CRM_Event_BAO_Event::sendMail($contactId, $this->_values, $participantID, $isTest);
1356 }
1357 }
1358 }
1359
1360 /**
1361 * Method to check if the user is already registered for the event
1362 * and if result found redirect to the event info page
1363 *
1364 * @param array $fields the input form values(anonymous user)
1365 * @param array $self event data
168e792f
DL
1366 * @param boolean $isAdditional treat isAdditional participants a bit differently
1367 * @param boolean $returnContactId just find and return the contactID match to use
1368 * @param boolean $useDedupeRules force usage of dedupe rules
6a488035
TO
1369 *
1370 * @return void
1371 * @access public
1372 */
178073d6 1373 static function checkRegistration($fields, &$self, $isAdditional = FALSE, $returnContactId = FALSE, $useDedupeRules = FALSE) {
6a488035
TO
1374 // CRM-3907, skip check for preview registrations
1375 // CRM-4320 participant need to walk wizard
1376 if (!$returnContactId &&
1377 ($self->_mode == 'test' || $self->_allowConfirmation)
1378 ) {
1379 return FALSE;
1380 }
1381
1382 $contactID = NULL;
1383 $session = CRM_Core_Session::singleton();
1384 if (!$isAdditional) {
1385 $contactID = parent::getContactID();
1386 }
1387
178073d6 1388 if (!$contactID && is_array($fields) && $fields) {
6a488035
TO
1389
1390 //CRM-6996
1391 //as we are allowing w/ same email address,
1392 //lets check w/ other contact params.
1393 if ($self->_values['event']['allow_same_participant_emails']) {
1394 $params = $fields;
1395 $level = ($isAdditional) ? 'Supervised' : 'Unsupervised';
1396
1397 $dedupeParams = CRM_Dedupe_Finder::formatParams($params, 'Individual');
1398
1399 // disable permission based on cache since event registration is public page/feature.
1400 $dedupeParams['check_permission'] = FALSE;
1401 $ids = CRM_Dedupe_Finder::dupesByParams($dedupeParams, 'Individual', $level);
1402 $contactID = CRM_Utils_Array::value(0, $ids);
1403 }
1404 else {
1405 foreach ($fields as $fieldname => $fieldvalue) {
1406 if (substr($fieldname, 0, 6) == 'email-') {
1407 $emailString = trim($fieldvalue);
1408 if (!empty($emailString)) {
1409 $match = CRM_Contact_BAO_Contact::matchContactOnEmail($emailString, 'Individual');
1410 if (!empty($match)) {
1411 $contactID = $match->contact_id;
1412 }
1413 }
1414 }
1415 }
1416 }
1417 }
1418
1419 if ($returnContactId) {
1420 // CRM-7377
1421 // return contactID if contact already exists
1422 return $contactID;
1423 }
1424
1425 if ($contactID) {
1426 $participant = new CRM_Event_BAO_Participant();
1427 $participant->contact_id = $contactID;
1428 $participant->event_id = $self->_values['event']['id'];
1429 if (!empty($fields['participant_role']) && is_numeric($fields['participant_role'])) {
1430 $participant->role_id = $fields['participant_role'];
1431 }
1432 else {
1433 $participant->role_id = $self->_values['event']['default_role_id'];
1434 }
1435 $participant->is_test = 0;
1436 $participant->find();
1437 $statusTypes = CRM_Event_PseudoConstant::participantStatus(NULL, 'is_counted = 1');
1438 while ($participant->fetch()) {
1439 if (array_key_exists($participant->status_id, $statusTypes)) {
1440 if (!$isAdditional && !$self->_values['event']['allow_same_participant_emails']) {
1441 $registerUrl = CRM_Utils_System::url('civicrm/event/register',
1442 "reset=1&id={$self->_values['event']['id']}&cid=0"
1443 );
1444 if ($self->_pcpId) {
1445 $registerUrl .= '&pcpId=' . $self->_pcpId;
1446 }
1447
1448 $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));
1449 $session->setStatus($status, ts('Oops.'), 'alert');
1450 $url = CRM_Utils_System::url('civicrm/event/info',
1451 "reset=1&id={$self->_values['event']['id']}&noFullMsg=true"
1452 );
1453 if ($self->_action & CRM_Core_Action::PREVIEW) {
1454 $url .= '&action=preview';
1455 }
1456
1457 if ($self->_pcpId) {
1458 $url .= '&pcpId=' . $self->_pcpId;
1459 }
1460
1461 CRM_Utils_System::redirect($url);
1462 }
1463
1464 if ($isAdditional) {
1465 $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.");
1466 $session->setStatus($status, ts('Oops.'), 'alert');
1467 return $participant->id;
1468 }
1469 }
1470 }
1471 }
1472 }
1473}
1474