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