Commit | Line | Data |
---|---|---|
8fe81c50 | 1 | <?php |
2 | /*************************************************************************** | |
9f5bd98e | 3 | * Copyright (C) 2003-2010 Polytechnique.org * |
8fe81c50 | 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 | ||
90343d1e FB |
22 | require_once dirname(__FILE__) . '/question.inc.php'; |
23 | require_once dirname(__FILE__) . '/answer.inc.php'; | |
24 | ||
2f4b93be | 25 | class Survey extends PlDBTableEntry implements SurveyQuestionContainer |
8fe81c50 | 26 | { |
2f4b93be FB |
27 | private $fetchQuestions = true; |
28 | public $questions = array(); | |
90343d1e FB |
29 | public $viewerFilter = null; |
30 | public $voterFilter = null; | |
8fe81c50 | 31 | |
2f4b93be | 32 | public function __construct() |
8fe81c50 | 33 | { |
2f4b93be FB |
34 | parent::__construct('surveys'); |
35 | $this->registerFieldValidator('shortname', 'ShortNameFieldValidator'); | |
36 | $this->registerFieldFormatter('voters', 'JSonFieldFormatter'); | |
37 | $this->registerFieldFormatter('viewers', 'JSonFieldFormatter'); | |
8fe81c50 | 38 | } |
39 | ||
2f4b93be | 40 | protected function postFetch() |
8fe81c50 | 41 | { |
90343d1e FB |
42 | if (!is_null($this->voters)) { |
43 | $this->voterFilter = UserFilter::fromExportedConditions($this->voters); | |
44 | } else { | |
45 | $this->voterFilter = null; | |
46 | } | |
47 | if (!is_null($this->viewers)) { | |
48 | $this->viewerFilter = UserFilter::fromExportedConditions($this->viewers); | |
49 | } else { | |
50 | $this->viewerFilter = null; | |
51 | } | |
2f4b93be | 52 | if (!$this->fetchQuestions) { |
4b8c8634 | 53 | return true; |
54 | } | |
2f4b93be FB |
55 | $selector = new SurveyQuestion($this); |
56 | $selector->sid = $this->id; | |
57 | ||
58 | $stack = array(); | |
59 | foreach ($selector as $question) { | |
60 | $question = $question->typedInstance(); | |
61 | if (is_null($question->parent)) { | |
62 | $this->addQuestion($question); | |
8fe81c50 | 63 | } else { |
2f4b93be FB |
64 | $pos = count($stack) - 1; |
65 | while ($stack[$pos]->qid != $question->parent) { | |
66 | --$pos; | |
67 | array_pop($stack); | |
8fe81c50 | 68 | } |
2f4b93be FB |
69 | Platal::assert(count($stack) > 0, "Invalid question structure"); |
70 | Platal::assert($stack[$pos] instanceof SurveyQuestionContainer, "Invalid question type"); | |
71 | $stack[$pos]->addQuestion($question); | |
8fe81c50 | 72 | } |
2f4b93be | 73 | array_push($stack, $question); |
8fe81c50 | 74 | } |
2f4b93be | 75 | return true; |
8fe81c50 | 76 | } |
77 | ||
90343d1e FB |
78 | protected function preSave() |
79 | { | |
80 | if (!is_null($this->voterFilter)) { | |
81 | $this->voters = $this->voterFilter->exportConditions(); | |
82 | } else { | |
83 | $this->voters = null; | |
84 | } | |
85 | if (!is_null($this->viewerFilter)) { | |
86 | $this->viewers = $this->viewerFilter->exportConditions(); | |
87 | } else { | |
88 | $this->viewers = null; | |
89 | } | |
90 | return true; | |
91 | } | |
92 | ||
2f4b93be | 93 | protected function postSave() |
4b8c8634 | 94 | { |
2f4b93be FB |
95 | $questions = array(); |
96 | $selector = new SurveyQuestion($this); | |
97 | $selector->sid = $this->id; | |
98 | $selector->delete(); | |
4b8c8634 | 99 | |
2f4b93be FB |
100 | $this->reassignQuestionIds(); |
101 | foreach ($this->questions as $question) { | |
102 | $question->sid = $this->id; | |
103 | $question->insert(); | |
8fe81c50 | 104 | } |
5c6e38d7 | 105 | } |
5c6e38d7 | 106 | |
2f4b93be | 107 | public function addQuestion(SurveyQuestion $question, $pos = null) |
5c6e38d7 | 108 | { |
2f4b93be FB |
109 | $question->parent = null; |
110 | if (is_null($pos)) { | |
111 | $this->questions[] = $question; | |
5c6e38d7 | 112 | } else { |
2f4b93be | 113 | array_splice($this->questions, $pos, 0, $question); |
8fe81c50 | 114 | } |
8fe81c50 | 115 | } |
116 | ||
2f4b93be | 117 | public function newQuestion($type, $pos = null) |
8fe81c50 | 118 | { |
2f4b93be FB |
119 | $question = SurveyQuestion::instanceForType($this, $type); |
120 | $this->addQuestion($question, $pos); | |
121 | return $question; | |
8fe81c50 | 122 | } |
8fe81c50 | 123 | |
90343d1e FB |
124 | public function questionForId($qid) |
125 | { | |
126 | $prev = null; | |
127 | foreach ($this->questions as $question) { | |
128 | if ($qid == $question->qid) { | |
129 | return $question; | |
130 | } else if ($qid < $question->qid) { | |
131 | Platal::assert($prev instanceof SurveyQuestionGroup, | |
132 | "Id gap must be caused by question groups"); | |
133 | return $prev->child($qid); | |
134 | } | |
135 | $prev = $question; | |
136 | } | |
137 | Platal::assert($prev instanceof SurveyQuestionGroup, | |
138 | "Id gap must be caused by question groups"); | |
139 | return $prev->child($qid); | |
140 | } | |
141 | ||
2f4b93be | 142 | public function reassignQuestionIds() |
8fe81c50 | 143 | { |
2f4b93be FB |
144 | $id = 0; |
145 | foreach ($this->questions as $question) { | |
146 | $question->qid = $id; | |
147 | if ($question instanceof SurveyQuestionContainer) { | |
148 | $id = $question->reassignQuestionIds(); | |
5c6e38d7 | 149 | } else { |
2f4b93be | 150 | $id++; |
8fe81c50 | 151 | } |
8fe81c50 | 152 | } |
2f4b93be | 153 | return $id; |
8fe81c50 | 154 | } |
155 | ||
2f4b93be | 156 | public function export() |
8fe81c50 | 157 | { |
2f4b93be FB |
158 | $export = parent::export(); |
159 | $export['questions'] = array(); | |
160 | foreach ($this->questions as $question) { | |
161 | $export['questions'][] = $question->export(); | |
5c6e38d7 | 162 | } |
2f4b93be | 163 | return $export; |
8fe81c50 | 164 | } |
8fe81c50 | 165 | |
90343d1e FB |
166 | /* Return an indicator of the progression of the survey: |
167 | * negative values means 'the survey is not started' | |
168 | * 0 means 'the survey is in progress' | |
169 | * positive values means 'the survey expired' | |
170 | */ | |
171 | public function progression() | |
172 | { | |
173 | if (!$this->flags->hasFlag('validated')) { | |
174 | return -2; | |
175 | } | |
176 | $now = time(); | |
177 | if ($this->begin->format('U') > $now) { | |
178 | return -1; | |
179 | } | |
180 | if ($this->end->format('U') <= $now) { | |
181 | return 1; | |
182 | } | |
183 | return 0; | |
184 | } | |
185 | ||
2f4b93be | 186 | public function canSee(User $user) |
8fe81c50 | 187 | { |
90343d1e | 188 | if ($this->canSeeResults($user) || $this->canVote($user)) { |
2f4b93be | 189 | return true; |
8fe81c50 | 190 | } |
2f4b93be | 191 | return false; |
8fe81c50 | 192 | } |
8fe81c50 | 193 | |
90343d1e FB |
194 | public function canSeeResults(User $user) |
195 | { | |
196 | if ($user->id() == $this->uid || $user->hasFlag('admin')) { | |
197 | return true; | |
198 | } | |
199 | if (is_null($this->viewerFilter)) { | |
200 | return $this->viewerFilter->checkUser($user); | |
201 | } | |
202 | return false; | |
203 | } | |
204 | ||
205 | public function canVote(User $user) | |
206 | { | |
207 | $status = $this->progression(); | |
208 | if ($status < 0) { | |
209 | return "Ce sondage n'est pas encore commencé"; | |
210 | } else if ($status > 0) { | |
211 | return "Ce sondage est terminé"; | |
212 | } | |
213 | if (!is_null($this->voterFilter) && !$this->voterFilter->checkUser($user)) { | |
214 | return "Ce sondage ne s'adresse pas à toi"; | |
215 | } | |
216 | $vote = SurveyVote::getVote($this, $user, false); | |
217 | if (is_null($vote)) { | |
218 | return "Tu as déjà voté à ce sondage."; | |
219 | } | |
220 | return true; | |
221 | } | |
222 | ||
223 | public function vote(User $user, array $answers) | |
224 | { | |
225 | if (!$this->canVote($user)) { | |
226 | return array('survey' => "Tu n'es pas autorisé à voter à ce sondage."); | |
227 | } | |
228 | $vote = SurveyVote::getVote($this, $user); | |
229 | if (is_null($vote)) { | |
230 | return $vote; | |
231 | } | |
232 | $answers = new PlDict($answers); | |
233 | foreach ($this->questions as $question) { | |
234 | $question->vote($vote, $answers); | |
235 | } | |
236 | return $vote; | |
237 | } | |
238 | ||
2f4b93be | 239 | public static function get($name, $fetchQuestions = true) |
797d27db | 240 | { |
2f4b93be FB |
241 | if (is_array($name)) { |
242 | $name = $name[0]; | |
797d27db | 243 | } |
2f4b93be FB |
244 | $survey = new Survey(); |
245 | $survey->fetchQuestions = $fetchQuestions; | |
246 | if (can_convert_to_integer($name)) { | |
247 | $survey->id = $name; | |
797d27db | 248 | } else { |
2f4b93be | 249 | $survey->shortname = $name; |
8fe81c50 | 250 | } |
2f4b93be FB |
251 | if (!$survey->fetch()) { |
252 | return null; | |
5c6e38d7 | 253 | } |
2f4b93be | 254 | return $survey; |
8fe81c50 | 255 | } |
256 | ||
2f4b93be | 257 | public static function iterActive() |
8fe81c50 | 258 | { |
2f4b93be FB |
259 | $survey = new Survey(); |
260 | $survey->fetchQuestions = false; | |
261 | return $survey->iterateOnCondition('begin <= CURDATE() AND end >= CURDATE() | |
262 | AND FIND_IN_SET(\'validated\', flags)'); | |
8fe81c50 | 263 | } |
5c6e38d7 | 264 | } |
8fe81c50 | 265 | |
2f4b93be | 266 | class ShortNameFieldValidator implements PlDBTableFieldValidator |
5c6e38d7 | 267 | { |
2f4b93be | 268 | public function __construct(PlDBTableField $field, $value) |
8fe81c50 | 269 | { |
2f4b93be FB |
270 | if (can_convert_to_integer($value) || !preg_match('/^[a-z0-9]+[-_\.a-z0-9]*[a-z0-9]+$/i', $value)) { |
271 | throw new PlDBBadValueException($value, $field, | |
272 | 'The shortname can only contain alphanumerical caracters, dashes, underscores and dots'); | |
273 | } | |
4b8c8634 | 274 | } |
8fe81c50 | 275 | } |
8fe81c50 | 276 | |
8602c852 | 277 | // vim:set et sw=4 sts=4 ts=4 foldmethod=marker enc=utf-8: |
8fe81c50 | 278 | ?> |