2 /***************************************************************************
3 * Copyright (C) 2003-2011 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 require_once dirname(__FILE__
) . '/question.inc.php';
23 require_once dirname(__FILE__
) . '/answer.inc.php';
25 class Survey
extends PlDBTableEntry
implements SurveyQuestionContainer
27 private $fetchQuestions = true
;
28 public $questions = array();
29 public $viewerFilter = null
;
30 public $voterFilter = null
;
32 public function __construct()
34 parent
::__construct('surveys');
35 $this->registerFieldValidator('shortname', 'ShortNameFieldValidator');
36 $this->registerFieldFormatter('voters', 'JSonFieldFormatter');
37 $this->registerFieldFormatter('viewers', 'JSonFieldFormatter');
40 protected function postFetch()
42 if (!is_null($this->voters
)) {
43 $this->voterFilter
= UserFilter
::fromExportedConditions($this->voters
);
45 $this->voterFilter
= null
;
47 if (!is_null($this->viewers
)) {
48 $this->viewerFilter
= UserFilter
::fromExportedConditions($this->viewers
);
50 $this->viewerFilter
= null
;
52 if (!$this->fetchQuestions
) {
55 $selector = new SurveyQuestion($this);
56 $selector->sid
= $this->id
;
59 foreach ($selector as $question) {
60 $question = $question->typedInstance();
61 if (is_null($question->parent
)) {
62 $this->addQuestion($question);
64 $pos = count($stack) - 1;
65 while ($stack[$pos]->qid
!= $question->parent
) {
69 Platal
::assert(count($stack) > 0, "Invalid question structure");
70 Platal
::assert($stack[$pos] instanceof SurveyQuestionContainer
, "Invalid question type");
71 $stack[$pos]->addQuestion($question);
73 array_push($stack, $question);
78 protected function preSave()
80 if (!is_null($this->voterFilter
)) {
81 $this->voters
= $this->voterFilter
->exportConditions();
85 if (!is_null($this->viewerFilter
)) {
86 $this->viewers
= $this->viewerFilter
->exportConditions();
88 $this->viewers
= null
;
93 protected function postSave()
96 $selector = new SurveyQuestion($this);
97 $selector->sid
= $this->id
;
100 $this->reassignQuestionIds();
101 foreach ($this->questions
as $question) {
102 $question->sid
= $this->id
;
107 public function clearQuestions()
109 $this->fetchQuestions
= true
;
110 $this->questions
= array();
113 public function addQuestion(SurveyQuestion
$question, $pos = null
)
115 $question->parent
= null
;
117 $this->questions
[] = $question;
119 array_splice($this->questions
, $pos, 0, $question);
123 public function newQuestion($type, $pos = null
)
125 $question = SurveyQuestion
::instanceForType($this, $type);
126 $this->addQuestion($question, $pos);
130 public function questionForId($qid)
133 foreach ($this->questions
as $question) {
134 if ($qid == $question->qid
) {
136 } else if ($qid < $question->qid
) {
137 Platal
::assert($prev instanceof SurveyQuestionGroup
,
138 "Id gap must be caused by question groups");
139 return $prev->child($qid);
143 Platal
::assert($prev instanceof SurveyQuestionGroup
,
144 "Id gap must be caused by question groups");
145 return $prev->child($qid);
148 public function reassignQuestionIds()
151 foreach ($this->questions
as $question) {
152 $question->qid
= $id;
153 if ($question instanceof SurveyQuestionContainer
) {
154 $id = $question->reassignQuestionIds();
162 public function export()
164 $export = parent
::export();
165 $export['questions'] = $this->exportQuestions();
169 public function exportQuestions()
172 foreach ($this->questions
as $question) {
173 $export[] = $question->export();
178 public function exportQuestionsToJSON()
180 return json_encode($this->exportQuestions());
183 /* Return an indicator of the progression of the survey:
184 * negative values means 'the survey is not started'
185 * 0 means 'the survey is in progress'
186 * positive values means 'the survey expired'
188 public function progression()
190 if (!$this->flags
->hasFlag('validated')) {
194 if ($this->begin
->format('U') > $now) {
197 if ($this->end
->format('U') <= $now) {
203 public function canSee(User
$user)
205 if ($this->canSeeResults($user) ||
$this->canVote($user)) {
211 public function canSeeResults(User
$user)
213 if ($user->id() == $this->uid ||
$user->hasFlag('admin')) {
216 if (is_null($this->viewerFilter
)) {
217 return $this->viewerFilter
->checkUser($user);
222 public function canVote(User
$user)
224 $status = $this->progression();
226 return "Ce sondage n'est pas encore commencé";
227 } else if ($status > 0) {
228 return "Ce sondage est terminé";
230 if (!is_null($this->voterFilter
) && !$this->voterFilter
->checkUser($user)) {
231 return "Ce sondage ne s'adresse pas à toi";
233 $vote = SurveyVote
::getVote($this, $user, false
);
234 if (is_null($vote)) {
235 return "Tu as déjà voté à ce sondage.";
240 public function vote(User
$user, array $answers)
242 if (!$this->canVote($user)) {
243 return array('survey' => "Tu n'es pas autorisé à voter à ce sondage.");
245 $vote = SurveyVote
::getVote($this, $user);
246 if (is_null($vote)) {
249 $answers = new PlDict($answers);
250 foreach ($this->questions
as $question) {
251 $question->vote($vote, $answers);
256 public static function get($name, $fetchQuestions = true
)
258 if (is_array($name)) {
261 $survey = new Survey();
262 $survey->fetchQuestions
= $fetchQuestions;
263 if (can_convert_to_integer($name)) {
266 $survey->shortname
= $name;
268 if (!$survey->fetch()) {
274 public static function iterActive()
276 $survey = new Survey();
277 $survey->fetchQuestions
= false
;
278 return $survey->iterateOnCondition('begin <= CURDATE() AND end >= CURDATE()
279 AND FIND_IN_SET(\'validated\', flags)');
283 class ShortNameFieldValidator
implements PlDBTableFieldValidator
285 public function __construct(PlDBTableField
$field, $value)
287 if (can_convert_to_integer($value) ||
!preg_match('/^[a-z0-9]+[-_\.a-z0-9]*[a-z0-9]+$/i', $value)) {
288 throw new PlDBBadValueException($value, $field,
289 'The shortname can only contain alphanumerical caracters, dashes, underscores and dots');
294 // vim:set et sw=4 sts=4 ts=4 foldmethod=marker enc=utf-8: