3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
6 | This work is published under the GNU AGPLv3 license with some |
7 | permitted exceptions and without any warranty. For full license |
8 | and copyright information, see https://civicrm.org/licensing |
9 +--------------------------------------------------------------------+
14 * @copyright CiviCRM LLC https://civicrm.org/licensing
18 * This class generates form components for processing Event.
20 class CRM_Event_Form_ManageEvent_Registration
extends CRM_Event_Form_ManageEvent
{
23 * What blocks should we show and hide.
25 * @var CRM_Core_ShowHideBlocks
29 protected $_profilePostMultiple = [];
30 protected $_profilePostMultipleAdd = [];
33 * Set variables up before form is built.
35 public function preProcess() {
36 $this->_addProfileBottom
= CRM_Utils_Array
::value('addProfileBottom', $_GET, FALSE);
37 $this->_profileBottomNum
= CRM_Utils_Array
::value('addProfileNum', $_GET, 0);
38 $this->_addProfileBottomAdd
= CRM_Utils_Array
::value('addProfileBottomAdd', $_GET, FALSE);
39 $this->_profileBottomNumAdd
= CRM_Utils_Array
::value('addProfileNumAdd', $_GET, 0);
42 $this->setSelectedChild('registration');
44 $this->assign('addProfileBottom', $this->_addProfileBottom
);
45 $this->assign('profileBottomNum', $this->_profileBottomNum
);
47 $urlParams = "id={$this->_id}&addProfileBottom=1&qfKey={$this->controller->_key}";
48 $this->assign('addProfileParams', $urlParams);
50 if ($addProfileBottom = CRM_Utils_Array
::value('custom_post_id_multiple', $_POST)) {
51 foreach (array_keys($addProfileBottom) as $profileNum) {
52 self
::buildMultipleProfileBottom($this, $profileNum);
56 $this->assign('addProfileBottomAdd', $this->_addProfileBottomAdd
);
57 $this->assign('profileBottomNumAdd', $this->_profileBottomNumAdd
);
59 $urlParamsAdd = "id={$this->_id}&addProfileBottomAdd=1&qfKey={$this->controller->_key}";
60 $this->assign('addProfileParamsAdd', $urlParamsAdd);
62 if ($addProfileBottomAdd = CRM_Utils_Array
::value('additional_custom_post_id_multiple', $_POST)) {
63 foreach (array_keys($addProfileBottomAdd) as $profileNum) {
64 self
::buildMultipleProfileBottom($this, $profileNum, 'additional_', ts('Profile for Additional Participants'));
70 * Set default values for the form.
72 * The default values are retrieved from the database.
74 public function setDefaultValues() {
75 if ($this->_addProfileBottom ||
$this->_addProfileBottomAdd
) {
78 $eventId = $this->_id
;
80 $defaults = parent
::setDefaultValues();
82 $this->setShowHide($defaults);
83 if (isset($eventId)) {
84 $params = ['id' => $eventId];
85 CRM_Event_BAO_Event
::retrieve($params, $defaults);
88 'entity_table' => 'civicrm_event',
89 'module' => 'CiviEvent',
90 'entity_id' => $eventId,
93 list($defaults['custom_pre_id'],
94 $defaults['custom_post']
95 ) = CRM_Core_BAO_UFJoin
::getUFGroupIds($ufJoinParams);
97 // Get the id for the event registration profile
98 $eventRegistrationIdParams = $eventRegistrationIdDefaults = [
99 'name' => 'event_registration',
101 CRM_Core_BAO_UFGroup
::retrieve($eventRegistrationIdParams, $eventRegistrationIdDefaults);
103 // Set event registration as the default profile if none selected
104 if (!$defaults['custom_pre_id'] && count($defaults['custom_post']) == 0) {
105 $defaults['custom_pre_id'] = $eventRegistrationIdDefaults['id'] ??
NULL;
107 if (isset($defaults['custom_post']) && is_numeric($defaults['custom_post'])) {
108 $defaults['custom_post_id'] = $defaults['custom_post'];
110 elseif (!empty($defaults['custom_post'])) {
111 $defaults['custom_post_id'] = $defaults['custom_post'][0];
112 unset($defaults['custom_post'][0]);
113 $this->_profilePostMultiple
= $defaults['custom_post'];
114 foreach ($defaults['custom_post'] as $key => $value) {
115 self
::buildMultipleProfileBottom($this, $key);
116 $defaults["custom_post_id_multiple[$key]"] = $value;
120 $this->assign('profilePostMultiple', CRM_Utils_Array
::value('custom_post', $defaults));
122 // CRM-17745: Make max additional participants configurable
123 if (empty($defaults['max_additional_participants'])) {
124 $defaults['max_additional_participants'] = 9;
127 if (!empty($defaults['is_multiple_registrations'])) {
128 // CRM-4377: set additional participants’ profiles – set to ‘none’ if explicitly unset (non-active)
131 'entity_table' => 'civicrm_event',
132 'module' => 'CiviEvent_Additional',
133 'entity_id' => $eventId,
136 list($defaults['additional_custom_pre_id'],
137 $defaults['additional_custom_post']
138 ) = CRM_Core_BAO_UFJoin
::getUFGroupIds($ufJoinAddParams);
140 if (isset($defaults['additional_custom_post']) && is_numeric($defaults['additional_custom_post'])) {
141 $defaults['additional_custom_post_id'] = $defaults['additional_custom_post'];
143 elseif (!empty($defaults['additional_custom_post'])) {
144 $defaults['additional_custom_post_id'] = $defaults['additional_custom_post'][0];
145 unset($defaults['additional_custom_post'][0]);
147 $this->_profilePostMultipleAdd
= $defaults['additional_custom_post'];
148 foreach ($defaults['additional_custom_post'] as $key => $value) {
149 self
::buildMultipleProfileBottom($this, $key, 'additional_', ts('Profile for Additional Participants'));
150 $defaults["additional_custom_post_id_multiple[$key]"] = $value;
153 $this->assign('profilePostMultipleAdd', CRM_Utils_Array
::value('additional_custom_post', $defaults, []));
157 $defaults['is_email_confirm'] = 0;
160 // provide defaults for required fields if empty (and as a 'hint' for approval message field)
161 $defaults['registration_link_text'] = CRM_Utils_Array
::value('registration_link_text', $defaults, ts('Register Now'));
162 $defaults['confirm_title'] = CRM_Utils_Array
::value('confirm_title', $defaults, ts('Confirm Your Registration Information'));
163 $defaults['thankyou_title'] = CRM_Utils_Array
::value('thankyou_title', $defaults, ts('Thank You for Registering'));
164 $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.'));
170 * Fix what blocks to show/hide based on the default values set
172 * @param array $defaults
173 * The array of default values.
177 public function setShowHide($defaults) {
178 $this->_showHide
= new CRM_Core_ShowHideBlocks(['registration' => 1],
181 if (empty($defaults)) {
182 $this->_showHide
->addHide('registration');
183 $this->_showHide
->addHide('id-approval-text');
186 if (empty($defaults['requires_approval'])) {
187 $this->_showHide
->addHide('id-approval-text');
190 $this->assign('defaultsEmpty', empty($defaults));
191 $this->_showHide
->addToTemplate();
195 * Build the form object.
199 public function buildQuickForm() {
200 if ($this->_addProfileBottom
) {
201 return self
::buildMultipleProfileBottom($this, $this->_profileBottomNum
);
204 if ($this->_addProfileBottomAdd
) {
205 return self
::buildMultipleProfileBottom($this, $this->_profileBottomNumAdd
, 'additional_', ts('Profile for Additional Participants'));
208 $this->applyFilter('__ALL__', 'trim');
209 $attributes = CRM_Core_DAO
::getAttribute('CRM_Event_DAO_Event');
211 $this->addElement('checkbox',
212 'is_online_registration',
213 ts('Allow Online Registration'),
216 'onclick' => "return showHideByValue('is_online_registration'," .
218 "'registration_blocks'," .
225 $this->add('text', 'registration_link_text', ts('Registration Link Text'));
227 if (!$this->_isTemplate
) {
228 $this->add('datepicker', 'registration_start_date', ts('Registration Start Date'), [], FALSE, ['time' => TRUE]);
229 $this->add('datepicker', 'registration_end_date', ts('Registration End Date'), [], FALSE, ['time' => TRUE]);
233 'used' => 'Supervised',
234 'contact_type' => 'Individual',
236 $dedupeRuleFields = CRM_Dedupe_BAO_Rule
::dedupeRuleFields($params);
238 foreach ($dedupeRuleFields as $key => $fields) {
239 $ruleFields[$key] = ucwords(str_replace('_', ' ', $fields));
242 $this->addElement('checkbox',
243 'is_multiple_registrations',
244 ts('Register multiple participants?')
247 // CRM-17745: Make maximum additional participants configurable
248 $numericOptions = CRM_Core_SelectValues
::getNumericOptions(1, 9);
249 $this->add('select', 'max_additional_participants', ts('Maximum additional participants'), $numericOptions, FALSE, ['class' => 'required']);
251 $this->addElement('checkbox',
252 'allow_same_participant_emails',
253 ts('Same email address?')
255 $this->assign('ruleFields', json_encode($ruleFields));
258 '' => '- Unsupervised rule -',
260 $dedupeRules +
= CRM_Dedupe_BAO_RuleGroup
::getByType('Individual');
261 $this->add('select', 'dedupe_rule_group_id', ts('Duplicate matching rule'), $dedupeRules);
263 $participantStatuses = CRM_Event_PseudoConstant
::participantStatus();
264 if (in_array('Awaiting approval', $participantStatuses) and in_array('Pending from approval', $participantStatuses) and in_array('Rejected', $participantStatuses)) {
265 $this->addElement('checkbox',
267 ts('Require participant approval?'),
269 ['onclick' => "return showHideByValue('requires_approval', '', 'id-approval-text', 'table-row', 'radio', false);"]
271 $this->add('textarea', 'approval_req_text', ts('Approval message'), $attributes['approval_req_text']);
274 $this->add('text', 'expiration_time', ts('Pending participant expiration (hours)'));
275 $this->addRule('expiration_time', ts('Please enter the number of hours (as an integer).'), 'integer');
276 $this->addField('allow_selfcancelxfer', ['label' => ts('Allow self-service cancellation or transfer?'), 'type' => 'advcheckbox']);
277 $this->add('text', 'selfcancelxfer_time', ts('Cancellation or transfer time limit (hours)'));
278 $this->addRule('selfcancelxfer_time', ts('Please enter the number of hours (as an integer).'), 'integer');
279 self
::buildRegistrationBlock($this);
280 self
::buildConfirmationBlock($this);
281 self
::buildMailBlock($this);
282 self
::buildThankYouBlock($this);
284 parent
::buildQuickForm();
288 * Build Registration Block.
290 * @param CRM_Core_Form $form
293 public function buildRegistrationBlock(&$form) {
294 $attributes = CRM_Core_DAO
::getAttribute('CRM_Event_DAO_Event', 'intro_text') +
['class' => 'collapsed', 'preset' => 'civievent'];
295 $form->add('wysiwyg', 'intro_text', ts('Introductory Text'), $attributes);
296 $form->add('wysiwyg', 'footer_text', ts('Footer Text'), $attributes);
298 extract(self
::getProfileSelectorTypes());
300 $form->addProfileSelector('custom_pre_id', ts('Include Profile') . '<br />' . ts('(top of page)'), $allowCoreTypes, $allowSubTypes, $profileEntities, TRUE, $usedFor);
301 $form->addProfileSelector('custom_post_id', ts('Include Profile') . '<br />' . ts('(bottom of page)'), $allowCoreTypes, $allowSubTypes, $profileEntities, TRUE, $usedFor);
303 $form->addProfileSelector('additional_custom_pre_id', ts('Profile for Additional Participants') . '<br />' . ts('(top of page)'), $allowCoreTypes, $allowSubTypes, $profileEntities, TRUE, $usedFor);
304 $form->addProfileSelector('additional_custom_post_id', ts('Profile for Additional Participants') . '<br />' . ts('(bottom of page)'), $allowCoreTypes, $allowSubTypes, $profileEntities, TRUE, $usedFor);
308 * Subroutine to insert a Profile Editor widget.
309 * depends on getProfileSelectorTypes
311 * @param array &$form
314 * @param string $prefix
315 * Dom element ID prefix.
316 * @param string $label
318 * @param array $configs
319 * Optional, for addProfileSelector(), defaults to using getProfileSelectorTypes().
321 public function buildMultipleProfileBottom(&$form, $count, $prefix = '', $label = 'Include Profile', $configs = NULL) {
322 extract((is_null($configs)) ? self
::getProfileSelectorTypes() : $configs);
323 $element = $prefix . "custom_post_id_multiple[$count]";
324 $label .= '<br />' . ts('(bottom of page)');
325 $form->addProfileSelector($element, $label, $allowCoreTypes, $allowSubTypes, $profileEntities, TRUE, $usedFor);
329 * Create initializers for addprofileSelector.
332 * ['allowCoreTypes' => array, 'allowSubTypes' => array, 'profileEntities' => array]
334 public static function getProfileSelectorTypes() {
336 'allowCoreTypes' => [],
337 'allowSubTypes' => [],
338 'profileEntities' => [],
342 $configs['allowCoreTypes'] = array_merge([
345 ], CRM_Contact_BAO_ContactType
::subTypes('Individual'));
346 $configs['allowCoreTypes'][] = 'Participant';
347 if (CRM_Core_Permission
::check('manage event profiles') && !CRM_Core_Permission
::check('administer CiviCRM')) {
348 $configs['usedFor'][] = 'CiviEvent';
351 $id = CRM_Utils_Request
::retrieve('id', 'Integer');
353 $participantEventType = CRM_Core_DAO
::getFieldValue("CRM_Event_DAO_Event", $id, 'event_type_id', 'id');
354 $participantRole = CRM_Core_DAO
::getFieldValue('CRM_Event_DAO_Event', $id, 'default_role_id');
355 $configs['allowSubTypes']['ParticipantEventName'] = [$id];
356 $configs['allowSubTypes']['ParticipantEventType'] = [$participantEventType];
357 $configs['allowSubTypes']['ParticipantRole'] = [$participantRole];
359 $configs['profileEntities'][] = ['entity_name' => 'contact_1', 'entity_type' => 'IndividualModel'];
360 $configs['profileEntities'][] = [
361 'entity_name' => 'participant_1',
362 'entity_type' => 'ParticipantModel',
363 'entity_sub_type' => '*',
370 * Build Confirmation Block.
372 * @param CRM_Core_Form $form
375 public function buildConfirmationBlock(&$form) {
376 $attributes = CRM_Core_DAO
::getAttribute('CRM_Event_DAO_Event');
377 // CRM-11182 - Optional confirmation page for free events
378 $is_monetary = CRM_Core_DAO
::getFieldValue('CRM_Event_DAO_Event', $form->_id
, 'is_monetary');
379 $form->assign('is_monetary', $is_monetary);
380 if ($is_monetary == "0") {
381 $form->addYesNo('is_confirm_enabled', ts('Use a confirmation screen?'), NULL, NULL, ['onclick' => "return showHideByValue('is_confirm_enabled','','confirm_screen_settings','block','radio',false);"]);
383 $form->add('text', 'confirm_title', ts('Title'), $attributes['confirm_title']);
384 $form->add('wysiwyg', 'confirm_text', ts('Introductory Text'), $attributes['confirm_text'] +
['class' => 'collapsed', 'preset' => 'civievent']);
385 $form->add('wysiwyg', 'confirm_footer_text', ts('Footer Text'), $attributes['confirm_text'] +
['class' => 'collapsed', 'preset' => 'civievent']);
391 * @param CRM_Core_Form $form
394 public function buildMailBlock(&$form) {
395 $form->registerRule('emailList', 'callback', 'emailList', 'CRM_Utils_Rule');
396 $attributes = CRM_Core_DAO
::getAttribute('CRM_Event_DAO_Event');
397 $form->addYesNo('is_email_confirm', ts('Send Confirmation Email?'), NULL, NULL, ['onclick' => "return showHideByValue('is_email_confirm','','confirmEmail','block','radio',false);"]);
398 $form->add('textarea', 'confirm_email_text', ts('Text'), $attributes['confirm_email_text']);
399 $form->add('text', 'cc_confirm', ts('CC Confirmation To'), CRM_Core_DAO
::getAttribute('CRM_Event_DAO_Event', 'cc_confirm'));
400 $form->addRule('cc_confirm', ts('Please enter a valid list of comma delimited email addresses'), 'emailList');
401 $form->add('text', 'bcc_confirm', ts('BCC Confirmation To'), CRM_Core_DAO
::getAttribute('CRM_Event_DAO_Event', 'bcc_confirm'));
402 $form->addRule('bcc_confirm', ts('Please enter a valid list of comma delimited email addresses'), 'emailList');
403 $form->add('text', 'confirm_from_name', ts('Confirm From Name'));
404 $form->add('text', 'confirm_from_email', ts('Confirm From Email'));
405 $form->addRule('confirm_from_email', ts('Email is not valid.'), 'email');
409 * @param CRM_Core_Form $form
411 public function buildThankYouBlock(&$form) {
412 $attributes = CRM_Core_DAO
::getAttribute('CRM_Event_DAO_Event');
413 $form->add('text', 'thankyou_title', ts('Title'), $attributes['thankyou_title']);
414 $form->add('wysiwyg', 'thankyou_text', ts('Introductory Text'), $attributes['thankyou_text'] +
['class' => 'collapsed', 'preset' => 'civievent']);
415 $form->add('wysiwyg', 'thankyou_footer_text', ts('Footer Text'), $attributes['thankyou_text'] +
['class' => 'collapsed', 'preset' => 'civievent']);
419 * Add local and global form rules.
424 public function addRules() {
425 if ($this->_addProfileBottom ||
$this->_addProfileBottomAdd
) {
428 $this->addFormRule(['CRM_Event_Form_ManageEvent_Registration', 'formRule'], $this);
432 * Global validation rules for the form.
434 * @param array $values
436 * @param CRM_Core_Form $form
439 * list of errors to be posted back to the form
441 public static function formRule($values, $files, $form) {
442 if (!empty($values['is_online_registration'])) {
444 if (!$values['confirm_title']) {
445 $errorMsg['confirm_title'] = ts('Please enter a Title for the registration Confirmation Page');
447 if (!$values['thankyou_title']) {
448 $errorMsg['thankyou_title'] = ts('Please enter a Title for the registration Thank-you Page');
450 if ($values['is_email_confirm']) {
451 if (!$values['confirm_from_name']) {
452 $errorMsg['confirm_from_name'] = ts('Please enter Confirmation Email FROM Name.');
455 if (!$values['confirm_from_email']) {
456 $errorMsg['confirm_from_email'] = ts('Please enter Confirmation Email FROM Email Address.');
460 if (isset($values['registration_start_date']) && isset($values['registration_end_date'])) {
461 if ($values['registration_end_date'] < $values['registration_start_date']) {
462 $errorMsg['registration_end_date'] = ts('Registration end date should be after Registration start date');
466 //check that the selected profiles have either firstname+lastname or email required
468 CRM_Utils_Array
::value('custom_pre_id', $values),
469 CRM_Utils_Array
::value('custom_post_id', $values),
471 $additionalProfileIds = [
472 CRM_Utils_Array
::value('additional_custom_pre_id', $values),
473 CRM_Utils_Array
::value('additional_custom_post_id', $values),
475 //additional profile fields default to main if not set
476 if (!is_numeric($additionalProfileIds[0])) {
477 $additionalProfileIds[0] = $profileIds[0];
479 if (!is_numeric($additionalProfileIds[1])) {
480 $additionalProfileIds[1] = $profileIds[1];
482 //add multiple profiles if set
483 self
::addMultipleProfiles($profileIds, $values, 'custom_post_id_multiple');
484 self
::addMultipleProfiles($additionalProfileIds, $values, 'additional_custom_post_id_multiple');
485 $isProfileComplete = self
::isProfileComplete($profileIds);
486 $isAdditionalProfileComplete = self
::isProfileComplete($additionalProfileIds);
488 //Check main profiles have an email address available if 'send confirmation email' is selected
489 if ($values['is_email_confirm']) {
490 $emailFields = self
::getEmailFields($profileIds);
491 if (!count($emailFields)) {
492 $errorMsg['is_email_confirm'] = ts("Please add a profile with an email address if 'Send Confirmation Email?' is selected");
495 $additionalCustomPreId = $additionalCustomPostId = NULL;
496 $isPreError = $isPostError = TRUE;
497 if (!empty($values['allow_same_participant_emails']) && !empty($values['is_multiple_registrations'])) {
498 $types = array_merge(['Individual'], CRM_Contact_BAO_ContactType
::subTypes('Individual'));
499 $profiles = CRM_Core_BAO_UFGroup
::getProfiles($types);
501 //check for additional custom pre profile
502 $additionalCustomPreId = $values['additional_custom_pre_id'] ??
NULL;
503 if (!empty($additionalCustomPreId)) {
504 if (!($additionalCustomPreId == 'none')) {
505 $customPreId = $additionalCustomPreId;
512 $customPreId = !empty($values['custom_pre_id']) ?
$values['custom_pre_id'] : NULL;
514 //check whether the additional custom pre profile is of type 'Individual' and its subtypes
515 if (!empty($customPreId)) {
516 $profileTypes = CRM_Core_BAO_UFGroup
::profileGroups($customPreId);
517 foreach ($types as $individualTypes) {
518 if (in_array($individualTypes, $profileTypes)) {
528 // We don't have required Individual fields in the pre-custom profile, so now check the post-custom profile
530 $additionalCustomPostId = $values['additional_custom_post_id'] ??
NULL;
531 if (!empty($additionalCustomPostId)) {
532 if (!($additionalCustomPostId == 'none')) {
533 $customPostId = $additionalCustomPostId;
536 $isPostError = FALSE;
540 $customPostId = !empty($values['custom_post_id']) ?
$values['custom_post_id'] : NULL;
542 //check whether the additional custom post profile is of type 'Individual' and its subtypes
543 if (!empty($customPostId)) {
544 $profileTypes = CRM_Core_BAO_UFGroup
::profileGroups($customPostId);
545 foreach ($types as $individualTypes) {
546 if (in_array($individualTypes, $profileTypes)) {
547 $isPostError = FALSE;
553 $isPostError = FALSE;
556 if (empty($customPreId) && empty($customPostId)) {
557 $errorMsg['additional_custom_pre_id'] = ts("Allow multiple registrations from the same email address requires a profile of type 'Individual'");
560 $errorMsg['additional_custom_post_id'] = ts("Allow multiple registrations from the same email address requires a profile of type 'Individual'");
564 if (!$isProfileComplete) {
565 $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.");
567 if (!$isAdditionalProfileComplete) {
568 $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.");
572 // $config = CRM_Core_Config::singleton();
573 // if ( $config->doNotAttachPDFReceipt ) {
574 // if (!empty($values['custom_post_id_multiple'])) {
575 // foreach( $values['custom_post_id_multiple'] as $count => $customPostMultiple ) {
576 // if ( $customPostMultiple ) {
577 // $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' ) ) );
583 // if (!empty($values['is_multiple_registrations']) &&
584 // CRM_Utils_Array::value('additional_custom_post_id_multiple', $values) ) {
585 // foreach( $values['additional_custom_post_id_multiple'] as $count => $customPostMultiple ) {
586 // if ( $customPostMultiple ) {
587 // $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' ) ) );
594 if (!empty($errorMsg)) {
595 if (!empty($values['custom_post_id_multiple'])) {
596 foreach ($values['custom_post_id_multiple'] as $count => $customPostMultiple) {
597 self
::buildMultipleProfileBottom($form, $count);
599 $form->assign('profilePostMultiple', $values['custom_post_id_multiple']);
601 if (!empty($values['additional_custom_post_id_multiple'])) {
602 foreach ($values['additional_custom_post_id_multiple'] as $count => $customPostMultiple) {
603 self
::buildMultipleProfileBottom($form, $count, 'additional_', ts('Profile for Additional Participants'));
605 $form->assign('profilePostMultipleAdd', $values['additional_custom_post_id_multiple']);
610 if (!empty($errorMsg)) {
618 * Collect all email fields for an array of profile ids.
623 public static function getEmailFields($profileIds) {
625 foreach ($profileIds as $profileId) {
626 if ($profileId && is_numeric($profileId)) {
627 $fields = CRM_Core_BAO_UFGroup
::getFields($profileId);
628 foreach ($fields as $field) {
629 if (substr_count($field['name'], 'email')) {
630 $emailFields[] = $field;
639 * Check if a profile contains required fields.
644 public static function isProfileComplete($profileIds) {
645 $profileReqFields = [];
646 foreach ($profileIds as $profileId) {
647 if ($profileId && is_numeric($profileId)) {
648 $fields = CRM_Core_BAO_UFGroup
::getFields($profileId);
649 foreach ($fields as $field) {
651 case substr_count($field['name'], 'email'):
652 $profileReqFields[] = 'email';
655 case substr_count($field['name'], 'first_name'):
656 $profileReqFields[] = 'first_name';
659 case substr_count($field['name'], 'last_name'):
660 $profileReqFields[] = 'last_name';
666 $profileComplete = (in_array('email', $profileReqFields)
667 ||
(in_array('first_name', $profileReqFields) && in_array('last_name', $profileReqFields))
669 return $profileComplete;
673 * Check if the profiles collect enough information to dedupe.
679 public static function canProfilesDedupe($profileIds, $rgId = 0) {
680 // find the unsupervised rule
682 'used' => 'Unsupervised',
683 'contact_type' => 'Individual',
686 $rgParams['id'] = $rgId;
688 $activeRg = CRM_Dedupe_BAO_RuleGroup
::dedupeRuleFieldsWeight($rgParams);
690 // get the combinations that could be a match for the rule
691 $okCombos = $combos = [];
692 CRM_Dedupe_BAO_RuleGroup
::combos($activeRg[0], $activeRg[1], $combos);
694 // create an index of what combinations involve each field
696 foreach ($combos as $comboid => $combo) {
697 foreach ($combo as $cfield) {
698 $index[$cfield][$comboid] = TRUE;
700 $combos[$comboid] = array_fill_keys($combo, 0);
701 $okCombos[$comboid] = array_fill_keys($combo, 2);
704 // get profiles and see if they have the necessary combos
705 $profileReqFields = [];
706 foreach ($profileIds as $profileId) {
707 if ($profileId && is_numeric($profileId)) {
708 $fields = CRM_Core_BAO_UFGroup
::getFields($profileId);
710 // walk through the fields in the profile
711 foreach ($fields as $field) {
713 // check each of the fields in the index against the profile field
714 foreach ($index as $ifield => $icombos) {
715 if (strpos($field['name'], $ifield) !== FALSE) {
717 // we found the field in the profile, now record it in the index
718 foreach ($icombos as $icombo => $dontcare) {
719 $combos[$icombo][$ifield] = ($combos[$icombo][$ifield] != 2 && !$field['is_required']) ?
1 : 2;
721 if ($combos[$icombo] == $okCombos[$icombo]) {
722 // if any combo is complete with 2s (all fields are present and required), we can go home
732 // check the combos to see if everything is > 0
733 foreach ($combos as $comboid => $combo) {
735 foreach ($combo as $cfield) {
740 // this combo isn't complete--skip to the next combo
749 // no combo succeeded
754 * Add additional profiles from the form to an array of profile ids.
756 * @param array $profileIds
757 * @param array $values
758 * @param string $field
760 public static function addMultipleProfiles(&$profileIds, $values, $field) {
761 if ($multipleProfiles = CRM_Utils_Array
::value($field, $values)) {
762 foreach ($multipleProfiles as $profileId) {
763 $profileIds[] = $profileId;
769 * Process the form submission.
774 public function postProcess() {
775 $params = $this->exportValues();
777 $params['id'] = $this->_id
;
780 $params['is_online_registration'] = CRM_Utils_Array
::value('is_online_registration', $params, FALSE);
782 $params['is_confirm_enabled'] = CRM_Utils_Array
::value('is_confirm_enabled', $params, FALSE);
783 $params['is_multiple_registrations'] = CRM_Utils_Array
::value('is_multiple_registrations', $params, FALSE);
784 $params['allow_same_participant_emails'] = CRM_Utils_Array
::value('allow_same_participant_emails', $params, FALSE);
785 $params['requires_approval'] = CRM_Utils_Array
::value('requires_approval', $params, FALSE);
787 // reset is_email confirm if not online reg
788 if (!$params['is_online_registration']) {
789 $params['is_email_confirm'] = FALSE;
791 if (!empty($params['allow_selfcancelxfer'])) {
792 $params['selfcancelxfer_time'] = !empty($params['selfcancelxfer_time']) ?
$params['selfcancelxfer_time'] : 0;
795 CRM_Event_BAO_Event
::add($params);
797 // also update the ProfileModule tables
800 'module' => 'CiviEvent',
801 'entity_table' => 'civicrm_event',
802 'entity_id' => $this->_id
,
805 // first delete all past entries
806 CRM_Core_BAO_UFJoin
::deleteAll($ufJoinParams);
810 if (!empty($params['custom_pre_id'])) {
811 $uf[1] = $params['custom_pre_id'];
815 if (!empty($params['custom_post_id'])) {
816 $uf[2] = $params['custom_post_id'];
819 if (!empty($params['custom_post_id_multiple'])) {
820 $uf = array_merge($uf, $params['custom_post_id_multiple']);
822 $uf = array_values($uf);
824 foreach ($uf as $weight => $ufGroupId) {
825 $ufJoinParams['weight'] = $weight +
$wt;
826 $ufJoinParams['uf_group_id'] = $ufGroupId;
827 CRM_Core_BAO_UFJoin
::create($ufJoinParams);
828 unset($ufJoinParams['id']);
831 // also update the ProfileModule tables
834 'module' => 'CiviEvent_Additional',
835 'entity_table' => 'civicrm_event',
836 'entity_id' => $this->_id
,
839 // first delete all past entries
840 CRM_Core_BAO_UFJoin
::deleteAll($ufJoinParamsAdd);
841 if (!empty($params['is_multiple_registrations'])) {
845 if (array_key_exists('additional_custom_pre_id', $params)) {
846 if (empty($params['additional_custom_pre_id'])) {
847 $ufAdd[1] = $params['custom_pre_id'];
850 elseif (CRM_Utils_Array
::value('additional_custom_pre_id', $params) == 'none') {
853 $ufAdd[1] = $params['additional_custom_pre_id'];
858 if (array_key_exists('additional_custom_post_id', $params)) {
859 if (empty($params['additional_custom_post_id'])) {
860 $ufAdd[2] = $params['custom_post_id'];
862 elseif (CRM_Utils_Array
::value('additional_custom_post_id', $params) == 'none') {
865 $ufAdd[2] = $params['additional_custom_post_id'];
869 if (!empty($params['additional_custom_post_id_multiple'])) {
870 $additionalPostMultiple = [];
871 foreach ($params['additional_custom_post_id_multiple'] as $key => $value) {
872 if (is_null($value) && !empty($params['custom_post_id'])) {
873 $additionalPostMultiple[$key] = $params['custom_post_id'];
875 elseif ($value == 'none') {
879 $additionalPostMultiple[$key] = $value;
882 $ufAdd = array_merge($ufAdd, $additionalPostMultiple);
885 $ufAdd = array_values($ufAdd);
886 if (!empty($ufAdd)) {
887 foreach ($ufAdd as $weightAdd => $ufGroupIdAdd) {
889 $ufJoinParamsAdd['weight'] = $weightAdd +
$wtAdd;
890 $ufJoinParamsAdd['uf_group_id'] = $ufGroupIdAdd;
892 CRM_Core_BAO_UFJoin
::create($ufJoinParamsAdd);
893 unset($ufJoinParamsAdd['id']);
898 // get the profiles to evaluate what they collect
900 CRM_Utils_Array
::value('custom_pre_id', $params),
901 CRM_Utils_Array
::value('custom_post_id', $params),
903 $additionalProfileIds = [
904 CRM_Utils_Array
::value('additional_custom_pre_id', $params),
905 CRM_Utils_Array
::value('additional_custom_post_id', $params),
907 // additional profile fields default to main if not set
908 if (!is_numeric($additionalProfileIds[0])) {
909 $additionalProfileIds[0] = $profileIds[0];
911 if (!is_numeric($additionalProfileIds[1])) {
912 $additionalProfileIds[1] = $profileIds[1];
914 //add multiple profiles if set
915 self
::addMultipleProfiles($profileIds, $params, 'custom_post_id_multiple');
916 self
::addMultipleProfiles($additionalProfileIds, $params, 'additional_custom_post_id_multiple');
919 $rgId = CRM_Utils_Array
::value('dedupe_rule_group_id', $params, 0);
921 switch (self
::canProfilesDedupe($profileIds, $rgId)) {
923 $dedupeTitle = 'Duplicate Matching Impossible';
924 $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.");
928 $dedupeTitle = 'Duplicate Contacts Possible';
929 $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.");
931 if (!empty($params['is_multiple_registrations'])) {
932 switch (self
::canProfilesDedupe($additionalProfileIds, $rgId)) {
934 $dedupeTitle = 'Duplicate Matching Impossible';
936 $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.");
939 $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.");
945 $dedupeTitle = 'Duplicate Contacts Possible';
946 $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.");
951 CRM_Core_Session
::setStatus($cantDedupe, $dedupeTitle, 'alert dedupenotify', ['expires' => 0]);
954 // Update tab "disabled" css class
955 $this->ajaxResponse
['tabValid'] = !empty($params['is_online_registration']);
957 parent
::endPostProcess();
961 * Return a descriptive name for the page, used in wizard header
965 public function getTitle() {
966 return ts('Online Registration');