Add class DirEnum, to access all enumerations used in the site
[platal.git] / include / ufbuilder.php
CommitLineData
d9b3d712
RB
1<?php
2/***************************************************************************
3 * Copyright (C) 2003-2009 Polytechnique.org *
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
22class UserFilterBuilder
23{
24 private $envprefix;
25 private $fields;
26 private $valid = true;
27 private $ufc = null;
28
29 /** Constructor
30 * @param $fields An array of UFB_Field objects
31 * @param $envprefix Prefix to use for parts of the query
32 */
33 public function __construct($fields, $envprefix = '')
34 {
35 $this->fields = $fields;
36 $this->envprefix = $envprefix;
37 }
38
39 /** Builds the UFC; returns as soon as a field says it is invalid
40 */
41 private function buildUFC()
42 {
43 if ($this->ufc != null) {
44 return;
45 }
46 $this->ufc = new PFC_And();
47
48 foreach ($this->fields as $field) {
49 $this->valid = $field->apply(&$this);
50 if (!$this->valid) {
51 return;
52 }
53 }
54 }
55
56 public function addCond(PlFilterCondition &$cond)
57 {
58 $this->ufc->addChild($cond);
59 }
60
61 public function isValid()
62 {
63 $this->buildUFC();
64 return $this->valid;
65 }
66
67 /** Returns the built UFC
68 * @return The UFC, or PFC_False() if an error happened
69 */
70 public function &getUFC()
71 {
72 $this->buildUFC();
73 if ($this->valid) {
74 return $this->ufc;
75 } else {
76 return new PFC_False();
77 }
78 }
79
80 /** Wrappers around Env::i/s/..., to add envprefix
81 */
82 public function s($key, $def) {
83 return trim(Env::s($this->envprefix . $key, $def));
84 }
85
86 public function i($key, $def) {
87 return intval(trim(Env::i($this->envprefix . $key, $def)));
88 }
89
90 public function v($key, $def) {
91 return Env::v($this->envprefix . $key, $def);
92 }
93
94 public function has($key) {
95 return Env::has($this->envprefix . $key);
96 }
97}
98
99abstract class UFB_Field
100{
101 protected $envfield;
102 protected $formtext;
103
104 protected $empty = false;
105 protected $val = null;
106
107 /** Constructor
108 * @param $envfield Name of the field in the environment
109 * @param $formtext User-friendly name of that field
110 */
111 public function __construct($envfield, $formtext = '')
112 {
113 $this->envfield = $envfield;
114 if ($formtext != '') {
115 $this->formtext = $formtext;
116 } else {
117 $formtext = ucfirst($envfield);
118 }
119 }
120
121 /** Prints the given error message to the user, and returns false
122 * in order to be used as return $this->raise('ERROR');
123 *
124 * All %s in the $msg will be replaced with the formtext.
125 */
126 protected function raise($msg)
127 {
128 Platal::page()->trigError(str_replace('%s', $this->formtext, $msg));
129 return false;
130 }
131
132 public function apply(UserFilterBuilder &$ufb) {
133 if (!$this->check($ufb)) {
134 return false;
135 }
136
137 if (!$this->empty) {
138 $ufc = $this->buildUFC($ufb);
139 if ($ufc != null) {
140 $ufb->addCond($ufc);
141 }
142 }
143 return true;
144 }
145
146 /** Create the UFC associated to the field; won't be called
147 * if the field is "empty"
148 * @param &$ufb UFB to which fields must be added
149 * @return UFC
150 */
151 abstract protected function buildUFC(UserFilterBuilder &$ufb);
152
153 /** This function is intended to run consistency checks on the value
154 * @return boolean Whether the input is valid
155 */
156 abstract protected function check(UserFilterBuilder &$ufb);
157}
158
159abstract class UFBF_Text extends UFB_Field
160{
161 private $forbiddenchars;
162 private $minlength;
163 private $maxlength;
164
165 public function __construct($envfield, $formtext = '', $forbiddenchars = '', $minlength = 2, $maxlength = 255)
166 {
167 parent::__construct($envfield, $formtext);
168 $this->forbiddenchars = $forbiddenchars;
169 $this->minlength = $minlength;
170 $this->maxlength = $maxlength;
171 }
172
173 protected function check(UserFilterBuilder &$ufb)
174 {
175 if (!$ufb->has($this->envfield)) {
176 $this->empty = true;
177 return true;
178 }
179
180 $this->val = $ufb->s($this->envfield);
181 if (strlen($this->val) < $this->minlength) {
182 return $this->raise("Le champ %s est trop court (minimum {$this->minlength}).");
183 } else if (strlen($this->val) > $this->maxlength) {
184 return $this->raise("Le champ %s est trop long (maximum {$this->maxlength}).");
185 }
186 return true;
187 }
188}
189
190/** Subclass to use for fields which only allow integers within a range
191 */
192abstract class UFBF_Range extends UFB_Field
193{
194
195 private $min;
196 private $max;
197
198 public function __construct($envfield, $formtext = '', $min = 0, $max = 65535)
199 {
200 parent::__construct($envfield, $formtext);
201 $this->min = $min;
202 $this->max = $max;
203 }
204
205 protected function check(UserFilterBuilder &$ufb)
206 {
207 if (!$ufb->has($this->envfield)) {
208 $this->empty = true;
209 return true;
210 }
211
212 $this->val = $ufb->i($this->envfield);
213 if ($this->val < $this->min) {
214 return $this->raise("Le champs %s est inférieur au minimum ({$this->min}).");
215 } else if ($this->val > $this->max) {
216 return $this->raise("Le champ %s est supérieur au maximum ({$this->max}).");
217 }
218 return true;
219 }
220}
221
222/** Subclass to use for indexed fields
223 */
224abstract class UFBF_Index extends UFB_Field
225{
226 protected function check(UserFilterBuilder &$ufb)
227 {
228 if (!$ufb->has($this->envfield)) {
229 $this->empty = true;
230 }
231 return true;
232 }
233}
234
235/** Subclass to use for fields whose value must belong to a specific set of values
236 */
237abstract class UFBF_Enum extends UFB_Field
238{
239 public function __construct($envfield, $formtext = '', $allowedvalues = array())
240 {
241 parent::__construct($envfield, $formtext);
242 $this->allowedvalues = $allowedvalues;
243 }
244
245 protected function check(UserFilterBuilder &$ufb)
246 {
247 if (!$ufb->has($this->envfield)) {
248 $this->empty = true;
249 return true;
250 }
251
252 $this->val = $ufb->v($this->envfield);
253 if (! in_array($this->val, $this->allowedvalues)) {
254 return $this->raise("La valeur {$this->val} n'est pas valide pour le champ %s.");
255 }
256 return true;
257 }
258}
259
260class UFBF_Name extends UFBF_Text
261{
262 private $type;
263
264 public function __construct($envfield, $type, $formtext = '', $forbiddenchars = '', $minlength = 2, $maxlength = 255)
265 {
266 parent::__construct($envfield, $formtext, $forbiddenchars, $minlength, $maxlength);
267 $this->type = $type;
268 }
269
270 protected function buildUFC(UserFilterBuilder &$ufb)
271 {
272 if ($ufb->i('exact')) {
273 return new UFC_Name($this->type, $this->val, UFC_Name::VARIANTS);
274 } else {
275 return new UFC_Name($this->type, $this->val, UFC_Name::VARIANTS | UFC_Name::CONTAINS);
276 }
277 }
278}
279
280class UFBF_Promo extends UFB_Field
281{
282 private static $validcomps = array('<', '<=', '=', '>=', '>');
283 private $comp;
284 private $envfieldcomp;
285
286 public function __construct($envfield, $fromtext = '', $envfieldcomp)
287 {
288 parent::__construct($envfield, $fromtext);
289 $this->envfieldcomp = $envfieldcomp;
290 }
291
292 protected function check(UserFilterBuilder &$ufb)
293 {
294 if (!$ufb->has($this->envfield) || !$ufb->has($this->envfieldcomp)) {
295 $this->empty = true;
296 return true;
297 }
298
299 $this->val = $ubf->i($this->envfield);
300 $this->comp = $ubf->v($this->envfieldcomp);
301
302 if (!in_array($this->comp, self::$validcomps)) {
303 return $this->raise("Le critère {$this->comp} n'est pas valide pour le champ %s");
304 }
305
306 if (preg_match('/^[0-9]{2}$/', $this->val)) {
307 $this->val += 1900;
308 }
309 if ($this->val < 1900 || $this->val > 9999) {
310 return $this->raise("Le champ %s doit être une année à 4 chiffres.");
311 }
312 return true;
313 }
314
315 protected function buildUFC(UserFilterBuilder &$ufb) {
316 return new UFC_Promo($this->comp, UserFilter::DISPLAY, 'X' . $this->val);
317 }
318}
319
320?>