Implements sorting and limits on UserFilter. Start porting xnetgrp to UserFilter.
[platal.git] / classes / userfilter.php
CommitLineData
a087cc8d
FB
1<?php
2/***************************************************************************
3 * Copyright (C) 2003-2009 Polytechnique.org *
4 * http://opensource.polytechnique.org/ *
5 * *
6 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 2 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program; if not, write to the Free Software *
18 * Foundation, Inc., *
19 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
20 ***************************************************************************/
21
d865c296
FB
22
23/******************
24 * CONDITIONS
25 ******************/
26
a087cc8d
FB
27interface UserFilterCondition
28{
5dd9d823
FB
29 const COND_TRUE = 'TRUE';
30 const COND_FALSE = 'FALSE';
31
a087cc8d
FB
32 /** Check that the given user matches the rule.
33 */
784745ce 34 public function buildCondition(UserFilter &$uf);
a087cc8d
FB
35}
36
37abstract class UFC_OneChild implements UserFilterCondition
38{
39 protected $child;
40
5dd9d823
FB
41 public function __construct($child = null)
42 {
43 if (!is_null($child) && ($child instanceof UserFilterCondition)) {
44 $this->setChild($child);
45 }
46 }
47
a087cc8d
FB
48 public function setChild(UserFilterCondition &$cond)
49 {
50 $this->child =& $cond;
51 }
52}
53
54abstract class UFC_NChildren implements UserFilterCondition
55{
56 protected $children = array();
57
5dd9d823
FB
58 public function __construct()
59 {
60 $children = func_get_args();
61 foreach ($children as &$child) {
62 if (!is_null($child) && ($child instanceof UserFilterCondition)) {
63 $this->addChild($child);
64 }
65 }
66 }
67
a087cc8d
FB
68 public function addChild(UserFilterCondition &$cond)
69 {
70 $this->children[] =& $cond;
71 }
5dd9d823
FB
72
73 protected function catConds(array $cond, $op, $fallback)
74 {
75 if (count($cond) == 0) {
76 return $fallback;
77 } else if (count($cond) == 1) {
78 return $cond[0];
79 } else {
4927ee54 80 return '(' . implode(') ' . $op . ' (', $cond) . ')';
5dd9d823
FB
81 }
82 }
a087cc8d
FB
83}
84
85class UFC_True implements UserFilterCondition
86{
784745ce 87 public function buildCondition(UserFilter &$uf)
a087cc8d 88 {
5dd9d823 89 return self::COND_TRUE;
a087cc8d
FB
90 }
91}
92
93class UFC_False implements UserFilterCondition
94{
784745ce 95 public function buildCondition(UserFilter &$uf)
a087cc8d 96 {
5dd9d823 97 return self::COND_FALSE;
a087cc8d
FB
98 }
99}
100
101class UFC_Not extends UFC_OneChild
102{
784745ce 103 public function buildCondition(UserFilter &$uf)
a087cc8d 104 {
5dd9d823
FB
105 $val = $this->child->buildCondition($uf);
106 if ($val == self::COND_TRUE) {
107 return self::COND_FALSE;
108 } else if ($val == self::COND_FALSE) {
109 return self::COND_TRUE;
110 } else {
111 return 'NOT (' . $val . ')';
112 }
a087cc8d
FB
113 }
114}
115
116class UFC_And extends UFC_NChildren
117{
784745ce 118 public function buildCondition(UserFilter &$uf)
a087cc8d 119 {
784745ce 120 if (empty($this->children)) {
5dd9d823 121 return self::COND_FALSE;
784745ce 122 } else {
5dd9d823 123 $true = self::COND_FALSE;
784745ce
FB
124 $conds = array();
125 foreach ($this->children as &$child) {
5dd9d823
FB
126 $val = $child->buildCondition($uf);
127 if ($val == self::COND_TRUE) {
128 $true = self::COND_TRUE;
129 } else if ($val == self::COND_FALSE) {
130 return self::COND_FALSE;
131 } else {
132 $conds[] = $val;
133 }
a087cc8d 134 }
5dd9d823 135 return $this->catConds($conds, 'AND', $true);
a087cc8d 136 }
a087cc8d
FB
137 }
138}
139
140class UFC_Or extends UFC_NChildren
141{
784745ce 142 public function buildCondition(UserFilter &$uf)
a087cc8d 143 {
784745ce 144 if (empty($this->children)) {
5dd9d823 145 return self::COND_TRUE;
784745ce 146 } else {
5dd9d823 147 $true = self::COND_TRUE;
784745ce
FB
148 $conds = array();
149 foreach ($this->children as &$child) {
5dd9d823
FB
150 $val = $child->buildCondition($uf);
151 if ($val == self::COND_TRUE) {
152 return self::COND_TRUE;
153 } else if ($val == self::COND_FALSE) {
154 $true = self::COND_FALSE;
155 } else {
156 $conds[] = $val;
157 }
a087cc8d 158 }
5dd9d823 159 return $this->catConds($conds, 'OR', $true);
a087cc8d 160 }
a087cc8d
FB
161 }
162}
163
164class UFC_Promo implements UserFilterCondition
165{
a087cc8d
FB
166
167 private $grade;
168 private $promo;
169 private $comparison;
170
171 public function __construct($comparison, $grade, $promo)
172 {
173 $this->grade = $grade;
174 $this->comparison = $comparison;
175 $this->promo = $promo;
784745ce 176 UserFilter::assertGrade($this->grade);
a087cc8d
FB
177 }
178
784745ce 179 public function buildCondition(UserFilter &$uf)
a087cc8d 180 {
784745ce 181 $sub = $uf->addEducationFilter(true, $this->grade);
d865c296 182 $field = 'pe' . $sub . '.' . UserFilter::promoYear($this->grade);
784745ce
FB
183 return $field . ' IS NOT NULL AND ' . $field . ' ' . $this->comparison . ' ' . XDB::format('{?}', $this->promo);
184 }
185}
186
187class UFC_Name implements UserFilterCondition
188{
189 const PREFIX = 1;
190 const SUFFIX = 2;
191 const PARTICLE = 7;
192 const VARIANTS = 8;
193 const CONTAINS = 3;
194
195 private $type;
196 private $text;
197 private $mode;
198
199 public function __construct($type, $text, $mode)
200 {
201 $this->type = $type;
202 $this->text = $text;
203 $this->mode = $mode;
204 }
205
206 private function buildNameQuery($type, $variant, $where, UserFilter &$uf)
207 {
208 $sub = $uf->addNameFilter($type, $variant);
209 return str_replace('$ME', 'pn' . $sub, $where);
210 }
211
212 public function buildCondition(UserFilter &$uf)
213 {
214 $left = '$ME.name';
215 $op = ' LIKE ';
216 if (($this->mode & self::PARTICLE) == self::PARTICLE) {
217 $left = 'CONCAT($ME.particle, \' \', $ME.name)';
218 }
219 if (($this->mode & self::CONTAINS) == 0) {
220 $right = XDB::format('{?}', $this->text);
221 $op = ' = ';
222 } else if (($this->mode & self::CONTAINS) == self::PREFIX) {
223 $right = XDB::format('CONCAT({?}, \'%\')', $this->text);
224 } else if (($this->mode & self::CONTAINS) == self::SUFFIX) {
225 $right = XDB::format('CONCAT(\'%\', {?})', $this->text);
226 } else {
227 $right = XDB::format('CONCAT(\'%\', {?}, \'%\')', $this->text);
228 }
229 $cond = $left . $op . $right;
230 $conds = array($this->buildNameQuery($this->type, null, $cond, $uf));
d865c296 231 if (($this->mode & self::VARIANTS) != 0 && isset(UserFilter::$name_variants[$this->type])) {
784745ce
FB
232 foreach (UserFilter::$name_variants[$this->type] as $var) {
233 $conds[] = $this->buildNameQuery($this->type, $var, $cond, $uf);
234 }
235 }
236 return implode(' OR ', $conds);
a087cc8d
FB
237 }
238}
239
4927ee54
FB
240class UFC_Dead implements UserFilterCondition
241{
242 private $dead;
243 public function __construct($dead)
244 {
245 $this->dead = $dead;
246 }
247
248 public function buildCondition(UserFilter &$uf)
249 {
250 if ($this->dead) {
251 return 'p.deathdate IS NOT NULL';
252 } else {
253 return 'p.deathdate IS NULL';
254 }
255 }
256}
257
258class UFC_Registered implements UserFilterCondition
259{
260 private $active;
261 public function __construct($active = false)
262 {
263 $this->only_active = $active;
264 }
265
266 public function buildCondition(UserFilter &$uf)
267 {
268 if ($this->active) {
269 return 'a.uid IS NOT NULL AND a.state = \'active\'';
270 } else {
271 return 'a.uid IS NOT NULL AND a.state != \'pending\'';
272 }
273 }
274}
275
276class UFC_Sex implements UserFilterCondition
277{
278 private $sex;
279 public function __construct($sex)
280 {
281 $this->sex = $sex;
282 }
283
284 public function buildCondition(UserFilter &$uf)
285 {
286 if ($this->sex != User::GENDER_MALE && $this->sex != User::GENDER_FEMALE) {
287 return self::COND_FALSE;
288 } else {
24e08e33 289 return XDB::format('p.sex = {?}', $this->sex == User::GENDER_FEMALE ? 'female' : 'male');
4927ee54
FB
290 }
291 }
292}
293
294class UFC_Group implements UserFilterCondition
295{
296 private $group;
297 private $admin;
298 public function __construct($group, $admin = false)
299 {
300 $this->group = $group;
301 $this->admin = $admin;
302 }
303
304 public function buildCondition(UserFilter &$uf)
305 {
306 $sub = $uf->addGroupFilter($this->group);
307 $where = 'gpm' . $sub . '.perms IS NOT NULL';
308 if ($this->admin) {
309 $where .= ' AND gpm' . $sub . '.perms = \'admin\'';
310 }
311 return $where;
312 }
313}
314
d865c296
FB
315
316
317/******************
318 * ORDERS
319 ******************/
320
321abstract class UserFilterOrder
322{
323 protected $desc = false;
324
325 public function buildSort(UserFilter &$uf)
326 {
327 $sel = $this->getSortTokens($uf);
328 if (!is_array($sel)) {
329 $sel = array($sel);
330 }
331 if ($this->desc) {
332 foreach ($sel as $k=>$s) {
333 $sel[$k] = $s . ' DESC';
334 }
335 }
336 return $sel;
337 }
338
339 abstract protected function getSortTokens(UserFilter &$uf);
340}
341
342class UFO_Promo extends UserFilterOrder
343{
344 private $grade;
345
346 public function __construct($grade = null, $desc = false)
347 {
348 $this->grade = $grade;
349 $this->desc = $desc;
350 }
351
352 protected function getSortTokens(UserFilter &$uf)
353 {
354 if (UserFilter::isGrade($this->grade)) {
355 $sub = $uf->addEducationFilter($this->grade);
356 return 'pe' . $sub . '.' . UserFilter::promoYear($this->grade);
357 } else {
358 $sub = $uf->addDisplayFilter();
359 return 'pd' . $sub . '.promo';
360 }
361 }
362}
363
364class UFO_Name extends UserFilterOrder
365{
366 private $type;
367 private $variant;
368 private $particle;
369
370 public function __construct($type, $variant = null, $particle = false, $desc = false)
371 {
372 $this->type = $type;
373 $this->variant = $variant;
374 $this->particle = $particle;
375 $this->desc = $desc;
376 }
377
378 protected function getSortTokens(UserFilter &$uf)
379 {
380 if (UserFilter::isDisplayName($this->type)) {
381 $sub = $uf->addDisplayFilter();
382 return 'pd' . $sub . '.' . $this->type;
383 } else {
384 $sub = $uf->addNameFilter($this->type, $this->variant);
385 if ($this->particle) {
386 return 'CONCAT(pn' . $sub . '.particle, \' \', pn' . $sub . '.name)';
387 } else {
388 return 'pn' . $sub . '.name';
389 }
390 }
391 }
392}
393
394/***********************************
395 *********************************
396 USER FILTER CLASS
397 *********************************
398 ***********************************/
399
a087cc8d
FB
400class UserFilter
401{
d865c296
FB
402 static private $joinMethods = array();
403
a087cc8d 404 private $root;
24e08e33 405 private $sort = array();
784745ce 406 private $query = null;
24e08e33 407 private $orderby = null;
784745ce 408
d865c296
FB
409 private $lastcount = 0;
410
24e08e33 411 public function __construct($cond = null, $sort = null)
5dd9d823 412 {
d865c296
FB
413 if (empty(self::$joinMethods)) {
414 $class = new ReflectionClass('UserFilter');
415 foreach ($class->getMethods() as $method) {
416 $name = $method->getName();
417 if (substr($name, -5) == 'Joins' && $name != 'buildJoins') {
418 self::$joinMethods[] = $name;
419 }
420 }
421 }
5dd9d823
FB
422 if (!is_null($cond)) {
423 if ($cond instanceof UserFilterCondition) {
424 $this->setCondition($cond);
425 }
426 }
24e08e33
FB
427 if (!is_null($sort)) {
428 if ($sort instanceof UserFilterOrder) {
429 $this->addSort($sort);
d865c296
FB
430 } else if (is_array($sort)) {
431 foreach ($sort as $s) {
432 $this->addSort($s);
433 }
24e08e33
FB
434 }
435 }
5dd9d823
FB
436 }
437
784745ce
FB
438 private function buildQuery()
439 {
d865c296
FB
440 if (is_null($this->orderby)) {
441 $orders = array();
442 foreach ($this->sort as $sort) {
443 $orders = array_merge($orders, $sort->buildSort($this));
444 }
445 if (count($orders) == 0) {
446 $this->orderby = '';
447 } else {
448 $this->orderby = 'ORDER BY ' . implode(', ', $orders);
449 }
450 }
784745ce
FB
451 if (is_null($this->query)) {
452 $where = $this->root->buildCondition($this);
453 $joins = $this->buildJoins();
454 $this->query = 'FROM accounts AS a
455 INNER JOIN account_profiles AS ap ON (ap.uid = a.uid AND FIND_IN_SET(\'owner\', ap.perms))
456 INNER JOIN profiles AS p ON (p.pid = ap.pid)
457 ' . $joins . '
458 WHERE (' . $where . ')';
459 }
460 }
461
462 private function formatJoin(array $joins)
463 {
464 $str = '';
465 foreach ($joins as $key => $infos) {
466 $mode = $infos[0];
467 $table = $infos[1];
468 if ($mode == 'inner') {
469 $str .= 'INNER JOIN ';
470 } else if ($mode == 'left') {
471 $str .= 'LEFT JOIN ';
472 } else {
473 Platal::page()->kill("Join mode error");
474 }
475 $str .= $table . ' AS ' . $key;
476 if (isset($infos[2])) {
4927ee54 477 $str .= ' ON (' . str_replace(array('$ME', '$PID', '$UID'), array($key, 'p.pid', 'a.uid'), $infos[2]) . ')';
784745ce
FB
478 }
479 $str .= "\n";
480 }
481 return $str;
482 }
483
484 private function buildJoins()
485 {
d865c296
FB
486 $joins = array();
487 foreach (self::$joinMethods as $method) {
488 $joins = array_merge($joins, $this->$method());
489 }
784745ce
FB
490 return $this->formatJoin($joins);
491 }
a087cc8d 492
d865c296
FB
493 private function getUIDList($uids = null, $count = null, $offset = null)
494 {
495 $this->buildQuery();
496 $limit = '';
497 if (!is_null($count)) {
498 if (!is_null($offset)) {
499 $limit = XDB::format('LIMIT {?}, {?}', $offset, $count);
500 } else {
501 $limit = XDB::format('LIMIT {?}', $count);
502 }
503 }
504 $cond = '';
505 if (!is_null($uids)) {
506 $cond = ' AND a.uid IN (' . implode(', ', $uids) . ')';
507 }
508 $fetched = XDB::fetchColumn('SELECT SQL_CALC_FOUND_ROWS a.uid
509 ' . $this->query . $cond . '
510 GROUP BY a.uid
511 ' . $this->orderby . '
512 ' . $limit);
513 $this->lastcount = (int)XDB::fetchOneCell('SELECT FOUND_ROWS()');
514 return $fetched;
515 }
516
a087cc8d
FB
517 /** Check that the user match the given rule.
518 */
519 public function checkUser(PlUser &$user)
520 {
784745ce
FB
521 $this->buildQuery();
522 $count = (int)XDB::fetchOneCell('SELECT COUNT(*)
523 ' . $this->query . XDB::format(' AND a.uid = {?}', $user->id()));
524 return $count == 1;
a087cc8d
FB
525 }
526
527 /** Filter a list of user to extract the users matching the rule.
528 */
d865c296 529 public function filter(array $users, $count = null, $offset = null)
a087cc8d 530 {
4927ee54
FB
531 $this->buildQuery();
532 $table = array();
533 $uids = array();
534 foreach ($users as $user) {
535 $uids[] = $user->id();
536 $table[$user->id()] = $user;
537 }
d865c296 538 $fetched = $this->getUIDList($uids, $count, $offset);
a087cc8d 539 $output = array();
4927ee54
FB
540 foreach ($fetched as $uid) {
541 $output[] = $table[$uid];
a087cc8d
FB
542 }
543 return $output;
544 }
545
d865c296 546 public function getUIDs($count = null, $offset = null)
4927ee54 547 {
d865c296
FB
548 return $this->getUIDList(null, $count, $offset);
549 }
550
551 public function getUsers($count = null, $offset = null)
552 {
553 return User::getBulkUsersWithUIDs($this->getUIDs($count, $offset));
4927ee54
FB
554 }
555
d865c296 556 public function getTotalCount()
4927ee54 557 {
d865c296 558 return $this->lastcount;
4927ee54
FB
559 }
560
a087cc8d
FB
561 public function setCondition(UserFilterCondition &$cond)
562 {
563 $this->root =& $cond;
784745ce 564 $this->query = null;
a087cc8d
FB
565 }
566
24e08e33
FB
567 public function addSort(UserFilterOrder &$sort)
568 {
d865c296
FB
569 $this->sort[] = $sort;
570 $this->orderby = null;
24e08e33
FB
571 }
572
a087cc8d
FB
573 static public function getLegacy($promo_min, $promo_max)
574 {
a087cc8d 575 if ($promo_min != 0) {
784745ce 576 $min = new UFC_Promo('>=', self::GRADE_ING, intval($promo_min));
5dd9d823
FB
577 } else {
578 $min = new UFC_True();
a087cc8d 579 }
a087cc8d 580 if ($promo_max != 0) {
784745ce 581 $max = new UFC_Promo('<=', self::GRADE_ING, intval($promo_max));
a087cc8d 582 } else {
5dd9d823 583 $max = new UFC_True();
a087cc8d 584 }
5dd9d823 585 return new UserFilter(new UFC_And($min, $max));
a087cc8d 586 }
784745ce
FB
587
588
d865c296
FB
589 /** DISPLAY
590 */
591 private $pd = false;
592 public function addDisplayFilter()
593 {
594 $this->pd = true;
595 return '';
596 }
597
598 private function displayJoins()
599 {
600 if ($this->pd) {
601 return array('pd' => array('left', 'profile_display', '$ME.pid = $PID'));
602 } else {
603 return array();
604 }
605 }
606
784745ce
FB
607 /** NAMES
608 */
d865c296 609 /* name tokens */
784745ce
FB
610 const LASTNAME = 'lastname';
611 const FIRSTNAME = 'firstname';
612 const NICKNAME = 'nickname';
613 const PSEUDONYM = 'pseudonym';
614 const NAME = 'name';
d865c296 615 /* name variants */
784745ce
FB
616 const VN_MARITAL = 'marital';
617 const VN_ORDINARY = 'ordinary';
618 const VN_OTHER = 'other';
619 const VN_INI = 'ini';
d865c296
FB
620 /* display names */
621 const DN_FULL = 'directory_name';
622 const DN_DISPLAY = 'yourself';
623 const DN_YOURSELF = 'yourself';
624 const DN_DIRECTORY = 'directory_name';
625 const DN_PRIVATE = 'private_name';
626 const DN_PUBLIC = 'public_name';
627 const DN_SHORT = 'short_name';
628 const DN_SORT = 'sort_name';
784745ce
FB
629
630 static public $name_variants = array(
631 self::LASTNAME => array(self::VN_MARITAL, self::VN_ORDINARY),
d865c296
FB
632 self::FIRSTNAME => array(self::VN_ORDINARY, self::VN_INI, self::VN_OTHER)
633 );
784745ce
FB
634
635 static public function assertName($name)
636 {
637 if (!Profile::getNameTypeId($name)) {
638 Platal::page()->kill('Invalid name type');
639 }
640 }
641
d865c296
FB
642 static public function isDisplayName($name)
643 {
644 return $name == self::DN_FULL || $name == self::DN_DISPLAY
645 || $name == self::DN_YOURSELF || $name == self::DN_DIRECTORY
646 || $name == self::DN_PRIVATE || $name == self::DN_PUBLIC
647 || $name == self::DN_SHORT || $name == self::DN_SORT;
648 }
649
784745ce
FB
650 private $pn = array();
651 private $pno = 0;
652 public function addNameFilter($type, $variant = null)
653 {
654 if (!is_null($variant)) {
655 $ft = $type . '_' . $variant;
656 } else {
657 $ft = $type;
658 }
659 $sub = '_' . $ft;
660 self::assertName($ft);
661
662 if (!is_null($variant) && $variant == 'other') {
663 $sub .= $this->pno++;
664 }
665 $this->pn[$sub] = Profile::getNameTypeId($ft);
666 return $sub;
667 }
668
669 private function nameJoins()
670 {
671 $joins = array();
672 foreach ($this->pn as $sub => $type) {
673 $joins['pn' . $sub] = array('left', 'profile_name', '$ME.pid = $PID AND $ME.typeid = ' . $type);
674 }
675 return $joins;
676 }
677
678
679 /** EDUCATION
680 */
681 const GRADE_ING = 'Ing.';
682 const GRADE_PHD = 'PhD';
683 const GRADE_MST = 'M%';
684 static public function isGrade($grade)
685 {
686 return $grade == self::GRADE_ING || self::$grade == GRADE_PHD || self::$grade == GRADE_MST;
687 }
688
689 static public function assertGrade($grade)
690 {
691 if (!self::isGrade($grade)) {
692 Platal::page()->killError("DiplĂ´me non valide");
693 }
694 }
695
d865c296
FB
696 static public function promoYear($grade)
697 {
698 // XXX: Definition of promotion for phds and masters might change in near future.
699 return ($grade == UserFilter::GRADE_ING) ? 'entry_year' : 'grad_year';
700 }
701
784745ce
FB
702 private $pepe = array();
703 private $with_pee = false;
704 private $pe_g = 0;
705 public function addEducationFilter($x = false, $grade = null)
706 {
707 if (!$x) {
708 $index = $this->pe_g;
709 $sub = $this->pe_g++;
710 } else {
711 self::assertGrade($grade);
712 $index = $grade;
713 $sub = $grade[0];
714 $this->with_pee = true;
715 }
716 $sub = '_' . $sub;
717 $this->pepe[$index] = $sub;
718 return $sub;
719 }
720
721 private function educationJoins()
722 {
723 $joins = array();
724 if ($this->with_pee) {
725 $joins['pee'] = array('inner', 'profile_education_enum', 'pee.abbreviation = \'X\'');
726 }
727 foreach ($this->pepe as $grade => $sub) {
728 if ($this->isGrade($grade)) {
729 $joins['pe' . $sub] = array('left', 'profile_education', '$ME.eduid = pee.id AND $ME.uid = $PID');
730 $joins['pede' . $sub] = array('inner', 'profile_education_degree_enum', '$ME.id = pe' . $sub . '.degreeid AND $ME.abbreviation LIKE ' .
731 XDB::format('{?}', $grade));
732 } else {
733 $joins['pe' . $sub] = array('left', 'profile_education', '$ME.uid = $PID');
734 $joins['pee' . $sub] = array('inner', 'profile_education_enum', '$ME.id = pe' . $sub . '.eduid');
735 $joins['pede' . $sub] = array('inner', 'profile_education_degree_enum', '$ME.id = pe' . $sub . '.degreeid');
736 }
737 }
738 return $joins;
739 }
4927ee54
FB
740
741
742 /** GROUPS
743 */
744 private $gpm = array();
745 private $gpm_o = 0;
746 public function addGroupFilter($group = null)
747 {
748 if (!is_null($group)) {
749 if (ctype_digit($group)) {
750 $index = $sub = $group;
751 } else {
752 $index = $group;
753 $sub = preg_replace('/[^a-z0-9]/i', '', $group);
754 }
755 } else {
756 $sub = 'group_' . $this->gpm_o++;
757 $index = null;
758 }
759 $sub = '_' . $sub;
760 $this->gpm[$sub] = $index;
761 return $sub;
762 }
763
764 private function groupJoins()
765 {
766 $joins = array();
767 foreach ($this->gpm as $sub => $key) {
768 if (is_null($key)) {
769 $joins['gpa' . $sub] = array('inner', 'groupex.asso');
770 $joins['gpm' . $sub] = array('left', 'groupex.membres', '$ME.uid = $UID AND $ME.asso_id = gpa' . $sub . '.id');
771 } else if (ctype_digit($key)) {
772 $joins['gpm' . $sub] = array('left', 'groupex.membres', '$ME.uid = $UID AND $ME.asso_id = ' . $key);
773 } else {
774 $joins['gpa' . $sub] = array('inner', 'groupex.asso', XDB::format('$ME.diminutif = {?}', $key));
775 $joins['gpm' . $sub] = array('left', 'groupex.membres', '$ME.uid = $UID AND $ME.asso_id = gpa' . $sub . '.id');
776 }
777 }
778 return $joins;
779 }
a087cc8d
FB
780}
781
782// vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8:
783?>