Filter groups according to included profiles
[civicrm-core.git] / CRM / Contact / Form / Edit / TagsAndGroups.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
fee14197 4 | CiviCRM version 5 |
6a488035 5 +--------------------------------------------------------------------+
6b83d5bd 6 | Copyright CiviCRM LLC (c) 2004-2019 |
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 +--------------------------------------------------------------------+
d25dd0ee 26 */
6a488035
TO
27
28/**
29 *
30 * @package CRM
6b83d5bd 31 * @copyright CiviCRM LLC (c) 2004-2019
6a488035 32 */
150f50c1 33class CRM_Contact_Form_Edit_TagsAndGroups {
6a488035
TO
34
35 /**
fe482240 36 * Constant to determine which forms we are generating.
6a488035
TO
37 *
38 * Used by both profile and edit contact
39 */
7da04cde 40 const GROUP = 1, TAG = 2, ALL = 3;
6a488035
TO
41
42 /**
ce064e4f 43 * Build form elements.
6a488035 44 *
77c5b619
TO
45 * @param CRM_Core_Form $form
46 * The form object that we are operating on.
47 * @param int $contactId
48 * Contact id.
49 * @param int $type
50 * What components are we interested in.
51 * @param bool $visibility
52 * Visibility of the field.
77b97be7 53 * @param null $isRequired
77c5b619
TO
54 * @param string $groupName
55 * If used for building group block.
56 * @param string $tagName
57 * If used for building tag block.
58 * @param string $fieldName
59 * This is used in batch profile(i.e to build multiple blocks).
77b97be7
EM
60 *
61 * @param string $groupElementType
6a488035 62 *
6a488035 63 */
ae5ffbb7 64 public static function buildQuickForm(
51ccfbbe 65 &$form,
150f50c1
CW
66 $contactId = 0,
67 $type = self::ALL,
6a488035
TO
68 $visibility = FALSE,
69 $isRequired = NULL,
1d69c242
ML
70 $groupName = 'Group(s)',
71 $tagName = 'Tag(s)',
c18f95b7
PJ
72 $fieldName = NULL,
73 $groupElementType = 'checkbox'
6a488035
TO
74 ) {
75 if (!isset($form->_tagGroup)) {
be2fb01f 76 $form->_tagGroup = [];
6a488035
TO
77 }
78
79 // NYSS 5670
80 if (!$contactId && !empty($form->_contactId)) {
81 $contactId = $form->_contactId;
82 }
83
150f50c1
CW
84 $type = (int) $type;
85 if ($type & self::GROUP) {
6a488035
TO
86
87 $fName = 'group';
88 if ($fieldName) {
89 $fName = $fieldName;
90 }
91
6a488035
TO
92 $groupID = isset($form->_grid) ? $form->_grid : NULL;
93 if ($groupID && $visibility) {
be2fb01f 94 $ids = [$groupID => $groupID];
6a488035
TO
95 }
96 else {
97 if ($visibility) {
98 $group = CRM_Core_PseudoConstant::allGroup();
99 }
100 else {
101 $group = CRM_Core_PseudoConstant::group();
102 }
f828fa2c 103 $ids = $group;
6a488035
TO
104 }
105
106 if ($groupID || !empty($group)) {
107 $groups = CRM_Contact_BAO_Group::getGroupsHierarchy($ids);
108
43bc5eb5
AE
109 // sudoman hack begins
110 //
111 // This hack allows us to filter Groups listings so users aren't
112 // overwhelmed with choices. The advantage of this over smart groups
113 // is that normal groups use double opt-in.
114 //
115 // To set the variable, use the following method:
116 //
d8826aac
AE
117 // $ drush vset --format=string groups_field_filters '
118 // {
119 // "profile": {
120 // "468": {
121 // "groups": [41, 25],
122 // "titles": ["Yes, sign me up!", "Sign me up to the other group!"]
123 // }
124 // },
d8826aac 125 // }'
43bc5eb5
AE
126 //
127 // The "string" format must be used and not the "json" format.
128 // Otherwise the json will be converted to a PHP array, which will not
129 // work with this code.
130 //
43bc5eb5 131 //
7918286c
AE
132 // The string contains json text, with the first level referring to
133 // profiles, then the profile number, then the list of ids of groups to
134 // display on that page and optional replacement titles for those
135 // groups.
136
43bc5eb5
AE
137
138 // Find the list of groups that we want to let pass through a filter on
139 // a given profile or page. If there is no filter for that page, then
140 // all groups are displayed.
141
142 $groups_field_filters = json_decode(variable_get('groups_field_filters', NULL), $assoc = TRUE);
143
144 $form_class_name = get_class($form);
43bc5eb5
AE
145 switch ($form_class_name) {
146
147 case 'CRM_Profile_Form_Edit':
7918286c
AE
148 $profile_id = $form->get('gid'); // gid, not id
149 $filter_config = $groups_field_filters['profile'][strval($profile_id)];
43bc5eb5
AE
150 break;
151
7918286c
AE
152 default:
153 foreach (['custom_pre_id', 'custom_post_id'] as $which_profile) {
43bc5eb5 154
7918286c
AE
155 $profile_ids = $form->get('values')[$which_profile];
156
157 // some pages can have multiple profiles
158 if (!is_array($profile_ids)) {
159 $all_profile_ids[] = $profile_ids;
160 } else {
161 $all_profile_ids = array_merge($all_profile_ids, $profile_ids);
162 }
163 }
164
165 foreach ($all_profile_ids as $profile_id) {
166 $possible_filter = $groups_field_filters['profile'][strval($profile_id)];
167
168 if (isset($possible_filter)) {
169 $filter_config = $possible_filter;
170 break;
171 }
172 }
43bc5eb5
AE
173 break;
174 }
d8826aac
AE
175
176 if (isset($filter_config)) {
177
178 $filter_ids = $filter_config['groups'];
179 $filter_titles = $filter_config['titles'];
180 }
43bc5eb5
AE
181 // sudoman hack continues further below
182
d8826aac 183
6a488035 184 $attributes['skiplabel'] = TRUE;
be2fb01f
CW
185 $elements = [];
186 $groupsOptions = [];
6a488035 187 foreach ($groups as $id => $group) {
43bc5eb5
AE
188
189 // sudoman hack continues
190 // filter groups if a filter is set
d8826aac 191 if (isset($filter_ids) and !in_array($id, $filter_ids)) {
43bc5eb5
AE
192 continue;
193 }
d8826aac 194 // sudoman hack continues further below
43bc5eb5 195
6a488035
TO
196 // make sure that this group has public visibility
197 if ($visibility &&
198 $group['visibility'] == 'User and User Admin Only'
199 ) {
200 continue;
201 }
77b97be7 202
ab345ca5 203 if ($groupElementType == 'select') {
c18f95b7
PJ
204 $groupsOptions[$id] = $group['title'];
205 }
206 else {
d8826aac
AE
207
208 // sudoman hack continues
209 if (isset($filter_titles)) {
210 $custom_group_title = $filter_titles[array_search($id, $filter_ids)];
211 }
212 if (isset($custom_group_title)) {
213 $group_title = $custom_group_title;
214 } else {
215 $group_title = $group['title'];
216 }
217
218 // only slight modification here
c18f95b7 219 $form->_tagGroup[$fName][$id]['description'] = $group['description'];
d8826aac
AE
220 $elements[] = &$form->addElement('advcheckbox', $id, NULL, $group_title, $attributes);
221
222 // sudoman hack continues with calls to CRM_Contact_Form_Edit_TagsAndGroups::reInsertFilteredGroupMemberships
c18f95b7
PJ
223 }
224 }
225
ab345ca5 226 if ($groupElementType == 'select' && !empty($groupsOptions)) {
58438e5b 227 $form->add('select', $fName, $groupName, $groupsOptions, FALSE,
be2fb01f 228 ['id' => $fName, 'multiple' => 'multiple', 'class' => 'crm-select2 twenty']
c18f95b7
PJ
229 );
230 $form->assign('groupCount', count($groupsOptions));
6a488035
TO
231 }
232
c18f95b7 233 if ($groupElementType == 'checkbox' && !empty($elements)) {
6a488035
TO
234 $form->addGroup($elements, $fName, $groupName, '&nbsp;<br />');
235 $form->assign('groupCount', count($elements));
236 if ($isRequired) {
be2fb01f 237 $form->addRule($fName, ts('%1 is a required field.', [1 => $groupName]), 'required');
6a488035
TO
238 }
239 }
c18f95b7 240 $form->assign('groupElementType', $groupElementType);
6a488035
TO
241 }
242 }
243
150f50c1 244 if ($type & self::TAG) {
a52a8469 245 $tags = CRM_Core_BAO_Tag::getColorTags('civicrm_contact');
6a488035 246
a52a8469 247 if (!empty($tags)) {
be2fb01f 248 $form->add('select2', 'tag', ts('Tag(s)'), $tags, FALSE, ['class' => 'huge', 'placeholder' => ts('- select -'), 'multiple' => TRUE]);
6a488035 249 }
4a679824 250
d8d2f9e1 251 // build tag widget
252 $parentNames = CRM_Core_BAO_Tag::getTagSet('civicrm_contact');
253 CRM_Core_Form_Tag::buildQuickForm($form, $parentNames, 'civicrm_contact', $contactId, FALSE, TRUE);
254 }
a52a8469 255 $form->assign('tagGroup', $form->_tagGroup);
6dac2504 256 }
6a488035
TO
257
258 /**
fe482240 259 * Set defaults for relevant form elements.
6a488035 260 *
77c5b619
TO
261 * @param int $id
262 * The contact id.
263 * @param array $defaults
264 * The defaults array to store the values in.
265 * @param int $type
266 * What components are we interested in.
267 * @param string $fieldName
268 * This is used in batch profile(i.e to build multiple blocks).
6a488035 269 *
77b97be7 270 * @param string $groupElementType
6a488035 271 */
00be9182 272 public static function setDefaults($id, &$defaults, $type = self::ALL, $fieldName = NULL, $groupElementType = 'checkbox') {
6a488035
TO
273 $type = (int ) $type;
274 if ($type & self::GROUP) {
275 $fName = 'group';
276 if ($fieldName) {
277 $fName = $fieldName;
278 }
279
280 $contactGroup = CRM_Contact_BAO_GroupContact::getContactGroup($id, 'Added', NULL, FALSE, TRUE);
281 if ($contactGroup) {
282 foreach ($contactGroup as $group) {
ab345ca5 283 if ($groupElementType == 'select') {
c18f95b7
PJ
284 $defaults[$fName][] = $group['group_id'];
285 }
286 else {
287 $defaults[$fName . '[' . $group['group_id'] . ']'] = 1;
288 }
6a488035
TO
289 }
290 }
291 }
292
293 if ($type & self::TAG) {
a52a8469 294 $defaults['tag'] = implode(',', CRM_Core_BAO_EntityTag::getTag($id, 'civicrm_contact'));
6a488035
TO
295 }
296 }
297
298 /**
c490a46a 299 * Set default values for the form. Note that in edit/view mode
6a488035
TO
300 * the default values are retrieved from the database
301 *
6a488035 302 *
c490a46a 303 * @param CRM_Core_Form $form
ce064e4f 304 * @param array $defaults
6a488035
TO
305 */
306 public static function setDefaultValues(&$form, &$defaults) {
307 $contactEditOptions = $form->get('contactEditOptions');
c18f95b7 308
6a488035
TO
309 if ($form->_action & CRM_Core_Action::ADD) {
310 if (array_key_exists('TagsAndGroups', $contactEditOptions)) {
311 // set group and tag defaults if any
312 if ($form->_gid) {
313 $defaults['group'][$form->_gid] = 1;
314 }
315 if ($form->_tid) {
316 $defaults['tag'][$form->_tid] = 1;
317 }
318 }
319 }
320 else {
321 if (array_key_exists('TagsAndGroups', $contactEditOptions)) {
322 // set the group and tag ids
c18f95b7
PJ
323 $groupElementType = 'checkbox';
324 if (CRM_Utils_System::getClassName($form) == 'CRM_Contact_Form_Contact') {
ab345ca5 325 $groupElementType = 'select';
c18f95b7
PJ
326 }
327 self::setDefaults($form->_contactId, $defaults, self::ALL, NULL, $groupElementType);
6a488035
TO
328 }
329 }
330 }
96025800 331
7918286c 332 /** re-add groups selectively filtered out by sudoman's hack
43bc5eb5
AE
333 *
334 * the sudoman hack continues from above and from calls to this function.
335 *
336 * re-add any filtered-out groups if the contact is already in those groups
337 * so createProfileContact() doesn't remove group memberships.
338 *
7918286c 339 * @param array $profile_ids (ids of profiles in use on page)
43bc5eb5
AE
340 * @param int $contactID (id of contact)
341 * @param bool $ignorePermission (passed to getContactGroup, often TRUE)
7918286c 342 * @param array $params (form parameters)
43bc5eb5
AE
343 *
344 * @return array $params (modified parameters: active groups that were filtered are inserted)
345 */
7918286c 346 public static function reInsertFilteredGroupMemberships($profile_ids,
43bc5eb5
AE
347 $contactID, $ignorePermission, $params) {
348
349 $groups_field_filters = json_decode(variable_get('groups_field_filters', NULL), $assoc = TRUE);
7918286c
AE
350
351 foreach ($profile_ids as $profile_id) {
352 $filter = $groups_field_filters['profile'][strval($profile_id)];
353
354 if (isset($filter)) {
355 $filter_ids = $filter['groups'];
356 break;
357 }
358 }
43bc5eb5
AE
359
360 if ($contactID !== NULL) {
361
362 $contactGroupList = &CRM_Contact_BAO_GroupContact::getContactGroup($contactID, 'Added',
363 NULL, FALSE, $ignorePermission
364 );
365
366 foreach ($contactGroupList as $value) {
367
368 $groupId = $value['group_id'];
d8826aac 369 if (!empty($filter_ids) && !in_array($groupId, $filter_ids)) {
43bc5eb5
AE
370
371 $params['group'][strval($groupId)] = 1;
372 }
373 }
374 }
375
376 return $params;
377 }
378 // sudoman hack ends
379
232624b1 380}