]> git.agnieray.net Git - galette.git/blob - galette/lib/Galette/Entity/SavedSearch.php
218f7e8a4a3a435515e1acae1a844b5ed98ff801
[galette.git] / galette / lib / Galette / Entity / SavedSearch.php
1 <?php
2
3 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
4
5 /**
6 * Saved search
7 *
8 * PHP version 5
9 *
10 * Copyright © 2019 The Galette Team
11 *
12 * This file is part of Galette (http://galette.tuxfamily.org).
13 *
14 * Galette is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation, either version 3 of the License, or
17 * (at your option) any later version.
18 *
19 * Galette is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with Galette. If not, see <http://www.gnu.org/licenses/>.
26 *
27 * @category Entity
28 * @package Galette
29 *
30 * @author Johan Cwiklinski <johan@x-tnd.be>
31 * @copyright 2019 The Galette Team
32 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
33 * @link http://galette.tuxfamily.org
34 * @since Available since 0.9.3dev - 2019-03-25
35 */
36
37 namespace Galette\Entity;
38
39 use Galette\Core;
40 use Galette\Core\Db;
41 use Galette\Core\Login;
42 use Analog\Analog;
43
44 /**
45 * Saved search
46 *
47 * @category Entity
48 * @name SavedSearch
49 * @package Galette
50 * @author Johan Cwiklinski <johan@x-tnd.be>
51 * @copyright 2019 The Galette Team
52 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
53 * @link http://galette.tuxfamily.org
54 * @since Available since 0.9.3dev - 2019-03-25
55 */
56
57 class SavedSearch
58 {
59 const TABLE = 'searches';
60 const PK = 'search_id';
61
62 private $zdb;
63 private $id;
64 private $name;
65 private $parameters = [];
66 private $author_id;
67 private $creation_date;
68 private $form;
69
70 private $login;
71 private $errors = [];
72
73 /**
74 * Main constructor
75 *
76 * @param Db $zdb Database instance
77 * @param Login $login Login instance
78 * @param mixed $args Arguments
79 */
80 public function __construct(Db $zdb, Login $login, $args = null)
81 {
82 $this->zdb = $zdb;
83 $this->login = $login;
84 $this->creation_date = date('Y-m-d H:i:s');
85
86 if (is_int($args)) {
87 $this->load($args);
88 } elseif ($args !== null && is_object($args)) {
89 $this->loadFromRs($args);
90 }
91 }
92
93 /**
94 * Load a saved search from its identifier
95 *
96 * @param integer $id Identifier
97 *
98 * @return void
99 */
100 private function load($id)
101 {
102 try {
103 $select = $this->zdb->select(self::TABLE);
104 $select->limit(1)->where(self::PK . ' = ' . $id);
105 if ($this->login->isSuperAdmin()) {
106 $select->where(Adherent::PK . ' IS NULL');
107 } else {
108 $select->where(Adherent::PK . ' = ' . (int)$this->login->id);
109 }
110
111 $results = $this->zdb->execute($select);
112 $res = $results->current();
113
114 $this->loadFromRs($res);
115 } catch (\Exception $e) {
116 Analog::log(
117 'An error occurred loading saved search #' . $id . "Message:\n" .
118 $e->getMessage(),
119 Analog::ERROR
120 );
121 }
122 }
123
124 /**
125 * Load a saved search from a db ResultSet
126 *
127 * @param ResultSet $rs ResultSet
128 *
129 * @return void
130 */
131 private function loadFromRs($rs)
132 {
133 $pk = self::PK;
134 $this->id = $rs->$pk;
135 $this->name = $rs->name;
136 $this->parameters = json_decode($rs->parameters, true);
137 $this->author_id = $rs->id_adh;
138 $this->creation_date = $rs->creation_date;
139 $this->form = $rs->form;
140 }
141
142 /**
143 * Check and set values
144 *
145 * @param array $values Values to set
146 *
147 * @return boolean
148 */
149 public function check($values)
150 {
151 $this->errors = [];
152 $mandatory = [
153 'form' => _T('Form is mandatory!')
154 ];
155
156 foreach ($values as $key => $value) {
157 if (in_array($key, ['nbshow', 'page'])) {
158 continue;
159 }
160 if (empty($value) && isset($mandatory[$key])) {
161 $this->errors[] = $mandatory[$key];
162 }
163 $this->$key = $value;
164 unset($mandatory[$key]);
165 }
166
167 if (count($mandatory)) {
168 $this->errors = array_merge($this->errors, $mandatory);
169 }
170
171 if ($this->id === null && !$this->login->isSuperAdmin()) {
172 //set author for new searches
173 $this->author_id = $this->login->id;
174 }
175
176 return (count($this->errors) === 0);
177 }
178
179 /**
180 * Store saved search in database
181 *
182 * @return boolean|null
183 */
184 public function store()
185 {
186 $parameters = json_encode($this->parameters);
187 $parameters_sum = sha1($parameters, true);
188 if ($this->zdb->isPostgres()) {
189 $parameters_sum = pg_escape_bytea($parameters_sum);
190 }
191 $data = array(
192 'name' => $this->name,
193 'parameters' => $parameters,
194 'parameters_sum' => $parameters_sum,
195 'id_adh' => $this->author_id,
196 'creation_date' => ($this->creation_date !== null ? $this->creation_date : date('Y-m-d H:i:s')),
197 'form' => $this->form
198 );
199
200 try {
201 $select = $this->zdb->select(self::TABLE);
202 $select
203 ->where([
204 'form' => $this->form,
205 'parameters_sum' => $parameters_sum,
206 'id_adh' => $this->author_id,
207 ])
208 ->limit(1);
209
210 $results = $this->zdb->execute($select);
211 if ($results->count() !== 0) {
212 $result = $results->current();
213 //search already exists
214 Analog::log(
215 str_replace('%name', $result->name, 'Already saved as "%name"!'),
216 Analog::INFO
217 );
218 return null;
219 } else {
220 $insert = $this->zdb->insert(self::TABLE);
221 $insert->values($data);
222 $add = $this->zdb->execute($insert);
223 if (!$add->count() > 0) {
224 Analog::log('Not stored!', Analog::ERROR);
225 return false;
226 }
227 }
228 return true;
229 } catch (\Exception $e) {
230 throw $e;
231 Analog::log(
232 'An error occurred storing saved search: ' . $e->getMessage() .
233 "\n" . print_r($data, true),
234 Analog::ERROR
235 );
236 return false;
237 }
238 }
239
240 /**
241 * Remove current saved search
242 *
243 * @return boolean
244 */
245 public function remove()
246 {
247 $id = (int)$this->id;
248 try {
249 $delete = $this->zdb->delete(self::TABLE);
250 $delete->where(
251 self::PK . ' = ' . $id
252 );
253 $this->zdb->execute($delete);
254 Analog::log(
255 'Saved search #' . $id . ' (' . $this->name
256 . ') deleted successfully.',
257 Analog::INFO
258 );
259 return true;
260 } catch (\RuntimeException $re) {
261 throw $re;
262 } catch (\Exception $e) {
263 Analog::log(
264 'Unable to delete saved search ' . $id . ' | ' . $e->getMessage(),
265 Analog::ERROR
266 );
267 throw $e;
268 }
269 }
270
271 /**
272 * Getter
273 *
274 * @param string $name Property name
275 *
276 * @return mixed
277 */
278 public function __get($name)
279 {
280 $forbidden = [];
281 $virtuals = ['sparameters'];
282 if (in_array($name, $virtuals)
283 || !in_array($name, $forbidden)
284 && isset($this->$name)
285 ) {
286 switch ($name) {
287 case 'creation_date':
288 if ($this->$name != '') {
289 try {
290 $d = new \DateTime($this->$name);
291 return $d->format(__("Y-m-d"));
292 } catch (\Exception $e) {
293 //oops, we've got a bad date :/
294 Analog::log(
295 'Bad date (' . $this->$name . ') | ' .
296 $e->getMessage(),
297 Analog::INFO
298 );
299 return $this->$name;
300 }
301 }
302 break;
303 case 'sparameters':
304 include_once GALETTE_ROOT . 'includes/fields_defs/members_fields.php';
305 $parameters = [];
306 foreach ((array)$this->parameters as $key => $parameter) {
307 if (isset($members_fields[$key])) {
308 $key = $members_fields[$key]['label'];
309 }
310 if (is_array($parameter) || is_object($parameter)) {
311 $parameter = json_encode($parameter);
312 }
313 $parameters[$key] = $parameter;
314 }
315 return $parameters;
316 break;
317 default:
318 if (!property_exists($this, $name)) {
319 Analog::log(
320 "Unknown property '$name'",
321 Analog::WARNING
322 );
323 return null;
324 } else {
325 return $this->$name;
326 }
327 break;
328 }
329 }
330 }
331
332 /**
333 * Setter
334 *
335 * @param string $name Property name
336 * @param mixed $value Property value
337 *
338 * @return void
339 */
340 public function __set($name, $value)
341 {
342 switch ($name) {
343 case 'form':
344 if (!in_array($value, $this->getKnownForms())) {
345 $this->errors[] = str_replace('%form', $value, _T("Unknown form %form!"));
346 }
347 $this->form = $value;
348 break;
349 case 'parameters':
350 if (!is_array($value)) {
351 Analog::log(
352 'Search parameters must be an array!',
353 Analog::ERROR
354 );
355 }
356 $this->parameters = $value;
357 break;
358 case 'name':
359 if (trim($value) === '') {
360 $this->errors[] = _T("Name cannot be empty!");
361 }
362 $this->name = $value;
363 break;
364 case 'author_id':
365 $this->author_id = (int)$value;
366 break;
367 default:
368 Analog::log(
369 str_replace(
370 ['%class', '%property'],
371 [self::class, $name],
372 'Unable to set %class property %property'
373 ),
374 Analog::WARNING
375 );
376 break;
377 }
378 }
379
380 /**
381 * Get known forms
382 *
383 * @return array
384 */
385 public function getKnownForms()
386 {
387 return [
388 'Adherent'
389 ];
390 }
391
392 /**
393 * Get errors
394 *
395 * @return array
396 */
397 public function getErrors()
398 {
399 return $this->errors;
400 }
401 }