1 <?php
2 /**
3 * @package Joomla.Libraries
4 * @subpackage Helper
5 *
6 * @copyright Copyright (C) 2005 - 2017 Open Source Matters, Inc. All rights reserved.
7 * @license GNU General Public License version 2 or later; see LICENSE.txt
8 */
9
10 defined('JPATH_PLATFORM') or die;
11
12 /**
13 * Helper to deal with user groups.
14 *
15 * @since 3.6.3
16 */
17 final class JHelperUsergroups
18 {
19 /**
20 * @const integer
21 * @since 3.6.3
22 */
23 const MODE_SINGLETON = 1;
24
25 /**
26 * @const integer
27 * @since 3.6.3
28 */
29 const MODE_INSTANCE = 2;
30
31 /**
32 * Singleton instance.
33 *
34 * @var array
35 * @since 3.6.3
36 */
37 private static $instance;
38
39 /**
40 * Available user groups
41 *
42 * @var array
43 * @since 3.6.3
44 */
45 private $groups = array();
46
47 /**
48 * Mode this class is working: singleton or std instance
49 *
50 * @var integer
51 * @since 3.6.3
52 */
53 private $mode;
54
55 /**
56 * Total available groups
57 *
58 * @var integer
59 * @since 3.6.3
60 */
61 private $total;
62
63 /**
64 * Constructor
65 *
66 * @param array $groups Array of groups
67 * @param integer $mode Working mode for this class
68 *
69 * @since 3.6.3
70 */
71 public function __construct(array $groups = array(), $mode = self::MODE_INSTANCE)
72 {
73 $this->mode = (int) $mode;
74
75 if ($groups)
76 {
77 $this->setGroups($groups);
78 }
79 }
80
81 /**
82 * Count loaded user groups.
83 *
84 * @return integer
85 *
86 * @since 3.6.3
87 */
88 public function count()
89 {
90 return count($this->groups);
91 }
92
93 /**
94 * Get the helper instance.
95 *
96 * @return self
97 *
98 * @since 3.6.3
99 */
100 public static function getInstance()
101 {
102 if (static::$instance === null)
103 {
104 // Only here to avoid code style issues...
105 $groups = array();
106
107 static::$instance = new static($groups, static::MODE_SINGLETON);
108 }
109
110 return static::$instance;
111 }
112
113 /**
114 * Get a user group by its id.
115 *
116 * @param integer $id Group identifier
117 *
118 * @return mixed stdClass on success. False otherwise
119 *
120 * @since 3.6.3
121 */
122 public function get($id)
123 {
124 if ($this->has($id))
125 {
126 return $this->groups[$id];
127 }
128
129 // Singleton will load groups as they are requested
130 if ($this->isSingleton())
131 {
132 $this->groups[$id] = $this->load($id);
133
134 return $this->groups[$id];
135 }
136
137 return false;
138 }
139
140 /**
141 * Get the list of existing user groups.
142 *
143 * @return array
144 *
145 * @since 3.6.3
146 */
147 public function getAll()
148 {
149 if ($this->isSingleton() && $this->total() !== $this->count())
150 {
151 $this->loadAll();
152 }
153
154 return $this->groups;
155 }
156
157 /**
158 * Check if a group is in the list.
159 *
160 * @param integer $id Group identifier
161 *
162 * @return boolean
163 *
164 * @since 3.6.3
165 */
166 public function has($id)
167 {
168 return (array_key_exists($id, $this->groups) && $this->groups[$id] !== false);
169 }
170
171 /**
172 * Check if this instance is a singleton.
173 *
174 * @return boolean
175 *
176 * @since 3.6.3
177 */
178 private function isSingleton()
179 {
180 return $this->mode === static::MODE_SINGLETON;
181 }
182
183 /**
184 * Get total available user groups in database.
185 *
186 * @return integer
187 *
188 * @since 3.6.3
189 */
190 public function total()
191 {
192 if ($this->total === null)
193 {
194 $db = JFactory::getDbo();
195
196 $query = $db->getQuery(true)
197 ->select('count(id)')
198 ->from('#__usergroups');
199
200 $db->setQuery($query);
201
202 $this->total = (int) $db->loadResult();
203 }
204
205 return $this->total;
206 }
207
208 /**
209 * Load a group from database.
210 *
211 * @param integer $id Group identifier
212 *
213 * @return mixed
214 *
215 * @since 3.6.3
216 */
217 public function load($id)
218 {
219 $db = JFactory::getDbo();
220
221 $query = $db->getQuery(true)
222 ->select('*')
223 ->from('#__usergroups')
224 ->where('id = ' . (int) $id);
225
226 $db->setQuery($query);
227
228 $group = $db->loadObject();
229
230 if (!$group)
231 {
232 return false;
233 }
234
235 return $this->populateGroupData($group);
236 }
237
238 /**
239 * Load all user groups from the database.
240 *
241 * @return self
242 *
243 * @since 3.6.3
244 */
245 public function loadAll()
246 {
247 $this->groups = array();
248
249 $db = \JFactory::getDbo();
250
251 $query = $db->getQuery(true)
252 ->select('*')
253 ->from('#__usergroups')
254 ->order('lft ASC');
255
256 $db->setQuery($query);
257
258 $groups = $db->loadObjectList('id');
259
260 $this->groups = $groups ?: array();
261 $this->populateGroupsData();
262
263 return $this;
264 }
265
266 /**
267 * Populates extra information for groups.
268 *
269 * @return array
270 *
271 * @since 3.6.3
272 */
273 private function populateGroupsData()
274 {
275 foreach ($this->groups as $group)
276 {
277 $this->populateGroupData($group);
278 }
279
280 return $this->groups;
281 }
282
283 /**
284 * Populate data for a specific user group.
285 *
286 * @param stdClass $group Group
287 *
288 * @return stdClass
289 *
290 * @since 3.6.3
291 */
292 public function populateGroupData($group)
293 {
294 if (!$group || property_exists($group, 'path'))
295 {
296 return $group;
297 }
298
299 $parentId = (int) $group->parent_id;
300
301 if ($parentId === 0)
302 {
303 $group->path = array($group->id);
304 $group->level = 0;
305
306 return $group;
307 }
308
309 $parentGroup = $this->has($parentId) ? $this->get($parentId) : $this->load($parentId);
310
311 if (!property_exists($parentGroup, 'path'))
312 {
313 $parentGroup = $this->populateGroupData($parentGroup);
314 }
315
316 $group->path = array_merge($parentGroup->path, array($group->id));
317 $group->level = count($group->path) - 1;
318
319 return $group;
320 }
321
322 /**
323 * Set the groups to be used as source.
324 *
325 * @param array $groups Array of user groups.
326 *
327 * @return self
328 *
329 * @since 3.6.3
330 */
331 public function setGroups(array $groups)
332 {
333 $this->groups = $groups;
334 $this->populateGroupsData();
335 $this->total = count($groups);
336
337 return $this;
338 }
339 }
340