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