]> git.agnieray.net Git - galette.git/blob - galette/lib/Galette/DynamicFields/DynamicField.php
Use prepared statement rather than direct SQL
[galette.git] / galette / lib / Galette / DynamicFields / DynamicField.php
1 <?php
2
3 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
4
5 /**
6 * Abstract dynamic field
7 *
8 * PHP version 5
9 *
10 * Copyright © 2012-2021 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 DynamicFields
28 * @package Galette
29 *
30 * @author Johan Cwiklinski <johan@x-tnd.be>
31 * @copyright 2012-2021 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.7.1dev - 2012-07-28
35 */
36
37 namespace Galette\DynamicFields;
38
39 use Throwable;
40 use Analog\Analog;
41 use Galette\Core\Db;
42 use Galette\Entity\DynamicFieldsHandle;
43 use Galette\Features\Translatable;
44 use Galette\Features\I18n;
45 use Laminas\Db\Sql\Expression;
46 use Laminas\Db\Sql\Predicate\Expression as PredicateExpression;
47
48 /**
49 * Abstract dynamic field
50 *
51 * @name DynamicField
52 * @category DynamicFields
53 * @package Galette
54 *
55 * @author Johan Cwiklinski <johan@x-tnd.be>
56 * @copyright 2012-2014 The Galette Team
57 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
58 * @link http://galette.tuxfamily.org
59 */
60
61 abstract class DynamicField
62 {
63 use Translatable;
64 use I18n;
65
66 public const TABLE = 'field_types';
67 public const PK = 'field_id';
68
69 /** Separator field */
70 public const SEPARATOR = 0;
71 /** Simple text field */
72 public const TEXT = 1;
73 /** Line field */
74 public const LINE = 2;
75 /** Choice field (listbox) */
76 public const CHOICE = 3;
77 /** Date field */
78 public const DATE = 4;
79 /** Boolean field (checkbox) */
80 public const BOOLEAN = 5;
81 /** File field (upload) */
82 public const FILE = 6;
83
84 public const PERM_USER_WRITE = 0;
85 public const PERM_ADMIN = 1;
86 public const PERM_STAFF = 2;
87 public const PERM_MANAGER = 3;
88 public const PERM_USER_READ = 4;
89
90 public const DEFAULT_MAX_FILE_SIZE = 1024;
91 public const VALUES_FIELD_LENGTH = 100;
92
93 protected $has_data = false;
94 protected $has_width = false;
95 protected $has_height = false;
96 protected $has_size = false;
97 protected $multi_valued = false;
98 protected $fixed_values = false;
99 protected $has_permissions = true;
100
101 protected $id;
102 protected $index;
103 protected $perm;
104 protected $required;
105 protected $width;
106 protected $height;
107 protected $repeat;
108 protected $size;
109 protected $old_size;
110 protected $values;
111 protected $form;
112
113 protected $errors;
114
115 protected $zdb;
116
117 /**
118 * Default constructor
119 *
120 * @param Db $zdb Database instance
121 * @param mixed $args Arguments
122 */
123 public function __construct(Db $zdb, $args = null)
124 {
125 $this->zdb = $zdb;
126
127 if (is_int($args)) {
128 $this->load($args);
129 } elseif ($args !== null && is_object($args)) {
130 $this->loadFromRs($args);
131 }
132 }
133
134 /**
135 * Load field from its id
136 *
137 * @param Db $zdb Database instance
138 * @param int $id Field id
139 *
140 * @return DynamicField|false
141 */
142 public static function loadFieldType(Db $zdb, $id)
143 {
144 try {
145 $select = $zdb->select(self::TABLE);
146 $select->where(['field_id' => $id]);
147
148 $results = $zdb->execute($select);
149 $result = $results->current();
150 if ($result) {
151 $field_type = $result->field_type;
152 $field_type = self::getFieldType($zdb, $field_type);
153 $field_type->loadFromRs($result);
154 return $field_type;
155 }
156 } catch (Throwable $e) {
157 Analog::log(
158 __METHOD__ . ' | Unable to retrieve field `' . $id .
159 '` information | ' . $e->getMessage(),
160 Analog::ERROR
161 );
162 return false;
163 }
164 return false;
165 }
166
167 /**
168 * Get correct field type instance
169 *
170 * @param Db $zdb Database instance
171 * @param int $t Field type
172 * @param int $id Optional dynamic field id (to load data)
173 *
174 * @return DynamicField
175 */
176 public static function getFieldType(Db $zdb, $t, $id = null)
177 {
178 $df = null;
179 switch ($t) {
180 case self::SEPARATOR:
181 $df = new Separator($zdb, $id);
182 break;
183 case self::TEXT:
184 $df = new Text($zdb, $id);
185 break;
186 case self::LINE:
187 $df = new Line($zdb, $id);
188 break;
189 case self::CHOICE:
190 $df = new Choice($zdb, $id);
191 break;
192 case self::DATE:
193 $df = new Date($zdb, $id);
194 break;
195 case self::BOOLEAN:
196 $df = new Boolean($zdb, $id);
197 break;
198 case self::FILE:
199 $df = new File($zdb, $id);
200 break;
201 default:
202 throw new \Exception('Unknown field type ' . $t . '!');
203 break;
204 }
205 return $df;
206 }
207
208 /**
209 * Load field
210 *
211 * @param integer $id Id
212 *
213 * @return void
214 */
215 public function load($id)
216 {
217 try {
218 $select = $this->zdb->select(self::TABLE);
219 $select->where([self::PK => $id]);
220
221 $results = $this->zdb->execute($select);
222 $result = $results->current();
223
224 if ($result) {
225 $this->loadFromRs($result);
226 }
227 } catch (Throwable $e) {
228 Analog::log(
229 'Unable to retrieve field type for field ' . $id . ' | ' .
230 $e->getMessage(),
231 Analog::ERROR
232 );
233 }
234 }
235
236 /**
237 * Load field type from a db ResultSet
238 *
239 * @param ResultSet $rs ResultSet
240 * @param boolean $values Whether to load values. Defaults to true
241 *
242 * @return void
243 */
244 public function loadFromRs($rs, $values = true)
245 {
246 $this->id = (int)$rs->field_id;
247 $this->name = $rs->field_name;
248 $this->index = (int)$rs->field_index;
249 $this->perm = (int)$rs->field_perm;
250 $this->required = ($rs->field_required == 1 ? true : false);
251 $this->width = $rs->field_width;
252 $this->height = $rs->field_height;
253 $this->repeat = $rs->field_repeat;
254 $this->size = $rs->field_size;
255 $this->form = $rs->field_form;
256 if ($values && $this->hasFixedValues()) {
257 $this->loadFixedValues();
258 }
259 }
260
261 /**
262 * Retrieve fixed values table name
263 *
264 * @param integer $id Field ID
265 * @param boolean $prefixed Whether table name should be prefixed
266 *
267 * @return string
268 */
269 public static function getFixedValuesTableName($id, $prefixed = false)
270 {
271 $name = 'field_contents_' . $id;
272 if ($prefixed === true) {
273 $name = PREFIX_DB . $name;
274 }
275 return $name;
276 }
277
278 /**
279 * Returns an array of fixed valued for a field of type 'choice'.
280 *
281 * @return void
282 */
283 private function loadFixedValues()
284 {
285 try {
286 $val_select = $this->zdb->select(
287 self::getFixedValuesTableName($this->id)
288 );
289
290 $val_select->columns(
291 array(
292 'val'
293 )
294 )->order('id');
295
296 $results = $this->zdb->execute($val_select);
297 $this->values = array();
298 if ($results) {
299 foreach ($results as $val) {
300 $this->values[] = $val->val;
301 }
302 }
303 } catch (Throwable $e) {
304 Analog::log(
305 __METHOD__ . ' | ' . $e->getMessage(),
306 Analog::WARNING
307 );
308 }
309 }
310
311 /**
312 * Get field type
313 *
314 * @return integer
315 */
316 abstract public function getType();
317
318 /**
319 * Get field type name
320 *
321 * @return String
322 */
323 public function getTypeName()
324 {
325 $types = $this->getFieldsTypesNames();
326 if (isset($types[$this->getType()])) {
327 return $types[$this->getType()];
328 } else {
329 throw new \RuntimeException(
330 'Unknow type ' . $this->getType()
331 );
332 }
333 }
334
335 /**
336 * Does the field handle data?
337 *
338 * @return boolean
339 */
340 public function hasData()
341 {
342 return $this->has_data;
343 }
344
345 /**
346 * Does the field has width?
347 *
348 * @return boolean
349 */
350 public function hasWidth()
351 {
352 return $this->has_width;
353 }
354
355 /**
356 * Does the field has height?
357 *
358 * @return boolean
359 */
360 public function hasHeight()
361 {
362 return $this->has_height;
363 }
364
365 /**
366 * Does the field has a size?
367 *
368 * @return boolean
369 */
370 public function hasSize()
371 {
372 return $this->has_size;
373 }
374
375 /**
376 * Is the field multi valued?
377 *
378 * @return boolean
379 */
380 public function isMultiValued()
381 {
382 return $this->multi_valued;
383 }
384
385 /**
386 * Does the field has fixed values?
387 *
388 * @return boolean
389 */
390 public function hasFixedValues()
391 {
392 return $this->fixed_values;
393 }
394
395 /**
396 * Does the field require permissions?
397 *
398 * @return boolean
399 */
400 public function hasPermissions()
401 {
402 return $this->has_permissions;
403 }
404
405
406 /**
407 * Get field id
408 *
409 * @return integer
410 */
411 public function getId()
412 {
413 return $this->id;
414 }
415
416 /**
417 * Get field Permissions
418 *
419 * @return integer
420 */
421 public function getPerm()
422 {
423 return $this->perm;
424 }
425
426
427 /**
428 * Is field required?
429 *
430 * @return boolean
431 */
432 public function isRequired()
433 {
434 return $this->required;
435 }
436
437 /**
438 * Get field width
439 *
440 * @return integer
441 */
442 public function getWidth()
443 {
444 return $this->width;
445 }
446
447 /**
448 * Get field height
449 *
450 * @return integer
451 */
452 public function getHeight()
453 {
454 return $this->height;
455 }
456
457 /**
458 * Is current field repeatable?
459 *
460 * @return boolean
461 */
462 public function isRepeatable()
463 {
464 return $this->repeat != null && trim($this->repeat) != '' && (int)$this->repeat >= 0;
465 }
466
467 /**
468 * Get fields repetitions
469 *
470 * @return integer|boolean
471 */
472 public function getRepeat()
473 {
474 return $this->repeat;
475 }
476
477 /**
478 * Get field size
479 *
480 * @return integer
481 */
482 public function getSize()
483 {
484 return $this->size;
485 }
486
487 /**
488 * Get field index
489 *
490 * @return integer
491 */
492 public function getIndex()
493 {
494 return $this->index;
495 }
496
497 /**
498 * Retrieve permissions names for display
499 *
500 * @return array
501 */
502 public static function getPermsNames()
503 {
504 return [
505 self::PERM_USER_WRITE => _T("User, read/write"),
506 self::PERM_STAFF => _T("Staff member"),
507 self::PERM_ADMIN => _T("Administrator"),
508 self::PERM_MANAGER => _T("Group manager"),
509 self::PERM_USER_READ => _T("User, read only")
510 ];
511 }
512
513 /**
514 * Retrieve forms names
515 *
516 * @return array
517 */
518 public static function getFormsNames()
519 {
520 return [
521 'adh' => _T("Members"),
522 'contrib' => _T("Contributions"),
523 'trans' => _T("Transactions")
524 ];
525 }
526
527 /**
528 * Retrieve form name
529 *
530 * @param string $form_name Form name
531 *
532 * @return string
533 */
534 public static function getFormTitle($form_name)
535 {
536 $names = self::getFormsNames();
537 return $names[$form_name];
538 }
539
540 /**
541 * Get permission name
542 *
543 * @return string
544 */
545 public function getPermName()
546 {
547 $perms = self::getPermsNames();
548 return $perms[$this->getPerm()];
549 }
550
551 /**
552 * Get form
553 *
554 * @return string
555 */
556 public function getForm()
557 {
558 return $this->form;
559 }
560
561 /**
562 * Get field values
563 *
564 * @param boolean $imploded Whether to implode values
565 *
566 * @return array
567 */
568 public function getValues($imploded = false)
569 {
570 if (!is_array($this->values)) {
571 return false;
572 }
573 if ($imploded === true) {
574 return implode("\n", $this->values);
575 } else {
576 return $this->values;
577 }
578 }
579
580 /**
581 * Check posted values validity
582 *
583 * @param array $values All values to check, basically the $_POST array
584 * after sending the form
585 *
586 * @return true|array
587 */
588 public function check($values)
589 {
590 $this->errors = [];
591 $this->warnings = [];
592
593 if (
594 (!isset($values['field_name']) || $values['field_name'] == '')
595 && get_class($this) != '\Galette\DynamicField\Separator'
596 ) {
597 $this->errors[] = _T('Missing required field name!');
598 } else {
599 if ($this->old_name === null && $this->name !== null && $this->name != $values['field_name']) {
600 $this->old_name = $this->name;
601 }
602 $this->name = $values['field_name'];
603 }
604
605 if (!isset($values['field_perm']) || $values['field_perm'] === '') {
606 $this->errors[] = _T('Missing required field permissions!');
607 } else {
608 if (in_array($values['field_perm'], array_keys(self::getPermsNames()))) {
609 $this->perm = $values['field_perm'];
610 } else {
611 $this->errors[] = _T('Unknown permission!');
612 }
613 }
614
615 if ($this->id === null) {
616 if (!isset($values['form_name']) || $values['form_name'] == '') {
617 $this->errors[] = _T('Missing required form!');
618 } else {
619 if (in_array($values['form_name'], array_keys(self::getFormsNames()))) {
620 $this->form = $values['form_name'];
621 } else {
622 $this->errors[] = _T('Unknown form!');
623 }
624 }
625 }
626
627 $this->required = $values['field_required'] ?? false;
628
629 if (count($this->errors) === 0 && $this->isDuplicate($values['form_name'], $this->name, $this->id)) {
630 $this->errors[] = _T("- Field name already used.");
631 }
632
633 if ($this->hasWidth() && isset($values['field_width']) && trim($values['field_width']) != '') {
634 $this->width = $values['field_width'];
635 }
636
637 if ($this->hasHeight() && isset($values['field_height']) && trim($values['field_height']) != '') {
638 $this->height = $values['field_height'];
639 }
640
641 if ($this->hasSize() && isset($values['field_size']) && trim($values['field_size']) != '') {
642 $this->size = $values['field_size'];
643 }
644
645 if (isset($values['field_repeat']) && trim($values['field_repeat']) != '') {
646 $this->repeat = $values['field_repeat'];
647 }
648
649 if ($this->hasFixedValues() && isset($values['fixed_values'])) {
650 $fixed_values = [];
651 foreach (explode("\n", $values['fixed_values']) as $val) {
652 $val = trim($val);
653 $len = mb_strlen($val);
654 if ($len > 0) {
655 $fixed_values[] = $val;
656 if ($len > $this->size) {
657 if ($this->old_size === null) {
658 $this->old_size = $this->size;
659 }
660 $this->size = $len;
661 }
662 }
663 }
664
665 $this->values = $fixed_values;
666 }
667
668 if ($this->id == null) {
669 $this->index = $this->getNewIndex();
670 }
671
672 if (count($this->errors) === 0) {
673 return true;
674 } else {
675 return false;
676 }
677 }
678
679 /**
680 * Store the field type
681 *
682 * @param array $values All values to check, basically the $_POST array
683 * after sending the form
684 *
685 * @return boolean
686 */
687 public function store($values)
688 {
689 if (!$this->check($values)) {
690 return false;
691 }
692
693 $isnew = ($this->id === null);
694 if ($this->old_name !== null) {
695 $this->deleteTranslation($this->old_name);
696 $this->addTranslation($this->name);
697 }
698
699 try {
700 $values = array(
701 'field_name' => strip_tags($this->name),
702 'field_perm' => $this->perm,
703 'field_required' => $this->required,
704 'field_width' => ($this->width === null ? new Expression('NULL') : $this->width),
705 'field_height' => ($this->height === null ? new Expression('NULL') : $this->height),
706 'field_size' => ($this->size === null ? new Expression('NULL') : $this->size),
707 'field_repeat' => ($this->repeat === null ? new Expression('NULL') : $this->repeat),
708 'field_form' => $this->form,
709 'field_index' => $this->index
710 );
711
712 if ($this->required === false) {
713 //Handle booleans for postgres ; bugs #18899 and #19354
714 $values['field_required'] = $this->zdb->isPostgres() ? 'false' : 0;
715 }
716
717 if (!$isnew) {
718 $update = $this->zdb->update(self::TABLE);
719 $update->set($values)->where([self::PK => $this->id]);
720 $this->zdb->execute($update);
721 } else {
722 $values['field_type'] = $this->getType();
723 $insert = $this->zdb->insert(self::TABLE);
724 $insert->values($values);
725 $this->zdb->execute($insert);
726
727 $this->id = $this->zdb->getLastGeneratedValue($this);
728
729 if ($this->name != '') {
730 $this->addTranslation($this->name);
731 }
732 }
733 } catch (Throwable $e) {
734 Analog::log(
735 'An error occurred storing field | ' . $e->getMessage(),
736 Analog::ERROR
737 );
738 $this->errors[] = _T("An error occurred storing the field.");
739 }
740
741 if (count($this->errors) === 0 && $this->hasFixedValues()) {
742 $contents_table = self::getFixedValuesTableName($this->id, true);
743
744 try {
745 $this->zdb->drop(str_replace(PREFIX_DB, '', $contents_table), true);
746 $field_size = ((int)$this->size > 0) ? $this->size : 1;
747 $this->zdb->db->query(
748 'CREATE TABLE ' . $contents_table .
749 ' (id INTEGER NOT NULL,val varchar(' . $field_size .
750 ') NOT NULL)',
751 \Laminas\Db\Adapter\Adapter::QUERY_MODE_EXECUTE
752 );
753 } catch (Throwable $e) {
754 Analog::log(
755 'Unable to manage fields values table ' .
756 $contents_table . ' | ' . $e->getMessage(),
757 Analog::ERROR
758 );
759 $this->errors[] = _T("An error occurred creating field values table");
760 }
761
762 if (count($this->errors) == 0 && is_array($this->values)) {
763 $contents_table = self::getFixedValuesTableName($this->id);
764 try {
765 $this->zdb->connection->beginTransaction();
766
767 $insert = $this->zdb->insert($contents_table);
768 $insert->values(
769 array(
770 'id' => ':id',
771 'val' => ':val'
772 )
773 );
774 $stmt = $this->zdb->sql->prepareStatementForSqlObject($insert);
775
776 $cnt_values = count($this->values);
777 for ($i = 0; $i < $cnt_values; $i++) {
778 $stmt->execute(
779 array(
780 'id' => $i,
781 'val' => $this->values[$i]
782 )
783 );
784 }
785 $this->zdb->connection->commit();
786 } catch (Throwable $e) {
787 $this->zdb->connection->rollBack();
788 Analog::log(
789 'Unable to store field ' . $this->id . ' values (' .
790 $e->getMessage() . ')',
791 Analog::ERROR
792 );
793 $this->warnings[] = _T('An error occurred storing dynamic field values :(');
794 }
795 }
796 }
797
798 if (count($this->errors) === 0) {
799 return true;
800 } else {
801 return false;
802 }
803 }
804
805 /**
806 * Get new index
807 *
808 * @return integer
809 */
810 protected function getNewIndex()
811 {
812 $select = $this->zdb->select(self::TABLE);
813 $select->columns(
814 array(
815 'idx' => new \Laminas\Db\Sql\Expression('COUNT(*) + 1')
816 )
817 );
818 $select->where(['field_form' => $this->form]);
819 $results = $this->zdb->execute($select);
820 $result = $results->current();
821 $idx = $result->idx;
822 return $idx;
823 }
824
825 /**
826 * Is field duplicated?
827 *
828 * @return boolean
829 */
830 public function isDuplicate()
831 {
832 //let's consider field is duplicated, in case of future errors
833 $duplicated = true;
834 try {
835 $select = $this->zdb->select(self::TABLE);
836 $select->columns(
837 array(
838 'cnt' => new \Laminas\Db\Sql\Expression('COUNT(' . self::PK . ')')
839 )
840 )->where(
841 array(
842 'field_form' => $this->form,
843 'field_name' => $this->name
844 )
845 );
846
847 if ($this->id !== null) {
848 $select->where->addPredicate(
849 new PredicateExpression(
850 'field_id NOT IN (?)',
851 array($this->id)
852 )
853 );
854 }
855
856 $results = $this->zdb->execute($select);
857 $result = $results->current();
858 $dup = $result->cnt;
859 if (!$dup > 0) {
860 $duplicated = false;
861 }
862 } catch (Throwable $e) {
863 Analog::log(
864 'An error occurred checking field duplicity' . $e->getMessage(),
865 Analog::ERROR
866 );
867 }
868 return $duplicated;
869 }
870 /**
871 * Move a dynamic field
872 *
873 * @param string $action What to do (either 'up' or 'down')
874 *
875 * @return boolean
876 */
877 public function move($action)
878 {
879 try {
880 $this->zdb->connection->beginTransaction();
881
882 $old_rank = $this->index;
883
884 $direction = $action == 'up' ? -1 : 1;
885 $new_rank = $old_rank + $direction;
886 $update = $this->zdb->update(self::TABLE);
887 $update->set([
888 'field_index' => $old_rank
889 ])->where([
890 'field_index' => $new_rank,
891 'field_form' => $this->form
892 ]);
893 $this->zdb->execute($update);
894
895 $update = $this->zdb->update(self::TABLE);
896 $update->set(
897 array(
898 'field_index' => $new_rank
899 )
900 )->where(
901 array(
902 self::PK => $this->id
903 )
904 );
905 $this->zdb->execute($update);
906 $this->zdb->connection->commit();
907
908 return true;
909 } catch (Throwable $e) {
910 $this->zdb->connection->rollBack();
911 Analog::log(
912 'Unable to change field ' . $this->id . ' rank | ' .
913 $e->getMessage(),
914 Analog::ERROR
915 );
916 return false;
917 }
918 }
919
920 /**
921 * Delete a dynamic field
922 *
923 * @return boolean
924 */
925 public function remove()
926 {
927 try {
928 if ($this->hasFixedValues()) {
929 $contents_table = self::getFixedValuesTableName($this->id);
930 $this->zdb->drop($contents_table);
931 }
932
933 $this->zdb->connection->beginTransaction();
934 $old_rank = $this->index;
935
936 $update = $this->zdb->update(self::TABLE);
937 $update->set(
938 array(
939 'field_index' => new \Laminas\Db\Sql\Expression('field_index-1')
940 )
941 )->where
942 ->greaterThan('field_index', $old_rank)
943 ->equalTo('field_form', $this->form);
944 $this->zdb->execute($update);
945
946 //remove associated values
947 $delete = $this->zdb->delete(DynamicFieldsHandle::TABLE);
948 $delete->where(
949 array(
950 'field_id' => $this->id,
951 'field_form' => $this->form
952 )
953 );
954 $result = $this->zdb->execute($delete);
955 if (!$result) {
956 throw new \RuntimeException('Unable to remove associated values for field ' . $this->id . '!');
957 }
958
959 //remove field type
960 $delete = $this->zdb->delete(self::TABLE);
961 $delete->where(
962 array(
963 'field_id' => $this->id,
964 'field_form' => $this->form
965 )
966 );
967 $result = $this->zdb->execute($delete);
968 if (!$result) {
969 throw new \RuntimeException('Unable to remove field ' . $this->id . '!');
970 }
971
972 $this->deleteTranslation($this->name);
973
974 $this->zdb->connection->commit();
975
976 return true;
977 } catch (Throwable $e) {
978 if ($this->zdb->connection->inTransaction()) {
979 //because of DROP autocommit on mysql...
980 $this->zdb->connection->rollBack();
981 }
982 Analog::log(
983 'An error occurred deleting field | ' . $e->getMessage(),
984 Analog::ERROR
985 );
986 return false;
987 }
988 }
989
990 /**
991 * Retrieve fields types names
992 *
993 * @return array
994 */
995 public static function getFieldsTypesNames()
996 {
997 $names = [
998 self::SEPARATOR => _T("separator"),
999 self::TEXT => _T("free text"),
1000 self::LINE => _T("single line"),
1001 self::CHOICE => _T("choice"),
1002 self::DATE => _T("date"),
1003 self::BOOLEAN => _T("boolean"),
1004 self::FILE => _T("file")
1005 ];
1006 return $names;
1007 }
1008
1009 /**
1010 * Get errors
1011 *
1012 * @return array
1013 */
1014 public function getErrors()
1015 {
1016 return $this->errors;
1017 }
1018
1019 /**
1020 * Get warnings
1021 *
1022 * @return array
1023 */
1024 public function getWarnings()
1025 {
1026 return $this->warnings;
1027 }
1028 }