From 3266ed622db4c1f45f5519e85df560d67b3c4ab5 Mon Sep 17 00:00:00 2001 From: Seamus Lee <seamuslee001@gmail.com> Date: Wed, 26 Jun 2024 13:35:11 +1000 Subject: [PATCH 1/4] Add in some defensive coding to avoid hard error, add in case for if members are in 30 day break or url parameter is set to not check the is_opt_out checkbox --- .../Form/EmailSubscriptionCentre.php | 53 ++++++++++--------- 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/CRM/Emailsubscriptioncentre/Form/EmailSubscriptionCentre.php b/CRM/Emailsubscriptioncentre/Form/EmailSubscriptionCentre.php index 9a79546..18fc0b5 100644 --- a/CRM/Emailsubscriptioncentre/Form/EmailSubscriptionCentre.php +++ b/CRM/Emailsubscriptioncentre/Form/EmailSubscriptionCentre.php @@ -41,13 +41,15 @@ class CRM_Emailsubscriptioncentre_Form_EmailSubscriptionCentre extends CRM_Core_ $managePreferecesOptions[] = $this->createElement('advCheckBox', 'constitutional', NULL, E::ts('Receive constitutionally required member emails'), ['class' => 'crm-form-checkbox form-check-inline']); $defaults['manage_your_preferences']['constitutional'] = 1; } - $defaults['manage_your_preferences']['opt_out'] = CRM_Core_DAO::singleValueQuery("SELECT is_opt_out FROM civicrm_contact WHERE id = %1", [1 => [$this->getContactID(), 'Positive']]); - $this->assign('display_name', CRM_Core_DAO::singleValueQuery("SELECT display_name FROM civicrm_contact WHERE id = %1", [1 => [$this->getContactID(), 'Positive']])); - $this->assign('current_email', CRM_Utils_String::maskEmail(CRM_Core_DAO::singleValueQuery("SELECT email FROM civicrm_email WHERE is_primary = 1 AND contact_id = %1", [1 => [$this->getContactID(), 'Positive']]) ?? '')); if (empty(Civi::settings()->get('emailsubscriptioncentre_break_group_id'))) { throw new \CRM_Core_Exception(E::ts('No 30 day break group set, Please contact your system administrator')); } + $is_opt_out = CRM_Core_DAO::singleValueQuery("SELECT is_opt_out FROM civicrm_contact WHERE id = %1 AND id", [1 => [$this->getContactID(), 'Positive']]); $breakGroupCheck = CRM_Core_DAO::singleValueQuery("SELECT group_id FROM civicrm_group_contact WHERE group_id = %2 AND contact_id = %1 AND status = 'Added'", [1 => [$this->getContactID(), 'Positive'], 2 => [Civi::settings()->get('emailsubscriptioncentre_break_group_id'), 'Integer']]); + $no_opt_out = CRM_Utils_Request::retrieveValue('nb', 'Boolean', 0); + $defaults['manage_your_preferences']['opt_out'] = ($is_opt_out && empty($breakGroupCheck) && empty($no_opt_out)) ? 1 : 0; + $this->assign('display_name', CRM_Core_DAO::singleValueQuery("SELECT display_name FROM civicrm_contact WHERE id = %1", [1 => [$this->getContactID(), 'Positive']])); + $this->assign('current_email', CRM_Utils_String::maskEmail(CRM_Core_DAO::singleValueQuery("SELECT email FROM civicrm_email WHERE is_primary = 1 AND contact_id = %1", [1 => [$this->getContactID(), 'Positive']]) ?? '')); $defaults['manage_your_preferences']['break'] = !empty($breakGroupCheck) ? 1 : 0; $this->addGroup($managePreferecesOptions, 'manage_your_preferences', E::ts('Manage Your Preferences'), '<br />'); $sections = OptionValue::get(FALSE) @@ -58,12 +60,6 @@ class CRM_Emailsubscriptioncentre_Form_EmailSubscriptionCentre extends CRM_Core_ foreach ($sections as $section) { $sectionTitles[$section['id']] = $section['label']; $sectionProperties = SubscriptionSections::get(FALSE)->addWhere('section_id', '=', $section['id'])->execute()->first(); - if ($sectionProperties['is_inclusive']) { - $inclusiveSections[] = $section['id']; - } - if ($sectionProperties['start_column']) { - $columnSectionStarts[] = $section['id']; - } $options = MailingSubscriptionCentre::get(FALSE) ->addSelect('group_id.id') ->addSelect('group_id.frontend_title') @@ -76,20 +72,27 @@ class CRM_Emailsubscriptioncentre_Form_EmailSubscriptionCentre extends CRM_Core_ $sectionOptions[] = $this->createElement('advcheckbox', $option['group_id.id'], NULL, $option['group_id.frontend_title'], ['class' => 'crm-form-checkbox form-check-inline']); $sectionGroupIds[] = $option['group_id.id']; } - - $groupMembership = CRM_Core_DAO::executeQuery("SELECT group_id FROM civicrm_group_contact WHERE group_id IN (%1) AND status = 'Added' AND contact_id = %2", [ - 1 => [implode(',', $sectionGroupIds), 'CommaSeparatedIntegers'], - 2 => [$this->getContactID(), 'Integer'], - ]); - $defaults['section_' . $section['id']] = []; - while ($groupMembership->fetch()) { - $this->contactGroups[] = $groupMembership->group_id; - $defaults['section_' . $section['id']][$groupMembership->group_id] = 1; + if (!empty($sectionGroupIds)) { + $groupMembership = CRM_Core_DAO::executeQuery("SELECT group_id FROM civicrm_group_contact WHERE group_id IN (%1) AND status = 'Added' AND contact_id = %2", [ + 1 => [implode(',', $sectionGroupIds), 'CommaSeparatedIntegers'], + 2 => [$this->getContactID(), 'Integer'], + ]); + $defaults['section_' . $section['id']] = []; + while ($groupMembership->fetch()) { + $this->contactGroups[] = $groupMembership->group_id; + $defaults['section_' . $section['id']][$groupMembership->group_id] = 1; + } + $this->addGroup($sectionOptions, 'section_' . $section['id'], $section['label'], '<br />'); + if ($sectionProperties['is_inclusive']) { + $inclusiveSections[] = $section['id']; + } + if ($sectionProperties['start_column']) { + $columnSectionStarts[] = $section['id']; + } } - $this->addGroup($sectionOptions, 'section_' . $section['id'], $section['label'], '<br />'); } $notYouUrlSetting = Civi::settings()->get('emailsubscriptioncentre_not_you_url_redirect'); - $this->assign('not_you_url', (!empty($notYouUrlSetting) ? $notYouUrlSetting: CRM_Utils_System::url('/', '', TRUE, NULL, FALSE, TRUE))); + $this->assign('not_you_url', (!empty($notYouUrlSetting) ? $notYouUrlSetting : CRM_Utils_System::url('/', '', TRUE, NULL, FALSE, TRUE))); $this->assign('sectionTitles', $sectionTitles); $this->assign('columnSectionStarts', $columnSectionStarts); $this->add('text', 'primary_email_update', E::ts('Update your primary email address')); @@ -122,11 +125,11 @@ class CRM_Emailsubscriptioncentre_Form_EmailSubscriptionCentre extends CRM_Core_ } if ($fieldName === 'manage_your_preferences') { foreach ($value as $option => $selected) { + $inGroup = CRM_Core_DAO::singleValueQuery("SELECT group_id FROM civicrm_group_contact WHERE group_id = %1 AND status = 'Added' AND contact_id = %2", [ + 1 => [Civi::settings()->get('emailsubscriptioncentre_break_group_id'), 'Integer'], + 2 => [$this->getContactID(), 'Integer'], + ]); if ($option === 'break') { - $inGroup = CRM_Core_DAO::singleValueQuery("SELECT group_id FROM civicrm_group_contact WHERE group_id = %1 AND status = 'Added' AND contact_id = %2", [ - 1 => [Civi::settings()->get('emailsubscriptioncentre_break_group_id'), 'Integer'], - 2 => [$this->getContactID(), 'Integer'], - ]); if ($inGroup || !empty($selected)) { GroupContact::save(FALSE) ->addRecord([ @@ -141,7 +144,7 @@ class CRM_Emailsubscriptioncentre_Form_EmailSubscriptionCentre extends CRM_Core_ ->execute(); } } - elseif ($option === 'opt_out') { + elseif ($option === 'opt_out' && empty($inGroup) && empty($value['break'])) { Contact::update(FALSE)->addValue('is_opt_out', (!empty($selected) ? 1 : 0))->addWhere('id', '=', $this->getContactID())->execute(); } } -- GitLab From 235f649091d06633c2b63ea7df2e3c1c394ad7c3 Mon Sep 17 00:00:00 2001 From: Seamus Lee <seamuslee001@gmail.com> Date: Wed, 26 Jun 2024 16:13:30 +1000 Subject: [PATCH 2/4] Visually hide the 30 day break or the is opt out checkbox is one is set and ensure that the consituttional checkbox looks more disabled and add in a checksum to redirect to the thank you page so we can present an update preferences Url on the thank you page as per Laurence and modify url parameter as per John --- .../Form/EmailSubscriptionCentre.php | 6 ++-- .../Page/SubscriptionCentreThankYou.php | 9 ++++++ js/EmailSubscriptionCentre.js | 32 ++++++++++++++++++- .../Page/SubscriptionCentreThankYou.tpl | 3 ++ 4 files changed, 46 insertions(+), 4 deletions(-) diff --git a/CRM/Emailsubscriptioncentre/Form/EmailSubscriptionCentre.php b/CRM/Emailsubscriptioncentre/Form/EmailSubscriptionCentre.php index 18fc0b5..93ad81e 100644 --- a/CRM/Emailsubscriptioncentre/Form/EmailSubscriptionCentre.php +++ b/CRM/Emailsubscriptioncentre/Form/EmailSubscriptionCentre.php @@ -46,7 +46,7 @@ class CRM_Emailsubscriptioncentre_Form_EmailSubscriptionCentre extends CRM_Core_ } $is_opt_out = CRM_Core_DAO::singleValueQuery("SELECT is_opt_out FROM civicrm_contact WHERE id = %1 AND id", [1 => [$this->getContactID(), 'Positive']]); $breakGroupCheck = CRM_Core_DAO::singleValueQuery("SELECT group_id FROM civicrm_group_contact WHERE group_id = %2 AND contact_id = %1 AND status = 'Added'", [1 => [$this->getContactID(), 'Positive'], 2 => [Civi::settings()->get('emailsubscriptioncentre_break_group_id'), 'Integer']]); - $no_opt_out = CRM_Utils_Request::retrieveValue('nb', 'Boolean', 0); + $no_opt_out = CRM_Utils_Request::retrieveValue('n', 'Boolean', 0); $defaults['manage_your_preferences']['opt_out'] = ($is_opt_out && empty($breakGroupCheck) && empty($no_opt_out)) ? 1 : 0; $this->assign('display_name', CRM_Core_DAO::singleValueQuery("SELECT display_name FROM civicrm_contact WHERE id = %1", [1 => [$this->getContactID(), 'Positive']])); $this->assign('current_email', CRM_Utils_String::maskEmail(CRM_Core_DAO::singleValueQuery("SELECT email FROM civicrm_email WHERE is_primary = 1 AND contact_id = %1", [1 => [$this->getContactID(), 'Positive']]) ?? '')); @@ -144,7 +144,7 @@ class CRM_Emailsubscriptioncentre_Form_EmailSubscriptionCentre extends CRM_Core_ ->execute(); } } - elseif ($option === 'opt_out' && empty($inGroup) && empty($value['break'])) { + elseif ($option === 'opt_out' && empty($value['break'])) { Contact::update(FALSE)->addValue('is_opt_out', (!empty($selected) ? 1 : 0))->addWhere('id', '=', $this->getContactID())->execute(); } } @@ -168,7 +168,7 @@ class CRM_Emailsubscriptioncentre_Form_EmailSubscriptionCentre extends CRM_Core_ } } CRM_Core_Session::setStatus(E::ts('Your Subscription requests have been saved')); - CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/email-subscription-centre/thank-you', [], TRUE, NULL, TRUE, TRUE)); + CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/email-subscription-centre/thank-you', ['cid' => $this->getContactID(), 'cs' => CRM_Contact_BAO_Contact_Utils::generateChecksum($this->getContactID())], TRUE, NULL, TRUE, TRUE)); parent::postProcess(); } diff --git a/CRM/Emailsubscriptioncentre/Page/SubscriptionCentreThankYou.php b/CRM/Emailsubscriptioncentre/Page/SubscriptionCentreThankYou.php index 7cb62f8..3104dac 100644 --- a/CRM/Emailsubscriptioncentre/Page/SubscriptionCentreThankYou.php +++ b/CRM/Emailsubscriptioncentre/Page/SubscriptionCentreThankYou.php @@ -4,6 +4,15 @@ use CRM_Emailsubscriptioncentre_ExtensionUtil as E; class CRM_Emailsubscriptioncentre_Page_SubscriptionCentreThankYou extends CRM_Core_Page { public function run() { + $cid = CRM_Utils_Request::retrieveValue('cid', 'Positive'); + $cs = CRM_Utils_Request::retrieveValue('cs', 'String'); + if (!empty($cid) && !empty($cs)) { + CRM_Contact_BAO_Contact_Utils::validChecksum($cid, $cs); + $this->assign('preferencesURL', CRM_Utils_System::url('civicrm/email-subscription-centre', ['cid' => $cid, 'cs' => CRM_Contact_BAO_Contact_Utils::generateChecksum($cid)], TRUE, NULL, TRUE, TRUE)); + } + else { + $this->assign('preferencesURL', FALSE); + } // Example: Set the page-title dynamically; alternatively, declare a static title in xml/Menu/*.xml CRM_Utils_System::setTitle(Civi::settings()->get('emailsubscriptioncentre_thank_you_title') ?? 'Subscription Centre Settings Saved'); diff --git a/js/EmailSubscriptionCentre.js b/js/EmailSubscriptionCentre.js index a42ea4a..1f9d2c2 100644 --- a/js/EmailSubscriptionCentre.js +++ b/js/EmailSubscriptionCentre.js @@ -4,12 +4,42 @@ $('label[for=' + elementId + ']').addClass('form-check-label'); }); if (CRM.vars.emailsubscriptioncentre.isMember) { - $('#manage_your_preferences_constitutional').addClass('emailsubcription-checkbox-disabled'); + $('#manage_your_preferences_constitutional').addClass('emailsubcription-checkbox-disabled').prop('disabled'); $('label[for=manage_your_preferences_constitutional]').addClass('emailsubcription-checkbox-disabled'); $('#manage_your_preferences_constitutional').on('click', function(event) { event.preventDefault(); }); } + let opt_out_field_id = 'manage_your_preferences_opt_out'; + let break_field_id = 'manage_your_preferences_break'; + if ($('#' + opt_out_field_id).prop('checked')) { + $('#' + break_field_id).hide(); + $('label[for=' + break_field_id + ']').hide(); + } + else if ($('#' + break_field_id).prop('checked')) { + $('#' + opt_out_field_id).hide(); + $('label[for=' + opt_out_field_id + ']').hide(); + } + $('#' + opt_out_field_id).on('change', function() { + if ($(this).prop('checked')) { + $('#' + break_field_id).hide().prop('checked', false).trigger('change'); + $('label[for=' + break_field_id + ']').hide(); + } + else { + $('label[for=' + break_field_id + ']').show(); + $('#' + break_field_id).show(); + } + }); + $('#' + break_field_id).on('change', function() { + if ($(this).prop('checked')) { + $('#' + opt_out_field_id).hide().prop('checked', false).trigger('change'); + $('label[for=' + opt_out_field_id + ']').hide(); + } + else { + $('label[for=' + opt_out_field_id + ']').show(); + $('#' + opt_out_field_id).show(); + } + }); let sections = CRM.vars.emailsubscriptioncentre.inclusive_sections; sections.forEach(function (id, element) { $('.email-subscription-centre-' + id).find('input').on('change', function() { diff --git a/templates/CRM/Emailsubscriptioncentre/Page/SubscriptionCentreThankYou.tpl b/templates/CRM/Emailsubscriptioncentre/Page/SubscriptionCentreThankYou.tpl index e27f215..0cf71be 100644 --- a/templates/CRM/Emailsubscriptioncentre/Page/SubscriptionCentreThankYou.tpl +++ b/templates/CRM/Emailsubscriptioncentre/Page/SubscriptionCentreThankYou.tpl @@ -2,6 +2,9 @@ <div class="row"> <div class="col-md-12 pt-2"> {$thankYouMessage} + {if $preferencesURL} + <p>{ts 1='href="{$preferencesURL}">'}You can always <a %1>change your preferences</a>{/ts} + {/if} </div> </div> </div> \ No newline at end of file -- GitLab From 64ba58a55d3a90846b8e8243f3a2fc11901a6359 Mon Sep 17 00:00:00 2001 From: Seamus Lee <seamuslee001@gmail.com> Date: Wed, 26 Jun 2024 16:56:52 +1000 Subject: [PATCH 3/4] Ensure disabled prop is set to true --- js/EmailSubscriptionCentre.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/EmailSubscriptionCentre.js b/js/EmailSubscriptionCentre.js index 1f9d2c2..48ee8b7 100644 --- a/js/EmailSubscriptionCentre.js +++ b/js/EmailSubscriptionCentre.js @@ -4,7 +4,7 @@ $('label[for=' + elementId + ']').addClass('form-check-label'); }); if (CRM.vars.emailsubscriptioncentre.isMember) { - $('#manage_your_preferences_constitutional').addClass('emailsubcription-checkbox-disabled').prop('disabled'); + $('#manage_your_preferences_constitutional').addClass('emailsubcription-checkbox-disabled').prop('disabled', true); $('label[for=manage_your_preferences_constitutional]').addClass('emailsubcription-checkbox-disabled'); $('#manage_your_preferences_constitutional').on('click', function(event) { event.preventDefault(); -- GitLab From b779537e98f9e5dc786fc9f9115ac50444061180 Mon Sep 17 00:00:00 2001 From: Seamus Lee <seamuslee001@gmail.com> Date: Wed, 26 Jun 2024 17:03:41 +1000 Subject: [PATCH 4/4] Fix generating preferences url in thank you page --- .../Page/SubscriptionCentreThankYou.tpl | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/templates/CRM/Emailsubscriptioncentre/Page/SubscriptionCentreThankYou.tpl b/templates/CRM/Emailsubscriptioncentre/Page/SubscriptionCentreThankYou.tpl index 0cf71be..2142315 100644 --- a/templates/CRM/Emailsubscriptioncentre/Page/SubscriptionCentreThankYou.tpl +++ b/templates/CRM/Emailsubscriptioncentre/Page/SubscriptionCentreThankYou.tpl @@ -1,10 +1,13 @@ +{crmScope extension="emailsubscriptioncentre"} <div class="container"> <div class="row"> <div class="col-md-12 pt-2"> {$thankYouMessage} {if $preferencesURL} - <p>{ts 1='href="{$preferencesURL}">'}You can always <a %1>change your preferences</a>{/ts} + {capture assign="preferenceHref"}href="{$preferencesURL}"{/capture} + <p>{ts 1=$preferenceHref}You can always <a %1>change your preferences</a>{/ts} {/if} </div> </div> -</div> \ No newline at end of file +</div> +{/crmScope} \ No newline at end of file -- GitLab