init
[garradin.git] / include / class.config.php
1 <?php
2
3 namespace Garradin;
4
5 class Config
6 {
7 protected $fields_types = null;
8 protected $config = null;
9 protected $modified = [];
10
11 static protected $_instance = null;
12
13 static public function getInstance()
14 {
15 return self::$_instance ?: self::$_instance = new Config;
16 }
17
18 private function __clone()
19 {
20 }
21
22 protected function __construct()
23 {
24 // Définition des types de données stockées
25 $string = '';
26 $int = 0;
27 $float = 0.0;
28 $array = [];
29 $bool = false;
30 $object = new \stdClass;
31
32 $this->fields_types = [
33 'nom_asso' => $string,
34 'adresse_asso' => $string,
35 'email_asso' => $string,
36 'site_asso' => $string,
37
38 'monnaie' => $string,
39 'pays' => $string,
40
41 'champs_membres' => $object,
42
43 'email_envoi_automatique'=> $string,
44
45 'categorie_membres' => $int,
46
47 'categorie_dons' => $int,
48 'categorie_cotisations' => $int,
49
50 'accueil_wiki' => $string,
51 'accueil_connexion' => $string,
52
53 'frequence_sauvegardes' => $int,
54 'nombre_sauvegardes' => $int,
55
56 'champ_identifiant' => $string,
57 'champ_identite' => $string,
58
59 'version' => $string,
60 ];
61
62 $db = DB::getInstance();
63
64 $this->config = $db->simpleStatementFetchAssoc('SELECT cle, valeur FROM config ORDER BY cle;');
65
66 foreach ($this->config as $key=>&$value)
67 {
68 if (!array_key_exists($key, $this->fields_types))
69 {
70 // Ancienne clé de config qui n'est plus utilisée
71 continue;
72 }
73
74 if (is_array($this->fields_types[$key]))
75 {
76 $value = explode(',', $value);
77 }
78 elseif ($key == 'champs_membres')
79 {
80 $value = new Champs_Membres((string)$value);
81 }
82 else
83 {
84 settype($value, gettype($this->fields_types[$key]));
85 }
86 }
87 }
88
89 public function __destruct()
90 {
91 if (!empty($this->modified))
92 {
93 //echo '<div style="color: red; background: #fff;">Il y a des champs modifiés non sauvés dans '.__CLASS__.' !</div>';
94 }
95 }
96
97 public function save()
98 {
99 if (empty($this->modified))
100 return true;
101
102 $values = [];
103
104 $db = DB::getInstance();
105 $db->exec('BEGIN;');
106
107 foreach ($this->modified as $key=>$modified)
108 {
109 $value = $this->config[$key];
110
111 if (is_array($value))
112 {
113 $value = implode(',', $value);
114 }
115 elseif (is_object($value))
116 {
117 $value = (string) $value;
118 }
119
120 $db->simpleExec('INSERT OR REPLACE INTO config (cle, valeur) VALUES (?, ?);',
121 $key, $value);
122 }
123
124 if (!empty($this->modified['champ_identifiant']))
125 {
126 // Mettre les champs identifiant vides à NULL pour pouvoir créer un index unique
127 $db->exec('UPDATE membres SET '.$this->get('champ_identifiant').' = NULL
128 WHERE '.$this->get('champ_identifiant').' = "";');
129
130 // Création de l'index unique
131 $db->exec('DROP INDEX IF EXISTS membres_identifiant;');
132 $db->exec('CREATE UNIQUE INDEX membres_identifiant ON membres ('.$this->get('champ_identifiant').');');
133 }
134
135 $db->exec('END;');
136
137 $this->modified = [];
138
139 return true;
140 }
141
142 public function get($key)
143 {
144 if (!array_key_exists($key, $this->fields_types))
145 {
146 throw new \OutOfBoundsException('Ce champ est inconnu.');
147 }
148
149 if (!array_key_exists($key, $this->config))
150 {
151 return null;
152 }
153
154 return $this->config[$key];
155 }
156
157 public function getVersion()
158 {
159 if (!array_key_exists('version', $this->config))
160 {
161 return '0';
162 }
163
164 return $this->config['version'];
165 }
166
167 public function setVersion($version)
168 {
169 $this->config['version'] = $version;
170
171 $db = DB::getInstance();
172 $db->simpleExec('INSERT OR REPLACE INTO config (cle, valeur) VALUES (?, ?);',
173 'version', $version);
174
175 return true;
176 }
177
178 public function set($key, $value)
179 {
180 if (!array_key_exists($key, $this->fields_types))
181 {
182 throw new \OutOfBoundsException('Ce champ est inconnu.');
183 }
184
185 if (is_array($this->fields_types[$key]))
186 {
187 $value = !empty($value) ? (array) $value : [];
188 }
189 elseif (is_int($this->fields_types[$key]))
190 {
191 $value = (int) $value;
192 }
193 elseif (is_float($this->fields_types[$key]))
194 {
195 $value = (float) $value;
196 }
197 elseif (is_bool($this->fields_types[$key]))
198 {
199 $value = (bool) $value;
200 }
201 elseif (is_string($this->fields_types[$key]))
202 {
203 $value = (string) $value;
204 }
205
206 switch ($key)
207 {
208 case 'nom_asso':
209 {
210 if (!trim($value))
211 {
212 throw new UserException('Le nom de l\'association ne peut rester vide.');
213 }
214 break;
215 }
216 case 'accueil_wiki':
217 case 'accueil_connexion':
218 {
219 if (!trim($value))
220 {
221 $key = str_replace('accueil_', '', $key);
222 throw new UserException('Le nom de la page d\'accueil ' . $key . ' ne peut rester vide.');
223 }
224 break;
225 }
226 case 'email_asso':
227 case 'email_envoi_automatique':
228 {
229 if (!filter_var($value, FILTER_VALIDATE_EMAIL))
230 {
231 throw new UserException('Adresse e-mail invalide.');
232 }
233 break;
234 }
235 case 'champs_membres':
236 {
237 if (!($value instanceOf Champs_Membres))
238 {
239 throw new \UnexpectedValueException('$value doit être de type Champs_Membres');
240 }
241 break;
242 }
243 case 'champ_identite':
244 case 'champ_identifiant':
245 {
246 $champs = $this->get('champs_membres');
247 $db = DB::getInstance();
248
249 // Vérification que le champ existe bien
250 if (!$champs->get($value))
251 {
252 throw new UserException('Le champ '.$value.' n\'existe pas pour la configuration de '.$key);
253 }
254
255 // Vérification que le champ est unique pour l'identifiant
256 if ($key == 'champ_identifiant'
257 && !$db->simpleQuerySingle('SELECT (COUNT(DISTINCT '.$value.') = COUNT(*))
258 FROM membres WHERE '.$value.' IS NOT NULL AND '.$value.' != \'\';'))
259 {
260 throw new UserException('Le champ '.$value.' comporte des doublons et ne peut donc pas servir comme identifiant pour la connexion.');
261 }
262 break;
263 }
264 case 'categorie_cotisations':
265 case 'categorie_dons':
266 {
267 return false;
268 $db = DB::getInstance();
269 if (!$db->simpleQuerySingle('SELECT 1 FROM compta_categories WHERE id = ?;', false, $value))
270 {
271 throw new UserException('Champ '.$key.' : La catégorie comptable numéro \''.$value.'\' ne semble pas exister.');
272 }
273 break;
274 }
275 case 'categorie_membres':
276 {
277 $db = DB::getInstance();
278 if (!$db->simpleQuerySingle('SELECT 1 FROM membres_categories WHERE id = ?;', false, $value))
279 {
280 throw new UserException('La catégorie de membres par défaut numéro \''.$value.'\' ne semble pas exister.');
281 }
282 break;
283 }
284 case 'monnaie':
285 {
286 if (!trim($value))
287 {
288 throw new UserException('La monnaie doit être renseignée.');
289 }
290
291 break;
292 }
293 case 'pays':
294 {
295 if (!trim($value) || !utils::getCountryName($value))
296 {
297 throw new UserException('Le pays renseigné est invalide.');
298 }
299
300 break;
301 }
302 default:
303 break;
304 }
305
306 if (!isset($this->config[$key]) || $value !== $this->config[$key])
307 {
308 $this->config[$key] = $value;
309 $this->modified[$key] = true;
310 }
311
312 return true;
313 }
314
315 public function getFieldsTypes()
316 {
317 return $this->fields_types;
318 }
319
320 public function getConfig()
321 {
322 return $this->config;
323 }
324 }
325
326 ?>