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