dolibarr 21.0.0-alpha
ProductAttribute.class.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2016 Marcos García <marcosgdf@gmail.com>
3 * Copyright (C) 2022 Open-Dsi <support@open-dsi.fr>
4 * Copyright (C) 2023-2024 Frédéric France <frederic.france@free.fr>
5 * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
27require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
28
37{
42 public $db;
43
47 public $module = 'variants';
48
52 public $element = 'productattribute';
53
57 public $table_element = 'product_attribute';
58
62 public $table_element_line = 'product_attribute_value';
63
67 public $fk_element = 'fk_product_attribute';
68
72 public $picto = 'product';
73
102 public $fields = array(
103 'rowid' => array('type' => 'integer', 'label' => 'TechnicalID', 'enabled' => 1, 'position' => 1, 'notnull' => 1, 'visible' => 0, 'noteditable' => 1, 'index' => 1, 'css' => 'left', 'comment' => "Id"),
104 'ref' => array('type' => 'varchar(255)', 'label' => 'Ref', 'visible' => 1, 'enabled' => 1, 'position' => 10, 'notnull' => 1, 'index' => 1, 'searchall' => 1, 'comment' => "Reference of object", 'css' => 'width200'),
105 'ref_ext' => array('type' => 'varchar(255)', 'label' => 'ExternalRef', 'enabled' => 1, 'visible' => 0, 'position' => 20, 'searchall' => 1),
106 'label' => array('type' => 'varchar(255)', 'label' => 'Label', 'enabled' => 1, 'position' => 30, 'notnull' => 1, 'visible' => 1, 'searchall' => 1, 'css' => 'minwidth300', 'help' => "", 'showoncombobox' => 1,),
107 'position' => array('type' => 'integer', 'label' => 'Rank', 'enabled' => 1, 'visible' => 0, 'default' => '0', 'position' => 40, 'notnull' => 1,),
108 );
109
113 public $id;
114
118 public $ref;
119
123 public $ref_ext;
124
128 public $label;
129
135 public $rang;
136
140 public $position;
141
145 public $lines = array();
146
150 public $line;
151
155 public $is_used_by_products;
156
157
163 public function __construct(DoliDB $db)
164 {
165 global $conf, $langs;
166
167 $this->db = $db;
168
169 $this->ismultientitymanaged = 1;
170 $this->isextrafieldmanaged = 1;
171 $this->entity = $conf->entity;
172
173 if (!getDolGlobalString('MAIN_SHOW_TECHNICAL_ID') && isset($this->fields['rowid'])) {
174 $this->fields['rowid']['visible'] = 0;
175 }
176 if (!isModEnabled('multicompany') && isset($this->fields['entity'])) {
177 $this->fields['entity']['enabled'] = 0;
178 }
179
180 // Unset fields that are disabled
181 foreach ($this->fields as $key => $val) {
182 if (isset($val['enabled']) && empty($val['enabled'])) {
183 unset($this->fields[$key]);
184 }
185 }
186
187 // Translate some data of arrayofkeyval
188 if (is_object($langs)) {
189 foreach ($this->fields as $key => $val) {
190 if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) {
191 foreach ($val['arrayofkeyval'] as $key2 => $val2) {
192 $this->fields[$key]['arrayofkeyval'][$key2] = $langs->trans($val2);
193 }
194 }
195 }
196 }
197 }
198
206 public function create(User $user, $notrigger = 0)
207 {
208 global $langs;
209 $error = 0;
210
211 // Clean parameters
212 $this->ref = strtoupper(dol_sanitizeFileName(dol_string_nospecial(trim($this->ref)))); // Ref must be uppercase
213 $this->label = trim($this->label);
214 $this->position = $this->position > 0 ? $this->position : 0;
215
216 // Position to use
217 if (empty($this->position)) {
218 $positionmax = $this->getMaxAttributesPosition();
219 $this->position = $positionmax + 1;
220 }
221
222 // Check parameters
223 if (empty($this->ref)) {
224 $this->errors[] = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Ref"));
225 $error++;
226 }
227 if (empty($this->label)) {
228 $this->errors[] = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Label"));
229 $error++;
230 }
231 if ($error) {
232 dol_syslog(__METHOD__ . ' ' . $this->errorsToString(), LOG_ERR);
233 return -1;
234 }
235
236 $this->db->begin();
237
238 $sql = "INSERT INTO " . MAIN_DB_PREFIX . $this->table_element . " (";
239 $sql .= " ref, ref_ext, label, entity, position";
240 $sql .= ")";
241 $sql .= " VALUES (";
242 $sql .= " '" . $this->db->escape($this->ref) . "'";
243 $sql .= ", '" . $this->db->escape($this->ref_ext) . "'";
244 $sql .= ", '" . $this->db->escape($this->label) . "'";
245 $sql .= ", " . ((int) $this->entity);
246 $sql .= ", " . ((int) $this->position);
247 $sql .= ")";
248
249 dol_syslog(__METHOD__, LOG_DEBUG);
250 $resql = $this->db->query($sql);
251 if (!$resql) {
252 $this->errors[] = "Error " . $this->db->lasterror();
253 $error++;
254 }
255
256 if (!$error) {
257 $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX . $this->table_element);
258 $result = $this->insertExtraFields();
259 if ($result < 0) {
260 $error++;
261 }
262 }
263
264 if (!$error && !$notrigger) {
265 // Call trigger
266 $result = $this->call_trigger('PRODUCT_ATTRIBUTE_CREATE', $user);
267 if ($result < 0) {
268 $error++;
269 }
270 // End call triggers
271 }
272
273 if (!$error) {
274 $this->db->commit();
275 return $this->id;
276 } else {
277 $this->db->rollback();
278 return -1 * $error;
279 }
280 }
281
288 public function fetch($id)
289 {
290 global $langs;
291 $error = 0;
292
293 // Clean parameters
294 $id = $id > 0 ? $id : 0;
295
296 // Check parameters
297 if (empty($id)) {
298 $this->errors[] = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("TechnicalID"));
299 $error++;
300 }
301 if ($error) {
302 dol_syslog(__METHOD__ . ' ' . $this->errorsToString(), LOG_ERR);
303 return -1;
304 }
305
306 $sql = "SELECT rowid, ref, ref_ext, label, position";
307 $sql .= " FROM " . MAIN_DB_PREFIX . $this->table_element;
308 $sql .= " WHERE rowid = " . ((int) $id);
309 $sql .= " AND entity IN (" . getEntity('product') . ")";
310
311 dol_syslog(__METHOD__, LOG_DEBUG);
312 $resql = $this->db->query($sql);
313 if (!$resql) {
314 $this->errors[] = "Error " . $this->db->lasterror();
315 dol_syslog(__METHOD__ . ' ' . $this->errorsToString(), LOG_ERR);
316 return -1;
317 }
318
319 $numrows = $this->db->num_rows($resql);
320 if ($numrows) {
321 $obj = $this->db->fetch_object($resql);
322
323 $this->id = $obj->rowid;
324 $this->ref = $obj->ref;
325 $this->ref_ext = $obj->ref_ext;
326 $this->label = $obj->label;
327 $this->rang = $obj->position; // deprecated
328 $this->position = $obj->position;
329 $this->fetch_optionals();
330 }
331 $this->db->free($resql);
332
333 return $numrows;
334 }
335
341 public function fetchAll()
342 {
343 $return = array();
344
345 $sql = "SELECT rowid, ref, ref_ext, label, position";
346 $sql .= " FROM " . MAIN_DB_PREFIX . $this->table_element;
347 $sql .= " WHERE entity IN (" . getEntity('product') . ")";
348 $sql .= $this->db->order("position", "asc");
349
350 dol_syslog(__METHOD__, LOG_DEBUG);
351 $resql = $this->db->query($sql);
352 if (!$resql) {
353 $this->errors[] = "Error " . $this->db->lasterror();
354 dol_print_error($this->db);
355 return $return;
356 }
357
358 while ($obj = $this->db->fetch_object($resql)) {
359 $tmp = new ProductAttribute($this->db);
360
361 $tmp->id = $obj->rowid;
362 $tmp->ref = $obj->ref;
363 $tmp->ref_ext = $obj->ref_ext;
364 $tmp->label = $obj->label;
365 $tmp->rang = $obj->position; // deprecated
366 $tmp->position = $obj->position;
367
368 $return[] = $tmp;
369 }
370
371 return $return;
372 }
373
381 public function update(User $user, $notrigger = 0)
382 {
383 global $langs;
384 $error = 0;
385
386 // Clean parameters
387 $this->id = $this->id > 0 ? $this->id : 0;
388 $this->ref = strtoupper(dol_sanitizeFileName(dol_string_nospecial(trim($this->ref)))); // Ref must be uppercase
389 $this->label = trim($this->label);
390
391 // Check parameters
392 if (empty($this->id)) {
393 $this->errors[] = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("TechnicalID"));
394 $error++;
395 }
396 if (empty($this->ref)) {
397 $this->errors[] = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Ref"));
398 $error++;
399 }
400 if (empty($this->label)) {
401 $this->errors[] = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Label"));
402 $error++;
403 }
404 if ($error) {
405 dol_syslog(__METHOD__ . ' ' . $this->errorsToString(), LOG_ERR);
406 return -1;
407 }
408
409 $this->db->begin();
410
411 $sql = "UPDATE " . MAIN_DB_PREFIX . $this->table_element . " SET";
412
413 $sql .= " ref = '" . $this->db->escape($this->ref) . "'";
414 $sql .= ", ref_ext = '" . $this->db->escape($this->ref_ext) . "'";
415 $sql .= ", label = '" . $this->db->escape($this->label) . "'";
416 $sql .= ", position = " . ((int) $this->position);
417
418 $sql .= " WHERE rowid = " . ((int) $this->id);
419
420 dol_syslog(__METHOD__, LOG_DEBUG);
421 $resql = $this->db->query($sql);
422 if (!$resql) {
423 $this->errors[] = "Error " . $this->db->lasterror();
424 $error++;
425 }
426 if (!$error) {
427 $result = $this->insertExtraFields();
428 if ($result < 0) {
429 $error++;
430 }
431 }
432 if (!$error && !$notrigger) {
433 // Call trigger
434 $result = $this->call_trigger('PRODUCT_ATTRIBUTE_MODIFY', $user);
435 if ($result < 0) {
436 $error++;
437 }
438 // End call triggers
439 }
440
441 if (!$error) {
442 $this->db->commit();
443 return 1;
444 } else {
445 $this->db->rollback();
446 return -1 * $error;
447 }
448 }
449
457 public function delete(User $user, $notrigger = 0)
458 {
459 global $langs;
460 $error = 0;
461
462 // Clean parameters
463 $this->id = $this->id > 0 ? $this->id : 0;
464
465 // Check parameters
466 if (empty($this->id)) {
467 $this->errors[] = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("TechnicalID"));
468 $error++;
469 }
470 if ($error) {
471 dol_syslog(__METHOD__ . ' ' . $this->errorsToString(), LOG_ERR);
472 return -1;
473 }
474
475 $result = $this->isUsed();
476 if ($result < 0) {
477 return -1;
478 } elseif ($result > 0) {
479 $this->errors[] = $langs->trans('ErrorAttributeIsUsedIntoProduct');
480 return -1;
481 }
482
483 $this->db->begin();
484
485 if (!$notrigger) {
486 // Call trigger
487 $result = $this->call_trigger('PRODUCT_ATTRIBUTE_DELETE', $user);
488 if ($result < 0) {
489 $error++;
490 }
491 // End call triggers
492 }
493
494 if (!$error) {
495 // Delete values
496 $sql = "DELETE FROM " . MAIN_DB_PREFIX . $this->table_element_line;
497 $sql .= " WHERE " . $this->fk_element . " = " . ((int) $this->id);
498
499 dol_syslog(__METHOD__ . ' - Delete values', LOG_DEBUG);
500 $resql = $this->db->query($sql);
501 if (!$resql) {
502 $this->errors[] = "Error " . $this->db->lasterror();
503 $error++;
504 }
505 }
506
507 if (!$error) {
508 $sql = "DELETE FROM " . MAIN_DB_PREFIX . $this->table_element;
509 $sql .= " WHERE rowid = " . ((int) $this->id);
510
511 dol_syslog(__METHOD__ . ' - Delete attribute', LOG_DEBUG);
512 $resql = $this->db->query($sql);
513 if (!$resql) {
514 $this->errors[] = "Error " . $this->db->lasterror();
515 $error++;
516 }
517 }
518
519 if (!$error) {
520 $this->db->commit();
521 return 1;
522 } else {
523 $this->db->rollback();
524 return -1 * $error;
525 }
526 }
527
528 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
535 public function fetch_lines($filters = '')
536 {
537 // phpcs:enable
538 global $langs;
539
540 $this->lines = array();
541
542 $error = 0;
543
544 // Clean parameters
545 $this->id = $this->id > 0 ? $this->id : 0;
546
547 // Check parameters
548 if (empty($this->id)) {
549 $this->errors[] = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("TechnicalID"));
550 $error++;
551 }
552 if ($error) {
553 dol_syslog(__METHOD__ . ' ' . $this->errorsToString(), LOG_ERR);
554 return -1;
555 }
556
557 $sql = "SELECT td.rowid, td.fk_product_attribute, td.ref, td.value, td.position";
558 $sql .= " FROM " . MAIN_DB_PREFIX . $this->table_element_line . " AS td";
559 $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . $this->table_element . " AS t ON t.rowid = td." . $this->fk_element;
560 $sql .= " WHERE t.rowid = " . ((int) $this->id);
561 $sql .= " AND t.entity IN (" . getEntity('product') . ")";
562 if ($filters) {
563 $sql .= $filters;
564 }
565 $sql .= $this->db->order("td.position", "asc");
566
567 dol_syslog(__METHOD__, LOG_DEBUG);
568 $resql = $this->db->query($sql);
569 if (!$resql) {
570 $this->errors[] = "Error " . $this->db->lasterror();
571 dol_syslog(__METHOD__ . ' ' . $this->errorsToString(), LOG_ERR);
572 return -3;
573 }
574
575 $num = $this->db->num_rows($resql);
576 if ($num) {
577 $i = 0;
578 while ($i < $num) {
579 $obj = $this->db->fetch_object($resql);
580
581 $line = new ProductAttributeValue($this->db);
582
583 $line->id = $obj->rowid;
584 $line->fk_product_attribute = $obj->fk_product_attribute;
585 $line->ref = $obj->ref;
586 $line->value = $obj->value;
587 $line->position = $obj->position;
588 $line->fetch_optionals();
589
590 $this->lines[$i] = $line;
591 $i++;
592 }
593 }
594 $this->db->free($resql);
595
596 return $num;
597 }
598
605 public function getLinesArray($filters = '')
606 {
607 return $this->fetch_lines($filters);
608 }
609
623 public function addLine($ref, $value, $position = -1, $notrigger = 0)
624 {
625 global $langs, $user;
626 dol_syslog(__METHOD__ . " id=".$this->id.", ref=".$ref.", value=".$value.", notrigger=".$notrigger);
627 $error = 0;
628
629 // Clean parameters
630 $this->id = $this->id > 0 ? $this->id : 0;
631
632 // Check parameters
633 if (empty($this->id)) {
634 $this->errors[] = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("TechnicalID"));
635 $error++;
636 }
637 if ($error) {
638 dol_syslog(__METHOD__ . ' ' . $this->errorsToString(), LOG_ERR);
639 return -1;
640 }
641
642 $this->db->begin();
643
644 // Fetch current line from the database and then clone the object and set it in $oldcopy property
645 $this->line = new ProductAttributeValue($this->db);
646
647 // Position to use
648 $positiontouse = $position;
649 if ($positiontouse == -1) {
650 $positionmax = $this->line_max(0);
651 $positiontouse = $positionmax + 1;
652 }
653
654 $this->line->context = $this->context;
655 $this->line->fk_product_attribute = $this->id;
656 $this->line->ref = $ref;
657 $this->line->value = $value;
658 $this->line->position = $positiontouse;
659
660 $result = $this->line->create($user, $notrigger);
661
662 if ($result < 0) {
663 $this->error = $this->line->error;
664 $this->errors = $this->line->errors;
665 $this->db->rollback();
666 return -1;
667 } else {
668 $this->db->commit();
669 return $this->line->id;
670 }
671 }
672
673
683 public function updateLine($lineid, $ref, $value, $notrigger = 0)
684 {
685 global $user;
686
687 dol_syslog(__METHOD__ . " lineid=$lineid, ref=$ref, value=$value, notrigger=$notrigger");
688
689 // Clean parameters
690 $lineid = $lineid > 0 ? $lineid : 0;
691
692 $this->db->begin();
693
694 // Fetch current line from the database and then clone the object and set it in $oldcopy property
695 $this->line = new ProductAttributeValue($this->db);
696 $result = $this->line->fetch($lineid);
697 if ($result > 0) {
698 $this->line->oldcopy = clone $this->line;
699
700 $this->line->context = $this->context;
701 $this->line->ref = $ref;
702 $this->line->value = $value;
703
704 $result = $this->line->update($user, $notrigger);
705 }
706
707 if ($result < 0) {
708 $this->error = $this->line->error;
709 $this->errors = $this->line->errors;
710 $this->db->rollback();
711 return -1;
712 } else {
713 $this->db->commit();
714 return $result;
715 }
716 }
717
726 public function deleteLine(User $user, $lineid, $notrigger = 0)
727 {
728 dol_syslog(__METHOD__ . " lineid=$lineid, notrigger=$notrigger");
729
730 // Clean parameters
731 $lineid = $lineid > 0 ? $lineid : 0;
732
733 $this->db->begin();
734
735 // Fetch current line from the database
736 $this->line = new ProductAttributeValue($this->db);
737 $result = $this->line->fetch($lineid);
738 if ($result > 0) {
739 $this->line->context = $this->context;
740
741 $result = $this->line->delete($user, $notrigger);
742 }
743
744 if ($result < 0) {
745 $this->error = $this->line->error;
746 $this->errors = $this->line->errors;
747 $this->db->rollback();
748 return -1;
749 } else {
750 $this->db->commit();
751 return $result;
752 }
753 }
754
760 public function countChildValues()
761 {
762 global $langs;
763 $error = 0;
764 $count = 0;
765
766 // Clean parameters
767 $this->id = $this->id > 0 ? $this->id : 0;
768
769 // Check parameters
770 if (empty($this->id)) {
771 $this->errors[] = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("TechnicalID"));
772 $error++;
773 }
774 if ($error) {
775 dol_syslog(__METHOD__ . ' ' . $this->errorsToString(), LOG_ERR);
776 return -1;
777 }
778
779 $sql = "SELECT COUNT(*) AS count";
780 $sql .= " FROM " . MAIN_DB_PREFIX . $this->table_element_line;
781 $sql .= " WHERE " . $this->fk_element . " = " . ((int) $this->id);
782
783 dol_syslog(__METHOD__, LOG_DEBUG);
784 $resql = $this->db->query($sql);
785 if (!$resql) {
786 $this->errors[] = "Error " . $this->db->lasterror();
787 dol_syslog(__METHOD__ . ' ' . $this->errorsToString(), LOG_ERR);
788 return -1;
789 }
790
791 if ($obj = $this->db->fetch_object($resql)) {
792 $count = $obj->count;
793 }
794
795 return $count;
796 }
797
803 public function countChildProducts()
804 {
805 global $langs;
806 $error = 0;
807 $count = 0;
808
809 // Clean parameters
810 $this->id = ($this->id > 0) ? $this->id : 0;
811
812 // Check parameters
813 if (empty($this->id)) {
814 $this->errors[] = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("TechnicalID"));
815 $error++;
816 }
817 if ($error) {
818 dol_syslog(__METHOD__ . ' ' . $this->errorsToString(), LOG_ERR);
819 return -1;
820 }
821
822 $sql = "SELECT COUNT(*) AS count";
823 $sql .= " FROM " . MAIN_DB_PREFIX . "product_attribute_combination2val AS pac2v";
824 $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "product_attribute_combination AS pac ON pac2v.fk_prod_combination = pac.rowid";
825 $sql .= " WHERE pac2v.fk_prod_attr = " . ((int) $this->id);
826 $sql .= " AND pac.entity IN (" . getEntity('product') . ")";
827
828 dol_syslog(__METHOD__, LOG_DEBUG);
829 $resql = $this->db->query($sql);
830 if (!$resql) {
831 $this->errors[] = "Error " . $this->db->lasterror();
832 dol_syslog(__METHOD__ . ' ' . $this->errorsToString(), LOG_ERR);
833 return -1;
834 }
835
836 if ($obj = $this->db->fetch_object($resql)) {
837 $count = $obj->count;
838 }
839
840 return $count;
841 }
842
848 public function isUsed()
849 {
850 global $langs;
851 $error = 0;
852
853 // Clean parameters
854 $this->id = $this->id > 0 ? $this->id : 0;
855
856 // Check parameters
857 if (empty($this->id)) {
858 $this->errors[] = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("TechnicalID"));
859 $error++;
860 }
861 if ($error) {
862 dol_syslog(__METHOD__ . ' ' . $this->errorsToString(), LOG_ERR);
863 return -1;
864 }
865
866 $sql = "SELECT COUNT(*) AS nb FROM " . MAIN_DB_PREFIX . "product_attribute_combination2val WHERE fk_prod_attr = " . ((int) $this->id);
867
868 dol_syslog(__METHOD__, LOG_DEBUG);
869 $resql = $this->db->query($sql);
870 if (!$resql) {
871 $this->errors[] = "Error " . $this->db->lasterror();
872 return -1;
873 }
874
875 $used = 0;
876 if ($obj = $this->db->fetch_object($resql)) {
877 $used = $obj->nb;
878 }
879
880 return $used ? 1 : 0;
881 }
882
891 public function attributeOrder($renum = false, $rowidorder = 'ASC')
892 {
893 // Count number of attributes to reorder (according to choice $renum)
894 $nl = 0;
895 $sql = "SELECT count(rowid) FROM " . MAIN_DB_PREFIX . $this->table_element;
896 $sql .= " WHERE entity IN (" . getEntity('product') . ")";
897 if (!$renum) {
898 $sql .= " AND position = 0";
899 } else {
900 $sql .= " AND position <> 0";
901 }
902
903 dol_syslog(__METHOD__, LOG_DEBUG);
904 $resql = $this->db->query($sql);
905 if ($resql) {
906 $row = $this->db->fetch_row($resql);
907 $nl = $row[0];
908 } else {
909 dol_print_error($this->db);
910 }
911 if ($nl > 0) {
912 // The goal of this part is to reorder all attributes.
913 $rows = array();
914
915 // We first search all attributes
916 $sql = "SELECT rowid FROM " . MAIN_DB_PREFIX . $this->table_element;
917 $sql .= " WHERE entity IN (" . getEntity('product') . ")";
918 $sql .= " ORDER BY position ASC, rowid " . $rowidorder;
919
920 dol_syslog(__METHOD__ . " search all attributes", LOG_DEBUG);
921 $resql = $this->db->query($sql);
922 if ($resql) {
923 $i = 0;
924 $num = $this->db->num_rows($resql);
925 while ($i < $num) {
926 $row = $this->db->fetch_row($resql);
927 $rows[] = $row[0]; // Add attributes into array rows
928 $i++;
929 }
930
931 // Now we set a new number for each attributes
932 if (!empty($rows)) {
933 foreach ($rows as $key => $row) {
934 $this->updatePositionOfAttribute($row, ($key + 1));
935 }
936 }
937 } else {
938 dol_print_error($this->db);
939 }
940 }
941 return 1;
942 }
943
951 public function updatePositionOfAttribute($rowid, $position)
952 {
953 global $hookmanager;
954
955 $sql = "UPDATE " . MAIN_DB_PREFIX . $this->table_element . " SET position = " . ((int) $position);
956 $sql .= " WHERE rowid = " . ((int) $rowid);
957
958 dol_syslog(__METHOD__, LOG_DEBUG);
959 if (!$this->db->query($sql)) {
960 dol_print_error($this->db);
961 return -1;
962 } else {
963 $parameters = array('rowid' => $rowid, 'position' => $position);
964 $action = '';
965 $reshook = $hookmanager->executeHooks('afterPositionOfAttributeUpdate', $parameters, $this, $action);
966 return ($reshook >= 0 ? 1 : -1);
967 }
968 }
969
976 public function getPositionOfAttribute($rowid)
977 {
978 $sql = "SELECT position FROM " . MAIN_DB_PREFIX . $this->table_element;
979 $sql .= " WHERE entity IN (" . getEntity('product') . ")";
980
981 dol_syslog(__METHOD__, LOG_DEBUG);
982 $resql = $this->db->query($sql);
983 if ($resql) {
984 $row = $this->db->fetch_row($resql);
985 return $row[0];
986 }
987
988 return 0;
989 }
990
997 public function attributeMoveUp($rowid)
998 {
999 $this->attributeOrder(false, 'ASC');
1000
1001 // Get position of attribute
1002 $position = $this->getPositionOfAttribute($rowid);
1003
1004 // Update position of attribute
1005 $this->updateAttributePositionUp($rowid, $position);
1006
1007 return 1;
1008 }
1009
1016 public function attributeMoveDown($rowid)
1017 {
1018 $this->attributeOrder(false, 'ASC');
1019
1020 // Get position of line
1021 $position = $this->getPositionOfAttribute($rowid);
1022
1023 // Get max value for position
1024 $max = $this->getMaxAttributesPosition();
1025
1026 // Update position of attribute
1027 $this->updateAttributePositionDown($rowid, $position, $max);
1028
1029 return 1;
1030 }
1031
1039 public function updateAttributePositionUp($rowid, $position)
1040 {
1041 if ($position > 1) {
1042 $sql = "UPDATE " . MAIN_DB_PREFIX . $this->table_element . " SET position = " . ((int) $position);
1043 $sql .= " WHERE entity IN (" . getEntity('product') . ")";
1044 $sql .= " AND position = " . ((int) ($position - 1));
1045 if ($this->db->query($sql)) {
1046 $sql = "UPDATE " . MAIN_DB_PREFIX . $this->table_element . " SET position = " . ((int) ($position - 1));
1047 $sql .= " WHERE rowid = " . ((int) $rowid);
1048 if (!$this->db->query($sql)) {
1049 dol_print_error($this->db);
1050 }
1051 } else {
1052 dol_print_error($this->db);
1053 }
1054 }
1055 }
1056
1065 public function updateAttributePositionDown($rowid, $position, $max)
1066 {
1067 if ($position < $max) {
1068 $sql = "UPDATE " . MAIN_DB_PREFIX . $this->table_element . " SET position = " . ((int) $position);
1069 $sql .= " WHERE entity IN (" . getEntity('product') . ")";
1070 $sql .= " AND position = " . ((int) ($position + 1));
1071 if ($this->db->query($sql)) {
1072 $sql = "UPDATE " . MAIN_DB_PREFIX . $this->table_element . " SET position = " . ((int) ($position + 1));
1073 $sql .= " WHERE rowid = " . ((int) $rowid);
1074 if (!$this->db->query($sql)) {
1075 dol_print_error($this->db);
1076 }
1077 } else {
1078 dol_print_error($this->db);
1079 }
1080 }
1081 }
1082
1089 {
1090 // Search the last position of attributes
1091 $sql = "SELECT max(position) FROM " . MAIN_DB_PREFIX . $this->table_element;
1092 $sql .= " WHERE entity IN (" . getEntity('product') . ")";
1093
1094 dol_syslog(__METHOD__, LOG_DEBUG);
1095 $resql = $this->db->query($sql);
1096 if ($resql) {
1097 $row = $this->db->fetch_row($resql);
1098 return $row[0];
1099 }
1100
1101 return 0;
1102 }
1103
1110 public function attributesAjaxOrder($rows)
1111 {
1112 $num = count($rows);
1113 for ($i = 0; $i < $num; $i++) {
1114 $this->updatePositionOfAttribute($rows[$i], ($i + 1));
1115 }
1116 }
1117
1128 public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1)
1129 {
1130 global $conf, $langs, $hookmanager;
1131
1132 if (!empty($conf->dol_no_mouse_hover)) {
1133 $notooltip = 1; // Force disable tooltips
1134 }
1135
1136 $result = '';
1137
1138 $label = img_picto('', $this->picto) . ' <u>' . $langs->trans("ProductAttribute") . '</u>';
1139 if (isset($this->status)) {
1140 $label .= ' ' . $this->getLibStatut(5);
1141 }
1142 $label .= '<br>';
1143 $label .= '<b>' . $langs->trans('Ref') . ':</b> ' . $this->ref;
1144 if (!empty($this->label)) {
1145 $label .= '<br><b>' . $langs->trans('Label') . ':</b> ' . $this->label;
1146 }
1147
1148 $url = dol_buildpath('/variants/card.php', 1) . '?id=' . $this->id;
1149
1150 if ($option != 'nolink') {
1151 // Add param to save lastsearch_values or not
1152 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
1153 if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
1154 $add_save_lastsearch_values = 1;
1155 }
1156 if ($url && $add_save_lastsearch_values) {
1157 $url .= '&save_lastsearch_values=1';
1158 }
1159 }
1160
1161 $linkclose = '';
1162 if (empty($notooltip)) {
1163 if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
1164 $label = $langs->trans("ShowProductAttribute");
1165 $linkclose .= ' alt="' . dol_escape_htmltag($label, 1) . '"';
1166 }
1167 $linkclose .= ' title="' . dol_escape_htmltag($label, 1) . '"';
1168 $linkclose .= ' class="classfortooltip' . ($morecss ? ' ' . $morecss : '') . '"';
1169 } else {
1170 $linkclose = ($morecss ? ' class="' . $morecss . '"' : '');
1171 }
1172
1173 if ($option == 'nolink' || empty($url)) {
1174 $linkstart = '<span';
1175 } else {
1176 $linkstart = '<a href="' . $url . '"';
1177 }
1178 $linkstart .= $linkclose . '>';
1179 if ($option == 'nolink' || empty($url)) {
1180 $linkend = '</span>';
1181 } else {
1182 $linkend = '</a>';
1183 }
1184
1185 $result .= $linkstart;
1186
1187 if (empty($this->showphoto_on_popup)) {
1188 if ($withpicto) {
1189 $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="' . (($withpicto != 2) ? 'paddingright ' : '') . 'classfortooltip"'), 0, 0, $notooltip ? 0 : 1);
1190 }
1191 } else {
1192 if ($withpicto) {
1193 require_once DOL_DOCUMENT_ROOT . '/core/lib/files.lib.php';
1194
1195 list($class, $module) = explode('@', $this->picto);
1196 $upload_dir = $conf->$module->multidir_output[$conf->entity] . "/$class/" . dol_sanitizeFileName($this->ref);
1197 $filearray = dol_dir_list($upload_dir, "files");
1198 $filename = $filearray[0]['name'];
1199 if (!empty($filename)) {
1200 $pospoint = strpos($filearray[0]['name'], '.');
1201
1202 $pathtophoto = $class . '/' . $this->ref . '/thumbs/' . substr($filename, 0, $pospoint) . '_mini' . substr($filename, $pospoint);
1203 if (!getDolGlobalString(strtoupper($module . '_' . $class) . '_FORMATLISTPHOTOSASUSERS')) {
1204 $result .= '<div class="floatleft inline-block valignmiddle divphotoref"><div class="photoref"><img class="photo' . $module . '" alt="No photo" border="0" src="' . DOL_URL_ROOT . '/viewimage.php?modulepart=' . $module . '&entity=' . $conf->entity . '&file=' . urlencode($pathtophoto) . '"></div></div>';
1205 } else {
1206 $result .= '<div class="floatleft inline-block valignmiddle divphotoref"><img class="photouserphoto userphoto" alt="No photo" border="0" src="' . DOL_URL_ROOT . '/viewimage.php?modulepart=' . $module . '&entity=' . $conf->entity . '&file=' . urlencode($pathtophoto) . '"></div>';
1207 }
1208
1209 $result .= '</div>';
1210 } else {
1211 $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="' . (($withpicto != 2) ? 'paddingright ' : '') . 'classfortooltip"'), 0, 0, $notooltip ? 0 : 1);
1212 }
1213 }
1214 }
1215
1216 if ($withpicto != 2) {
1217 $result .= $this->ref;
1218 }
1219
1220 $result .= $linkend;
1221 //if ($withpicto != 2) $result.=(($addlabel && $this->label) ? $sep . dol_trunc($this->label, ($addlabel > 1 ? $addlabel : 0)) : '');
1222
1223 global $action, $hookmanager;
1224 $hookmanager->initHooks(array('variantsdao'));
1225 $parameters = array('id' => $this->id, 'getnomurl' => $result);
1226 $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
1227 if ($reshook > 0) {
1228 $result = $hookmanager->resPrint;
1229 } else {
1230 $result .= $hookmanager->resPrint;
1231 }
1232
1233 return $result;
1234 }
1235
1243 public function getKanbanView($option = '', $arraydata = null)
1244 {
1245 $selected = (empty($arraydata['selected']) ? 0 : $arraydata['selected']);
1246
1247 $return = '<div class="box-flex-item box-flex-grow-zero">';
1248 $return .= '<div class="info-box info-box-sm">';
1249 $return .= '<span class="info-box-icon bg-infobox-action">';
1250 $return .= img_picto('', $this->picto);
1251 $return .= '</span>';
1252 $return .= '<div class="info-box-content">';
1253 $return .= '<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">'.(method_exists($this, 'getNomUrl') ? $this->getNomUrl() : $this->ref).'</span>';
1254 if ($selected >= 0) {
1255 $return .= '<input id="cb'.$this->id.'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->id.'"'.($selected ? ' checked="checked"' : '').'>';
1256 }
1257 if (property_exists($this, 'label')) {
1258 $return .= ' <div class="inline-block opacitymedium valignmiddle tdoverflowmax100">'.$this->label.'</div>';
1259 }
1260 if (property_exists($this, 'thirdparty') && is_object($this->thirdparty)) {
1261 $return .= '<br><div class="info-box-ref tdoverflowmax150">'.$this->thirdparty->getNomUrl(1).'</div>';
1262 }
1263 if (method_exists($this, 'getLibStatut')) {
1264 $return .= '<br><div class="info-box-status">'.$this->getLibStatut(3).'</div>';
1265 }
1266 $return .= '</div>';
1267 $return .= '</div>';
1268 $return .= '</div>';
1269
1270 return $return;
1271 }
1272
1279 public function getLabelStatus($mode = 0)
1280 {
1281 return $this->LibStatut(0, $mode);
1282 }
1283
1290 public function getLibStatut($mode = 0)
1291 {
1292 return $this->LibStatut(0, $mode);
1293 }
1294
1295 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1303 public function LibStatut($status, $mode = 1)
1304 {
1305 // phpcs:enable
1306 return '';
1307 }
1308
1309 // --------------------
1310 // TODO: All functions here must be redesigned and moved as they are not business functions but output functions
1311 // --------------------
1312
1313 /* This is to show add lines */
1314
1324 public function formAddObjectLine($dateSelector, $seller, $buyer, $defaulttpldir = '/variants/tpl')
1325 {
1326 global $conf, $user, $langs, $object, $hookmanager;
1327 global $form;
1328
1329 // Output template part (modules that overwrite templates must declare this into descriptor)
1330 // Use global variables + $dateSelector + $seller and $buyer
1331 // Note: This is deprecated. If you need to overwrite the tpl file, use instead the hook 'formAddObjectLine'.
1332 $dirtpls = array_merge($conf->modules_parts['tpl'], array($defaulttpldir));
1333 foreach ($dirtpls as $module => $reldir) {
1334 if (!empty($module)) {
1335 $tpl = dol_buildpath($reldir . '/productattributevalueline_create.tpl.php');
1336 } else {
1337 $tpl = DOL_DOCUMENT_ROOT . $reldir . '/productattributevalueline_create.tpl.php';
1338 }
1339
1340 if (empty($conf->file->strict_mode)) {
1341 $res = @include $tpl;
1342 } else {
1343 $res = include $tpl; // for debug
1344 }
1345 if ($res) {
1346 break;
1347 }
1348 }
1349 }
1350
1351 /* This is to show array of line of details */
1352
1368 public function printObjectLines($action, $seller, $buyer, $selected = 0, $dateSelector = 0, $defaulttpldir = '/variants/tpl', $addcreateline = 0)
1369 {
1370 global $conf, $hookmanager, $langs, $user, $form, $object;
1371 global $mysoc;
1372 // TODO We should not use global var for this
1373 global $disableedit, $disablemove, $disableremove;
1374
1375 $num = count($this->lines);
1376
1377 $parameters = array('num' => $num, 'selected' => $selected, 'table_element_line' => $this->table_element_line);
1378 $reshook = $hookmanager->executeHooks('printObjectLineTitle', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
1379 if (empty($reshook)) {
1380 // Output template part (modules that overwrite templates must declare this into descriptor)
1381 // Use global variables + $dateSelector + $seller and $buyer
1382 // Note: This is deprecated. If you need to overwrite the tpl file, use instead the hook.
1383 $dirtpls = array_merge($conf->modules_parts['tpl'], array($defaulttpldir));
1384 foreach ($dirtpls as $module => $reldir) {
1385 if (!empty($module)) {
1386 $tpl = dol_buildpath($reldir . '/productattributevalueline_title.tpl.php');
1387 } else {
1388 $tpl = DOL_DOCUMENT_ROOT . $reldir . '/productattributevalueline_title.tpl.php';
1389 }
1390 if (empty($conf->file->strict_mode)) {
1391 $res = @include $tpl;
1392 } else {
1393 $res = include $tpl; // for debug
1394 }
1395 if ($res) {
1396 break;
1397 }
1398 }
1399 }
1400
1401
1402 if ($addcreateline) {
1403 // Form to add new line
1404 if ($action != 'selectlines') {
1405 if ($action != 'editline') {
1406 // Add products/services form
1407
1408 $parameters = array();
1409 $reshook = $hookmanager->executeHooks('formAddObjectLine', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1410 if ($reshook < 0) {
1411 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
1412 }
1413 if (empty($reshook)) {
1414 $object->formAddObjectLine(1, $mysoc, $buyer);
1415 }
1416 }
1417 }
1418 }
1419
1420 $i = 0;
1421
1422 print "<!-- begin printObjectLines() -->\n";
1423 foreach ($this->lines as $line) {
1424 if (is_object($hookmanager)) { // Old code is commented on preceding line.
1425 $parameters = array('line' => $line, 'num' => $num, 'i' => $i, 'selected' => $selected, 'table_element_line' => $line->table_element);
1426 $reshook = $hookmanager->executeHooks('printObjectLine', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
1427 }
1428 if (empty($reshook)) {
1429 $this->printObjectLine($action, $line, '', $num, $i, $dateSelector, $seller, $buyer, $selected, null, $defaulttpldir);
1430 }
1431
1432 $i++;
1433 }
1434 print "<!-- end printObjectLines() -->\n";
1435 }
1436
1454 public function printObjectLine($action, $line, $var, $num, $i, $dateSelector, $seller, $buyer, $selected = 0, $extrafields = null, $defaulttpldir = '/variants/tpl')
1455 {
1456 global $conf, $langs, $user, $object, $hookmanager;
1457 global $form;
1458 global $disableedit, $disablemove, $disableremove; // TODO We should not use global var for this !
1459
1460 // Line in view mode
1461 if ($action != 'editline' || $selected != $line->id) {
1462 // Output template part (modules that overwrite templates must declare this into descriptor)
1463 // Use global variables + $dateSelector + $seller and $buyer
1464 // Note: This is deprecated. If you need to overwrite the tpl file, use instead the hook printObjectLine and printObjectSubLine.
1465 $dirtpls = array_merge($conf->modules_parts['tpl'], array($defaulttpldir));
1466 foreach ($dirtpls as $module => $reldir) {
1467 if (!empty($module)) {
1468 $tpl = dol_buildpath($reldir . '/productattributevalueline_view.tpl.php');
1469 } else {
1470 $tpl = DOL_DOCUMENT_ROOT . $reldir . '/productattributevalueline_view.tpl.php';
1471 }
1472
1473 if (empty($conf->file->strict_mode)) {
1474 $res = @include $tpl;
1475 } else {
1476 $res = include $tpl; // for debug
1477 }
1478 if ($res) {
1479 break;
1480 }
1481 }
1482 }
1483
1484 // Line in update mode
1485 if ($action == 'editline' && $selected == $line->id) {
1486 // Output template part (modules that overwrite templates must declare this into descriptor)
1487 // Use global variables + $dateSelector + $seller and $buyer
1488 // Note: This is deprecated. If you need to overwrite the tpl file, use instead the hook printObjectLine and printObjectSubLine.
1489 $dirtpls = array_merge($conf->modules_parts['tpl'], array($defaulttpldir));
1490 foreach ($dirtpls as $module => $reldir) {
1491 if (!empty($module)) {
1492 $tpl = dol_buildpath($reldir . '/productattributevalueline_edit.tpl.php');
1493 } else {
1494 $tpl = DOL_DOCUMENT_ROOT . $reldir . '/productattributevalueline_edit.tpl.php';
1495 }
1496
1497 if (empty($conf->file->strict_mode)) {
1498 $res = @include $tpl;
1499 } else {
1500 $res = include $tpl; // for debug
1501 }
1502 if ($res) {
1503 break;
1504 }
1505 }
1506 }
1507 }
1508
1509 /* This is to show array of line of details of source object */
1510}
if( $user->socid > 0) if(! $user->hasRight('accounting', 'chartofaccount')) $object
Definition card.php:58
print $object position
Definition edit.php:195
$object ref
Definition info.php:79
Parent class of all other business classes (invoices, contracts, proposals, orders,...
fetch_optionals($rowid=null, $optionsArray=null)
Function to get extra fields of an object into $this->array_options This method is in most cases call...
errorsToString()
Method to output saved errors.
line_max($fk_parent_line=0)
Get max value used for position of line (rang)
insertExtraFields($trigger='', $userused=null)
Add/Update all extra fields values for the current object.
call_trigger($triggerName, $user)
Call trigger based on this instance.
Class to manage Dolibarr database access.
Class ProductAttribute Used to represent a Product attribute Examples:
updateAttributePositionDown($rowid, $position, $max)
Update position of attribute (down)
updatePositionOfAttribute($rowid, $position)
Update position of line (rang)
addLine($ref, $value, $position=-1, $notrigger=0)
getKanbanView($option='', $arraydata=null)
Return a thumb for kanban views.
attributeMoveDown($rowid)
Update a attribute to have a lower position.
fetch($id)
Fetches the properties of a product attribute.
update(User $user, $notrigger=0)
Updates a product attribute.
attributeOrder($renum=false, $rowidorder='ASC')
Save a new position (field position) for details lines.
fetchAll()
Returns an array with all the ProductAttribute objects of a given entity.
updateAttributePositionUp($rowid, $position)
Update position of attribute (up)
isUsed()
Test if this attribute is used by a Product.
updateLine($lineid, $ref, $value, $notrigger=0)
Update a line.
__construct(DoliDB $db)
Constructor.
getMaxAttributesPosition()
Get max value used for position of attributes.
LibStatut($status, $mode=1)
Return label of a status.
attributesAjaxOrder($rows)
Update position of attributes with ajax.
getLinesArray($filters='')
Retrieve an array of proposal lines.
fetch_lines($filters='')
Load array lines.
attributeMoveUp($rowid)
Update a attribute to have a higher position.
create(User $user, $notrigger=0)
Creates a product attribute.
countChildProducts()
Return the number of product variants using this attribute.
deleteLine(User $user, $lineid, $notrigger=0)
Delete a line.
formAddObjectLine($dateSelector, $seller, $buyer, $defaulttpldir='/variants/tpl')
Show add free and predefined products/services form.
getNomUrl($withpicto=0, $option='', $notooltip=0, $morecss='', $save_lastsearch_value=-1)
Return a link to the object card (with optionally the picto)
getLibStatut($mode=0)
Return label of status of product attribute.
getPositionOfAttribute($rowid)
Get position of attribute.
printObjectLine($action, $line, $var, $num, $i, $dateSelector, $seller, $buyer, $selected=0, $extrafields=null, $defaulttpldir='/variants/tpl')
Return HTML content of a detail line TODO Move this into an output class file (htmlline....
printObjectLines($action, $seller, $buyer, $selected=0, $dateSelector=0, $defaulttpldir='/variants/tpl', $addcreateline=0)
Return HTML table for object lines TODO Move this into an output class file (htmlline....
getLabelStatus($mode=0)
Return the label of the status.
countChildValues()
Returns the number of values for this attribute.
Class ProductAttributeValue Used to represent a product attribute value.
Class to manage Dolibarr users.
print $langs trans("Ref").' m titre as m m statut as status
Or an array listing all the potential status of the object: array: int of the status => translated la...
Definition index.php:162
dol_dir_list($utf8_path, $types="all", $recursive=0, $filter="", $excludefilter=null, $sortcriteria="name", $sortorder=SORT_ASC, $mode=0, $nohook=0, $relativename="", $donotfollowsymlinks=0, $nbsecondsold=0)
Scan a directory and return a list of files/directories.
Definition files.lib.php:63
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0)
Show a picto called object_picto (generic function)
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0, $attop=0)
Set event messages in dol_events session object.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
dol_string_nospecial($str, $newstr='_', $badcharstoreplace='', $badcharstoremove='', $keepspaces=0)
Clean a string from all punctuation characters to use it as a ref or login.
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1)
Clean a string to use it as a file name.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
getEntity($element, $shared=1, $currentobject=null)
Get list of entity id to use.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...