Fixes deprecated features in PHP 5.3.x.
[platal.git] / include / validations.inc.php
CommitLineData
0337d704 1<?php
2/***************************************************************************
12262f13 3 * Copyright (C) 2003-2011 Polytechnique.org *
0337d704 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
0337d704 22define('SIZE_MAX', 32768);
23
ce8ca505 24global $globals;
2f151d5f 25
0337d704 26
616918d0 27/** Virtual class to adapt for every possible implementation.
0337d704 28 */
612a2d8a 29abstract class Validate
0337d704 30{
31 // {{{ properties
eaf30d86 32
5daf68f6 33 public $user;
612a2d8a 34
35 public $stamp;
36 public $unique;
616918d0 37 // Enable the refuse button.
612a2d8a 38 public $refuse = true;
eaf30d86 39
612a2d8a 40 public $type;
41 public $comments = Array();
616918d0
SJ
42 // Validations rules: comments for administrators.
43 public $rules = 'Mieux vaut laisser une demande de validation à un autre administrateur que de valider une requête illégale ou que de refuser une demande légitime.';
0337d704 44
e33b29e5
SJ
45 // Unless differently stated, a validation must be done by a site administrator.
46 public $requireAdmin = true;
47
0337d704 48 // }}}
49 // {{{ constructor
eaf30d86 50
616918d0
SJ
51 /** Constructor
52 * @param $_user: user object that required the validation.
53 * @param $_unique: set to false if a profile can have multiple requests of this type.
54 * @param $_type: request's type.
0337d704 55 */
26ba053e 56 public function __construct(User $_user, $_unique, $_type)
0337d704 57 {
532c06cf 58 $this->user = &$_user;
0337d704 59 $this->stamp = date('YmdHis');
60 $this->unique = $_unique;
61 $this->type = $_type;
8f2104cb 62 $this->promo = $this->user->promo();
0337d704 63 }
eaf30d86 64
0337d704 65 // }}}
66 // {{{ function submit()
67
616918d0
SJ
68 /** Sends data to validation.
69 * It also deletes multiple requests for a couple (profile, type)
70 * when $this->unique is set to true.
0337d704 71 */
612a2d8a 72 public function submit()
0337d704 73 {
0337d704 74 if ($this->unique) {
1bf36cd1
SJ
75 XDB::execute('DELETE FROM requests
76 WHERE uid = {?} AND type = {?}',
77 $this->user->id(), $this->type);
0337d704 78 }
eaf30d86 79
0337d704 80 $this->stamp = date('YmdHis');
1bf36cd1
SJ
81 XDB::execute('INSERT INTO requests (uid, type, data, stamp)
82 VALUES ({?}, {?}, {?}, {?})',
616918d0 83 $this->user->id(), $this->type, $this, $this->stamp);
0337d704 84
84868ee9 85 global $globals;
ebfdf077 86 $globals->updateNbValid();
0337d704 87 return true;
88 }
89
90 // }}}
91 // {{{ function update()
92
612a2d8a 93 protected function update()
0337d704 94 {
1bf36cd1
SJ
95 XDB::execute('UPDATE requests
96 SET data = {?}, stamp = stamp
97 WHERE uid = {?} AND type = {?} AND stamp = {?}',
5daf68f6 98 $this, $this->user->id(), $this->type, $this->stamp);
0337d704 99 return true;
100 }
101
102 // }}}
103 // {{{ function clean()
eaf30d86 104
616918d0
SJ
105 /** Deletes request from 'requests' table.
106 * If $this->unique is set, it deletes every requests of this type.
0337d704 107 */
d17761d8 108 public function clean()
0337d704 109 {
95e36b0f
SJ
110 global $globals;
111
0337d704 112 if ($this->unique) {
1bf36cd1
SJ
113 $success = XDB::execute('DELETE FROM requests
114 WHERE uid = {?} AND type = {?}',
5daf68f6 115 $this->user->id(), $this->type);
0337d704 116 } else {
1bf36cd1
SJ
117 $success = XDB::execute('DELETE FROM requests
118 WHERE uid = {?} AND type = {?} AND stamp = {?}',
5daf68f6 119 $this->user->id(), $this->type, $this->stamp);
0337d704 120 }
ebfdf077 121 $globals->updateNbValid();
84868ee9 122 return $success;
0337d704 123 }
124
125 // }}}
126 // {{{ function handle_formu()
eaf30d86 127
616918d0 128 /** Handles form validation.
0337d704 129 */
612a2d8a 130 public function handle_formu()
0337d704 131 {
e33b29e5
SJ
132 if ($this->requireAdmin && !S::admin()) {
133 $this->trigError('Vous n\'avez pas les permissions nécessaires pour valider cette demande.');
134 return false;
135 }
136
0337d704 137 if (Env::has('delete')) {
138 $this->clean();
616918d0 139 $this->trigSuccess('Requête supprimée.');
0337d704 140 return true;
141 }
142
616918d0 143 // Data updates.
6aa01fed 144 if (Env::has('edit')) {
145 if ($this->handle_editor()) {
146 $this->update();
616918d0 147 $this->trigSuccess('Requête mise à jour.');
6aa01fed 148 return true;
149 }
150 return false;
151 }
152
616918d0 153 // Comment addition.
0337d704 154 if (Env::has('hold') && Env::has('comm')) {
4791ff77 155 $formid = Env::i('formid');
156 foreach ($this->comments as $comment) {
157 if ($comment[2] === $formid) {
158 return true;
159 }
160 }
90608d68 161 if (!strlen(trim(Env::v('comm')))) {
162 return true;
163 }
616918d0 164 $this->comments[] = array(S::user()->login(), Env::v('comm'), $formid);
0337d704 165
616918d0 166 // Sends email to our hotline.
0337d704 167 global $globals;
b9c53090 168 $mailer = new PlMailer();
0337d704 169 $mailer->setSubject("Commentaires de validation {$this->type}");
170 $mailer->setFrom("validation+{$this->type}@{$globals->mail->domain}");
b9c53090 171 $mailer->addTo($globals->core->admin_email);
0337d704 172
53092def 173 $body = "Validation {$this->type} pour {$this->user->login()}\n\n"
5daf68f6
VZ
174 . S::user()->login() . " a ajouté le commentaire :\n\n"
175 . Env::v('comm') . "\n\n"
176 . "cf la discussion sur : " . $globals->baseurl . "/admin/validate";
0337d704 177
178 $mailer->setTxtBody(wordwrap($body));
179 $mailer->send();
180
181 $this->update();
616918d0 182 $this->trigSuccess('Commentaire ajouté.');
0337d704 183 return true;
184 }
185
186 if (Env::has('accept')) {
187 if ($this->commit()) {
188 $this->sendmail(true);
189 $this->clean();
faefdbb7 190 $this->trigSuccess('Email de validation envoyé');
0337d704 191 return true;
192 } else {
a7d35093 193 $this->trigError('Erreur lors de la validation');
0337d704 194 return false;
195 }
196 }
197
198 if (Env::has('refuse')) {
5e2307dc 199 if (Env::v('comm')) {
0337d704 200 $this->sendmail(false);
201 $this->clean();
616918d0 202 $this->trigSuccess('Email de refus envoyé.');
0337d704 203 return true;
204 } else {
6bb2f79a 205 $this->trigError('Pas de motivation pour le refus&nbsp;!!!');
0337d704 206 }
207 }
208
209 return false;
210 }
211
212 // }}}
213 // {{{ function sendmail
214
612a2d8a 215 protected function sendmail($isok)
0337d704 216 {
217 global $globals;
1e33266a 218 $mailer = new PlMailer();
0337d704 219 $mailer->setSubject($this->_mail_subj());
220 $mailer->setFrom("validation+{$this->type}@{$globals->mail->domain}");
5daf68f6 221 $mailer->addTo("\"{$this->user->fullName()}\" <{$this->user->bestEmail()}>");
0337d704 222 $mailer->addCc("validation+{$this->type}@{$globals->mail->domain}");
223
5daf68f6 224 $body = ($this->user->isFemale() ? "Chère camarade,\n\n" : "Cher camarade,\n\n")
0337d704 225 . $this->_mail_body($isok)
9be4a981 226 . (Env::has('comm') ? "\n\n" . Env::v('comm') : '')
5353e51e
SJ
227 . "\n\nCordialement,\n-- \nL'équipe de Polytechnique.org\n"
228 . $this->_mail_ps($isok);
0337d704 229
230 $mailer->setTxtBody(wordwrap($body));
231 $mailer->send();
232 }
233
234 // }}}
235 // {{{ function trig()
eaf30d86 236
a7d35093 237 protected function trigError($msg)
612a2d8a 238 {
d7610c35 239 Platal::page()->trigError($msg);
a7d35093
FB
240 }
241
242 protected function trigWarning($msg)
243 {
d7610c35 244 Platal::page()->trigWarning($msg);
a7d35093
FB
245 }
246
247 protected function trigSuccess($msg)
248 {
d7610c35 249 Platal::page()->trigSuccess($msg);
0337d704 250 }
eaf30d86 251
0337d704 252 // }}}
20d7932b 253 // {{{ function get_typed_request()
0337d704 254
616918d0
SJ
255 /**
256 * @param $pid: profile's pid
257 * @param $type: request's type
258 * @param $stamp: request's timestamp
0337d704 259 *
616918d0 260 * Should only be used to retrieve an object in the databse with Validate::get_typed_request(...)
0337d704 261 */
612a2d8a 262 static public function get_typed_request($uid, $type, $stamp = -1)
0337d704 263 {
0337d704 264 if ($stamp == -1) {
1bf36cd1
SJ
265 $res = XDB::query('SELECT data
266 FROM requests
267 WHERE uid = {?} and type = {?}',
268 $uid, $type);
0337d704 269 } else {
1bf36cd1
SJ
270 $res = XDB::query('SELECT data, DATE_FORMAT(stamp, "%Y%m%d%H%i%s")
271 FROM requests
272 WHERE uid = {?} AND type = {?} and stamp = {?}',
273 $uid, $type, $stamp);
0337d704 274 }
275 if ($result = $res->fetchOneCell()) {
33b47675 276 $result = Validate::unserialize($result);
0337d704 277 } else {
278 $result = false;
279 }
280 return($result);
281 }
282
283 // }}}
02838718 284 // {{{ function get_request_by_id()
285
286 static public function get_request_by_id($id)
287 {
288 list($uid, $type, $stamp) = explode('_', $id, 3);
289 return Validate::get_typed_request($uid, $type, $stamp);
290 }
291
292 // }}}
5b0dc389 293 // {{{ function get_typed_requests()
294
616918d0 295 /** Same as get_typed_request() but return an array of objects.
5b0dc389 296 */
612a2d8a 297 static public function get_typed_requests($uid, $type)
5b0dc389 298 {
1bf36cd1
SJ
299 $res = XDB::iterRow('SELECT data
300 FROM requests
301 WHERE uid = {?} and type = {?}',
302 $uid, $type);
5b0dc389 303 $array = array();
304 while (list($data) = $res->next()) {
33b47675 305 $array[] = Validate::unserialize($data);
5b0dc389 306 }
307 return $array;
308 }
309
310 // }}}
bb0727ea
VZ
311 // {{{ function get_typed_requests_count()
312
616918d0 313 /** Same as get_typed_requests() but return the count of available requests.
bb0727ea
VZ
314 */
315 static public function get_typed_requests_count($uid, $type)
316 {
1bf36cd1
SJ
317 $res = XDB::query('SELECT COUNT(data)
318 FROM requests
319 WHERE uid = {?} and type = {?}',
320 $uid, $type);
bb0727ea
VZ
321 return $res->fetchOneCell();
322 }
323
324 // }}}
0337d704 325 // {{{ function _mail_body
326
612a2d8a 327 abstract protected function _mail_body($isok);
eaf30d86 328
0337d704 329 // }}}
330 // {{{ function _mail_subj
331
612a2d8a 332 abstract protected function _mail_subj();
eaf30d86 333
0337d704 334 // }}}
9be4a981
SJ
335 // {{{ function _mail_ps
336
337 protected function _mail_ps($isok)
338 {
5353e51e 339 return '';
9be4a981
SJ
340 }
341
342 // }}}
0337d704 343 // {{{ function commit()
eaf30d86 344
616918d0 345 /** Inserts data in database.
0337d704 346 */
612a2d8a 347 abstract public function commit();
0337d704 348
349 // }}}
350 // {{{ function formu()
eaf30d86 351
616918d0 352 /** Retunrs the name of the form's template. */
612a2d8a 353 abstract public function formu();
0337d704 354
355 // }}}
6aa01fed 356 // {{{ function editor()
357
616918d0 358 /** Returns the name of the edition form's template. */
612a2d8a 359 public function editor()
360 {
361 return null;
362 }
6aa01fed 363
364 // }}}
e18888f4 365 // {{{ function answers()
366
616918d0 367 /** Automatic answers table for this type of validation. */
612a2d8a 368 public function answers()
369 {
e18888f4 370 static $answers_table;
371 if (!isset($answers_table[$this->type])) {
616918d0
SJ
372 $r = XDB::query('SELECT id, title, answer
373 FROM requests_answers
374 WHERE category = {?}',
375 $this->type);
745539c0 376 $answers_table[$this->type] = $r->fetchAllAssoc();
e18888f4 377 }
378 return $answers_table[$this->type];
379 }
380
381 // }}}
616918d0 382 // {{{ function id()
ed5b9703 383
612a2d8a 384 public function id()
ed5b9703 385 {
5daf68f6 386 return $this->user->id() . '_' . $this->type . '_' . $this->stamp;
ed5b9703 387 }
388
389 // }}}
fba760d2 390 // {{{ function ruleText()
391
392 public function ruleText()
393 {
394 return str_replace('\'', '\\\'', $this->rules);
395 }
396
397 // }}}
33b47675 398 // {{{ function unserialize()
4407871a 399
33b47675
FB
400 public static function unserialize($data)
401 {
616918d0 402 return unserialize($data);
33b47675 403 }
4407871a
SJ
404
405 // }}}
7b094a73
FB
406
407 /** Return an iterator over the validation concerning the given type
408 * and the given user.
409 *
410 * @param type The type of the validations to fetch, null mean "any type"
411 * @param applyTo A User or a Profile object the validation applies to.
412 */
413 public static function iterate($type = null, $applyTo = null)
414 {
415 function toValidation($elt)
416 {
417 list($result, $stamp) = $elt;
418 $result = Validate::unserialize($result);
419 $result->stamp = $stamp;
420 return $result;
421 }
422
423 $where = array();
424 if ($type) {
425 $where[] = XDB::format('type = {?}', $type);
426 }
427 if ($applyTo) {
428 if ($applyTo instanceof User) {
429 $where[] = XDB::format('uid = {?}', $applyTo->id());
430 } else if ($applyTo instanceof Profile) {
431 $where[] = XDB::format('pid = {?}', $applyTo->id());
432 }
433 }
434 if (!empty($where)) {
435 $where = 'WHERE ' . implode('AND', $where);
436 }
437 $it = XDB::iterRow('SELECT data, DATE_FORMAT(stamp, "%Y%m%d%H%i%s")
438 FROM requests
439 ' . $where . '
440 ORDER BY stamp');
441 return PlIteratorUtils::map($it, 'toValidation');
442 }
4407871a
SJ
443}
444
445/** Virtual class for profile related validation.
446 */
447abstract class ProfileValidate extends Validate
448{
449 // {{{ properties
450
451 public $profile;
452 public $profileOwner;
453 public $userIsProfileOwner;
a0fce0c6 454 public $ownerIsRegistered;
4407871a
SJ
455
456 // }}}
457 // {{{ constructor
458
616918d0 459 /** Constructor
4407871a
SJ
460 * @param $_user: user object that required the validation.
461 * @param $_profile: profile object that is to be modified,
462 * its owner (if exists) can differ from $_user.
463 * @param $_unique: set to false if a profile can have multiple requests of this type.
464 * @param $_type: request's type.
465 */
26ba053e 466 public function __construct(User $_user, Profile $_profile, $_unique, $_type)
4407871a
SJ
467 {
468 parent::__construct($_user, $_unique, $_type);
469 $this->profile = &$_profile;
470 $this->profileOwner = $this->profile->owner();
a0fce0c6
SJ
471 $this->userIsProfileOwner = (!is_null($this->profileOwner)
472 && $this->profileOwner->id() == $this->user->id());
473 $this->ownerIsRegistered = $this->profile->isActive();
4407871a
SJ
474 }
475
476 // }}}
477 // {{{ function submit()
478
479 /** Sends data to validation.
480 * It also deletes multiple requests for a couple (profile, type)
481 * when $this->unique is set to true.
482 */
483 public function submit()
484 {
485 if ($this->unique) {
486 XDB::execute('DELETE FROM requests
487 WHERE pid = {?} AND type = {?}',
488 $this->profile->id(), $this->type);
489 }
490
491 $this->stamp = date('YmdHis');
492 XDB::execute('INSERT INTO requests (uid, pid, type, data, stamp)
d84b97ba 493 VALUES ({?}, {?}, {?}, {?}, {?})',
4407871a
SJ
494 $this->user->id(), $this->profile->id(), $this->type, $this, $this->stamp);
495
496 global $globals;
497 $globals->updateNbValid();
498 return true;
499 }
500
501 // }}}
502 // {{{ function update()
503
504 protected function update()
505 {
506 XDB::execute('UPDATE requests
507 SET data = {?}, stamp = stamp
508 WHERE pid = {?} AND type = {?} AND stamp = {?}',
509 $this, $this->profile->id(), $this->type, $this->stamp);
510 return true;
511 }
512
513 // }}}
514 // {{{ function clean()
515
516 /** Deletes request from 'requests' table.
517 * If $this->unique is set, it deletes every requests of this type.
518 */
519 public function clean()
520 {
521 global $globals;
522
523 if ($this->unique) {
524 $success = XDB::execute('DELETE FROM requests
525 WHERE pid = {?} AND type = {?}',
526 $this->profile->id(), $this->type);
527 } else {
528 $success = XDB::execute('DELETE FROM requests
529 WHERE pid = {?} AND type = {?} AND stamp = {?}',
530 $this->profile->id(), $this->type, $this->stamp);
531 }
532 $globals->updateNbValid();
533 return $success;
534 }
535
536 // }}}
537 // {{{ function sendmail
538
539 protected function sendmail($isok)
540 {
a0fce0c6
SJ
541 // Only sends email if the profile's owner exists and is registered.
542 if ($this->ownerIsRegistered) {
543 global $globals;
4407871a 544
a0fce0c6
SJ
545 $mailer = new PlMailer();
546 $mailer->setSubject($this->_mail_subj());
547 $mailer->setFrom("validation+{$this->type}@{$globals->mail->domain}");
548 $mailer->addTo("\"{$this->profile->fullName()}\" <{$this->profileOwner->bestEmail()}>");
549 $mailer->addCc("validation+{$this->type}@{$globals->mail->domain}");
550 $body = ($this->profile->isFemale() ? "Chère camarade,\n\n" : "Cher camarade,\n\n")
551 . $this->_mail_body($isok)
552 . (Env::has('comm') ? "\n\n" . Env::v('comm') : '')
553 . "\n\nCordialement,\n-- \nL'équipe de Polytechnique.org\n"
554 . $this->_mail_ps($isok);
555 $mailer->setTxtBody(wordwrap($body));
556 $mailer->send();
557 }
4407871a
SJ
558 }
559
560 // }}}
561 // {{{ function get_typed_request()
562
563 /**
564 * @param $pid: profile's pid
565 * @param $type: request's type
566 * @param $stamp: request's timestamp
567 *
568 * Should only be used to retrieve an object in the databse with Validate::get_typed_request(...)
569 */
570 static public function get_typed_request($pid, $type, $stamp = -1)
571 {
572 if ($stamp == -1) {
573 $res = XDB::query('SELECT data
574 FROM requests
575 WHERE pid = {?} and type = {?}',
576 $pid, $type);
577 } else {
578 $res = XDB::query('SELECT data, DATE_FORMAT(stamp, "%Y%m%d%H%i%s")
579 FROM requests
580 WHERE pid = {?} AND type = {?} and stamp = {?}',
581 $pid, $type, $stamp);
582 }
583 if ($result = $res->fetchOneCell()) {
584 $result = Validate::unserialize($result);
585 } else {
586 $result = false;
587 }
588 return $result;
589 }
590
591 // }}}
592 // {{{ function get_request_by_id()
593
594 static public function get_request_by_id($id)
595 {
596 list($pid, $type, $stamp) = explode('_', $id, 3);
597 return Validate::get_typed_request($pid, $type, $stamp);
598 }
599
600 // }}}
601 // {{{ function get_typed_requests()
602
603 /** Same as get_typed_request() but return an array of objects.
604 */
605 static public function get_typed_requests($pid, $type)
606 {
607 $res = XDB::iterRow('SELECT data
608 FROM requests
328bd54a
SJ
609 WHERE pid = {?} and type = {?}
610 ORDER BY stamp',
4407871a
SJ
611 $pid, $type);
612 $array = array();
613 while (list($data) = $res->next()) {
614 $array[] = Validate::unserialize($data);
615 }
616 return $array;
617 }
618
619 // }}}
620 // {{{ function get_typed_requests_count()
621
622 /** Same as get_typed_requests() but returns the count of available requests.
623 */
624 static public function get_typed_requests_count($pid, $type)
625 {
626 $res = XDB::query('SELECT COUNT(data)
627 FROM requests
628 WHERE pid = {?} and type = {?}',
629 $pid, $type);
630 return $res->fetchOneCell();
631 }
632
633 // }}}
616918d0 634 // {{{ function id()
4407871a
SJ
635
636 public function id()
637 {
d134ddda 638 return $this->profile->id() . '_' . $this->type . '_' . $this->stamp;
4407871a
SJ
639 }
640
641 // }}}
0337d704 642}
643
4407871a
SJ
644foreach (glob(dirname(__FILE__) . '/validations/*.inc.php') as $file) {
645 require_once $file;
0337d704 646}
647
a7de4ef7 648/* vim: set expandtab shiftwidth=4 tabstop=4 softtabstop=4 foldmethod=marker enc=utf-8: */
0337d704 649?>