f600b1a1817c91a5b5123caeba02f0ece1a7192d
[civicrm-core.git] / CRM / Event / Form / Registration.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.7 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2015 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
9 | |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
13 | |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
18 | |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
26 */
27
28 /**
29 *
30 *
31 * @package CRM
32 * @copyright CiviCRM LLC (c) 2004-2015
33 * $Id$
34 *
35 */
36
37 /**
38 * This class generates form components for processing Event
39 *
40 */
41 class CRM_Event_Form_Registration extends CRM_Core_Form {
42
43 /**
44 * How many locationBlocks should we display?
45 *
46 * @var int
47 * @const
48 */
49 const LOCATION_BLOCKS = 1;
50
51 /**
52 * The id of the event we are proceessing.
53 *
54 * @var int
55 */
56 public $_eventId;
57
58 /**
59 * The array of ids of all the participant we are proceessing.
60 *
61 * @var int
62 */
63 protected $_participantIDS = NULL;
64
65 /**
66 * The id of the participant we are proceessing.
67 *
68 * @var int
69 */
70 protected $_participantId;
71
72 /**
73 * Is participant able to walk registration wizard.
74 *
75 * @var Boolean
76 */
77 public $_allowConfirmation;
78
79 /**
80 * Is participant requires approval.
81 *
82 * @var Boolean
83 */
84 public $_requireApproval;
85
86 /**
87 * Is event configured for waitlist.
88 *
89 * @var Boolean
90 */
91 public $_allowWaitlist;
92
93 /**
94 * Store additional participant ids.
95 * when there are pre-registered.
96 *
97 * @var array
98 */
99 public $_additionalParticipantIds;
100
101 /**
102 * The mode that we are in.
103 *
104 * @var string
105 * @protect
106 */
107 public $_mode;
108
109 /**
110 * The values for the contribution db object.
111 *
112 * @var array
113 */
114 public $_values;
115
116 /**
117 * The paymentProcessor attributes for this page.
118 *
119 * @var array
120 */
121 public $_paymentProcessor;
122
123 /**
124 * The params submitted by the form and computed by the app.
125 *
126 * @var array
127 */
128 protected $_params;
129
130 /**
131 * The fields involved in this contribution page.
132 *
133 * @var array
134 */
135 public $_fields;
136
137 /**
138 * The billing location id for this contribiution page.
139 *
140 * @var int
141 */
142 public $_bltID;
143
144 /**
145 * Price Set ID, if the new price set method is used
146 *
147 * @var int
148 */
149 public $_priceSetId = NULL;
150
151 /**
152 * Array of fields for the price set.
153 *
154 * @var array
155 */
156 public $_priceSet;
157
158 public $_action;
159
160 public $_pcpId;
161
162 /* Is event already full.
163 *
164 * @var boolean
165 */
166
167 public $_isEventFull;
168
169 public $_lineItem;
170 public $_lineItemParticipantsCount;
171 public $_availableRegistrations;
172
173 public $_forcePayement;
174
175 public $_isBillingAddressRequiredForPayLater;
176
177 /**
178 * Set variables up before form is built.
179 */
180 public function preProcess() {
181 $this->_eventId = CRM_Utils_Request::retrieve('id', 'Positive', $this, TRUE);
182 $this->_action = CRM_Utils_Request::retrieve('action', 'String', $this, FALSE);
183
184 //CRM-4320
185 $this->_participantId = CRM_Utils_Request::retrieve('participantId', 'Positive', $this);
186
187 // current mode
188 $this->_mode = ($this->_action == 1024) ? 'test' : 'live';
189
190 $this->_values = $this->get('values');
191 $this->_fields = $this->get('fields');
192 $this->_bltID = $this->get('bltID');
193 $this->_paymentProcessor = $this->get('paymentProcessor');
194 $this->_priceSetId = $this->get('priceSetId');
195 $this->_priceSet = $this->get('priceSet');
196 $this->_lineItem = $this->get('lineItem');
197 $this->_isEventFull = $this->get('isEventFull');
198 $this->_lineItemParticipantsCount = $this->get('lineItemParticipants');
199 if (!is_array($this->_lineItem)) {
200 $this->_lineItem = array();
201 }
202 if (!is_array($this->_lineItemParticipantsCount)) {
203 $this->_lineItemParticipantsCount = array();
204 }
205 $this->_availableRegistrations = $this->get('availableRegistrations');
206 $this->_participantIDS = $this->get('participantIDs');
207
208 //check if participant allow to walk registration wizard.
209 $this->_allowConfirmation = $this->get('allowConfirmation');
210
211 // check for Approval
212 $this->_requireApproval = $this->get('requireApproval');
213
214 // check for waitlisting.
215 $this->_allowWaitlist = $this->get('allowWaitlist');
216
217 $this->_forcePayement = $this->get('forcePayement');
218
219 //get the additional participant ids.
220 $this->_additionalParticipantIds = $this->get('additionalParticipantIds');
221 $config = CRM_Core_Config::singleton();
222
223 if (!$this->_values) {
224 // create redirect URL to send folks back to event info page is registration not available
225 $infoUrl = CRM_Utils_System::url('civicrm/event/info', "reset=1&id={$this->_eventId}",
226 FALSE, NULL, FALSE, TRUE
227 );
228
229 // this is the first time we are hitting this, so check for permissions here
230 if (!CRM_Core_Permission::event(CRM_Core_Permission::EDIT, $this->_eventId, 'register for events')) {
231 CRM_Core_Error::statusBounce(ts('You do not have permission to register for this event'), $infoUrl);
232 }
233
234 // get all the values from the dao object
235 $this->_values = $this->_fields = array();
236 $this->_forcePayement = FALSE;
237
238 //retrieve event information
239 $params = array('id' => $this->_eventId);
240 CRM_Event_BAO_Event::retrieve($params, $this->_values['event']);
241 // check for is_monetary status
242 $isMonetary = CRM_Utils_Array::value('is_monetary', $this->_values['event']);
243 // check for ability to add contributions of type
244 if ($isMonetary
245 && CRM_Financial_BAO_FinancialType::isACLFinancialTypeStatus()
246 && !CRM_Core_Permission::check('add contributions of type ' . CRM_Contribute_PseudoConstant::financialType($this->_values['event']['financial_type_id']))
247 ) {
248 CRM_Core_Error::fatal(ts('You do not have permission to access this page.'));
249 }
250
251 $this->checkValidEvent($infoUrl);
252 // get the participant values, CRM-4320
253 $this->_allowConfirmation = FALSE;
254 if ($this->_participantId) {
255 $this->processFirstParticipant($this->_participantId);
256 }
257 //check for additional participants.
258 if ($this->_allowConfirmation && $this->_values['event']['is_multiple_registrations']) {
259 $additionalParticipantIds = CRM_Event_BAO_Participant::getAdditionalParticipantIds($this->_participantId);
260 $cnt = 1;
261 foreach ($additionalParticipantIds as $additionalParticipantId) {
262 $this->_additionalParticipantIds[$cnt] = $additionalParticipantId;
263 $cnt++;
264 }
265 $this->set('additionalParticipantIds', $this->_additionalParticipantIds);
266 }
267
268 $eventFull = CRM_Event_BAO_Participant::eventFull($this->_eventId, FALSE,
269 CRM_Utils_Array::value('has_waitlist', $this->_values['event'])
270 );
271
272 $this->_allowWaitlist = $this->_isEventFull = FALSE;
273 if ($eventFull && !$this->_allowConfirmation) {
274 $this->_isEventFull = TRUE;
275 //lets redirecting to info only when to waiting list.
276 $this->_allowWaitlist = CRM_Utils_Array::value('has_waitlist', $this->_values['event']);
277 if (!$this->_allowWaitlist) {
278 CRM_Utils_System::redirect($infoUrl);
279 }
280 }
281 $this->set('isEventFull', $this->_isEventFull);
282 $this->set('allowWaitlist', $this->_allowWaitlist);
283
284 //check for require requires approval.
285 $this->_requireApproval = FALSE;
286 if (!empty($this->_values['event']['requires_approval']) && !$this->_allowConfirmation) {
287 $this->_requireApproval = TRUE;
288 }
289 $this->set('requireApproval', $this->_requireApproval);
290
291 if (isset($this->_values['event']['default_role_id'])) {
292 $participant_role = CRM_Core_OptionGroup::values('participant_role');
293 $this->_values['event']['participant_role'] = $participant_role["{$this->_values['event']['default_role_id']}"];
294 }
295 $isPayLater = CRM_Core_DAO::getFieldValue('CRM_Event_DAO_Event', $this->_eventId, 'is_pay_later');
296 //check for various combinations for paylater, payment
297 //process with paid event.
298 if ($isMonetary && (!$isPayLater || !empty($this->_values['event']['payment_processor']))) {
299 $this->_paymentProcessorIDs = explode(CRM_Core_DAO::VALUE_SEPARATOR, CRM_Utils_Array::value('payment_processor',
300 $this->_values['event']
301 ));
302 $this->assignPaymentProcessor();
303
304 }
305 //init event fee.
306 self::initEventFee($this, $this->_eventId);
307
308 // get the profile ids
309 $ufJoinParams = array(
310 'entity_table' => 'civicrm_event',
311 // CRM-4377: CiviEvent for the main participant, CiviEvent_Additional for additional participants
312 'module' => 'CiviEvent',
313 'entity_id' => $this->_eventId,
314 );
315 list($this->_values['custom_pre_id'],
316 $this->_values['custom_post_id']
317 ) = CRM_Core_BAO_UFJoin::getUFGroupIds($ufJoinParams);
318
319 // set profiles for additional participants
320 if ($this->_values['event']['is_multiple_registrations']) {
321 // CRM-4377: CiviEvent for the main participant, CiviEvent_Additional for additional participants
322 $ufJoinParams['module'] = 'CiviEvent_Additional';
323
324 list($this->_values['additional_custom_pre_id'],
325 $this->_values['additional_custom_post_id'], $preActive, $postActive
326 ) = CRM_Core_BAO_UFJoin::getUFGroupIds($ufJoinParams);
327
328 // CRM-4377: we need to maintain backward compatibility, hence if there is profile for main contact
329 // set same profile for additional contacts.
330 if ($this->_values['custom_pre_id'] && !$this->_values['additional_custom_pre_id']) {
331 $this->_values['additional_custom_pre_id'] = $this->_values['custom_pre_id'];
332 }
333
334 if ($this->_values['custom_post_id'] && !$this->_values['additional_custom_post_id']) {
335 $this->_values['additional_custom_post_id'] = $this->_values['custom_post_id'];
336 }
337 // now check for no profile condition, in that case is_active = 0
338 if (isset($preActive) && !$preActive) {
339 unset($this->_values['additional_custom_pre_id']);
340 }
341 if (isset($postActive) && !$postActive) {
342 unset($this->_values['additional_custom_post_id']);
343 }
344 }
345
346 $this->assignBillingType();
347
348 if ($this->_values['event']['is_monetary']) {
349 CRM_Core_Payment_Form::setPaymentFieldsByProcessor($this, $this->_paymentProcessor);
350 }
351 $params = array('entity_id' => $this->_eventId, 'entity_table' => 'civicrm_event');
352 $this->_values['location'] = CRM_Core_BAO_Location::getValues($params, TRUE);
353
354 $this->set('values', $this->_values);
355 $this->set('fields', $this->_fields);
356
357 $this->_availableRegistrations
358 = CRM_Event_BAO_Participant::eventFull(
359 $this->_values['event']['id'], TRUE,
360 CRM_Utils_Array::value('has_waitlist', $this->_values['event'])
361 );
362 $this->set('availableRegistrations', $this->_availableRegistrations);
363 }
364 $this->assign_by_ref('paymentProcessor', $this->_paymentProcessor);
365
366 // check if this is a paypal auto return and redirect accordingly
367 if (CRM_Core_Payment::paypalRedirect($this->_paymentProcessor)) {
368 $url = CRM_Utils_System::url('civicrm/event/register',
369 "_qf_ThankYou_display=1&qfKey={$this->controller->_key}"
370 );
371 CRM_Utils_System::redirect($url);
372 }
373 // The concept of contributeMode is deprecated.
374 $this->_contributeMode = $this->get('contributeMode');
375 $this->assign('contributeMode', $this->_contributeMode);
376
377 // setting CMS page title
378 CRM_Utils_System::setTitle($this->_values['event']['title']);
379 $this->assign('title', $this->_values['event']['title']);
380
381 $this->assign('paidEvent', $this->_values['event']['is_monetary']);
382
383 // we do not want to display recently viewed items on Registration pages
384 $this->assign('displayRecent', FALSE);
385 // Registration page values are cleared from session, so can't use normal Printer Friendly view.
386 // Use Browser Print instead.
387 $this->assign('browserPrint', TRUE);
388
389 $isShowLocation = CRM_Utils_Array::value('is_show_location', $this->_values['event']);
390 $this->assign('isShowLocation', $isShowLocation);
391 // Handle PCP
392 $pcpId = CRM_Utils_Request::retrieve('pcpId', 'Positive', $this);
393 if ($pcpId) {
394 $pcp = CRM_PCP_BAO_PCP::handlePcp($pcpId, 'event', $this->_values['event']);
395 $this->_pcpId = $pcp['pcpId'];
396 $this->_values['event']['intro_text'] = CRM_Utils_Array::value('intro_text', $pcp['pcpInfo']);
397 }
398
399 // assign all event properties so wizard templates can display event info.
400 $this->assign('event', $this->_values['event']);
401 $this->assign('location', $this->_values['location']);
402 $this->assign('bltID', $this->_bltID);
403 $isShowLocation = CRM_Utils_Array::value('is_show_location', $this->_values['event']);
404 $this->assign('isShowLocation', $isShowLocation);
405 //CRM-6907
406 $config->defaultCurrency = CRM_Utils_Array::value('currency', $this->_values['event'],
407 $config->defaultCurrency
408 );
409
410 //lets allow user to override campaign.
411 $campID = CRM_Utils_Request::retrieve('campID', 'Positive', $this);
412 if ($campID && CRM_Core_DAO::getFieldValue('CRM_Campaign_DAO_Campaign', $campID)) {
413 $this->_values['event']['campaign_id'] = $campID;
414 }
415
416 // Set the same value for is_billing_required as contribution page so code can be shared.
417 $this->_values['is_billing_required'] = CRM_Utils_Array::value('is_billing_required', $this->_values['event']);
418 // check if billing block is required for pay later
419 // note that I have started removing the use of isBillingAddressRequiredForPayLater in favour of letting
420 // the CRM_Core_Payment_Manual class handle it - but there are ~300 references to it in the code base so only
421 // removing in very limited cases.
422 if (CRM_Utils_Array::value('is_pay_later', $this->_values['event'])) {
423 $this->_isBillingAddressRequiredForPayLater = CRM_Utils_Array::value('is_billing_required', $this->_values['event']);
424 $this->assign('isBillingAddressRequiredForPayLater', $this->_isBillingAddressRequiredForPayLater);
425 }
426 }
427
428 /**
429 * Assign the minimal set of variables to the template.
430 *
431 * @return void
432 */
433 public function assignToTemplate() {
434 //process only primary participant params
435 $this->_params = $this->get('params');
436 if (isset($this->_params[0])) {
437 $params = $this->_params[0];
438 }
439 $name = '';
440 if (!empty($params['billing_first_name'])) {
441 $name = $params['billing_first_name'];
442 }
443
444 if (!empty($params['billing_middle_name'])) {
445 $name .= " {$params['billing_middle_name']}";
446 }
447
448 if (!empty($params['billing_last_name'])) {
449 $name .= " {$params['billing_last_name']}";
450 }
451 $this->assign('billingName', $name);
452 $this->set('name', $name);
453
454 $vars = array(
455 'amount',
456 'currencyID',
457 'credit_card_type',
458 'trxn_id',
459 'amount_level',
460 'receive_date',
461 );
462
463 foreach ($vars as $v) {
464 if (!empty($params[$v])) {
465 if ($v == 'receive_date') {
466 $this->assign($v, CRM_Utils_Date::mysqlToIso($params[$v]));
467 }
468 else {
469 $this->assign($v, $params[$v]);
470 }
471 }
472 elseif (CRM_Utils_Array::value('amount', $params) == 0) {
473 $this->assign($v, CRM_Utils_Array::value($v, $params));
474 }
475 }
476
477 // assign the address formatted up for display
478 $addressParts = array(
479 "street_address-{$this->_bltID}",
480 "city-{$this->_bltID}",
481 "postal_code-{$this->_bltID}",
482 "state_province-{$this->_bltID}",
483 "country-{$this->_bltID}",
484 );
485 $addressFields = array();
486 foreach ($addressParts as $part) {
487 list($n, $id) = explode('-', $part);
488 if (isset($params['billing_' . $part])) {
489 $addressFields[$n] = CRM_Utils_Array::value('billing_' . $part, $params);
490 }
491 }
492
493 $this->assign('address', CRM_Utils_Address::format($addressFields));
494
495 // The concept of contributeMode is deprecated.
496 if ($this->_contributeMode == 'direct' && empty($params['is_pay_later'])) {
497 $date = CRM_Utils_Date::format(CRM_Utils_Array::value('credit_card_exp_date', $params));
498 $date = CRM_Utils_Date::mysqlToIso($date);
499 $this->assign('credit_card_exp_date', $date);
500 $this->assign('credit_card_number',
501 CRM_Utils_System::mungeCreditCard(CRM_Utils_Array::value('credit_card_number', $params))
502 );
503 }
504
505 // get the email that the confirmation would have been sent to
506 $session = CRM_Core_Session::singleton();
507
508 // assign is_email_confirm to templates
509 if (isset($this->_values['event']['is_email_confirm'])) {
510 $this->assign('is_email_confirm', $this->_values['event']['is_email_confirm']);
511 }
512
513 // assign pay later stuff
514 $params['is_pay_later'] = CRM_Utils_Array::value('is_pay_later', $params, FALSE);
515 $this->assign('is_pay_later', $params['is_pay_later']);
516 if ($params['is_pay_later']) {
517 $this->assign('pay_later_text', $this->_values['event']['pay_later_text']);
518 $this->assign('pay_later_receipt', $this->_values['event']['pay_later_receipt']);
519 }
520
521 // also assign all participantIDs to the template
522 // useful in generating confirmation numbers if needed
523 $this->assign('participantIDs',
524 $this->_participantIDS
525 );
526 }
527
528 /**
529 * Add the custom fields.
530 *
531 * @param int $id
532 * @param string $name
533 * @param bool $viewOnly
534 *
535 * @return void
536 */
537 public function buildCustom($id, $name, $viewOnly = FALSE) {
538 if ($id) {
539 $button = substr($this->controller->getButtonName(), -4);
540 $cid = CRM_Utils_Request::retrieve('cid', 'Positive', $this);
541 $session = CRM_Core_Session::singleton();
542 $contactID = $session->get('userID');
543
544 // we don't allow conflicting fields to be
545 // configured via profile
546 $fieldsToIgnore = array(
547 'participant_fee_amount' => 1,
548 'participant_fee_level' => 1,
549 );
550 if ($contactID) {
551 //FIX CRM-9653
552 if (is_array($id)) {
553 $fields = array();
554 foreach ($id as $profileID) {
555 $field = CRM_Core_BAO_UFGroup::getFields($profileID, FALSE, CRM_Core_Action::ADD,
556 NULL, NULL, FALSE, NULL,
557 FALSE, NULL, CRM_Core_Permission::CREATE,
558 'field_name', TRUE
559 );
560 $fields = array_merge($fields, $field);
561 }
562 }
563 else {
564 if (CRM_Core_BAO_UFGroup::filterUFGroups($id, $contactID)) {
565 $fields = CRM_Core_BAO_UFGroup::getFields($id, FALSE, CRM_Core_Action::ADD,
566 NULL, NULL, FALSE, NULL,
567 FALSE, NULL, CRM_Core_Permission::CREATE,
568 'field_name', TRUE
569 );
570 }
571 }
572 }
573 else {
574 $fields = CRM_Core_BAO_UFGroup::getFields($id, FALSE, CRM_Core_Action::ADD,
575 NULL, NULL, FALSE, NULL,
576 FALSE, NULL, CRM_Core_Permission::CREATE,
577 'field_name', TRUE
578 );
579 }
580
581 if (array_intersect_key($fields, $fieldsToIgnore)) {
582 $fields = array_diff_key($fields, $fieldsToIgnore);
583 CRM_Core_Session::setStatus(ts('Some of the profile fields cannot be configured for this page.'));
584 }
585 $addCaptcha = FALSE;
586
587 if (!empty($this->_fields)) {
588 $fields = @array_diff_assoc($fields, $this->_fields);
589 }
590
591 if (empty($this->_params[0]['additional_participants']) &&
592 is_null($cid)
593 ) {
594 CRM_Core_BAO_Address::checkContactSharedAddressFields($fields, $contactID);
595 }
596 $this->assign($name, $fields);
597 if (is_array($fields)) {
598 foreach ($fields as $key => $field) {
599 if ($viewOnly &&
600 isset($field['data_type']) &&
601 $field['data_type'] == 'File' || ($viewOnly && $field['name'] == 'image_URL')
602 ) {
603 // ignore file upload fields
604 continue;
605 }
606 //make the field optional if primary participant
607 //have been skip the additional participant.
608 if ($button == 'skip') {
609 $field['is_required'] = FALSE;
610 }
611 // CRM-11316 Is ReCAPTCHA enabled for this profile AND is this an anonymous visitor
612 elseif ($field['add_captcha'] && !$contactID) {
613 // only add captcha for first page
614 $addCaptcha = TRUE;
615 }
616 list($prefixName, $index) = CRM_Utils_System::explode('-', $key, 2);
617 CRM_Core_BAO_UFGroup::buildProfile($this, $field, CRM_Profile_Form::MODE_CREATE, $contactID, TRUE);
618
619 $this->_fields[$key] = $field;
620 }
621 }
622
623 if ($addCaptcha && !$viewOnly) {
624 $captcha = CRM_Utils_ReCAPTCHA::singleton();
625 $captcha->add($this);
626 $this->assign('isCaptcha', TRUE);
627 }
628 }
629 }
630
631 /**
632 * @param CRM_Core_Form $form
633 * @param int $eventID
634 *
635 * @throws Exception
636 */
637 public static function initEventFee(&$form, $eventID) {
638 // get price info
639
640 // retrive all active price set fields.
641 $discountId = CRM_Core_BAO_Discount::findSet($eventID, 'civicrm_event');
642 if (property_exists($form, '_discountId') && $form->_discountId) {
643 $discountId = $form->_discountId;
644 }
645
646 //CRM-16456 get all price field including expired one.
647 $getAllPriceField = TRUE;
648 $className = CRM_Utils_System::getClassName($form);
649 if ($className == 'CRM_Event_Form_ParticipantFeeSelection' && $form->_action == CRM_Core_Action::UPDATE) {
650 $getAllPriceField = FALSE;
651 }
652
653 if ($discountId) {
654 $priceSetId = CRM_Core_DAO::getFieldValue('CRM_Core_BAO_Discount', $discountId, 'price_set_id');
655 $price = CRM_Price_BAO_PriceSet::initSet($form, $eventID, 'civicrm_event', $getAllPriceField, $priceSetId);
656 }
657 else {
658 $price = CRM_Price_BAO_PriceSet::initSet($form, $eventID, 'civicrm_event', $getAllPriceField);
659 }
660
661 if (property_exists($form, '_context') && ($form->_context == 'standalone'
662 || $form->_context == 'participant')
663 ) {
664 $discountedEvent = CRM_Core_BAO_Discount::getOptionGroup($eventID, 'civicrm_event');
665 if (is_array($discountedEvent)) {
666 foreach ($discountedEvent as $key => $priceSetId) {
667 $priceSet = CRM_Price_BAO_PriceSet::getSetDetail($priceSetId);
668 $priceSet = CRM_Utils_Array::value($priceSetId, $priceSet);
669 $form->_values['discount'][$key] = CRM_Utils_Array::value('fields', $priceSet);
670 $fieldID = key($form->_values['discount'][$key]);
671 $form->_values['discount'][$key][$fieldID]['name'] = CRM_Core_DAO::getFieldValue(
672 'CRM_Price_DAO_PriceSet',
673 $priceSetId,
674 'title'
675 );
676 }
677 }
678 }
679 $eventFee = CRM_Utils_Array::value('fee', $form->_values);
680 if (!is_array($eventFee) || empty($eventFee)) {
681 $form->_values['fee'] = array();
682 }
683
684 //fix for non-upgraded price sets.CRM-4256.
685 if (isset($form->_isPaidEvent)) {
686 $isPaidEvent = $form->_isPaidEvent;
687 }
688 else {
689 $isPaidEvent = CRM_Utils_Array::value('is_monetary', $form->_values['event']);
690 }
691 if (CRM_Financial_BAO_FinancialType::isACLFinancialTypeStatus()
692 && !empty($form->_values['fee'])
693 ) {
694 foreach ($form->_values['fee'] as $k => $fees) {
695 foreach ($fees['options'] as $options) {
696 if (!CRM_Core_Permission::check('add contributions of type ' . CRM_Contribute_PseudoConstant::financialType($options['financial_type_id']))) {
697 unset($form->_values['fee'][$k]);
698 }
699 }
700 }
701 }
702 if ($isPaidEvent && empty($form->_values['fee'])) {
703 if (CRM_Utils_System::getClassName($form) != 'CRM_Event_Form_Participant') {
704 CRM_Core_Error::fatal(ts('No Fee Level(s) or Price Set is configured for this event.<br />Click <a href=\'%1\'>CiviEvent >> Manage Event >> Configure >> Event Fees</a> to configure the Fee Level(s) or Price Set for this event.', array(1 => CRM_Utils_System::url('civicrm/event/manage/fee', 'reset=1&action=update&id=' . $form->_eventId))));
705 }
706 }
707 }
708
709 /**
710 * Handle process after the confirmation of payment by User.
711 *
712 * @param int $contactID
713 * @param null $contribution
714 * @param null $payment
715 *
716 * @return void
717 */
718 public function confirmPostProcess($contactID = NULL, $contribution = NULL, $payment = NULL) {
719 // add/update contact information
720 $fields = array();
721 unset($this->_params['note']);
722
723 //to avoid conflict overwrite $this->_params
724 $this->_params = $this->get('value');
725
726 //get the amount of primary participant
727 if (!empty($this->_params['is_primary'])) {
728 $this->_params['fee_amount'] = $this->get('primaryParticipantAmount');
729 }
730
731 // add participant record
732 $participant = CRM_Event_Form_Registration::addParticipant($this, $contactID);
733 $this->_participantIDS[] = $participant->id;
734
735 //setting register_by_id field and primaryContactId
736 if (!empty($this->_params['is_primary'])) {
737 $this->set('registerByID', $participant->id);
738 $this->set('primaryContactId', $contactID);
739
740 // CRM-10032
741 $this->processFirstParticipant($participant->id);
742 }
743
744 CRM_Core_BAO_CustomValueTable::postProcess($this->_params,
745 'civicrm_participant',
746 $participant->id,
747 'Participant'
748 );
749
750 $createPayment = (CRM_Utils_Array::value('amount', $this->_params, 0) != 0) ? TRUE : FALSE;
751
752 // force to create zero amount payment, CRM-5095
753 // we know the amout is zero since createPayment is false
754 if (!$createPayment &&
755 (isset($contribution) && $contribution->id) &&
756 $this->_priceSetId &&
757 $this->_lineItem
758 ) {
759 $createPayment = TRUE;
760 }
761
762 if ($createPayment && $this->_values['event']['is_monetary'] && !empty($this->_params['contributionID'])) {
763 $paymentParams = array(
764 'participant_id' => $participant->id,
765 'contribution_id' => $contribution->id,
766 );
767 $ids = array();
768 $paymentPartcipant = CRM_Event_BAO_ParticipantPayment::create($paymentParams, $ids);
769 }
770
771 //set only primary participant's params for transfer checkout.
772 // The concept of contributeMode is deprecated.
773 if (($this->_contributeMode == 'checkout' || $this->_contributeMode == 'notify') && !empty($this->_params['is_primary'])) {
774 $this->_params['participantID'] = $participant->id;
775 $this->set('primaryParticipant', $this->_params);
776 }
777
778 $this->assign('action', $this->_action);
779
780 // create CMS user
781 if (!empty($this->_params['cms_create_account'])) {
782 $this->_params['contactID'] = $contactID;
783
784 if (array_key_exists('email-5', $this->_params)) {
785 $mail = 'email-5';
786 }
787 else {
788 foreach ($this->_params as $name => $dontCare) {
789 if (substr($name, 0, 5) == 'email') {
790 $mail = $name;
791 break;
792 }
793 }
794 }
795
796 // we should use primary email for
797 // 1. free event registration.
798 // 2. pay later participant.
799 // 3. waiting list participant.
800 // 4. require approval participant.
801 if (!empty($this->_params['is_pay_later']) ||
802 $this->_allowWaitlist || $this->_requireApproval || empty($this->_values['event']['is_monetary'])
803 ) {
804 $mail = 'email-Primary';
805 }
806
807 if (!CRM_Core_BAO_CMSUser::create($this->_params, $mail)) {
808 CRM_Core_Error::statusBounce(ts('Your profile is not saved and Account is not created.'));
809 }
810 }
811 }
812
813 /**
814 * Process the participant.
815 *
816 * @param CRM_Core_Form $form
817 * @param int $contactID
818 * @return \CRM_Event_BAO_Participant
819 */
820 public static function addParticipant(&$form, $contactID) {
821 if (empty($form->_params)) {
822 return NULL;
823 }
824 $params = $form->_params;
825 $transaction = new CRM_Core_Transaction();
826
827 $groupName = 'participant_role';
828 $query = "
829 SELECT v.label as label ,v.value as value
830 FROM civicrm_option_value v,
831 civicrm_option_group g
832 WHERE v.option_group_id = g.id
833 AND g.name = %1
834 AND v.is_active = 1
835 AND g.is_active = 1
836 ";
837 $p = array(1 => array($groupName, 'String'));
838
839 $dao = CRM_Core_DAO::executeQuery($query, $p);
840 if ($dao->fetch()) {
841 $roleID = $dao->value;
842 }
843
844 // handle register date CRM-4320
845 $registerDate = NULL;
846 if (!empty($form->_allowConfirmation) && $form->_participantId) {
847 $registerDate = $params['participant_register_date'];
848 }
849 elseif (!empty($params['participant_register_date']) &&
850 is_array($params['participant_register_date']) &&
851 !empty($params['participant_register_date'])
852 ) {
853 $registerDate = CRM_Utils_Date::format($params['participant_register_date']);
854 }
855
856 $participantFields = CRM_Event_DAO_Participant::fields();
857 $participantParams = array(
858 'id' => CRM_Utils_Array::value('participant_id', $params),
859 'contact_id' => $contactID,
860 'event_id' => $form->_eventId ? $form->_eventId : $params['event_id'],
861 'status_id' => CRM_Utils_Array::value('participant_status',
862 $params, 1
863 ),
864 'role_id' => CRM_Utils_Array::value('participant_role_id',
865 $params, $roleID
866 ),
867 'register_date' => ($registerDate) ? $registerDate : date('YmdHis'),
868 'source' => CRM_Utils_String::ellipsify(
869 isset($params['participant_source']) ? CRM_Utils_Array::value('participant_source', $params) : CRM_Utils_Array::value('description', $params),
870 $participantFields['participant_source']['maxlength']
871 ),
872 'fee_level' => CRM_Utils_Array::value('amount_level', $params),
873 'is_pay_later' => CRM_Utils_Array::value('is_pay_later', $params, 0),
874 'fee_amount' => CRM_Utils_Array::value('fee_amount', $params),
875 'registered_by_id' => CRM_Utils_Array::value('registered_by_id', $params),
876 'discount_id' => CRM_Utils_Array::value('discount_id', $params),
877 'fee_currency' => CRM_Utils_Array::value('currencyID', $params),
878 'campaign_id' => CRM_Utils_Array::value('campaign_id', $params),
879 );
880
881 if ($form->_action & CRM_Core_Action::PREVIEW || CRM_Utils_Array::value('mode', $params) == 'test') {
882 $participantParams['is_test'] = 1;
883 }
884 else {
885 $participantParams['is_test'] = 0;
886 }
887
888 if (!empty($form->_params['note'])) {
889 $participantParams['note'] = $form->_params['note'];
890 }
891 elseif (!empty($form->_params['participant_note'])) {
892 $participantParams['note'] = $form->_params['participant_note'];
893 }
894
895 // reuse id if one already exists for this one (can happen
896 // with back button being hit etc)
897 if (!$participantParams['id'] && !empty($params['contributionID'])) {
898 $pID = CRM_Core_DAO::getFieldValue('CRM_Event_DAO_ParticipantPayment',
899 $params['contributionID'],
900 'participant_id',
901 'contribution_id'
902 );
903 $participantParams['id'] = $pID;
904 }
905 $participantParams['discount_id'] = CRM_Core_BAO_Discount::findSet($form->_eventId, 'civicrm_event');
906
907 if (!$participantParams['discount_id']) {
908 $participantParams['discount_id'] = "null";
909 }
910
911 $participant = CRM_Event_BAO_Participant::create($participantParams);
912
913 $transaction->commit();
914
915 return $participant;
916 }
917
918 /* Calculate the total participant count as per params.
919 *
920 * @param array $params
921 * User params.
922 *
923 * @return $totalCount total participant count.
924 */
925 /**
926 * @param CRM_Core_Form $form
927 * @param array $params
928 * @param bool $skipCurrent
929 *
930 * @return int|string
931 */
932 public static function getParticipantCount(&$form, $params, $skipCurrent = FALSE) {
933 $totalCount = 0;
934 if (!is_array($params) || empty($params)) {
935 return $totalCount;
936 }
937
938 $priceSetId = $form->get('priceSetId');
939 $addParticipantNum = substr($form->_name, 12);
940 $priceSetFields = $priceSetDetails = array();
941 $hasPriceFieldsCount = FALSE;
942 if ($priceSetId) {
943 $priceSetDetails = $form->get('priceSet');
944 if (isset($priceSetDetails['optionsCountTotal'])
945 && $priceSetDetails['optionsCountTotal']
946 ) {
947 $hasPriceFieldsCount = TRUE;
948 $priceSetFields = $priceSetDetails['optionsCountDetails']['fields'];
949 }
950 }
951
952 $singleFormParams = FALSE;
953 foreach ($params as $key => $val) {
954 if (!is_numeric($key)) {
955 $singleFormParams = TRUE;
956 break;
957 }
958 }
959
960 //first format the params.
961 if ($singleFormParams) {
962 $params = self::formatPriceSetParams($form, $params);
963 $params = array($params);
964 }
965
966 foreach ($params as $key => $values) {
967 if (!is_numeric($key) ||
968 $values == 'skip' ||
969 ($skipCurrent && ($addParticipantNum == $key))
970 ) {
971 continue;
972 }
973 $count = 1;
974
975 $usedCache = FALSE;
976 $cacheCount = CRM_Utils_Array::value($key, $form->_lineItemParticipantsCount);
977 if ($cacheCount && is_numeric($cacheCount)) {
978 $count = $cacheCount;
979 $usedCache = TRUE;
980 }
981
982 if (!$usedCache && $hasPriceFieldsCount) {
983 $count = 0;
984 foreach ($values as $valKey => $value) {
985 if (strpos($valKey, 'price_') === FALSE) {
986 continue;
987 }
988 $priceFieldId = substr($valKey, 6);
989 if (!$priceFieldId ||
990 !is_array($value) ||
991 !array_key_exists($priceFieldId, $priceSetFields)
992 ) {
993 continue;
994 }
995 foreach ($value as $optId => $optVal) {
996 $currentCount = $priceSetFields[$priceFieldId]['options'][$optId] * $optVal;
997 if ($currentCount) {
998 $count += $currentCount;
999 }
1000 }
1001 }
1002 if (!$count) {
1003 $count = 1;
1004 }
1005 }
1006 $totalCount += $count;
1007 }
1008 if (!$totalCount) {
1009 $totalCount = 1;
1010 }
1011
1012 return $totalCount;
1013 }
1014
1015 /* Format user submitted price set params.
1016 * Convert price set each param as an array.
1017 *
1018 * @param array $params
1019 * An array of user submitted params.
1020 *
1021 *
1022 * @return array
1023 * , formatted price set params.
1024 */
1025 /**
1026 * @param CRM_Core_Form $form
1027 * @param array $params
1028 *
1029 * @return mixed
1030 */
1031 public static function formatPriceSetParams(&$form, $params) {
1032 if (!is_array($params) || empty($params)) {
1033 return $params;
1034 }
1035
1036 $priceSetId = $form->get('priceSetId');
1037 if (!$priceSetId) {
1038 return $params;
1039 }
1040 $priceSetDetails = $form->get('priceSet');
1041
1042 foreach ($params as $key => & $value) {
1043 $vals = array();
1044 if (strpos($key, 'price_') !== FALSE) {
1045 $fieldId = substr($key, 6);
1046 if (!array_key_exists($fieldId, $priceSetDetails['fields']) ||
1047 is_array($value) ||
1048 !$value
1049 ) {
1050 continue;
1051 }
1052 $field = $priceSetDetails['fields'][$fieldId];
1053 if ($field['html_type'] == 'Text') {
1054 $fieldOption = current($field['options']);
1055 $value = array($fieldOption['id'] => $value);
1056 }
1057 else {
1058 $value = array($value => TRUE);
1059 }
1060 }
1061 }
1062
1063 return $params;
1064 }
1065
1066 /* Calculate total count for each price set options.
1067 * those are currently selected by user.
1068 *
1069 * @param $form
1070 * Form object.
1071 *
1072 *
1073 * @return array
1074 * , array of each option w/ count total.
1075 */
1076 /**
1077 * @param $form
1078 *
1079 * @return array
1080 */
1081 public static function getPriceSetOptionCount(&$form) {
1082 $params = $form->get('params');
1083 $priceSet = $form->get('priceSet');
1084 $priceSetId = $form->get('priceSetId');
1085
1086 $optionsCount = array();
1087 if (!$priceSetId ||
1088 !is_array($priceSet) ||
1089 empty($priceSet) ||
1090 !is_array($params) ||
1091 empty($params)
1092 ) {
1093 return $optionsCount;
1094 }
1095
1096 $priceSetFields = $priceMaxFieldDetails = array();
1097 if (!empty($priceSet['optionsCountTotal'])) {
1098 $priceSetFields = $priceSet['optionsCountDetails']['fields'];
1099 }
1100
1101 if (!empty($priceSet['optionsMaxValueTotal'])) {
1102 $priceMaxFieldDetails = $priceSet['optionsMaxValueDetails']['fields'];
1103 }
1104
1105 $addParticipantNum = substr($form->_name, 12);
1106 foreach ($params as $pCnt => $values) {
1107 if ($values == 'skip' ||
1108 $pCnt === $addParticipantNum
1109 ) {
1110 continue;
1111 }
1112
1113 foreach ($values as $valKey => $value) {
1114 if (strpos($valKey, 'price_') === FALSE) {
1115 continue;
1116 }
1117
1118 $priceFieldId = substr($valKey, 6);
1119 if (!$priceFieldId ||
1120 !is_array($value) ||
1121 !(array_key_exists($priceFieldId, $priceSetFields) || array_key_exists($priceFieldId, $priceMaxFieldDetails))
1122 ) {
1123 continue;
1124 }
1125
1126 foreach ($value as $optId => $optVal) {
1127 if (CRM_Utils_Array::value('html_type', $priceSet['fields'][$priceFieldId]) == 'Text') {
1128 $currentCount = $optVal;
1129 }
1130 else {
1131 $currentCount = 1;
1132 }
1133
1134 if (isset($priceSetFields[$priceFieldId]) && isset($priceSetFields[$priceFieldId]['options'][$optId])) {
1135 $currentCount = $priceSetFields[$priceFieldId]['options'][$optId] * $optVal;
1136 }
1137
1138 $optionsCount[$optId] = $currentCount + CRM_Utils_Array::value($optId, $optionsCount, 0);
1139 }
1140 }
1141 }
1142
1143 return $optionsCount;
1144 }
1145
1146 /**
1147 * @param string $suffix
1148 *
1149 * @return null|string
1150 */
1151 public function checkTemplateFileExists($suffix = '') {
1152 if ($this->_eventId) {
1153 $templateName = $this->_name;
1154 if (substr($templateName, 0, 12) == 'Participant_') {
1155 $templateName = 'AdditionalParticipant';
1156 }
1157
1158 $templateFile = "CRM/Event/Form/Registration/{$this->_eventId}/{$templateName}.{$suffix}tpl";
1159 $template = CRM_Core_Form::getTemplate();
1160 if ($template->template_exists($templateFile)) {
1161 return $templateFile;
1162 }
1163 }
1164 return NULL;
1165 }
1166
1167 /**
1168 * @return null|string
1169 */
1170 public function getTemplateFileName() {
1171 $fileName = $this->checkTemplateFileExists();
1172 return $fileName ? $fileName : parent::getTemplateFileName();
1173 }
1174
1175 /**
1176 * @return null|string
1177 */
1178 public function overrideExtraTemplateFileName() {
1179 $fileName = $this->checkTemplateFileExists('extra.');
1180 return $fileName ? $fileName : parent::overrideExtraTemplateFileName();
1181 }
1182
1183 /**
1184 * Reset values for all options those are full.
1185 *
1186 * @param array $optionFullIds
1187 * @param $form
1188 */
1189 public static function resetElementValue($optionFullIds = array(), &$form) {
1190 if (!is_array($optionFullIds) ||
1191 empty($optionFullIds) ||
1192 !$form->isSubmitted()
1193 ) {
1194 return;
1195 }
1196
1197 foreach ($optionFullIds as $fldId => $optIds) {
1198 $name = "price_$fldId";
1199 if (!$form->elementExists($name)) {
1200 continue;
1201 }
1202
1203 $element = $form->getElement($name);
1204 $eleType = $element->getType();
1205
1206 $resetSubmitted = FALSE;
1207 switch ($eleType) {
1208 case 'text':
1209 if ($element->getValue() && $element->isFrozen()) {
1210 $label = "{$element->getLabel()}<tt>(x)</tt>";
1211 $element->setLabel($label);
1212 $element->setPersistantFreeze();
1213 $resetSubmitted = TRUE;
1214 }
1215 break;
1216
1217 case 'group':
1218 if (is_array($element->_elements)) {
1219 foreach ($element->_elements as $child) {
1220 $childType = $child->getType();
1221 $methodName = 'getName';
1222 if ($childType) {
1223 $methodName = 'getValue';
1224 }
1225 if (in_array($child->{$methodName}(), $optIds) && $child->isFrozen()) {
1226 $resetSubmitted = TRUE;
1227 $child->setPersistantFreeze();
1228 }
1229 }
1230 }
1231 break;
1232
1233 case 'select':
1234 $value = $element->getValue();
1235 if (in_array($value[0], $optIds)) {
1236 foreach ($element->_options as $option) {
1237 if ($option['attr']['value'] === "crm_disabled_opt-{$value[0]}") {
1238 $placeholder = html_entity_decode($option['text'], ENT_QUOTES, "UTF-8");
1239 $element->updateAttributes(array('placeholder' => $placeholder));
1240 break;
1241 }
1242 }
1243 $resetSubmitted = TRUE;
1244 }
1245 break;
1246 }
1247
1248 //finally unset values from submitted.
1249 if ($resetSubmitted) {
1250 self::resetSubmittedValue($name, $optIds, $form);
1251 }
1252 }
1253 }
1254
1255 /**
1256 * @param string $elementName
1257 * @param array $optionIds
1258 * @param CRM_Core_form $form
1259 */
1260 public static function resetSubmittedValue($elementName, $optionIds = array(), &$form) {
1261 if (empty($elementName) ||
1262 !$form->elementExists($elementName) ||
1263 !$form->getSubmitValue($elementName)
1264 ) {
1265 return;
1266 }
1267 foreach (array(
1268 'constantValues',
1269 'submitValues',
1270 'defaultValues',
1271 ) as $val) {
1272 $values = $form->{"_$val"};
1273 if (!is_array($values) || empty($values)) {
1274 continue;
1275 }
1276 $eleVal = CRM_Utils_Array::value($elementName, $values);
1277 if (empty($eleVal)) {
1278 continue;
1279 }
1280 if (is_array($eleVal)) {
1281 $found = FALSE;
1282 foreach ($eleVal as $keyId => $ignore) {
1283 if (in_array($keyId, $optionIds)) {
1284 $found = TRUE;
1285 unset($values[$elementName][$keyId]);
1286 }
1287 }
1288 if ($found && empty($values[$elementName][$keyId])) {
1289 $values[$elementName][$keyId] = NULL;
1290 }
1291 }
1292 else {
1293 if (!empty($keyId)) {
1294 $values[$elementName][$keyId] = NULL;
1295 }
1296 }
1297 }
1298 }
1299
1300 /**
1301 * Validate price set submitted params for price option limit,
1302 * as well as user should select at least one price field option.
1303 *
1304 * @param CRM_Core_Form $form
1305 * @param array $params
1306 *
1307 * @return array
1308 */
1309 public static function validatePriceSet(&$form, $params) {
1310 $errors = array();
1311 $hasOptMaxValue = FALSE;
1312 if (!is_array($params) || empty($params)) {
1313 return $errors;
1314 }
1315
1316 $currentParticipantNum = substr($form->_name, 12);
1317 if (!$currentParticipantNum) {
1318 $currentParticipantNum = 0;
1319 }
1320
1321 $priceSetId = $form->get('priceSetId');
1322 $priceSetDetails = $form->get('priceSet');
1323 if (
1324 !$priceSetId ||
1325 !is_array($priceSetDetails) ||
1326 empty($priceSetDetails)
1327 ) {
1328 return $errors;
1329 }
1330
1331 $optionsCountDetails = $optionsMaxValueDetails = array();
1332 if (
1333 isset($priceSetDetails['optionsMaxValueTotal'])
1334 && $priceSetDetails['optionsMaxValueTotal']
1335 ) {
1336 $hasOptMaxValue = TRUE;
1337 $optionsMaxValueDetails = $priceSetDetails['optionsMaxValueDetails']['fields'];
1338 }
1339 if (
1340 isset($priceSetDetails['optionsCountTotal'])
1341 && $priceSetDetails['optionsCountTotal']
1342 ) {
1343 $hasOptCount = TRUE;
1344 $optionsCountDetails = $priceSetDetails['optionsCountDetails']['fields'];
1345 }
1346 $feeBlock = $form->_feeBlock;
1347
1348 if (empty($feeBlock)) {
1349 $feeBlock = $priceSetDetails['fields'];
1350 }
1351
1352 $optionMaxValues = $fieldSelected = array();
1353 foreach ($params as $pNum => $values) {
1354 if (!is_array($values) || $values == 'skip') {
1355 continue;
1356 }
1357
1358 foreach ($values as $valKey => $value) {
1359 if (strpos($valKey, 'price_') === FALSE) {
1360 continue;
1361 }
1362 $priceFieldId = substr($valKey, 6);
1363 $noneOptionValueSelected = FALSE;
1364 if (!$feeBlock[$priceFieldId]['is_required'] && $value == 0) {
1365 $noneOptionValueSelected = TRUE;
1366 }
1367
1368 if (
1369 !$priceFieldId ||
1370 (!$noneOptionValueSelected && !is_array($value))
1371 ) {
1372 continue;
1373 }
1374
1375 $fieldSelected[$pNum] = TRUE;
1376
1377 if (!$hasOptMaxValue || !is_array($value)) {
1378 continue;
1379 }
1380
1381 foreach ($value as $optId => $optVal) {
1382 if (CRM_Utils_Array::value('html_type', $feeBlock[$priceFieldId]) == 'Text') {
1383 $currentMaxValue = $optVal;
1384 }
1385 else {
1386 $currentMaxValue = 1;
1387 }
1388
1389 if (isset($optionsCountDetails[$priceFieldId]) && isset($optionsCountDetails[$priceFieldId]['options'][$optId])) {
1390 $currentMaxValue = $optionsCountDetails[$priceFieldId]['options'][$optId] * $optVal;
1391 }
1392 if (empty($optionMaxValues)) {
1393 $optionMaxValues[$priceFieldId][$optId] = $currentMaxValue;
1394 }
1395 else {
1396 $optionMaxValues[$priceFieldId][$optId]
1397 = $currentMaxValue + CRM_Utils_Array::value($optId, CRM_Utils_Array::value($priceFieldId, $optionMaxValues), 0);
1398 }
1399 $soldOutPnum[$optId] = $pNum;
1400 }
1401 }
1402
1403 //validate for price field selection.
1404 if (empty($fieldSelected[$pNum])) {
1405 $errors[$pNum]['_qf_default'] = ts('Select at least one option from Event Fee(s).');
1406 }
1407 }
1408
1409 //validate for option max value.
1410 foreach ($optionMaxValues as $fieldId => $values) {
1411 $options = CRM_Utils_Array::value('options', $feeBlock[$fieldId], array());
1412 foreach ($values as $optId => $total) {
1413 $optMax = $optionsMaxValueDetails[$fieldId]['options'][$optId];
1414 $opDbCount = CRM_Utils_Array::value('db_total_count', $options[$optId], 0);
1415 $total += $opDbCount;
1416 if ($optMax && ($total > $optMax)) {
1417 if ($opDbCount && ($opDbCount >= $optMax)) {
1418 $errors[$soldOutPnum[$optId]]["price_{$fieldId}"]
1419 = ts('Sorry, this option is currently sold out.');
1420 }
1421 elseif (($optMax - $opDbCount) == 1) {
1422 $errors[$soldOutPnum[$optId]]["price_{$fieldId}"]
1423 = ts('Sorry, currently only a single seat is available for this option.', array(1 => ($optMax - $opDbCount)));
1424 }
1425 else {
1426 $errors[$soldOutPnum[$optId]]["price_{$fieldId}"]
1427 = ts('Sorry, currently only %1 seats are available for this option.', array(1 => ($optMax - $opDbCount)));
1428 }
1429 }
1430 }
1431 }
1432 return $errors;
1433 }
1434
1435 /**
1436 * set the first participant ID if not set, CRM-10032
1437 *
1438 * @param int $participantID
1439 */
1440 public function processFirstParticipant($participantID) {
1441 $this->_participantId = $participantID;
1442 $this->set('participantId', $this->_participantId);
1443
1444 $ids = $participantValues = array();
1445 $participantParams = array('id' => $this->_participantId);
1446 CRM_Event_BAO_Participant::getValues($participantParams, $participantValues, $ids);
1447 $this->_values['participant'] = $participantValues[$this->_participantId];
1448 $this->set('values', $this->_values);
1449
1450 // also set the allow confirmation stuff
1451 if (array_key_exists(
1452 $this->_values['participant']['status_id'],
1453 CRM_Event_PseudoConstant::participantStatus(NULL, "class = 'Pending'")
1454 )) {
1455 $this->_allowConfirmation = TRUE;
1456 $this->set('allowConfirmation', TRUE);
1457 }
1458 }
1459
1460 /**
1461 * @todo - combine this with CRM_Event_BAO_Event::validRegistrationRequest
1462 * (probably extract relevant values here & call that with them & handle bounces & redirects here -as
1463 * those belong in the form layer)
1464 *
1465 * @param string $redirect
1466 */
1467 public function checkValidEvent($redirect = NULL) {
1468 // is the event active (enabled)?
1469 if (!$this->_values['event']['is_active']) {
1470 // form is inactive, die a fatal death
1471 CRM_Core_Error::statusBounce(ts('The event you requested is currently unavailable (contact the site administrator for assistance).'));
1472 }
1473
1474 // is online registration is enabled?
1475 if (!$this->_values['event']['is_online_registration']) {
1476 CRM_Core_Error::statusBounce(ts('Online registration is not currently available for this event (contact the site administrator for assistance).'), $redirect);
1477 }
1478
1479 // is this an event template ?
1480 if (!empty($this->_values['event']['is_template'])) {
1481 CRM_Core_Error::statusBounce(ts('Event templates are not meant to be registered.'), $redirect);
1482 }
1483
1484 $now = date('YmdHis');
1485 $startDate = CRM_Utils_Date::processDate(CRM_Utils_Array::value('registration_start_date',
1486 $this->_values['event']
1487 ));
1488
1489 if (
1490 $startDate &&
1491 $startDate >= $now
1492 ) {
1493 CRM_Core_Error::statusBounce(ts('Registration for this event begins on %1', array(1 => CRM_Utils_Date::customFormat(CRM_Utils_Array::value('registration_start_date', $this->_values['event'])))), $redirect);
1494 }
1495
1496 $regEndDate = CRM_Utils_Date::processDate(CRM_Utils_Array::value('registration_end_date',
1497 $this->_values['event']
1498 ));
1499 $eventEndDate = CRM_Utils_Date::processDate(CRM_Utils_Array::value('event_end_date', $this->_values['event']));
1500 if (($regEndDate && ($regEndDate < $now)) || (empty($regEndDate) && !empty($eventEndDate) && ($eventEndDate < $now))) {
1501 $endDate = CRM_Utils_Date::customFormat(CRM_Utils_Array::value('registration_end_date', $this->_values['event']));
1502 if (empty($regEndDate)) {
1503 $endDate = CRM_Utils_Date::customFormat(CRM_Utils_Array::value('event_end_date', $this->_values['event']));
1504 }
1505 CRM_Core_Error::statusBounce(ts('Registration for this event ended on %1', array(1 => $endDate)), $redirect);
1506 }
1507 }
1508
1509 }