Fix inverted test.
[platal.git] / classes / profile.php
CommitLineData
e7b93962
FB
1<?php
2/***************************************************************************
34ade5a6 3 * Copyright (C) 2003-2009 Polytechnique.org *
e7b93962
FB
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
22class Profile
23{
f5642983
FB
24 static private $v_values = array('public' => array('public'),
25 'ax' => array('ax', 'public'),
26 'private' => array('private', 'ax', 'public'));
27 const VISIBILITY_PUBLIC = 'public';
28 const VISIBILITY_AX = 'ax';
29 const VISIBILITY_PRIVATE = 'private';
30
31 const ADDRESS_MAIN = 0x000001;
32 const ADDRESS_PERSO = 0x000002;
33 const ADDRESS_PRO = 0x000004;
34 const ADDRESS_ALL = 0x000006;
35 const ADDRESS_POSTAL = 0x000008;
36
37 const EDUCATION_MAIN = 0x000010;
4bc5b8f0
FB
38 const EDUCATION_EXTRA = 0x000020;
39 const EDUCATION_ALL = 0x000040;
40 const EDUCATION_FINISHED = 0x000080;
41 const EDUCATION_CURRENT = 0x000100;
f5642983 42
4bc5b8f0
FB
43 const JOBS_MAIN = 0x001000;
44 const JOBS_ALL = 0x002000;
45 const JOBS_FINISHED = 0x004000;
46 const JOBS_CURRENT = 0x008000;
f5642983 47
e7b93962
FB
48 private $pid;
49 private $hrpid;
3e53a496
FB
50 private $data = array();
51
f5642983
FB
52 private $visibility = null;
53
b774ddab 54 private function __construct(array $data)
e7b93962 55 {
b774ddab 56 $this->data = $data;
832e6fcb
FB
57 $this->pid = $this->data['pid'];
58 $this->hrpid = $this->data['hrpid'];
e7b93962
FB
59 }
60
61 public function id()
62 {
63 return $this->pid;
64 }
65
66 public function hrid()
67 {
68 return $this->hrpid;
69 }
70
d5e60905
FB
71 public function promo()
72 {
73 return $this->promo;
74 }
75
94b72319
FB
76 /** Print a name with the given formatting:
77 * %s = • for women
78 * %f = firstname
79 * %l = lastname
80 * %F = fullname
81 * %S = shortname
82 * %p = promo
83 */
84 public function name($format)
85 {
86 return str_replace(array('%s', '%f', '%l', '%F', '%S', '%p'),
87 array($this->isFemale() ? '•' : '',
88 $this->first_name, $this->last_name,
89 $this->full_name, $this->short_name,
90 $this->promo), $format);
91 }
92
93 public function fullName($with_promo = false)
94 {
95 if ($with_promo) {
96 return $this->full_name . ' (' . $this->promo . ')';
97 }
98 return $this->full_name;
99 }
100
101 public function shortName($with_promo = false)
102 {
103 if ($with_promo) {
104 return $this->short_name . ' (' . $this->promo . ')';
105 }
106 return $this->short_name;
107 }
108
109 public function firstName()
110 {
08c91036 111 return $this->firstname;
94b72319
FB
112 }
113
114 public function lastName()
115 {
08c91036 116 return $this->lastname;
94b72319
FB
117 }
118
119 public function isFemale()
120 {
121 return $this->sex == PlUser::GENDER_FEMALE;
122 }
123
124 public function data()
125 {
126 $this->first_name;
127 return $this->data;
128 }
129
3e53a496
FB
130 public function __get($name)
131 {
132 if (property_exists($this, $name)) {
133 return $this->$name;
134 }
135
3e53a496
FB
136 if (isset($this->data[$name])) {
137 return $this->data[$name];
138 }
139
140 return null;
141 }
142
143 public function __isset($name)
144 {
145 return property_exists($this, $name) || isset($this->data[$name]);
146 }
147
f5642983
FB
148 public function setVisibilityLevel($visibility)
149 {
150 if ($visibility != self::VISIBILITY_PRIVATE
151 && $visibility != self::VISIBILITY_AX
152 && $visibility != self::VISIBILITY_PUBLIC) {
153 Platal::page()->kill("Visibility invalide: " . $visibility);
154 }
155 $this->visibility = self::$v_values[$visibility];
156 }
157
4bc5b8f0
FB
158
159 /* Addresses
160 */
161 public function getAddresses($flags, $limit = null)
f5642983
FB
162 {
163 $where = XDB::format('pa.pid = {?}', $this->id());
164 if ($flags & self::ADDRESS_MAIN) {
165 $where .= ' AND FIND_IN_SET(\'current\', pa.flags)';
166 }
167 if ($flags & self::ADDRESS_POSTAL) {
168 $where .= ' AND FIND_IN_SET(\'mail\', pa.flags)';
169 }
170 if ($this->visibility) {
171 $where .= ' AND pa.pub IN ' . XDB::formatArray($this->visibility);
172 }
173 $type = array();
174 if ($flags & self::ADDRESS_PRO) {
175 $type[] = 'job';
176 }
177 if ($flags & self::ADDRESS_PERSO) {
178 $type[] = 'home';
179 }
180 if (count($type) > 0) {
181 $where .= ' AND pa.type IN ' . XDB::formatArray($type);
182 }
4bc5b8f0 183 $limit = is_null($limit) ? '' : XDB::format('LIMIT {?}', (int)$limit);
f5642983
FB
184 return XDB::iterator('SELECT pa.text, pa.postalCode, pa.type, pa.latitude, pa.longitude,
185 gl.name AS locality, gas.name AS subAdministrativeArea,
186 ga.name AS administrativeArea, gc.countryFR AS country,
187 FIND_IN_SET(\'current\', pa.flags) AS current,
188 FIND_IN_SET(\'temporary\', pa.flags) AS temporary,
189 FIND_IN_SET(\'secondary\', pa.flags) AS secondary,
190 FIND_IN_SET(\'mail\', pa.flags) AS mail, pa.type
191 FROM profile_addresses AS pa
192 LEFT JOIN geoloc_localities AS gl ON (gl.id = pa.localityId)
193 LEFT JOIN geoloc_administrativeareas AS ga ON (ga.id = pa.administrativeAreaId)
194 LEFT JOIN geoloc_administrativeareas AS gas ON (gas.id = pa.subAdministrativeAreaId)
195 LEFT JOIN geoloc_countries AS gc ON (gc.iso_3166_1_a2 = pa.countryId)
4bc5b8f0
FB
196 WHERE ' . $where . '
197 ORDER BY pa.id
198 ' . $limit);
f5642983
FB
199 }
200
201 public function getMainAddress()
202 {
203 $it = $this->getAddresses(self::ADDRESS_PERSO | self::ADDRESS_MAIN);
204 if ($it->total() == 0) {
205 return null;
206 } else {
207 return $it->next();
208 }
209 }
3e53a496 210
4bc5b8f0
FB
211
212 /* Educations
213 */
214 public function getEducations($flags, $limit = null)
215 {
216 $where = XDB::format('pe.uid = {?}', $this->id());
217 if ($flags & self::EDUCATION_MAIN) {
218 $where .= ' AND FIND_IN_SET(\'primary\', pe.flags)';
219 } else if ($flags & self::EDUCATION_EXTRA) {
220 $where .= ' AND NOT FIND_IN_SET(\'primary\', pe.flags)';
221 } else if ($flags & self::EDUCATION_FINISHED) {
222 $where .= ' AND pe.grad_year <= YEAR(CURDATE())';
223 } else if ($flags & self::EDUCATION_CURRENT) {
224 $where .= ' AND pe.grad_year > YEAR(CURDATE())';
225 }
226 $limit = is_null($limit) ? '' : XDB::format('LIMIT {?}', (int)$limit);
227 return XDB::iterator('SELECT pe.entry_year, pe.grad_year, pe.program,
228 pee.name AS school, pee.abbreviation AS school_short, pee.url AS school_url, gc.countryFR AS country,
229 pede.degree, pede.abbreviation AS degree_short, pede.level AS degree_level, pefe.field,
230 FIND_IN_SET(\'primary\', pe.flags) AS prim
231 FROM profile_education AS pe
232 INNER JOIN profile_education_enum AS pee ON (pe.eduid = pee.id)
233 LEFT JOIN geoloc_countries AS gc ON (gc.iso_3166_1_a2 = pee.country)
234 INNER JOIN profile_education_degree_enum AS pede ON (pe.degreeid = pede.id)
235 LEFT JOIN profile_education_field_enum AS pefe ON (pe.fieldid = pefe.id)
236 WHERE ' . $where . '
237 ORDER BY NOT FIND_IN_SET(\'primary\', pe.flags), pe.entry_year, pe.id
238 ' . $limit);
239 }
240
241 public function getExtraEducations($limit = null)
242 {
243 return $this->getEducations(self::EDUCATION_EXTRA, $limit);
244 }
245
246
e7b93962
FB
247 public function owner()
248 {
249 return User::getSilent($this);
250 }
251
b774ddab
FB
252 private static function fetchProfileData(array $pids)
253 {
254 if (count($pids) == 0) {
255 return array();
256 }
257 return XDB::fetchAllAssoc('SELECT p.*, p.sex = \'female\' AS sex, pe.entry_year, pe.grad_year,
258 pn_f.name AS firstname, pn_l.name AS lastname, pn_n.name AS nickname,
259 IF(pn_uf.name IS NULL, pn_f.name, pn_uf.name) AS firstname_usual,
260 IF(pn_ul.name IS NULL, pn_l.name, pn_ul.name) AS lastname_usual,
261 pd.promo AS promo, pd.short_name, pd.directory_name AS full_name
262 FROM profiles AS p
263 INNER JOIN profile_display AS pd ON (pd.pid = p.pid)
264 INNER JOIN profile_education AS pe ON (pe.uid = p.pid AND FIND_IN_SET(\'primary\', pe.flags))
265 INNER JOIN profile_name AS pn_f ON (pn_f.pid = p.pid
266 AND pn_f.typeid = ' . self::getNameTypeId('lastname', true) . ')
267 INNER JOIN profile_name AS pn_l ON (pn_l.pid = p.pid
268 AND pn_l.typeid = ' . self::getNameTypeId('firstname', true) . ')
269 LEFT JOIN profile_name AS pn_uf ON (pn_uf.pid = p.pid
270 AND pn_uf.typeid = ' . self::getNameTypeId('lastname_ordinary', true) . ')
271 LEFT JOIN profile_name AS pn_ul ON (pn_ul.pid = p.pid
272 AND pn_ul.typeid = ' . self::getNameTypeId('firstname_ordinary', true) . ')
273 LEFT JOIN profile_name aS pn_n ON (pn_n.pid = p.pid
274 AND pn_n.typeid = ' . self::getNameTypeId('nickname', true) . ')
275 WHERE p.pid IN ' . XDB::formatArray($pids) . '
276 GROUP BY p.pid');
277 }
278
279 public static function getPID($login)
280 {
281 if ($login instanceof PlUser) {
282 return XDB::fetchOneCell('SELECT pid
283 FROM account_profiles
284 WHERE uid = {?} AND FIND_IN_SET(\'owner\', perms)',
285 $login->id());
286 } else if (ctype_digit($login)) {
287 return XDB::fetchOneCell('SELECT pid
288 FROM profiles
289 WHERE pid = {?}', $login);
290 } else {
291 return XDB::fetchOneCell('SELECT pid
292 FROM profiles
293 WHERE hrpid = {?}', $login);
294 }
295 }
296
297
e7b93962
FB
298 /** Return the profile associated with the given login.
299 */
a3118782
FB
300 public static function get($login)
301 {
b774ddab
FB
302 $pid = self::getPID($login);
303 if (!is_null($pid)) {
304 $data = self::fetchProfileData(array($pid));
305 return new Profile(array_pop($data));
306 } else {
efe597c5
FB
307 /* Let say we can identify a profile using the identifiers of its owner.
308 */
455ea0c9
FB
309 if (!($login instanceof PlUser)) {
310 $user = User::getSilent($login);
311 if ($user && $user->hasProfile()) {
312 return $user->profile();
313 }
efe597c5 314 }
3e53a496 315 return null;
e7b93962
FB
316 }
317 }
a3118782 318
b774ddab
FB
319 /** Return profiles for the list of pids.
320 */
321 public static function getBulkProfilesWithPIDs(array $pids)
322 {
323 if (count($pids) == 0) {
324 return array();
325 }
326 $data = self::fetchProfileData($pids);
327 $inv = array_flip($pids);
328 $profiles = array();
329 foreach ($data AS $p) {
330 $p = new Profile($p);
331 $key = $inv[$p->id()];
332 $profiles[$key] = $p;
333 }
334 return $profiles;
335 }
336
337 /** Return profiles for uids.
338 */
339 public static function getBulkProfilesWithUIDS(array $uids)
340 {
341 if (count($uids) == 0) {
342 return array();
343 }
344 $table = XDB::fetchAllAssoc('uid', 'SELECT ap.uid, ap.pid
345 FROM account_profiles AS ap
346 WHERE FIND_IN_SET(\'owner\', ap.perms)
347 AND ap.uid IN ' . XDB::formatArray($uids));
348 return self::getBulkProfilesWithPIDs($table);
349 }
350
a3118782
FB
351 public static function getNameTypeId($type, $for_sql = false)
352 {
353 if (!S::has('name_types')) {
eb6207f7 354 $table = XDB::fetchAllAssoc('type', 'SELECT id, type
32742f84 355 FROM profile_name_enum');
a3118782
FB
356 S::set('name_types', $table);
357 } else {
358 $table = S::v('name_types');
359 }
360 if ($for_sql) {
361 return XDB::escape($table[$type]);
362 } else {
363 return $table[$type];
364 }
365 }
e7b93962
FB
366}
367
368// vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8:
369?>