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