Merge pull request #14279 from eileenmcnaughton/db_test2
[civicrm-core.git] / CRM / Event / Form / Registration / Register.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
fee14197 4 | CiviCRM version 5 |
6a488035 5 +--------------------------------------------------------------------+
6b83d5bd 6 | Copyright CiviCRM LLC (c) 2004-2019 |
6a488035
TO
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 +--------------------------------------------------------------------+
d25dd0ee 26 */
6a488035
TO
27
28/**
6a488035 29 * @package CRM
6b83d5bd 30 * @copyright CiviCRM LLC (c) 2004-2019
6a488035
TO
31 */
32
33/**
3bdf1f3a 34 * This class generates form components for processing Event.
6a488035
TO
35 */
36class CRM_Event_Form_Registration_Register extends CRM_Event_Form_Registration {
37
38 /**
66f9e52b 39 * The fields involved in this page.
90b461f1 40 * @var array
6a488035
TO
41 */
42 public $_fields;
43
6a488035
TO
44 /**
45 * The status message that user view.
90b461f1 46 * @var sting
6a488035
TO
47 */
48 protected $_waitlistMsg = NULL;
49 protected $_requireApprovalMsg = NULL;
50
3bdf1f3a 51 /**
52 * Deprecated parameter that we hope to remove.
53 *
54 * @var bool
55 */
6a488035
TO
56 public $_quickConfig = NULL;
57
58 /**
3bdf1f3a 59 * Skip duplicate check.
60 *
61 * This can be set using hook_civicrm_buildForm() to override the registration dupe check.
6a488035 62 * CRM-7604
90b461f1 63 * @var bool
6a488035
TO
64 */
65 public $_skipDupeRegistrationCheck = FALSE;
66
cc789d46 67 public $_paymentProcessorID;
6a488035 68
16d1c8e2 69 /**
3bdf1f3a 70 * Show fee block or not.
71 *
d51c6add 72 * @var bool determines if fee block should be shown or hidden
16d1c8e2 73 */
74 public $_noFees;
75
0b36bfd7
MWMC
76 /**
77 * @var array Fee Block
78 */
79 public $_feeBlock;
80
cc789d46 81 /**
3bdf1f3a 82 * Array of payment related fields to potentially display on this form (generally credit card or debit card fields).
83 *
84 * This is rendered via billingBlock.tpl.
85 *
cc789d46
EM
86 * @var array
87 */
be2fb01f 88 public $_paymentFields = [];
cc789d46 89
7b64dc81 90 /**
91 * Get the contact id for the registration.
92 *
93 * @param array $fields
0b36bfd7 94 * @param CRM_Event_Form_Registration $form
7b64dc81 95 * @param bool $isAdditional
96 *
97 * @return int|null
98 */
0b36bfd7 99 public static function getRegistrationContactID($fields, $form, $isAdditional) {
7b64dc81 100 $contactID = NULL;
101 if (!$isAdditional) {
0b36bfd7 102 $contactID = $form->getContactID();
7b64dc81 103 }
104 if (!$contactID && is_array($fields) && $fields) {
b8cb7e46 105 $contactID = CRM_Contact_BAO_Contact::getFirstDuplicateContact($fields, 'Individual', 'Unsupervised', [], FALSE, CRM_Utils_Array::value('dedupe_rule_group_id', $form->_values['event']), ['event_id' => CRM_Utils_Array::value('id', $form->_values['event'])]);
7b64dc81 106 }
107 return $contactID;
108 }
109
6a488035 110 /**
66f9e52b 111 * Set variables up before form is built.
6a488035 112 */
00be9182 113 public function preProcess() {
6a488035 114 parent::preProcess();
7bf9cde2 115
6a488035
TO
116 //CRM-4320.
117 //here we can't use parent $this->_allowWaitlist as user might
cc789d46 118 //walk back and we might set this value in this postProcess.
6a488035 119 //(we set when spaces < group count and want to allow become part of waiting )
6a488035
TO
120 $eventFull = CRM_Event_BAO_Participant::eventFull($this->_eventId, FALSE, CRM_Utils_Array::value('has_waitlist', $this->_values['event']));
121
b6a469c5
CW
122 // Get payment processors if appropriate for this event
123 // We hide the payment fields if the event is full or requires approval,
124 // and the current user has not yet been approved CRM-12279
16d1c8e2 125 $this->_noFees = (($eventFull || $this->_requireApproval) && !$this->_allowConfirmation);
be2fb01f 126 $this->_paymentProcessors = $this->_noFees ? [] : $this->get('paymentProcessors');
42e3a033 127 $this->preProcessPaymentOptions();
b6a469c5 128
6a488035 129 $this->_allowWaitlist = FALSE;
8cc574cf 130 if ($eventFull && !$this->_allowConfirmation && !empty($this->_values['event']['has_waitlist'])) {
6a488035
TO
131 $this->_allowWaitlist = TRUE;
132 $this->_waitlistMsg = CRM_Utils_Array::value('waitlist_text', $this->_values['event']);
133 if (!$this->_waitlistMsg) {
134 $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.');
135 }
136 }
137 $this->set('allowWaitlist', $this->_allowWaitlist);
138
139 //To check if the user is already registered for the event(CRM-2426)
140 if (!$this->_skipDupeRegistrationCheck) {
141 self::checkRegistration(NULL, $this);
142 }
143
144 $this->assign('availableRegistrations', $this->_availableRegistrations);
145
146 // get the participant values from EventFees.php, CRM-4320
147 if ($this->_allowConfirmation) {
148 CRM_Event_Form_EventFees::preProcess($this);
149 }
6a488035
TO
150 }
151
152 /**
70d1766d 153 * Set default values for the form.
6a488035 154 */
00be9182 155 public function setDefaultValues() {
be2fb01f 156 $this->_defaults = [];
5ec4b965 157 if (!$this->_allowConfirmation && $this->_requireApproval) {
158 $this->_defaults['bypass_payment'] = 1;
159 }
5c280496 160 $contactID = $this->getContactID();
70d1766d 161 CRM_Core_Payment_Form::setDefaultValues($this, $contactID);
a28e436f 162
c7d52684 163 CRM_Event_BAO_Participant::formatFieldsAndSetProfileDefaults($contactID, $this);
3feb567a 164
13ac605f
DG
165 // Set default payment processor as default payment_processor radio button value
166 if (!empty($this->_paymentProcessors)) {
167 foreach ($this->_paymentProcessors as $pid => $value) {
a7488080 168 if (!empty($value['is_default'])) {
e02d7e96 169 $this->_defaults['payment_processor_id'] = $pid;
13ac605f
DG
170 }
171 }
172 }
173
6a488035
TO
174 //if event is monetary and pay later is enabled and payment
175 //processor is not available then freeze the pay later checkbox with
176 //default check
a7488080 177 if (!empty($this->_values['event']['is_pay_later']) &&
6a488035
TO
178 !is_array($this->_paymentProcessor)
179 ) {
180 $this->_defaults['is_pay_later'] = 1;
181 }
182
183 //set custom field defaults
184 if (!empty($this->_fields)) {
185 //load default campaign from page.
186 if (array_key_exists('participant_campaign_id', $this->_fields)) {
187 $this->_defaults['participant_campaign_id'] = CRM_Utils_Array::value('campaign_id',
188 $this->_values['event']
189 );
190 }
191
192 foreach ($this->_fields as $name => $field) {
193 if ($customFieldID = CRM_Core_BAO_CustomField::getKeyID($name)) {
194 // fix for CRM-1743
195 if (!isset($this->_defaults[$name])) {
196 CRM_Core_BAO_CustomField::setProfileDefaults($customFieldID, $name, $this->_defaults,
197 NULL, CRM_Profile_Form::MODE_REGISTER
198 );
199 }
200 }
201 }
202 }
203
204 //fix for CRM-3088, default value for discount set.
205 $discountId = NULL;
206 if (!empty($this->_values['discount'])) {
207 $discountId = CRM_Core_BAO_Discount::findSet($this->_eventId, 'civicrm_event');
208 if ($discountId) {
209 if (isset($this->_values['event']['default_discount_fee_id'])) {
210 $discountKey = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_OptionValue',
211 $this->_values['event']['default_discount_fee_id'],
212 'weight', 'id'
213 );
214
215 $this->_defaults['amount'] = key(array_slice($this->_values['discount'][$discountId],
353ffa53
TO
216 $discountKey - 1, $discountKey, TRUE
217 ));
6a488035
TO
218 }
219 }
220 }
221
222 // add this event's default participant role to defaults array
223 // (for cases where participant_role field is included in form via profile)
224 if ($this->_values['event']['default_role_id']) {
608e6658 225 $this->_defaults['participant_role']
226 = $this->_defaults['participant_role_id'] = $this->_values['event']['default_role_id'];
6a488035
TO
227 }
228 if ($this->_priceSetId && !empty($this->_feeBlock)) {
229 foreach ($this->_feeBlock as $key => $val) {
0dc0b759 230 if (empty($val['options'])) {
231 continue;
232 }
be2fb01f 233 $optionFullIds = CRM_Utils_Array::value('option_full_ids', $val, []);
6a488035 234 foreach ($val['options'] as $keys => $values) {
8cc574cf 235 if ($values['is_default'] && empty($values['is_full'])) {
6a488035
TO
236
237 if ($val['html_type'] == 'CheckBox') {
238 $this->_defaults["price_{$key}"][$keys] = 1;
239 }
240 else {
241 $this->_defaults["price_{$key}"] = $keys;
242 }
243 }
244 }
0dc0b759 245 $unsetSubmittedOptions[$val['id']] = $optionFullIds;
6a488035 246 }
0dc0b759 247 //reset values for all options those are full.
248 CRM_Event_Form_Registration::resetElementValue($unsetSubmittedOptions, $this);
6a488035
TO
249 }
250
251 //set default participant fields, CRM-4320.
252 $hasAdditionalParticipants = FALSE;
253 if ($this->_allowConfirmation) {
254 $this->_contactId = $contactID;
255 $this->_discountId = $discountId;
256 $forcePayLater = CRM_Utils_Array::value('is_pay_later', $this->_defaults, FALSE);
257 $this->_defaults = array_merge($this->_defaults, CRM_Event_Form_EventFees::setDefaultValues($this));
258 $this->_defaults['is_pay_later'] = $forcePayLater;
259
260 if ($this->_additionalParticipantIds) {
261 $hasAdditionalParticipants = TRUE;
262 $this->_defaults['additional_participants'] = count($this->_additionalParticipantIds);
263 }
264 }
265 $this->assign('hasAdditionalParticipants', $hasAdditionalParticipants);
266
267 // //hack to simplify credit card entry for testing
268 // $this->_defaults['credit_card_type'] = 'Visa';
269 // $this->_defaults['credit_card_number'] = '4807731747657838';
270 // $this->_defaults['cvv2'] = '000';
271 // $this->_defaults['credit_card_exp_date'] = array( 'Y' => '2010', 'M' => '05' );
272
273 // to process Custom data that are appended to URL
274 $getDefaults = CRM_Core_BAO_CustomGroup::extractGetParams($this, "'Contact', 'Individual', 'Contribution', 'Participant'");
275 if (!empty($getDefaults)) {
276 $this->_defaults = array_merge($this->_defaults, $getDefaults);
277 }
278
279 return $this->_defaults;
280 }
281
282 /**
66f9e52b 283 * Build the form object.
6a488035
TO
284 */
285 public function buildQuickForm() {
4839c695
KJ
286 // build profiles first so that we can determine address fields etc
287 // and then show copy address checkbox
288 $this->buildCustom($this->_values['custom_pre_id'], 'customPre');
289 $this->buildCustom($this->_values['custom_post_id'], 'customPost');
290
d38c288e 291 // CRM-18399: used by template to pass pre profile id as a url arg
292 $this->assign('custom_pre_id', $this->_values['custom_pre_id']);
4839c695 293
cc789d46 294 CRM_Core_Payment_ProcessorForm::buildQuickForm($this);
6a488035 295
5c280496 296 $contactID = $this->getContactID();
37326fa1
DG
297 if ($contactID) {
298 $this->assign('contact_id', $contactID);
f498a273 299 $this->assign('display_name', CRM_Contact_BAO_Contact::displayName($contactID));
37326fa1 300 }
6a488035 301
6a488035
TO
302 $this->add('hidden', 'scriptFee', NULL);
303 $this->add('hidden', 'scriptArray', NULL);
304
305 $bypassPayment = $allowGroupOnWaitlist = $isAdditionalParticipants = FALSE;
306 if ($this->_values['event']['is_multiple_registrations']) {
307 // don't allow to add additional during confirmation if not preregistered.
308 if (!$this->_allowConfirmation || $this->_additionalParticipantIds) {
f1bc01e0 309 // CRM-17745: Make maximum additional participants configurable
6a488035 310 // Label is value + 1, since the code sees this is ADDITIONAL participants (in addition to "self")
be2fb01f 311 $additionalOptions = [];
f1bc01e0 312 $additionalOptions[''] = 1;
30ddbdcb 313 for ($i = 1; $i <= $this->_values['event']['max_additional_participants']; $i++) {
f1bc01e0
J
314 $additionalOptions[$i] = $i + 1;
315 }
5f39c1a6 316 $this->add('select', 'additional_participants',
6a488035
TO
317 ts('How many people are you registering?'),
318 $additionalOptions,
319 NULL,
be2fb01f 320 ['onChange' => "allowParticipant()"]
6a488035
TO
321 );
322 $isAdditionalParticipants = TRUE;
323 }
324 }
325
5ec4b965 326 if (!$this->_allowConfirmation) {
327 $bypassPayment = TRUE;
328 }
329
6a488035 330 //hack to allow group to register w/ waiting
8cc574cf 331 if ((!empty($this->_values['event']['is_multiple_registrations']) ||
6a488035
TO
332 $this->_priceSetId
333 ) &&
334 !$this->_allowConfirmation &&
353ffa53
TO
335 is_numeric($this->_availableRegistrations) && !empty($this->_values['event']['has_waitlist'])
336 ) {
6a488035
TO
337 $bypassPayment = TRUE;
338 //case might be group become as a part of waitlist.
339 //If not waitlist then they require admin approve.
340 $allowGroupOnWaitlist = TRUE;
be2fb01f 341 $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.", [1 => $this->_availableRegistrations]);
6a488035
TO
342
343 if ($this->_requireApproval) {
344 $this->_requireApprovalMsg = CRM_Utils_Array::value('approval_req_text', $this->_values['event'],
345 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.')
346 );
347 }
348 }
349
350 //case where only approval needed - no waitlist.
351 if ($this->_requireApproval &&
352 !$this->_allowWaitlist && !$bypassPayment
353 ) {
354 $this->_requireApprovalMsg = CRM_Utils_Array::value('approval_req_text', $this->_values['event'],
355 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.')
356 );
357 }
358
359 //lets display status to primary page only.
360 $this->assign('waitlistMsg', $this->_waitlistMsg);
361 $this->assign('requireApprovalMsg', $this->_requireApprovalMsg);
362 $this->assign('allowGroupOnWaitlist', $allowGroupOnWaitlist);
363 $this->assign('isAdditionalParticipants', $isAdditionalParticipants);
364
6a488035
TO
365 if ($this->_values['event']['is_monetary']) {
366 self::buildAmount($this);
367 }
368
be2fb01f 369 $pps = [];
596bff78 370 //@todo this processor adding fn is another one duplicated on contribute - a shared
371 // common class would make this sort of thing extractable
cf6a124f 372 $onlinePaymentProcessorEnabled = FALSE;
6a488035 373 if (!empty($this->_paymentProcessors)) {
596bff78 374 foreach ($this->_paymentProcessors as $key => $name) {
22e263ad 375 if ($name['billing_mode'] == 1) {
596bff78 376 $onlinePaymentProcessorEnabled = TRUE;
377 }
6a488035
TO
378 $pps[$key] = $name['name'];
379 }
380 }
aa288d3f 381 if ($this->getContactID() === 0 && !$this->_values['event']['is_multiple_registrations']) {
e1ce628e 382 //@todo we are blocking for multiple registrations because we haven't tested
596bff78 383 $this->addCidZeroOptions($onlinePaymentProcessorEnabled);
384 }
a7488080 385 if (!empty($this->_values['event']['is_pay_later']) &&
6a488035
TO
386 ($this->_allowConfirmation || (!$this->_requireApproval && !$this->_allowWaitlist))
387 ) {
388 $pps[0] = $this->_values['event']['pay_later_text'];
389 }
390
391 if ($this->_values['event']['is_monetary']) {
392 if (count($pps) > 1) {
e02d7e96 393 $this->addRadio('payment_processor_id', ts('Payment Method'), $pps,
fdf1844b 394 NULL, "&nbsp;"
6a488035
TO
395 );
396 }
397 elseif (!empty($pps)) {
398 $ppKeys = array_keys($pps);
399 $currentPP = array_pop($ppKeys);
e02d7e96 400 $this->addElement('hidden', 'payment_processor_id', $currentPP);
6a488035
TO
401 }
402 }
403
be2fb01f 404 $this->addElement('hidden', 'bypass_payment', NULL, ['id' => 'bypass_payment']);
5ec4b965 405
6a488035 406 $this->assign('bypassPayment', $bypassPayment);
6a488035 407
5c280496 408 $userID = $this->getContactID();
6a488035
TO
409
410 if (!$userID) {
411 $createCMSUser = FALSE;
412
413 if ($this->_values['custom_pre_id']) {
414 $profileID = $this->_values['custom_pre_id'];
415 $createCMSUser = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_UFGroup', $profileID, 'is_cms_user');
416 }
417
418 if (!$createCMSUser &&
419 $this->_values['custom_post_id']
420 ) {
421 if (!is_array($this->_values['custom_post_id'])) {
be2fb01f 422 $profileIDs = [$this->_values['custom_post_id']];
6a488035
TO
423 }
424 else {
425 $profileIDs = $this->_values['custom_post_id'];
426 }
427 foreach ($profileIDs as $pid) {
428 if (CRM_Core_DAO::getFieldValue('CRM_Core_DAO_UFGroup', $pid, 'is_cms_user')) {
429 $profileID = $pid;
430 $createCMSUser = TRUE;
431 break;
432 }
433 }
434 }
435
436 if ($createCMSUser) {
437 CRM_Core_BAO_CMSUser::buildForm($this, $profileID, TRUE);
438 }
439 }
440
441 //we have to load confirm contribution button in template
442 //when multiple payment processor as the user
443 //can toggle with payment processor selection
444 $billingModePaymentProcessors = 0;
445 if (!CRM_Utils_System::isNull($this->_paymentProcessors)) {
446 foreach ($this->_paymentProcessors as $key => $values) {
447 if ($values['billing_mode'] == CRM_Core_Payment::BILLING_MODE_BUTTON) {
448 $billingModePaymentProcessors++;
449 }
450 }
451 }
452
453 if ($billingModePaymentProcessors && count($this->_paymentProcessors) == $billingModePaymentProcessors) {
454 $allAreBillingModeProcessors = TRUE;
0db6c3e1
TO
455 }
456 else {
6a488035
TO
457 $allAreBillingModeProcessors = FALSE;
458 }
459
8cc574cf 460 if (!$allAreBillingModeProcessors || !empty($this->_values['event']['is_pay_later']) || $bypassPayment
6a488035
TO
461 ) {
462
463 //freeze button to avoid multiple calls.
464 $js = NULL;
465
a7488080 466 if (empty($this->_values['event']['is_monetary'])) {
be2fb01f 467 $js = ['onclick' => "return submitOnce(this,'" . $this->_name . "','" . ts('Processing') . "');"];
6a488035 468 }
2a6da8d7 469
1909126f 470 // CRM-11182 - Optional confirmation screen
471 // Change button label depending on whether the next action is confirm or register
472 if (
473 !$this->_values['event']['is_multiple_registrations']
d6121d3e 474 && !$this->_values['event']['is_monetary']
1909126f 475 && !$this->_values['event']['is_confirm_enabled']
476 ) {
f212d37d 477 $buttonLabel = ts('Register');
0db6c3e1
TO
478 }
479 else {
f212d37d 480 $buttonLabel = ts('Continue');
1909126f 481 }
2a6da8d7 482
be2fb01f 483 $this->addButtons([
90b461f1
SL
484 [
485 'type' => 'upload',
486 'name' => $buttonLabel,
487 'spacing' => '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;',
488 'isDefault' => TRUE,
489 'js' => $js,
490 ],
491 ]);
6a488035
TO
492 }
493
be2fb01f 494 $this->addFormRule(['CRM_Event_Form_Registration_Register', 'formRule'], $this);
86c0d461 495 $this->unsavedChangesWarn = TRUE;
6a488035
TO
496
497 // add pcp fields
498 if ($this->_pcpId) {
499 CRM_PCP_BAO_PCP::buildPcp($this->_pcpId, $this);
500 }
501 }
502
503 /**
100fef9d 504 * Build the radio/text form elements for the amount field
6a488035 505 *
0b36bfd7 506 * @param CRM_Event_Form_Registration_Register $form
d4dd1e85
TO
507 * Form object.
508 * @param bool $required
509 * True if you want to add formRule.
510 * @param int $discountId
511 * Discount id for the event.
6a488035 512 */
90b461f1 513 public static function buildAmount(&$form, $required = TRUE, $discountId = NULL) {
16d1c8e2 514 // build amount only when needed, skip incase of event full and waitlisting is enabled
515 // and few other conditions check preProcess()
a2a1e950 516 if (property_exists($form, '_noFees') && $form->_noFees) {
16d1c8e2 517 return;
518 }
519
6a488035 520 //if payment done, no need to build the fee block.
7bf9cde2 521 if (!empty($form->_paymentId)) {
b6e641a4 522 //fix to display line item in update mode.
6a488035
TO
523 $form->assign('priceSet', isset($form->_priceSet) ? $form->_priceSet : NULL);
524 return;
525 }
526
527 $feeFields = CRM_Utils_Array::value('fee', $form->_values);
528
529 if (is_array($feeFields)) {
530 $form->_feeBlock = &$form->_values['fee'];
531 }
532
533 //check for discount.
534 $discountedFee = CRM_Utils_Array::value('discount', $form->_values);
535 if (is_array($discountedFee) && !empty($discountedFee)) {
536 if (!$discountId) {
537 $form->_discountId = $discountId = CRM_Core_BAO_Discount::findSet($form->_eventId, 'civicrm_event');
538 }
539 if ($discountId) {
540 $form->_feeBlock = &$form->_values['discount'][$discountId];
541 }
542 }
543 if (!is_array($form->_feeBlock)) {
be2fb01f 544 $form->_feeBlock = [];
6a488035
TO
545 }
546
547 //its time to call the hook.
548 CRM_Utils_Hook::buildAmount('event', $form, $form->_feeBlock);
549
550 //reset required if participant is skipped.
551 $button = substr($form->controller->getButtonName(), -4);
552 if ($required && $button == 'skip') {
553 $required = FALSE;
554 }
555
556 $className = CRM_Utils_System::getClassName($form);
557
558 //build the priceset fields.
559 if (isset($form->_priceSetId) && $form->_priceSetId) {
560
561 //format price set fields across option full.
562 self::formatFieldsForOptionFull($form);
563
a7488080 564 if (!empty($form->_priceSet['is_quick_config'])) {
6a488035
TO
565 $form->_quickConfig = $form->_priceSet['is_quick_config'];
566 }
567 $form->add('hidden', 'priceSetId', $form->_priceSetId);
568
c7b3d063 569 // CRM-14492 Admin price fields should show up on event registration if user has 'administer CiviCRM' permissions
ab8a593e 570 $adminFieldVisible = FALSE;
c7b3d063 571 if (CRM_Core_Permission::check('administer CiviCRM')) {
4eeb9a5b 572 $adminFieldVisible = TRUE;
c7b3d063
DG
573 }
574
a13c171d
CR
575 $hideAdminValues = TRUE;
576 if (CRM_Core_Permission::check('edit event participants')) {
577 $hideAdminValues = FALSE;
578 }
579
6a488035 580 foreach ($form->_feeBlock as $field) {
d06f3157 581 // public AND admin visibility fields are included for back-office registration and back-office change selections
6a488035 582 if (CRM_Utils_Array::value('visibility', $field) == 'public' ||
4eeb9a5b 583 (CRM_Utils_Array::value('visibility', $field) == 'admin' && $adminFieldVisible == TRUE) ||
d06f3157
DG
584 $className == 'CRM_Event_Form_Participant' ||
585 $className == 'CRM_Event_Form_ParticipantFeeSelection'
6a488035
TO
586 ) {
587 $fieldId = $field['id'];
588 $elementName = 'price_' . $fieldId;
589
590 $isRequire = CRM_Utils_Array::value('is_required', $field);
591 if ($button == 'skip') {
592 $isRequire = FALSE;
593 }
594
595 //user might modified w/ hook.
596 $options = CRM_Utils_Array::value('options', $field);
be2fb01f 597 $formClasses = ['CRM_Event_Form_Participant', 'CRM_Event_Form_ParticipantFeeSelection'];
a13c171d 598
6a488035
TO
599 if (!is_array($options)) {
600 continue;
601 }
a13c171d 602 elseif ($hideAdminValues && !in_array($className, $formClasses)) {
ad2785a2
CR
603 $publicVisibilityID = CRM_Price_BAO_PriceField::getVisibilityOptionID('public');
604 $adminVisibilityID = CRM_Price_BAO_PriceField::getVisibilityOptionID('admin');
605
a13c171d 606 foreach ($options as $key => $currentOption) {
ad2785a2
CR
607 $optionVisibility = CRM_Utils_Array::value('visibility_id', $currentOption, $publicVisibilityID);
608 if ($optionVisibility == $adminVisibilityID) {
a13c171d
CR
609 unset($options[$key]);
610 }
611 }
612 }
6a488035 613
be2fb01f 614 $optionFullIds = CRM_Utils_Array::value('option_full_ids', $field, []);
6a488035
TO
615
616 //soft suppress required rule when option is full.
617 if (!empty($optionFullIds) && (count($options) == count($optionFullIds))) {
618 $isRequire = FALSE;
619 }
1019b2fe
SL
620 if (!empty($options)) {
621 //build the element.
622 CRM_Price_BAO_PriceField::addQuickFormElement($form,
623 $elementName,
624 $fieldId,
625 FALSE,
626 $isRequire,
627 NULL,
628 $options,
629 $optionFullIds
630 );
631 }
6a488035
TO
632 }
633 }
634 $form->assign('priceSet', $form->_priceSet);
635 }
636 else {
be2fb01f 637 $eventFeeBlockValues = [];
6a488035
TO
638 foreach ($form->_feeBlock as $fee) {
639 if (is_array($fee)) {
640
641 //CRM-7632, CRM-6201
642 $totalAmountJs = NULL;
643 if ($className == 'CRM_Event_Form_Participant') {
be2fb01f 644 $totalAmountJs = ['onClick' => "fillTotalAmount(" . $fee['value'] . ")"];
6a488035
TO
645 }
646
647 $eventFeeBlockValues['amount_id_' . $fee['amount_id']] = $fee['value'];
648 $elements[] = &$form->createElement('radio', NULL, '',
649 CRM_Utils_Money::format($fee['value']) . ' ' .
650 $fee['label'],
651 $fee['amount_id'],
652 $totalAmountJs
653 );
654 }
655 }
656 $form->assign('eventFeeBlockValues', json_encode($eventFeeBlockValues));
657
658 $form->_defaults['amount'] = CRM_Utils_Array::value('default_fee_id', $form->_values['event']);
659 $element = &$form->addGroup($elements, 'amount', ts('Event Fee(s)'), '<br />');
660 if (isset($form->_online) && $form->_online) {
661 $element->freeze();
662 }
663 if ($required) {
664 $form->addRule('amount', ts('Fee Level is a required field.'), 'required');
665 }
666 }
667 }
668
0cf587a7 669 /**
0b36bfd7 670 * @param CRM_Event_Form_Registration $form
0cf587a7 671 */
6a488035
TO
672 public static function formatFieldsForOptionFull(&$form) {
673 $priceSet = $form->get('priceSet');
674 $priceSetId = $form->get('priceSetId');
be2fb01f 675 $defaultPricefieldIds = [];
e9bb507e 676 if (!empty($form->_values['line_items'])) {
677 foreach ($form->_values['line_items'] as $lineItem) {
678 $defaultPricefieldIds[] = $lineItem['price_field_value_id'];
679 }
680 }
6a488035
TO
681 if (!$priceSetId ||
682 !is_array($priceSet) ||
353ffa53
TO
683 empty($priceSet) || empty($priceSet['optionsMaxValueTotal'])
684 ) {
6a488035
TO
685 return;
686 }
687
be2fb01f 688 $skipParticipants = $formattedPriceSetDefaults = [];
e03317f1 689 if (!empty($form->_allowConfirmation) && (isset($form->_pId) || isset($form->_additionalParticipantId))) {
6a488035
TO
690 $participantId = isset($form->_pId) ? $form->_pId : $form->_additionalParticipantId;
691 $pricesetDefaults = CRM_Event_Form_EventFees::setDefaultPriceSet($participantId,
692 $form->_eventId
693 );
694 // modify options full to respect the selected fields
695 // options on confirmation.
217d80ab 696 $formattedPriceSetDefaults = self::formatPriceSetParams($form, $pricesetDefaults);
6a488035
TO
697
698 // to skip current registered participants fields option count on confirmation.
699 $skipParticipants[] = $form->_participantId;
700 if (!empty($form->_additionalParticipantIds)) {
701 $skipParticipants = array_merge($skipParticipants, $form->_additionalParticipantIds);
702 }
703 }
704
705 $className = CRM_Utils_System::getClassName($form);
706
707 //get the current price event price set options count.
708 $currentOptionsCount = self::getPriceSetOptionCount($form);
709 $recordedOptionsCount = CRM_Event_BAO_Participant::priceSetOptionsCount($form->_eventId, $skipParticipants);
e9bb507e 710 $optionFullTotalAmount = 0;
0dc0b759 711 $currentParticipantNo = (int) substr($form->_name, 12);
6a488035 712 foreach ($form->_feeBlock as & $field) {
be2fb01f 713 $optionFullIds = [];
6a488035
TO
714 $fieldId = $field['id'];
715 if (!is_array($field['options'])) {
716 continue;
717 }
718 foreach ($field['options'] as & $option) {
353ffa53
TO
719 $optId = $option['id'];
720 $count = CRM_Utils_Array::value('count', $option, 0);
721 $maxValue = CRM_Utils_Array::value('max_value', $option, 0);
722 $dbTotalCount = CRM_Utils_Array::value($optId, $recordedOptionsCount, 0);
6a488035
TO
723 $currentTotalCount = CRM_Utils_Array::value($optId, $currentOptionsCount, 0);
724
79b152ac 725 $totalCount = $currentTotalCount + $dbTotalCount;
6a488035
TO
726 $isFull = FALSE;
727 if ($maxValue &&
0dc0b759 728 (($totalCount >= $maxValue) &&
729 (empty($form->_lineItem[$currentParticipantNo][$optId]['price_field_id']) || $dbTotalCount >= $maxValue))
6a488035
TO
730 ) {
731 $isFull = TRUE;
732 $optionFullIds[$optId] = $optId;
e9bb507e 733 if ($field['html_type'] != 'Select') {
734 if (in_array($optId, $defaultPricefieldIds)) {
735 $optionFullTotalAmount += CRM_Utils_Array::value('amount', $option);
736 }
737 }
738 else {
739 if (!empty($defaultPricefieldIds) && in_array($optId, $defaultPricefieldIds)) {
740 unset($optionFullIds[$optId]);
741 }
742 }
6a488035 743 }
6a488035
TO
744 //here option is not full,
745 //but we don't want to allow participant to increase
746 //seats at the time of re-walking registration.
747 if ($count &&
8dfe9fe3 748 !empty($form->_allowConfirmation) &&
6a488035
TO
749 !empty($formattedPriceSetDefaults)
750 ) {
217d80ab 751 if (empty($formattedPriceSetDefaults["price_{$field}"]) || empty($formattedPriceSetDefaults["price_{$fieldId}"][$optId])) {
6a488035
TO
752 $optionFullIds[$optId] = $optId;
753 $isFull = TRUE;
754 }
755 }
756 $option['is_full'] = $isFull;
757 $option['db_total_count'] = $dbTotalCount;
758 $option['total_option_count'] = $dbTotalCount + $currentTotalCount;
759 }
760
761 //ignore option full for offline registration.
762 if ($className == 'CRM_Event_Form_Participant') {
be2fb01f 763 $optionFullIds = [];
6a488035
TO
764 }
765
766 //finally get option ids in.
767 $field['option_full_ids'] = $optionFullIds;
768 }
e9bb507e 769 $form->assign('optionFullTotalAmount', $optionFullTotalAmount);
6a488035
TO
770 }
771
772 /**
66f9e52b 773 * Global form rule.
6a488035 774 *
d4dd1e85
TO
775 * @param array $fields
776 * The input form values.
777 * @param array $files
778 * The uploaded files if any.
0b36bfd7 779 * @param CRM_Event_Form_Registration $form
2a6da8d7 780 *
6a488035 781 *
72b3a70c
CW
782 * @return bool|array
783 * true if no errors, else array of errors
6a488035 784 */
0b36bfd7 785 public static function formRule($fields, $files, $form) {
be2fb01f 786 $errors = [];
6a488035 787 //check that either an email or firstname+lastname is included in the form(CRM-9587)
0b36bfd7 788 self::checkProfileComplete($fields, $errors, $form->_eventId);
6a488035 789 //To check if the user is already registered for the event(CRM-2426)
0b36bfd7
MWMC
790 if (!$form->_skipDupeRegistrationCheck) {
791 self::checkRegistration($fields, $form);
6a488035
TO
792 }
793 //check for availability of registrations.
0b36bfd7
MWMC
794 if (!$form->_allowConfirmation && empty($fields['bypass_payment']) &&
795 is_numeric($form->_availableRegistrations) &&
796 CRM_Utils_Array::value('additional_participants', $fields) >= $form->_availableRegistrations
6a488035 797 ) {
be2fb01f 798 $errors['additional_participants'] = ts("There is only enough space left on this event for %1 participant(s).", [1 => $form->_availableRegistrations]);
6a488035
TO
799 }
800
801 // during confirmation don't allow to increase additional participants, CRM-4320
0b36bfd7
MWMC
802 if ($form->_allowConfirmation && !empty($fields['additional_participants']) &&
803 is_array($form->_additionalParticipantIds) &&
804 $fields['additional_participants'] > count($form->_additionalParticipantIds)
6a488035 805 ) {
be2fb01f 806 $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.", [1 => count($form->_additionalParticipantIds)]);
6a488035
TO
807 }
808
809 //don't allow to register w/ waiting if enough spaces available.
0b36bfd7
MWMC
810 if (!empty($fields['bypass_payment']) && $form->_allowConfirmation) {
811 if (!is_numeric($form->_availableRegistrations) ||
812 (empty($fields['priceSetId']) && CRM_Utils_Array::value('additional_participants', $fields) < $form->_availableRegistrations)
6a488035
TO
813 ) {
814 $errors['bypass_payment'] = ts("Oops. There are enough available spaces in this event. You can not add yourself to the waiting list.");
815 }
816 }
817
a7488080 818 if (!empty($fields['additional_participants']) &&
6a488035
TO
819 !CRM_Utils_Rule::positiveInteger($fields['additional_participants'])
820 ) {
821 $errors['additional_participants'] = ts('Please enter a whole number for Number of additional people.');
822 }
823
824 // priceset validations
0dc0b759 825 if (!empty($fields['priceSetId']) &&
0b36bfd7 826 !$form->_requireApproval && !$form->_allowWaitlist
0dc0b759 827 ) {
6a488035 828 //format params.
0b36bfd7 829 $formatted = self::formatPriceSetParams($form, $fields);
be2fb01f 830 $ppParams = [$formatted];
0b36bfd7
MWMC
831 $priceSetErrors = self::validatePriceSet($form, $ppParams);
832 $primaryParticipantCount = self::getParticipantCount($form, $ppParams);
6a488035
TO
833
834 //get price set fields errors in.
be2fb01f 835 $errors = array_merge($errors, CRM_Utils_Array::value(0, $priceSetErrors, []));
6a488035
TO
836
837 $totalParticipants = $primaryParticipantCount;
a7488080 838 if (!empty($fields['additional_participants'])) {
6a488035
TO
839 $totalParticipants += $fields['additional_participants'];
840 }
841
a7488080 842 if (empty($fields['bypass_payment']) &&
0b36bfd7
MWMC
843 !$form->_allowConfirmation &&
844 is_numeric($form->_availableRegistrations) &&
845 $form->_availableRegistrations < $totalParticipants
6a488035 846 ) {
be2fb01f 847 $errors['_qf_default'] = ts("Only %1 Registrations available.", [1 => $form->_availableRegistrations]);
6a488035
TO
848 }
849
be2fb01f 850 $lineItem = [];
0b36bfd7 851 CRM_Price_BAO_PriceSet::processAmount($form->_values['fee'], $fields, $lineItem);
601c7a24 852
853 $minAmt = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceSet', $fields['priceSetId'], 'min_amount');
6a488035
TO
854 if ($fields['amount'] < 0) {
855 $errors['_qf_default'] = ts('Event Fee(s) can not be less than zero. Please select the options accordingly');
856 }
601c7a24 857 elseif (!empty($minAmt) && $fields['amount'] < $minAmt) {
be2fb01f 858 $errors['_qf_default'] = ts('A minimum amount of %1 should be selected from Event Fee(s).', [
601c7a24 859 1 => CRM_Utils_Money::format($minAmt),
be2fb01f 860 ]);
601c7a24 861 }
6a488035
TO
862 }
863
f48e6cf7 864 // @todo - can we remove the 'is_monetary' concept?
0b36bfd7
MWMC
865 if ($form->_values['event']['is_monetary']) {
866 if (empty($form->_requireApproval) && !empty($fields['amount']) && $fields['amount'] > 0 &&
1019b2fe 867 !isset($fields['payment_processor_id'])) {
e02d7e96 868 $errors['payment_processor_id'] = ts('Please select a Payment Method');
0d588131 869 }
6a488035 870
0d588131 871 $isZeroAmount = $skipPaymentValidation = FALSE;
a7488080 872 if (!empty($fields['priceSetId'])) {
6a488035
TO
873 if (CRM_Utils_Array::value('amount', $fields) == 0) {
874 $isZeroAmount = TRUE;
875 }
876 }
a7488080 877 elseif (!empty($fields['amount']) &&
0b36bfd7
MWMC
878 (isset($form->_values['discount'][$fields['amount']])
879 && CRM_Utils_Array::value('value', $form->_values['discount'][$fields['amount']]) == 0
6a488035
TO
880 )
881 ) {
882 $isZeroAmount = TRUE;
883 }
a7488080 884 elseif (!empty($fields['amount']) &&
0b36bfd7
MWMC
885 (isset($form->_values['fee'][$fields['amount']])
886 && CRM_Utils_Array::value('value', $form->_values['fee'][$fields['amount']]) == 0
6a488035
TO
887 )
888 ) {
889 $isZeroAmount = TRUE;
890 }
891
0b36bfd7 892 if ($isZeroAmount && !($form->_forcePayement && !empty($fields['additional_participants']))) {
0d588131 893 $skipPaymentValidation = TRUE;
6a488035
TO
894 }
895
f48e6cf7 896 // also return if zero fees for valid members
897 if (!empty($fields['bypass_payment']) ||
0d588131 898 $skipPaymentValidation ||
0b36bfd7 899 (!$form->_allowConfirmation && ($form->_requireApproval || $form->_allowWaitlist))
6a488035
TO
900 ) {
901 return empty($errors) ? TRUE : $errors;
902 }
f48e6cf7 903 CRM_Core_Payment_Form::validatePaymentInstrument(
904 $fields['payment_processor_id'],
905 $fields,
906 $errors,
0b36bfd7 907 (!$form->_isBillingAddressRequiredForPayLater ? NULL : 'billing')
f48e6cf7 908 );
6a488035 909 }
6a488035 910
6a488035
TO
911 foreach (CRM_Contact_BAO_Contact::$_greetingTypes as $greeting) {
912 if ($greetingType = CRM_Utils_Array::value($greeting, $fields)) {
233319bf 913 $customizedValue = CRM_Core_PseudoConstant::getKey('CRM_Contact_BAO_Contact', $greeting . '_id', 'Customized');
6a488035 914 if ($customizedValue == $greetingType && empty($fields[$greeting . '_custom'])) {
217d80ab 915 $errors[$greeting . '_custom'] = ts('Custom %1 is a required field if %1 is of type Customized.',
be2fb01f 916 [1 => ucwords(str_replace('_', ' ', $greeting))]
6a488035
TO
917 );
918 }
919 }
920 }
921 return empty($errors) ? TRUE : $errors;
922 }
923
924 /**
ec022878 925 * Check if profiles are complete when event registration occurs(CRM-9587).
926 *
927 * @param array $fields
928 * @param array $errors
929 * @param int $eventId
6a488035 930 */
00be9182 931 public static function checkProfileComplete($fields, &$errors, $eventId) {
6a488035
TO
932 $email = '';
933 foreach ($fields as $fieldname => $fieldvalue) {
934 if (substr($fieldname, 0, 6) == 'email-' && $fieldvalue) {
935 $email = $fieldvalue;
936 }
937 }
938
8cc574cf 939 if (!$email && !(!empty($fields['first_name']) && !empty($fields['last_name']))) {
be2fb01f 940 $defaults = $params = ['id' => $eventId];
6a488035
TO
941 CRM_Event_BAO_Event::retrieve($params, $defaults);
942 $message = ts("Mandatory fields (first name and last name, OR email address) are missing from this form.");
943 $errors['_qf_default'] = $message;
944 }
945 }
946
947 /**
66f9e52b 948 * Process the form submission.
6a488035
TO
949 */
950 public function postProcess() {
951 // get the submitted form values.
952 $params = $this->controller->exportValues($this->_name);
953
954 //set as Primary participant
955 $params['is_primary'] = 1;
956
8ae4d0d3 957 if ($this->_values['event']['is_pay_later']
e02d7e96 958 && (!array_key_exists('hidden_processor', $params) || $params['payment_processor_id'] == 0)
353ffa53 959 ) {
6a488035
TO
960 $params['is_pay_later'] = 1;
961 }
962 else {
963 $params['is_pay_later'] = 0;
964 }
965
966 $this->set('is_pay_later', $params['is_pay_later']);
967
968 // assign pay later stuff
969 $this->_params['is_pay_later'] = CRM_Utils_Array::value('is_pay_later', $params, FALSE);
970 $this->assign('is_pay_later', $params['is_pay_later']);
971 if ($params['is_pay_later']) {
972 $this->assign('pay_later_text', $this->_values['event']['pay_later_text']);
973 $this->assign('pay_later_receipt', $this->_values['event']['pay_later_receipt']);
974 }
6a488035 975
168e792f
DL
976 if (!$this->_allowConfirmation) {
977 // check if the participant is already registered
978 if (!$this->_skipDupeRegistrationCheck) {
7dfe13ab 979 $params['contact_id'] = self::getRegistrationContactID($params, $this, FALSE);
168e792f
DL
980 }
981 }
982
a7488080 983 if (!empty($params['image_URL'])) {
6a488035
TO
984 CRM_Contact_BAO_Contact::processImageParams($params);
985 }
986
987 //carry campaign to partcipants.
988 if (array_key_exists('participant_campaign_id', $params)) {
989 $params['campaign_id'] = $params['participant_campaign_id'];
990 }
991 else {
992 $params['campaign_id'] = CRM_Utils_Array::value('campaign_id', $this->_values['event']);
993 }
994
995 //hack to allow group to register w/ waiting
996 $primaryParticipantCount = self::getParticipantCount($this, $params);
997
998 $totalParticipants = $primaryParticipantCount;
a7488080 999 if (!empty($params['additional_participants'])) {
6a488035
TO
1000 $totalParticipants += $params['additional_participants'];
1001 }
8cc574cf 1002 if (!$this->_allowConfirmation && !empty($params['bypass_payment']) &&
6a488035
TO
1003 is_numeric($this->_availableRegistrations) &&
1004 $totalParticipants > $this->_availableRegistrations
1005 ) {
1006 $this->_allowWaitlist = TRUE;
1007 $this->set('allowWaitlist', TRUE);
1008 }
1009
1010 //carry participant id if pre-registered.
1011 if ($this->_allowConfirmation && $this->_participantId) {
1012 $params['participant_id'] = $this->_participantId;
1013 }
1014
1015 $params['defaultRole'] = 1;
1016 if (array_key_exists('participant_role', $params)) {
1017 $params['participant_role_id'] = $params['participant_role'];
1018 }
1019
1020 if (array_key_exists('participant_role_id', $params)) {
1021 $params['defaultRole'] = 0;
1022 }
a7488080 1023 if (empty($params['participant_role_id']) &&
6a488035
TO
1024 $this->_values['event']['default_role_id']
1025 ) {
1026 $params['participant_role_id'] = $this->_values['event']['default_role_id'];
1027 }
1028
1029 $config = CRM_Core_Config::singleton();
1030 $params['currencyID'] = $config->defaultCurrency;
1031
1032 if ($this->_values['event']['is_monetary']) {
1033 // we first reset the confirm page so it accepts new values
1034 $this->controller->resetPage('Confirm');
1035
1036 //added for discount
1037 $discountId = CRM_Core_BAO_Discount::findSet($this->_eventId, 'civicrm_event');
c039f658 1038 $params['amount_level'] = $this->getAmountLevel($params, $discountId);
6a488035
TO
1039 if (!empty($this->_values['discount'][$discountId])) {
1040 $params['discount_id'] = $discountId;
6a488035
TO
1041 $params['amount'] = $this->_values['discount'][$discountId][$params['amount']]['value'];
1042 }
1043 elseif (empty($params['priceSetId'])) {
16d1c8e2 1044 if (!empty($params['amount'])) {
16d1c8e2 1045 $params['amount'] = $this->_values['fee'][$params['amount']]['value'];
1046 }
1047 else {
c039f658 1048 $params['amount'] = '';
16d1c8e2 1049 }
6a488035
TO
1050 }
1051 else {
be2fb01f 1052 $lineItem = [];
9da8dc8c 1053 CRM_Price_BAO_PriceSet::processAmount($this->_values['fee'], $params, $lineItem);
d91b8b33 1054 if ($params['tax_amount']) {
1055 $this->set('tax_amount', $params['tax_amount']);
1056 }
9d8d8fd0 1057 $submittedLineItems = $this->get('lineItem');
1058 if (!empty($submittedLineItems) && is_array($submittedLineItems)) {
0dc0b759 1059 $submittedLineItems[0] = $lineItem;
1060 }
1061 else {
be2fb01f 1062 $submittedLineItems = [$lineItem];
0dc0b759 1063 }
dba6436f 1064 $submittedLineItems = array_filter($submittedLineItems);
0dc0b759 1065 $this->set('lineItem', $submittedLineItems);
be2fb01f 1066 $this->set('lineItemParticipantsCount', [$primaryParticipantCount]);
6a488035
TO
1067 }
1068
1069 $this->set('amount', $params['amount']);
1070 $this->set('amount_level', $params['amount_level']);
1071
1072 // generate and set an invoiceID for this transaction
1073 $invoiceID = md5(uniqid(rand(), TRUE));
1074 $this->set('invoiceID', $invoiceID);
1075
b0c462ac 1076 if ($this->_paymentProcessor) {
077017db 1077 $payment = $this->_paymentProcessor['object'];
ec022878 1078 $payment->setBaseReturnUrl('civicrm/event/register');
6a488035 1079 }
0eb1f7ff 1080
1081 // ContributeMode is a deprecated concept. It is short-hand for a bunch of
1082 // assumptions we are working to remove.
6a488035
TO
1083 $this->set('contributeMode', 'direct');
1084
0eb1f7ff 1085 // This code is duplicated multiple places and should be consolidated.
6a488035
TO
1086 if (isset($params["state_province_id-{$this->_bltID}"]) &&
1087 $params["state_province_id-{$this->_bltID}"]
1088 ) {
1089 $params["state_province-{$this->_bltID}"] = CRM_Core_PseudoConstant::stateProvinceAbbreviation($params["state_province_id-{$this->_bltID}"]);
1090 }
1091
1092 if (isset($params["country_id-{$this->_bltID}"]) &&
1093 $params["country_id-{$this->_bltID}"]
1094 ) {
1095 $params["country-{$this->_bltID}"] = CRM_Core_PseudoConstant::countryIsoCode($params["country_id-{$this->_bltID}"]);
1096 }
1097 if (isset($params['credit_card_exp_date'])) {
1098 $params['year'] = CRM_Core_Payment_Form::getCreditCardExpirationYear($params);
1099 $params['month'] = CRM_Core_Payment_Form::getCreditCardExpirationMonth($params);
1100 }
1101 if ($this->_values['event']['is_monetary']) {
1102 $params['ip_address'] = CRM_Utils_System::ipAddress();
1103 $params['currencyID'] = $config->defaultCurrency;
6a488035
TO
1104 $params['invoiceID'] = $invoiceID;
1105 }
d0ebccea 1106 $this->_params = $this->get('params');
ec022878 1107 // Set the button so we know what
1108 $params['button'] = $this->controller->getButtonName();
d0ebccea 1109 if (!empty($this->_params) && is_array($this->_params)) {
0dc0b759 1110 $this->_params[0] = $params;
1111 }
1112 else {
be2fb01f 1113 $this->_params = [];
0dc0b759 1114 $this->_params[] = $params;
1115 }
6a488035 1116 $this->set('params', $this->_params);
f92fc7eb 1117 if ($this->_paymentProcessor &&
223190c8 1118 // Actually we don't really need to check if it supports pre-approval - we could just call
1119 // it regardless as the function we call re-acts tot the rests of the preApproval call.
ec022878 1120 $this->_paymentProcessor['object']->supports('preApproval')
1121 && !$this->_allowWaitlist &&
1122 !$this->_requireApproval
f92fc7eb 1123 ) {
6a488035 1124
0f2b049e 1125 // The concept of contributeMode is deprecated - but still needs removal from the message templates.
ec022878 1126 $this->set('contributeMode', 'express');
6a488035 1127
ec022878 1128 // Send Event Name & Id in Params
1129 $params['eventName'] = $this->_values['event']['title'];
1130 $params['eventId'] = $this->_values['event']['id'];
6a488035 1131
ec022878 1132 $params['cancelURL'] = CRM_Utils_System::url('civicrm/event/register',
1133 "_qf_Register_display=1&qfKey={$this->controller->_key}",
1134 TRUE, NULL, FALSE
1135 );
1136 if (CRM_Utils_Array::value('additional_participants', $params, FALSE)) {
1137 $urlArgs = "_qf_Participant_1_display=1&rfp=1&qfKey={$this->controller->_key}";
1138 }
1139 else {
1140 $urlArgs = "_qf_Confirm_display=1&rfp=1&qfKey={$this->controller->_key}";
1141 }
1142 $params['returnURL'] = CRM_Utils_System::url('civicrm/event/register',
1143 $urlArgs,
1144 TRUE, NULL, FALSE
1145 );
1146 $params['invoiceID'] = $invoiceID;
6a488035 1147
ec022878 1148 $params['component'] = 'event';
223190c8 1149 $this->handlePreApproval($params);
6a488035 1150 }
f92fc7eb 1151 elseif ($this->_paymentProcessor &&
5e3148f4 1152 (int) $this->_paymentProcessor['billing_mode'] & CRM_Core_Payment::BILLING_MODE_NOTIFY
f92fc7eb 1153 ) {
0f2b049e 1154 // The concept of contributeMode is deprecated - but still needs removal from the message templates.
6a488035
TO
1155 $this->set('contributeMode', 'notify');
1156 }
13f230bc 1157 }
1158 else {
1159 $params['description'] = ts('Online Event Registration') . ' ' . $this->_values['event']['title'];
6a488035 1160
be2fb01f 1161 $this->_params = [];
13f230bc 1162 $this->_params[] = $params;
1163 $this->set('params', $this->_params);
6a488035 1164
13f230bc 1165 if (
1166 empty($params['additional_participants'])
90b461f1
SL
1167 // CRM-11182 - Optional confirmation screen
1168 && !$this->_values['event']['is_confirm_enabled']
13f230bc 1169 ) {
3033e657 1170 $this->processRegistration($this->_params);
6a488035
TO
1171 }
1172 }
1173
1174 // If registering > 1 participant, give status message
1175 if (CRM_Utils_Array::value('additional_participants', $params, FALSE)) {
1176 $statusMsg = ts('Registration information for participant 1 has been saved.');
1177 CRM_Core_Session::setStatus($statusMsg, ts('Saved'), 'success');
1178 }
1179 }
6a488035 1180
6a488035 1181 /**
66f9e52b 1182 * Method to check if the user is already registered for the event.
6a488035
TO
1183 * and if result found redirect to the event info page
1184 *
d4dd1e85
TO
1185 * @param array $fields
1186 * The input form values(anonymous user).
0b36bfd7 1187 * @param CRM_Event_Form_Registration_Register $form
d4dd1e85
TO
1188 * Event data.
1189 * @param bool $isAdditional
1190 * Treat isAdditional participants a bit differently.
6a488035 1191 *
54957108 1192 * @return int
6a488035 1193 */
0b36bfd7 1194 public static function checkRegistration($fields, $form, $isAdditional = FALSE) {
6a488035
TO
1195 // CRM-3907, skip check for preview registrations
1196 // CRM-4320 participant need to walk wizard
7dfe13ab 1197 if (
0b36bfd7 1198 ($form->_mode == 'test' || $form->_allowConfirmation)
6a488035
TO
1199 ) {
1200 return FALSE;
1201 }
1202
0b36bfd7 1203 $contactID = self::getRegistrationContactID($fields, $form, $isAdditional);
6a488035 1204
6a488035
TO
1205 if ($contactID) {
1206 $participant = new CRM_Event_BAO_Participant();
1207 $participant->contact_id = $contactID;
0b36bfd7 1208 $participant->event_id = $form->_values['event']['id'];
6a488035
TO
1209 if (!empty($fields['participant_role']) && is_numeric($fields['participant_role'])) {
1210 $participant->role_id = $fields['participant_role'];
1211 }
1212 else {
0b36bfd7 1213 $participant->role_id = $form->_values['event']['default_role_id'];
6a488035
TO
1214 }
1215 $participant->is_test = 0;
1216 $participant->find();
1217 $statusTypes = CRM_Event_PseudoConstant::participantStatus(NULL, 'is_counted = 1');
1218 while ($participant->fetch()) {
1219 if (array_key_exists($participant->status_id, $statusTypes)) {
0b36bfd7 1220 if (!$isAdditional && !$form->_values['event']['allow_same_participant_emails']) {
6a488035 1221 $registerUrl = CRM_Utils_System::url('civicrm/event/register',
0b36bfd7 1222 "reset=1&id={$form->_values['event']['id']}&cid=0"
6a488035 1223 );
0b36bfd7
MWMC
1224 if ($form->_pcpId) {
1225 $registerUrl .= '&pcpId=' . $form->_pcpId;
6a488035
TO
1226 }
1227
be2fb01f 1228 $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 received this message in error, please contact the site administrator.") . ' ' . ts('You can also <a href="%1">register another participant</a>.', [1 => $registerUrl]);
7dfe13ab 1229 CRM_Core_Session::singleton()->setStatus($status, ts('Oops.'), 'alert');
6a488035 1230 $url = CRM_Utils_System::url('civicrm/event/info',
0b36bfd7 1231 "reset=1&id={$form->_values['event']['id']}&noFullMsg=true"
6a488035 1232 );
0b36bfd7 1233 if ($form->_action & CRM_Core_Action::PREVIEW) {
6a488035
TO
1234 $url .= '&action=preview';
1235 }
1236
0b36bfd7
MWMC
1237 if ($form->_pcpId) {
1238 $url .= '&pcpId=' . $form->_pcpId;
6a488035
TO
1239 }
1240
1241 CRM_Utils_System::redirect($url);
1242 }
1243
1244 if ($isAdditional) {
06141953 1245 $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 received this message in error, please contact the site administrator.");
7dfe13ab 1246 CRM_Core_Session::singleton()->setStatus($status, ts('Oops.'), 'alert');
6a488035
TO
1247 return $participant->id;
1248 }
1249 }
1250 }
1251 }
1252 }
96025800 1253
6a488035 1254}