limit option for confirmation only for free events
[civicrm-core.git] / CRM / Event / Form / ManageEvent / Registration.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
06b69b18 4 | CiviCRM version 4.5 |
6a488035 5 +--------------------------------------------------------------------+
06b69b18 6 | Copyright CiviCRM LLC (c) 2004-2014 |
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 +--------------------------------------------------------------------+
26*/
27
28/**
29 *
30 *
31 * @package CRM
06b69b18 32 * @copyright CiviCRM LLC (c) 2004-2014
6a488035
TO
33 * $Id$
34 *
35 */
36
37/**
38 * This class generates form components for processing Event
39 *
40 */
41class CRM_Event_Form_ManageEvent_Registration extends CRM_Event_Form_ManageEvent {
42
43 /**
44 * what blocks should we show and hide.
45 *
46 * @var CRM_Core_ShowHideBlocks
47 */
48 protected $_showHide;
49
50 protected $_profilePostMultiple = array();
51 protected $_profilePostMultipleAdd = array();
52
53 /**
54 * Function to set variables up before form is built
55 *
56 * @return void
57 * @access public
f55dc004 58 */
6a488035
TO
59 function preProcess() {
60 $this->_addProfileBottom = CRM_Utils_Array::value('addProfileBottom', $_GET, FALSE);
61 $this->_profileBottomNum = CRM_Utils_Array::value('addProfileNum', $_GET, 0);
62 $this->_addProfileBottomAdd = CRM_Utils_Array::value('addProfileBottomAdd', $_GET, FALSE);
63 $this->_profileBottomNumAdd = CRM_Utils_Array::value('addProfileNumAdd', $_GET, 0);
64
65 parent::preProcess();
66
67 $this->assign('addProfileBottom', $this->_addProfileBottom);
68 $this->assign('profileBottomNum', $this->_profileBottomNum);
69
70 $urlParams = "id={$this->_id}&addProfileBottom=1&qfKey={$this->controller->_key}";
71 $this->assign('addProfileParams', $urlParams);
72
73 if ($addProfileBottom = CRM_Utils_Array::value('custom_post_id_multiple', $_POST)) {
74 foreach (array_keys($addProfileBottom) as $profileNum) {
75 self::buildMultipleProfileBottom($this, $profileNum);
76 }
77 }
78
79 $this->assign('addProfileBottomAdd', $this->_addProfileBottomAdd);
80 $this->assign('profileBottomNumAdd', $this->_profileBottomNumAdd);
81
82 $urlParamsAdd = "id={$this->_id}&addProfileBottomAdd=1&qfKey={$this->controller->_key}";
83 $this->assign('addProfileParamsAdd', $urlParamsAdd);
84
85 if ($addProfileBottomAdd = CRM_Utils_Array::value('additional_custom_post_id_multiple', $_POST)) {
86 foreach (array_keys($addProfileBottomAdd) as $profileNum) {
87 self::buildMultipleProfileBottom($this, $profileNum, 'additional_', ts('Profile for Additional Participants'));
88 }
89 }
90 }
91
92 /**
93 * This function sets the default values for the form.
94 * the default values are retrieved from the database
95 *
96 * @access public
97 *
355ba699 98 * @return void
6a488035
TO
99 */
100 function setDefaultValues() {
101 if ($this->_addProfileBottom || $this->_addProfileBottomAdd) {
102 return;
103 }
104 $eventId = $this->_id;
105
106 $defaults = parent::setDefaultValues();
107
108 $this->setShowHide($defaults);
109 if (isset($eventId)) {
110 $params = array('id' => $eventId);
111 CRM_Event_BAO_Event::retrieve($params, $defaults);
112
113 $ufJoinParams = array(
114 'entity_table' => 'civicrm_event',
115 'module' => 'CiviEvent',
116 'entity_id' => $eventId,
117 );
118
119 list($defaults['custom_pre_id'],
120 $defaults['custom_post']
121 ) = CRM_Core_BAO_UFJoin::getUFGroupIds($ufJoinParams);
122
123 // Get the id for the event registration profile
124 $eventRegistrationIdParams = $eventRegistrationIdDefaults = array(
125 'name' => 'event_registration',
126 );
127 CRM_Core_BAO_UFGroup::retrieve($eventRegistrationIdParams, $eventRegistrationIdDefaults);
128
129 // Set event registration as the default profile if none selected
130 if (!$defaults['custom_pre_id'] && count($defaults['custom_post']) == 0) {
131 $defaults['custom_pre_id'] = CRM_Utils_Array::value('id', $eventRegistrationIdDefaults);
132 }
133 if (isset($defaults['custom_post']) && is_numeric($defaults['custom_post'])) {
134 $defaults['custom_post_id'] = $defaults['custom_post'];
135 }
136 elseif (!empty($defaults['custom_post'])) {
137 $defaults['custom_post_id'] = $defaults['custom_post'][0];
138 unset($defaults['custom_post'][0]);
139 $this->_profilePostMultiple = $defaults['custom_post'];
140 foreach ($defaults['custom_post'] as $key => $value) {
141 self::buildMultipleProfileBottom($this, $key);
142 $defaults["custom_post_id_multiple[$key]"] = $value;
143 }
144 }
145
146 $this->assign('profilePostMultiple', CRM_Utils_Array::value('custom_post', $defaults));
147
a7488080 148 if (!empty($defaults['is_multiple_registrations'])) {
6a488035
TO
149 // CRM-4377: set additional participants’ profiles – set to ‘none’ if explicitly unset (non-active)
150
151 $ufJoinAddParams = array(
152 'entity_table' => 'civicrm_event',
153 'module' => 'CiviEvent_Additional',
154 'entity_id' => $eventId,
155 );
156
157 list($defaults['additional_custom_pre_id'],
158 $defaults['additional_custom_post']
159 ) = CRM_Core_BAO_UFJoin::getUFGroupIds($ufJoinAddParams);
160
161 if (isset($defaults['additional_custom_post']) && is_numeric($defaults['additional_custom_post'])) {
162 $defaults['additional_custom_post_id'] = $defaults['additional_custom_post'];
163 }
164 elseif (!empty($defaults['additional_custom_post'])) {
165 $defaults['additional_custom_post_id'] = $defaults['additional_custom_post'][0];
166 unset($defaults['additional_custom_post'][0]);
167
168 $this->_profilePostMultipleAdd = $defaults['additional_custom_post'];
169 foreach ($defaults['additional_custom_post'] as $key => $value) {
170 self::buildMultipleProfileBottom($this, $key, 'additional_', ts('Profile for Additional Participants'));
171 $defaults["additional_custom_post_id_multiple[$key]"] = $value;
172 }
173 }
174 $this->assign('profilePostMultipleAdd', CRM_Utils_Array::value('additional_custom_post', $defaults));
175 }
176 }
177 else {
178 $defaults['is_email_confirm'] = 0;
179 }
180
181 // provide defaults for required fields if empty (and as a 'hint' for approval message field)
182 $defaults['registration_link_text'] = CRM_Utils_Array::value('registration_link_text', $defaults, ts('Register Now'));
183 $defaults['confirm_title'] = CRM_Utils_Array::value('confirm_title', $defaults, ts('Confirm Your Registration Information'));
184 $defaults['thankyou_title'] = CRM_Utils_Array::value('thankyou_title', $defaults, ts('Thank You for Registering'));
185 $defaults['approval_req_text'] = CRM_Utils_Array::value('approval_req_text', $defaults, ts('Participation in this event requires approval. Submit your registration request here. Once approved, you will receive an email with a link to a web page where you can complete the registration process.'));
186
a7488080 187 if (!empty($defaults['registration_start_date'])) {
6a488035
TO
188 list($defaults['registration_start_date'],
189 $defaults['registration_start_date_time']
190 ) = CRM_Utils_Date::setDateDefaults($defaults['registration_start_date'],
191 'activityDateTime'
192 );
193 }
194
a7488080 195 if (!empty($defaults['registration_end_date'])) {
6a488035
TO
196 list($defaults['registration_end_date'],
197 $defaults['registration_end_date_time']
198 ) = CRM_Utils_Date::setDateDefaults($defaults['registration_end_date'],
199 'activityDateTime'
200 );
201 }
202
203 return $defaults;
204 }
205
206 /**
207 * Fix what blocks to show/hide based on the default values set
208 *
209 * @param array $defaults the array of default values
210 * @param boolean $force should we set show hide based on input defaults
211 *
212 * @return void
213 */
214 function setShowHide($defaults) {
215 $this->_showHide = new CRM_Core_ShowHideBlocks(array('registration' => 1),
216 ''
217 );
218 if (empty($defaults)) {
219 $this->_showHide->addHide('registration');
6a488035
TO
220 $this->_showHide->addHide('id-approval-text');
221 }
222 else {
a7488080 223 if (empty($defaults['requires_approval'])) {
6a488035
TO
224 $this->_showHide->addHide('id-approval-text');
225 }
226 }
227 $this->assign('defaultsEmpty', empty($defaults));
228 $this->_showHide->addToTemplate();
229 }
230
231 /**
232 * Function to build the form
233 *
355ba699 234 * @return void
6a488035
TO
235 * @access public
236 */
237 public function buildQuickForm() {
238 if ($this->_addProfileBottom) {
239 return self::buildMultipleProfileBottom($this, $this->_profileBottomNum);
240 }
241
242 if ($this->_addProfileBottomAdd) {
243 return self::buildMultipleProfileBottom($this, $this->_profileBottomNumAdd, 'additional_', ts('Profile for Additional Participants'));
244 }
245
246 $this->applyFilter('__ALL__', 'trim');
247 $attributes = CRM_Core_DAO::getAttribute('CRM_Event_DAO_Event');
248
249 $this->addElement('checkbox',
250 'is_online_registration',
251 ts('Allow Online Registration?'),
252 NULL,
253 array(
f55dc004 254 'onclick' => "return showHideByValue('is_online_registration',
255 '',
256 'registration_blocks',
257 'block',
258 'radio',
6a488035
TO
259 false );",
260 )
261 );
262
263 $this->add('text', 'registration_link_text', ts('Registration Link Text'));
264
265 if (!$this->_isTemplate) {
266 $this->addDateTime('registration_start_date', ts('Registration Start Date'), FALSE, array('formatType' => 'activityDateTime'));
267 $this->addDateTime('registration_end_date', ts('Registration End Date'), FALSE, array('formatType' => 'activityDateTime'));
268 }
269
270 $params = array(
271 'used' => 'Supervised',
272 'contact_type' => 'Individual',
273 );
274 $dedupeRuleFields = CRM_Dedupe_BAO_Rule::dedupeRuleFields($params);
275
276 foreach ($dedupeRuleFields as $key => $fields) {
277 $ruleFields[$key] = ucwords(str_replace('_', ' ', $fields));
278 }
279
280 $this->addElement('checkbox',
281 'is_multiple_registrations',
b01353b5 282 ts('Register multiple participants?')
6a488035
TO
283 );
284
285 $this->addElement('checkbox',
286 'allow_same_participant_emails',
03390e26 287 ts('Same email address?')
6a488035
TO
288 );
289 $this->assign('ruleFields', json_encode($ruleFields));
290
03390e26 291 $dedupeRules = array(
292 '' => '- Unsupervised rule -',
293 );
294 $dedupeRules += CRM_Dedupe_BAO_RuleGroup::getByType('Individual');
295 $this->add('select', 'dedupe_rule_group_id', ts('Duplicate matching rule'), $dedupeRules);
296
6a488035
TO
297 $participantStatuses = CRM_Event_PseudoConstant::participantStatus();
298 if (in_array('Awaiting approval', $participantStatuses) and in_array('Pending from approval', $participantStatuses) and in_array('Rejected', $participantStatuses)) {
299 $this->addElement('checkbox',
300 'requires_approval',
301 ts('Require participant approval?'),
302 NULL,
303 array('onclick' => "return showHideByValue('requires_approval', '', 'id-approval-text', 'table-row', 'radio', false);")
304 );
305 $this->add('textarea', 'approval_req_text', ts('Approval message'), $attributes['approval_req_text']);
306 }
307
308 $this->add('text', 'expiration_time', ts('Pending participant expiration (hours)'));
309 $this->addRule('expiration_time', ts('Please enter the number of hours (as an integer).'), 'integer');
310
311 self::buildRegistrationBlock($this);
312 self::buildConfirmationBlock($this);
313 self::buildMailBlock($this);
314 self::buildThankYouBlock($this);
315
316 parent::buildQuickForm();
317 }
318
319 /**
320 * Function to build Registration Block
321 *
322 * @param int $pageId
323 * @static
324 */
325 function buildRegistrationBlock(&$form) {
326 $attributes = CRM_Core_DAO::getAttribute('CRM_Event_DAO_Event');
327 $form->addWysiwyg('intro_text', ts('Introductory Text'), $attributes['intro_text']);
328 // FIXME: This hack forces height of editor to 175px. Need to modify QF classes for editors to allow passing
329 // explicit height and width.
330 $form->addWysiwyg('footer_text', ts('Footer Text'), array('rows' => 2, 'cols' => 40));
331
b9feacb8 332 extract( self::getProfileSelectorTypes() );
6a488035 333
518ef837 334 $form->addProfileSelector( 'custom_pre_id', ts('Include Profile') . '<br />' . ts('(top of page)'), $allowCoreTypes, $allowSubTypes, $profileEntities);
335 $form->addProfileSelector( 'custom_post_id', ts('Include Profile') . '<br />' . ts('(bottom of page)'), $allowCoreTypes, $allowSubTypes, $profileEntities);
6a488035 336
b9feacb8 337 $form->addProfileSelector( 'additional_custom_pre_id', ts('Profile for Additional Participants') . '<br />' . ts('(top of page)'), $allowCoreTypes, $allowSubTypes, $profileEntities);
338 $form->addProfileSelector( 'additional_custom_post_id', ts('Profile for Additional Participants') . '<br />' . ts('(bottom of page)'), $allowCoreTypes, $allowSubTypes, $profileEntities);
6a488035
TO
339 }
340
8e8a3d81 341 /**
342 * Subroutine to insert a Profile Editor widget
343 * depends on getProfileSelectorTypes
03390e26 344 *
8e8a3d81 345 * @param array &$form
346 * @param int $count unique index
347 * @param string $prefix dom element ID prefix
61739595 348 * @param string $label Label
8e8a3d81 349 * @param array $configs Optional, for addProfileSelector(), defaults to using getProfileSelectorTypes()
350 **/
61739595 351 function buildMultipleProfileBottom(&$form, $count, $prefix = '', $label = 'Include Profile', $configs = null) {
b9feacb8 352 extract( ( is_null($configs) ) ? self::getProfileSelectorTypes() : $configs );
518ef837 353 $element = $prefix . "custom_post_id_multiple[$count]";
61739595 354 $label .= '<br />'.ts('(bottom of page)');
355 $form->addProfileSelector( $element, $label, $allowCoreTypes, $allowSubTypes, $profileEntitites);
518ef837 356 }
357
8e8a3d81 358 /**
359 * Create initializers for addprofileSelector
360 *
361 * @return array( 'allowCoreTypes' => array(), 'allowSubTypes' => array(), 'profileEntities' => array() )
362 **/
b9feacb8 363 static function getProfileSelectorTypes() {
518ef837 364 $configs = array(
365 'allowCoreTypes' => array(),
366 'allowSubTypes' => array(),
367 'profileEntities' => array(),
6a488035
TO
368 );
369
518ef837 370 $configs['allowCoreTypes'][] = 'Contact';
371 $configs['allowCoreTypes'][] = 'Individual';
372 $configs['allowCoreTypes'][] = 'Participant';
6a488035 373
518ef837 374 $configs['profileEntities'][] = array('entity_name' => 'individual_entity', 'entity_type' => 'IndividualModel');
375 $configs['profileEntities'][] = array('entity_name' => 'participant_entity', 'entity_type' => 'ParticipantModel');
6a488035 376
518ef837 377 return $configs;
6a488035
TO
378 }
379
380 /**
381 * Function to build Confirmation Block
382 *
383 * @param int $pageId
384 * @static
385 */
386 function buildConfirmationBlock(&$form) {
387 $attributes = CRM_Core_DAO::getAttribute('CRM_Event_DAO_Event');
1909126f 388
d6121d3e 389 // CRM-11182 - Optional confirmation page for free events
390 $is_monetary = CRM_Core_DAO::getFieldValue('CRM_Event_DAO_Event', $form->_id, 'is_monetary');
391 $form->assign('is_monetary', $is_monetary);
392 if ($is_monetary == "0") {
393 $form->addYesNo('is_confirm_enabled', ts('Use a confirmation screen?'), NULL, NULL, array('onclick' => "return showHideByValue('is_confirm_enabled','','confirm_screen_settings','block','radio',false);"));
394 }
6a488035
TO
395 $form->add('text', 'confirm_title', ts('Title'), $attributes['confirm_title']);
396 $form->addWysiwyg('confirm_text', ts('Introductory Text'), $attributes['confirm_text']);
397 // FIXME: This hack forces height of editor to 175px. Need to modify QF classes for editors to allow passing
398 // explicit height and width.
399 $form->addWysiwyg('confirm_footer_text', ts('Footer Text'), array('rows' => 2, 'cols' => 40));
400 }
401
402 /**
403 * Function to build Email Block
404 *
405 * @param int $pageId
406 * @static
407 */
408 function buildMailBlock(&$form) {
409 $form->registerRule('emailList', 'callback', 'emailList', 'CRM_Utils_Rule');
410 $attributes = CRM_Core_DAO::getAttribute('CRM_Event_DAO_Event');
411 $form->addYesNo('is_email_confirm', ts('Send Confirmation Email?'), NULL, NULL, array('onclick' => "return showHideByValue('is_email_confirm','','confirmEmail','block','radio',false);"));
412 $form->add('textarea', 'confirm_email_text', ts('Text'), $attributes['confirm_email_text']);
413 $form->add('text', 'cc_confirm', ts('CC Confirmation To'), CRM_Core_DAO::getAttribute('CRM_Event_DAO_Event', 'cc_confirm'));
414 $form->addRule('cc_confirm', ts('Please enter a valid list of comma delimited email addresses'), 'emailList');
415 $form->add('text', 'bcc_confirm', ts('BCC Confirmation To'), CRM_Core_DAO::getAttribute('CRM_Event_DAO_Event', 'bcc_confirm'));
416 $form->addRule('bcc_confirm', ts('Please enter a valid list of comma delimited email addresses'), 'emailList');
417 $form->add('text', 'confirm_from_name', ts('Confirm From Name'));
418 $form->add('text', 'confirm_from_email', ts('Confirm From Email'));
419 $form->addRule('confirm_from_email', ts('Email is not valid.'), 'email');
420 }
421
422 function buildThankYouBlock(&$form) {
423 $attributes = CRM_Core_DAO::getAttribute('CRM_Event_DAO_Event');
424 $form->add('text', 'thankyou_title', ts('Title'), $attributes['thankyou_title']);
425 $form->addWysiwyg('thankyou_text', ts('Introductory Text'), $attributes['thankyou_text']);
426 // FIXME: This hack forces height of editor to 175px. Need to modify QF classes for editors to allow passing
427 // explicit height and width.
428 $form->addWysiwyg('thankyou_footer_text', ts('Footer Text'), array('rows' => 2, 'cols' => 40));
429 }
430
431 /**
432 * Add local and global form rules
433 *
434 * @access protected
435 *
436 * @return void
437 */
438 function addRules() {
439 if ($this->_addProfileBottom || $this->_addProfileBottomAdd) {
440 return;
441 }
442 $this->addFormRule(array('CRM_Event_Form_ManageEvent_Registration', 'formRule'), $this);
443 }
444
445 /**
446 * global validation rules for the form
447 *
448 * @param array $fields posted values of the form
449 *
450 * @return array list of errors to be posted back to the form
451 * @static
452 * @access public
453 */
454 static function formRule($values, $files, $form) {
a7488080 455 if (!empty($values['is_online_registration'])) {
6a488035
TO
456
457 if (!$values['confirm_title']) {
458 $errorMsg['confirm_title'] = ts('Please enter a Title for the registration Confirmation Page');
459 }
460 if (!$values['thankyou_title']) {
461 $errorMsg['thankyou_title'] = ts('Please enter a Title for the registration Thank-you Page');
462 }
463 if ($values['is_email_confirm']) {
464 if (!$values['confirm_from_name']) {
465 $errorMsg['confirm_from_name'] = ts('Please enter Confirmation Email FROM Name.');
466 }
467
468 if (!$values['confirm_from_email']) {
469 $errorMsg['confirm_from_email'] = ts('Please enter Confirmation Email FROM Email Address.');
470 }
471 }
f55dc004 472
ef597b45
DL
473 if (
474 isset($values['registration_start_date']) &&
475 isset($values['registration_end_date'])
476 ) {
6a488035
TO
477 $start = CRM_Utils_Date::processDate($values['registration_start_date']);
478 $end = CRM_Utils_Date::processDate($values['registration_end_date']);
479 if ($end < $start) {
480 $errorMsg['registration_end_date'] = ts('Registration end date should be after Registration start date');
481 }
482 }
483
484 //check that the selected profiles have either firstname+lastname or email required
485 $profileIds = array(
486 CRM_Utils_Array::value('custom_pre_id', $values),
487 CRM_Utils_Array::value('custom_post_id', $values),
488 );
489 $additionalProfileIds = array(
490 CRM_Utils_Array::value('additional_custom_pre_id', $values),
491 CRM_Utils_Array::value('additional_custom_post_id', $values),
492 );
493 //additional profile fields default to main if not set
494 if (!is_numeric($additionalProfileIds[0])) {
495 $additionalProfileIds[0] = $profileIds[0];
496 }
497 if (!is_numeric($additionalProfileIds[1])) {
498 $additionalProfileIds[1] = $profileIds[1];
499 }
500 //add multiple profiles if set
501 self::addMultipleProfiles($profileIds, $values, 'custom_post_id_multiple');
502 self::addMultipleProfiles($additionalProfileIds, $values, 'additional_custom_post_id_multiple');
503 $isProfileComplete = self::isProfileComplete($profileIds);
504 $isAdditionalProfileComplete = self::isProfileComplete($additionalProfileIds);
03390e26 505
6a488035
TO
506 //Check main profiles have an email address available if 'send confirmation email' is selected
507 if ($values['is_email_confirm']) {
508 $emailFields = self::getEmailFields($profileIds);
509 if (!count($emailFields)) {
510 $errorMsg['is_email_confirm'] = ts("Please add a profile with an email address if 'Send Confirmation Email?' is selected");
511 }
512 }
513 $additionalCustomPreId = $additionalCustomPostId = NULL;
514 $isPreError = $isPostError = TRUE;
8cc574cf 515 if (!empty($values['allow_same_participant_emails']) && !empty($values['is_multiple_registrations'])) {
6a488035
TO
516 $types = array_merge(array('Individual'), CRM_Contact_BAO_ContactType::subTypes('Individual'));
517 $profiles = CRM_Core_BAO_UFGroup::getProfiles($types);
518
519 //check for additional custom pre profile
520 $additionalCustomPreId = CRM_Utils_Array::value('additional_custom_pre_id', $values);
521 if (!empty($additionalCustomPreId)) {
522 if (!($additionalCustomPreId == 'none')) {
523 $customPreId = $additionalCustomPreId;
524 }
525 else {
526 $isPreError = FALSE;
527 }
528 }
529 else {
0d8afee2 530 $customPreId = !empty($values['custom_pre_id']) ? $values['custom_pre_id'] : NULL;
6a488035
TO
531 }
532 //check whether the additional custom pre profile is of type 'Individual' and its subtypes
533 if (!empty($customPreId)) {
534 $profileTypes = CRM_Core_BAO_UFGroup::profileGroups($customPreId);
535 foreach ($types as $individualTypes) {
536 if (in_array($individualTypes, $profileTypes)) {
537 $isPreError = FALSE;
538 break;
539 }
540 }
541 }
542 else {
543 $isPreError = FALSE;
544 }
f55dc004 545
dbeb7efb
DG
546 // We don't have required Individual fields in the pre-custom profile, so now check the post-custom profile
547 if ($isPreError) {
548 $additionalCustomPostId = CRM_Utils_Array::value('additional_custom_post_id', $values);
549 if (!empty($additionalCustomPostId)) {
550 if (!($additionalCustomPostId == 'none')) {
551 $customPostId = $additionalCustomPostId;
552 }
553 else {
554 $isPostError = FALSE;
555 }
6a488035
TO
556 }
557 else {
0d8afee2 558 $customPostId = !empty($values['custom_post_id']) ? $values['custom_post_id'] : NULL;
6a488035 559 }
dbeb7efb
DG
560 //check whether the additional custom post profile is of type 'Individual' and its subtypes
561 if (!empty($customPostId)) {
562 $profileTypes = CRM_Core_BAO_UFGroup::profileGroups($customPostId);
563 foreach ($types as $individualTypes) {
564 if (in_array($individualTypes, $profileTypes)) {
565 $isPostError = FALSE;
566 break;
567 }
6a488035
TO
568 }
569 }
dbeb7efb
DG
570 else {
571 $isPostError = FALSE;
572 }
573
574 if (empty($customPreId) && empty($customPostId)) {
575 $errorMsg['additional_custom_pre_id'] = ts("Allow multiple registrations from the same email address requires a profile of type 'Individual'");
576 }
577 if ($isPostError) {
578 $errorMsg['additional_custom_post_id'] = ts("Allow multiple registrations from the same email address requires a profile of type 'Individual'");
579 }
6a488035
TO
580 }
581 }
582 if (!$isProfileComplete) {
583 $errorMsg['custom_pre_id'] = ts("Please include a Profile for online registration that contains an Email Address field and / or First Name + Last Name fields.");
584 }
585 if (!$isAdditionalProfileComplete) {
586 $errorMsg['additional_custom_pre_id'] = ts("Please include a Profile for online registration of additional participants that contains an Email Address field and / or First Name + Last Name fields.");
587 }
588
589 // // CRM-8485
590 // $config = CRM_Core_Config::singleton();
591 // if ( $config->doNotAttachPDFReceipt ) {
a7488080 592 // if (!empty($values['custom_post_id_multiple'])) {
6a488035
TO
593 // foreach( $values['custom_post_id_multiple'] as $count => $customPostMultiple ) {
594 // if ( $customPostMultiple ) {
595 // $errorMsg["custom_post_id_multiple[{$count}]"] = ts('Please disable PDF receipt as an attachment in <a href="%1">Miscellaneous Settings</a> if you want to add additional profiles.', array( 1 => CRM_Utils_System::url( 'civicrm/admin/setting/misc', 'reset=1' ) ) );
596 // break;
597 // }
598 // }
599 // }
600 //
a7488080 601 // if (!empty($values['is_multiple_registrations']) &&
6a488035
TO
602 // CRM_Utils_Array::value('additional_custom_post_id_multiple', $values) ) {
603 // foreach( $values['additional_custom_post_id_multiple'] as $count => $customPostMultiple ) {
604 // if ( $customPostMultiple ) {
605 // $errorMsg["additional_custom_post_id_multiple[{$count}]"] = ts('Please disable PDF receipt as an attachment in <a href="%1">Miscellaneous Settings</a> if you want to add additional profiles.', array( 1 => CRM_Utils_System::url( 'civicrm/admin/setting/misc', 'reset=1' ) ) );
606 // break;
607 // }
608 // }
609 // }
610 // }
611
612 if (!empty($errorMsg)) {
a7488080 613 if (!empty($values['custom_post_id_multiple'])) {
6a488035
TO
614 foreach ($values['custom_post_id_multiple'] as $count => $customPostMultiple) {
615 self::buildMultipleProfileBottom($form, $count);
616 }
617 $form->assign('profilePostMultiple', $values['custom_post_id_multiple']);
618 }
a7488080 619 if (!empty($values['additional_custom_post_id_multiple'])) {
6a488035
TO
620 foreach ($values['additional_custom_post_id_multiple'] as $count => $customPostMultiple) {
621 self::buildMultipleProfileBottom($form, $count, 'additional_', ts('Profile for Additional Participants'));
622 }
623 $form->assign('profilePostMultipleAdd', $values['additional_custom_post_id_multiple']);
624 }
625 }
626 }
627
628 if (!empty($errorMsg)) {
629 return $errorMsg;
630 }
631
632 return TRUE;
633 }
634
635 /**
636 * Collect all email fields for an array of profile ids
637 *
638 * @return boolean
639 */
640 static function getEmailFields($profileIds) {
641 $emailFields = array();
642 foreach ($profileIds as $profileId) {
643 if ($profileId && is_numeric($profileId)) {
644 $fields = CRM_Core_BAO_UFGroup::getFields($profileId);
645 foreach ($fields as $field) {
646 if (substr_count($field['name'], 'email')) {
647 $emailFields[] = $field;
648 }
649 }
650 }
651 }
652 return $emailFields;
653 }
654
655 /**
656 * Check if a profile contains required fields
657 *
658 * @return boolean
659 */
660 static function isProfileComplete($profileIds) {
661 $profileReqFields = array();
662 foreach ($profileIds as $profileId) {
663 if ($profileId && is_numeric($profileId)) {
664 $fields = CRM_Core_BAO_UFGroup::getFields($profileId);
665 foreach ($fields as $field) {
666 switch (TRUE) {
667 case substr_count($field['name'], 'email'):
668 $profileReqFields[] = 'email';
669 break;
670
671 case substr_count($field['name'], 'first_name'):
672 $profileReqFields[] = 'first_name';
673 break;
674
675 case substr_count($field['name'], 'last_name'):
676 $profileReqFields[] = 'last_name';
677 break;
678 }
679 }
680 }
681 }
682 $profileComplete = (in_array('email', $profileReqFields)
683 || (in_array('first_name', $profileReqFields) && in_array('last_name', $profileReqFields))
684 );
685 return $profileComplete;
686 }
687
03390e26 688 /**
689 * Check if the profiles collect enough information to dedupe
690 *
691 * @return boolean
692 */
693
694 function canProfilesDedupe($profileIds, $rgId = 0) {
695
696 // find the unsupervised rule
697
698 $rgParams = array(
699 'used' => 'Unsupervised',
700 'contact_type' => 'Individual',
701 );
702 if ($rgId > 0) {
703 $rgParams['id'] = $rgId;
704 }
705 $activeRg = CRM_Dedupe_BAO_RuleGroup::dedupeRuleFieldsWeight($rgParams);
706
707 // get the combinations that could be a match for the rule
708 $okCombos = $combos = array();
709 CRM_Dedupe_BAO_RuleGroup::combos($activeRg[0], $activeRg[1], $combos);
710
711 // create an index of what combinations involve each field
712 $index = array();
713 foreach ($combos as $comboid => $combo) {
714 foreach ($combo as $cfield) {
715 $index[$cfield][$comboid] = true;
716 }
717 $combos[$comboid] = array_fill_keys($combo, 0);
718 $okCombos[$comboid] = array_fill_keys($combo, 2);
719 }
720
721 // get profiles and see if they have the necessary combos
722 $profileReqFields = array();
723 foreach ($profileIds as $profileId) {
724 if ($profileId && is_numeric($profileId)) {
725 $fields = CRM_Core_BAO_UFGroup::getFields($profileId);
726
727 // walk through the fields in the profile
728 foreach ($fields as $field) {
729
730 // check each of the fields in the index against the profile field
731 foreach ($index as $ifield => $icombos) {
732 if(strpos($field['name'], $ifield) !== false) {
733
734 // we found the field in the profile, now record it in the index
735 foreach ($icombos as $icombo => $dontcare) {
736 $combos[$icombo][$ifield] = ($combos[$icombo][$ifield] != 2 && !$field['is_required']) ? 1 : 2;
737
738 if ($combos[$icombo] == $okCombos[$icombo]) {
739 // if any combo is complete with 2s (all fields are present and required), we can go home
740 return 2;
741 }
742 }
743 }
744 }
745 }
746 }
747 }
748
749 // check the combos to see if everything is > 0
750 foreach ($combos as $comboid => $combo) {
751 $complete = false;
752 foreach ($combo as $cfield) {
753 if ($cfield > 0) {
754 $complete = true;
755 }
756 else {
757 // this combo isn't complete--skip to the next combo
758 continue 2;
759 }
760 }
761 if ($complete) { return 1; }
762 }
763
764 // no combo succeeded
765 return 0;
766 }
767
6a488035
TO
768 /**
769 * Add additional profiles from the form to an array of profile ids.
770 *
771 */
772 static function addMultipleProfiles(&$profileIds, $values, $field) {
773 if ($multipleProfiles = CRM_Utils_Array::value($field, $values)) {
774 foreach ($multipleProfiles as $profileId) {
775 $profileIds[] = $profileId;
776 }
777 }
778 }
779
780 /**
781 * Function to process the form
782 *
783 * @access public
784 *
355ba699 785 * @return void
6a488035
TO
786 */
787 public function postProcess() {
6a488035
TO
788 $params = $this->exportValues();
789
790 $params['id'] = $this->_id;
791
1909126f 792 // format params
6a488035 793 $params['is_online_registration'] = CRM_Utils_Array::value('is_online_registration', $params, FALSE);
1909126f 794 $params['is_confirm_enabled'] = CRM_Utils_Array::value('is_confirm_enabled', $params, FALSE); // CRM-11182
6a488035
TO
795 $params['is_multiple_registrations'] = CRM_Utils_Array::value('is_multiple_registrations', $params, FALSE);
796 $params['allow_same_participant_emails'] = CRM_Utils_Array::value('allow_same_participant_emails', $params, FALSE);
797 $params['requires_approval'] = CRM_Utils_Array::value('requires_approval', $params, FALSE);
798
799 // reset is_email confirm if not online reg
800 if (!$params['is_online_registration']) {
801 $params['is_email_confirm'] = FALSE;
802 }
803
804 if (!$this->_isTemplate) {
805 $params['registration_start_date'] = CRM_Utils_Date::processDate($params['registration_start_date'],
806 $params['registration_start_date_time'],
807 TRUE
808 );
809 $params['registration_end_date'] = CRM_Utils_Date::processDate($params['registration_end_date'],
810 $params['registration_end_date_time'],
811 TRUE
812 );
813 }
814
815 CRM_Event_BAO_Event::add($params);
816
817 // also update the ProfileModule tables
818 $ufJoinParams = array(
819 'is_active' => 1,
820 'module' => 'CiviEvent',
821 'entity_table' => 'civicrm_event',
822 'entity_id' => $this->_id,
823 );
824
825
826 // first delete all past entries
827 CRM_Core_BAO_UFJoin::deleteAll($ufJoinParams);
828
829 $uf = array();
830 $wt = 2;
831 if (!empty($params['custom_pre_id'])) {
832 $uf[1] = $params['custom_pre_id'];
833 $wt = 1;
834 }
835
836 if (!empty($params['custom_post_id'])) {
837 $uf[2] = $params['custom_post_id'];
838 }
839
a7488080 840 if (!empty($params['custom_post_id_multiple'])) {
6a488035
TO
841 $uf = array_merge($uf, $params['custom_post_id_multiple']);
842 }
843 $uf = array_values($uf);
844 if (!empty($uf)) {
845 foreach ($uf as $weight => $ufGroupId) {
846 $ufJoinParams['weight'] = $weight + $wt;
847 $ufJoinParams['uf_group_id'] = $ufGroupId;
848 CRM_Core_BAO_UFJoin::create($ufJoinParams);
849 unset($ufJoinParams['id']);
850 }
851 }
852 // also update the ProfileModule tables
853 $ufJoinParamsAdd = array(
854 'is_active' => 1,
855 'module' => 'CiviEvent_Additional',
856 'entity_table' => 'civicrm_event',
857 'entity_id' => $this->_id,
858 );
859
860 // first delete all past entries
861 CRM_Core_BAO_UFJoin::deleteAll($ufJoinParamsAdd);
a7488080 862 if (!empty($params['is_multiple_registrations'])) {
6a488035
TO
863 $ufAdd = array();
864 $wtAdd = 2;
865
866 if (array_key_exists('additional_custom_pre_id', $params)) {
a7488080 867 if (empty($params['additional_custom_pre_id'])) {
6a488035
TO
868 $ufAdd[1] = $params['custom_pre_id'];
869 $wtAdd = 1;
870 }
871 elseif (CRM_Utils_Array::value('additional_custom_pre_id', $params) == 'none') {}
872 else {
873 $ufAdd[1] = $params['additional_custom_pre_id'];
874 $wtAdd = 1;
875 }
876 }
877
878 if (array_key_exists('additional_custom_post_id', $params)) {
a7488080 879 if (empty($params['additional_custom_post_id'])) {
6a488035
TO
880 $ufAdd[2] = $params['custom_post_id'];
881 }
882 elseif (CRM_Utils_Array::value('additional_custom_post_id', $params) == 'none') {}
883 else {
884 $ufAdd[2] = $params['additional_custom_post_id'];
885 }
886 }
887
a7488080 888 if (!empty($params['additional_custom_post_id_multiple'])) {
6a488035
TO
889 $additionalPostMultiple = array();
890 foreach ($params['additional_custom_post_id_multiple'] as $key => $value) {
8cc574cf 891 if (!$value && !empty($params['custom_post_id'])) {
6a488035
TO
892 $additionalPostMultiple[$key] = $params['custom_post_id'];
893 }
894 elseif ($value == 'none') {
895 continue;
896 }
897 elseif ($value) {
898 $additionalPostMultiple[$key] = $value;
899 }
900 }
901 $ufAdd = array_merge($ufAdd, $additionalPostMultiple);
902 }
903
904 $ufAdd = array_values($ufAdd);
905 if (!empty($ufAdd)) {
906 foreach ($ufAdd as $weightAdd => $ufGroupIdAdd) {
907
908 $ufJoinParamsAdd['weight'] = $weightAdd + $wtAdd;
909 $ufJoinParamsAdd['uf_group_id'] = $ufGroupIdAdd;
910
911 CRM_Core_BAO_UFJoin::create($ufJoinParamsAdd);
912 unset($ufJoinParamsAdd['id']);
913 }
914 }
915 }
916
03390e26 917 // get the profiles to evaluate what they collect
918 $profileIds = array(
919 CRM_Utils_Array::value('custom_pre_id', $params),
920 CRM_Utils_Array::value('custom_post_id', $params),
921 );
922 $additionalProfileIds = array(
923 CRM_Utils_Array::value('additional_custom_pre_id', $params),
924 CRM_Utils_Array::value('additional_custom_post_id', $params),
925 );
926 // additional profile fields default to main if not set
927 if (!is_numeric($additionalProfileIds[0])) {
928 $additionalProfileIds[0] = $profileIds[0];
929 }
930 if (!is_numeric($additionalProfileIds[1])) {
931 $additionalProfileIds[1] = $profileIds[1];
932 }
933 //add multiple profiles if set
934 self::addMultipleProfiles($profileIds, $params, 'custom_post_id_multiple');
935 self::addMultipleProfiles($additionalProfileIds, $params, 'additional_custom_post_id_multiple');
936
937 $cantDedupe = false;
938 $rgId = CRM_Utils_Array::value('dedupe_rule_group_id', $params, 0);
939
940 switch (self::canProfilesDedupe($profileIds, $rgId)) {
941 case 0:
942 $dedupeTitle = 'Duplicate Matching Impossible';
943 $cantDedupe = ts("The selected profiles do not contain the fields necessary to match registrations with existing contacts. This means all anonymous registrations will result in a new contact.");
944 break;
945 case 1:
946 $dedupeTitle = 'Duplicate Contacts Possible';
947 $cantDedupe = ts("The selected profiles can collect enough information to match registrations with existing contacts, but not all of the relevant fields are required. Anonymous registrations may result in duplicate contacts.");
948 }
949 if (!empty($params['is_multiple_registrations'])) {
950 switch(self::canProfilesDedupe($additionalProfileIds, $rgId)) {
951 case 0:
952 $dedupeTitle = 'Duplicate Matching Impossible';
953 if ($cantDedupe) {
954 $cantDedupe = ts("The selected profiles do not contain the fields necessary to match registrations with existing contacts. This means all anonymous registrations will result in a new contact.");
955 }
956 else {
957 $cantDedupe = ts("The selected profiles do not contain the fields necessary to match additional participants with existing contacts. This means all additional participants will result in a new contact.");
958 }
959 break;
960 case 1:
961 if (!$cantDedupe) {
962 $dedupeTitle = 'Duplicate Contacts Possible';
963 $cantDedupe = ts("The selected profiles can collect enough information to match additional participants with existing contacts, but not all of the relevant fields are required. This may result in duplicate contacts.");
964 }
965 }
966 }
967 if ($cantDedupe) {
968 CRM_Core_Session::setStatus($cantDedupe, $dedupeTitle, 'alert dedupenotify', array('expires' => 0));
969 }
970
5d92a7e7
CW
971 // Update tab "disabled" css class
972 $this->ajaxResponse['tabValid'] = !empty($params['is_online_registration']);
973
6a488035
TO
974 parent::endPostProcess();
975 }
976 //end of function
977
978 /**
979 * Return a descriptive name for the page, used in wizard header
980 *
981 * @return string
982 * @access public
983 */
984 public function getTitle() {
985 return ts('Online Registration');
986 }
987}
988