Add ProfileFields
[platal.git] / include / profilefields.inc.php
CommitLineData
9f21bd15
RB
1<?php
2/***************************************************************************
3 * Copyright (C) 2003-2010 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
22// {{{ class ProfileField
23/** To store a "field" from the profile
24 * Provides functions for loading a batch of such data
25 */
26abstract class ProfileField
27{
28 /** The profile to which this field belongs
29 */
30 public $pid;
31
32 /** Fetches data from the database for the given pids, compatible with
33 * the visibility context.
34 * @param $pids An array of pids
35 * @param $visibility The level of visibility fetched fields must have
36 * @return a PlIterator yielding data suitable for a "new ProfileBlah($data)"
37 */
38 abstract public static function fetchData(array $pids, $visibility);
39
40 public static function buildForPID($cls, $pid, $visibility)
41 {
42 $res = self::buildFromPIDs($cls, array($pid), $visibility);
43 return array_pop($res);
44 }
45
46 /** Build a list of ProfileFields from a set of pids
47 * @param $cls The name of the field to create ('ProfileMedals', ...)
48 * @param $pids An array of pids
49 * @param $visibility An array of allowed visibility contexts
50 * @return An array of $pid => ProfileField
51 */
52 public static function buildFromPIDs($cls, array $pids, $visibility)
53 {
54 $it = new ProfileFieldIterator($cls, $pids, $visibility);
55 $res = array();
56 while ($pf = $it->next()) {
57 $res[$pf->pid] = $pf;
58 }
59 return $res;
60 }
61}
62// }}}
63
64// {{{ class ProfileFieldIterator
65class ProfileFieldIterator implements PlIterator
66{
67 private $data;
68 private $cls;
69
70 public function __construct($cls, array $pids, $visibility)
71 {
72 $this->data = call_user_func(array($cls, 'fetchData'), $pids, $visibility);
73 $this->cls = $cls;
74 }
75
76 public function next()
77 {
78 $d = $this->data->next();
79 if ($d == null) {
80 return null;
81 } else {
82 $cls = $this->cls;
83 return new $cls($d);
84 }
85 }
86
87 public function total()
88 {
89 return $this->data->total();
90 }
91
92 public function first()
93 {
94 return $this->data->first();
95 }
96
97 public function last()
98 {
99 return $this->data->last();
100 }
101}
102// }}}
103
104// {{{ class Phone
105class Phone
106{
107 const TYPE_FAX = 'fax';
108 const TYPE_FIXED = 'fixed';
109 const TYPE_MOBILE = 'mobile';
110 public $type;
111
112 public $search;
113 public $display;
114 public $comment = '';
115
116 const LINK_JOB = 'job';
117 const LINK_ADDRESS = 'address';
118 const LINK_PROFILE = 'user';
119 const LINK_COMPANY = 'hq';
120 public $link_type;
121 public $link_id;
122
123 /** Fields are :
124 * $type, $search, $display, $link_type, $link_id, $comment, $pid, $id
125 */
126 public function __construct($data)
127 {
128 foreach ($data as $key => $val) {
129 $this->$key = $val;
130 }
131 }
132}
133// }}}
134// {{{ class Company
135class Company
136{
137 public $id;
138 public $name;
139 public $acronym;
140 public $url;
141 public $phone = null;
142 public $address = null;
143
144 /** Fields are:
145 * $id, $name, $acronym, $url
146 */
147 public function __construct($date)
148 {
149 foreach ($data as $key => $val) {
150 $this->$key = $val;
151 }
152 }
153
154 public function setPhone(Phone &$phone)
155 {
156 if ($phone->link_type == Phone::LINK_COMPANY && $phone->link_id == $this->id) {
157 $this->phone = $phone;
158 }
159 }
160
161 public function setAddress(Address &$address)
162 {
163 if ($address->link_type == Address::LINK_COMPANY && $address->link_id == $this->id) {
164 $this->address = $address;
165 }
166 }
167
168}
169// }}}
170// {{{ class Job
171class Job
172{
173 public $pid;
174 public $id;
175
176 private $company = null;
177 private $phones = array();
178 private $address = null;
179
180 public $company_id;
181
182 public $description;
183 public $url;
184 public $email;
185
186 /** Fields are:
187 * pid, id, company_id, description, url, email
188 */
189 public function __construct($data)
190 {
191 foreach ($data as $key => $val) {
192 $this->$key = $val;
193 }
194 }
195
196 public function phones()
197 {
198 return $this->phones;
199 }
200
201 public function company()
202 {
203 return $this->company;
204 }
205
206 public function addPhone(Phone &$phone)
207 {
208 if ($phone->link_type == Phone::LINK_JOB && $phone->link_id == $this->id && $phone->pid == $this->pid) {
209 $this->phones[] = $phone;
210 }
211 }
212
213 public function setAddress(Address $address)
214 {
215 if ($address->link_id == Address::LINK_JOB && $address->link_id == $this->id && $address->pid == $this->pid) {
216 $this->address = $address;
217 }
218 }
219
220 public function setCompany(Company $company)
221 {
222 $this->company = $company;
223 }
224}
225// }}}
226// {{{ class Address
227class Address
228{
229 const LINK_JOB = 'job';
230 const LINK_COMPANY = 'hq';
231 const LINK_PROFILE = 'home';
232
233 public $link_id;
234 public $link_type;
235
236 public $flags;
237 public $text;
238 public $postcode;
239 public $country;
240
241 private $phones = array();
242
243 /** Fields are:
244 * pƮd, id, link_id, link_type, flags, text, postcode, country
245 */
246 public function __construct($data)
247 {
248 foreach ($data as $key => $val) {
249 $this->$key = $val;
250 }
251 }
252
253 public function addPhone(Phone &$phone)
254 {
255 if ($phone->link_type == Phone::LINK_ADDRESS && $phone->link_id == $this->id && $phone->pid == $this->pid) {
256 $this->phones[] = $phone;
257 }
258 }
259
260 public function phones()
261 {
262 return $this->phones;
263 }
264}
265// }}}
266
267// {{{ class ProfileEducation [ Field ]
268class ProfileEducation extends ProfileField
269{
270 public $schools = array();
271
272 private function __construct(PlIterator $it)
273 {
274 $this->visibility = Profile::VISIBILITY_PUBLIC;
275 while ($edu = $it->next()) {
276 $this->schools[$edu['id']] = $edu;
277 }
278 }
279
280 public static function fetchData(array $pids, $visibility)
281 {
282 $data = XDB::iterator('SELECT *
283 FROM profile_education
284 WHERE pid IN {?}
285 ORDER BY ' . XDB::formatCustomOrder('pid', $pids),
286 $pids);
287
288 return PlIteratorUtils::subIterator($data, PlIteratorUtils::arrayValueCallback('pid'));
289 }
290}
291// }}}
292// {{{ class ProfileMedals [ Field ]
293class ProfileMedals extends ProfileField
294{
295 public $medals = array();
296
297 private function __construct(PlIterator $it)
298 {
299 while ($medal = $it->next()) {
300 $this->medals[$medal['mid']] = $medal['gid'];
301 }
302 }
303
304 public static function fetchData(array $pids, $visibility)
305 {
306 $data = XDB::iterator('SELECT pm.pid, pm.mid, pm.gid
307 FROM profile_medals AS pm
308 LEFT JOIN profiles AS p ON (pm.pid = p.pid)
309 WHERE pm.pid IN {?} AND p.medals_pub IN {?}
310 ORDER BY ' . XDB::formatCustomOrder('pm.pid', $pids),
311 XDB::formatArray($pids),
312 XDB::formatArray($visibility)
313 );
314
315 return PlIteratorUtils::subIterator($data, PlIteratorUtils::arrayValueCallback('pid'));
316 }
317}
318// }}}
319// {{{ class ProfileNetworking [ Field ]
320class ProfileNetworking extends ProfileField
321{
322 private $networks = array();
323 private $visibilities = array();
324
325 private function __construct(PlIterator $it)
326 {
327 while ($network = $it->next()) {
328 $this->networks[$network['nwid']] = $network['address'];
329 $this->visibilities[$network['nwid']] = $network['pub'];
330 }
331 }
332
333 public static function fetchData(array $pids, $visibility)
334 {
335 $data = XDB::iterator('SELECT pid, nwid, address, pub
336 FROM profile_networking
337 WHERE pid IN {?} AND pub IN {?}
338 ORDER BY ' . XDB::formatCustomOrder('pid', $pids),
339 XDB::formatArray($pids),
340 XDB::formatArray($visibility)
341 );
342
343 return PlIteratorUtils::subIterator($data, PlIteratorUtils::arrayValueCallback('pid'));
344 }
345
346 public function networks()
347 {
348 $nws = array();
349 foreach ($this->visibilities as $id => $vis) {
350 if ($this->profile->isVisible($vis)) {
351 $nws[$id] = $this->networks[$id];
352 }
353 }
354 return $nws;
355 }
356}
357// }}}
358// {{{ class ProfilePhoto [ Field ]
359class ProfilePhoto extends ProfileField
360{
361 public $pic;
362
363 public function __construct(array $data)
364 {
365 if ($data == null || count($data) == 0) {
366 $this->pic = null;
367 } else {
368 $this->pid = $data['pid'];
369 $this->pic = PlImage::fromDATA($data['attach'],
370 $data['attachmime'],
371 $data['x'],
372 $data['y']);
373 }
374 }
375
376 public static function fetchData(array $pids, $visibility)
377 {
378 $data = XDB::iterator('SELECT *
379 FROM profile_photos
380 WHERE pid IN {?} AND attachmime IN (\'jpeg\', \'png\') AND pub IN {?}
381 ORDER BY ' . XDB::formatCustomOrder('pid', $pids),
382 $pids,
383 $visibility
384 );
385
386 return $data;
387 }
388}
389// }}}
390// {{{ class ProfileCorps [ Field ]
391class ProfileCorps extends ProfileField
392{
393 public $original;
394 public $current;
395 public $rank;
396
397 private function __construct(array $data)
398 {
399 $this->original = $data['original_corpsid'];
400 $this->current = $data['current_corpsid'];
401 $this->rank = $data['rankid'];
402 $this->visibility = $data['corps_pub'];
403 }
404
405 public static function fetchData(array $pids, $visibility)
406 {
407 $data = XDB::iterator('SELECT pid, original_corpsid, current_corpsid,
408 rankid
409 FROM profile_corps
410 WHERE pid IN {?} AND corps_pub IN {?}
411 ORDER BY ' . XDB::formatCustomOrder('pid', $pids),
412 XDB::formatArray($pids),
413 XDB::formatArray($visibility)
414 );
415
416 return $data;
417 }
418}
419// }}}
420
421/** Loading of data for a Profile :
422 * 1) load jobs, addresses, phones
423 * 2) attach phones to addresses, jobs and profiles
424 * 3) attach addresses to jobs and profiles
425 */
426
427// {{{ class ProfileAddresses [ Field ]
428class ProfileAddresses extends ProfileField
429{
430 private $addresses = array();
431
432 private function __construct(PlIterator $addrs)
433 {
434 while ($addr = $it->next()) {
435 $this->addresses[] = Address::buildFromData($addr);
436 }
437 }
438
439 public static function fetchData(array $pids, $visibility)
440 {
441 $data = XDB::iterator('SELECT text, postalCode, type, latitude, longitude,
442 flags, type
443 FROM profile_addresses
444 WHERE pid in {?} AND pub IN {?}
445 ORDER BY ' . XDB::formatCustomOrder('pid', $pids),
446 XDB::formatArray($pids),
447 XDB::formatArray($visibility)
448 );
449
450 return PlIteratorUtils::subIterator($data, PlIteratorUtils::arrayValueCallback('pid'));
451 }
452
453 public static function addPhones(array $addresses, $phones)
454 {
455 foreach ($phones as $phone) {
456 if ($phone->link_type == Phone::LINK_ADDRESS) {
457 $addresses[$phone->link_id]->addPhone($phone);
458 }
459 }
460 return $addresses;
461 }
462}
463// }}}
464// {{{ class ProfilePhones [ Field ]
465class ProfilePhones extends ProfileField
466{
467 private $phones = array();
468
469 private function __construct(PlIterator $phones)
470 {
471 while ($phone = $it->next()) {
472 $this->phones[] = Phone::buildFromData($phone);
473 }
474 }
475
476 public static function fetchData(array $pids, $visibility)
477 {
478 $data = XDB::iterator('SELECT type, search, display, link_type, comment
479 FROM profile_phones
480 WHERE pid IN {?} AND pub IN {?}
481 ORDER BY ' . XDB::formatCustomOrder('pid', $pids),
482 XDB::formatArray($pids),
483 XDB::formatArray($visibility)
484 );
485 return PlIteratorUtils::subIterator($data, PlIteratorUtils::arrayValueCallback('pid'));
486 }
487}
488// }}}
489// {{{ class ProfileJobs [ Field ]
490class ProfileJobs extends ProfileField
491{
492 private $jobs = array();
493
494 private function __construct(PlIterator $jobs)
495 {
496 while ($job = $jobs->next()) {
497 $this->jobs[] = Jobs::buildFromData($job);
498 }
499 }
500
501 public static function fetchData(array $pids, $visibility)
502 {
503 $data = XDB::iterator('SELECT description, url, jobid, IF(email_pub IN {?}, email, NULL) AS email
504 FROM profile_job
505 WHERE pid IN {?} AND pub IN {?}
506 ORDER BY ' . XDB::formatCustomOrder('pid', $pids),
507 XDB::formatArray($visibility),
508 XDB::formatArray($pids),
509 XDB::formatArray($visibility)
510 );
511 return PlIteratorUtils::subIterator($data, PlIteratorUtils::arrayValueCallback('pid'));
512 }
513
514 public static function addPhones(array $jobs, array $phones)
515 {
516 foreach ($phones as $phone)
517 {
518 if ($phone->link_type == Phone::LINK_JOB) {
519 $jobs[$phone->link_id]->addPhones($phone);
520 }
521 }
522 return $jobs;
523 }
524
525 public static function addAddresses(array $jobs, array $addresses)
526 {
527 foreach ($addresses as $address)
528 {
529 if ($address->link_type == Address::LINK_JOB) {
530 $jobs[$address->link_id]->setAddress($address);
531 }
532 }
533 return $jobs;
534 }
535
536 public static function addCompanies(array $jobs, array $companies)
537 {
538 foreach ($jobs as $job)
539 {
540 $job->setCompany($companies[$job->company_id]);
541 }
542 return $jobs;
543 }
544}
545// }}}
546
547// {{{ class CompanyList
548class CompanyList
549{
550 static private $fullload = false;
551 static private $companies = array();
552
553 static public function preload($pids = array())
554 {
555 if (self::$fullload) {
556 return;
557 }
558 // Load raw data
559 if (count($pids)) {
560 $join = 'LEFT JOIN profile_jobs ON (profile_job.jobid = profile_job_enum.id)';
561 $where = 'profile_jobs.pid IN ' . XDB::formatArray($pids);
562 } else {
563 $join = '';
564 $where = '';
565 }
566
567 $it = XDB::iterator('SELECT pje.id, pje.name, pje.acronmy, pje.url,
568 pa.flags, pa.text, pa.postcode, pa.country,
569 pa.link_type, pa.pub
570 FROM profile_job_enum AS pje
571 LEFT JOIN profile_addresses AS pa ON (pje.id = pa.jobid AND pa.type = \'hq\')
572 ' . $join . '
573 ' . $where);
574 while ($row = $it->next()) {
575 $cp = Company::buildFromData($row);
576 $addr = Address::buildFromData($row);
577 $cp->setAddress($addr);
578 self::$companies[$row['id']] = $cp;
579 }
580
581 // TODO: add phones to addresses
582 if (count($pids) == 0) {
583 self::$fullload = true;
584 }
585 }
586
587 static public function getCompany($id)
588 {
589 if (!array_key_exists($id, self::$companies)) {
590 self::preload();
591 }
592 return self::$companies[$id];
593 }
594}
595
596// vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8:
597?>