Filter groups according to included profiles
authorAndrew Engelbrecht <andrew@fsf.org>
Mon, 25 Sep 2017 22:34:51 +0000 (18:34 -0400)
committerMichael McMahon <michael@fsf.org>
Thu, 7 Sep 2023 18:14:58 +0000 (14:14 -0400)
This is a continuation of the contact groups filtering feature, which
allows admins to filter the public listings of contact groups on various
Civi pages by setting a Drupal variable with drush.

It is now possible to set a rule for a profile and for that rule to
automatically apply to standalone profile pages, contribution pages that
include the profile, and event pages that include it as well.

See comments in CRM/Contact/Form/Edit/TagsAndGroups.php for instructions
on how to set the variable via drush.

CRM/Contact/Form/Edit/TagsAndGroups.php
CRM/Contribute/Form/Contribution/Confirm.php
CRM/Event/Form/Registration/Confirm.php
CRM/Profile/Form.php

index cac0823d02c05b54fb6b7323a417f490417c14ab..14ad05c8af93489de7ab477b48721d6e62369e99 100644 (file)
@@ -101,19 +101,26 @@ class CRM_Contact_Form_Edit_TagsAndGroups {
         //
         // To set the variable, use the following method:
         //
-        // $ drush vset --format=string groups_field_filters "{'profile': {'468': [25, 41]}, 'contribution': {'14': [25, 41]}, 'event': {'49': [25, 41]}}"
+        // $ drush vset --format=string groups_field_filters '
+        // {
+        //     "profile": {
+        //         "468": {
+        //             "groups": [41, 25],
+        //             "titles": ["Yes, sign me up!", "Sign me up to the other group!"]
+        //         }
+        //     },
+        // }'
         //
         // The "string" format must be used and not the "json" format.
         // Otherwise the json will be converted to a PHP array, which will not
         // work with this code.
         //
-        // The string contains json text, with the first level referring to
-        // page type, then the page number, then the list of ids of groups to
-        // display on that page.
         //
-        // 'profile' is for standalone profiles. If the profile is embedded in
-        // a contrib or event page, then the id of the contrib or event page
-        // must be added to the string.
+        // The string contains json text, with the first level referring to
+        // profiles, then the profile number, then the list of ids of groups to
+        // display on that page and optional replacement titles for those
+        // groups.
+
 
         // Find the list of groups that we want to let pass through a filter on
         // a given profile or page. If there is no filter for that page, then
@@ -122,27 +129,34 @@ class CRM_Contact_Form_Edit_TagsAndGroups {
         $groups_field_filters = json_decode(variable_get('groups_field_filters', NULL), $assoc = TRUE);
 
         $form_class_name = get_class($form);
-
-        // this commented line is useful for printing class names for future use in the switch statement below:
-        //watchdog("hacking", "foo message (form class): " . $form_class_name, NULL, WATCHDOG_ALERT);
-
         switch ($form_class_name) {
 
           case 'CRM_Profile_Form_Edit':
-            $page_id = $form->get('gid'); // gid, not id
-            $filter_config = $groups_field_filters['profile'][strval($page_id)];
+            $profile_id = $form->get('gid'); // gid, not id
+            $filter_config = $groups_field_filters['profile'][strval($profile_id)];
             break;
 
-          case 'CRM_Contribute_Form_Contribution_Main':
-          case 'CRM_Contribute_Form_Contribution_Confirm':
-          case 'CRM_Contribute_Form_Contribution_ThankYou':
-            $page_id = $form->get('id'); // id, not gid
-            $filter_config = $groups_field_filters['contribution'][strval($page_id)];
-            break;
+          default:
+            foreach (['custom_pre_id', 'custom_post_id'] as $which_profile) {
 
-          case 'CRM_Event_Form_Registration_Register':
-            $page_id = $form->get('id'); // id, not gid
-            $filter_config = $groups_field_filters['event'][strval($page_id)];
+              $profile_ids = $form->get('values')[$which_profile];
+
+              // some pages can have multiple profiles
+              if (!is_array($profile_ids)) {
+                $all_profile_ids[] = $profile_ids;
+              } else {
+                $all_profile_ids = array_merge($all_profile_ids, $profile_ids);
+              }
+            }
+
+            foreach ($all_profile_ids as $profile_id) {
+              $possible_filter = $groups_field_filters['profile'][strval($profile_id)];
+
+              if (isset($possible_filter)) {
+                $filter_config = $possible_filter;
+                break;
+              }
+            }
             break;
         }
 
@@ -302,26 +316,33 @@ class CRM_Contact_Form_Edit_TagsAndGroups {
     }
   }
 
-  /** re-add groups selectively filtered by sudoman's hack
+  /** re-add groups selectively filtered out by sudoman's hack
    *
    * the sudoman hack continues from above and from calls to this function.
    *
    * re-add any filtered-out groups if the contact is already in those groups
    * so createProfileContact() doesn't remove group memberships.
    *
-   * @param int     $page_id (page number)
-   * @param string  $page_type ('profile', 'contribution' or 'event')
+   * @param array   $profile_ids (ids of profiles in use on page)
    * @param int     $contactID (id of contact)
    * @param bool    $ignorePermission (passed to getContactGroup, often TRUE)
-   * @param array   $params (for parameters)
+   * @param array   $params (form parameters)
    *
    * @return array  $params (modified parameters: active groups that were filtered are inserted)
    */
-  public static function reInsertFilteredGroupMemberships($page_id, $page_type,
+  public static function reInsertFilteredGroupMemberships($profile_ids,
       $contactID, $ignorePermission, $params) {
 
     $groups_field_filters = json_decode(variable_get('groups_field_filters', NULL), $assoc = TRUE);
-    $filter_ids = $groups_field_filters[$page_type][strval($page_id)]['groups'];
+
+    foreach ($profile_ids as $profile_id) {
+      $filter = $groups_field_filters['profile'][strval($profile_id)];
+
+      if (isset($filter)) {
+        $filter_ids = $filter['groups'];
+        break;
+      }
+    }
 
     if ($contactID !== NULL) {
 
index 8071ea1662a36d2d7a69434794654a4c2fc867bf..8f0ebf778a683f739adbc3d0c88cc4ef2977464e 100644 (file)
@@ -2272,7 +2272,9 @@ class CRM_Contribute_Form_Contribution_Confirm extends CRM_Contribute_Form_Contr
     }
 
     // sudoman hack: re-insert filtered group memberships
-    $params = CRM_Contact_Form_Edit_TagsAndGroups::reInsertFilteredGroupMemberships($this->_id, 'contribution', $contactID, TRUE, $params);
+    if (isset($this->_fields['group'])) {
+      $params = CRM_Contact_Form_Edit_TagsAndGroups::reInsertFilteredGroupMemberships([$this->_fields['group']['group_id']], $contactID, TRUE, $params);
+    }
 
     $contactID = CRM_Contact_BAO_Contact::createProfileContact(
       $params,
index 1580d1e30bce0f89a827ecd5010767bdbd8fd4df..6b6caac5ba666359fef23c155432a2cd10d72579 100644 (file)
@@ -1157,8 +1157,23 @@ class CRM_Event_Form_Registration_Confirm extends CRM_Event_Form_Registration {
         unset($params['contact_id']);
       }
 
-      // sudoman hack: re-insert filtered group memberships
-      $params = CRM_Contact_Form_Edit_TagsAndGroups::reInsertFilteredGroupMemberships($form->get('id'), 'event', $contactID, TRUE, $params);
+      // sudoman hack: get profile ids before re-inserting filtered group memberships
+      foreach (['custom_pre_id', 'custom_post_id'] as $which_profile) {
+
+        $profile_ids = $form->get('values')[$which_profile];
+
+        // some pages can have multiple profiles
+        if (!is_array($profile_ids)) {
+          $all_profile_ids[] = $profile_ids;
+        } else {
+          $all_profile_ids = array_merge($all_profile_ids, $profile_ids);
+        }
+      }
+
+      // sudoman hack: continues from above: re-insert filtered group memberships
+      if (isset($fields['group'])) {
+        $params = CRM_Contact_Form_Edit_TagsAndGroups::reInsertFilteredGroupMemberships($all_profile_ids, $contactID, TRUE, $params);
+      }
 
       $contactID = CRM_Contact_BAO_Contact::createProfileContact(
         $params,
index a24100818b7d6f64237f9cc9b404d9720e9fb8e1..67435665f1195b4b9902d662c489db7e6427f6d5 100644 (file)
@@ -1283,7 +1283,7 @@ class CRM_Profile_Form extends CRM_Core_Form {
     }
 
     // sudoman hack: re-insert filtered group memberships
-    $params = CRM_Contact_Form_Edit_TagsAndGroups::reInsertFilteredGroupMemberships($this->_gid, 'profile', $this->_id, TRUE, $params);
+    $params = CRM_Contact_Form_Edit_TagsAndGroups::reInsertFilteredGroupMemberships([$this->_gid], $this->_id, TRUE, $params);
 
     $this->_id = CRM_Contact_BAO_Contact::createProfileContact(
       $params,