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