1<?php 2// (c) Copyright by authors of the Tiki Wiki CMS Groupware Project 3// 4// All Rights Reserved. See copyright.txt for details and a complete list of authors. 5// Licensed under the GNU LESSER GENERAL PUBLIC LICENSE. See license.txt for details. 6// $Id$ 7 8/** 9 * Handler class for GroupSelector 10 * 11 * Letter key: ~g~ 12 * 13 */ 14class Tracker_Field_GroupSelector extends Tracker_Field_Abstract implements Tracker_Field_Filterable 15{ 16 public static function getTypes() 17 { 18 return [ 19 'g' => [ 20 'name' => tr('Group Selector'), 21 'description' => tr('Allow a selection from a specified list of user groups.'), 22 'help' => 'Group selector', 23 'prefs' => ['trackerfield_groupselector'], 24 'tags' => ['advanced'], 25 'default' => 'n', 26 'params' => [ 27 'autoassign' => [ 28 'name' => tr('Auto-Assign'), 29 'description' => tr('Determines if any group should be automatically assigned to the field.'), 30 'filter' => 'int', 31 'options' => [ 32 0 => tr('None'), 33 1 => tr('Creator'), 34 2 => tr('Modifier'), 35 ], 36 'legacy_index' => 0, 37 ], 38 'owner' => [ 39 'name' => tr('Item Owner'), 40 'description' => tr('Field that determines permissions of the item when "Group can see their own items" is enabled for the tracker'), 41 'filter' => 'int', 42 'options' => [ 43 0 => tr('No'), 44 1 => tr('Yes'), 45 ], 46 'default' => 0, 47 ], 48 'groupId' => [ 49 'name' => tr('Group Filter'), 50 'description' => tr('Limit listed groups to those including the specified group.'), 51 'filter' => 'text', 52 'legacy_index' => 1, 53 ], 54 'userGroups' => [ 55 'name' => tr('User Groups'), 56 'description' => tr('Show groups user belongs to instead of the ones user has permission to see.'), 57 'filter' => 'int', 58 'options' => [ 59 0 => tr('No'), 60 1 => tr('Yes'), 61 ], 62 'default' => 0, 63 'legacy_index' => 4, 64 ], 65 'assign' => [ 66 'name' => tr('Assign to the group'), 67 'description' => tr('For no auto-assigned field, the user (user selector if it exists, or user) will be assigned to the group and it will be his or her default group. The group must have the user choice setting activated.'), 68 'filter' => 'int', 69 'options' => [ 70 0 => tr('None'), 71 1 => tr('Assign'), 72 ], 73 'default' => 0, 74 'legacy_index' => 2, 75 ], 76 'unassign' => [ 77 'name' => tr('Unassign from previous selection'), 78 'description' => tr('When assign to the group is set, the user (user selector if it exists, or user) will be unassigned from the previously selected group (if any). That group must have the user choice setting activated.'), 79 'filter' => 'int', 80 'options' => [ 81 0 => tr('None'), 82 1 => tr('Unassign'), 83 ], 84 'default' => 0, 85 ], 86 'notify' => [ 87 'name' => tr('Email Notification'), 88 'description' => tr('Add selected group to group monitor the item. Group watches feature must be enabled.'), 89 'filter' => 'int', 90 'options' => [ 91 0 => tr('No'), 92 1 => tr('Yes'), 93 ], 94 'legacy_index' => 3, 95 ] 96 ], 97 ], 98 ]; 99 } 100 101 function getFieldData(array $requestData = []) 102 { 103 // $group is set to the default group in lib/setup/user_prefs.php 104 global $group, $user; 105 $usersLib = TikiLib::lib('user'); 106 107 $ins_id = $this->getInsertId(); 108 109 $data = []; 110 $defGroup = $group; 111 $userGroups = $usersLib->get_user_groups_inclusion($user); 112 $perms = Perms::get('tracker', $this->getConfiguration('trackerId')); 113 114 $groupId = $this->getOption('groupId'); 115 if (empty($groupId)) { 116 if ($this->getOption('userGroups')) { 117 $data['list'] = array_keys($userGroups); 118 sort($data['list']); 119 } else { 120 $data['list'] = $usersLib->list_all_groups_with_permission(); 121 } 122 } else { 123 if (ctype_digit($groupId)) { 124 $group_info = $usersLib->get_groupId_info($groupId); 125 $data['list'] = $usersLib->get_including_groups($group_info['groupName']); 126 } elseif ($usersLib->group_exists($groupId)) { 127 $data['list'] = $usersLib->get_including_groups($groupId); 128 } 129 } 130 131 // check the default group is one of the groups we are looking for 132 if (! in_array($defGroup, $data['list'])) { 133 // find the one in the list this user is in 134 $includedGroups = array_intersect(array_keys($userGroups), $data['list']); 135 if (empty($includedGroups) && ! $perms->admin_trackers) { 136 // user not in any of the required groups, use the global default $group and warn 137 $defGroup = $group; 138 Feedback::warning(tr('User not in any of the required groups for GroupSelector field')); 139 } else if (count($includedGroups) === 1) { 140 // just the one, easy 141 $defGroup = array_shift($includedGroups); 142 } else { 143 // more than one? 144 if (in_array($group, $includedGroups)) { 145 // use the user's default group if there 146 $defGroup = $group; 147 } else { 148 $found = false; 149 foreach ($userGroups as $userGroup => $membership) { 150 if (in_array($userGroup, $includedGroups) && $membership === 'real') { 151 // use the first group this user is a real member of, not just included 152 $defGroup = $userGroup; 153 $found = true; 154 break; 155 } 156 } 157 if (! $found) { 158 // use the first one as a fall back 159 $defGroup = array_shift($includedGroups); 160 } 161 } 162 } 163 } 164 165 if (isset($requestData[$ins_id])) { 166 if ($this->getOption('autoassign') < 1 || $perms->admin_trackers) { 167 $data['value'] = in_array($requestData[$ins_id], $data['list']) ? $requestData[$ins_id] : ''; 168 } else { 169 if ($this->getOption('autoassign') == 2) { 170 $data['defvalue'] = $defGroup; 171 $data['value'] = $defGroup; 172 } elseif ($this->getOption('autoassign') == 1) { 173 $data['value'] = $defGroup; 174 } else { 175 $data['value'] = ''; 176 } 177 } 178 } else { 179 $data['defvalue'] = $defGroup; 180 $data['value'] = $this->getValue(); 181 } 182 183 return $data; 184 } 185 186 function renderInput($context = []) 187 { 188 return $this->renderTemplate('trackerinput/groupselector.tpl', $context); 189 } 190 191 function handleSave($value, $oldValue) 192 { 193 global $prefs, $user; 194 195 if ($this->getOption('autoassign') && is_null($oldValue)) { 196 $definition = $this->getTrackerDefinition(); 197 if ($prefs['groupTracker'] == 'y' && $definition->isEnabled('autoCreateGroup')) { 198 $value = TikiLib::lib('trk')->groupName($definition->getInformation(), $this->getItemId()); 199 } 200 } 201 if ($this->getOption('assign')) { 202 $creators = TikiLib::lib('trk')->get_item_creators($this->getConfiguration('trackerId'), $this->getItemId()); 203 if (empty($creators)) { 204 $creators = [$user]; 205 } 206 $ginfo = TikiLib::lib('user')->get_group_info($value); 207 if ($this->getOption('unassign') && $oldValue) { 208 $oldginfo = TikiLib::lib('user')->get_group_info($oldValue); 209 } 210 foreach ($creators as $creator) { 211 if ($ginfo['userChoice'] == 'y') { 212 TikiLib::lib('user')->assign_user_to_group($creator, $value); 213 TikiLib::lib('user')->set_default_group($creator, $value); 214 } 215 if ($this->getOption('unassign') && $oldValue && $oldginfo['userChoice'] == 'y') { 216 TikiLib::lib('user')->remove_user_from_group($creator, $oldValue); 217 } 218 } 219 } 220 221 if ($this->getOption('notify') && $prefs['feature_group_watches'] == 'y') { 222 $objectId = $this->getItemId(); 223 $watchEvent = 'tracker_item_modified'; 224 $objectType = 'tracker ' . $this->getConfiguration('trackerId'); 225 226 $tikilib = TikiLib::lib('tiki'); 227 $old_watches = $tikilib->get_groups_watching($objectId, $watchEvent, $objectType); 228 229 foreach ($old_watches as $key => $group) { 230 if ($group != $value) { 231 $tikilib->remove_group_watch($group, $watchEvent, $objectId, $objectType); 232 } 233 } 234 235 if (! empty($value) && ! in_array($value, $old_watches)) { 236 $trackerInfo = $this->getTrackerDefinition()->getInformation(); 237 $objectName = $trackerInfo['name']; 238 $objectHref = 'tiki-view_tracker_item.php?trackerId=' . $this->getConfiguration('trackerId') . '&itemId=' . $this->getItemId(); 239 $tikilib->add_group_watch($value, $watchEvent, $objectId, $objectType, $objectName, $objectHref); 240 } 241 } 242 243 return [ 244 'value' => $value, 245 ]; 246 } 247 248 function getDocumentPart(Search_Type_Factory_Interface $typeFactory) 249 { 250 $baseKey = $this->getBaseKey(); 251 252 $value = $this->getValue(); 253 254 return [ 255 $baseKey => $typeFactory->identifier($value), 256 "{$baseKey}_text" => $typeFactory->sortable($value), 257 ]; 258 } 259 260 function getProvidedFields() { 261 $baseKey = $this->getBaseKey(); 262 return [$baseKey, "{$baseKey}_text"]; 263 } 264 265 function getFilterCollection() 266 { 267 $userlib = TikiLib::lib('user'); 268 $groups = $userlib->list_all_groups_with_permission(); 269 $groups = $userlib->get_group_info($groups); 270 271 $possibilities = []; 272 foreach ($groups as $group) { 273 $possibilities[$group['groupName']] = $group['groupName']; 274 } 275 $possibilities['-Blank (no data)-'] = tr('-Blank (no data)-'); 276 277 $filters = new Tracker\Filter\Collection($this->getTrackerDefinition()); 278 $permName = $this->getConfiguration('permName'); 279 $name = $this->getConfiguration('name'); 280 $baseKey = $this->getBaseKey(); 281 282 $filters->addNew($permName, 'dropdown') 283 ->setLabel($name) 284 ->setControl(new Tracker\Filter\Control\DropDown("tf_{$permName}_dd", $possibilities)) 285 ->setApplyCondition(function ($control, Search_Query $query) use ($baseKey) { 286 $value = $control->getValue(); 287 288 if ($value === '-Blank (no data)-') { 289 $query->filterIdentifier('', $baseKey . '_text'); 290 } elseif ($value) { 291 $query->filterIdentifier($value, $baseKey); 292 } 293 }); 294 295 $filters->addNew($permName, 'multiselect') 296 ->setLabel($name) 297 ->setControl(new Tracker\Filter\Control\MultiSelect("tf_{$permName}_ms", $possibilities)) 298 ->setApplyCondition(function ($control, Search_Query $query) use ($permName, $baseKey) { 299 $values = $control->getValues(); 300 301 if (! empty($values)) { 302 $sub = $query->getSubQuery("ms_$permName"); 303 304 foreach ($values as $v) { 305 if ($v === '-Blank (no data)-') { 306 $sub->filterIdentifier('', $baseKey . '_text'); 307 } elseif ($v) { 308 $sub->filterIdentifier((string) $v, $baseKey); 309 } 310 } 311 } 312 }); 313 314 return $filters; 315 } 316} 317