]> git.agnieray.net Git - galette.git/blob - galette/lib/Galette/Entity/ListsConfig.php
Switch to PSR12, phpcbf fix
[galette.git] / galette / lib / Galette / Entity / ListsConfig.php
1 <?php
2
3 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
4
5 /**
6 * Lists config handling
7 *
8 * PHP version 5
9 *
10 * Copyright © 2020 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 2020 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 * @version SVN: $Id$
34 * @link http://galette.tuxfamily.org
35 * @since Available since 0.9.4dev - 2020-05-13
36 */
37
38 namespace Galette\Entity;
39
40 use ArrayObject;
41 use Analog\Analog;
42 use Laminas\Db\Adapter\Adapter;
43 use Galette\Core\Db;
44 use Galette\Core\Login;
45 use Galette\Core\Authentication;
46
47 /**
48 * Lists config class for galette:
49 * defines fields order and visibility
50 *
51 * @category Entity
52 * @name FieldsConfig
53 * @package Galette
54 * @author Johan Cwiklinski <johan@x-tnd.be>
55 * @copyright 2020 The Galette Team
56 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
57 * @link http://galette.tuxfamily.org
58 * @since Available since 0.9.4dev - 2020-05-13
59 */
60 class ListsConfig extends FieldsConfig
61 {
62 protected $listed_fields = array();
63
64 /**
65 * Fields that are not part of lists
66 *
67 * @var array
68 */
69 private $non_list_elements = array(
70 'mdp_adh',
71 'adresse2_adh',
72 'info_adh',
73 'info_public_adh',
74 'nom_adh',
75 'prenom_adh'
76 );
77
78 /**
79 * ACL mapping for list elements not present in form configuration
80 *
81 * @var array
82 */
83 private $acl_mapping = array(
84 'list_adh_name' => 'nom_adh',
85 'list_adh_contribstatus' => 'id_statut'
86 );
87
88 /**
89 * Prepare a field (required data, automation)
90 *
91 * @param ArrayObject $rset DB ResultSet row
92 *
93 * @return array
94 */
95 protected function buildField(ArrayObject $rset): array
96 {
97 $f = parent::buildField($rset);
98 $f['list_position'] = (int)$rset->list_position;
99 $f['list_visible'] = ($f['list_position'] >= 0);
100 return $f;
101 }
102
103 /**
104 * Create field array configuration,
105 * Several lists of fields are kept (visible, requireds, etc), build them.
106 *
107 * @return void
108 */
109 protected function buildLists()
110 {
111 //Specific list fields does not have rights; fix this from mapping
112 //Cannot be done preparing fields, cannot be sure of the order it is processed
113 foreach ($this->acl_mapping as $list_key => $field_key) {
114 $this->core_db_fields[$list_key]['visible'] = $this->core_db_fields[$field_key]['visible'];
115 }
116
117 //handle parent field: is always inactive on form. Hardcode to STAFF.
118 if (isset($this->core_db_fields['parent_id'])) {
119 $this->core_db_fields['parent_id']['visible'] = self::STAFF;
120 }
121
122 parent::buildLists();
123 //make sure array order is the same as in the database, since query is ordered differently
124 ksort($this->listed_fields);
125 }
126
127 /**
128 * Adds a field to lists
129 *
130 * @param array $field Field values
131 *
132 * @return void
133 */
134 protected function addToLists(array $field)
135 {
136 if (in_array($field['field_id'], $this->non_list_elements)) {
137 return;
138 }
139 parent::addToLists($field);
140
141 if ($field['list_visible'] ?? false) {
142 $this->listed_fields[(int)$field['list_position']] = $field;
143 }
144 }
145
146 /**
147 * Retrieve display elements
148 *
149 * @param Login $login Login instance
150 *
151 * @return array
152 */
153 public function getDisplayElements(Login $login)
154 {
155 global $preferences;
156
157 $display_elements = [];
158 $access_level = $login->getAccessLevel();
159 try {
160 $elements = $this->listed_fields;
161
162 foreach ($elements as $elt) {
163 $o = (object)$elt;
164 $this->handleLabel($o);
165
166 if ($o->field_id == 'id_adh') {
167 // ignore access control, as member ID is always needed
168 //if (!isset($preferences) || !$preferences->pref_show_id) {
169 $o->type = self::TYPE_STR;
170 $display_elements[] = $o;
171 //}
172 } else {
173 // skip fields blacklisted for display
174 if (in_array($o->field_id, $this->non_list_elements)) {
175 continue;
176 }
177
178 // skip fields according to access control
179 if (
180 $o->visible == self::NOBODY ||
181 ($o->visible == self::ADMIN &&
182 $access_level < Authentication::ACCESS_ADMIN) ||
183 ($o->visible == self::STAFF &&
184 $access_level < Authentication::ACCESS_STAFF) ||
185 ($o->visible == self::MANAGER &&
186 $access_level < Authentication::ACCESS_MANAGER)
187 ) {
188 continue;
189 }
190 $display_elements[] = $o;
191 }
192 }
193
194 return $display_elements;
195 } catch (\Exception $e) {
196 Analog::log(
197 'An error occurred getting list elements to display',
198 Analog::ERROR
199 );
200 throw $e;
201 }
202 }
203
204 /**
205 * Handle list labels
206 *
207 * @param stdClass $field Field data
208 *
209 * @return stdClass
210 */
211 private function handleLabel($field)
212 {
213 switch ($field->field_id) {
214 case 'bool_admin_adh':
215 $field->label = __('Is admin');
216 break;
217 case 'date_modif_adh':
218 $field->label = _T('Modified');
219 break;
220 case 'ddn_adh':
221 //TRANS: see https://www.urbandictionary.com/define.php?term=b-day
222 $field->label = _('b-day');
223 break;
224 case 'tel_adh':
225 $field->label = _T('Phone');
226 break;
227 case 'bool_display_info':
228 $field->label = _T('Public');
229 break;
230 }
231
232 $field->label = trim(str_replace('&nbsp;', ' ', $field->label));
233 $field->label = preg_replace('/\s?:$/', '', $field->label);
234
235 return $field;
236 }
237
238 /**
239 * Get all fields for list
240 *
241 * @return array
242 */
243 public function getListedFields(): array
244 {
245 return $this->listed_fields;
246 }
247
248 /**
249 * Get remaining free fields for list
250 *
251 * @return array
252 */
253 public function getRemainingFields(): array
254 {
255 $db_fields = $this->core_db_fields;
256
257 //remove non list
258 foreach ($this->non_list_elements as $todrop) {
259 unset($db_fields[$todrop]);
260 }
261
262 //remove already listed
263 foreach ($this->listed_fields as $listed) {
264 unset($db_fields[$listed['field_id']]);
265 }
266
267 $remainings = [];
268 foreach ($db_fields as $key => $db_field) {
269 $remainings[$key] = $db_field;
270 }
271
272 return $remainings;
273 }
274
275 /**
276 * Set fields
277 *
278 * @param array $fields categorized fields array
279 *
280 * @return boolean
281 */
282 public function setListFields($fields)
283 {
284 $this->listed_fields = $fields;
285 return $this->storeList();
286 }
287
288 /**
289 * Store list config in database
290 *
291 * @return boolean
292 */
293 private function storeList()
294 {
295 $class = get_class($this);
296
297 try {
298 if (!count($this->listed_fields)) {
299 throw new \RuntimeException('No fields for list, aborting.');
300 }
301
302 $this->zdb->connection->beginTransaction();
303
304 $update = $this->zdb->update(self::TABLE);
305 $update->set(
306 array(
307 'list_visible' => ':list_visible',
308 'list_position' => ':list_position'
309 )
310 )->where(
311 array(
312 'field_id' => ':field_id',
313 'table_name' => $this->table
314 )
315 );
316 $stmt = $this->zdb->sql->prepareStatementForSqlObject($update);
317
318 $params = null;
319
320 foreach ($this->listed_fields as $pos => $field) {
321 $params = array(
322 'list_visible' => $field['list_visible'],
323 'list_position' => $pos,
324 'where1' => $field['field_id']
325 );
326 $stmt->execute($params);
327 }
328
329 foreach (array_keys($this->getRemainingFields()) as $field) {
330 $params = array(
331 'list_visible' => $this->zdb->isPostgres() ? 'false' : 0,
332 'list_position' => -1,
333 'where1' => $field
334 );
335 $stmt->execute($params);
336 }
337
338 Analog::log(
339 str_replace(
340 '%s',
341 $this->table,
342 '[' . $class . '] List configuration for table %s stored ' .
343 'successfully.'
344 ),
345 Analog::INFO
346 );
347
348 $this->zdb->connection->commit();
349 return $this->load();
350 } catch (\Exception $e) {
351 $this->zdb->connection->rollBack();
352 Analog::log(
353 '[' . $class . '] An error occurred while storing list ' .
354 'configuration for table `' . $this->table . '`.' .
355 $e->getMessage(),
356 Analog::ERROR
357 );
358 Analog::log(
359 $e->getTraceAsString(),
360 Analog::ERROR
361 );
362 return false;
363 }
364 }
365
366 /**
367 * Get ACL mapping for list elements not present in form configuration
368 *
369 * @return array
370 */
371 public function getAclMapping(): array
372 {
373 return $this->acl_mapping;
374 }
375
376 /**
377 * Get visibility for specified field
378 *
379 * @param string $field The requested field
380 *
381 * @return boolean
382 */
383 public function getVisibility($field)
384 {
385 if (in_array($field, $this->non_list_elements)) {
386 return self::NOBODY;
387 }
388 return $this->all_visibles[$field];
389 }
390 }