3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.6 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2014 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
32 * @copyright CiviCRM LLC (c) 2004-2014
38 * This class generates form components for processing Event
41 class CRM_Event_Form_Registration_Register
extends CRM_Event_Form_Registration
{
44 * The fields involved in this page
50 * The defaults involved in this page
56 * The status message that user view.
59 protected $_waitlistMsg = NULL;
60 protected $_requireApprovalMsg = NULL;
62 public $_quickConfig = NULL;
65 * Allow developer to use hook_civicrm_buildForm()
66 * to override the registration dupe check
69 public $_skipDupeRegistrationCheck = FALSE;
71 public $_paymentProcessorID;
75 * @var boolean determines if fee block should be shown or hidden
80 * Array of payment related fields to potentially display on this form (generally credit card or debit card fields). This is rendered via billingBlock.tpl
83 public $_paymentFields = array();
86 * Set variables up before form is built
90 public function preProcess() {
94 //here we can't use parent $this->_allowWaitlist as user might
95 //walk back and we might set this value in this postProcess.
96 //(we set when spaces < group count and want to allow become part of waiting )
97 $eventFull = CRM_Event_BAO_Participant
::eventFull($this->_eventId
, FALSE, CRM_Utils_Array
::value('has_waitlist', $this->_values
['event']));
99 // Get payment processors if appropriate for this event
100 // We hide the payment fields if the event is full or requires approval,
101 // and the current user has not yet been approved CRM-12279
102 $this->_noFees
= (($eventFull ||
$this->_requireApproval
) && !$this->_allowConfirmation
);
103 CRM_Contribute_Form_Contribution_Main
::preProcessPaymentOptions($this, $this->_noFees
);
104 if ($this->_snippet
) {
108 $this->_allowWaitlist
= FALSE;
109 if ($eventFull && !$this->_allowConfirmation
&& !empty($this->_values
['event']['has_waitlist'])) {
110 $this->_allowWaitlist
= TRUE;
111 $this->_waitlistMsg
= CRM_Utils_Array
::value('waitlist_text', $this->_values
['event']);
112 if (!$this->_waitlistMsg
) {
113 $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.');
116 $this->set('allowWaitlist', $this->_allowWaitlist
);
118 //To check if the user is already registered for the event(CRM-2426)
119 if (!$this->_skipDupeRegistrationCheck
) {
120 self
::checkRegistration(NULL, $this);
123 $this->assign('availableRegistrations', $this->_availableRegistrations
);
125 // get the participant values from EventFees.php, CRM-4320
126 if ($this->_allowConfirmation
) {
127 CRM_Event_Form_EventFees
::preProcess($this);
132 * Set default values for the form. For edit/view mode
133 * the default values are retrieved from the database
134 * Adding discussion from CRM-11915 as code comments
135 * When multiple payment processors are configured for a event and user does any selection changes for them on online event registeration page :
136 * The 'Register' page gets loaded through ajax and following happens :
137 * the setDefaults function is called with the variable _ppType set with selected payment processor type,
138 * 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.
139 *- For payment processors of billing mode 'Notify' - return from setDefaults before the code for billing profile population execution .
140 * (done this is because for payment processors with 'Notify' mode billing profile form doesn't get rendered on UI)
145 public function setDefaultValues() {
146 if ($this->_paymentProcessorID
&& $this->_snippet
&& !($this->_paymentProcessor
['billing_mode'] & CRM_Core_Payment
::BILLING_MODE_FORM
)) {
147 // see function comment block for explanation of this. Note that CRM-15555 will require this to look at the billing form fields not the
148 // billing_mode which
151 $this->_defaults
= array();
152 $contactID = $this->getContactID();
153 $billingDefaults = $this->getProfileDefaults('Billing', $contactID);
154 $this->_defaults
= array_merge($this->_defaults
, $billingDefaults);
156 $config = CRM_Core_Config
::singleton();
157 // set default country from config if no country set
158 // note the effect of this is to set the billing country to default to the site default
159 // country if the person has an address but no country (for anonymous country is set above)
160 // this could have implications if the billing profile is filled but hidden.
161 // this behaviour has been in place for a while but the use of js to hide things has increased
162 if (empty($this->_defaults
["billing_country_id-{$this->_bltID}"])) {
163 $this->_defaults
["billing_country_id-{$this->_bltID}"] = $config->defaultContactCountry
;
166 // set default state/province from config if no state/province set
167 if (empty($this->_defaults
["billing_state_province_id-{$this->_bltID}"])) {
168 $this->_defaults
["billing_state_province_id-{$this->_bltID}"] = $config->defaultContactStateProvince
;
171 if ($this->_snippet
) {
172 return $this->_defaults
;
178 if (!empty($this->_fields
)) {
179 $removeCustomFieldTypes = array('Participant');
180 foreach ($this->_fields
as $name => $dontCare) {
181 if (substr($name, 0, 7) == 'custom_') {
182 $id = substr($name, 7);
183 if (!$this->_allowConfirmation
&&
184 !CRM_Core_BAO_CustomGroup
::checkCustomField($id, $removeCustomFieldTypes)
188 // ignore component fields
190 elseif ((substr($name, 0, 12) == 'participant_')) {
198 if (!empty($fields)) {
199 CRM_Core_BAO_UFGroup
::setProfileDefaults($contactID, $fields, $this->_defaults
);
202 // Set default payment processor as default payment_processor radio button value
203 if (!empty($this->_paymentProcessors
)) {
204 foreach ($this->_paymentProcessors
as $pid => $value) {
205 if (!empty($value['is_default'])) {
206 $this->_defaults
['payment_processor'] = $pid;
211 //if event is monetary and pay later is enabled and payment
212 //processor is not available then freeze the pay later checkbox with
214 if (!empty($this->_values
['event']['is_pay_later']) &&
215 !is_array($this->_paymentProcessor
)
217 $this->_defaults
['is_pay_later'] = 1;
220 //set custom field defaults
221 if (!empty($this->_fields
)) {
222 //load default campaign from page.
223 if (array_key_exists('participant_campaign_id', $this->_fields
)) {
224 $this->_defaults
['participant_campaign_id'] = CRM_Utils_Array
::value('campaign_id',
225 $this->_values
['event']
229 foreach ($this->_fields
as $name => $field) {
230 if ($customFieldID = CRM_Core_BAO_CustomField
::getKeyID($name)) {
232 if (!isset($this->_defaults
[$name])) {
233 CRM_Core_BAO_CustomField
::setProfileDefaults($customFieldID, $name, $this->_defaults
,
234 NULL, CRM_Profile_Form
::MODE_REGISTER
241 //fix for CRM-3088, default value for discount set.
243 if (!empty($this->_values
['discount'])) {
244 $discountId = CRM_Core_BAO_Discount
::findSet($this->_eventId
, 'civicrm_event');
246 if (isset($this->_values
['event']['default_discount_fee_id'])) {
247 $discountKey = CRM_Core_DAO
::getFieldValue('CRM_Core_DAO_OptionValue',
248 $this->_values
['event']['default_discount_fee_id'],
252 $this->_defaults
['amount'] = key(array_slice($this->_values
['discount'][$discountId],
253 $discountKey - 1, $discountKey, TRUE
259 // add this event's default participant role to defaults array
260 // (for cases where participant_role field is included in form via profile)
261 if ($this->_values
['event']['default_role_id']) {
262 $this->_defaults
['participant_role'] =
263 $this->_defaults
['participant_role_id'] = $this->_values
['event']['default_role_id'];
265 if ($this->_priceSetId
&& !empty($this->_feeBlock
)) {
266 foreach ($this->_feeBlock
as $key => $val) {
267 foreach ($val['options'] as $keys => $values) {
268 if ($values['is_default'] && empty($values['is_full'])) {
270 if ($val['html_type'] == 'CheckBox') {
271 $this->_defaults
["price_{$key}"][$keys] = 1;
274 $this->_defaults
["price_{$key}"] = $keys;
281 //set default participant fields, CRM-4320.
282 $hasAdditionalParticipants = FALSE;
283 if ($this->_allowConfirmation
) {
284 $this->_contactId
= $contactID;
285 $this->_discountId
= $discountId;
286 $forcePayLater = CRM_Utils_Array
::value('is_pay_later', $this->_defaults
, FALSE);
287 $this->_defaults
= array_merge($this->_defaults
, CRM_Event_Form_EventFees
::setDefaultValues($this));
288 $this->_defaults
['is_pay_later'] = $forcePayLater;
290 if ($this->_additionalParticipantIds
) {
291 $hasAdditionalParticipants = TRUE;
292 $this->_defaults
['additional_participants'] = count($this->_additionalParticipantIds
);
295 $this->assign('hasAdditionalParticipants', $hasAdditionalParticipants);
297 // //hack to simplify credit card entry for testing
298 // $this->_defaults['credit_card_type'] = 'Visa';
299 // $this->_defaults['credit_card_number'] = '4807731747657838';
300 // $this->_defaults['cvv2'] = '000';
301 // $this->_defaults['credit_card_exp_date'] = array( 'Y' => '2010', 'M' => '05' );
303 // to process Custom data that are appended to URL
304 $getDefaults = CRM_Core_BAO_CustomGroup
::extractGetParams($this, "'Contact', 'Individual', 'Contribution', 'Participant'");
305 if (!empty($getDefaults)) {
306 $this->_defaults
= array_merge($this->_defaults
, $getDefaults);
309 return $this->_defaults
;
313 * Build the form object
317 public function buildQuickForm() {
318 // build profiles first so that we can determine address fields etc
319 // and then show copy address checkbox
320 $this->buildCustom($this->_values
['custom_pre_id'], 'customPre');
321 $this->buildCustom($this->_values
['custom_post_id'], 'customPost');
323 if (!empty($this->_fields
) && !empty($this->_values
['custom_pre_id'])) {
324 $profileAddressFields = array();
325 foreach ($this->_fields
as $key => $value) {
326 CRM_Core_BAO_UFField
::assignAddressField($key, $profileAddressFields, array(
327 'uf_group_id' => $this->_values
['custom_pre_id']
330 $this->set('profileAddressFields', $profileAddressFields);
333 CRM_Core_Payment_ProcessorForm
::buildQuickForm($this);
334 // Return if we are in an ajax callback
335 if ($this->_snippet
) {
339 $contactID = $this->getContactID();
340 $this->assign('contact_id', $contactID);
341 $this->assign('display_name', CRM_Contact_BAO_Contact
::displayName($contactID));
343 $this->add('hidden', 'scriptFee', NULL);
344 $this->add('hidden', 'scriptArray', NULL);
346 $bypassPayment = $allowGroupOnWaitlist = $isAdditionalParticipants = FALSE;
347 if ($this->_values
['event']['is_multiple_registrations']) {
348 // don't allow to add additional during confirmation if not preregistered.
349 if (!$this->_allowConfirmation ||
$this->_additionalParticipantIds
) {
350 // Hardcode maximum number of additional participants here for now. May need to make this configurable per event.
351 // Label is value + 1, since the code sees this is ADDITIONAL participants (in addition to "self")
352 $additionalOptions = array(
353 '' => '1', 1 => '2', 2 => '3', 3 => '4', 4 => '5',
354 5 => '6', 6 => '7', 7 => '8', 8 => '9', 9 => '10',
356 $element = $this->add('select', 'additional_participants',
357 ts('How many people are you registering?'),
360 array('onChange' => "allowParticipant()")
362 $isAdditionalParticipants = TRUE;
366 //hack to allow group to register w/ waiting
367 if ((!empty($this->_values
['event']['is_multiple_registrations']) ||
370 !$this->_allowConfirmation
&&
371 is_numeric($this->_availableRegistrations
) && !empty($this->_values
['event']['has_waitlist'])) {
372 $bypassPayment = TRUE;
373 //case might be group become as a part of waitlist.
374 //If not waitlist then they require admin approve.
375 $allowGroupOnWaitlist = TRUE;
376 $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
));
378 if ($this->_requireApproval
) {
379 $this->_requireApprovalMsg
= CRM_Utils_Array
::value('approval_req_text', $this->_values
['event'],
380 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.')
385 //case where only approval needed - no waitlist.
386 if ($this->_requireApproval
&&
387 !$this->_allowWaitlist
&& !$bypassPayment
389 $this->_requireApprovalMsg
= CRM_Utils_Array
::value('approval_req_text', $this->_values
['event'],
390 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.')
394 //lets display status to primary page only.
395 $this->assign('waitlistMsg', $this->_waitlistMsg
);
396 $this->assign('requireApprovalMsg', $this->_requireApprovalMsg
);
397 $this->assign('allowGroupOnWaitlist', $allowGroupOnWaitlist);
398 $this->assign('isAdditionalParticipants', $isAdditionalParticipants);
400 //lets get js on two different qf elements.
401 $showHidePayfieldName = NULL;
402 $showHidePaymentInformation = FALSE;
403 if ($this->_values
['event']['is_monetary']) {
404 self
::buildAmount($this);
408 //@todo this processor adding fn is another one duplicated on contribute - a shared
409 // common class would make this sort of thing extractable
410 $onlinePaymentProcessorEnabled = FALSE;
411 if (!empty($this->_paymentProcessors
)) {
412 foreach ($this->_paymentProcessors
as $key => $name) {
413 if($name['billing_mode'] == 1) {
414 $onlinePaymentProcessorEnabled = TRUE;
416 $pps[$key] = $name['name'];
419 if($this->getContactID() === '0' && !$this->_values
['event']['is_multiple_registrations']) {
420 //@todo we are blocking for multiple registrations because we haven't tested
421 $this->addCidZeroOptions($onlinePaymentProcessorEnabled);
423 if (!empty($this->_values
['event']['is_pay_later']) &&
424 ($this->_allowConfirmation ||
(!$this->_requireApproval
&& !$this->_allowWaitlist
))
426 $pps[0] = $this->_values
['event']['pay_later_text'];
429 if ($this->_values
['event']['is_monetary']) {
430 if (count($pps) > 1) {
431 $this->addRadio('payment_processor', ts('Payment Method'), $pps,
435 elseif (!empty($pps)) {
436 $ppKeys = array_keys($pps);
437 $currentPP = array_pop($ppKeys);
438 $this->addElement('hidden', 'payment_processor', $currentPP);
442 //lets add some qf element to bypass payment validations, CRM-4320
443 if ($bypassPayment) {
444 $this->addElement('hidden', 'bypass_payment', NULL, array('id' => 'bypass_payment'));
446 $this->assign('bypassPayment', $bypassPayment);
447 $this->assign('showHidePaymentInformation', $showHidePaymentInformation);
449 $userID = $this->getContactID();
452 $createCMSUser = FALSE;
454 if ($this->_values
['custom_pre_id']) {
455 $profileID = $this->_values
['custom_pre_id'];
456 $createCMSUser = CRM_Core_DAO
::getFieldValue('CRM_Core_DAO_UFGroup', $profileID, 'is_cms_user');
459 if (!$createCMSUser &&
460 $this->_values
['custom_post_id']
462 if (!is_array($this->_values
['custom_post_id'])) {
463 $profileIDs = array($this->_values
['custom_post_id']);
466 $profileIDs = $this->_values
['custom_post_id'];
468 foreach ($profileIDs as $pid) {
469 if (CRM_Core_DAO
::getFieldValue('CRM_Core_DAO_UFGroup', $pid, 'is_cms_user')) {
471 $createCMSUser = TRUE;
477 if ($createCMSUser) {
478 CRM_Core_BAO_CMSUser
::buildForm($this, $profileID, TRUE);
482 //we have to load confirm contribution button in template
483 //when multiple payment processor as the user
484 //can toggle with payment processor selection
485 $billingModePaymentProcessors = 0;
486 if (!CRM_Utils_System
::isNull($this->_paymentProcessors
)) {
487 foreach ($this->_paymentProcessors
as $key => $values) {
488 if ($values['billing_mode'] == CRM_Core_Payment
::BILLING_MODE_BUTTON
) {
489 $billingModePaymentProcessors++
;
494 if ($billingModePaymentProcessors && count($this->_paymentProcessors
) == $billingModePaymentProcessors) {
495 $allAreBillingModeProcessors = TRUE;
498 $allAreBillingModeProcessors = FALSE;
501 if (!$allAreBillingModeProcessors ||
!empty($this->_values
['event']['is_pay_later']) ||
$bypassPayment
504 //freeze button to avoid multiple calls.
507 if (empty($this->_values
['event']['is_monetary'])) {
508 $js = array('onclick' => "return submitOnce(this,'" . $this->_name
. "','" . ts('Processing') . "');");
511 // CRM-11182 - Optional confirmation screen
512 // Change button label depending on whether the next action is confirm or register
514 !$this->_values
['event']['is_multiple_registrations']
515 && !$this->_values
['event']['is_monetary']
516 && !$this->_values
['event']['is_confirm_enabled']
518 $buttonLabel = ts('Register >>');
521 $buttonLabel = ts('Continue >>');
524 $this->addButtons(array(
527 'name' => $buttonLabel,
528 'spacing' => ' ',
536 $this->addFormRule(array('CRM_Event_Form_Registration_Register', 'formRule'), $this);
540 CRM_PCP_BAO_PCP
::buildPcp($this->_pcpId
, $this);
545 * Build the radio/text form elements for the amount field
547 * @param CRM_Core_Form $form
549 * @param bool $required
550 * True if you want to add formRule.
551 * @param int $discountId
552 * Discount id for the event.
557 static public function buildAmount(&$form, $required = TRUE, $discountId = NULL) {
558 // build amount only when needed, skip incase of event full and waitlisting is enabled
559 // and few other conditions check preProcess()
560 if (property_exists($form, '_noFees') && $form->_noFees
) {
564 //if payment done, no need to build the fee block.
565 if (!empty($form->_paymentId
)) {
566 //fix to display line item in update mode.
567 $form->assign('priceSet', isset($form->_priceSet
) ?
$form->_priceSet
: NULL);
571 $feeFields = CRM_Utils_Array
::value('fee', $form->_values
);
573 if (is_array($feeFields)) {
574 $form->_feeBlock
= &$form->_values
['fee'];
577 //check for discount.
578 $discountedFee = CRM_Utils_Array
::value('discount', $form->_values
);
579 if (is_array($discountedFee) && !empty($discountedFee)) {
581 $form->_discountId
= $discountId = CRM_Core_BAO_Discount
::findSet($form->_eventId
, 'civicrm_event');
584 $form->_feeBlock
= &$form->_values
['discount'][$discountId];
587 if (!is_array($form->_feeBlock
)) {
588 $form->_feeBlock
= array();
591 //its time to call the hook.
592 CRM_Utils_Hook
::buildAmount('event', $form, $form->_feeBlock
);
594 //reset required if participant is skipped.
595 $button = substr($form->controller
->getButtonName(), -4);
596 if ($required && $button == 'skip') {
600 $className = CRM_Utils_System
::getClassName($form);
602 //build the priceset fields.
603 if (isset($form->_priceSetId
) && $form->_priceSetId
) {
605 //format price set fields across option full.
606 self
::formatFieldsForOptionFull($form);
608 if (!empty($form->_priceSet
['is_quick_config'])) {
609 $form->_quickConfig
= $form->_priceSet
['is_quick_config'];
611 $form->add('hidden', 'priceSetId', $form->_priceSetId
);
613 // CRM-14492 Admin price fields should show up on event registration if user has 'administer CiviCRM' permissions
614 $adminFieldVisible = false;
615 if (CRM_Core_Permission
::check('administer CiviCRM')) {
616 $adminFieldVisible = true;
619 foreach ($form->_feeBlock
as $field) {
620 // public AND admin visibility fields are included for back-office registration and back-office change selections
621 if (CRM_Utils_Array
::value('visibility', $field) == 'public' ||
622 (CRM_Utils_Array
::value('visibility', $field) == 'admin' && $adminFieldVisible == true) ||
623 $className == 'CRM_Event_Form_Participant' ||
624 $className == 'CRM_Event_Form_ParticipantFeeSelection'
626 $fieldId = $field['id'];
627 $elementName = 'price_' . $fieldId;
629 $isRequire = CRM_Utils_Array
::value('is_required', $field);
630 if ($button == 'skip') {
634 //user might modified w/ hook.
635 $options = CRM_Utils_Array
::value('options', $field);
636 if (!is_array($options)) {
640 $optionFullIds = CRM_Utils_Array
::value('option_full_ids', $field, array());
642 //soft suppress required rule when option is full.
643 if (!empty($optionFullIds) && (count($options) == count($optionFullIds))) {
648 CRM_Price_BAO_PriceField
::addQuickFormElement($form,
659 $form->assign('priceSet', $form->_priceSet
);
662 $eventFeeBlockValues = array();
663 foreach ($form->_feeBlock
as $fee) {
664 if (is_array($fee)) {
667 $totalAmountJs = NULL;
668 if ($className == 'CRM_Event_Form_Participant') {
669 $totalAmountJs = array('onClick' => "fillTotalAmount(" . $fee['value'] . ")");
672 $eventFeeBlockValues['amount_id_' . $fee['amount_id']] = $fee['value'];
673 $elements[] = &$form->createElement('radio', NULL, '',
674 CRM_Utils_Money
::format($fee['value']) . ' ' .
681 $form->assign('eventFeeBlockValues', json_encode($eventFeeBlockValues));
683 $form->_defaults
['amount'] = CRM_Utils_Array
::value('default_fee_id', $form->_values
['event']);
684 $element = &$form->addGroup($elements, 'amount', ts('Event Fee(s)'), '<br />');
685 if (isset($form->_online
) && $form->_online
) {
689 $form->addRule('amount', ts('Fee Level is a required field.'), 'required');
695 * @param CRM_Core_Form $form
697 public static function formatFieldsForOptionFull(&$form) {
698 $priceSet = $form->get('priceSet');
699 $priceSetId = $form->get('priceSetId');
700 $defaultPricefieldIds = array();
701 if (!empty($form->_values
['line_items'])) {
702 foreach ($form->_values
['line_items'] as $lineItem) {
703 $defaultPricefieldIds[] = $lineItem['price_field_value_id'];
707 !is_array($priceSet) ||
708 empty($priceSet) ||
empty($priceSet['optionsMaxValueTotal'])) {
712 $skipParticipants = $formattedPriceSetDefaults = array();
713 if (!empty($form->_allowConfirmation
) && (isset($form->_pId
) ||
isset($form->_additionalParticipantId
))) {
714 $participantId = isset($form->_pId
) ?
$form->_pId
: $form->_additionalParticipantId
;
715 $pricesetDefaults = CRM_Event_Form_EventFees
::setDefaultPriceSet($participantId,
718 // modify options full to respect the selected fields
719 // options on confirmation.
720 $formattedPriceSetDefaults = self
::formatPriceSetParams($form, $pricesetDefaults);
722 // to skip current registered participants fields option count on confirmation.
723 $skipParticipants[] = $form->_participantId
;
724 if (!empty($form->_additionalParticipantIds
)) {
725 $skipParticipants = array_merge($skipParticipants, $form->_additionalParticipantIds
);
729 $className = CRM_Utils_System
::getClassName($form);
731 //get the current price event price set options count.
732 $currentOptionsCount = self
::getPriceSetOptionCount($form);
733 $recordedOptionsCount = CRM_Event_BAO_Participant
::priceSetOptionsCount($form->_eventId
, $skipParticipants);
734 $optionFullTotalAmount = 0;
736 foreach ($form->_feeBlock
as & $field) {
737 $optionFullIds = array();
738 $fieldId = $field['id'];
739 if (!is_array($field['options'])) {
742 foreach ($field['options'] as & $option) {
743 $optId = $option['id'];
744 $count = CRM_Utils_Array
::value('count', $option, 0);
745 $maxValue = CRM_Utils_Array
::value('max_value', $option, 0);
746 $dbTotalCount = CRM_Utils_Array
::value($optId, $recordedOptionsCount, 0);
747 $currentTotalCount = CRM_Utils_Array
::value($optId, $currentOptionsCount, 0);
750 $totalCount = $currentTotalCount +
$dbTotalCount;
753 (($totalCount > $maxValue) ||
($totalCount +
$count > $maxValue))
756 $optionFullIds[$optId] = $optId;
757 if ($field['html_type'] != 'Select') {
758 if (in_array($optId, $defaultPricefieldIds)) {
759 $optionFullTotalAmount +
= CRM_Utils_Array
::value('amount', $option);
763 if (!empty($defaultPricefieldIds) && in_array($optId, $defaultPricefieldIds)) {
764 unset($optionFullIds[$optId]);
768 //here option is not full,
769 //but we don't want to allow participant to increase
770 //seats at the time of re-walking registration.
772 !empty($form->_allowConfirmation
) &&
773 !empty($formattedPriceSetDefaults)
775 if (empty($formattedPriceSetDefaults["price_{$field}"]) ||
empty($formattedPriceSetDefaults["price_{$fieldId}"][$optId])) {
776 $optionFullIds[$optId] = $optId;
780 $option['is_full'] = $isFull;
781 $option['db_total_count'] = $dbTotalCount;
782 $option['total_option_count'] = $dbTotalCount +
$currentTotalCount;
785 //ignore option full for offline registration.
786 if ($className == 'CRM_Event_Form_Participant') {
787 $optionFullIds = array();
790 //finally get option ids in.
791 $field['option_full_ids'] = $optionFullIds;
793 $form->assign('optionFullTotalAmount', $optionFullTotalAmount);
799 * @param array $fields
800 * The input form values.
801 * @param array $files
802 * The uploaded files if any.
806 * @return true if no errors, else array of errors
809 public static function formRule($fields, $files, $self) {
811 //check that either an email or firstname+lastname is included in the form(CRM-9587)
812 self
::checkProfileComplete($fields, $errors, $self->_eventId
);
813 //To check if the user is already registered for the event(CRM-2426)
814 if (!$self->_skipDupeRegistrationCheck
) {
815 self
::checkRegistration($fields, $self);
817 //check for availability of registrations.
818 if (!$self->_allowConfirmation
&& empty($fields['bypass_payment']) &&
819 is_numeric($self->_availableRegistrations
) &&
820 CRM_Utils_Array
::value('additional_participants', $fields) >= $self->_availableRegistrations
822 $errors['additional_participants'] = ts("There is only enough space left on this event for %1 participant(s).", array(1 => $self->_availableRegistrations
));
825 // during confirmation don't allow to increase additional participants, CRM-4320
826 if ($self->_allowConfirmation
&& !empty($fields['additional_participants']) &&
827 is_array($self->_additionalParticipantIds
) &&
828 $fields['additional_participants'] > count($self->_additionalParticipantIds
)
830 $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
)));
833 //don't allow to register w/ waiting if enough spaces available.
834 if (!empty($fields['bypass_payment'])) {
835 if (!is_numeric($self->_availableRegistrations
) ||
836 (empty($fields['priceSetId']) && CRM_Utils_Array
::value('additional_participants', $fields) < $self->_availableRegistrations
)
838 $errors['bypass_payment'] = ts("Oops. There are enough available spaces in this event. You can not add yourself to the waiting list.");
842 if (!empty($fields['additional_participants']) &&
843 !CRM_Utils_Rule
::positiveInteger($fields['additional_participants'])
845 $errors['additional_participants'] = ts('Please enter a whole number for Number of additional people.');
848 // priceset validations
849 if (!empty($fields['priceSetId'])) {
851 $formatted = self
::formatPriceSetParams($self, $fields);
852 $ppParams = array($formatted);
853 $priceSetErrors = self
::validatePriceSet($self, $ppParams);
854 $primaryParticipantCount = self
::getParticipantCount($self, $ppParams);
856 //get price set fields errors in.
857 $errors = array_merge($errors, CRM_Utils_Array
::value(0, $priceSetErrors, array()));
859 $totalParticipants = $primaryParticipantCount;
860 if (!empty($fields['additional_participants'])) {
861 $totalParticipants +
= $fields['additional_participants'];
864 if (empty($fields['bypass_payment']) &&
865 !$self->_allowConfirmation
&&
866 is_numeric($self->_availableRegistrations
) &&
867 $self->_availableRegistrations
< $totalParticipants
869 $errors['_qf_default'] = ts("Only %1 Registrations available.", array(1 => $self->_availableRegistrations
));
873 CRM_Price_BAO_PriceSet
::processAmount($self->_values
['fee'], $fields, $lineItem);
874 if ($fields['amount'] < 0) {
875 $errors['_qf_default'] = ts('Event Fee(s) can not be less than zero. Please select the options accordingly');
879 if ($self->_values
['event']['is_monetary']) {
880 if (empty($self->_requireApproval
) && !empty($fields['amount']) && $fields['amount'] > 0 && !isset($fields['payment_processor'])) {
881 $errors['payment_processor'] = ts('Please select a Payment Method');
883 // return if this is express mode
884 if ($self->_paymentProcessor
&&
885 $self->_paymentProcessor
['billing_mode'] & CRM_Core_Payment
::BILLING_MODE_BUTTON
887 if (!empty($fields[$self->_expressButtonName
. '_x']) ||
!empty($fields[$self->_expressButtonName
. '_y']) ||
888 CRM_Utils_Array
::value($self->_expressButtonName
, $fields)
890 return empty($errors) ?
TRUE : $errors;
894 $isZeroAmount = $skipPaymentValidation = FALSE;
895 if (!empty($fields['priceSetId'])) {
896 if (CRM_Utils_Array
::value('amount', $fields) == 0) {
897 $isZeroAmount = TRUE;
900 elseif (!empty($fields['amount']) &&
901 (isset($self->_values
['discount'][$fields['amount']])
902 && CRM_Utils_Array
::value('value', $self->_values
['discount'][$fields['amount']]) == 0
905 $isZeroAmount = TRUE;
907 elseif (!empty($fields['amount']) &&
908 (isset($self->_values
['fee'][$fields['amount']])
909 && CRM_Utils_Array
::value('value', $self->_values
['fee'][$fields['amount']]) == 0
912 $isZeroAmount = TRUE;
915 if ($isZeroAmount && !($self->_forcePayement
&& !empty($fields['additional_participants']))) {
916 $skipPaymentValidation = TRUE;
919 // also return if paylater mode or zero fees for valid members
920 if (!empty($fields['is_pay_later']) ||
!empty($fields['bypass_payment']) ||
921 $skipPaymentValidation ||
922 (!$self->_allowConfirmation
&& ($self->_requireApproval ||
$self->_allowWaitlist
))
924 return empty($errors) ?
TRUE : $errors;
926 if (!empty($self->_paymentFields
)) {
927 CRM_Core_Form
::validateMandatoryFields($self->_paymentFields
, $fields, $errors);
929 CRM_Core_Payment_Form
::validateCreditCard($fields, $errors);
932 foreach (CRM_Contact_BAO_Contact
::$_greetingTypes as $greeting) {
933 if ($greetingType = CRM_Utils_Array
::value($greeting, $fields)) {
934 $customizedValue = CRM_Core_OptionGroup
::getValue($greeting, 'Customized', 'name');
935 if ($customizedValue == $greetingType && empty($fields[$greeting . '_custom'])) {
936 $errors[$greeting . '_custom'] = ts('Custom %1 is a required field if %1 is of type Customized.',
937 array(1 => ucwords(str_replace('_', ' ', $greeting)))
942 return empty($errors) ?
TRUE : $errors;
946 * Check if profiles are complete when event registration occurs(CRM-9587)
949 public static function checkProfileComplete($fields, &$errors, $eventId) {
951 foreach ($fields as $fieldname => $fieldvalue) {
952 if (substr($fieldname, 0, 6) == 'email-' && $fieldvalue) {
953 $email = $fieldvalue;
957 if (!$email && !(!empty($fields['first_name']) && !empty($fields['last_name']))) {
958 $defaults = $params = array('id' => $eventId);
959 CRM_Event_BAO_Event
::retrieve($params, $defaults);
960 $message = ts("Mandatory fields (first name and last name, OR email address) are missing from this form.");
961 $errors['_qf_default'] = $message;
966 * Process the form submission
971 public function postProcess() {
972 // get the submitted form values.
973 $params = $this->controller
->exportValues($this->_name
);
975 //set as Primary participant
976 $params['is_primary'] = 1;
978 if ($this->_values
['event']['is_pay_later']
979 && (!array_key_exists('hidden_processor', $params) ||
$params['payment_processor'] == 0)) {
980 $params['is_pay_later'] = 1;
983 $params['is_pay_later'] = 0;
986 $this->set('is_pay_later', $params['is_pay_later']);
988 // assign pay later stuff
989 $this->_params
['is_pay_later'] = CRM_Utils_Array
::value('is_pay_later', $params, FALSE);
990 $this->assign('is_pay_later', $params['is_pay_later']);
991 if ($params['is_pay_later']) {
992 $this->assign('pay_later_text', $this->_values
['event']['pay_later_text']);
993 $this->assign('pay_later_receipt', $this->_values
['event']['pay_later_receipt']);
996 if (!$this->_allowConfirmation
) {
997 // check if the participant is already registered
998 if (!$this->_skipDupeRegistrationCheck
) {
999 $params['contact_id'] = self
::checkRegistration($params, $this, FALSE, TRUE, TRUE);
1003 if (!empty($params['image_URL'])) {
1004 CRM_Contact_BAO_Contact
::processImageParams($params);
1007 //carry campaign to partcipants.
1008 if (array_key_exists('participant_campaign_id', $params)) {
1009 $params['campaign_id'] = $params['participant_campaign_id'];
1012 $params['campaign_id'] = CRM_Utils_Array
::value('campaign_id', $this->_values
['event']);
1015 //hack to allow group to register w/ waiting
1016 $primaryParticipantCount = self
::getParticipantCount($this, $params);
1018 $totalParticipants = $primaryParticipantCount;
1019 if (!empty($params['additional_participants'])) {
1020 $totalParticipants +
= $params['additional_participants'];
1022 if (!$this->_allowConfirmation
&& !empty($params['bypass_payment']) &&
1023 is_numeric($this->_availableRegistrations
) &&
1024 $totalParticipants > $this->_availableRegistrations
1026 $this->_allowWaitlist
= TRUE;
1027 $this->set('allowWaitlist', TRUE);
1030 //carry participant id if pre-registered.
1031 if ($this->_allowConfirmation
&& $this->_participantId
) {
1032 $params['participant_id'] = $this->_participantId
;
1035 $params['defaultRole'] = 1;
1036 if (array_key_exists('participant_role', $params)) {
1037 $params['participant_role_id'] = $params['participant_role'];
1040 if (array_key_exists('participant_role_id', $params)) {
1041 $params['defaultRole'] = 0;
1043 if (empty($params['participant_role_id']) &&
1044 $this->_values
['event']['default_role_id']
1046 $params['participant_role_id'] = $this->_values
['event']['default_role_id'];
1049 $config = CRM_Core_Config
::singleton();
1050 $params['currencyID'] = $config->defaultCurrency
;
1052 if ($this->_values
['event']['is_monetary']) {
1053 // we first reset the confirm page so it accepts new values
1054 $this->controller
->resetPage('Confirm');
1056 //added for discount
1057 $discountId = CRM_Core_BAO_Discount
::findSet($this->_eventId
, 'civicrm_event');
1059 if (!empty($this->_values
['discount'][$discountId])) {
1060 $params['discount_id'] = $discountId;
1061 $params['amount_level'] = $this->_values
['discount'][$discountId][$params['amount']]['label'];
1063 $params['amount'] = $this->_values
['discount'][$discountId][$params['amount']]['value'];
1065 elseif (empty($params['priceSetId'])) {
1066 if (!empty($params['amount'])) {
1067 $params['amount_level'] = $this->_values
['fee'][$params['amount']]['label'];
1068 $params['amount'] = $this->_values
['fee'][$params['amount']]['value'];
1071 $params['amount_level'] = $params['amount'] = '';
1075 $lineItem = array();
1076 CRM_Price_BAO_PriceSet
::processAmount($this->_values
['fee'], $params, $lineItem);
1077 if ($params['tax_amount']) {
1078 $this->set('tax_amount', $params['tax_amount']);
1080 $this->set('lineItem', array($lineItem));
1081 $this->set('lineItemParticipantsCount', array($primaryParticipantCount));
1084 $this->set('amount', $params['amount']);
1085 $this->set('amount_level', $params['amount_level']);
1087 // generate and set an invoiceID for this transaction
1088 $invoiceID = md5(uniqid(rand(), TRUE));
1089 $this->set('invoiceID', $invoiceID);
1091 if (is_array($this->_paymentProcessor
)) {
1092 $payment = CRM_Core_Payment
::singleton($this->_mode
, $this->_paymentProcessor
, $this);
1094 // default mode is direct
1095 $this->set('contributeMode', 'direct');
1097 if (isset($params["state_province_id-{$this->_bltID}"]) &&
1098 $params["state_province_id-{$this->_bltID}"]
1100 $params["state_province-{$this->_bltID}"] = CRM_Core_PseudoConstant
::stateProvinceAbbreviation($params["state_province_id-{$this->_bltID}"]);
1103 if (isset($params["country_id-{$this->_bltID}"]) &&
1104 $params["country_id-{$this->_bltID}"]
1106 $params["country-{$this->_bltID}"] = CRM_Core_PseudoConstant
::countryIsoCode($params["country_id-{$this->_bltID}"]);
1108 if (isset($params['credit_card_exp_date'])) {
1109 $params['year'] = CRM_Core_Payment_Form
::getCreditCardExpirationYear($params);
1110 $params['month'] = CRM_Core_Payment_Form
::getCreditCardExpirationMonth($params);
1112 if ($this->_values
['event']['is_monetary']) {
1113 $params['ip_address'] = CRM_Utils_System
::ipAddress();
1114 $params['currencyID'] = $config->defaultCurrency
;
1115 $params['payment_action'] = 'Sale';
1116 $params['invoiceID'] = $invoiceID;
1119 $this->_params
= array();
1120 $this->_params
[] = $params;
1121 $this->set('params', $this->_params
);
1123 if ($this->_paymentProcessor
&&
1124 $this->_paymentProcessor
['billing_mode'] & CRM_Core_Payment
::BILLING_MODE_BUTTON
1126 //get the button name
1127 $buttonName = $this->controller
->getButtonName();
1128 if (in_array($buttonName,
1130 $this->_expressButtonName
,
1131 $this->_expressButtonName
. '_x',
1132 $this->_expressButtonName
. '_y',
1134 ) && empty($params['is_pay_later']) &&
1135 !$this->_allowWaitlist
&&
1136 !$this->_requireApproval
1138 $this->set('contributeMode', 'express');
1140 // Send Event Name & Id in Params
1141 $params['eventName'] = $this->_values
['event']['title'];
1142 $params['eventId'] = $this->_values
['event']['id'];
1144 $params['cancelURL'] = CRM_Utils_System
::url('civicrm/event/register',
1145 "_qf_Register_display=1&qfKey={$this->controller->_key}",
1148 if (CRM_Utils_Array
::value('additional_participants', $params, FALSE)) {
1149 $urlArgs = "_qf_Participant_1_display=1&rfp=1&qfKey={$this->controller->_key}";
1152 $urlArgs = "_qf_Confirm_display=1&rfp=1&qfKey={$this->controller->_key}";
1154 $params['returnURL'] = CRM_Utils_System
::url('civicrm/event/register',
1158 $params['invoiceID'] = $invoiceID;
1160 //default action is Sale
1161 $params['payment_action'] = 'Sale';
1163 $token = $payment->setExpressCheckout($params);
1164 if (is_a($token, 'CRM_Core_Error')) {
1165 CRM_Core_Error
::displaySessionError($token);
1166 CRM_Utils_System
::redirect($params['cancelURL']);
1169 $this->set('token', $token);
1171 $paymentURL = $this->_paymentProcessor
['url_site'] . "/cgi-bin/webscr?cmd=_express-checkout&token=$token";
1173 CRM_Utils_System
::redirect($paymentURL);
1176 elseif ($this->_paymentProcessor
&&
1177 $this->_paymentProcessor
['billing_mode'] & CRM_Core_Payment
::BILLING_MODE_NOTIFY
1179 $this->set('contributeMode', 'notify');
1183 $session = CRM_Core_Session
::singleton();
1184 $params['description'] = ts('Online Event Registration') . ' ' . $this->_values
['event']['title'];
1186 $this->_params
= array();
1187 $this->_params
[] = $params;
1188 $this->set('params', $this->_params
);
1191 empty($params['additional_participants'])
1192 && !$this->_values
['event']['is_confirm_enabled'] // CRM-11182 - Optional confirmation screen
1194 self
::processRegistration($this->_params
);
1198 // If registering > 1 participant, give status message
1199 if (CRM_Utils_Array
::value('additional_participants', $params, FALSE)) {
1200 $statusMsg = ts('Registration information for participant 1 has been saved.');
1201 CRM_Core_Session
::setStatus($statusMsg, ts('Saved'), 'success');
1206 * process Registration of free event
1208 * @param array $param
1210 * @param int contactID
1217 * @param array $params
1218 * @param int $contactID
1220 public function processRegistration($params, $contactID = NULL) {
1221 $session = CRM_Core_Session
::singleton();
1222 $this->_participantInfo
= array();
1224 // CRM-4320, lets build array of cancelled additional participant ids
1225 // those are drop or skip by primary at the time of confirmation.
1226 // get all in and then unset those are confirmed.
1227 $cancelledIds = $this->_additionalParticipantIds
;
1229 $participantCount = array();
1230 foreach ($params as $participantNum => $record) {
1231 if ($record == 'skip') {
1232 $participantCount[$participantNum] = 'skip';
1234 elseif ($participantNum) {
1235 $participantCount[$participantNum] = 'participant';
1239 $registerByID = NULL;
1240 foreach ($params as $key => $value) {
1241 if ($value != 'skip') {
1244 // setting register by Id and unset contactId.
1245 if (empty($value['is_primary'])) {
1247 $registerByID = $this->get('registerByID');
1248 if ($registerByID) {
1249 $value['registered_by_id'] = $registerByID;
1251 // get an email if one exists for the participant
1252 $participantEmail = '';
1253 foreach (array_keys($value) as $valueName) {
1254 if (substr($valueName, 0, 6) == 'email-') {
1255 $participantEmail = $value[$valueName];
1258 if ($participantEmail) {
1259 $this->_participantInfo
[] = $participantEmail;
1262 $this->_participantInfo
[] = $value['first_name'] . ' ' . $value['last_name'];
1265 elseif (!empty($value['contact_id'])) {
1266 $contactID = $value['contact_id'];
1269 $contactID = $this->getContactID();
1272 CRM_Event_Form_Registration_Confirm
::fixLocationFields($value, $fields, $this);
1273 //for free event or additional participant, dont create billing email address.
1274 if (empty($value['is_primary']) ||
!$this->_values
['event']['is_monetary']) {
1275 unset($value["email-{$this->_bltID}"]);
1278 $contactID = CRM_Event_Form_Registration_Confirm
::updateContactFields($contactID, $value, $fields, $this);
1280 // lets store the contactID in the session
1281 // we dont store in userID in case the user is doing multiple
1283 // for things like tell a friend
1284 if (!$this->getContactID() && !empty($value['is_primary'])) {
1285 $session->set('transaction.userID', $contactID);
1288 //lets get the status if require approval or waiting.
1290 $waitingStatuses = CRM_Event_PseudoConstant
::participantStatus(NULL, "class = 'Waiting'");
1291 if ($this->_allowWaitlist
&& !$this->_allowConfirmation
) {
1292 $value['participant_status_id'] = $value['participant_status'] = array_search('On waitlist', $waitingStatuses);
1294 elseif ($this->_requireApproval
&& !$this->_allowConfirmation
) {
1295 $value['participant_status_id'] = $value['participant_status'] = array_search('Awaiting approval', $waitingStatuses);
1298 $this->set('value', $value);
1299 $this->confirmPostProcess($contactID, NULL, NULL);
1301 //lets get additional participant id to cancel.
1302 if ($this->_allowConfirmation
&& is_array($cancelledIds)) {
1303 $additonalId = CRM_Utils_Array
::value('participant_id', $value);
1304 if ($additonalId && $key = array_search($additonalId, $cancelledIds)) {
1305 unset($cancelledIds[$key]);
1311 // update status and send mail to cancelled additonal participants, CRM-4320
1312 if ($this->_allowConfirmation
&& is_array($cancelledIds) && !empty($cancelledIds)) {
1313 $cancelledId = array_search('Cancelled',
1314 CRM_Event_PseudoConstant
::participantStatus(NULL, "class = 'Negative'")
1316 CRM_Event_BAO_Participant
::transitionParticipants($cancelledIds, $cancelledId);
1319 //set information about additional participants if exists
1320 if (count($this->_participantInfo
)) {
1321 $this->set('participantInfo', $this->_participantInfo
);
1324 //send mail Confirmation/Receipt
1325 if ($this->_contributeMode
!= 'checkout' ||
1326 $this->_contributeMode
!= 'notify'
1329 if ($this->_action
& CRM_Core_Action
::PREVIEW
) {
1333 //handle if no additional participant.
1334 if (!$registerByID) {
1335 $registerByID = $this->get('registerByID');
1337 $primaryContactId = $this->get('primaryContactId');
1339 //build an array of custom profile and assigning it to template.
1340 $additionalIDs = CRM_Event_BAO_Event
::buildCustomProfile($registerByID, NULL,
1341 $primaryContactId, $isTest, TRUE
1344 //lets carry all paticipant params w/ values.
1345 foreach ($additionalIDs as $participantID => $contactId) {
1346 $participantNum = NULL;
1347 if ($participantID == $registerByID) {
1348 $participantNum = 0;
1351 if ($participantNum = array_search('participant', $participantCount)) {
1352 unset($participantCount[$participantNum]);
1356 if ($participantNum === NULL) {
1360 //carry the participant submitted values.
1361 $this->_values
['params'][$participantID] = $params[$participantNum];
1364 //lets send mails to all with meanigful text, CRM-4320.
1365 $this->assign('isOnWaitlist', $this->_allowWaitlist
);
1366 $this->assign('isRequireApproval', $this->_requireApproval
);
1368 foreach ($additionalIDs as $participantID => $contactId) {
1369 if ($participantID == $registerByID) {
1370 //set as Primary Participant
1371 $this->assign('isPrimary', 1);
1373 $customProfile = CRM_Event_BAO_Event
::buildCustomProfile($participantID, $this->_values
, NULL, $isTest);
1375 if (count($customProfile)) {
1376 $this->assign('customProfile', $customProfile);
1377 $this->set('customProfile', $customProfile);
1381 $this->assign('isPrimary', 0);
1382 $this->assign('customProfile', NULL);
1385 //send Confirmation mail to Primary & additional Participants if exists
1386 CRM_Event_BAO_Event
::sendMail($contactId, $this->_values
, $participantID, $isTest);
1392 * Method to check if the user is already registered for the event
1393 * and if result found redirect to the event info page
1395 * @param array $fields
1396 * The input form values(anonymous user).
1397 * @param array $self
1399 * @param bool $isAdditional
1400 * Treat isAdditional participants a bit differently.
1401 * @param bool $returnContactId
1402 * Just find and return the contactID match to use.
1403 * @param bool $useDedupeRules
1404 * Force usage of dedupe rules.
1408 public static function checkRegistration($fields, &$self, $isAdditional = FALSE, $returnContactId = FALSE, $useDedupeRules = FALSE) {
1409 // CRM-3907, skip check for preview registrations
1410 // CRM-4320 participant need to walk wizard
1411 if (!$returnContactId &&
1412 ($self->_mode
== 'test' ||
$self->_allowConfirmation
)
1418 $session = CRM_Core_Session
::singleton();
1419 if (!$isAdditional) {
1420 $contactID = $self->getContactID();
1423 if (!$contactID && is_array($fields) && $fields) {
1425 //CRM-14134 use Unsupervised rule for everyone
1426 $dedupeParams = CRM_Dedupe_Finder
::formatParams($fields, 'Individual');
1428 // disable permission based on cache since event registration is public page/feature.
1429 $dedupeParams['check_permission'] = FALSE;
1431 // find event dedupe rule
1432 if (CRM_Utils_Array
::value('dedupe_rule_group_id', $self->_values
['event'], 0) > 0) {
1433 $ids = CRM_Dedupe_Finder
::dupesByParams($dedupeParams, 'Individual', 'Unsupervised', array(), $self->_values
['event']['dedupe_rule_group_id']);
1436 $ids = CRM_Dedupe_Finder
::dupesByParams($dedupeParams, 'Individual', 'Unsupervised');
1438 $contactID = CRM_Utils_Array
::value(0, $ids);
1442 if ($returnContactId) {
1444 // return contactID if contact already exists
1449 $participant = new CRM_Event_BAO_Participant();
1450 $participant->contact_id
= $contactID;
1451 $participant->event_id
= $self->_values
['event']['id'];
1452 if (!empty($fields['participant_role']) && is_numeric($fields['participant_role'])) {
1453 $participant->role_id
= $fields['participant_role'];
1456 $participant->role_id
= $self->_values
['event']['default_role_id'];
1458 $participant->is_test
= 0;
1459 $participant->find();
1460 $statusTypes = CRM_Event_PseudoConstant
::participantStatus(NULL, 'is_counted = 1');
1461 while ($participant->fetch()) {
1462 if (array_key_exists($participant->status_id
, $statusTypes)) {
1463 if (!$isAdditional && !$self->_values
['event']['allow_same_participant_emails']) {
1464 $registerUrl = CRM_Utils_System
::url('civicrm/event/register',
1465 "reset=1&id={$self->_values['event']['id']}&cid=0"
1467 if ($self->_pcpId
) {
1468 $registerUrl .= '&pcpId=' . $self->_pcpId
;
1471 $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));
1472 $session->setStatus($status, ts('Oops.'), 'alert');
1473 $url = CRM_Utils_System
::url('civicrm/event/info',
1474 "reset=1&id={$self->_values['event']['id']}&noFullMsg=true"
1476 if ($self->_action
& CRM_Core_Action
::PREVIEW
) {
1477 $url .= '&action=preview';
1480 if ($self->_pcpId
) {
1481 $url .= '&pcpId=' . $self->_pcpId
;
1484 CRM_Utils_System
::redirect($url);
1487 if ($isAdditional) {
1488 $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.");
1489 $session->setStatus($status, ts('Oops.'), 'alert');
1490 return $participant->id
;