2 /***************************************************************************
3 * Copyright (C) 2003-2007 Polytechnique.org *
4 * http://opensource.polytechnique.org/ *
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. *
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. *
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 *
19 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
20 ***************************************************************************/
22 // {{{ class Survey : static database managing functions
25 // {{{ static function retrieveList() : gets the list of available survey (current, old and not validated surveys)
26 public static function retrieveList($type, $tpl = true
)
35 $where = 'valid=1 AND end > NOW()';
39 $where = 'valid=1 AND end <= NOW()';
44 $sql = 'SELECT survey_id, title, end
48 return XDB
::iterator($sql);
50 return XDB
::iterRow($sql);
55 // {{{ static function proposeSurvey() : stores a proposition of survey in database (before validation)
56 public static function proposeSurvey($survey)
58 $sql = 'INSERT INTO survey_questions
66 $data = $survey->storeArray();
67 return XDB
::execute($sql, serialize($survey), $data['question'], $data['comment'], S
::v('uid'), $data['end'], $data['promos']);
71 // {{{ static function updateSurvey() : updates a survey in database (before validation)
72 public static function updateSurvey($survey, $sid)
74 $sql = 'UPDATE survey_questions
80 WHERE survey_id={?};';
81 $data = $survey->storeArray();
82 return XDB
::execute($sql, serialize($survey), $data['question'], $data['comment'], $data['end'], $data['promos'], $sid);
86 // {{{ static function retrieveSurvey() : gets a survey in database (and unserialize the survey object structure)
87 public static function retrieveSurvey($sid)
89 $sql = 'SELECT questions, title, description, end, promos, valid
92 $res = XDB
::query($sql, $sid);
93 $data = $res->fetchOneAssoc();
94 if (is_null($data) ||
!is_array($data)) {
97 $survey = unserialize($data['questions']);
98 if (isset($data['end'])) {
99 $data['end'] = preg_replace('#^(\d{4})-(\d{2})-(\d{2})$#', '\3/\2/\1', $data['end']);
101 $survey->update(array('question' => $data['title'], 'comment' => $data['description'], 'end' => $data['end'], 'promos' => $data['promos']));
102 $survey->setValid($data['valid']);
107 // {{{ static function retrieveSurveyInfo() : gets information about a survey (title, description, end date, restrictions) but does not unserialize the survey object structure
108 public static function retrieveSurveyInfo($sid)
110 $sql = 'SELECT title, description, end, promos, valid
111 FROM survey_questions
112 WHERE survey_id={?}';
113 $res = XDB
::query($sql, $sid);
114 return $res->fetchOneAssoc();
118 // {{{ static function validateSurvey() : validates a survey
119 public static function validateSurvey($sid)
121 $sql = 'UPDATE survey_questions
123 WHERE survey_id={?};';
124 return XDB
::execute($sql, $sid);
128 // {{{ static function deleteSurvey() : deletes a survey (and all its votes)
129 public static function deleteSurvey($sid)
131 $sql1 = 'DELETE FROM survey_questions
132 WHERE survey_id={?};';
133 $sql2 = 'DELETE FROM survey_answers
134 WHERE survey_id={?};';
135 $sql3 = 'DELETE FROM survey_votes
136 WHERE survey_id={?};';
137 return (XDB
::execute($sql1, $sid) && XDB
::execute($sql2, $sid) && XDB
::execute($sql3, $sid));
143 // {{{ abstract class SurveyQuestion
144 abstract class SurveyQuestion
146 // {{{ static properties and methods regarding question types
147 private static $types = array('text' => 'texte court',
148 'textarea' => 'texte long',
149 'num' => 'numérique',
151 'checkbox' => 'checkbox',
152 'personal' => 'informations personnelles');
154 public static function getTypes()
159 public static function isType($t)
161 return array_key_exists($t, self
::$types);
165 // {{{ common properties, constructor, and basic methods
171 protected function __construct($i, $args)
174 $this->update($args);
177 protected function update($a)
179 $this->question
= $a['question'];
180 $this->comment
= $a['comment'];
183 protected function getId()
188 abstract protected function getQuestionType();
191 // {{{ tree manipulation methods : not implemented here (but definition needed)
192 protected function addChildNested($i, $c)
197 protected function addChildAfter($i, $c)
202 protected function delChild($i)
208 // {{{ function edit($i, $a) : searches and edits question $i
209 protected function edit($i, $a)
211 if ($this->id
== $i) {
220 // {{{ functions toArray() and searchToArray($i) : (searches and) converts to array
221 protected function toArray()
223 return $this->storeArray();
226 protected function searchToArray($i)
228 if ($this->id
== $i) {
229 return $this->storeArray();
235 protected function storeArray()
237 return array('type' => $this->getQuestionType(), 'id' => $this->id
, 'question' => $this->question
, 'comment' => $this->comment
);
241 // {{{ function checkSyntax() : checks question elements (before storing into database)
242 protected function checkSyntax()
248 // {{{ function vote() : handles vote
249 protected function checkAnswer($ans)
254 function vote($sid, $vid, $a)
256 $ans = $this->checkAnswer($a[$this->getId
]);
259 'INSERT INTO survey_answers
263 answer = "{?}"', $sid, $vid, $id, $ans);
270 // {{{ abstract class SurveyTreeable extends SurveyQuestion : questions that allow nested ones
271 abstract class SurveyTreeable
extends SurveyQuestion
273 // {{{ common properties, constructor
276 protected function __construct($i, $args)
278 parent
::__construct($i, $args);
279 $this->children
= array();
283 // {{{ tree manipulation functions : actual implementation
284 protected function hasChild()
286 return !is_null($this->children
) && is_array($this->children
);
289 protected function addChildNested($i, $c)
291 if ($this->getId() == $i) {
292 if ($this->hasChild()) {
293 array_unshift($this->children
, $c);
295 $this->children
= array($c);
299 foreach ($this->children
as $child) {
300 if ($child->addChildNested($i, $c)) {
308 protected function addChildAfter($i, $c)
311 for ($k = 0; $k < count($this->children
); $k++
) {
312 if ($this->children
[$k]->getId() == $i) {
316 if ($this->children
[$k]->addChildAfter($i, $c)) {
322 array_splice($this->children
, $k+
1, 0, array($c));
328 protected function delChild($i)
331 for ($k = 0; $k < count($this->children
); $k++
) {
332 if ($this->children
[$k]->getId() == $i) {
336 if ($this->children
[$k]->delChild($i)) {
342 array_splice($this->children
, $k, 1);
349 // {{{ function edit() with tree support
350 protected function edit($i, $a)
352 if ($this->getId() == $i) {
356 foreach ($this->children
as $child) {
357 if ($child->edit($i, $a)) {
366 // {{{ functions toArray() and searchToArray() with tree support
367 protected function toArray()
369 if ($this->hasChild()) {
371 foreach ($this->children
as $child) {
372 $cArr[] = $child->toArray();
374 $a = $this->storeArray();
375 $a['children'] = $cArr;
378 return $this->storeArray();
382 protected function searchToArray($i)
384 if ($this->getId() == $i) {
385 return $this->storeArray();
387 foreach ($this->children
as $child) {
388 $a = $child->searchToArray($i);
389 if (!is_null($a) && is_array($a)) {
398 // {{{ function checkSyntax()
399 protected function checkSyntax()
402 foreach ($this->children
as $child) {
403 $a = $child->checkSyntax();
408 return (empty($rArr))? null
: $rArr;
412 // {{{ function vote()
413 function vote($sid, $vid, $a)
415 parent
::vote($sid, $vid, $a);
416 if ($this->hasChild()) {
417 foreach ($this->children
as $c) {
418 $c->vote($sid, $vid, $a);
426 // {{{ class SurveyRoot extends SurveyTreeable : root of any survey, actually the only entry point (no public methods outside this class)
427 class SurveyRoot
extends SurveyTreeable
429 // {{{ properties, constructor and basic methods
436 public function __construct($args)
438 parent
::__construct(0, $args);
442 public function update($args)
444 parent
::update($args);
445 //$this->beginning = $args['beginning_year'] . "-" . $args['beginning_month'] . "-" . $args['beginning_day'];
446 //$this->end = $args['end_year'] . "-" . $args['end_year'] . "-" . $args['end_day'];
447 if (preg_match('#^\d{2}/\d{2}/\d{4}$#', $args['end'])) {
448 $this->end
= preg_replace('#^(\d{2})/(\d{2})/(\d{4})$#', '\3-\2-\1', $args['end']);
450 $this->end
= (preg_match('#^\d{4}-\d{2}-\d{2}$#', $args['end']))?
$args['end'] : '#';
452 $this->promos
= ($args['promos'] == '' ||
preg_match('#^(\d{4}-?|(\d{4})?-\d{4})(,(\d{4}-?|(\d{4})?-\d{4}))*$#', $args['promos']))?
$args['promos'] : '#';
455 private function getNextId()
458 return $this->last_id
;
461 public function setValid($v)
463 $this->valid
= (boolean
) $v;
466 public function isValid()
471 protected function getQuestionType()
477 // {{{ function factory($type, $args) : builds a question according to the given type
478 public function factory($t, $args)
480 $i = $this->getNextId();
483 return new SurveyText($i, $args);
485 return new SurveyTextarea($i, $args);
487 return new SurveyNum($i, $args);
489 return new SurveyRadio($i, $args);
491 return new SurveyCheckbox($i, $args);
493 return new SurveyPersonal($i, $args);
500 // {{{ methods needing public access
501 public function addChildNested($i, $c)
503 return !$this->isValid() && parent
::addChildNested($i, $c);
506 public function addChildAfter($i, $c)
508 return !$this->isValid() && parent
::addChildAfter($i, $c);
511 public function delChild($i)
513 return !$this->isValid() && parent
::delChild($i);
516 public function edit($i, $a)
518 return (!$this->isValid() ||
$this->getId() == $i) && parent
::edit($i, $a);
521 public function toArray()
523 return parent
::toArray();
526 public function searchToArray($i)
528 return parent
::searchToArray($i);
532 // {{{ function storeArray()
533 public function storeArray()
535 $rArr = parent
::storeArray();
536 $rArr['beginning'] = $this->beginning
;
537 $rArr['end'] = $this->end
;
538 $rArr['promos'] = $this->promos
;
539 $rArr['valid'] = $this->valid
;
544 // {{{ function checkSyntax()
545 private static $errorMessages = array(
546 "dateformat" => "la date de fin de sondage est mal formattée : elle doit respecter la syntaxe dd/mm/aaaa",
547 "datepassed" => "la date de fin de sondage est déjà dépassée : vous devez préciser une date future",
548 "promoformat" => "les restrictions à certaines promotions sont mal formattées"
551 public function checkSyntax()
553 $rArr = parent
::checkSyntax();
554 if (!preg_match('#^\d{4}-\d{2}-\d{2}$#', $this->end
)) {
555 $rArr[] = array('question' => $this->getId(), 'error' => self
::$errorMessages["dateformat"]);
557 if (strtotime($this->end
) - time() <= 0) {
558 $rArr[] = array('question' => $this->getId(), 'error' => self
::$errorMessages["datepassed"]);
561 if ($this->promos
!= '' && !preg_match('#^(\d{4}-?|(\d{4})?-\d{4})(,(\d{4}-?|(\d{4})?-\d{4}))*$#', $this->promos
)) {
562 $rArr[] = array('question' => $this->getId(), 'error' => self
::$errorMessages["promoformat"]);
564 return (empty($rArr))? null
: $rArr;
570 // {{{ abstract class SurveySimple extends SurveyQuestion : "opened" questions
571 abstract class SurveySimple
extends SurveyQuestion
573 protected function checkAnswer($ans)
579 // {{{ class SurveyText extends SurveySimple : simple text field, allowing a few words
580 class SurveyText
extends SurveySimple
582 protected function getQuestionType()
589 // {{{ class SurveyTextarea extends SurveySimple : textarea field, allowing longer comments
590 class SurveyTextarea
extends SurveySimple
592 protected function getQuestionType()
599 // {{{ class SurveyNum extends SurveySimple : allows numerical answers
600 class SurveyNum
extends SurveySimple
602 protected function checkAnswer($ans)
607 protected function getQuestionType()
615 // {{{ abstract class SurveyList extends SurveyTreeable : restricted questions that allows only a list of possible answers
616 abstract class SurveyList
extends SurveyTreeable
620 protected function update($args)
622 parent
::update($args);
623 $this->choices
= explode('|', $args['options']);
626 protected function storeArray()
628 $rArr = parent
::storeArray();
629 $rArr['choices'] = $this->choices
;
630 $rArr['options'] = implode('|', $this->choices
);
636 // {{{ class SurveyRadio extends SurveyList : radio question, allows one answer among the list offered
637 class SurveyRadio
extends SurveyList
639 protected function checkAnswer($ans)
641 return (in_array($ans, $this->choices
)) ?
$ans : "";
644 protected function getQuestionType()
651 // {{{ class SurveyCheckbox extends SurveyList : checkbox question, allows any number of answers among the list offered
652 class SurveyCheckbox
extends SurveyList
654 protected function checkAnswer($ans)
657 foreach ($this->choices
as $key => $value) {
658 if (array_key_exists($key,$v[$id]) && $v[$id][$key]) {
662 $rep = (strlen($rep) >= 4) ?
substr($rep, 4) : "";
666 protected function getQuestionType()
674 // {{{ class SurveyPersonal extends SurveyQuestion : allows easy and verified access to user's personal data (promotion, name...)
675 class SurveyPersonal
extends SurveyQuestion
679 protected function update($args)
681 $args['question'] = "Informations personnelles";
682 parent
::update($args);
683 $this->perm
['promo'] = isset($args['promo'])?
1 : 0;
684 $this->perm
['name'] = isset($args['name'])?
1 : 0;
687 protected function checkAnswer($ans)
689 if (intval($ans) == 1) {
697 protected function getQuestionType()
702 protected function storeArray()
704 $a = parent
::storeArray();
705 $a['promo'] = $this->perm
['promo'];
706 $a['name'] = $this->perm
['name'];
712 // vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8: