Switch core to core-account branch
[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
8363588b 27// {{{ interface UserFilterCondition
2d83cac9
RB
28/** This interface describe objects which filter users based
29 * on various parameters.
30 * The parameters of the filter must be given to the constructor.
31 * The buildCondition function is called by UserFilter when
32 * actually building the query. That function must call
33 * $uf->addWheteverFilter so that the UserFilter makes
34 * adequate joins. It must return the 'WHERE' condition to use
35 * with the filter.
36 */
a087cc8d
FB
37interface UserFilterCondition
38{
5dd9d823
FB
39 const COND_TRUE = 'TRUE';
40 const COND_FALSE = 'FALSE';
41
a087cc8d
FB
42 /** Check that the given user matches the rule.
43 */
784745ce 44 public function buildCondition(UserFilter &$uf);
a087cc8d 45}
8363588b 46// }}}
a087cc8d 47
8363588b 48// {{{ class UFC_OneChild
a087cc8d
FB
49abstract class UFC_OneChild implements UserFilterCondition
50{
51 protected $child;
52
5dd9d823
FB
53 public function __construct($child = null)
54 {
55 if (!is_null($child) && ($child instanceof UserFilterCondition)) {
56 $this->setChild($child);
57 }
58 }
59
a087cc8d
FB
60 public function setChild(UserFilterCondition &$cond)
61 {
62 $this->child =& $cond;
63 }
64}
8363588b 65// }}}
a087cc8d 66
8363588b 67// {{{ class UFC_NChildren
a087cc8d
FB
68abstract class UFC_NChildren implements UserFilterCondition
69{
70 protected $children = array();
71
5dd9d823
FB
72 public function __construct()
73 {
74 $children = func_get_args();
75 foreach ($children as &$child) {
76 if (!is_null($child) && ($child instanceof UserFilterCondition)) {
77 $this->addChild($child);
78 }
79 }
80 }
81
a087cc8d
FB
82 public function addChild(UserFilterCondition &$cond)
83 {
84 $this->children[] =& $cond;
85 }
5dd9d823
FB
86
87 protected function catConds(array $cond, $op, $fallback)
88 {
89 if (count($cond) == 0) {
90 return $fallback;
91 } else if (count($cond) == 1) {
92 return $cond[0];
93 } else {
4927ee54 94 return '(' . implode(') ' . $op . ' (', $cond) . ')';
5dd9d823
FB
95 }
96 }
a087cc8d 97}
8363588b 98// }}}
a087cc8d 99
8363588b 100// {{{ class UFC_True
a087cc8d
FB
101class UFC_True implements UserFilterCondition
102{
784745ce 103 public function buildCondition(UserFilter &$uf)
a087cc8d 104 {
5dd9d823 105 return self::COND_TRUE;
a087cc8d
FB
106 }
107}
8363588b 108// }}}
a087cc8d 109
8363588b 110// {{{ class UFC_False
a087cc8d
FB
111class UFC_False implements UserFilterCondition
112{
784745ce 113 public function buildCondition(UserFilter &$uf)
a087cc8d 114 {
5dd9d823 115 return self::COND_FALSE;
a087cc8d
FB
116 }
117}
8363588b 118// }}}
a087cc8d 119
8363588b 120// {{{ class UFC_Not
a087cc8d
FB
121class UFC_Not extends UFC_OneChild
122{
784745ce 123 public function buildCondition(UserFilter &$uf)
a087cc8d 124 {
5dd9d823
FB
125 $val = $this->child->buildCondition($uf);
126 if ($val == self::COND_TRUE) {
127 return self::COND_FALSE;
128 } else if ($val == self::COND_FALSE) {
129 return self::COND_TRUE;
130 } else {
131 return 'NOT (' . $val . ')';
132 }
a087cc8d
FB
133 }
134}
8363588b 135// }}}
a087cc8d 136
8363588b 137// {{{ class UFC_And
a087cc8d
FB
138class UFC_And extends UFC_NChildren
139{
784745ce 140 public function buildCondition(UserFilter &$uf)
a087cc8d 141 {
784745ce 142 if (empty($this->children)) {
5dd9d823 143 return self::COND_FALSE;
784745ce 144 } else {
5dd9d823 145 $true = self::COND_FALSE;
784745ce
FB
146 $conds = array();
147 foreach ($this->children as &$child) {
5dd9d823
FB
148 $val = $child->buildCondition($uf);
149 if ($val == self::COND_TRUE) {
150 $true = self::COND_TRUE;
151 } else if ($val == self::COND_FALSE) {
152 return self::COND_FALSE;
153 } else {
154 $conds[] = $val;
155 }
a087cc8d 156 }
5dd9d823 157 return $this->catConds($conds, 'AND', $true);
a087cc8d 158 }
a087cc8d
FB
159 }
160}
8363588b 161// }}}
a087cc8d 162
8363588b 163// {{{ class UFC_Or
a087cc8d
FB
164class UFC_Or extends UFC_NChildren
165{
784745ce 166 public function buildCondition(UserFilter &$uf)
a087cc8d 167 {
784745ce 168 if (empty($this->children)) {
5dd9d823 169 return self::COND_TRUE;
784745ce 170 } else {
5dd9d823 171 $true = self::COND_TRUE;
784745ce
FB
172 $conds = array();
173 foreach ($this->children as &$child) {
5dd9d823
FB
174 $val = $child->buildCondition($uf);
175 if ($val == self::COND_TRUE) {
176 return self::COND_TRUE;
177 } else if ($val == self::COND_FALSE) {
178 $true = self::COND_FALSE;
179 } else {
180 $conds[] = $val;
181 }
a087cc8d 182 }
5dd9d823 183 return $this->catConds($conds, 'OR', $true);
a087cc8d 184 }
a087cc8d
FB
185 }
186}
8363588b 187// }}}
a087cc8d 188
8363588b 189// {{{ class UFC_Profile
53eae167
RB
190/** Filters users who have a profile
191 */
eb1449b8
FB
192class UFC_Profile implements UserFilterCondition
193{
194 public function buildCondition(UserFilter &$uf)
195 {
196 return '$PID IS NOT NULL';
197 }
198}
8363588b 199// }}}
eb1449b8 200
8363588b 201// {{{ class UFC_Promo
5d2e55c7 202/** Filters users based on promotion
53eae167
RB
203 * @param $comparison Comparison operator (>, =, ...)
204 * @param $grade Formation on which to restrict, UserFilter::DISPLAY for "any formation"
5d2e55c7 205 * @param $promo Promotion on which the filter is based
53eae167 206 */
a087cc8d
FB
207class UFC_Promo implements UserFilterCondition
208{
a087cc8d
FB
209
210 private $grade;
211 private $promo;
212 private $comparison;
213
214 public function __construct($comparison, $grade, $promo)
215 {
216 $this->grade = $grade;
217 $this->comparison = $comparison;
218 $this->promo = $promo;
38c6fe96
FB
219 if ($this->grade != UserFilter::DISPLAY) {
220 UserFilter::assertGrade($this->grade);
221 }
a087cc8d
FB
222 }
223
784745ce 224 public function buildCondition(UserFilter &$uf)
a087cc8d 225 {
38c6fe96
FB
226 if ($this->grade == UserFilter::DISPLAY) {
227 $sub = $uf->addDisplayFilter();
228 return XDB::format('pd' . $sub . '.promo = {?}', $this->promo);
229 } else {
230 $sub = $uf->addEducationFilter(true, $this->grade);
231 $field = 'pe' . $sub . '.' . UserFilter::promoYear($this->grade);
232 return $field . ' IS NOT NULL AND ' . $field . ' ' . $this->comparison . ' ' . XDB::format('{?}', $this->promo);
233 }
784745ce
FB
234 }
235}
8363588b 236// }}}
784745ce 237
8363588b 238// {{{ class UFC_Name
53eae167 239/** Filters users based on name
5d2e55c7 240 * @param $type Type of name field on which filtering is done (firstname, lastname...)
53eae167 241 * @param $text Text on which to filter
5d2e55c7 242 * @param $mode Flag indicating search type (prefix, suffix, with particule...)
53eae167 243 */
784745ce
FB
244class UFC_Name implements UserFilterCondition
245{
246 const PREFIX = 1;
247 const SUFFIX = 2;
248 const PARTICLE = 7;
249 const VARIANTS = 8;
250 const CONTAINS = 3;
251
252 private $type;
253 private $text;
254 private $mode;
255
256 public function __construct($type, $text, $mode)
257 {
258 $this->type = $type;
259 $this->text = $text;
260 $this->mode = $mode;
261 }
262
263 private function buildNameQuery($type, $variant, $where, UserFilter &$uf)
264 {
265 $sub = $uf->addNameFilter($type, $variant);
266 return str_replace('$ME', 'pn' . $sub, $where);
267 }
268
269 public function buildCondition(UserFilter &$uf)
270 {
271 $left = '$ME.name';
272 $op = ' LIKE ';
273 if (($this->mode & self::PARTICLE) == self::PARTICLE) {
274 $left = 'CONCAT($ME.particle, \' \', $ME.name)';
275 }
276 if (($this->mode & self::CONTAINS) == 0) {
277 $right = XDB::format('{?}', $this->text);
278 $op = ' = ';
279 } else if (($this->mode & self::CONTAINS) == self::PREFIX) {
280 $right = XDB::format('CONCAT({?}, \'%\')', $this->text);
281 } else if (($this->mode & self::CONTAINS) == self::SUFFIX) {
282 $right = XDB::format('CONCAT(\'%\', {?})', $this->text);
283 } else {
284 $right = XDB::format('CONCAT(\'%\', {?}, \'%\')', $this->text);
285 }
286 $cond = $left . $op . $right;
287 $conds = array($this->buildNameQuery($this->type, null, $cond, $uf));
d865c296 288 if (($this->mode & self::VARIANTS) != 0 && isset(UserFilter::$name_variants[$this->type])) {
784745ce
FB
289 foreach (UserFilter::$name_variants[$this->type] as $var) {
290 $conds[] = $this->buildNameQuery($this->type, $var, $cond, $uf);
291 }
292 }
293 return implode(' OR ', $conds);
a087cc8d
FB
294 }
295}
8363588b 296// }}}
a087cc8d 297
8363588b 298// {{{ class UFC_Dead
53eae167
RB
299/** Filters users based on death date
300 * @param $comparison Comparison operator
301 * @param $date Date to which death date should be compared
302 */
4927ee54
FB
303class UFC_Dead implements UserFilterCondition
304{
38c6fe96
FB
305 private $comparison;
306 private $date;
307
308 public function __construct($comparison = null, $date = null)
4927ee54 309 {
38c6fe96
FB
310 $this->comparison = $comparison;
311 $this->date = $date;
4927ee54
FB
312 }
313
314 public function buildCondition(UserFilter &$uf)
315 {
38c6fe96
FB
316 $str = 'p.deathdate IS NOT NULL';
317 if (!is_null($this->comparison)) {
318 $str .= ' AND p.deathdate ' . $this->comparison . ' ' . XDB::format('{?}', date('Y-m-d', $this->date));
4927ee54 319 }
38c6fe96 320 return $str;
4927ee54
FB
321 }
322}
8363588b 323// }}}
4927ee54 324
8363588b 325// {{{ class UFC_Registered
53eae167
RB
326/** Filters users based on registration state
327 * @param $active Whether we want to use only "active" users (i.e with a valid redirection)
328 * @param $comparison Comparison operator
329 * @param $date Date to which users registration date should be compared
330 */
4927ee54
FB
331class UFC_Registered implements UserFilterCondition
332{
333 private $active;
38c6fe96
FB
334 private $comparison;
335 private $date;
336
337 public function __construct($active = false, $comparison = null, $date = null)
4927ee54
FB
338 {
339 $this->only_active = $active;
38c6fe96
FB
340 $this->comparison = $comparison;
341 $this->date = $date;
4927ee54
FB
342 }
343
344 public function buildCondition(UserFilter &$uf)
345 {
346 if ($this->active) {
38c6fe96 347 $date = 'a.uid IS NOT NULL AND a.state = \'active\'';
4927ee54 348 } else {
38c6fe96
FB
349 $date = 'a.uid IS NOT NULL AND a.state != \'pending\'';
350 }
351 if (!is_null($this->comparison)) {
352 $date .= ' AND a.registration_date ' . $this->comparison . ' ' . XDB::format('{?}', date('Y-m-d', $this->date));
4927ee54 353 }
38c6fe96 354 return $date;
4927ee54
FB
355 }
356}
8363588b 357// }}}
4927ee54 358
8363588b 359// {{{ class UFC_ProfileUpdated
53eae167
RB
360/** Filters users based on profile update date
361 * @param $comparison Comparison operator
362 * @param $date Date to which profile update date must be compared
363 */
7e735012
FB
364class UFC_ProfileUpdated implements UserFilterCondition
365{
366 private $comparison;
367 private $date;
368
369 public function __construct($comparison = null, $date = null)
370 {
371 $this->comparison = $comparison;
372 $this->date = $date;
373 }
374
375 public function buildCondition(UserFilter &$uf)
376 {
377 return 'p.last_change ' . $this->comparison . XDB::format(' {?}', date('Y-m-d H:i:s', $this->date));
378 }
379}
8363588b 380// }}}
7e735012 381
8363588b 382// {{{ class UFC_Birthday
53eae167
RB
383/** Filters users based on next birthday date
384 * @param $comparison Comparison operator
385 * @param $date Date to which users next birthday date should be compared
386 */
7e735012
FB
387class UFC_Birthday implements UserFilterCondition
388{
389 private $comparison;
390 private $date;
391
392 public function __construct($comparison = null, $date = null)
393 {
394 $this->comparison = $comparison;
395 $this->date = $date;
396 }
397
398 public function buildCondition(UserFilter &$uf)
399 {
400 return 'p.next_birthday ' . $this->comparison . XDB::format(' {?}', date('Y-m-d', $this->date));
401 }
402}
8363588b 403// }}}
7e735012 404
8363588b 405// {{{ class UFC_Sex
53eae167
RB
406/** Filters users based on sex
407 * @parm $sex One of User::GENDER_MALE or User::GENDER_FEMALE, for selecting users
408 */
4927ee54
FB
409class UFC_Sex implements UserFilterCondition
410{
411 private $sex;
412 public function __construct($sex)
413 {
414 $this->sex = $sex;
415 }
416
417 public function buildCondition(UserFilter &$uf)
418 {
419 if ($this->sex != User::GENDER_MALE && $this->sex != User::GENDER_FEMALE) {
420 return self::COND_FALSE;
421 } else {
24e08e33 422 return XDB::format('p.sex = {?}', $this->sex == User::GENDER_FEMALE ? 'female' : 'male');
4927ee54
FB
423 }
424 }
425}
8363588b 426// }}}
4927ee54 427
8363588b 428// {{{ class UFC_Group
53eae167 429/** Filters users based on group membership
5d2e55c7
RB
430 * @param $group Group whose members we are selecting
431 * @param $anim Whether to restrict selection to animators of that group
53eae167 432 */
4927ee54
FB
433class UFC_Group implements UserFilterCondition
434{
435 private $group;
5d2e55c7
RB
436 private $anim;
437 public function __construct($group, $anim = false)
4927ee54
FB
438 {
439 $this->group = $group;
5d2e55c7 440 $this->anim = $anim;
4927ee54
FB
441 }
442
443 public function buildCondition(UserFilter &$uf)
444 {
445 $sub = $uf->addGroupFilter($this->group);
446 $where = 'gpm' . $sub . '.perms IS NOT NULL';
5d2e55c7 447 if ($this->anim) {
4927ee54
FB
448 $where .= ' AND gpm' . $sub . '.perms = \'admin\'';
449 }
450 return $where;
451 }
452}
8363588b 453// }}}
4927ee54 454
8363588b 455// {{{ class UFC_Email
53eae167
RB
456/** Filters users based on email address
457 * @param $email Email whose owner we are looking for
458 */
aa21c568
FB
459class UFC_Email implements UserFilterCondition
460{
461 private $email;
462 public function __construct($email)
463 {
464 $this->email = $email;
465 }
466
467 public function buildCondition(UserFilter &$uf)
468 {
469 if (User::isForeignEmailAddress($this->email)) {
470 $sub = $uf->addEmailRedirectFilter($this->email);
471 return XDB::format('e' . $sub . '.email IS NOT NULL OR a.email = {?}', $this->email);
21401768
FB
472 } else if (User::isVirtualEmailAddress($this->email)) {
473 $sub = $uf->addVirtualEmailFilter($this->email);
474 return 'vr' . $sub . '.redirect IS NOT NULL';
aa21c568 475 } else {
21401768
FB
476 @list($user, $domain) = explode('@', $this->email);
477 $sub = $uf->addAliasFilter($user);
aa21c568
FB
478 return 'al' . $sub . '.alias IS NOT NULL';
479 }
480 }
481}
8363588b 482// }}}
d865c296 483
8363588b 484// {{{ class UFC_EmailList
5d2e55c7 485/** Filters users based on an email list
53eae167
RB
486 * @param $emails List of emails whose owner must be selected
487 */
21401768
FB
488class UFC_EmailList implements UserFilterCondition
489{
490 private $emails;
491 public function __construct($emails)
492 {
493 $this->emails = $emails;
494 }
495
496 public function buildCondition(UserFilter &$uf)
497 {
498 $email = null;
499 $virtual = null;
500 $alias = null;
501 $cond = array();
502
503 if (count($this->emails) == 0) {
504 return UserFilterCondition::COND_TRUE;
505 }
506
507 foreach ($this->emails as $entry) {
508 if (User::isForeignEmailAddress($entry)) {
509 if (is_null($email)) {
510 $email = $uf->addEmailRedirectFilter();
511 }
512 $cond[] = XDB::format('e' . $email . '.email = {?} OR a.email = {?}', $entry, $entry);
513 } else if (User::isVirtualEmailAddress($entry)) {
514 if (is_null($virtual)) {
515 $virtual = $uf->addVirtualEmailFilter();
516 }
517 $cond[] = XDB::format('vr' . $virtual . '.redirect IS NOT NULL AND v' . $virtual . '.alias = {?}', $entry);
518 } else {
519 if (is_null($alias)) {
520 $alias = $uf->addAliasFilter();
521 }
522 @list($user, $domain) = explode('@', $entry);
523 $cond[] = XDB::format('al' . $alias . '.alias = {?}', $user);
524 }
525 }
526 return '(' . implode(') OR (', $cond) . ')';
527 }
528}
8363588b 529// }}}
d865c296 530
8363588b 531// {{{ class UFC_Address
c4b24511 532/** Filters users based on their address
036d1637
RB
533 * @param $text Text for filter in fulltext search
534 * @param $textSearchMode Mode for search (PREFIX, SUFFIX, ...)
535 * @param $type Filter on address type
536 * @param $flags Filter on address flags
537 * @param $countryId Filter on address countryId
538 * @param $administrativeAreaId Filter on address administrativeAreaId
539 * @param $subAdministrativeAreaId Filter on address subAdministrativeAreaId
540 * @param $localityId Filter on address localityId
541 * @param $postalCode Filter on address postalCode
c4b24511
RB
542 */
543class UFC_Address implements UserFilterCondition
544{
036d1637
RB
545 /** Flags for text search
546 */
547 const PREFIX = 0x0001;
548 const SUFFIX = 0x0002;
549 const CONTAINS = 0x0003;
c4b24511 550
036d1637
RB
551 /** Valid address type ('hq' is reserved for company addresses)
552 */
553 const TYPE_HOME = 'home';
554 const TYPE_PRO = 'job';
c4b24511 555
036d1637
RB
556 /** Flags for addresses
557 */
558 const FLAG_CURRENT = 0x0001;
559 const FLAG_TEMP = 0x0002;
560 const FLAG_SECOND = 0x0004;
561 const FLAG_MAIL = 0x0008;
562 const FLAG_CEDEX = 0x0010;
563
564 // Binary OR of those flags
565 const FLAG_ANY = 0x001F;
566
567 /** Text of these flags
568 */
569 private static $flagtexts = array(
570 self::FLAG_CURRENT => 'current',
571 self::FLAG_TEMP => 'temporary',
572 self::FLAG_SECOND => 'secondary',
573 self::FLAG_MAIL => 'mail',
574 self::FLAG_CEDEX => 'cedex',
575 );
576
577 /** Data of the filter
578 */
579 private $text;
580 private $type;
581 private $flags;
582 private $countryId;
583 private $administrativeAreaId;
584 private $subAdministrativeAreaId;
585 private $localityId;
586 private $postalCode;
587
588 private $textSearchMode;
589
590 public function __construct($text = null, $textSearchMode = self::CONTAINS,
591 $type = null, $flags = self::FLAG_ANY, $countryId = null, $administrativeAreaId = null,
592 $subAdministrativeAreaId = null, $localityId = null, $postalCode = null)
593 {
594 $this->text = $text;
595 $this->textSearchMode = $textSearchMode;
596 $this->type = $type;
597 $this->flags = $flags;
598 $this->countryId = $countryId;
599 $this->administrativeAreaId = $administrativeAreaId;
600 $this->subAdministrativeAreaId = $subAdministrativeAreaId;
601 $this->localityId = $localityId;
602 $this->postalCode = $postalCode;
c4b24511
RB
603 }
604
605 public function buildCondition(UserFilter &$uf)
606 {
036d1637
RB
607 $sub = $uf->addAddressFilter();
608 $conds = array();
609 if ($this->text != null) {
610 $left = $sub . '.text ';
611 $op = ' LIKE ';
612 if (($this->textSearchMode & self::CONTAINS) == 0) {
613 $right = XDB::format('{?}', $this->text);
614 $op = ' = ';
615 } else if (($this->mode & self::CONTAINS) == self::PREFIX) {
616 $right = XDB::format('CONCAT({?}, \'%\')', $this->text);
617 } else if (($this->mode & self::CONTAINS) == self::SUFFIX) {
618 $right = XDB::format('CONCAT(\'%\', {?})', $this->text);
619 } else {
620 $right = XDB::format('CONCAT(\'%\', {?}, \'%\')', $this->text);
621 }
622 $conds[] = $left . $op . $right;
c4b24511 623 }
036d1637
RB
624
625 if ($this->type != null) {
626 $conds[] = $sub . '.type = ' . XDB::format('{?}', $this->type);
627 }
628
629 if ($this->flags != self::FLAG_ANY) {
630 foreach(self::$flagtexts as $flag => $text) {
631 if ($flag & $this->flags) {
632 $conds[] = 'FIND_IN_SET(' . XDB::format('{?}', $text) . ', ' . $sub . '.flags)';
633 }
634 }
635 }
636
637 if ($this->countryId != null) {
638 $conds[] = $sub . '.countryId = ' . XDB::format('{?}', $this->countryId);
639 }
640 if ($this->administrativeAreaId != null) {
641 $conds[] = $sub . '.administrativeAreaId = ' . XDB::format('{?}', $this->administrativeAreaId);
642 }
643 if ($this->subAdministrativeAreaId != null) {
644 $conds[] = $sub . '.subAdministrativeAreaId = ' . XDB::format('{?}', $this->subAdministrativeAreaId);
645 }
646 if ($this->localityId != null) {
647 $conds[] = $sub . '.localityId = ' . XDB::format('{?}', $this->localityId);
648 }
649 if ($this->postalCode != null) {
650 $conds[] = $sub . '.postalCode = ' . XDB::format('{?}', $this->postalCode);
651 }
652
653 return implode(' AND ', $conds);
c4b24511
RB
654 }
655}
8363588b 656// }}}
c4b24511 657
8363588b 658// {{{ class UFC_Corps
4083b126
RB
659/** Filters users based on the corps they belong to
660 * @param $corps Corps we are looking for (abbreviation)
661 * @param $type Whether we search for original or current corps
662 */
663class UFC_Corps implements UserFilterCondition
664{
5d2e55c7
RB
665 const CURRENT = 1;
666 const ORIGIN = 2;
4083b126
RB
667
668 private $corps;
669 private $type;
670
671 public function __construct($corps, $type = self::CURRENT)
672 {
673 $this->corps = $corps;
674 $this->type = $type;
675 }
676
677 public function buildCondition(UserFilter &$uf)
678 {
5d2e55c7
RB
679 /** Tables shortcuts:
680 * pc for profile_corps,
4083b126
RB
681 * pceo for profile_corps_enum - orginal
682 * pcec for profile_corps_enum - current
683 */
684 $sub = $uf->addCorpsFilter($this->type);
685 $cond = $sub . '.abbreviation = ' . $corps;
686 return $cond;
687 }
688}
8363588b 689// }}}
4083b126 690
8363588b 691// {{{ class UFC_Corps_Rank
4083b126
RB
692/** Filters users based on their rank in the corps
693 * @param $rank Rank we are looking for (abbreviation)
694 */
695class UFC_Corps_Rank implements UserFilterCondition
696{
697 private $rank;
698 public function __construct($rank)
699 {
700 $this->rank = $rank;
701 }
702
703 public function buildCondition(UserFilter &$uf)
704 {
5d2e55c7 705 /** Tables shortcuts:
4083b126
RB
706 * pcr for profile_corps_rank
707 */
708 $sub = $uf->addCorpsRankFilter();
709 $cond = $sub . '.abbreviation = ' . $rank;
710 return $cond;
711 }
712}
8363588b 713// }}}
4083b126 714
6a99c3ac
RB
715// {{{ class UFC_Job_Company
716/** Filters users based on the company they belong to
717 * @param $type The field being searched (self::JOBID, self::JOBNAME or self::JOBACRONYM)
718 * @param $value The searched value
719 */
4e2f2ad2 720class UFC_Job_Company implements UserFilterCondition
6a99c3ac
RB
721{
722 const JOBID = 'id';
723 const JOBNAME = 'name';
724 const JOBACRONYM = 'acronym';
725
726 private $type;
727 private $value;
728
729 public function __construct($type, $value)
730 {
731 $this->assertType($type);
732 $this->type = $type;
733 $this->value = $value;
734 }
735
736 private function assertType($type)
737 {
738 if ($type != self::JOBID && $type != self::JOBNAME && $type != self::JOBACRONYM) {
5d2e55c7 739 Platal::page()->killError("Type de recherche non valide.");
6a99c3ac
RB
740 }
741 }
742
743 public function buildCondition(UserFilter &$uf)
744 {
745 $sub = $uf->addJobCompanyFilter();
746 $cond = $sub . '.' . $this->type . ' = ' . XDB::format('{?}', $this->value);
747 return $cond;
748 }
749}
750// }}}
751
752// {{{ class UFC_Job_Sectorization
753/** Filters users based on the ((sub)sub)sector they work in
754 * @param $sector The sector searched
755 * @param $subsector The subsector
756 * @param $subsubsector The subsubsector
757 */
4e2f2ad2 758class UFC_Job_Sectorization implements UserFilterCondition
6a99c3ac
RB
759{
760
761 private $sector;
762 private $subsector;
763 private $subsubsector;
764
765 public function __construct($sector = null, $subsector = null, $subsubsector = null)
766 {
767 $this->sector = $sector;
768 $this->subsector = $subsector;
769 $this->subsubsector = $subsubsector;
770 }
771
772 public function buildCondition(UserFilter &$uf)
773 {
774 // No need to add the JobFilter, it will be done by addJobSectorizationFilter
775 $conds = array();
776 if ($this->sector !== null) {
777 $sub = $uf->addJobSectorizationFilter(UserFilter::JOB_SECTOR);
778 $conds[] = $sub . '.id = ' . XDB::format('{?}', $this->sector);
779 }
780 if ($this->subsector !== null) {
781 $sub = $uf->addJobSectorizationFilter(UserFilter::JOB_SUBSECTOR);
782 $conds[] = $sub . '.id = ' . XDB::format('{?}', $this->subsector);
783 }
784 if ($this->subsubsector !== null) {
785 $sub = $uf->addJobSectorizationFilter(UserFilter::JOB_SUBSUBSECTOR);
786 $conds[] = $sub . '.id = ' . XDB::format('{?}', $this->subsubsector);
787 }
788 return implode(' AND ', $conds);
789 }
790}
791// }}}
792
793// {{{ class UFC_Job_Description
794/** Filters users based on their job description
795 * @param $description The text being searched for
796 * @param $fields The fields to search for (user-defined, ((sub|)sub|)sector)
797 */
4e2f2ad2 798class UFC_Job_Description implements UserFilterCondition
6a99c3ac
RB
799{
800
801 /** Meta-filters
802 * Built with binary OR on UserFilter::JOB_*
803 */
804 const ANY = 31;
805 const SECTORIZATION = 15;
806
807 private $description;
808 private $fields;
809
810 public function __construct($description)
811 {
812 $this->fields = $fields;
813 $this->description = $description;
814 }
815
816 public function buildCondition(UserFilter &$uf)
817 {
818 $conds = array();
819 if ($this->fields & UserFilter::JOB_USERDEFINED) {
820 $sub = $uf->addJobFilter();
821 $conds[] = $sub . '.description LIKE ' . XDB::format('CONCAT(\'%\', {?}, \'%\')', $this->description);
822 }
823 if ($this->fields & UserFilter::JOB_SECTOR) {
824 $sub = $uf->addJobSectorizationFilter(UserFilter::JOB_SECTOR);
825 $conds[] = $sub . '.name LIKE ' . XDB::format('CONCAT(\'%\', {?}, \'%\')', $this->description);
826 }
827 if ($this->fields & UserFilter::JOB_SUBSECTOR) {
828 $sub = $uf->addJobSectorizationFilter(UserFilter::JOB_SUBSECTOR);
829 $conds[] = $sub . '.name LIKE ' . XDB::format('CONCAT(\'%\', {?}, \'%\')', $this->description);
830 }
831 if ($this->fields & UserFilter::JOB_SUBSUBSECTOR) {
832 $sub = $uf->addJobSectorizationFilter(UserFilter::JOB_SUBSUBSECTOR);
833 $conds[] = $sub . '.name LIKE ' . XDB::format('CONCAT(\'%\', {?}, \'%\')', $this->description);
834 $sub = $uf->addJobSectorizationFilter(UserFilter::JOB_ALTERNATES);
835 $conds[] = $sub . '.name LIKE ' . XDB::format('CONCAT(\'%\', {?}, \'%\')', $this->description);
836 }
837 return implode(' OR ', $conds);
838 }
839}
840// }}}
841
0a2e9c74
RB
842// {{{ class UFC_Networking
843/** Filters users based on network identity (IRC, ...)
844 * @param $type Type of network (-1 for any)
845 * @param $value Value to search
846 */
4e2f2ad2 847class UFC_Networking implements UserFilterCondition
0a2e9c74
RB
848{
849 private $type;
850 private $value;
851
852 public function __construct($type, $value)
853 {
854 $this->type = $type;
855 $this->value = $value;
856 }
857
858 public function buildCondition(UserFilter &$uf)
859 {
860 $sub = $uf->addNetworkingFilter();
861 $conds = array();
862 $conds[] = $sub . '.address = ' . XDB::format('CONCAT(\'%\', {?}, \'%\')', $this->value);
863 if ($this->type != -1) {
864 $conds[] = $sub . '.network_type = ' . XDB::format('{?}', $this->type);
865 }
866 return implode(' AND ', $conds);
867 }
868}
869// }}}
870
6d62969e
RB
871// {{{ class UFC_Phone
872/** Filters users based on their phone number
873 * @param $num_type Type of number (pro/user/home)
874 * @param $phone_type Type of phone (fixed/mobile/fax)
875 * @param $number Phone number
876 */
4e2f2ad2 877class UFC_Phone implements UserFilterCondition
6d62969e
RB
878{
879 const NUM_PRO = 'pro';
880 const NUM_USER = 'user';
881 const NUM_HOME = 'address';
882 const NUM_ANY = 'any';
883
884 const PHONE_FIXED = 'fixed';
885 const PHONE_MOBILE = 'mobile';
886 const PHONE_FAX = 'fax';
887 const PHONE_ANY = 'any';
888
889 private $num_type;
890 private $phone_type;
891 private $number;
892
893 public function __construct($number, $num_type = self::NUM_ANY, $phone_type = self::PHONE_ANY)
894 {
895 require_once('profil.inc.php');
896 $this->number = $number;
897 $this->num_type = $num_type;
898 $this->phone_type = format_phone_number($phone_type);
899 }
900
901 public function buildCondition(UserFilter &$uf)
902 {
903 $sub = $uf->addPhoneFilter();
904 $conds = array();
905 $conds[] = $sub . '.search_tel = ' . XDB::format('{?}', $this->number);
906 if ($this->num_type != self::NUM_ANY) {
907 $conds[] = $sub . '.link_type = ' . XDB::format('{?}', $this->num_type);
908 }
909 if ($this->phone_type != self::PHONE_ANY) {
910 $conds[] = $sub . '.tel_type = ' . XDB::format('{?}', $this->phone_type);
911 }
912 return implode(' AND ', $conds);
913 }
914}
915// }}}
916
ceb512d2
RB
917// {{{ class UFC_Medal
918/** Filters users based on their medals
919 * @param $medal ID of the medal
920 * @param $grade Grade of the medal (null for 'any')
921 */
4e2f2ad2 922class UFC_Medal implements UserFilterCondition
ceb512d2
RB
923{
924 private $medal;
925 private $grade;
926
927 public function __construct($medal, $grade = null)
928 {
929 $this->medal = $medal;
930 $this->grade = $grade;
931 }
932
933 public function buildCondition(UserFilter &$uf)
934 {
935 $conds = array();
936 $sub = $uf->addMedalFilter();
937 $conds[] = $sub . '.mid = ' . XDB::format('{?}', $this->medal);
938 if ($this->grade != null) {
939 $conds[] = $sub . '.gid = ' . XDB::format('{?}', $this->grade);
940 }
941 return implode(' AND ', $conds);
942 }
943}
944// }}}
945
671b7073
RB
946// {{{ class UFC_Mentor_Expertise
947/** Filters users by mentoring expertise
948 * @param $expertise Domain of expertise
949 */
4e2f2ad2 950class UFC_Mentor_Expertise implements UserFilterCondition
671b7073
RB
951{
952 private $expertise;
953
954 public function __construct($expertise)
955 {
956 $this->expertise = $expertise;
957 }
958
959 public function buildCondition(UserFilter &$uf)
960 {
961 $sub = $uf->addMentorFilter(UserFilter::MENTOR_EXPERTISE);
962 return $sub . '.expertise LIKE ' . XDB::format('CONCAT(\'%\', {?}, \'%\'', $this->expertise);
963 }
964}
965// }}}
966
967// {{{ class UFC_Mentor_Country
968/** Filters users by mentoring country
969 * @param $country Two-letters code of country being searched
970 */
4e2f2ad2 971class UFC_Mentor_Country implements UserFilterCondition
671b7073
RB
972{
973 private $country;
974
975 public function __construct($country)
976 {
977 $this->country = $country;
978 }
979
980 public function buildCondition(UserFilter &$uf)
981 {
982 $sub = $uf->addMentorFilter(UserFilter::MENTOR_COUNTRY);
983 return $sub . '.country = ' . XDB::format('{?}', $this->country);
984 }
985}
986// }}}
987
988// {{{ class UFC_Mentor_Sectorization
989/** Filters users based on mentoring (sub|)sector
990 * @param $sector ID of sector
991 * @param $subsector Subsector (null for any)
992 */
4e2f2ad2 993class UFC_Mentor_Sectorization implements UserFilterCondition
671b7073
RB
994{
995 private $sector;
996 private $subsector;
997
998 public function __construct($sector, $subsector = null)
999 {
1000 $this->sector = $sector;
1001 $this->subsubsector = $subsector;
1002 }
1003
1004 public function buildCondition(UserFilter &$uf)
1005 {
1006 $sub = $uf->addMentorFilter(UserFilter::MENTOR_SECTOR);
1007 $conds = array();
1008 $conds[] = $sub . '.sectorid = ' . XDB::format('{?}', $this->sector);
1009 if ($this->subsector != null) {
1010 $conds[] = $sub . '.subsectorid = ' . XDB::format('{?}', $this->subsector);
1011 }
1012 return implode(' AND ', $conds);
1013 }
1014}
1015// }}}
1016
8363588b 1017// {{{ class UFC_UserRelated
5d2e55c7 1018/** Filters users based on a relation toward a user
53eae167
RB
1019 * @param $user User to which searched users are related
1020 */
4e7bf1e0 1021abstract class UFC_UserRelated implements UserFilterCondition
3f42a6ad 1022{
009b8ab7
FB
1023 protected $user;
1024 public function __construct(PlUser &$user)
1025 {
1026 $this->user =& $user;
3f42a6ad 1027 }
4e7bf1e0 1028}
8363588b 1029// }}}
3f42a6ad 1030
8363588b 1031// {{{ class UFC_Contact
5d2e55c7 1032/** Filters users who belong to selected user's contacts
53eae167 1033 */
4e7bf1e0
FB
1034class UFC_Contact extends UFC_UserRelated
1035{
3f42a6ad
FB
1036 public function buildCondition(UserFilter &$uf)
1037 {
009b8ab7 1038 $sub = $uf->addContactFilter($this->user->id());
3f42a6ad
FB
1039 return 'c' . $sub . '.contact IS NOT NULL';
1040 }
1041}
8363588b 1042// }}}
3f42a6ad 1043
8363588b 1044// {{{ class UFC_WatchRegistration
53eae167
RB
1045/** Filters users being watched by selected user
1046 */
4e7bf1e0
FB
1047class UFC_WatchRegistration extends UFC_UserRelated
1048{
1049 public function buildCondition(UserFilter &$uf)
1050 {
009b8ab7
FB
1051 if (!$this->user->watch('registration')) {
1052 return UserFilterCondition::COND_FALSE;
1053 }
1054 $uids = $this->user->watchUsers();
1055 if (count($uids) == 0) {
1056 return UserFilterCondition::COND_FALSE;
1057 } else {
07eb5b0e 1058 return '$UID IN ' . XDB::formatArray($uids);
009b8ab7 1059 }
4e7bf1e0
FB
1060 }
1061}
8363588b 1062// }}}
4e7bf1e0 1063
8363588b 1064// {{{ class UFC_WatchPromo
53eae167
RB
1065/** Filters users belonging to a promo watched by selected user
1066 * @param $user Selected user (the one watching promo)
1067 * @param $grade Formation the user is watching
1068 */
4e7bf1e0
FB
1069class UFC_WatchPromo extends UFC_UserRelated
1070{
1071 private $grade;
009b8ab7 1072 public function __construct(PlUser &$user, $grade = UserFilter::GRADE_ING)
4e7bf1e0 1073 {
009b8ab7 1074 parent::__construct($user);
4e7bf1e0
FB
1075 $this->grade = $grade;
1076 }
1077
1078 public function buildCondition(UserFilter &$uf)
1079 {
009b8ab7
FB
1080 $promos = $this->user->watchPromos();
1081 if (count($promos) == 0) {
1082 return UserFilterCondition::COND_FALSE;
1083 } else {
1084 $sube = $uf->addEducationFilter(true, $this->grade);
1085 $field = 'pe' . $sube . '.' . UserFilter::promoYear($this->grade);
07eb5b0e 1086 return $field . ' IN ' . XDB::formatArray($promos);
009b8ab7 1087 }
4e7bf1e0
FB
1088 }
1089}
8363588b 1090// }}}
4e7bf1e0 1091
8363588b 1092// {{{ class UFC_WatchContact
53eae167
RB
1093/** Filters users watched by selected user
1094 */
009b8ab7 1095class UFC_WatchContact extends UFC_Contact
4e7bf1e0
FB
1096{
1097 public function buildCondition(UserFilter &$uf)
1098 {
009b8ab7
FB
1099 if (!$this->user->watchContacts()) {
1100 return UserFilterCondition::COND_FALSE;
1101 }
1102 return parent::buildCondition($uf);
4e7bf1e0
FB
1103 }
1104}
8363588b 1105// }}}
4e7bf1e0
FB
1106
1107
d865c296
FB
1108/******************
1109 * ORDERS
1110 ******************/
1111
8363588b 1112// {{{ class UserFilterOrder
2d83cac9
RB
1113/** Base class for ordering results of a query.
1114 * Parameters for the ordering must be given to the constructor ($desc for a
1115 * descending order).
1116 * The getSortTokens function is used to get actual ordering part of the query.
1117 */
d865c296
FB
1118abstract class UserFilterOrder
1119{
1120 protected $desc = false;
009b8ab7
FB
1121 public function __construct($desc = false)
1122 {
1123 $this->desc = $desc;
1124 }
d865c296
FB
1125
1126 public function buildSort(UserFilter &$uf)
1127 {
1128 $sel = $this->getSortTokens($uf);
1129 if (!is_array($sel)) {
1130 $sel = array($sel);
1131 }
1132 if ($this->desc) {
1133 foreach ($sel as $k=>$s) {
1134 $sel[$k] = $s . ' DESC';
1135 }
1136 }
1137 return $sel;
1138 }
1139
2d83cac9
RB
1140 /** This function must return the tokens to use for ordering
1141 * @param &$uf The UserFilter whose results must be ordered
1142 * @return The name of the field to use for ordering results
1143 */
d865c296
FB
1144 abstract protected function getSortTokens(UserFilter &$uf);
1145}
8363588b 1146// }}}
d865c296 1147
8363588b 1148// {{{ class UFO_Promo
5d2e55c7
RB
1149/** Orders users by promotion
1150 * @param $grade Formation whose promotion users should be sorted by (restricts results to users of that formation)
53eae167
RB
1151 * @param $desc Whether sort is descending
1152 */
d865c296
FB
1153class UFO_Promo extends UserFilterOrder
1154{
1155 private $grade;
1156
1157 public function __construct($grade = null, $desc = false)
1158 {
009b8ab7 1159 parent::__construct($desc);
d865c296 1160 $this->grade = $grade;
d865c296
FB
1161 }
1162
1163 protected function getSortTokens(UserFilter &$uf)
1164 {
1165 if (UserFilter::isGrade($this->grade)) {
1166 $sub = $uf->addEducationFilter($this->grade);
1167 return 'pe' . $sub . '.' . UserFilter::promoYear($this->grade);
1168 } else {
1169 $sub = $uf->addDisplayFilter();
1170 return 'pd' . $sub . '.promo';
1171 }
1172 }
1173}
8363588b 1174// }}}
d865c296 1175
8363588b 1176// {{{ class UFO_Name
53eae167 1177/** Sorts users by name
5d2e55c7
RB
1178 * @param $type Type of name on which to sort (firstname...)
1179 * @param $variant Variant of that name to use (marital, ordinary...)
53eae167
RB
1180 * @param $particle Set to true if particles should be included in the sorting order
1181 * @param $desc If sort order should be descending
1182 */
d865c296
FB
1183class UFO_Name extends UserFilterOrder
1184{
1185 private $type;
1186 private $variant;
1187 private $particle;
1188
1189 public function __construct($type, $variant = null, $particle = false, $desc = false)
1190 {
009b8ab7 1191 parent::__construct($desc);
d865c296
FB
1192 $this->type = $type;
1193 $this->variant = $variant;
1194 $this->particle = $particle;
d865c296
FB
1195 }
1196
1197 protected function getSortTokens(UserFilter &$uf)
1198 {
1199 if (UserFilter::isDisplayName($this->type)) {
1200 $sub = $uf->addDisplayFilter();
1201 return 'pd' . $sub . '.' . $this->type;
1202 } else {
1203 $sub = $uf->addNameFilter($this->type, $this->variant);
1204 if ($this->particle) {
1205 return 'CONCAT(pn' . $sub . '.particle, \' \', pn' . $sub . '.name)';
1206 } else {
1207 return 'pn' . $sub . '.name';
1208 }
1209 }
1210 }
1211}
8363588b 1212// }}}
d865c296 1213
8363588b 1214// {{{ class UFO_Registration
53eae167
RB
1215/** Sorts users based on registration date
1216 */
38c6fe96
FB
1217class UFO_Registration extends UserFilterOrder
1218{
009b8ab7 1219 protected function getSortTokens(UserFilter &$uf)
38c6fe96 1220 {
009b8ab7 1221 return 'a.registration_date';
38c6fe96 1222 }
009b8ab7 1223}
8363588b 1224// }}}
38c6fe96 1225
8363588b 1226// {{{ class UFO_Birthday
53eae167
RB
1227/** Sorts users based on next birthday date
1228 */
009b8ab7
FB
1229class UFO_Birthday extends UserFilterOrder
1230{
38c6fe96
FB
1231 protected function getSortTokens(UserFilter &$uf)
1232 {
009b8ab7 1233 return 'p.next_birthday';
38c6fe96
FB
1234 }
1235}
8363588b 1236// }}}
38c6fe96 1237
8363588b 1238// {{{ class UFO_ProfileUpdate
53eae167
RB
1239/** Sorts users based on last profile update
1240 */
009b8ab7
FB
1241class UFO_ProfileUpdate extends UserFilterOrder
1242{
1243 protected function getSortTokens(UserFilter &$uf)
1244 {
1245 return 'p.last_change';
1246 }
1247}
8363588b 1248// }}}
009b8ab7 1249
8363588b 1250// {{{ class UFO_Death
53eae167
RB
1251/** Sorts users based on death date
1252 */
009b8ab7
FB
1253class UFO_Death extends UserFilterOrder
1254{
1255 protected function getSortTokens(UserFilter &$uf)
1256 {
1257 return 'p.deathdate';
1258 }
1259}
8363588b 1260// }}}
009b8ab7
FB
1261
1262
d865c296
FB
1263/***********************************
1264 *********************************
1265 USER FILTER CLASS
1266 *********************************
1267 ***********************************/
1268
8363588b 1269// {{{ class UserFilter
2d83cac9
RB
1270/** This class provides a convenient and centralized way of filtering users.
1271 *
1272 * Usage:
1273 * $uf = new UserFilter(new UFC_Blah($x, $y), new UFO_Coin($z, $t));
1274 *
1275 * Resulting UserFilter can be used to:
1276 * - get a list of User objects matching the filter
1277 * - get a list of UIDs matching the filter
1278 * - get the number of users matching the filter
1279 * - check whether a given User matches the filter
1280 * - filter a list of User objects depending on whether they match the filter
1281 *
1282 * Usage for UFC and UFO objects:
1283 * A UserFilter will call all private functions named XXXJoins.
1284 * These functions must return an array containing the list of join
1285 * required by the various UFC and UFO associated to the UserFilter.
1286 * Entries in those returned array are of the following form:
1287 * 'join_tablealias' => array('join_type', 'joined_table', 'join_criter')
1288 * which will be translated into :
1289 * join_type JOIN joined_table AS join_tablealias ON (join_criter)
1290 * in the final query.
1291 *
1292 * In the join_criter text, $ME is replaced with 'join_tablealias', $PID with
1293 * profile.pid, and $UID with auth_user_md5.user_id.
1294 *
1295 * For each kind of "JOIN" needed, a function named addXXXFilter() should be defined;
1296 * its parameter will be used to set various private vars of the UserFilter describing
1297 * the required joins ; such a function shall return the "join_tablealias" to use
1298 * when referring to the joined table.
1299 *
1300 * For example, if data from profile_job must be available to filter results,
1301 * the UFC object will call $uf-addJobFilter(), which will set the 'with_pj' var and
1302 * return 'pj', the short name to use when referring to profile_job; when building
1303 * the query, calling the jobJoins function will return an array containing a single
1304 * row:
1305 * 'pj' => array('left', 'profile_job', '$ME.pid = $UID');
1306 *
1307 * The 'register_optional' function can be used to generate unique table aliases when
1308 * the same table has to be joined several times with different aliases.
1309 */
a087cc8d
FB
1310class UserFilter
1311{
d865c296
FB
1312 static private $joinMethods = array();
1313
a087cc8d 1314 private $root;
24e08e33 1315 private $sort = array();
784745ce 1316 private $query = null;
24e08e33 1317 private $orderby = null;
784745ce 1318
aa21c568 1319 private $lastcount = null;
d865c296 1320
24e08e33 1321 public function __construct($cond = null, $sort = null)
5dd9d823 1322 {
d865c296
FB
1323 if (empty(self::$joinMethods)) {
1324 $class = new ReflectionClass('UserFilter');
1325 foreach ($class->getMethods() as $method) {
1326 $name = $method->getName();
1327 if (substr($name, -5) == 'Joins' && $name != 'buildJoins') {
1328 self::$joinMethods[] = $name;
1329 }
1330 }
1331 }
5dd9d823
FB
1332 if (!is_null($cond)) {
1333 if ($cond instanceof UserFilterCondition) {
1334 $this->setCondition($cond);
1335 }
1336 }
24e08e33
FB
1337 if (!is_null($sort)) {
1338 if ($sort instanceof UserFilterOrder) {
1339 $this->addSort($sort);
d865c296
FB
1340 } else if (is_array($sort)) {
1341 foreach ($sort as $s) {
1342 $this->addSort($s);
1343 }
24e08e33
FB
1344 }
1345 }
5dd9d823
FB
1346 }
1347
784745ce
FB
1348 private function buildQuery()
1349 {
d865c296
FB
1350 if (is_null($this->orderby)) {
1351 $orders = array();
1352 foreach ($this->sort as $sort) {
1353 $orders = array_merge($orders, $sort->buildSort($this));
1354 }
1355 if (count($orders) == 0) {
1356 $this->orderby = '';
1357 } else {
1358 $this->orderby = 'ORDER BY ' . implode(', ', $orders);
1359 }
1360 }
784745ce
FB
1361 if (is_null($this->query)) {
1362 $where = $this->root->buildCondition($this);
1363 $joins = $this->buildJoins();
1364 $this->query = 'FROM accounts AS a
eb1449b8
FB
1365 LEFT JOIN account_profiles AS ap ON (ap.uid = a.uid AND FIND_IN_SET(\'owner\', ap.perms))
1366 LEFT JOIN profiles AS p ON (p.pid = ap.pid)
784745ce
FB
1367 ' . $joins . '
1368 WHERE (' . $where . ')';
1369 }
1370 }
1371
1372 private function formatJoin(array $joins)
1373 {
1374 $str = '';
1375 foreach ($joins as $key => $infos) {
1376 $mode = $infos[0];
1377 $table = $infos[1];
1378 if ($mode == 'inner') {
1379 $str .= 'INNER JOIN ';
1380 } else if ($mode == 'left') {
1381 $str .= 'LEFT JOIN ';
1382 } else {
1383 Platal::page()->kill("Join mode error");
1384 }
1385 $str .= $table . ' AS ' . $key;
1386 if (isset($infos[2])) {
4927ee54 1387 $str .= ' ON (' . str_replace(array('$ME', '$PID', '$UID'), array($key, 'p.pid', 'a.uid'), $infos[2]) . ')';
784745ce
FB
1388 }
1389 $str .= "\n";
1390 }
1391 return $str;
1392 }
1393
1394 private function buildJoins()
1395 {
d865c296
FB
1396 $joins = array();
1397 foreach (self::$joinMethods as $method) {
1398 $joins = array_merge($joins, $this->$method());
1399 }
784745ce
FB
1400 return $this->formatJoin($joins);
1401 }
a087cc8d 1402
d865c296
FB
1403 private function getUIDList($uids = null, $count = null, $offset = null)
1404 {
1405 $this->buildQuery();
1406 $limit = '';
1407 if (!is_null($count)) {
1408 if (!is_null($offset)) {
76cbe885 1409 $limit = XDB::format('LIMIT {?}, {?}', (int)$offset, (int)$count);
d865c296 1410 } else {
76cbe885 1411 $limit = XDB::format('LIMIT {?}', (int)$count);
d865c296
FB
1412 }
1413 }
1414 $cond = '';
1415 if (!is_null($uids)) {
07eb5b0e 1416 $cond = ' AND a.uid IN ' . XDB::formatArray($uids);
d865c296
FB
1417 }
1418 $fetched = XDB::fetchColumn('SELECT SQL_CALC_FOUND_ROWS a.uid
1419 ' . $this->query . $cond . '
1420 GROUP BY a.uid
1421 ' . $this->orderby . '
1422 ' . $limit);
1423 $this->lastcount = (int)XDB::fetchOneCell('SELECT FOUND_ROWS()');
1424 return $fetched;
1425 }
1426
a087cc8d
FB
1427 /** Check that the user match the given rule.
1428 */
1429 public function checkUser(PlUser &$user)
1430 {
784745ce
FB
1431 $this->buildQuery();
1432 $count = (int)XDB::fetchOneCell('SELECT COUNT(*)
1433 ' . $this->query . XDB::format(' AND a.uid = {?}', $user->id()));
1434 return $count == 1;
a087cc8d
FB
1435 }
1436
1437 /** Filter a list of user to extract the users matching the rule.
1438 */
d865c296 1439 public function filter(array $users, $count = null, $offset = null)
a087cc8d 1440 {
4927ee54
FB
1441 $this->buildQuery();
1442 $table = array();
1443 $uids = array();
1444 foreach ($users as $user) {
07eb5b0e
FB
1445 if ($user instanceof PlUser) {
1446 $uid = $user->id();
1447 } else {
1448 $uid = $user;
1449 }
1450 $uids[] = $uid;
1451 $table[$uid] = $user;
4927ee54 1452 }
d865c296 1453 $fetched = $this->getUIDList($uids, $count, $offset);
a087cc8d 1454 $output = array();
4927ee54
FB
1455 foreach ($fetched as $uid) {
1456 $output[] = $table[$uid];
a087cc8d
FB
1457 }
1458 return $output;
1459 }
1460
d865c296 1461 public function getUIDs($count = null, $offset = null)
4927ee54 1462 {
d865c296
FB
1463 return $this->getUIDList(null, $count, $offset);
1464 }
1465
1466 public function getUsers($count = null, $offset = null)
1467 {
1468 return User::getBulkUsersWithUIDs($this->getUIDs($count, $offset));
4927ee54
FB
1469 }
1470
d865c296 1471 public function getTotalCount()
4927ee54 1472 {
38c6fe96 1473 if (is_null($this->lastcount)) {
aa21c568 1474 $this->buildQuery();
7e735012
FB
1475 return (int)XDB::fetchOneCell('SELECT COUNT(DISTINCT a.uid)
1476 ' . $this->query);
38c6fe96
FB
1477 } else {
1478 return $this->lastcount;
1479 }
4927ee54
FB
1480 }
1481
a087cc8d
FB
1482 public function setCondition(UserFilterCondition &$cond)
1483 {
1484 $this->root =& $cond;
784745ce 1485 $this->query = null;
a087cc8d
FB
1486 }
1487
24e08e33
FB
1488 public function addSort(UserFilterOrder &$sort)
1489 {
d865c296
FB
1490 $this->sort[] = $sort;
1491 $this->orderby = null;
24e08e33
FB
1492 }
1493
a087cc8d
FB
1494 static public function getLegacy($promo_min, $promo_max)
1495 {
a087cc8d 1496 if ($promo_min != 0) {
784745ce 1497 $min = new UFC_Promo('>=', self::GRADE_ING, intval($promo_min));
5dd9d823
FB
1498 } else {
1499 $min = new UFC_True();
a087cc8d 1500 }
a087cc8d 1501 if ($promo_max != 0) {
784745ce 1502 $max = new UFC_Promo('<=', self::GRADE_ING, intval($promo_max));
a087cc8d 1503 } else {
5dd9d823 1504 $max = new UFC_True();
a087cc8d 1505 }
5dd9d823 1506 return new UserFilter(new UFC_And($min, $max));
a087cc8d 1507 }
784745ce 1508
07eb5b0e
FB
1509 static public function sortByName()
1510 {
1511 return array(new UFO_Name(self::LASTNAME), new UFO_Name(self::FIRSTNAME));
1512 }
1513
1514 static public function sortByPromo()
1515 {
1516 return array(new UFO_Promo(), new UFO_Name(self::LASTNAME), new UFO_Name(self::FIRSTNAME));
1517 }
1518
aa21c568
FB
1519 static private function getDBSuffix($string)
1520 {
1521 return preg_replace('/[^a-z0-9]/i', '', $string);
1522 }
1523
1524
2d83cac9
RB
1525 /** Stores a new (and unique) table alias in the &$table table
1526 * @param &$table Array in which the table alias must be stored
1527 * @param $val Value which will then be used to build the join
1528 * @return Name of the newly created alias
1529 */
aa21c568
FB
1530 private $option = 0;
1531 private function register_optional(array &$table, $val)
1532 {
1533 if (is_null($val)) {
1534 $sub = $this->option++;
1535 $index = null;
1536 } else {
1537 $sub = self::getDBSuffix($val);
1538 $index = $val;
1539 }
1540 $sub = '_' . $sub;
1541 $table[$sub] = $index;
1542 return $sub;
1543 }
784745ce 1544
d865c296
FB
1545 /** DISPLAY
1546 */
38c6fe96 1547 const DISPLAY = 'display';
d865c296
FB
1548 private $pd = false;
1549 public function addDisplayFilter()
1550 {
1551 $this->pd = true;
1552 return '';
1553 }
1554
1555 private function displayJoins()
1556 {
1557 if ($this->pd) {
1558 return array('pd' => array('left', 'profile_display', '$ME.pid = $PID'));
1559 } else {
1560 return array();
1561 }
1562 }
1563
784745ce
FB
1564 /** NAMES
1565 */
d865c296 1566 /* name tokens */
784745ce
FB
1567 const LASTNAME = 'lastname';
1568 const FIRSTNAME = 'firstname';
1569 const NICKNAME = 'nickname';
1570 const PSEUDONYM = 'pseudonym';
1571 const NAME = 'name';
d865c296 1572 /* name variants */
784745ce
FB
1573 const VN_MARITAL = 'marital';
1574 const VN_ORDINARY = 'ordinary';
1575 const VN_OTHER = 'other';
1576 const VN_INI = 'ini';
d865c296
FB
1577 /* display names */
1578 const DN_FULL = 'directory_name';
1579 const DN_DISPLAY = 'yourself';
1580 const DN_YOURSELF = 'yourself';
1581 const DN_DIRECTORY = 'directory_name';
1582 const DN_PRIVATE = 'private_name';
1583 const DN_PUBLIC = 'public_name';
1584 const DN_SHORT = 'short_name';
1585 const DN_SORT = 'sort_name';
784745ce
FB
1586
1587 static public $name_variants = array(
1588 self::LASTNAME => array(self::VN_MARITAL, self::VN_ORDINARY),
d865c296
FB
1589 self::FIRSTNAME => array(self::VN_ORDINARY, self::VN_INI, self::VN_OTHER)
1590 );
784745ce
FB
1591
1592 static public function assertName($name)
1593 {
1594 if (!Profile::getNameTypeId($name)) {
1595 Platal::page()->kill('Invalid name type');
1596 }
1597 }
1598
d865c296
FB
1599 static public function isDisplayName($name)
1600 {
1601 return $name == self::DN_FULL || $name == self::DN_DISPLAY
1602 || $name == self::DN_YOURSELF || $name == self::DN_DIRECTORY
1603 || $name == self::DN_PRIVATE || $name == self::DN_PUBLIC
1604 || $name == self::DN_SHORT || $name == self::DN_SORT;
1605 }
1606
784745ce 1607 private $pn = array();
784745ce
FB
1608 public function addNameFilter($type, $variant = null)
1609 {
1610 if (!is_null($variant)) {
1611 $ft = $type . '_' . $variant;
1612 } else {
1613 $ft = $type;
1614 }
1615 $sub = '_' . $ft;
1616 self::assertName($ft);
1617
1618 if (!is_null($variant) && $variant == 'other') {
aa21c568 1619 $sub .= $this->option++;
784745ce
FB
1620 }
1621 $this->pn[$sub] = Profile::getNameTypeId($ft);
1622 return $sub;
1623 }
1624
1625 private function nameJoins()
1626 {
1627 $joins = array();
1628 foreach ($this->pn as $sub => $type) {
1629 $joins['pn' . $sub] = array('left', 'profile_name', '$ME.pid = $PID AND $ME.typeid = ' . $type);
1630 }
1631 return $joins;
1632 }
1633
1634
1635 /** EDUCATION
1636 */
1637 const GRADE_ING = 'Ing.';
1638 const GRADE_PHD = 'PhD';
1639 const GRADE_MST = 'M%';
1640 static public function isGrade($grade)
1641 {
38c6fe96 1642 return $grade == self::GRADE_ING || $grade == self::GRADE_PHD || $grade == self::GRADE_MST;
784745ce
FB
1643 }
1644
1645 static public function assertGrade($grade)
1646 {
1647 if (!self::isGrade($grade)) {
1648 Platal::page()->killError("Diplôme non valide");
1649 }
1650 }
1651
d865c296
FB
1652 static public function promoYear($grade)
1653 {
1654 // XXX: Definition of promotion for phds and masters might change in near future.
1655 return ($grade == UserFilter::GRADE_ING) ? 'entry_year' : 'grad_year';
1656 }
1657
784745ce
FB
1658 private $pepe = array();
1659 private $with_pee = false;
784745ce
FB
1660 public function addEducationFilter($x = false, $grade = null)
1661 {
1662 if (!$x) {
aa21c568
FB
1663 $index = $this->option;
1664 $sub = $this->option++;
784745ce
FB
1665 } else {
1666 self::assertGrade($grade);
1667 $index = $grade;
1668 $sub = $grade[0];
1669 $this->with_pee = true;
1670 }
1671 $sub = '_' . $sub;
1672 $this->pepe[$index] = $sub;
1673 return $sub;
1674 }
1675
1676 private function educationJoins()
1677 {
1678 $joins = array();
1679 if ($this->with_pee) {
1680 $joins['pee'] = array('inner', 'profile_education_enum', 'pee.abbreviation = \'X\'');
1681 }
1682 foreach ($this->pepe as $grade => $sub) {
1683 if ($this->isGrade($grade)) {
1684 $joins['pe' . $sub] = array('left', 'profile_education', '$ME.eduid = pee.id AND $ME.uid = $PID');
1685 $joins['pede' . $sub] = array('inner', 'profile_education_degree_enum', '$ME.id = pe' . $sub . '.degreeid AND $ME.abbreviation LIKE ' .
1686 XDB::format('{?}', $grade));
1687 } else {
1688 $joins['pe' . $sub] = array('left', 'profile_education', '$ME.uid = $PID');
1689 $joins['pee' . $sub] = array('inner', 'profile_education_enum', '$ME.id = pe' . $sub . '.eduid');
1690 $joins['pede' . $sub] = array('inner', 'profile_education_degree_enum', '$ME.id = pe' . $sub . '.degreeid');
1691 }
1692 }
1693 return $joins;
1694 }
4927ee54
FB
1695
1696
1697 /** GROUPS
1698 */
1699 private $gpm = array();
4927ee54
FB
1700 public function addGroupFilter($group = null)
1701 {
1702 if (!is_null($group)) {
1703 if (ctype_digit($group)) {
1704 $index = $sub = $group;
1705 } else {
1706 $index = $group;
aa21c568 1707 $sub = self::getDBSuffix($group);
4927ee54
FB
1708 }
1709 } else {
aa21c568 1710 $sub = 'group_' . $this->option++;
4927ee54
FB
1711 $index = null;
1712 }
1713 $sub = '_' . $sub;
1714 $this->gpm[$sub] = $index;
1715 return $sub;
1716 }
1717
1718 private function groupJoins()
1719 {
1720 $joins = array();
1721 foreach ($this->gpm as $sub => $key) {
1722 if (is_null($key)) {
1723 $joins['gpa' . $sub] = array('inner', 'groupex.asso');
1724 $joins['gpm' . $sub] = array('left', 'groupex.membres', '$ME.uid = $UID AND $ME.asso_id = gpa' . $sub . '.id');
1725 } else if (ctype_digit($key)) {
1726 $joins['gpm' . $sub] = array('left', 'groupex.membres', '$ME.uid = $UID AND $ME.asso_id = ' . $key);
1727 } else {
1728 $joins['gpa' . $sub] = array('inner', 'groupex.asso', XDB::format('$ME.diminutif = {?}', $key));
1729 $joins['gpm' . $sub] = array('left', 'groupex.membres', '$ME.uid = $UID AND $ME.asso_id = gpa' . $sub . '.id');
1730 }
1731 }
1732 return $joins;
1733 }
aa21c568
FB
1734
1735 /** EMAILS
1736 */
1737 private $e = array();
1738 public function addEmailRedirectFilter($email = null)
1739 {
1740 return $this->register_optional($this->e, $email);
1741 }
1742
1743 private $ve = array();
1744 public function addVirtualEmailFilter($email = null)
1745 {
21401768 1746 $this->addAliasFilter(self::ALIAS_FORLIFE);
aa21c568
FB
1747 return $this->register_optional($this->ve, $email);
1748 }
1749
21401768
FB
1750 const ALIAS_BEST = 'bestalias';
1751 const ALIAS_FORLIFE = 'forlife';
aa21c568
FB
1752 private $al = array();
1753 public function addAliasFilter($alias = null)
1754 {
1755 return $this->register_optional($this->al, $alias);
1756 }
1757
1758 private function emailJoins()
1759 {
1760 global $globals;
1761 $joins = array();
1762 foreach ($this->e as $sub=>$key) {
1763 if (is_null($key)) {
1764 $joins['e' . $sub] = array('left', 'emails', '$ME.uid = $UID AND $ME.flags != \'filter\'');
1765 } else {
1766 $joins['e' . $sub] = array('left', 'emails', XDB::format('$ME.uid = $UID AND $ME.flags != \'filter\' AND $ME.email = {?}', $key));
1767 }
1768 }
21401768 1769 foreach ($this->al as $sub=>$key) {
aa21c568 1770 if (is_null($key)) {
21401768
FB
1771 $joins['al' . $sub] = array('left', 'aliases', '$ME.id = $UID AND $ME.type IN (\'alias\', \'a_vie\')');
1772 } else if ($key == self::ALIAS_BEST) {
1773 $joins['al' . $sub] = array('left', 'aliases', '$ME.id = $UID AND $ME.type IN (\'alias\', \'a_vie\') AND FIND_IN_SET(\'bestalias\', $ME.flags)');
1774 } else if ($key == self::ALIAS_FORLIFE) {
1775 $joins['al' . $sub] = array('left', 'aliases', '$ME.id = $UID AND $ME.type = \'a_vie\'');
aa21c568 1776 } else {
21401768 1777 $joins['al' . $sub] = array('left', 'aliases', XDB::format('$ME.id = $UID AND $ME.type IN (\'alias\', \'a_vie\') AND $ME.alias = {?}', $key));
aa21c568 1778 }
aa21c568 1779 }
21401768 1780 foreach ($this->ve as $sub=>$key) {
aa21c568 1781 if (is_null($key)) {
21401768 1782 $joins['v' . $sub] = array('left', 'virtual', '$ME.type = \'user\'');
aa21c568 1783 } else {
21401768 1784 $joins['v' . $sub] = array('left', 'virtual', XDB::format('$ME.type = \'user\' AND $ME.alias = {?}', $key));
aa21c568 1785 }
21401768
FB
1786 $joins['vr' . $sub] = array('left', 'virtual_redirect', XDB::format('$ME.vid = v' . $sub . '.vid
1787 AND ($ME.redirect IN (CONCAT(al_forlife.alias, \'@\', {?}),
1788 CONCAT(al_forlife.alias, \'@\', {?}),
1789 a.email))',
1790 $globals->mail->domain, $globals->mail->domain2));
aa21c568
FB
1791 }
1792 return $joins;
1793 }
3f42a6ad
FB
1794
1795
c4b24511
RB
1796 /** ADDRESSES
1797 */
036d1637 1798 private $with_pa = false;
c4b24511
RB
1799 public function addAddressFilter()
1800 {
036d1637
RB
1801 $this->with_pa = true;
1802 return 'pa';
c4b24511
RB
1803 }
1804
1805 private function addressJoins()
1806 {
1807 $joins = array();
036d1637 1808 if ($this->with_pa) {
5d2e55c7 1809 $joins['pa'] = array('left', 'profile_address', '$ME.pid = $PID');
c4b24511
RB
1810 }
1811 return $joins;
1812 }
1813
1814
4083b126
RB
1815 /** CORPS
1816 */
1817
1818 private $pc = false;
1819 private $pce = array();
1820 private $pcr = false;
1821 public function addCorpsFilter($type)
1822 {
1823 $this->pc = true;
1824 if ($type == UFC_Corps::CURRENT) {
1825 $pce['pcec'] = 'current_corpsid';
1826 return 'pcec';
1827 } else if ($type == UFC_Corps::ORIGIN) {
1828 $pce['pceo'] = 'original_corpsid';
1829 return 'pceo';
1830 }
1831 }
1832
1833 public function addCorpsRankFilter()
1834 {
1835 $this->pc = true;
1836 $this->pcr = true;
1837 return 'pcr';
1838 }
1839
1840 private function corpsJoins()
1841 {
1842 $joins = array();
1843 if ($this->pc) {
1844 $joins['pc'] = array('left', 'profile_corps', '$ME.uid = $UID');
1845 }
1846 if ($this->pcr) {
1847 $joins['pcr'] = array('left', 'profile_corps_rank_enum', '$ME.id = pc.rankid');
1848 }
1849 foreach($this->pce as $sub => $field) {
1850 $joins[$sub] = array('left', 'profile_corps_enum', '$ME.id = pc.' . $field);
1851 }
1852 return $joins;
1853 }
1854
6a99c3ac
RB
1855 /** JOBS
1856 */
1857
1858 const JOB_SECTOR = 1;
1859 const JOB_SUBSECTOR = 2;
1860 const JOB_SUBSUBSECTOR = 4;
1861 const JOB_ALTERNATES = 8;
1862 const JOB_USERDEFINED = 16;
1863
1864 /** Joins :
1865 * pj => profile_job
1866 * pje => profile_job_enum
1867 * pjse => profile_job_sector_enum
1868 * pjsse => profile_job_subsector_enum
1869 * pjssse => profile_job_subsubsector_enum
1870 * pja => profile_job_alternates
1871 */
1872 private $with_pj = false;
1873 private $with_pje = false;
1874 private $with_pjse = false;
1875 private $with_pjsse = false;
1876 private $with_pjssse = false;
1877 private $with_pja = false;
1878
1879 public function addJobFilter()
1880 {
1881 $this->with_pj = true;
1882 return 'pj';
1883 }
1884
1885 public function addJobCompanyFilter()
1886 {
1887 $this->addJobFilter();
1888 $this->with_pje = true;
1889 return 'pje';
1890 }
1891
1892 public function addJobSectorizationFilter($type)
1893 {
1894 $this->addJobFilter();
1895 if ($type == self::JOB_SECTOR) {
1896 $this->with_pjse = true;
1897 return 'pjse';
1898 } else if ($type == self::JOB_SUBSECTOR) {
1899 $this->with_pjsse = true;
1900 return 'pjsse';
1901 } else if ($type == self::JOB_SUBSUBSECTOR) {
1902 $this->with_pjssse = true;
1903 return 'pjssse';
1904 } else if ($type == self::JOB_ALTERNATES) {
1905 $this->with_pja = true;
1906 return 'pja';
1907 }
1908 }
1909
1910 private function jobJoins()
1911 {
1912 $joins = array();
1913 if ($this->with_pj) {
1914 $joins['pj'] = array('left', 'profile_job', '$ME.uid = $UID');
1915 }
1916 if ($this->with_pje) {
1917 $joins['pje'] = array('left', 'profile_job_enum', '$ME.id = pj.jobid');
1918 }
1919 if ($this->with_pjse) {
1920 $joins['pjse'] = array('left', 'profile_job_sector_enum', '$ME.id = pj.sectorid');
1921 }
1922 if ($this->with_pjsse) {
1923 $joins['pjsse'] = array('left', 'profile_job_subsector_enum', '$ME.id = pj.subsectorid');
1924 }
1925 if ($this->with_pjssse) {
1926 $joins['pjssse'] = array('left', 'profile_job_subsubsector_enum', '$ME.id = pj.subsubsectorid');
1927 }
1928 if ($this->with_pja) {
1929 $joins['pja'] = array('left', 'profile_job_alternates', '$ME.subsubsectorid = pj.subsubsectorid');
1930 }
1931 return $joins;
1932 }
1933
0a2e9c74
RB
1934 /** NETWORKING
1935 */
1936
1937 private $with_pnw = false;
1938 public function addNetworkingFilter()
1939 {
1940 $this->with_pnw = true;
1941 return 'pnw';
1942 }
1943
1944 private function networkingJoins()
1945 {
1946 $joins = array();
1947 if ($this->with_pnw) {
1948 $joins['pnw'] = array('left', 'profile_networking', '$ME.uid = $UID');
1949 }
1950 return $joins;
1951 }
1952
6d62969e
RB
1953 /** PHONE
1954 */
1955
2d83cac9 1956 private $with_ptel = false;
6d62969e
RB
1957
1958 public function addPhoneFilter()
1959 {
2d83cac9 1960 $this->with_ptel = true;
6d62969e
RB
1961 return 'ptel';
1962 }
1963
1964 private function phoneJoins()
1965 {
1966 $joins = array();
2d83cac9 1967 if ($this->with_ptel) {
6d62969e
RB
1968 $joins['ptel'] = array('left', 'profile_phone', '$ME.uid = $UID');
1969 }
1970 return $joins;
1971 }
1972
ceb512d2
RB
1973 /** MEDALS
1974 */
1975
2d83cac9 1976 private $with_pmed = false;
ceb512d2
RB
1977 public function addMedalFilter()
1978 {
2d83cac9 1979 $this->with_pmed = true;
ceb512d2
RB
1980 return 'pmed';
1981 }
1982
1983 private function medalJoins()
1984 {
1985 $joins = array();
2d83cac9 1986 if ($this->with_pmed) {
ceb512d2
RB
1987 $joins['pmed'] = array('left', 'profile_medals_sub', '$ME.uid = $UID');
1988 }
1989 return $joins;
1990 }
1991
671b7073
RB
1992 /** MENTORING
1993 */
1994
1995 private $pms = array();
1996 const MENTOR_EXPERTISE = 1;
1997 const MENTOR_COUNTRY = 2;
1998 const MENTOR_SECTOR = 3;
1999
2000 public function addMentorFilter($type)
2001 {
2002 switch($type) {
2003 case MENTOR_EXPERTISE:
2004 $pms['pme'] = 'profile_mentor';
2005 return 'pme';
2006 case MENTOR_COUNTRY:
2007 $pms['pmc'] = 'profile_mentor_country';
2008 return 'pmc';
2009 case MENTOR_SECTOR:
2010 $pms['pms'] = 'profile_mentor_sector';
2011 return 'pms';
2012 default:
5d2e55c7 2013 Platal::page()->killError("Undefined mentor filter.");
671b7073
RB
2014 }
2015 }
2016
2017 private function mentorJoins()
2018 {
2019 $joins = array();
2020 foreach ($this->pms as $sub => $tab) {
2021 $joins[$sub] = array('left', $tab, '$ME.uid = $UID');
2022 }
2023 return $joins;
2024 }
2025
3f42a6ad
FB
2026 /** CONTACTS
2027 */
2028 private $cts = array();
2029 public function addContactFilter($uid = null)
2030 {
2031 return $this->register_optional($this->cts, is_null($uid) ? null : 'user_' . $uid);
2032 }
2033
2034 private function contactJoins()
2035 {
2036 $joins = array();
2037 foreach ($this->cts as $sub=>$key) {
2038 if (is_null($key)) {
2039 $joins['c' . $sub] = array('left', 'contacts', '$ME.contact = $UID');
2040 } else {
2041 $joins['c' . $sub] = array('left', 'contacts', XDB::format('$ME.uid = {?} AND $ME.contact = $UID', substr($key, 5)));
2042 }
2043 }
2044 return $joins;
2045 }
4e7bf1e0
FB
2046
2047
2048 /** CARNET
2049 */
2050 private $wn = array();
2051 public function addWatchRegistrationFilter($uid = null)
2052 {
2053 return $this->register_optional($this->wn, is_null($uid) ? null : 'user_' . $uid);
2054 }
2055
2056 private $wp = array();
2057 public function addWatchPromoFilter($uid = null)
2058 {
2059 return $this->register_optional($this->wp, is_null($uid) ? null : 'user_' . $uid);
2060 }
2061
2062 private $w = array();
2063 public function addWatchFilter($uid = null)
2064 {
2065 return $this->register_optional($this->w, is_null($uid) ? null : 'user_' . $uid);
2066 }
2067
2068 private function watchJoins()
2069 {
2070 $joins = array();
2071 foreach ($this->w as $sub=>$key) {
2072 if (is_null($key)) {
2073 $joins['w' . $sub] = array('left', 'watch');
2074 } else {
2075 $joins['w' . $sub] = array('left', 'watch', XDB::format('$ME.uid = {?}', substr($key, 5)));
2076 }
2077 }
2078 foreach ($this->wn as $sub=>$key) {
2079 if (is_null($key)) {
2080 $joins['wn' . $sub] = array('left', 'watch_nonins', '$ME.ni_id = $UID');
2081 } else {
2082 $joins['wn' . $sub] = array('left', 'watch_nonins', XDB::format('$ME.uid = {?} AND $ME.ni_id = $UID', substr($key, 5)));
2083 }
2084 }
2085 foreach ($this->wn as $sub=>$key) {
2086 if (is_null($key)) {
2087 $joins['wn' . $sub] = array('left', 'watch_nonins', '$ME.ni_id = $UID');
2088 } else {
2089 $joins['wn' . $sub] = array('left', 'watch_nonins', XDB::format('$ME.uid = {?} AND $ME.ni_id = $UID', substr($key, 5)));
2090 }
2091 }
2092 foreach ($this->wp as $sub=>$key) {
2093 if (is_null($key)) {
2094 $joins['wp' . $sub] = array('left', 'watch_promo');
2095 } else {
2096 $joins['wp' . $sub] = array('left', 'watch_promo', XDB::format('$ME.uid = {?}', substr($key, 5)));
2097 }
2098 }
2099 return $joins;
2100 }
a087cc8d 2101}
8363588b 2102// }}}
3f42a6ad 2103
a087cc8d
FB
2104// vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8:
2105?>