]> git.agnieray.net Git - galette.git/blob - galette/lib/Galette/Repository/SavedSearches.php
Switch to phpstan level 4
[galette.git] / galette / lib / Galette / Repository / SavedSearches.php
1 <?php
2
3 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
4
5 /**
6 * Saved searches
7 *
8 * PHP version 5
9 *
10 * Copyright © 2019-2023 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 Repository
28 * @package Galette
29 *
30 * @author Johan Cwiklinski <johan@x-tnd.be>
31 * @copyright 2019-2023 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 2019-09-21
35 */
36
37 namespace Galette\Repository;
38
39 use ArrayObject;
40 use Laminas\Db\Sql\Select;
41 use Throwable;
42 use Analog\Analog;
43 use Laminas\Db\Sql\Expression;
44 use Galette\Core\Db;
45 use Galette\Core\Login;
46 use Galette\Core\History;
47 use Galette\Entity\SavedSearch;
48 use Galette\Filters\SavedSearchesList;
49 use Galette\Entity\Adherent;
50
51 /**
52 * Saved searches
53 *
54 * @category Repository
55 * @name SavedSearches
56 * @package Galette
57 * @author Johan Cwiklinski <johan@x-tnd.be>
58 * @copyright 2019-2023 The Galette Team
59 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
60 * @link http://galette.tuxfamily.org
61 * @since 2019-09-21
62 */
63 class SavedSearches
64 {
65 public const TABLE = SavedSearch::TABLE;
66 public const PK = SavedSearch::PK;
67
68 private $filters = false;
69 private $zdb;
70 private $login;
71 private $count = null;
72
73 /**
74 * Default constructor
75 *
76 * @param Db $zdb Database
77 * @param Login $login Login
78 * @param SavedSearchesList $filters Filtering
79 */
80 public function __construct(Db $zdb, Login $login, $filters = null)
81 {
82 $this->zdb = $zdb;
83 $this->login = $login;
84
85 if ($filters === null) {
86 $this->filters = new SavedSearchesList();
87 } else {
88 $this->filters = $filters;
89 }
90 }
91
92 /**
93 * Get saved searches list
94 *
95 * @param bool $as_search return the results as an array of
96 * SavedSearch object.
97 * @param array $fields field(s) name(s) to get. Should be a string or
98 * an array. If null, all fields will be
99 * returned
100 * @param boolean $count true if we want to count
101 *
102 * @return SavedSearch[]|ArrayObject
103 */
104 public function getList($as_search = false, $fields = null, $count = true)
105 {
106 try {
107 $select = $this->buildSelect($fields, $count);
108 $this->filters->setLimits($select);
109
110 $searches = array();
111 $results = $this->zdb->execute($select);
112 if ($as_search) {
113 foreach ($results as $row) {
114 $searches[] = new SavedSearch($this->zdb, $this->login, $row);
115 }
116 } else {
117 $searches = $results;
118 }
119 return $searches;
120 } catch (Throwable $e) {
121 Analog::log(
122 'Cannot list saved searches | ' . $e->getMessage(),
123 Analog::WARNING
124 );
125 throw $e;
126 }
127 }
128
129 /**
130 * Builds the SELECT statement
131 *
132 * @param ?array $fields fields list to retrieve
133 * @param bool $count true if we want to count members
134 * (not applicable from static calls), defaults to false
135 *
136 * @return Select SELECT statement
137 */
138 private function buildSelect(?array $fields, bool $count = false): Select
139 {
140 try {
141 $fieldsList = ['*'];
142 if ($fields !== null && count($fields)) {
143 $fieldsList = $fields;
144 }
145
146 $select = $this->zdb->select(self::TABLE, 's');
147 $select->columns($fieldsList);
148 if (0 === $this->login->id) {
149 $select->where->isNull(Adherent::PK);
150 } else {
151 $select->where([Adherent::PK => $this->login->id]);
152 }
153
154 $select->order(self::buildOrderClause());
155
156 if ($count) {
157 $this->proceedCount($select);
158 }
159
160 return $select;
161 } catch (Throwable $e) {
162 Analog::log(
163 'Cannot build SELECT clause for saved searches | ' . $e->getMessage(),
164 Analog::WARNING
165 );
166 throw $e;
167 }
168 }
169
170 /**
171 * Count searches from the query
172 *
173 * @param Select $select Original select
174 *
175 * @return void
176 */
177 private function proceedCount(Select $select)
178 {
179 try {
180 $countSelect = clone $select;
181 $countSelect->reset($countSelect::COLUMNS);
182 $countSelect->reset($countSelect::JOINS);
183 $countSelect->reset($countSelect::ORDER);
184 $countSelect->columns(
185 array(
186 self::PK => new Expression('COUNT(' . self::PK . ')')
187 )
188 );
189
190 $results = $this->zdb->execute($countSelect);
191 $result = $results->current();
192
193 $k = self::PK;
194 $this->count = $result->$k;
195 $this->filters->setCounter($this->count);
196 } catch (Throwable $e) {
197 Analog::log(
198 'Cannot count saved searches | ' . $e->getMessage(),
199 Analog::WARNING
200 );
201 throw $e;
202 }
203 }
204
205 /**
206 * Builds the order clause
207 *
208 * @return array
209 */
210 private function buildOrderClause()
211 {
212 $order = array();
213 $order[] = $this->filters->orderby . ' ' . $this->filters->ordered;
214
215 return $order;
216 }
217
218 /**
219 * Get count for current query
220 *
221 * @return int
222 */
223 public function getCount()
224 {
225 return $this->count;
226 }
227
228 /**
229 * Remove specified searches
230 *
231 * @param integer|array $ids Searches identifiers to delete
232 * @param History $hist History
233 * @param boolean $transaction True to begin a database transaction
234 *
235 * @return boolean
236 */
237 public function remove($ids, History $hist, $transaction = true)
238 {
239 $list = array();
240 if (is_numeric($ids)) {
241 //we've got only one identifier
242 $list[] = $ids;
243 } else {
244 $list = $ids;
245 }
246
247 if (count($list)) {
248 try {
249 if ($transaction) {
250 $this->zdb->connection->beginTransaction();
251 }
252 $select = $this->zdb->select(self::TABLE);
253 $select->where->in(self::PK, $list);
254 $searches = $this->zdb->execute($select);
255 foreach ($searches as $search) {
256 $s = new SavedSearch($this->zdb, $this->login, $search);
257 $res = $s->remove();
258 if ($res === false) {
259 throw new \Exception('Cannot remove saved search');
260 }
261 }
262 if ($transaction) {
263 $this->zdb->connection->commit();
264 }
265 $hist->add(
266 str_replace(
267 '%list',
268 print_r($list, true),
269 _T("Searches deleted (%list)")
270 )
271 );
272 return true;
273 } catch (Throwable $e) {
274 if ($transaction) {
275 $this->zdb->connection->rollBack();
276 }
277 Analog::log(
278 'An error occurred trying to remove searches | ' .
279 $e->getMessage(),
280 Analog::ERROR
281 );
282 throw $e;
283 }
284 } else {
285 //not numeric and not an array: incorrect.
286 Analog::log(
287 'Asking to remove searches, but without providing an array or a single numeric value.',
288 Analog::WARNING
289 );
290 return false;
291 }
292 }
293 }