(NFC) (dev/core#878) Simplify '@copyright' annotation
[civicrm-core.git] / CRM / Event / Form / Registration / AdditionalParticipant.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 5 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2020 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
9 | |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
13 | |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
18 | |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
26 */
27
28 /**
29 *
30 *
31 * @package CRM
32 * @copyright CiviCRM LLC https://civicrm.org/licensing
33 */
34
35 /**
36 * This class generates form components for processing Event.
37 */
38 class CRM_Event_Form_Registration_AdditionalParticipant extends CRM_Event_Form_Registration {
39
40 /**
41 * Pre-registered additional participant id.
42 * @var int
43 */
44 public $additionalParticipantId = NULL;
45
46 /**
47 * Set variables up before form is built.
48 *
49 * @return void
50 */
51 public function preProcess() {
52 parent::preProcess();
53
54 $participantNo = substr($this->_name, 12);
55
56 //lets process in-queue participants.
57 if ($this->_participantId && $this->_additionalParticipantIds) {
58 $this->_additionalParticipantId = CRM_Utils_Array::value($participantNo, $this->_additionalParticipantIds);
59 }
60
61 $participantCnt = $participantNo + 1;
62 $this->assign('formId', $participantNo);
63 $this->_params = [];
64 $this->_params = $this->get('params');
65
66 $participantTot = $this->_params[0]['additional_participants'] + 1;
67 $skipCount = count(array_keys($this->_params, "skip"));
68 if ($skipCount) {
69 $this->assign('skipCount', $skipCount);
70 }
71 CRM_Utils_System::setTitle(ts('Register Participant %1 of %2', [1 => $participantCnt, 2 => $participantTot]));
72
73 //CRM-4320, hack to check last participant.
74 $this->_lastParticipant = FALSE;
75 if ($participantTot == $participantCnt) {
76 $this->_lastParticipant = TRUE;
77 }
78 $this->assign('lastParticipant', $this->_lastParticipant);
79 }
80
81 /**
82 * Set default values for the form. For edit/view mode
83 * the default values are retrieved from the database
84 *
85 *
86 * @return void
87 */
88 public function setDefaultValues() {
89 $defaults = $unsetSubmittedOptions = [];
90 $discountId = NULL;
91 //fix for CRM-3088, default value for discount set.
92 if (!empty($this->_values['discount'])) {
93 $discountId = CRM_Core_BAO_Discount::findSet($this->_eventId, 'civicrm_event');
94 if ($discountId && !empty($this->_values['event']['default_discount_fee_id'])) {
95 $discountKey = CRM_Core_DAO::getFieldValue("CRM_Core_DAO_OptionValue", $this->_values['event']['default_discount_fee_id'], 'weight', 'id'
96 );
97 $defaults['amount'] = key(array_slice($this->_values['discount'][$discountId], $discountKey - 1, $discountKey, TRUE));
98 }
99 }
100 if ($this->_priceSetId) {
101 foreach ($this->_feeBlock as $key => $val) {
102 if (empty($val['options'])) {
103 continue;
104 }
105
106 $optionsFull = CRM_Utils_Array::value('option_full_ids', $val, []);
107 foreach ($val['options'] as $keys => $values) {
108 if ($values['is_default'] && !in_array($keys, $optionsFull)) {
109 if ($val['html_type'] == 'CheckBox') {
110 $defaults["price_{$key}"][$keys] = 1;
111 }
112 else {
113 $defaults["price_{$key}"] = $keys;
114 }
115 }
116 }
117 if (!empty($optionsFull)) {
118 $unsetSubmittedOptions[$val['id']] = $optionsFull;
119 }
120 }
121 }
122
123 //CRM-4320, setdefault additional participant values.
124 if ($this->_allowConfirmation && $this->_additionalParticipantId) {
125 //hack to get set default from eventFees.php
126 $this->_discountId = $discountId;
127 $this->_pId = $this->_additionalParticipantId;
128 $this->_contactId = CRM_Core_DAO::getFieldValue('CRM_Event_DAO_Participant', $this->_additionalParticipantId, 'contact_id');
129
130 CRM_Event_BAO_Participant::formatFieldsAndSetProfileDefaults($this->_contactId, $this);
131 $participantDefaults = CRM_Event_Form_EventFees::setDefaultValues($this);
132 $participantDefaults = array_merge($this->_defaults, $participantDefaults);
133 // use primary email address if billing email address is empty
134 if (empty($this->_defaults["email-{$this->_bltID}"]) &&
135 !empty($this->_defaults["email-Primary"])
136 ) {
137 $participantDefaults["email-{$this->_bltID}"] = $this->_defaults["email-Primary"];
138 }
139 $defaults = array_merge($defaults, $participantDefaults);
140 }
141
142 $defaults = array_merge($this->_defaults, $defaults);
143
144 //reset values for all options those are full.
145 CRM_Event_Form_Registration::resetElementValue($unsetSubmittedOptions, $this);
146
147 //load default campaign from page.
148 if (array_key_exists('participant_campaign_id', $this->_fields)) {
149 $defaults['participant_campaign_id'] = CRM_Utils_Array::value('campaign_id', $this->_values['event']);
150 }
151
152 //CRM-17865 set custom field defaults
153 if (!empty($this->_fields)) {
154 foreach ($this->_fields as $name => $field) {
155 if ($customFieldID = CRM_Core_BAO_CustomField::getKeyID($name)) {
156 if (!isset($defaults[$name])) {
157 CRM_Core_BAO_CustomField::setProfileDefaults($customFieldID, $name, $defaults,
158 NULL, CRM_Profile_Form::MODE_REGISTER
159 );
160 }
161 }
162 }
163 }
164
165 return $defaults;
166 }
167
168 /**
169 * Build the form object.
170 *
171 * @return void
172 */
173 public function buildQuickForm() {
174
175 $button = substr($this->controller->getButtonName(), -4);
176
177 if ($this->_values['event']['is_monetary']) {
178 CRM_Event_Form_Registration_Register::buildAmount($this);
179 }
180
181 //Add pre and post profiles on the form.
182 foreach (['pre', 'post'] as $keys) {
183 if (isset($this->_values['additional_custom_' . $keys . '_id'])) {
184 $this->buildCustom($this->_values['additional_custom_' . $keys . '_id'], 'additionalCustom' . ucfirst($keys));
185 }
186 }
187
188 //add buttons
189 if ($this->isLastParticipant(TRUE) && empty($this->_values['event']['is_monetary'])) {
190 $this->submitOnce = TRUE;
191 }
192
193 //handle case where user might sart with waiting by group
194 //registration and skip some people and now group fit to
195 //become registered so need to take payment from user.
196 //this case only occurs at dynamic waiting status, CRM-4320
197 $statusMessage = NULL;
198 $allowToProceed = TRUE;
199 $includeSkipButton = TRUE;
200 $this->_resetAllowWaitlist = FALSE;
201
202 $pricesetFieldsCount = CRM_Price_BAO_PriceSet::getPricesetCount($this->_priceSetId);
203
204 if ($this->_lastParticipant || $pricesetFieldsCount) {
205 //get the participant total.
206 $processedCnt = self::getParticipantCount($this, $this->_params, TRUE);
207 }
208
209 if (!$this->_allowConfirmation && !empty($this->_params[0]['bypass_payment']) &&
210 $this->_lastParticipant
211 ) {
212
213 //get the event spaces.
214 $spaces = $this->_availableRegistrations;
215
216 $currentPageMaxCount = 1;
217 if ($pricesetFieldsCount) {
218 $currentPageMaxCount = $pricesetFieldsCount;
219 }
220
221 //we might did reset allow waiting in case of dynamic calculation
222 // @TODO - does this bypass_payment still exist?
223 if (!empty($this->_params[0]['bypass_payment']) &&
224 is_numeric($spaces) &&
225 $processedCnt > $spaces
226 ) {
227 $this->_allowWaitlist = TRUE;
228 $this->set('allowWaitlist', TRUE);
229 }
230
231 //lets allow to become a part of runtime waiting list, if primary selected pay later.
232 $realPayLater = FALSE;
233 if (!empty($this->_values['event']['is_monetary']) && !empty($this->_values['event']['is_pay_later'])) {
234 $realPayLater = CRM_Utils_Array::value('is_pay_later', $this->_params[0]);
235 }
236
237 //truly spaces are greater than required.
238 if (is_numeric($spaces) && $spaces >= ($processedCnt + $currentPageMaxCount)) {
239 if (CRM_Utils_Array::value('amount', $this->_params[0], 0) == 0 || $this->_requireApproval) {
240 $this->_allowWaitlist = FALSE;
241 $this->set('allowWaitlist', $this->_allowWaitlist);
242 if ($this->_requireApproval) {
243 $statusMessage = ts("It looks like you are now registering a group of %1 participants. The event has %2 available spaces (you will not be wait listed). Registration for this event requires approval. You will receive an email once your registration has been reviewed.", [
244 1 => ++$processedCnt,
245 2 => $spaces,
246 ]);
247 }
248 else {
249 $statusMessage = ts("It looks like you are now registering a group of %1 participants. The event has %2 available spaces (you will not be wait listed).", [
250 1 => ++$processedCnt,
251 2 => $spaces,
252 ]);
253 }
254 }
255 else {
256 $statusMessage = ts("It looks like you are now registering a group of %1 participants. The event has %2 available spaces (you will not be wait listed). Please go back to the main registration page and reduce the number of additional people. You will also need to complete payment information.", [
257 1 => ++$processedCnt,
258 2 => $spaces,
259 ]);
260 $allowToProceed = FALSE;
261 }
262 CRM_Core_Session::setStatus($statusMessage, ts('Registration Error'), 'error');
263 }
264 elseif ($processedCnt == $spaces) {
265 if (CRM_Utils_Array::value('amount', $this->_params[0], 0) == 0
266 || $realPayLater || $this->_requireApproval
267 ) {
268 $this->_resetAllowWaitlist = TRUE;
269 if ($this->_requireApproval) {
270 $statusMessage = ts("If you skip this participant there will be enough spaces in the event for your group (you will not be wait listed). Registration for this event requires approval. You will receive an email once your registration has been reviewed.");
271 }
272 else {
273 $statusMessage = ts("If you skip this participant there will be enough spaces in the event for your group (you will not be wait listed).");
274 }
275 }
276 else {
277 //hey there is enough space and we require payment.
278 $statusMessage = ts("If you skip this participant there will be enough spaces in the event for your group (you will not be wait listed). Please go back to the main registration page and reduce the number of additional people. You will also need to complete payment information.");
279 $includeSkipButton = FALSE;
280 }
281 }
282 }
283
284 // for priceset with count
285 if ($pricesetFieldsCount && !empty($this->_values['event']['has_waitlist']) &&
286 !$this->_allowConfirmation
287 ) {
288
289 if ($this->_isEventFull) {
290 $statusMessage = ts('This event is currently full. You are registering for the waiting list. You will be notified if spaces become available.');
291 }
292 elseif ($this->_allowWaitlist ||
293 (!$this->_allowWaitlist && ($processedCnt + $pricesetFieldsCount) > $this->_availableRegistrations)
294 ) {
295
296 $waitingMsg = ts('It looks like you are registering more participants then there are spaces available. All participants will be added to the waiting list. You will be notified if spaces become available.');
297 $confirmedMsg = ts('It looks like there are enough spaces in this event for your group (you will not be wait listed).');
298 if ($this->_requireApproval) {
299 $waitingMsg = ts('It looks like you are now registering a group of %1 participants. The event has %2 available spaces (you will not be wait listed). Registration for this event requires approval. You will receive an email once your registration has been reviewed.');
300 $confirmedMsg = ts('It looks there are enough spaces in this event for your group (you will not be wait listed). Registration for this event requires approval. You will receive an email once your registration has been reviewed.');
301 }
302
303 $this->assign('waitingMsg', $waitingMsg);
304 $this->assign('confirmedMsg', $confirmedMsg);
305
306 $this->assign('availableRegistrations', $this->_availableRegistrations);
307 $this->assign('currentParticipantCount', $processedCnt);
308 $this->assign('allowGroupOnWaitlist', TRUE);
309
310 $paymentBypassed = NULL;
311 if (!empty($this->_params[0]['bypass_payment']) &&
312 !$this->_allowWaitlist &&
313 !$realPayLater &&
314 !$this->_requireApproval &&
315 !(CRM_Utils_Array::value('amount', $this->_params[0], 0) == 0)
316 ) {
317 $paymentBypassed = ts('Please go back to the main registration page, to complete payment information.');
318 }
319 $this->assign('paymentBypassed', $paymentBypassed);
320 }
321 }
322
323 $this->assign('statusMessage', $statusMessage);
324
325 $buttons = [
326 [
327 'type' => 'back',
328 'name' => ts('Go Back'),
329 'spacing' => '&nbsp;&nbsp;&nbsp;&nbsp',
330 ],
331 ];
332
333 //CRM-4320
334 if ($allowToProceed) {
335 $buttons = array_merge($buttons, [
336 [
337 'type' => 'upload',
338 'name' => ts('Continue'),
339 'spacing' => '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;',
340 'isDefault' => TRUE,
341 ],
342 ]);
343 if ($includeSkipButton) {
344 $buttons = array_merge($buttons, [
345 [
346 'type' => 'next',
347 'name' => ts('Skip Participant'),
348 'subName' => 'skip',
349 'icon' => 'fa-fast-forward',
350 ],
351 ]);
352 }
353 }
354 $this->addButtons($buttons);
355 $this->addFormRule(['CRM_Event_Form_Registration_AdditionalParticipant', 'formRule'], $this);
356 $this->unsavedChangesWarn = TRUE;
357 }
358
359 /**
360 * Global form rule.
361 *
362 * @param array $fields
363 * The input form values.
364 * @param array $files
365 * The uploaded files if any.
366 * @param $self
367 *
368 *
369 * @return bool|array
370 * true if no errors, else array of errors
371 */
372 public static function formRule($fields, $files, $self) {
373 $errors = [];
374 //get the button name.
375 $button = substr($self->controller->getButtonName(), -4);
376
377 $realPayLater = FALSE;
378 if (!empty($self->_values['event']['is_monetary']) && !empty($self->_values['event']['is_pay_later'])) {
379 $realPayLater = CRM_Utils_Array::value('is_pay_later', $self->_params[0]);
380 }
381
382 if ($button != 'skip') {
383 //Check that either an email or firstname+lastname is included in the form(CRM-9587)
384 CRM_Event_Form_Registration_Register::checkProfileComplete($fields, $errors, $self->_eventId);
385
386 //Additional Participant can also register for an event only once
387 $isRegistered = CRM_Event_Form_Registration_Register::checkRegistration($fields, $self, TRUE);
388 if ($isRegistered) {
389 if ($self->_values['event']['allow_same_participant_emails']) {
390 $errors['_qf_default'] = ts('A person is already registered for this event.');
391 }
392 else {
393 $errors["email-{$self->_bltID}"] = ts('A person with this email address is already registered for this event.');
394 }
395 }
396
397 //get the complete params.
398 $params = $self->get('params');
399
400 //take the participant instance.
401 $addParticipantNum = substr($self->_name, 12);
402
403 if (is_array($params)) {
404 foreach ($params as $key => $value) {
405 if ($key != $addParticipantNum) {
406 if (!$self->_values['event']['allow_same_participant_emails']) {
407 //collect all email fields
408 $existingEmails = [];
409 $additionalParticipantEmails = [];
410 if (is_array($value)) {
411 foreach ($value as $key => $val) {
412 if (substr($key, 0, 6) == 'email-' && $val) {
413 $existingEmails[] = $val;
414 }
415 }
416 }
417 foreach ($fields as $key => $val) {
418 if (substr($key, 0, 6) == 'email-' && $val) {
419 $additionalParticipantEmails[] = $val;
420 $mailKey = $key;
421 }
422 }
423 //check if any emails are common to both arrays
424 if (count(array_intersect($existingEmails, $additionalParticipantEmails))) {
425 $errors[$mailKey] = ts('The email address must be unique for each participant.');
426 break;
427 }
428 }
429 else {
430 // check with first_name and last_name for additional participants
431 if (!empty($value['first_name']) && ($value['first_name'] == CRM_Utils_Array::value('first_name', $fields)) &&
432 (CRM_Utils_Array::value('last_name', $value) == CRM_Utils_Array::value('last_name', $fields))
433 ) {
434 $errors['first_name'] = ts('The first name and last name must be unique for each participant.');
435 break;
436 }
437 }
438 }
439 }
440 }
441
442 //check for atleast one pricefields should be selected
443 if (!empty($fields['priceSetId'])) {
444 $allParticipantParams = $params;
445
446 //format current participant params.
447 $allParticipantParams[$addParticipantNum] = self::formatPriceSetParams($self, $fields);
448 $totalParticipants = self::getParticipantCount($self, $allParticipantParams);
449
450 //validate price field params.
451 $priceSetErrors = self::validatePriceSet($self, $allParticipantParams);
452 $errors = array_merge($errors, CRM_Utils_Array::value($addParticipantNum, $priceSetErrors, []));
453
454 if (!$self->_allowConfirmation &&
455 is_numeric($self->_availableRegistrations)
456 ) {
457 if (!empty($self->_params[0]['bypass_payment']) &&
458 !$self->_allowWaitlist &&
459 !$realPayLater &&
460 !$self->_requireApproval &&
461 !(CRM_Utils_Array::value('amount', $self->_params[0], 0) == 0) &&
462 $totalParticipants < $self->_availableRegistrations
463 ) {
464 $errors['_qf_default'] = ts("Your event registration will be confirmed. Please go back to the main registration page, to complete payment information.");
465 }
466 //check for availability of registrations.
467 if (!$self->_allowConfirmation && empty($self->_values['event']['has_waitlist']) &&
468 $totalParticipants > $self->_availableRegistrations
469 ) {
470 $errors['_qf_default'] = ts('Sorry, it looks like this event only has %2 spaces available, and you are trying to register %1 participants. Please change your selections accordingly.', [
471 1 => $totalParticipants,
472 2 => $self->_availableRegistrations,
473 ]);
474 }
475 }
476 }
477 }
478
479 if ($button == 'skip' && $self->_lastParticipant && !empty($fields['priceSetId'])) {
480 $pricesetFieldsCount = CRM_Price_BAO_PriceSet::getPricesetCount($fields['priceSetId']);
481 if (($pricesetFieldsCount < 1) || $self->_allowConfirmation) {
482 return $errors;
483 }
484
485 if (!empty($self->_values['event']['has_waitlist']) && !empty($self->_params[0]['bypass_payment']) &&
486 !$self->_allowWaitlist &&
487 !$realPayLater &&
488 !$self->_requireApproval &&
489 !(CRM_Utils_Array::value('amount', $self->_params[0], 0) == 0)
490 ) {
491 $errors['_qf_default'] = ts("You are going to skip the last participant, your event registration will be confirmed. Please go back to the main registration page, to complete payment information.");
492 }
493 }
494
495 if ($button != 'skip' &&
496 $self->_values['event']['is_monetary'] &&
497 !isset($errors['_qf_default']) &&
498 !$self->validatePaymentValues($self, $fields)
499 ) {
500 $errors['_qf_default'] = ts("Your payment information looks incomplete. Please go back to the main registration page, to complete payment information.");
501 $self->set('forcePayement', TRUE);
502 }
503 elseif ($button == 'skip') {
504 $self->set('forcePayement', TRUE);
505 }
506
507 return $errors;
508 }
509
510 /**
511 * @param $self
512 * @param $fields
513 *
514 * @return bool
515 */
516 public function validatePaymentValues($self, $fields) {
517
518 if (!empty($self->_params[0]['bypass_payment']) ||
519 $self->_allowWaitlist ||
520 empty($self->_fields) ||
521 CRM_Utils_Array::value('amount', $self->_params[0]) > 0
522 ) {
523 return TRUE;
524 }
525
526 $validatePayement = FALSE;
527 if (!empty($fields['priceSetId'])) {
528 $lineItem = [];
529 CRM_Price_BAO_PriceSet::processAmount($self->_values['fee'], $fields, $lineItem);
530 if ($fields['amount'] > 0) {
531 $validatePayement = TRUE;
532 // return false;
533 }
534 }
535 elseif (!empty($fields['amount']) &&
536 (CRM_Utils_Array::value('value', $self->_values['fee'][$fields['amount']]) > 0)
537 ) {
538 $validatePayement = TRUE;
539 }
540
541 if (!$validatePayement) {
542 return TRUE;
543 }
544
545 $errors = [];
546
547 CRM_Core_Form::validateMandatoryFields($self->_fields, $fields, $errors);
548
549 if (isset($self->_params[0]['payment_processor'])) {
550 // validate supplied payment instrument values (e.g. credit card number and cvv)
551 $payment_processor_id = $self->_params[0]['payment_processor'];
552 CRM_Core_Payment_Form::validatePaymentInstrument($payment_processor_id, $self->_params[0], $errors, (!$self->_isBillingAddressRequiredForPayLater ? NULL : 'billing'));
553 }
554 if (!empty($errors)) {
555 return FALSE;
556 }
557
558 foreach (CRM_Contact_BAO_Contact::$_greetingTypes as $greeting) {
559 if ($greetingType = CRM_Utils_Array::value($greeting, $self->_params[0])) {
560 $customizedValue = CRM_Core_PseudoConstant::getKey('CRM_Contact_BAO_Contact', $greeting . '_id', 'Customized');
561 if ($customizedValue == $greetingType && empty($self->_params[0][$greeting . '_custom'])) {
562 return FALSE;
563 }
564 }
565 }
566 return TRUE;
567 }
568
569 /**
570 * Process the form submission.
571 *
572 *
573 * @return void
574 */
575 public function postProcess() {
576 //get the button name.
577 $button = substr($this->controller->getButtonName(), -4);
578
579 //take the participant instance.
580 $addParticipantNum = substr($this->_name, 12);
581
582 //user submitted params.
583 $params = $this->controller->exportValues($this->_name);
584
585 if (!$this->_allowConfirmation) {
586 // check if the participant is already registered
587 $params['contact_id'] = CRM_Event_Form_Registration_Register::getRegistrationContactID($params, $this, TRUE);
588 }
589
590 if (!empty($params['image_URL'])) {
591 CRM_Contact_BAO_Contact::processImageParams($params);
592 }
593 //carry campaign to partcipants.
594 if (array_key_exists('participant_campaign_id', $params)) {
595 $params['campaign_id'] = $params['participant_campaign_id'];
596 }
597 else {
598 $params['campaign_id'] = CRM_Utils_Array::value('campaign_id', $this->_values['event']);
599 }
600
601 // if waiting is enabled
602 if (!$this->_allowConfirmation &&
603 is_numeric($this->_availableRegistrations)
604 ) {
605 $this->_allowWaitlist = FALSE;
606 //get the current page count.
607 $currentCount = self::getParticipantCount($this, $params);
608 if ($button == 'skip') {
609 $currentCount = 'skip';
610 }
611
612 //get the total count.
613 $previousCount = self::getParticipantCount($this, $this->_params, TRUE);
614 $totalParticipants = $previousCount;
615 if (is_numeric($currentCount)) {
616 $totalParticipants += $currentCount;
617 }
618 if (!empty($this->_values['event']['has_waitlist']) &&
619 $totalParticipants > $this->_availableRegistrations
620 ) {
621 $this->_allowWaitlist = TRUE;
622 }
623 $this->set('allowWaitlist', $this->_allowWaitlist);
624 $this->_lineItemParticipantsCount[$addParticipantNum] = $currentCount;
625 }
626
627 if ($button == 'skip') {
628 //hack for free/zero amount event.
629 if ($this->_resetAllowWaitlist) {
630 $this->_allowWaitlist = FALSE;
631 $this->set('allowWaitlist', FALSE);
632 if ($this->_requireApproval) {
633 $status = ts("You have skipped last participant and which result into event having enough spaces, but your registration require 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.");
634 }
635 else {
636 $status = ts("You have skipped last participant and which result into event having enough spaces, hence your group become as register participants though you selected on wait list.");
637 }
638 CRM_Core_Session::setStatus($status);
639 }
640
641 $this->_params[$addParticipantNum] = 'skip';
642 if (isset($this->_lineItem)) {
643 $this->_lineItem[$addParticipantNum] = 'skip';
644 $this->_lineItemParticipantsCount[$addParticipantNum] = 'skip';
645 }
646 }
647 else {
648
649 $config = CRM_Core_Config::singleton();
650 $params['currencyID'] = $config->defaultCurrency;
651
652 if ($this->_values['event']['is_monetary']) {
653
654 //added for discount
655 $discountId = CRM_Core_BAO_Discount::findSet($this->_eventId, 'civicrm_event');
656 $params['amount_level'] = $this->getAmountLevel($params, $discountId);
657 if (!empty($this->_values['discount'][$discountId])) {
658 $params['discount_id'] = $discountId;
659 $params['amount'] = $this->_values['discount'][$discountId][$params['amount']]['value'];
660 }
661 elseif (empty($params['priceSetId'])) {
662 $params['amount'] = $this->_values['fee'][$params['amount']]['value'];
663 }
664 else {
665 $lineItem = [];
666 CRM_Price_BAO_PriceSet::processAmount($this->_values['fee'], $params, $lineItem);
667
668 //build line item array..
669 //if requireApproval/waitlist is enabled we hide fees for primary participant
670 // (and not for additional participant which might be is a bug)
671 //lineItem are not correctly build for primary participant
672 //this results in redundancy since now lineItems for additional participant will be build against primary participantNum
673 //therefore lineItems must always be build against current participant No
674 $this->_lineItem[$addParticipantNum] = $lineItem;
675 }
676 }
677
678 if (array_key_exists('participant_role', $params)) {
679 $params['participant_role_id'] = $params['participant_role'];
680 }
681
682 if (empty($params['participant_role_id']) && $this->_values['event']['default_role_id']) {
683 $params['participant_role_id'] = $this->_values['event']['default_role_id'];
684 }
685
686 if (!empty($this->_params[0]['is_pay_later'])) {
687 $params['is_pay_later'] = 1;
688 }
689
690 //carry additional participant id, contact id if pre-registered.
691 if ($this->_allowConfirmation && $this->_additionalParticipantId) {
692 $params['contact_id'] = $this->_contactId;
693 $params['participant_id'] = $this->_additionalParticipantId;
694 }
695
696 //build the params array.
697 $this->_params[$addParticipantNum] = $params;
698 }
699
700 //finally set the params.
701 $this->set('params', $this->_params);
702 //set the line item.
703 if ($this->_lineItem) {
704 $this->set('lineItem', $this->_lineItem);
705 $this->set('lineItemParticipantsCount', $this->_lineItemParticipantsCount);
706 }
707
708 $participantNo = count($this->_params);
709 if ($button != 'skip') {
710 $statusMsg = ts('Registration information for participant %1 has been saved.', [1 => $participantNo]);
711 CRM_Core_Session::setStatus($statusMsg, ts('Registration Saved'), 'success');
712 }
713
714 // Check whether to process the registration now, calling processRegistration()
715 if (
716 // CRM-11182 - Optional confirmation screen
717 !$this->_values['event']['is_confirm_enabled']
718 && !$this->_values['event']['is_monetary']
719 && CRM_Utils_Array::value('additional_participants', $this->_params[0])
720 && $this->isLastParticipant()
721 ) {
722 $this->processRegistration($this->_params);
723 }
724 }
725
726 /**
727 * @param $additionalParticipant
728 *
729 * @return array
730 */
731 public static function &getPages($additionalParticipant) {
732 $details = [];
733 for ($i = 1; $i <= $additionalParticipant; $i++) {
734 $details["Participant_{$i}"] = [
735 'className' => 'CRM_Event_Form_Registration_AdditionalParticipant',
736 'title' => "Register Additional Participant {$i}",
737 ];
738 }
739 return $details;
740 }
741
742 /**
743 * Check whether call current participant is last one.
744 *
745 * @param bool $isButtonJs
746 *
747 * @return bool
748 * ture on success.
749 */
750 public function isLastParticipant($isButtonJs = FALSE) {
751 $participant = $isButtonJs ? $this->_params[0]['additional_participants'] : $this->_params[0]['additional_participants'] + 1;
752 if (count($this->_params) == $participant) {
753 return TRUE;
754 }
755 return FALSE;
756 }
757
758 }