]> git.agnieray.net Git - galette.git/blob - galette/lib/Galette/Entity/FieldsConfig.php
Few typos
[galette.git] / galette / lib / Galette / Entity / FieldsConfig.php
1 <?php
2
3 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
4
5 /**
6 * Fields config handling
7 *
8 * PHP version 5
9 *
10 * Copyright © 2009-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 2009-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 * @link http://galette.tuxfamily.org
34 * @since Available since 0.7dev - 2009-03-26
35 */
36
37 namespace Galette\Entity;
38
39 use ArrayObject;
40 use Analog\Analog;
41 use Laminas\Db\Adapter\Adapter;
42 use Galette\Core\Db;
43 use Galette\Core\Login;
44 use Galette\Core\Authentication;
45
46 /**
47 * Fields config class for galette :
48 * defines fields visibility for lists and forms
49 * defines fields order and requirement flag for forms
50 *
51 * @category Entity
52 * @name FieldsConfig
53 * @package Galette
54 * @author Johan Cwiklinski <johan@x-tnd.be>
55 * @copyright 2009-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.7dev - 2009-03-26
59 */
60 class FieldsConfig
61 {
62 const NOBODY = 0;
63 const USER_WRITE = 1;
64 const ADMIN = 2;
65 const STAFF = 3;
66 const MANAGER = 4;
67 const USER_READ = 5;
68
69 const TYPE_STR = 0;
70 const TYPE_HIDDEN = 1;
71 const TYPE_BOOL = 2;
72 const TYPE_INT = 3;
73 const TYPE_DEC = 4;
74 const TYPE_DATE = 5;
75 const TYPE_TXT = 6;
76 const TYPE_PASS = 7;
77 const TYPE_EMAIL = 8;
78 const TYPE_URL = 9;
79 const TYPE_RADIO = 10;
80 const TYPE_SELECT = 11;
81
82 protected $zdb;
83 protected $core_db_fields = array();
84 protected $all_required = array();
85 protected $all_visibles = array();
86 protected $categorized_fields = array();
87 protected $table;
88 protected $defaults = null;
89 protected $cats_defaults = null;
90
91 private $staff_fields = array(
92 'activite_adh',
93 'id_statut',
94 'bool_exempt_adh',
95 'date_crea_adh',
96 'info_adh'
97 );
98 private $admin_fields = array(
99 'bool_admin_adh'
100 );
101
102 const TABLE = 'fields_config';
103
104 /*
105 * Fields that are not visible in the
106 * form should not be visible here.
107 */
108 private $non_required = array(
109 'id_adh',
110 'date_echeance',
111 'bool_display_info',
112 'bool_exempt_adh',
113 'bool_admin_adh',
114 'activite_adh',
115 'date_crea_adh',
116 'date_modif_adh',
117 //Fields we do not want to be set as required
118 'societe_adh',
119 'id_statut',
120 'pref_lang',
121 'sexe_adh',
122 'parent_id'
123 );
124
125 private $non_form_elements = array(
126 'date_echeance',
127 'date_modif_adh'
128 );
129
130 private $non_display_elements = array(
131 'date_echeance',
132 'mdp_adh',
133 'titre_adh',
134 'sexe_adh',
135 'prenom_adh',
136 'adresse2_adh'
137 );
138
139 /**
140 * Default constructor
141 *
142 * @param Db $zdb Database
143 * @param string $table the table for which to get fields configuration
144 * @param array $defaults default values
145 * @param array $cats_defaults default categories values
146 * @param boolean $install Are we calling from installer?
147 */
148 public function __construct(Db $zdb, $table, $defaults, $cats_defaults, $install = false)
149 {
150 $this->zdb = $zdb;
151 $this->table = $table;
152 $this->defaults = $defaults;
153 $this->cats_defaults = $cats_defaults;
154 //prevent check at install time...
155 if (!$install) {
156 $this->load();
157 $this->checkUpdate();
158 }
159 }
160
161 /**
162 * Load current fields configuration from database.
163 *
164 * @return boolean
165 */
166 public function load()
167 {
168 try {
169 $select = $this->zdb->select(self::TABLE);
170 $select
171 ->where(array('table_name' => $this->table))
172 ->order(array(FieldsCategories::PK, 'position ASC'));
173
174 $results = $this->zdb->execute($select);
175 $this->core_db_fields = [];
176
177 foreach ($results as $k) {
178 $field = $this->buildField($k);
179 $this->core_db_fields[$k->field_id] = $field;
180 }
181
182 $this->buildLists();
183 return true;
184 } catch (\Exception $e) {
185 Analog::log(
186 'Fields configuration cannot be loaded!',
187 Analog::URGENT
188 );
189 throw $e;
190 }
191 }
192
193 /**
194 * Prepare a field (required data, automation)
195 *
196 * @param ArrayObject $rset DB ResultSet row
197 *
198 * @return ArrayObject
199 */
200 protected function prepareField(ArrayObject $rset): ArrayObject
201 {
202 if ($rset->field_id === 'parent_id') {
203 $rset->readonly = true;
204 $rset->required = false;
205 }
206 return $rset;
207 }
208
209 /**
210 * Prepare a field (required data, automation)
211 *
212 * @param ArrayObject $rset DB ResultSet row
213 *
214 * @return array
215 */
216 protected function buildField(ArrayObject $rset): array
217 {
218 $rset = $this->prepareField($rset);
219 $f = array(
220 'field_id' => $rset->field_id,
221 'label' => $this->defaults[$rset->field_id]['label'],
222 'category' => (int)$rset->id_field_category,
223 'visible' => (int)$rset->visible,
224 'required' => (bool)$rset->required,
225 'propname' => $this->defaults[$rset->field_id]['propname'],
226 'position' => (int)$rset->position,
227 'disabled' => false
228 );
229 return $f;
230 }
231
232 /**
233 * Create field array configuration,
234 * Several lists of fields are kept (visible, requireds, etc), build them.
235 *
236 * @return void
237 */
238 protected function buildLists()
239 {
240
241 $this->categorized_fields = [];
242 $this->all_required = [];
243 $this->all_visibles = [];
244
245 foreach ($this->core_db_fields as $field) {
246 $this->addToLists($field);
247 }
248 }
249
250 /**
251 * Adds a field to lists
252 *
253 * @param array $field Field values
254 *
255 * @return void
256 */
257 protected function addToLists(array $field)
258 {
259 if ($field['position'] >= 0) {
260 $this->categorized_fields[$field['category']][] = $field;
261 }
262
263 //array of all required fields
264 if ($field['required']) {
265 $this->all_required[$field['field_id']] = $field['required'];
266 }
267
268 //array of all fields visibility
269 $this->all_visibles[$field['field_id']] = $field['visible'];
270 }
271
272 /**
273 * Is a field set as required?
274 *
275 * @param string $field Field name
276 *
277 * @return boolean
278 */
279 public function isRequired($field)
280 {
281 return isset($this->all_required[$field]);
282 }
283
284 /**
285 * Temporary set a field as not required
286 * (password for existing members for example)
287 *
288 * @param string $field Field name
289 *
290 * @return void
291 */
292 public function setNotRequired($field)
293 {
294 if (isset($this->all_required[$field])) {
295 unset($this->all_required[$field]);
296 }
297
298 foreach ($this->categorized_fields as &$cat) {
299 foreach ($cat as &$f) {
300 if ($f['field_id'] === $field) {
301 $f['required'] = false;
302 return;
303 }
304 }
305 }
306 }
307
308 /**
309 * Checks if all fields are present in the database.
310 *
311 * For now, this function only checks if count matches.
312 *
313 * @return void
314 */
315 private function checkUpdate()
316 {
317 $class = get_class($this);
318
319 try {
320 $_all_fields = array();
321 if (count($this->core_db_fields)) {
322 array_walk(
323 $this->core_db_fields,
324 function ($field) use (&$_all_fields) {
325 $_all_fields[$field['field_id']] = $field;
326 }
327 );
328 } else {
329 //hum... no records. Let's check if any category exists
330 $select = $this->zdb->select(FieldsCategories::TABLE);
331 $results = $this->zdb->execute($select);
332
333 if ($results->count() == 0) {
334 //categories are missing, add them
335 $categories = new FieldsCategories($this->zdb, $this->cats_defaults);
336 $categories->installInit();
337 }
338 }
339
340 if (count($this->defaults) != count($_all_fields)) {
341 Analog::log(
342 'Fields configuration count for `' . $this->table .
343 '` columns does not match records. Is : ' .
344 count($_all_fields) . ' and should be ' .
345 count($this->defaults),
346 Analog::WARNING
347 );
348
349 $params = array();
350 foreach ($this->defaults as $k => $f) {
351 if (!isset($_all_fields[$k])) {
352 Analog::log(
353 'Missing field configuration for field `' . $k . '`',
354 Analog::INFO
355 );
356 $params[] = array(
357 'field_id' => $k,
358 'table_name' => $this->table,
359 'required' => $f['required'],
360 'visible' => $f['visible'],
361 'position' => $f['position'],
362 'category' => $f['category'],
363 'list_visible' => $f['list_visible'] ?? false,
364 'list_position' => $f['list_position'] ?? null
365 );
366 }
367 }
368
369 if (count($params) > 0) {
370 $this->insert($params);
371 $this->load();
372 }
373 }
374 } catch (\Exception $e) {
375 Analog::log(
376 '[' . $class . '] An error occurred while checking update for ' .
377 'fields configuration for table `' . $this->table . '`. ' .
378 $e->getMessage(),
379 Analog::ERROR
380 );
381 throw $e;
382 }
383 }
384
385 /**
386 * Set default fields configuration at install time. All previous
387 * existing values will be dropped first, including fields categories.
388 *
389 * @return boolean|\Exception
390 */
391 public function installInit()
392 {
393 try {
394 $fields = array_keys($this->defaults);
395 $categories = new FieldsCategories($this->zdb, $this->cats_defaults);
396
397 //first, we drop all values
398 $delete = $this->zdb->delete(self::TABLE);
399 $delete->where(
400 array('table_name' => $this->table)
401 );
402 $this->zdb->execute($delete);
403 //take care of fields categories, for db relations
404 $categories->installInit($this->zdb);
405
406 $fields = array_keys($this->defaults);
407 foreach ($fields as $f) {
408 //build default config for each field
409 $params[] = array(
410 'field_id' => $f,
411 'table_name' => $this->table,
412 'required' => $this->defaults[$f]['required'],
413 'visible' => $this->defaults[$f]['visible'],
414 'position' => (int)$this->defaults[$f]['position'],
415 'category' => $this->defaults[$f]['category'],
416 'list_visible' => $this->defaults[$f]['list_visible'] ?? false,
417 'list_position' => $this->defaults[$f]['list_position'] ?? -1
418 );
419 }
420 $this->insert($params);
421
422 Analog::log(
423 'Default fields configuration were successfully stored.',
424 Analog::INFO
425 );
426 return true;
427 } catch (\Exception $e) {
428 Analog::log(
429 'Unable to initialize default fields configuration.' . $e->getMessage(),
430 Analog::ERROR
431 );
432
433 /*$messages = array();
434 do {
435 $messages[] = $e->getMessage();
436 } while ($e = $e->getPrevious());
437
438 Analog::log(
439 'Unable to initialize default fields configuration.' .
440 implode("\n", $messages),
441 Analog::ERROR
442 );*/
443 return $e;
444 }
445 }
446
447 /**
448 * Get non required fields
449 *
450 * @return array
451 */
452 public function getNonRequired()
453 {
454 return $this->non_required;
455 }
456
457 /**
458 * Retrieve form elements
459 *
460 * @param Login $login Login instance
461 * @param boolean $new True when adding a new member
462 * @param boolean $selfs True if we're called from self subscription page
463 *
464 * @return array
465 */
466 public function getFormElements(Login $login, $new, $selfs = false)
467 {
468 global $preferences;
469
470 $hidden_elements = [];
471 $form_elements = [];
472
473 //get columns descriptions
474 $columns = $this->zdb->getColumns($this->table);
475
476 $access_level = $login->getAccessLevel();
477 $categories = FieldsCategories::getList($this->zdb);
478 try {
479 foreach ($categories as $c) {
480 $cpk = FieldsCategories::PK;
481 $cat_label = null;
482 foreach ($this->cats_defaults as $conf_cat) {
483 if ($conf_cat['id'] == $c->$cpk) {
484 $cat_label = $conf_cat['category'];
485 break;
486 }
487 }
488 if ($cat_label === null) {
489 $cat_label = $c->category;
490 }
491 $cat = (object)array(
492 'id' => (int)$c->$cpk,
493 'label' => $cat_label,
494 'elements' => array()
495 );
496
497 $elements = $this->categorized_fields[$c->$cpk];
498 $cat->elements = array();
499
500 foreach ($elements as $elt) {
501 $o = (object)$elt;
502 $o->readonly = false;
503
504 if ($o->field_id == 'id_adh') {
505 // ignore access control, as member ID is always needed
506 if (!$preferences->pref_show_id || $new === true) {
507 $hidden_elements[] = $o;
508 } else {
509 $o->type = self::TYPE_STR;
510 $o->readonly = true;
511 $cat->elements[$o->field_id] = $o;
512 }
513 } elseif ($o->field_id == 'parent_id') {
514 $hidden_elements[] = $o;
515 } else {
516 // skip fields blacklisted for edition
517 if (
518 in_array($o->field_id, $this->non_form_elements)
519 || $selfs && $this->isSelfExcluded($o->field_id)
520 ) {
521 continue;
522 }
523
524 // skip fields according to access control
525 if (
526 $o->visible == self::NOBODY ||
527 ($o->visible == self::ADMIN &&
528 $access_level < Authentication::ACCESS_ADMIN) ||
529 ($o->visible == self::STAFF &&
530 $access_level < Authentication::ACCESS_STAFF) ||
531 ($o->visible == self::MANAGER &&
532 $access_level < Authentication::ACCESS_MANAGER)
533 ) {
534 continue;
535 }
536
537 if (preg_match('/date/', $o->field_id)) {
538 $o->type = self::TYPE_DATE;
539 } elseif (preg_match('/bool/', $o->field_id)) {
540 $o->type = self::TYPE_BOOL;
541 } elseif (
542 $o->field_id == 'titre_adh'
543 || $o->field_id == 'pref_lang'
544 || $o->field_id == 'id_statut'
545 ) {
546 $o->type = self::TYPE_SELECT;
547 } elseif ($o->field_id == 'sexe_adh') {
548 $o->type = self::TYPE_RADIO;
549 } else {
550 $o->type = self::TYPE_STR;
551 }
552
553 //retrieve field information from DB
554 foreach ($columns as $column) {
555 if ($column->getName() === $o->field_id) {
556 $o->max_length
557 = $column->getCharacterMaximumLength();
558 $o->default = $column->getColumnDefault();
559 $o->datatype = $column->getDataType();
560 break;
561 }
562 }
563
564 // disabled field according to access control
565 if (
566 $o->visible == self::USER_READ &&
567 $access_level == Authentication::ACCESS_USER
568 ) {
569 $o->disabled = true;
570 } else {
571 $o->disabled = false;
572 }
573
574 $cat->elements[$o->field_id] = $o;
575 }
576 }
577
578 if (count($cat->elements) > 0) {
579 $form_elements[] = $cat;
580 }
581 }
582 return array(
583 'fieldsets' => $form_elements,
584 'hiddens' => $hidden_elements
585 );
586 } catch (\Exception $e) {
587 Analog::log(
588 'An error occurred getting form elements',
589 Analog::ERROR
590 );
591 throw $e;
592 }
593 }
594
595 /**
596 * Retrieve display elements
597 *
598 * @param Login $login Login instance
599 *
600 * @return array
601 */
602 public function getDisplayElements(Login $login)
603 {
604 global $preferences;
605
606 $display_elements = [];
607 $access_level = $login->getAccessLevel();
608 $categories = FieldsCategories::getList($this->zdb);
609 try {
610 foreach ($categories as $c) {
611 $cpk = FieldsCategories::PK;
612 $cat_label = null;
613 foreach ($this->cats_defaults as $conf_cat) {
614 if ($conf_cat['id'] == $c->$cpk) {
615 $cat_label = $conf_cat['category'];
616 break;
617 }
618 }
619 if ($cat_label === null) {
620 $cat_label = $c->category;
621 }
622 $cat = (object)array(
623 'id' => (int)$c->$cpk,
624 'label' => $cat_label,
625 'elements' => array()
626 );
627
628 $elements = $this->categorized_fields[$c->$cpk];
629 $cat->elements = array();
630
631 foreach ($elements as $elt) {
632 $o = (object)$elt;
633
634 if ($o->field_id == 'id_adh') {
635 // ignore access control, as member ID is always needed
636 if (!isset($preferences) || !$preferences->pref_show_id) {
637 $hidden_elements[] = $o;
638 } else {
639 $o->type = self::TYPE_STR;
640 $cat->elements[$o->field_id] = $o;
641 }
642 } else {
643 // skip fields blacklisted for display
644 if (in_array($o->field_id, $this->non_display_elements)) {
645 continue;
646 }
647
648 // skip fields according to access control
649 if (
650 $o->visible == self::NOBODY ||
651 ($o->visible == self::ADMIN &&
652 $access_level < Authentication::ACCESS_ADMIN) ||
653 ($o->visible == self::STAFF &&
654 $access_level < Authentication::ACCESS_STAFF) ||
655 ($o->visible == self::MANAGER &&
656 $access_level < Authentication::ACCESS_MANAGER)
657 ) {
658 continue;
659 }
660
661 $cat->elements[$o->field_id] = $o;
662 }
663 }
664
665 if (count($cat->elements) > 0) {
666 $display_elements[] = $cat;
667 }
668 }
669 return $display_elements;
670 } catch (\Exception $e) {
671 Analog::log(
672 'An error occurred getting display elements',
673 Analog::ERROR
674 );
675 throw $e;
676 }
677 }
678
679 /**
680 * Get required fields
681 *
682 * @return array of all required fields. Field names = keys
683 */
684 public function getRequired()
685 {
686 return $this->all_required;
687 }
688
689 /**
690 * Get visible fields
691 *
692 * @return array of all visibles fields
693 */
694 public function getVisibilities()
695 {
696 return $this->all_visibles;
697 }
698
699 /**
700 * Get visibility for specified field
701 *
702 * @param string $field The requested field
703 *
704 * @return boolean
705 */
706 public function getVisibility($field)
707 {
708 return $this->all_visibles[$field];
709 }
710
711 /**
712 * Get all fields with their categories
713 *
714 * @return array
715 */
716 public function getCategorizedFields()
717 {
718 return $this->categorized_fields;
719 }
720
721 /**
722 * Set fields
723 *
724 * @param array $fields categorized fields array
725 *
726 * @return boolean
727 */
728 public function setFields($fields)
729 {
730 $this->categorized_fields = $fields;
731 return $this->store();
732 }
733
734 /**
735 * Store config in database
736 *
737 * @return boolean
738 */
739 private function store()
740 {
741 $class = get_class($this);
742
743 try {
744 $this->zdb->connection->beginTransaction();
745
746 $update = $this->zdb->update(self::TABLE);
747 $update->set(
748 array(
749 'required' => ':required',
750 'visible' => ':visible',
751 'position' => ':position',
752 FieldsCategories::PK => ':category'
753 )
754 )->where(
755 array(
756 'field_id' => ':field_id',
757 'table_name' => $this->table
758 )
759 );
760 $stmt = $this->zdb->sql->prepareStatementForSqlObject($update);
761
762 $params = null;
763 foreach ($this->categorized_fields as $cat) {
764 foreach ($cat as $pos => $field) {
765 if (in_array($field['field_id'], $this->non_required)) {
766 $field['required'] = $this->zdb->isPostgres() ? 'false' : 0;
767 }
768
769 if ($field['field_id'] === 'parent_id') {
770 $field['visible'] = 0;
771 }
772
773 $params = array(
774 'required' => $field['required'],
775 'visible' => $field['visible'],
776 'position' => $pos,
777 FieldsCategories::PK => $field['category'],
778 'where1' => $field['field_id']
779 );
780
781 $stmt->execute($params);
782 }
783 }
784
785 Analog::log(
786 '[' . $class . '] Fields configuration stored successfully! ',
787 Analog::DEBUG
788 );
789 Analog::log(
790 str_replace(
791 '%s',
792 $this->table,
793 '[' . $class . '] Fields configuration for table %s stored ' .
794 'successfully.'
795 ),
796 Analog::INFO
797 );
798
799 $this->zdb->connection->commit();
800 return $this->load();
801 } catch (\Exception $e) {
802 $this->zdb->connection->rollBack();
803 Analog::log(
804 '[' . $class . '] An error occurred while storing fields ' .
805 'configuration for table `' . $this->table . '`.' .
806 $e->getMessage(),
807 Analog::ERROR
808 );
809 Analog::log(
810 $e->getTraceAsString(),
811 Analog::ERROR
812 );
813 return false;
814 }
815 }
816
817 /**
818 * Migrate old required fields configuration
819 * Only needeed for 0.7.4 upgrade
820 * (should have been 0.7.3 - but I missed that.)
821 *
822 * @return boolean
823 */
824 public function migrateRequired()
825 {
826 $old_required = null;
827
828 try {
829 $select = $this->zdb->select('required');
830 $select->from(PREFIX_DB . 'required');
831
832 $old_required = $this->zdb->execute($select);
833 } catch (\Exception $pe) {
834 Analog::log(
835 'Unable to retrieve required fields_config. Maybe ' .
836 'the table does not exists?',
837 Analog::WARNING
838 );
839 //not a blocker
840 return true;
841 }
842
843 $this->zdb->connection->beginTransaction();
844 try {
845 $update = $this->zdb->update(self::TABLE);
846 $update->set(
847 array(
848 'required' => ':required'
849 )
850 )->where(
851 array(
852 'field_id' => ':field_id',
853 'table_name' => $this->table
854 )
855 );
856
857 $stmt = $this->zdb->sql->prepareStatementForSqlObject($update);
858
859 foreach ($old_required as $or) {
860 /** Why where parameter is named where1 ?? */
861 $stmt->execute(
862 array(
863 'required' => ($or->required === false) ?
864 ($this->zdb->isPostgres() ? 'false' : 0) : true,
865 'where1' => $or->field_id
866 )
867 );
868 }
869
870 $class = get_class($this);
871 Analog::log(
872 str_replace(
873 '%s',
874 $this->table,
875 '[' . $class . '] Required fields for table %s upgraded ' .
876 'successfully.'
877 ),
878 Analog::INFO
879 );
880
881 $this->zdb->db->query(
882 'DROP TABLE ' . PREFIX_DB . 'required',
883 Adapter::QUERY_MODE_EXECUTE
884 );
885
886 $this->zdb->connection->commit();
887 return true;
888 } catch (\Exception $e) {
889 $this->zdb->connection->rollBack();
890 Analog::log(
891 'An error occurred migrating old required fields. | ' .
892 $e->getMessage(),
893 Analog::ERROR
894 );
895 return false;
896 }
897 }
898
899 /**
900 * Insert values in database
901 *
902 * @param array $values Values to insert
903 *
904 * @return void
905 */
906 private function insert($values)
907 {
908 $insert = $this->zdb->insert(self::TABLE);
909 $insert->values(
910 array(
911 'field_id' => ':field_id',
912 'table_name' => ':table_name',
913 'required' => ':required',
914 'visible' => ':visible',
915 FieldsCategories::PK => ':category',
916 'position' => ':position',
917 'list_visible' => ':list_visible',
918 'list_position' => ':list_position'
919 )
920 );
921 $stmt = $this->zdb->sql->prepareStatementForSqlObject($insert);
922 foreach ($values as $d) {
923 $required = $d['required'];
924 if ($required === false) {
925 $required = $this->zdb->isPostgres() ? 'false' : 0;
926 }
927
928 $list_visible = $f['list_visible'] ?? false;
929 if ($list_visible === false) {
930 $list_visible = $this->zdb->isPostgres() ? 'false' : 0;
931 }
932
933 $stmt->execute(
934 array(
935 'field_id' => $d['field_id'],
936 'table_name' => $d['table_name'],
937 'required' => $required,
938 'visible' => $d['visible'],
939 FieldsCategories::PK => $d['category'],
940 'position' => $d['position'],
941 'list_visible' => $list_visible,
942 'list_position' => $d['list_position'] ?? -1
943 )
944 );
945 }
946 }
947
948 /**
949 * Does field should be displayed in self subscription page
950 *
951 * @param string $name Field name
952 *
953 * @return boolean
954 */
955 public function isSelfExcluded($name)
956 {
957 return in_array(
958 $name,
959 array_merge(
960 $this->staff_fields,
961 $this->admin_fields
962 )
963 );
964 }
965
966 /**
967 * Get fields for massive changes
968 * @see FieldsConfig::getFormElements
969 *
970 * @param array $fields Member fields
971 * @param Login $login Login instance
972 *
973 * @return array
974 */
975 public function getMassiveFormElements(array $fields, Login $login)
976 {
977 $visibles = $this->getVisibilities();
978 $access_level = $login->getAccessLevel();
979
980 //remove not searchable fields
981 unset($fields['mdp_adh']);
982
983 foreach ($fields as $k => $f) {
984 if (
985 $visibles[$k] == FieldsConfig::NOBODY ||
986 ($visibles[$k] == FieldsConfig::ADMIN &&
987 $access_level < Authentication::ACCESS_ADMIN) ||
988 ($visibles[$k] == FieldsConfig::STAFF &&
989 $access_level < Authentication::ACCESS_STAFF) ||
990 ($visibles[$k] == FieldsConfig::MANAGER &&
991 $access_level < Authentication::ACCESS_MANAGER)
992 ) {
993 unset($fields[$k]);
994 }
995 }
996
997 $mass_fields = [
998 'titre_adh',
999 'sexe_adh',
1000 'pref_lang',
1001 'cp_adh',
1002 'ville_adh',
1003 'pays_adh',
1004 'bool_display_info',
1005 'activite_adh',
1006 Status::PK,
1007 'bool_admin_adh',
1008 'bool_exempt_adh',
1009 ];
1010 $mass_fields = array_intersect(array_keys($fields), $mass_fields);
1011
1012 foreach ($mass_fields as $mass_field) {
1013 $this->setNotRequired($mass_field);
1014 }
1015 $form_elements = $this->getFormElements($login, false);
1016 unset($form_elements['hiddens']);
1017
1018 foreach ($form_elements['fieldsets'] as &$form_element) {
1019 $form_element->elements = array_intersect_key($form_element->elements, array_flip($mass_fields));
1020 }
1021 return $form_elements;
1022 }
1023
1024 /**
1025 * Get field configuration
1026 *
1027 * @param string $name Field name
1028 *
1029 * @return array
1030 */
1031 public function getField($name): array
1032 {
1033 if (!isset($this->core_db_fields[$name])) {
1034 throw new \UnexpectedValueException("$name fied does not exists");
1035 }
1036 return $this->core_db_fields[$name];
1037 }
1038 }