]> git.agnieray.net Git - galette.git/blob - galette/lib/Galette/Repository/Groups.php
Fix query, replace aliases
[galette.git] / galette / lib / Galette / Repository / Groups.php
1 <?php
2
3 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
4
5 /**
6 * Groups entity
7 *
8 * PHP version 5
9 *
10 * Copyright © 2011-2021 The Galette Team
11 *
12 * This file is part of Galette (http://galette.tuxfamily.org).
13 *
14 * Galette is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation, either version 3 of the License, or
17 * (at your option) any later version.
18 *
19 * Galette is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with Galette. If not, see <http://www.gnu.org/licenses/>.
26 *
27 * @category Repository
28 * @package Galette
29 *
30 * @author Johan Cwiklinski <johan@x-tnd.be>
31 * @copyright 2011-2021 The Galette Team
32 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
33 * @link http://galette.tuxfamily.org
34 * @since Available since 0.7dev - 2011-10-25
35 */
36
37 namespace Galette\Repository;
38
39 use Throwable;
40 use Analog\Analog;
41 use Laminas\Db\Sql\Expression;
42 use Laminas\Db\Sql\Predicate\PredicateSet;
43 use Galette\Entity\Group;
44 use Galette\Entity\Adherent;
45 use Galette\Core\Login;
46 use Galette\Core\Db;
47
48 /**
49 * Groups entitiy
50 *
51 * @category Repository
52 * @name Groups
53 * @package Galette
54 * @author Johan Cwiklinski <johan@x-tnd.be>
55 * @copyright 2011-2021 The Galette Team
56 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
57 * @link http://galette.tuxfamily.org
58 * @since Available since 0.7dev - 2011-10-25
59 */
60 class Groups
61 {
62 /** @var Db */
63 private $zdb;
64 /** @var Login */
65 private $login;
66
67 /**
68 * Constructor
69 *
70 * @param Db $zdb Database instance
71 * @param Login $login Login instance
72 */
73 public function __construct(Db $zdb, Login $login)
74 {
75 $this->zdb = $zdb;
76 $this->login = $login;
77 }
78
79 /**
80 * Get simple groups list (only id and names)
81 *
82 * @param boolean $as_groups Retrieve Group[]
83 *
84 * @return array
85 */
86 public static function getSimpleList(bool $as_groups = false): array
87 {
88 global $zdb;
89
90 try {
91 $select = $zdb->select(Group::TABLE);
92 if ($as_groups === false) {
93 $select->columns(
94 array(Group::PK, 'group_name')
95 );
96 }
97 $groups = array();
98 $gpk = Group::PK;
99
100 $results = $zdb->execute($select);
101
102 foreach ($results as $row) {
103 if ($as_groups === false) {
104 $groups[$row->$gpk] = $row->group_name;
105 } else {
106 $groups[$row->$gpk] = new Group($row);
107 }
108 }
109 return $groups;
110 } catch (Throwable $e) {
111 Analog::log(
112 'Cannot list groups (simple) | ' . $e->getMessage(),
113 Analog::WARNING
114 );
115 throw $e;
116 }
117 }
118
119 /**
120 * Get groups list
121 *
122 * @param boolean $full Return full list or root only
123 * @param int|null $id Group ID to retrieve
124 *
125 * @return Group[]
126 */
127 public function getList(bool $full = true, int $id = null): array
128 {
129 try {
130 $select = $this->zdb->select(Group::TABLE, 'ggroup');
131
132 if (!$this->login->isAdmin() && !$this->login->isStaff() && $full === true) {
133 $select->join(
134 array('gmanagers' => PREFIX_DB . Group::GROUPSMANAGERS_TABLE),
135 'ggroup.' . Group::PK . '=gmanagers.' . Group::PK,
136 array()
137 )->where(['gmanagers.' . Adherent::PK => $this->login->id]);
138 }
139
140 $select->join(
141 array('gusers' => PREFIX_DB . Group::GROUPSUSERS_TABLE),
142 'ggroup.' . Group::PK . '=gusers.' . Group::PK,
143 array('members' => new Expression('count(gusers.' . Group::PK . ')')),
144 $select::JOIN_LEFT
145 );
146
147 if ($full !== true) {
148 $select->where('ggroup.parent_group IS NULL');
149 }
150
151 if ($id !== null) {
152 $select->where
153 ->nest()
154 ->equalTo('ggroup.' . Group::PK, $id)
155 ->or
156 ->equalTo('ggroup.parent_group', $id)
157 ->unnest()
158 ;
159 }
160
161 $select->group('ggroup.' . Group::PK)
162 ->group('ggroup.group_name')
163 ->group('ggroup.creation_date')
164 ->group('ggroup.parent_group')
165 ->order('ggroup.group_name ASC');
166
167 $groups = array();
168
169 $results = $this->zdb->execute($select);
170
171 foreach ($results as $row) {
172 $group = new Group($row);
173 $group->setLogin($this->login);
174 $groups[$group->getFullName()] = $group;
175 }
176 if ($full) { // Order by tree name instead of name
177 ksort($groups);
178 }
179 return $groups;
180 } catch (Throwable $e) {
181 Analog::log(
182 'Cannot list groups | ' . $e->getMessage(),
183 Analog::WARNING
184 );
185 throw $e;
186 }
187 }
188
189 /**
190 * Loads managed groups for specific member
191 *
192 * @param int $id Member id
193 * @param boolean $as_group Retrieve Group[] or int[]
194 *
195 * @return array
196 */
197 public static function loadManagedGroups(int $id, bool $as_group = true): array
198 {
199 return self::loadGroups($id, true, $as_group);
200 }
201
202 /**
203 * Loads groups for specific member
204 *
205 * @param int $id Member id
206 * @param boolean $managed Retrieve managed groups (defaults to false)
207 * @param boolean $as_group Retrieve Group[] or int[]
208 *
209 * @return array
210 */
211 public static function loadGroups(int $id, bool $managed = false, bool $as_group = true): array
212 {
213 global $zdb;
214 try {
215 $join_table = ($managed) ?
216 Group::GROUPSMANAGERS_TABLE : Group::GROUPSUSERS_TABLE;
217
218 $select = $zdb->select(Group::TABLE, 'group');
219 $select->join(
220 array(
221 'b' => PREFIX_DB . $join_table
222 ),
223 'group.' . Group::PK . '=b.' . Group::PK,
224 array()
225 )->where(array('b.' . Adherent::PK => $id));
226
227 $results = $zdb->execute($select);
228
229 $groups = array();
230 foreach ($results as $r) {
231 if ($as_group === true) {
232 $groups[] = new Group($r);
233 } else {
234 $gpk = Group::PK;
235 $groups[] = $r->$gpk;
236 }
237 }
238 return $groups;
239 } catch (Throwable $e) {
240 Analog::log(
241 'Cannot load member groups for id `' . $id . '` | ' .
242 $e->getMessage(),
243 Analog::WARNING
244 );
245 throw $e;
246 }
247 }
248
249 /**
250 * Add a member to specified groups
251 *
252 * @param Adherent $adh Member
253 * @param array $groups Groups Groups list. Each entry must contain
254 * the group id, name each value separated
255 * by a pipe.
256 * @param boolean $manager Add member as manager, defaults to false
257 * @param boolean $transaction Does a SQL transaction already exists? Defaults
258 * to false.
259 *
260 * @return boolean
261 */
262 public static function addMemberToGroups($adh, $groups, $manager = false, $transaction = false)
263 {
264 global $zdb, $login;
265
266 $managed_groups = [];
267 if (!$login->isSuperAdmin() && !$login->isAdmin() && !$login->isStaff()) {
268 $managed_groups = $login->getManagedGroups();
269 }
270
271 try {
272 if ($transaction === false) {
273 $zdb->connection->beginTransaction();
274 }
275
276 $table = null;
277 if ($manager === true) {
278 $table = Group::GROUPSMANAGERS_TABLE;
279 } else {
280 $table = Group::GROUPSUSERS_TABLE;
281 }
282
283 //first, remove current groups members
284 $delete = $zdb->delete($table);
285 $delete->where([Adherent::PK => $adh->id]);
286 if (count($managed_groups)) {
287 $delete->where->in(Group::PK, $managed_groups);
288 }
289 $zdb->execute($delete);
290
291 $msg = null;
292 if ($manager === true) {
293 $msg = 'Member `' . $adh->sname . '` has been detached from groups he manages';
294 } else {
295 $msg = 'Member `' . $adh->sname . '` has been detached of its groups';
296 }
297 Analog::log(
298 $msg . ', we can now store new ones.',
299 Analog::INFO
300 );
301
302 //we proceed, if groups has been specified
303 if (is_array($groups)) {
304 $insert = $zdb->insert($table);
305 $insert->values(
306 array(
307 Group::PK => ':group',
308 Adherent::PK => ':adh'
309 )
310 );
311 $stmt = $zdb->sql->prepareStatementForSqlObject($insert);
312
313 foreach ($groups as $group) {
314 list($gid, $gname) = explode('|', $group);
315
316 if (count($managed_groups) && !in_array($gid, $managed_groups)) {
317 continue;
318 }
319
320 $result = $stmt->execute(
321 array(
322 'group' => $gid,
323 'adh' => $adh->id
324 )
325 );
326
327 if ($result) {
328 $msg = 'Member `' . $adh->sname . '` attached to group `' .
329 $gname . '` (' . $gid . ')';
330 if ($manager === true) {
331 $msg .= ' as a manager';
332 }
333 Analog::log(
334 $msg,
335 Analog::DEBUG
336 );
337 } else {
338 $msg = 'Unable to attach member `' .
339 $adh->sname . '` (' . $adh->id . ') to group `' .
340 $gname . '` (' . $gid . ').';
341 if ($manager === true) {
342 $msg .= ' as a manager';
343 }
344 Analog::log(
345 $msg,
346 Analog::ERROR
347 );
348 throw new \Exception($msg);
349 }
350 }
351 }
352 if ($transaction === false) {
353 //commit all changes
354 $zdb->connection->commit();
355 }
356 return true;
357 } catch (Throwable $e) {
358 if ($transaction === false) {
359 $zdb->connection->rollBack();
360 }
361 $msg = 'Unable to add member `' . $adh->sname . '` (' . $adh->id .
362 ') to specified groups ' . print_r($groups, true);
363 if ($manager === true) {
364 $msg .= ' as a manager';
365 }
366 do {
367 $messages[] = $e->getMessage();
368 } while ($e = $e->getPrevious());
369 Analog::log(
370 $msg . ' |' . implode("\n", $messages),
371 Analog::ERROR
372 );
373 throw $e;
374 }
375 }
376
377 /**
378 * Remove members from all their groups
379 *
380 * @param array $ids Members ids
381 *
382 * @return void
383 */
384 public static function removeMembersFromGroups(array $ids)
385 {
386 global $zdb;
387
388 try {
389 $del_qry = $zdb->delete(Group::GROUPSUSERS_TABLE);
390 $del_qry->where->in(Adherent::PK, $ids);
391 $zdb->execute($del_qry);
392
393 $del_qry = $zdb->delete(Group::GROUPSMANAGERS_TABLE);
394 $del_qry->where->in(Adherent::PK, $ids);
395 $zdb->execute($del_qry);
396 } catch (Throwable $e) {
397 Analog::log(
398 'Unable to remove member #' . implode(', ', $ids) . ' from his groups: ' .
399 $e->getMessage(),
400 Analog::ERROR
401 );
402 throw $e;
403 }
404 }
405
406 /**
407 * Remove member from all his groups
408 *
409 * @param int $id Member's id
410 *
411 * @return void
412 */
413 public static function removeMemberFromGroups($id)
414 {
415 self::removeMembersFromGroups([$id]);
416 }
417
418 /**
419 * Check if groupname is unique
420 *
421 * @param Db $zdb Database instance
422 * @param string $name Requested name
423 * @param int|null $parent Parent groupe (defaults to null)
424 * @param int|null $current Current ID to be excluded (defaults to null)
425 *
426 * @return boolean
427 */
428 public static function isUnique(Db $zdb, string $name, int $parent = null, int $current = null)
429 {
430 try {
431 $select = $zdb->select(Group::TABLE);
432 $select->columns(['group_name'])
433 ->where(['group_name' => $name]);
434
435 if ($parent === null) {
436 $select->where('parent_group IS NULL');
437 } else {
438 $select->where(['parent_group' => $parent]);
439 }
440
441 if ($current !== null) {
442 $select->where->notEqualTo(Group::PK, $current);
443 }
444
445 $results = $zdb->execute($select);
446 return !($results->count() > 0);
447 } catch (Throwable $e) {
448 Analog::log(
449 'Cannot check group name uniqueness | ' . $e->getMessage(),
450 Analog::WARNING
451 );
452 throw $e;
453 }
454 }
455
456 /**
457 * Get managed users id list
458 *
459 * @param array $groups List of managed groups.
460 * If empty, Groups::loadManagedGroups() will be called
461 *
462 * @return array|false
463 */
464 public function getManagerUsers(array $groups = [])
465 {
466 if (!$this->login->isGroupManager()) {
467 return false;
468 }
469 if (!count($groups)) {
470 $groups = self::loadManagedGroups($this->login->id, false);
471 }
472
473 $select = $this->zdb->select(Adherent::TABLE, 'adh');
474 $select->columns(
475 [Adherent::PK]
476 )->join(
477 array('b' => PREFIX_DB . Group::GROUPSUSERS_TABLE),
478 'adh.' . Adherent::PK . '=b.' . Adherent::PK,
479 []
480 )->where->in('b.' . Group::PK, $groups);
481
482 $results = $this->zdb->execute($select);
483
484 $ids_adh = array();
485 foreach ($results as $r) {
486 $ids_adh[] = $r->id_adh;
487 }
488 return $ids_adh;
489 }
490 }