dolibarr 21.0.0-beta
categorie.class.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2005 Matthieu Valleton <mv@seeschloss.org>
3 * Copyright (C) 2005 Davoleau Brice <brice.davoleau@gmail.com>
4 * Copyright (C) 2005 Rodolphe Quiedeville <rodolphe@quiedeville.org>
5 * Copyright (C) 2006-2012 Regis Houssin <regis.houssin@inodbox.com>
6 * Copyright (C) 2006-2012 Laurent Destailleur <eldy@users.sourceforge.net>
7 * Copyright (C) 2007 Patrick Raguin <patrick.raguin@gmail.com>
8 * Copyright (C) 2013-2016 Juanjo Menent <jmenent@2byte.es>
9 * Copyright (C) 2013-2018 Philippe Grand <philippe.grand@atoo-net.com>
10 * Copyright (C) 2015 Marcos García <marcosgdf@gmail.com>
11 * Copyright (C) 2015 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr>
12 * Copyright (C) 2016-2024 Charlene Benke <charlene@patas-monkey.com>
13 * Copyright (C) 2018-2024 Frédéric France <frederic.france@free.fr>
14 * Copyright (C) 2023-2024 Benjamin Falière <benjamin.faliere@altairis.fr>
15 * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
16 *
17 * This program is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation; either version 3 of the License, or
20 * (at your option) any later version.
21 *
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * You should have received a copy of the GNU General Public License
28 * along with this program. If not, see <https://www.gnu.org/licenses/>.
29 */
30
37require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
38require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
39require_once DOL_DOCUMENT_ROOT.'/ticket/class/ticket.class.php';
40require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.class.php';
41require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php';
42require_once DOL_DOCUMENT_ROOT.'/knowledgemanagement/class/knowledgerecord.class.php';
43
44
49{
50 // Categories types (we use string because we want to accept any modules/types in a future)
51 const TYPE_PRODUCT = 'product';
52 const TYPE_SUPPLIER = 'supplier';
53 const TYPE_CUSTOMER = 'customer';
54 const TYPE_MEMBER = 'member';
55 const TYPE_CONTACT = 'contact';
56 const TYPE_USER = 'user';
57 const TYPE_PROJECT = 'project';
58 const TYPE_ACCOUNT = 'bank_account';
59 const TYPE_BANK_LINE = 'bank_line';
60 const TYPE_WAREHOUSE = 'warehouse';
61 const TYPE_ACTIONCOMM = 'actioncomm';
62 const TYPE_WEBSITE_PAGE = 'website_page';
63 const TYPE_TICKET = 'ticket';
64 const TYPE_KNOWLEDGEMANAGEMENT = 'knowledgemanagement';
65 const TYPE_FICHINTER = 'fichinter';
66
70 public $picto = 'category';
71
72
76 protected $MAP_ID = array(
77 'product' => 0,
78 'supplier' => 1,
79 'customer' => 2,
80 'member' => 3,
81 'contact' => 4,
82 'bank_account' => 5,
83 'project' => 6,
84 'user' => 7,
85 'bank_line' => 8,
86 'warehouse' => 9,
87 'actioncomm' => 10,
88 'website_page' => 11,
89 'ticket' => 12,
90 'knowledgemanagement' => 13,
91 'fichinter' => 14,
92 );
93
99 public static $MAP_ID_TO_CODE = array(
100 0 => 'product',
101 1 => 'supplier',
102 2 => 'customer',
103 3 => 'member',
104 4 => 'contact',
105 5 => 'bank_account',
106 6 => 'project',
107 7 => 'user',
108 8 => 'bank_line',
109 9 => 'warehouse',
110 10 => 'actioncomm',
111 11 => 'website_page',
112 12 => 'ticket',
113 13 => 'knowledgemanagement',
114 14 => 'fichinter',
115 );
116
122 public $MAP_CAT_FK = array(
123 'customer' => 'soc',
124 'supplier' => 'soc',
125 'contact' => 'socpeople',
126 'bank_account' => 'account',
127 );
128
134 public $MAP_CAT_TABLE = array(
135 'customer' => 'societe',
136 'supplier' => 'fournisseur',
137 'bank_account' => 'account',
138 );
139
145 public $MAP_OBJ_CLASS = array(
146 'product' => 'Product',
147 'customer' => 'Societe',
148 'supplier' => 'Fournisseur',
149 'member' => 'Adherent',
150 'contact' => 'Contact',
151 'user' => 'User',
152 'account' => 'Account', // old for bank account
153 'bank_account' => 'Account',
154 'project' => 'Project',
155 'warehouse' => 'Entrepot',
156 'actioncomm' => 'ActionComm',
157 'website_page' => 'WebsitePage',
158 'ticket' => 'Ticket',
159 'knowledgemanagement' => 'KnowledgeRecord',
160 'fichinter' => 'Fichinter',
161 );
162
168 public static $MAP_TYPE_TITLE_AREA = array(
169 'product' => 'ProductsCategoriesArea',
170 'customer' => 'CustomersCategoriesArea',
171 'supplier' => 'SuppliersCategoriesArea',
172 'member' => 'MembersCategoriesArea',
173 'contact' => 'ContactsCategoriesArea',
174 'user' => 'UsersCategoriesArea',
175 'account' => 'AccountsCategoriesArea', // old for bank account
176 'bank_account' => 'AccountsCategoriesArea',
177 'project' => 'ProjectsCategoriesArea',
178 'warehouse' => 'StocksCategoriesArea',
179 'actioncomm' => 'ActioncommCategoriesArea',
180 'website_page' => 'WebsitePagesCategoriesArea',
181 'ticket' => 'TicketsCategoriesArea',
182 'knowledgemanagement' => 'KnowledgemanagementsCategoriesArea',
183 'fichinter' => 'FichintersCategoriesArea',
184 );
185
190 public $MAP_OBJ_TABLE = array(
191 'customer' => 'societe',
192 'supplier' => 'societe',
193 'member' => 'adherent',
194 'contact' => 'socpeople',
195 'account' => 'bank_account', // old for bank account
196 'project' => 'projet',
197 'warehouse' => 'entrepot',
198 'knowledgemanagement' => 'knowledgemanagement_knowledgerecord',
199 'fichinter' => 'fichinter',
200 );
201
205 public $element = 'category';
206
210 public $table_element = 'categorie';
211
215 public $fk_parent;
216
220 public $label;
221
225 public $description;
226
230 public $color;
231
235 public $position;
236
240 public $visible;
241
245 public $socid;
246
265 public $type;
266
270 public $cats = array();
271
275 public $motherof = array();
276
280 public $childs = array();
281
285 public $multilangs = array();
286
290 public $imgWidth;
291
295 public $imgHeight;
296
297 public $fields = array(
298 "rowid" => array("type" => "integer", "label" => "TechnicalID", "enabled" => "1", 'position' => 10, 'notnull' => 1, "visible" => "-1",),
299 "fk_parent" => array("type" => "integer", "label" => "Fkparent", "enabled" => "1", 'position' => 20, 'notnull' => 1, "visible" => "-1", "css" => "maxwidth500 widthcentpercentminusxx",),
300 "label" => array("type" => "varchar(180)", "label" => "Label", "enabled" => "1", 'position' => 25, 'notnull' => 1, "visible" => "-1", "alwayseditable" => "1", "css" => "minwidth300", "cssview" => "wordbreak", "csslist" => "tdoverflowmax150",),
301 "ref_ext" => array("type" => "varchar(255)", "label" => "Refext", "enabled" => "1", 'position' => 30, 'notnull' => 0, "visible" => "0", "alwayseditable" => "1",),
302 "type" => array("type" => "integer", "label" => "Type", "enabled" => "1", 'position' => 35, 'notnull' => 1, "visible" => "-1", "alwayseditable" => "1",),
303 "description" => array("type" => "text", "label" => "Description", "enabled" => "1", 'position' => 40, 'notnull' => 0, "visible" => "-1", "alwayseditable" => "1",),
304 "color" => array("type" => "varchar(8)", "label" => "Color", "enabled" => "1", 'position' => 45, 'notnull' => 0, "visible" => "-1", "alwayseditable" => "1",),
305 "position" => array("type" => "integer", "label" => "Position", "enabled" => "1", 'position' => 50, 'notnull' => 0, "visible" => "-1", "alwayseditable" => "1",),
306 "fk_soc" => array("type" => "integer:Societe:societe/class/societe.class.php", "label" => "ThirdParty", "picto" => "company", "enabled" => "1", 'position' => 55, 'notnull' => 0, "visible" => "-1", "alwayseditable" => "1", "css" => "maxwidth500 widthcentpercentminusxx", "csslist" => "tdoverflowmax150",),
307 "visible" => array("type" => "integer", "label" => "Visible", "enabled" => "1", 'position' => 60, 'notnull' => 1, "visible" => "-1", "alwayseditable" => "1",),
308 "import_key" => array("type" => "varchar(14)", "label" => "ImportId", "enabled" => "1", 'position' => 900, 'notnull' => 0, "visible" => "-2", "alwayseditable" => "1",),
309 "date_creation" => array("type" => "datetime", "label" => "Datecreation", "enabled" => "1", 'position' => 70, 'notnull' => 0, "visible" => "-1", "alwayseditable" => "1",),
310 "tms" => array("type" => "timestamp", "label" => "DateModification", "enabled" => "1", 'position' => 75, 'notnull' => 1, "visible" => "-1", "alwayseditable" => "1",),
311 "fk_user_creat" => array("type" => "integer:User:user/class/user.class.php", "label" => "UserAuthor", "enabled" => "1", 'position' => 80, 'notnull' => 0, "visible" => "-2", "alwayseditable" => "1", "css" => "maxwidth500 widthcentpercentminusxx", "csslist" => "tdoverflowmax150",),
312 "fk_user_modif" => array("type" => "integer:User:user/class/user.class.php", "label" => "UserModif", "enabled" => "1", 'position' => 85, 'notnull' => -1, "visible" => "-2", "alwayseditable" => "1", "css" => "maxwidth500 widthcentpercentminusxx", "csslist" => "tdoverflowmax150",),
313 );
314
320 public function __construct($db)
321 {
322 global $hookmanager;
323
324 $this->db = $db;
325
326 if (is_object($hookmanager)) {
327 $hookmanager->initHooks(array('category'));
328 $parameters = array();
329 $reshook = $hookmanager->executeHooks('constructCategory', $parameters, $this); // Note that $action and $object may have been modified by some hooks
330 if ($reshook >= 0 && !empty($hookmanager->resArray)) {
331 foreach ($hookmanager->resArray as $mapList) {
332 $mapId = $mapList['id'];
333 $mapCode = $mapList['code'];
334 self::$MAP_ID_TO_CODE[$mapId] = $mapCode;
335 $this->MAP_ID[$mapCode] = $mapId;
336 $this->MAP_CAT_FK[$mapCode] = isset($mapList['cat_fk']) ? $mapList['cat_fk'] : null;
337 $this->MAP_CAT_TABLE[$mapCode] = isset($mapList['cat_table']) ? $mapList['cat_table'] : null;
338 $this->MAP_OBJ_CLASS[$mapCode] = $mapList['obj_class'];
339 $this->MAP_OBJ_TABLE[$mapCode] = $mapList['obj_table'];
340 }
341 }
342 }
343 }
344
350 public function getMapList()
351 {
352 $mapList = array();
353
354 foreach ($this->MAP_ID as $mapCode => $mapId) {
355 $mapList[] = array(
356 'id' => $mapId,
357 'code' => $mapCode,
358 'cat_fk' => (empty($this->MAP_CAT_FK[$mapCode]) ? $mapCode : $this->MAP_CAT_FK[$mapCode]),
359 'cat_table' => (empty($this->MAP_CAT_TABLE[$mapCode]) ? $mapCode : $this->MAP_CAT_TABLE[$mapCode]),
360 'obj_class' => (empty($this->MAP_OBJ_CLASS[$mapCode]) ? $mapCode : $this->MAP_OBJ_CLASS[$mapCode]),
361 'obj_table' => (empty($this->MAP_OBJ_TABLE[$mapCode]) ? $mapCode : $this->MAP_OBJ_TABLE[$mapCode])
362 );
363 }
364
365 return $mapList;
366 }
367
373 public function getMapId()
374 {
375 return $this->MAP_ID;
376 }
377
387 public function fetch($id, $label = '', $type = null, $ref_ext = '')
388 {
389 // Check parameters
390 if (empty($id) && empty($label) && empty($ref_ext)) {
391 $this->error = "No category to search for";
392 return -1;
393 }
394 if (!is_null($type) && !is_numeric($type)) {
395 $type = $this->MAP_ID[$type];
396 }
397
398 $sql = "SELECT rowid, fk_parent, entity, label, description, color, position, fk_soc, visible, type, ref_ext";
399 $sql .= ", date_creation, tms, fk_user_creat, fk_user_modif";
400 $sql .= " FROM ".MAIN_DB_PREFIX."categorie";
401 if ($id) {
402 $sql .= " WHERE rowid = ".((int) $id);
403 } elseif (!empty($ref_ext)) {
404 $sql .= " WHERE ref_ext LIKE '".$this->db->escape($ref_ext)."'";
405 } else {
406 $sql .= " WHERE label = '".$this->db->escape($label)."' AND entity IN (".getEntity('category').")";
407 if (!is_null($type)) {
408 $sql .= " AND type = ".((int) $type);
409 }
410 }
411
412 dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
413 $resql = $this->db->query($sql);
414 if ($resql) {
415 if ($this->db->num_rows($resql) > 0 && $res = $this->db->fetch_array($resql)) {
416 $this->id = $res['rowid'];
417 //$this->ref = $res['rowid'];
418 $this->fk_parent = (int) $res['fk_parent'];
419 $this->label = $res['label'];
420 $this->description = $res['description'];
421 $this->color = $res['color'];
422 $this->position = $res['position'];
423 $this->socid = (int) $res['fk_soc'];
424 $this->visible = (int) $res['visible'];
425 $this->type = $res['type'];
426 $this->ref_ext = $res['ref_ext'];
427 $this->entity = (int) $res['entity'];
428 $this->date_creation = $this->db->jdate($res['date_creation']);
429 $this->date_modification = $this->db->jdate($res['tms']);
430 $this->user_creation_id = (int) $res['fk_user_creat'];
431 $this->user_modification_id = (int) $res['fk_user_modif'];
432
433 // Retrieve all extrafield
434 // fetch optionals attributes and labels
435 $this->fetch_optionals();
436
437 $this->db->free($resql);
438
439 // multilangs
440 if (getDolGlobalInt('MAIN_MULTILANGS')) {
441 $this->getMultiLangs();
442 }
443
444 return 1;
445 } else {
446 $this->error = "No category found";
447 return 0;
448 }
449 } else {
450 dol_print_error($this->db);
451 $this->error = $this->db->lasterror;
452 $this->errors[] = $this->db->lasterror;
453 return -1;
454 }
455 }
456
467 public function create($user, $notrigger = 0)
468 {
469 global $conf, $langs;
470 $langs->load('categories');
471
472 $type = $this->type;
473
474 if (!is_numeric($type)) {
475 $type = $this->MAP_ID[$type];
476 }
477
478 $error = 0;
479
480 dol_syslog(get_class($this).'::create', LOG_DEBUG);
481
482 // Clean parameters
483 $this->label = trim($this->label);
484 $this->description = trim($this->description);
485 $this->color = trim($this->color);
486 $this->position = (int) $this->position;
487 if (isset($this->import_key)) {
488 $this->import_key = trim($this->import_key);
489 }
490 $this->ref_ext = trim($this->ref_ext);
491 if (empty($this->visible)) {
492 $this->visible = 0;
493 }
494 $this->fk_parent = ($this->fk_parent != "" ? intval($this->fk_parent) : 0);
495
496 if ($this->already_exists()) {
497 $this->error = $langs->trans("ImpossibleAddCat", $this->label);
498 $this->error .= " : ".$langs->trans("CategoryExistsAtSameLevel");
499 dol_syslog($this->error, LOG_WARNING);
500 return -4;
501 }
502
503 $this->db->begin();
504 $now = dol_now();
505 $sql = "INSERT INTO ".MAIN_DB_PREFIX."categorie (";
506 $sql .= "fk_parent,";
507 $sql .= " label,";
508 $sql .= " description,";
509 $sql .= " color,";
510 $sql .= " position,";
511 if (getDolGlobalString('CATEGORY_ASSIGNED_TO_A_CUSTOMER')) {
512 $sql .= "fk_soc,";
513 }
514 $sql .= " visible,";
515 $sql .= " type,";
516 $sql .= " import_key,";
517 $sql .= " ref_ext,";
518 $sql .= " entity,";
519 $sql .= " date_creation,";
520 $sql .= " fk_user_creat";
521 $sql .= ") VALUES (";
522 $sql .= (int) $this->fk_parent.",";
523 $sql .= "'".$this->db->escape($this->label)."', ";
524 $sql .= "'".$this->db->escape($this->description)."', ";
525 $sql .= "'".$this->db->escape($this->color)."', ";
526 $sql .= (int) $this->position.",";
527 if (getDolGlobalString('CATEGORY_ASSIGNED_TO_A_CUSTOMER')) {
528 $sql .= ($this->socid > 0 ? $this->socid : 'null').", ";
529 }
530 $sql .= "'".$this->db->escape($this->visible)."', ";
531 $sql .= ((int) $type).", ";
532 $sql .= (!empty($this->import_key) ? "'".$this->db->escape($this->import_key)."'" : 'null').", ";
533 $sql .= (!empty($this->ref_ext) ? "'".$this->db->escape($this->ref_ext)."'" : 'null').", ";
534 $sql .= (int) $conf->entity.", ";
535 $sql .= "'".$this->db->idate($now)."', ";
536 $sql .= (int) $user->id;
537 $sql .= ")";
538
539 $res = $this->db->query($sql);
540 if ($res) {
541 $id = $this->db->last_insert_id(MAIN_DB_PREFIX."categorie");
542
543 if ($id > 0) {
544 $this->id = $id;
545
546 $action = 'create';
547
548 // Actions on extra fields
549 if (!$error) {
550 $result = $this->insertExtraFields();
551 if ($result < 0) {
552 $error++;
553 }
554 }
555
556 if (!$error && !$notrigger) {
557 // Call trigger
558 $result = $this->call_trigger('CATEGORY_CREATE', $user);
559 if ($result < 0) {
560 $error++;
561 }
562 // End call triggers
563 }
564
565 if (!$error) {
566 $this->db->commit();
567 return $id;
568 } else {
569 $this->db->rollback();
570 return -3;
571 }
572 } else {
573 $this->db->rollback();
574 return -2;
575 }
576 } else {
577 $this->error = $this->db->error();
578 $this->db->rollback();
579 return -1;
580 }
581 }
582
592 public function update(User $user, $notrigger = 0)
593 {
594 global $langs;
595
596 $error = 0;
597
598 // Clean parameters
599 $this->label = trim($this->label);
600 $this->description = trim($this->description);
601 $this->ref_ext = trim($this->ref_ext);
602 $this->fk_parent = ($this->fk_parent != "" ? intval($this->fk_parent) : 0);
603 $this->visible = ($this->visible != "" ? intval($this->visible) : 0);
604
605 if ($this->already_exists()) {
606 $this->error = $langs->trans("ImpossibleUpdateCat");
607 $this->error .= " : ".$langs->trans("CategoryExistsAtSameLevel");
608 return -1;
609 }
610
611 $this->db->begin();
612
613 $sql = "UPDATE ".MAIN_DB_PREFIX."categorie";
614 $sql .= " SET label = '".$this->db->escape($this->label)."',";
615 $sql .= " description = '".$this->db->escape($this->description)."',";
616 $sql .= " ref_ext = '".$this->db->escape($this->ref_ext)."',";
617 $sql .= " color = '".$this->db->escape($this->color)."'";
618 $sql .= ", position = ".(int) $this->position;
619 if (getDolGlobalString('CATEGORY_ASSIGNED_TO_A_CUSTOMER')) {
620 $sql .= ", fk_soc = ".($this->socid > 0 ? $this->socid : 'null');
621 }
622 $sql .= ", visible = ".(int) $this->visible;
623 $sql .= ", fk_parent = ".(int) $this->fk_parent;
624 $sql .= ", fk_user_modif = ".(int) $user->id;
625 $sql .= " WHERE rowid = ".((int) $this->id);
626
627 dol_syslog(get_class($this)."::update", LOG_DEBUG);
628 if ($this->db->query($sql)) {
629 $action = 'update';
630
631 // Actions on extra fields
632 if (!$error) {
633 $result = $this->insertExtraFields();
634 if ($result < 0) {
635 $error++;
636 }
637 }
638
639 if (!$error && !$notrigger) {
640 // Call trigger
641 $result = $this->call_trigger('CATEGORY_MODIFY', $user);
642 if ($result < 0) {
643 $error++;
644 }
645 // End call triggers
646 }
647
648 if (!$error) {
649 $this->db->commit();
650 return 1;
651 } else {
652 $this->db->rollback();
653 return -1;
654 }
655 } else {
656 $this->db->rollback();
657 dol_print_error($this->db);
658 return -1;
659 }
660 }
661
669 public function delete($user, $notrigger = 0)
670 {
671 $error = 0;
672
673 // Clean parameters
674 $this->fk_parent = ($this->fk_parent != "" ? intval($this->fk_parent) : 0);
675
676 dol_syslog(get_class($this)."::remove");
677
678 $this->db->begin();
679
680 if (!$error && !$notrigger) {
681 // Call trigger
682 $result = $this->call_trigger('CATEGORY_DELETE', $user);
683 if ($result < 0) {
684 $error++;
685 }
686 // End call triggers
687 }
688
689 /* FIX #1317 : Check for child category and move up 1 level*/
690 if (!$error) {
691 $sql = "UPDATE ".MAIN_DB_PREFIX."categorie";
692 $sql .= " SET fk_parent = ".((int) $this->fk_parent);
693 $sql .= " WHERE fk_parent = ".((int) $this->id);
694
695 if (!$this->db->query($sql)) {
696 $this->error = $this->db->lasterror();
697 $error++;
698 }
699 }
700
701 $arraydelete = array(
702 'categorie_account' => 'fk_categorie',
703 'categorie_actioncomm' => 'fk_categorie',
704 'categorie_contact' => 'fk_categorie',
705 'categorie_fournisseur' => 'fk_categorie',
706 'categorie_knowledgemanagement' => array('field' => 'fk_categorie', 'enabled' => isModEnabled('knowledgemanagement')),
707 'categorie_fichinter' => array('field' => 'fk_categorie', 'enabled' => isModEnabled('intervention')),
708 'categorie_member' => 'fk_categorie',
709 'categorie_user' => 'fk_categorie',
710 'categorie_product' => 'fk_categorie',
711 'categorie_project' => 'fk_categorie',
712 'categorie_societe' => 'fk_categorie',
713 'categorie_ticket' => array('field' => 'fk_categorie', 'enabled' => isModEnabled('ticket')),
714 'categorie_warehouse' => 'fk_categorie',
715 'categorie_website_page' => array('field' => 'fk_categorie', 'enabled' => isModEnabled('website')),
716 'category_bankline' => 'fk_categ',
717 'categorie_lang' => 'fk_category',
718 'categorie' => 'rowid',
719 );
720 foreach ($arraydelete as $key => $value) {
721 if (is_array($value)) {
722 if (empty($value['enabled'])) {
723 continue;
724 }
725 $value = $value['field'];
726 }
727 $sql = "DELETE FROM ".MAIN_DB_PREFIX.$key;
728 $sql .= " WHERE ".$value." = ".((int) $this->id);
729 if (!$this->db->query($sql)) {
730 $this->errors[] = $this->db->lasterror();
731 dol_syslog("Error sql=".$sql." ".$this->error, LOG_ERR);
732 $error++;
733 }
734 }
735
736 // Removed extrafields
737 if (!$error) {
738 $result = $this->deleteExtraFields();
739 if ($result < 0) {
740 $error++;
741 dol_syslog(get_class($this)."::delete erreur ".$this->error, LOG_ERR);
742 }
743 }
744
745 if (!$error) {
746 $this->db->commit();
747 return 1;
748 } else {
749 $this->db->rollback();
750 return -1;
751 }
752 }
753
754 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
763 public function add_type($obj, $type = '')
764 {
765 // phpcs:enable
766 global $user;
767
768 $error = 0;
769
770 if ($this->id == -1) {
771 return -2;
772 }
773
774 if (empty($type)) {
775 $type = $obj->element;
776 }
777
778 dol_syslog(get_class($this).'::add_type', LOG_DEBUG);
779
780 $this->db->begin();
781
782 $sql = "INSERT INTO ".MAIN_DB_PREFIX."categorie_".(empty($this->MAP_CAT_TABLE[$type]) ? $type : $this->MAP_CAT_TABLE[$type]);
783 $sql .= " (fk_categorie, fk_".(empty($this->MAP_CAT_FK[$type]) ? $type : $this->MAP_CAT_FK[$type]).")";
784 $sql .= " VALUES (".((int) $this->id).", ".((int) $obj->id).")";
785
786 if ($this->db->query($sql)) {
787 if (getDolGlobalString('CATEGORIE_RECURSIV_ADD')) {
788 $sql = 'SELECT fk_parent FROM '.MAIN_DB_PREFIX.'categorie';
789 $sql .= " WHERE rowid = ".((int) $this->id);
790
791 dol_syslog(get_class($this)."::add_type", LOG_DEBUG);
792 $resql = $this->db->query($sql);
793 if ($resql) {
794 if ($this->db->num_rows($resql) > 0) {
795 $objparent = $this->db->fetch_object($resql);
796
797 if (!empty($objparent->fk_parent)) {
798 $cat = new Categorie($this->db);
799 $cat->id = $objparent->fk_parent;
800 if (!$cat->containsObject($type, $obj->id)) {
801 $result = $cat->add_type($obj, $type);
802 if ($result < 0) {
803 $this->error = $cat->error;
804 $error++;
805 }
806 }
807 }
808 }
809 } else {
810 $error++;
811 $this->error = $this->db->lasterror();
812 }
813
814 if ($error) {
815 $this->db->rollback();
816 return -1;
817 }
818 }
819
820 // Call trigger
821 $this->context = array('linkto' => $obj); // Save object we want to link category to into category instance to provide information to trigger
822 $result = $this->call_trigger('CATEGORY_MODIFY', $user);
823 if ($result < 0) {
824 $error++;
825 }
826 // End call triggers
827
828 if (!$error) {
829 $this->db->commit();
830 return 1;
831 } else {
832 $this->db->rollback();
833 return -2;
834 }
835 } else {
836 $this->db->rollback();
837 if ($this->db->lasterrno() == 'DB_ERROR_RECORD_ALREADY_EXISTS') {
838 $this->error = $this->db->lasterrno();
839 return -3;
840 } else {
841 $this->error = $this->db->lasterror();
842 }
843 return -1;
844 }
845 }
846
847 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
856 public function del_type($obj, $type)
857 {
858 // phpcs:enable
859 global $user;
860
861 $error = 0;
862
863 // For backward compatibility
864 if ($type == 'societe') {
865 $type = 'customer';
866 dol_syslog(get_class($this)."::del_type(): type 'societe' is deprecated, please use 'customer' instead", LOG_WARNING);
867 } elseif ($type == 'fournisseur') {
868 $type = 'supplier';
869 dol_syslog(get_class($this)."::del_type(): type 'fournisseur' is deprecated, please use 'supplier' instead", LOG_WARNING);
870 }
871
872 $this->db->begin();
873
874 $sql = "DELETE FROM ".MAIN_DB_PREFIX."categorie_".(empty($this->MAP_CAT_TABLE[$type]) ? $type : $this->MAP_CAT_TABLE[$type]);
875 $sql .= " WHERE fk_categorie = ".((int) $this->id);
876 $sql .= " AND fk_".(empty($this->MAP_CAT_FK[$type]) ? $type : $this->MAP_CAT_FK[$type])." = ".((int) $obj->id);
877
878 dol_syslog(get_class($this).'::del_type', LOG_DEBUG);
879 if ($this->db->query($sql)) {
880 // Call trigger
881 $this->context = array('unlinkoff' => $obj); // Save object we want to link category to into category instance to provide information to trigger
882 $result = $this->call_trigger('CATEGORY_MODIFY', $user);
883 if ($result < 0) {
884 $error++;
885 }
886 // End call triggers
887
888 if (!$error) {
889 $this->db->commit();
890 return 1;
891 } else {
892 $this->db->rollback();
893 return -2;
894 }
895 } else {
896 $this->db->rollback();
897 $this->error = $this->db->lasterror();
898 return -1;
899 }
900 }
901
919 public function getObjectsInCateg($type, $onlyids = 0, $limit = 0, $offset = 0, $sortfield = '', $sortorder = 'ASC', $filter = '', $filtermode = 'AND', $filterlang = '')
920 {
921 global $user;
922
923 $objs = array();
924
925 $classnameforobj = $this->MAP_OBJ_CLASS[$type];
926 $obj = new $classnameforobj($this->db);
927
928 $sql = "SELECT c.fk_".(empty($this->MAP_CAT_FK[$type]) ? $type : $this->MAP_CAT_FK[$type])." as fk_object";
929 $sql .= " FROM ".MAIN_DB_PREFIX."categorie_".(empty($this->MAP_CAT_TABLE[$type]) ? $type : $this->MAP_CAT_TABLE[$type])." as c";
930 $sql .= ", ".MAIN_DB_PREFIX.(empty($this->MAP_OBJ_TABLE[$type]) ? $type : $this->MAP_OBJ_TABLE[$type])." as o";
931 if (!empty($filterlang)) {
932 $sql .= ", ".MAIN_DB_PREFIX.(empty($this->MAP_OBJ_TABLE[$type]) ? $type : $this->MAP_OBJ_TABLE[$type])."_lang as ol";
933 }
934 $sql .= " WHERE o.entity IN (".getEntity($obj->element).")";
935 $sql .= " AND c.fk_categorie = ".((int) $this->id);
936 // Compatibility with actioncomm table which has id instead of rowid
937 if ((array_key_exists($type, $this->MAP_OBJ_TABLE) && $this->MAP_OBJ_TABLE[$type] == "actioncomm") || $type == "actioncomm") {
938 $sql .= " AND c.fk_".(empty($this->MAP_CAT_FK[$type]) ? $type : $this->MAP_CAT_FK[$type])." = o.id";
939 } else {
940 $sql .= " AND c.fk_".(empty($this->MAP_CAT_FK[$type]) ? $type : $this->MAP_CAT_FK[$type])." = o.rowid";
941 }
942 if (!empty($filterlang)) {
943 $sql .= " AND ol.fk_".(empty($this->MAP_OBJ_TABLE[$type]) ? $type : $this->MAP_OBJ_TABLE[$type])." = o.rowid";
944 $sql .= " AND ol.lang = '".$this->db->escape($filterlang)."'";
945 }
946 // Protection for external users
947 if (($type == 'customer' || $type == 'supplier') && $user->socid > 0) {
948 $sql .= " AND o.rowid = ".((int) $user->socid);
949 }
950
951 $errormessage = '';
952 $sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage);
953 if ($errormessage) {
954 $this->errors[] = $errormessage;
955 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
956 return -1;
957 }
958
959 $sql .= $this->db->order($sortfield, $sortorder);
960 if ($limit > 0 || $offset > 0) {
961 $sql .= $this->db->plimit($limit + 1, $offset);
962 }
963
964 dol_syslog(get_class($this)."::getObjectsInCateg", LOG_DEBUG);
965
966 $resql = $this->db->query($sql);
967 if ($resql) {
968 while ($rec = $this->db->fetch_array($resql)) {
969 if ($onlyids) {
970 $objs[] = $rec['fk_object'];
971 } else {
972 $classnameforobj = $this->MAP_OBJ_CLASS[$type];
973
974 $obj = new $classnameforobj($this->db);
975 $obj->fetch($rec['fk_object']);
976 if ($obj->id > 0) { // Failing fetch may happen for example when a category supplier was set and third party was moved as customer only. The object supplier can't be loaded.
977 $objs[] = $obj;
978 }
979 }
980 }
981 return $objs;
982 } else {
983 $this->error = $this->db->error().' sql='.$sql;
984 return -1;
985 }
986 }
987
996 public function containsObject($type, $object_id)
997 {
998 $sql = "SELECT COUNT(*) as nb FROM ".MAIN_DB_PREFIX."categorie_".(empty($this->MAP_CAT_TABLE[$type]) ? $type : $this->MAP_CAT_TABLE[$type]);
999 $sql .= " WHERE fk_categorie = ".((int) $this->id)." AND fk_".(empty($this->MAP_CAT_FK[$type]) ? $type : $this->MAP_CAT_FK[$type])." = ".((int) $object_id);
1000
1001 dol_syslog(get_class($this)."::containsObject", LOG_DEBUG);
1002
1003 $resql = $this->db->query($sql);
1004 if ($resql) {
1005 return $this->db->fetch_object($resql)->nb;
1006 } else {
1007 $this->error = $this->db->error();
1008 return -1;
1009 }
1010 }
1011
1023 public function getListForItem($id, $type = 'customer', $sortfield = "s.rowid", $sortorder = 'ASC', $limit = 0, $page = 0)
1024 {
1025 $categories = array();
1026
1027 $type = sanitizeVal($type, 'aZ09');
1028
1029 $sub_type = $type;
1030 $subcol_name = "fk_".$type;
1031 if ($type == "customer") {
1032 $sub_type = "societe";
1033 $subcol_name = "fk_soc";
1034 }
1035 if ($type == "supplier") {
1036 $sub_type = "fournisseur";
1037 $subcol_name = "fk_soc";
1038 }
1039 if ($type == "contact") {
1040 $subcol_name = "fk_socpeople";
1041 }
1042
1043 $idoftype = array_search($type, self::$MAP_ID_TO_CODE);
1044
1045 $sql = "SELECT s.rowid";
1046 $sql .= " FROM ".MAIN_DB_PREFIX."categorie as s, ".MAIN_DB_PREFIX."categorie_".$sub_type." as sub";
1047 $sql .= ' WHERE s.entity IN ('.getEntity('category').')';
1048 $sql .= ' AND s.type='.((int) $idoftype);
1049 $sql .= ' AND s.rowid = sub.fk_categorie';
1050 $sql .= " AND sub.".$subcol_name." = ".((int) $id);
1051
1052 $sql .= $this->db->order($sortfield, $sortorder);
1053
1054 $offset = 0;
1055 $nbtotalofrecords = '';
1056 if (!getDolGlobalInt('MAIN_DISABLE_FULL_SCANLIST')) {
1057 $result = $this->db->query($sql);
1058 $nbtotalofrecords = $this->db->num_rows($result);
1059 if (($page * $limit) > $nbtotalofrecords) { // if total resultset is smaller then paging size (filtering), goto and load page 0
1060 $page = 0;
1061 $offset = 0;
1062 }
1063 }
1064
1065 if ($limit) {
1066 if ($page < 0) {
1067 $page = 0;
1068 }
1069 $offset = $limit * $page;
1070
1071 $sql .= $this->db->plimit($limit + 1, $offset);
1072 }
1073
1074 $result = $this->db->query($sql);
1075 if ($result) {
1076 $i = 0;
1077 $num = $this->db->num_rows($result);
1078 $min = min($num, ($limit <= 0 ? $num : $limit));
1079 while ($i < $min) {
1080 $obj = $this->db->fetch_object($result);
1081 $category_static = new Categorie($this->db);
1082 if ($category_static->fetch($obj->rowid)) {
1083 $categories[$i]['id'] = $category_static->id;
1084 $categories[$i]['fk_parent'] = $category_static->fk_parent;
1085 $categories[$i]['label'] = $category_static->label;
1086 $categories[$i]['description'] = $category_static->description;
1087 $categories[$i]['color'] = $category_static->color;
1088 $categories[$i]['position'] = $category_static->position;
1089 $categories[$i]['socid'] = $category_static->socid;
1090 $categories[$i]['ref_ext'] = $category_static->ref_ext;
1091 $categories[$i]['visible'] = $category_static->visible;
1092 $categories[$i]['type'] = $category_static->type;
1093 $categories[$i]['entity'] = $category_static->entity;
1094 $categories[$i]['array_options'] = $category_static->array_options;
1095
1096 // multilangs
1097 if (getDolGlobalInt('MAIN_MULTILANGS') && isset($category_static->multilangs)) {
1098 $categories[$i]['multilangs'] = $category_static->multilangs;
1099 }
1100 }
1101 $i++;
1102 }
1103 } else {
1104 $this->error = $this->db->lasterror();
1105 return -1;
1106 }
1107 if (!count($categories)) {
1108 return [];
1109 }
1110
1111 return $categories;
1112 }
1113
1114 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1120 public function get_filles()
1121 {
1122 // phpcs:enable
1123 $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."categorie";
1124 $sql .= " WHERE fk_parent = ".((int) $this->id);
1125 $sql .= " AND entity IN (".getEntity('category').")";
1126
1127 $res = $this->db->query($sql);
1128 if ($res) {
1129 $cats = array();
1130 while ($rec = $this->db->fetch_array($res)) {
1131 $cat = new Categorie($this->db);
1132 $cat->fetch($rec['rowid']);
1133 $cats[] = $cat;
1134 }
1135 return $cats;
1136 } else {
1137 dol_print_error($this->db);
1138 return -1;
1139 }
1140 }
1141
1142 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1148 protected function load_motherof()
1149 {
1150 // phpcs:enable
1151 $this->motherof = array();
1152
1153 // Load array[child]=parent
1154 $sql = "SELECT fk_parent as id_parent, rowid as id_son";
1155 $sql .= " FROM ".MAIN_DB_PREFIX."categorie";
1156 $sql .= " WHERE fk_parent != 0";
1157 $sql .= " AND entity IN (".getEntity('category').")";
1158
1159 dol_syslog(get_class($this)."::load_motherof", LOG_DEBUG);
1160 $resql = $this->db->query($sql);
1161 if ($resql) {
1162 while ($obj = $this->db->fetch_object($resql)) {
1163 $this->motherof[$obj->id_son] = $obj->id_parent;
1164 }
1165 return 1;
1166 } else {
1167 dol_print_error($this->db);
1168 return -1;
1169 }
1170 }
1171
1172 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1192 public function get_full_arbo($type, $fromid = 0, $include = 0)
1193 {
1194 // phpcs:enable
1195 global $langs;
1196
1197 if (!is_numeric($type)) {
1198 $type = $this->MAP_ID[$type];
1199 }
1200 if (is_null($type)) {
1201 $this->error = 'BadValueForParameterType';
1202 return -1;
1203 }
1204
1205 if (is_string($fromid)) {
1206 $fromid = explode(',', $fromid);
1207 } elseif (is_numeric($fromid)) {
1208 if ($fromid > 0) {
1209 $fromid = array($fromid);
1210 } else {
1211 $fromid = array();
1212 }
1213 } elseif (!is_array($fromid)) {
1214 $fromid = array();
1215 }
1216
1217 $this->cats = array();
1218 $nbcateg = 0;
1219
1220 // Init this->motherof that is array(id_son=>id_parent, ...)
1221 $this->load_motherof();
1222 $current_lang = $langs->getDefaultLang();
1223
1224 // Init $this->cats array
1225 $sql = "SELECT DISTINCT c.rowid, c.label, c.ref_ext, c.description, c.color, c.position, c.fk_parent, c.visible"; // Distinct reduce pb with old tables with duplicates
1226 if (getDolGlobalInt('MAIN_MULTILANGS')) {
1227 $sql .= ", t.label as label_trans, t.description as description_trans";
1228 }
1229 $sql .= " FROM ".MAIN_DB_PREFIX."categorie as c";
1230 if (getDolGlobalInt('MAIN_MULTILANGS')) {
1231 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."categorie_lang as t ON t.fk_category=c.rowid AND t.lang='".$this->db->escape($current_lang)."'";
1232 }
1233 $sql .= " WHERE c.entity IN (".getEntity('category').")";
1234 $sql .= " AND c.type = ".(int) $type;
1235
1236 dol_syslog(get_class($this)."::get_full_arbo get category list", LOG_DEBUG);
1237 $resql = $this->db->query($sql);
1238 if ($resql) {
1239 $i = 0;
1240 $nbcateg = $this->db->num_rows($resql);
1241
1242 while ($obj = $this->db->fetch_object($resql)) {
1243 $this->cats[$obj->rowid]['rowid'] = $obj->rowid;
1244 $this->cats[$obj->rowid]['id'] = $obj->rowid;
1245 $this->cats[$obj->rowid]['fk_parent'] = $obj->fk_parent;
1246 $this->cats[$obj->rowid]['label'] = !empty($obj->label_trans) ? $obj->label_trans : $obj->label;
1247 $this->cats[$obj->rowid]['description'] = !empty($obj->description_trans) ? $obj->description_trans : $obj->description;
1248 $this->cats[$obj->rowid]['color'] = $obj->color;
1249 $this->cats[$obj->rowid]['position'] = $obj->position;
1250 $this->cats[$obj->rowid]['visible'] = $obj->visible;
1251 $this->cats[$obj->rowid]['ref_ext'] = $obj->ref_ext;
1252 $this->cats[$obj->rowid]['picto'] = 'category';
1253 // fields are filled with buildPathFromId
1254 $this->cats[$obj->rowid]['fullpath'] = '';
1255 $this->cats[$obj->rowid]['fulllabel'] = '';
1256 $i++;
1257 }
1258 } else {
1259 dol_print_error($this->db);
1260 return -1;
1261 }
1262
1263 // We add the fullpath property to each elements of first level (no parent exists)
1264 dol_syslog(get_class($this)."::get_full_arbo call to buildPathFromId", LOG_DEBUG);
1265 foreach ($this->cats as $key => $val) {
1266 //print 'key='.$key.'<br>'."\n";
1267 $this->buildPathFromId($key, $nbcateg); // Process a branch from the root category key (this category has no parent) and adds kevek to $this->cats items
1268 }
1269
1270 // Include or exclude leaf (including $fromid) from tree
1271 if (count($fromid) > 0) {
1272 $keyfiltercatid = '('.implode('|', $fromid).')';
1273
1274 //print "Look to discard category ".$fromid."\n";
1275 $keyfilter1 = '^'.$keyfiltercatid.'$';
1276 $keyfilter2 = '_'.$keyfiltercatid.'$';
1277 $keyfilter3 = '^'.$keyfiltercatid.'_';
1278 $keyfilter4 = '_'.$keyfiltercatid.'_';
1279 foreach (array_keys($this->cats) as $key) {
1280 $fullpath = (string) $this->cats[$key]['fullpath'];
1281 $test = (preg_match('/'.$keyfilter1.'/', $fullpath) || preg_match('/'.$keyfilter2.'/', $fullpath)
1282 || preg_match('/'.$keyfilter3.'/', $fullpath) || preg_match('/'.$keyfilter4.'/', $fullpath));
1283
1284 if (($test && !$include) || (!$test && $include)) {
1285 unset($this->cats[$key]); // @phpstan-ignore-line
1286 }
1287 }
1288 }
1289
1290 dol_syslog(get_class($this)."::get_full_arbo dol_sort_array", LOG_DEBUG);
1291
1292 $this->cats = dol_sort_array($this->cats, 'fulllabel', 'asc', 1, 0, 1); // Sort on full label like "Label 1 >> Sublabel a >> Subsublabel"
1293
1294 return $this->cats;
1295 }
1296
1307 private function buildPathFromId($id_categ, $protection = 1000)
1308 {
1309 //dol_syslog(get_class($this)."::buildPathFromId id_categ=".$id_categ." protection=".$protection, LOG_DEBUG);
1310
1311 if (!empty($this->cats[$id_categ]['fullpath'])) {
1312 // Already defined
1313 dol_syslog(get_class($this)."::buildPathFromId fullpath and fulllabel already defined", LOG_WARNING);
1314 return -1;
1315 }
1316
1317 // First build full array $motherof
1318 //$this->load_motherof(); // Disabled because already done by caller of buildPathFromId
1319
1320 // $this->cats[$id_categ] is supposed to be already an array. We just want to complete it with property fullpath and fulllabel
1321
1322 // Define fullpath and fulllabel
1323 $this->cats[$id_categ]['fullpath'] = '_'.$id_categ;
1324 $this->cats[$id_categ]['fulllabel'] = $this->cats[$id_categ]['label'];
1325 $i = 0;
1326 $cursor_categ = $id_categ;
1327 //print 'Work for id_categ='.$id_categ.'<br>'."\n";
1328 while ((empty($protection) || $i < $protection) && !empty($this->motherof[$cursor_categ])) {
1329 //print '&nbsp; cursor_categ='.$cursor_categ.' i='.$i.' '.$this->motherof[$cursor_categ].'<br>'."\n";
1330 $this->cats[$id_categ]['fullpath'] = '_'.$this->motherof[$cursor_categ].$this->cats[$id_categ]['fullpath'];
1331 $this->cats[$id_categ]['fulllabel'] = (empty($this->cats[$this->motherof[$cursor_categ]]) ? 'NotFound' : $this->cats[$this->motherof[$cursor_categ]]['label']).' >> '.$this->cats[$id_categ]['fulllabel'];
1332 //print '&nbsp; Result for id_categ='.$id_categ.' : '.$this->cats[$id_categ]['fullpath'].' '.$this->cats[$id_categ]['fulllabel'].'<br>'."\n";
1333 $i++;
1334 $cursor_categ = $this->motherof[$cursor_categ];
1335 }
1336 //print 'Result for id_categ='.$id_categ.' : '.$this->cats[$id_categ]['fullpath'].'<br>'."\n";
1337
1338 // We count number of _ to have level
1339 $nbunderscore = substr_count($this->cats[$id_categ]['fullpath'], '_');
1340 $this->cats[$id_categ]['level'] = ($nbunderscore ? $nbunderscore : null);
1341
1342 return 1;
1343 }
1344
1345
1346 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1354 public function get_all_categories($type = null, $parent = false)
1355 {
1356 // phpcs:enable
1357 if (!is_numeric($type) && !is_null($type)) {
1358 $type = $this->MAP_ID[$type];
1359 }
1360
1361 $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."categorie";
1362 $sql .= " WHERE entity IN (".getEntity('category').")";
1363 if (!is_null($type)) {
1364 $sql .= " AND type = ".(int) $type;
1365 }
1366 if ($parent) {
1367 $sql .= " AND fk_parent = 0";
1368 }
1369
1370 $res = $this->db->query($sql);
1371 if ($res) {
1372 $cats = array();
1373 while ($rec = $this->db->fetch_array($res)) {
1374 $cat = new Categorie($this->db);
1375 $cat->fetch($rec['rowid']);
1376 $cats[$rec['rowid']] = $cat;
1377 }
1378 return $cats;
1379 } else {
1380 dol_print_error($this->db);
1381 return -1;
1382 }
1383 }
1384
1385 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1392 public function get_main_categories($type = null)
1393 {
1394 // phpcs:enable
1395 return $this->get_all_categories($type, true);
1396 }
1397
1398 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1404 public function already_exists()
1405 {
1406 // phpcs:enable
1407 $type = $this->type;
1408
1409 if (!is_numeric($type)) {
1410 $type = $this->MAP_ID[$type];
1411 }
1412
1413 /* We have to select any rowid from llx_categorie which category's mother and label
1414 * are equals to those of the calling category
1415 */
1416 $sql = "SELECT c.rowid";
1417 $sql .= " FROM ".MAIN_DB_PREFIX."categorie as c ";
1418 $sql .= " WHERE c.entity IN (".getEntity('category').")";
1419 $sql .= " AND c.type = ".((int) $type);
1420 $sql .= " AND c.fk_parent = ".((int) $this->fk_parent);
1421 $sql .= " AND c.label = '".$this->db->escape($this->label)."'";
1422
1423 dol_syslog(get_class($this)."::already_exists", LOG_DEBUG);
1424
1425 $resql = $this->db->query($sql);
1426 if ($resql) {
1427 if ($this->db->num_rows($resql) > 0) { // Checking for empty resql
1428 $obj = $this->db->fetch_object($resql);
1429 /* If object called create, obj cannot have is id.
1430 * If object called update, he mustn't have the same label as an other category for this mother.
1431 * So if the result has the same id, update is not for label, and if result has an other one, update may be for label.
1432 */
1433 if (!empty($obj) && $obj->rowid > 0 && $obj->rowid != $this->id) {
1434 dol_syslog(get_class($this)."::already_exists category with name=".$this->label." and parent ".$this->fk_parent." exists: rowid=".$obj->rowid." current_id=".$this->id, LOG_DEBUG);
1435 return 1;
1436 }
1437 }
1438 dol_syslog(get_class($this)."::already_exists no category with same name=".$this->label." and same parent ".$this->fk_parent." than category id=".$this->id, LOG_DEBUG);
1439 return 0;
1440 } else {
1441 $this->error = $this->db->error();
1442 return -1;
1443 }
1444 }
1445
1446
1447 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1458 public function print_all_ways($sep = '&gt;&gt;', $url = '', $nocolor = 0, $addpicto = 0)
1459 {
1460 // phpcs:enable
1461 $ways = array();
1462
1463 $all_ways = $this->get_all_ways(); // Load array of categories
1464 foreach ($all_ways as $way) {
1465 $w = array();
1466 $i = 0;
1467 $forced_color = '';
1468 foreach ($way as $cat) {
1469 $i++;
1470
1471 if (empty($nocolor)) {
1472 $forced_color = 'colortoreplace';
1473 if ($i == count($way)) { // Last category in hierarchy
1474 // Check contrast with background and correct text color
1475 $forced_color = 'categtextwhite';
1476 if ($cat->color) {
1477 if (colorIsLight($cat->color)) {
1478 $forced_color = 'categtextblack';
1479 }
1480 }
1481 }
1482 }
1483
1484 if ($url == '') {
1485 $link = '<a href="'.DOL_URL_ROOT.'/categories/viewcat.php?id='.$cat->id.'&type='.$cat->type.'" class="'.$forced_color.'">';
1486 $linkend = '</a>';
1487 $w[] = $link.(($addpicto && $i == 1) ? img_object('', 'category', 'class="paddingright"') : '').$cat->label.$linkend;
1488 } elseif ($url == 'none') {
1489 $link = '<span class="'.$forced_color.'">';
1490 $linkend = '</span>';
1491 $w[] = $link.(($addpicto && $i == 1) ? img_object('', 'category', 'class="paddingright"') : '').$cat->label.$linkend;
1492 } else {
1493 $w[] = '<a class="'.$forced_color.'" href="'.DOL_URL_ROOT.'/'.$url.'?catid='.$cat->id.'">'.($addpicto ? img_object('', 'category') : '').$cat->label.'</a>';
1494 }
1495 }
1496 $newcategwithpath = preg_replace('/colortoreplace/', $forced_color, implode('<span class="inline-block valignmiddle paddingleft paddingright '.$forced_color.'">'.$sep.'</span>', $w));
1497
1498 $ways[] = $newcategwithpath;
1499 }
1500
1501 return $ways;
1502 }
1503
1504
1505 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1511 public function get_meres()
1512 {
1513 // phpcs:enable
1514 $parents = array();
1515
1516 $sql = "SELECT fk_parent FROM ".MAIN_DB_PREFIX."categorie";
1517 $sql .= " WHERE rowid = ".((int) $this->id);
1518
1519 $res = $this->db->query($sql);
1520
1521 if ($res) {
1522 while ($rec = $this->db->fetch_array($res)) {
1523 if ($rec['fk_parent'] > 0) {
1524 $cat = new Categorie($this->db);
1525 $cat->fetch($rec['fk_parent']);
1526 $parents[] = $cat;
1527 }
1528 }
1529 return $parents;
1530 } else {
1531 dol_print_error($this->db);
1532 return -1;
1533 }
1534 }
1535
1536 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1543 public function get_all_ways()
1544 {
1545 // phpcs:enable
1546 $ways = array();
1547
1548 $parents = $this->get_meres();
1549 if (is_array($parents)) {
1550 foreach ($parents as $parent) {
1551 $all_ways = $parent->get_all_ways();
1552 foreach ($all_ways as $way) {
1553 $w = $way;
1554 $w[] = $this;
1555 $ways[] = $w;
1556 }
1557 }
1558 }
1559
1560 if (count($ways) == 0) {
1561 $ways[0][0] = $this;
1562 }
1563
1564 return $ways;
1565 }
1566
1577 public function containing($id, $type, $mode = 'object')
1578 {
1579 $cats = array();
1580
1581 if (is_numeric($type)) {
1582 $type = Categorie::$MAP_ID_TO_CODE[$type];
1583 }
1584
1585 if ($type === Categorie::TYPE_BANK_LINE) { // TODO Remove this after migration of llx_category_bankline into llx_categorie_bankline
1586 // Load bank categories
1587 $sql = "SELECT c.label, c.rowid";
1588 $sql .= " FROM ".MAIN_DB_PREFIX."category_bankline as a, ".MAIN_DB_PREFIX."categorie as c";
1589 $sql .= " WHERE a.lineid=".((int) $id)." AND a.fk_categ = c.rowid";
1590 $sql .= " AND c.entity IN (".getEntity('category').")";
1591 $sql .= " ORDER BY c.label";
1592
1593 $res = $this->db->query($sql);
1594 if ($res) {
1595 while ($obj = $this->db->fetch_object($res)) {
1596 if ($mode == 'id') {
1597 $cats[] = $obj->rowid;
1598 } elseif ($mode == 'label') {
1599 $cats[] = $obj->label;
1600 } else {
1601 $cat = new Categorie($this->db);
1602 $cat->id = $obj->rowid;
1603 $cat->label = $obj->label;
1604 $cats[] = $cat;
1605 }
1606 }
1607 } else {
1608 dol_print_error($this->db);
1609 return -1;
1610 }
1611 } else {
1612 $sql = "SELECT ct.fk_categorie, c.label, c.rowid";
1613 $sql .= " FROM ".MAIN_DB_PREFIX."categorie_".(empty($this->MAP_CAT_TABLE[$type]) ? $type : $this->MAP_CAT_TABLE[$type])." as ct, ".MAIN_DB_PREFIX."categorie as c";
1614 $sql .= " WHERE ct.fk_categorie = c.rowid AND ct.fk_".(empty($this->MAP_CAT_FK[$type]) ? $type : $this->MAP_CAT_FK[$type])." = ".(int) $id;
1615 // This seems useless because the table already contains id of category of 1 unique type. So commented.
1616 // So now it works also with external added categories.
1617 //$sql .= " AND c.type = ".((int) $this->MAP_ID[$type]);
1618 $sql .= " AND c.entity IN (".getEntity('category').")";
1619
1620 $res = $this->db->query($sql);
1621 if ($res) {
1622 while ($obj = $this->db->fetch_object($res)) {
1623 if ($mode == 'id') {
1624 $cats[] = $obj->rowid;
1625 } elseif ($mode == 'label') {
1626 $cats[] = $obj->label;
1627 } else {
1628 $cat = new Categorie($this->db);
1629 $cat->fetch($obj->fk_categorie);
1630 $cats[] = $cat;
1631 }
1632 }
1633 } else {
1634 dol_print_error($this->db);
1635 return -1;
1636 }
1637 }
1638
1639 return $cats;
1640 }
1641
1653 public function rechercher($id, $nom, $type, $exact = false, $case = false)
1654 {
1655 // Deprecation warning
1656 if (is_numeric($type)) {
1657 dol_syslog(__METHOD__.': using numeric types is deprecated.', LOG_WARNING);
1658 }
1659
1660 $cats = array();
1661
1662 // For backward compatibility
1663 if (is_numeric($type)) {
1664 // We want to reverse lookup
1665 $map_type = array_flip($this->MAP_ID);
1666 $type = $map_type[$type];
1667 dol_syslog(get_class($this)."::rechercher(): numeric types are deprecated, please use string instead", LOG_WARNING);
1668 }
1669
1670 // Generation requete recherche
1671 $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."categorie";
1672 $sql .= " WHERE type = ".((int) $this->MAP_ID[$type]);
1673 $sql .= " AND entity IN (".getEntity('category').")";
1674 if ($nom) {
1675 if (!$exact) {
1676 $nom = '%'.$this->db->escape(str_replace('*', '%', $nom)).'%';
1677 }
1678 if (!$case) {
1679 $sql .= " AND label LIKE '".$this->db->escape($nom)."'";
1680 } else {
1681 $sql .= " AND label LIKE BINARY '".$this->db->escape($nom)."'";
1682 }
1683 }
1684 if ($id) {
1685 $sql .= " AND rowid = ".((int) $id);
1686 }
1687
1688 $res = $this->db->query($sql);
1689 if ($res) {
1690 while ($rec = $this->db->fetch_array($res)) {
1691 $cat = new Categorie($this->db);
1692 $cat->fetch($rec['rowid']);
1693 $cats[] = $cat;
1694 }
1695
1696 return $cats;
1697 } else {
1698 $this->error = $this->db->error().' sql='.$sql;
1699 return -1;
1700 }
1701 }
1702
1709 public function isAnyPhotoAvailable($sdir)
1710 {
1711 include_once DOL_DOCUMENT_ROOT . '/core/lib/files.lib.php';
1712 include_once DOL_DOCUMENT_ROOT . '/core/lib/images.lib.php';
1713
1714 $sdir .= '/' . get_exdir($this->id, 2, 0, 0, $this, 'category') . $this->id . "/photos/";
1715
1716 $dir_osencoded = dol_osencode($sdir);
1717 if (file_exists($dir_osencoded)) {
1718 $handle = opendir($dir_osencoded);
1719 if (is_resource($handle)) {
1720 while (($file = readdir($handle)) !== false) {
1721 if (!utf8_check($file)) {
1722 $file = mb_convert_encoding($file, 'UTF-8', 'ISO-8859-1'); // To be sure data is stored in UTF8 in memory
1723 }
1724 if (dol_is_file($sdir . $file) && image_format_supported($file) >= 0) {
1725 return true;
1726 }
1727 }
1728 }
1729 }
1730 return false;
1731 }
1732
1739 public function getTooltipContentArray($params)
1740 {
1741 global $langs;
1742
1743 $langs->load('categories');
1744
1745 $datas = [];
1746
1747 $datas['label'] = $langs->trans("ShowCategory").': '.($this->ref ? $this->ref : $this->label);
1748
1749 return $datas;
1750 }
1751
1765 public function getNomUrl($withpicto = 0, $option = '', $maxlength = 0, $moreparam = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = 0)
1766 {
1767 global $conf, $langs, $hookmanager;
1768
1769 if (!empty($conf->dol_no_mouse_hover)) {
1770 $notooltip = 1; // Force disable tooltips
1771 }
1772
1773 $result = '';
1774 $params = [
1775 'id' => $this->id,
1776 'objecttype' => $this->element,
1777 'option' => $option,
1778 ];
1779 $classfortooltip = 'classfortooltip';
1780 $dataparams = '';
1781 if (getDolGlobalInt('MAIN_ENABLE_AJAX_TOOLTIP')) {
1782 $classfortooltip = 'classforajaxtooltip';
1783 $dataparams = ' data-params="'.dol_escape_htmltag(json_encode($params)).'"';
1784 $label = '';
1785 } else {
1786 $label = implode($this->getTooltipContentArray($params));
1787 }
1788
1789 $url = DOL_URL_ROOT.'/categories/viewcat.php?id='.$this->id.'&type='.$this->type.$moreparam.'&backtopage='.urlencode($_SERVER['PHP_SELF'].($moreparam ? '?'.$moreparam : ''));
1790
1791 if ($option !== 'nolink') {
1792 // Add param to save lastsearch_values or not
1793 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
1794 if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
1795 $add_save_lastsearch_values = 1;
1796 }
1797 if ($url && $add_save_lastsearch_values) {
1798 $url .= '&save_lastsearch_values=1';
1799 }
1800 }
1801
1802 // Check contrast with background and correct text color
1803 $forced_color = 'categtextwhite';
1804 if ($this->color) {
1805 if (colorIsLight($this->color)) {
1806 $forced_color = 'categtextblack';
1807 }
1808 }
1809
1810 $linkclose = '';
1811 if (empty($notooltip)) {
1812 if (getDolGlobalInt('MAIN_OPTIMIZEFORTEXTBROWSER')) {
1813 $label = $langs->trans("ShowMyObject");
1814 $linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"';
1815 }
1816 $linkclose .= ($label ? ' title="'.dol_escape_htmltag($label, 1).'"' : ' title="tocomplete"');
1817 $linkclose .= $dataparams.' class="'.$classfortooltip.' '.$forced_color.($morecss ? ' '.$morecss : '').'"';
1818 } else {
1819 $linkclose = ' class="'.$forced_color.($morecss ? ' '.$morecss : '').'"';
1820 }
1821
1822 if ($option == 'nolink' || empty($url)) {
1823 $linkstart = '<span';
1824 } else {
1825 $linkstart = '<a href="'.$url.'"';
1826 }
1827 $linkstart .= $linkclose.'>';
1828 if ($option == 'nolink' || empty($url)) {
1829 $linkend = '</span>';
1830 } else {
1831 $linkend = '</a>';
1832 }
1833
1834 $result .= $linkstart;
1835
1836 if ($withpicto) {
1837 $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'"'), 0, 0, $notooltip ? 0 : 1);
1838 }
1839
1840 if ($withpicto != 2) {
1841 $result .= dol_trunc(($this->ref ? $this->ref : $this->label), $maxlength);
1842 }
1843
1844 $result .= $linkend;
1845
1846 global $action;
1847 $hookmanager->initHooks(array($this->element . 'dao'));
1848 $parameters = array('id' => $this->id, 'getnomurl' => &$result);
1849 $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
1850 if ($reshook > 0) {
1851 $result = $hookmanager->resPrint;
1852 } else {
1853 $result .= $hookmanager->resPrint;
1854 }
1855 return $result;
1856 }
1857
1858
1859 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1867 public function add_photo($sdir, $file)
1868 {
1869 // phpcs:enable
1870 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
1871
1872 $dir = $sdir.'/'.get_exdir($this->id, 2, 0, 0, $this, 'category').$this->id."/";
1873 $dir .= "photos/";
1874
1875 if (!file_exists($dir)) {
1876 dol_mkdir($dir);
1877 }
1878
1879 if (file_exists($dir)) {
1880 if (is_array($file['name'])) {
1881 $nbfile = count($file['name']);
1882 for ($i = 0; $i < $nbfile; $i++) {
1883 $originImage = $dir.$file['name'][$i];
1884
1885 // Cree fichier en taille origine
1886 dol_move_uploaded_file($file['tmp_name'][$i], $originImage, 1, 0, 0);
1887
1888 if (file_exists($originImage)) {
1889 // Create thumbs
1890 $this->addThumbs($originImage);
1891 }
1892 }
1893 } else {
1894 $originImage = $dir.$file['name'];
1895
1896 // Cree fichier en taille origine
1897 dol_move_uploaded_file($file['tmp_name'], $originImage, 1, 0, 0);
1898
1899 if (file_exists($originImage)) {
1900 // Create thumbs
1901 $this->addThumbs($originImage);
1902 }
1903 }
1904 }
1905 }
1906
1907 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1915 public function liste_photos($dir, $nbmax = 0)
1916 {
1917 // phpcs:enable
1918 include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
1919
1920 $nbphoto = 0;
1921 $tabobj = array();
1922
1923 $dirthumb = $dir.'thumbs/';
1924
1925 if (file_exists($dir)) {
1926 $handle = opendir($dir);
1927 if (is_resource($handle)) {
1928 while (($file = readdir($handle)) !== false) {
1929 if (dol_is_file($dir.$file) && preg_match('/(\.jpeg|\.jpg|\.bmp|\.gif|\.png|\.tiff)$/i', $dir.$file)) {
1930 $nbphoto++;
1931 $photo = $file;
1932
1933 // On determine nom du fichier vignette
1934 $photo_vignette = '';
1935 $regs = array();
1936 if (preg_match('/(\.jpeg|\.jpg|\.bmp|\.gif|\.png|\.tiff)$/i', $photo, $regs)) {
1937 $photo_vignette = preg_replace('/'.$regs[0].'/i', '', $photo).'_small'.$regs[0];
1938 }
1939
1940 // Object
1941 $obj = array();
1942 $obj['photo'] = $photo;
1943 if ($photo_vignette && is_file($dirthumb.$photo_vignette)) {
1944 $obj['photo_vignette'] = 'thumbs/'.$photo_vignette;
1945 } else {
1946 $obj['photo_vignette'] = "";
1947 }
1948
1949 $tabobj[$nbphoto - 1] = $obj;
1950
1951 // On continue ou on arrete de boucler
1952 if ($nbmax && $nbphoto >= $nbmax) {
1953 break;
1954 }
1955 }
1956 }
1957
1958 closedir($handle);
1959 }
1960 }
1961
1962 return $tabobj;
1963 }
1964
1965 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1972 public function delete_photo($file)
1973 {
1974 // phpcs:enable
1975 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
1976
1977 $dir = dirname($file).'/'; // Chemin du dossier contenant l'image d'origine
1978 $dirthumb = $dir.'/thumbs/'; // Chemin du dossier contenant la vignette
1979 $filename = preg_replace('/'.preg_quote($dir, '/').'/i', '', $file); // Nom du fichier
1980
1981 // On efface l'image d'origine
1982 dol_delete_file($file, 1);
1983
1984 // Si elle existe, on efface la vignette
1985 $regs = array();
1986 if (preg_match('/(\.jpeg|\.jpg|\.bmp|\.gif|\.png|\.tiff)$/i', $filename, $regs)) {
1987 $photo_vignette = preg_replace('/'.$regs[0].'/i', '', $filename).'_small'.$regs[0];
1988 if (file_exists($dirthumb.$photo_vignette)) {
1989 dol_delete_file($dirthumb.$photo_vignette, 1);
1990 }
1991 }
1992 }
1993
1994 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2001 public function get_image_size($file)
2002 {
2003 // phpcs:enable
2004 $infoImg = getimagesize($file); // Recuperation des infos de l'image
2005 $this->imgWidth = $infoImg[0]; // Largeur de l'image
2006 $this->imgHeight = $infoImg[1]; // Hauteur de l'image
2007 }
2008
2017 public function setMultiLangs(User $user, $notrigger = 0)
2018 {
2019 global $langs;
2020
2021 $langs_available = $langs->get_available_languages();
2022 $current_lang = $langs->getDefaultLang();
2023
2024 foreach ($langs_available as $key => $value) {
2025 $sql = "SELECT rowid";
2026 $sql .= " FROM ".MAIN_DB_PREFIX."categorie_lang";
2027 $sql .= " WHERE fk_category=".((int) $this->id);
2028 $sql .= " AND lang = '".$this->db->escape($key)."'";
2029
2030 $result = $this->db->query($sql);
2031
2032 if ($key == $current_lang) {
2033 $sql2 = '';
2034 if ($this->db->num_rows($result)) { // if no line in database
2035 $sql2 = "UPDATE ".MAIN_DB_PREFIX."categorie_lang";
2036 $sql2 .= " SET label = '".$this->db->escape($this->label)."',";
2037 $sql2 .= " description = '".$this->db->escape($this->description)."'";
2038 $sql2 .= " WHERE fk_category = ".((int) $this->id)." AND lang = '".$this->db->escape($key)."'";
2039 } elseif (isset($this->multilangs[$key])) {
2040 $sql2 = "INSERT INTO ".MAIN_DB_PREFIX."categorie_lang (fk_category, lang, label, description)";
2041 $sql2 .= " VALUES(".((int) $this->id).", '".$this->db->escape($key)."', '".$this->db->escape($this->label)."'";
2042 $sql2 .= ", '".$this->db->escape($this->multilangs[$key]["description"])."')";
2043 }
2044 dol_syslog(get_class($this).'::setMultiLangs', LOG_DEBUG);
2045 if ($sql2 && !$this->db->query($sql2)) {
2046 $this->error = $this->db->lasterror();
2047 return -1;
2048 }
2049 } elseif (isset($this->multilangs[$key])) {
2050 if ($this->db->num_rows($result)) { // if no line in database
2051 $sql2 = "UPDATE ".MAIN_DB_PREFIX."categorie_lang";
2052 $sql2 .= " SET label='".$this->db->escape($this->multilangs[$key]["label"])."',";
2053 $sql2 .= " description='".$this->db->escape($this->multilangs[$key]["description"])."'";
2054 $sql2 .= " WHERE fk_category=".((int) $this->id)." AND lang='".$this->db->escape($key)."'";
2055 } else {
2056 $sql2 = "INSERT INTO ".MAIN_DB_PREFIX."categorie_lang (fk_category, lang, label, description)";
2057 $sql2 .= " VALUES(".((int) $this->id).", '".$this->db->escape($key)."', '".$this->db->escape($this->multilangs[$key]["label"])."'";
2058 $sql2 .= ",'".$this->db->escape($this->multilangs[$key]["description"])."')";
2059 }
2060
2061 // on ne sauvegarde pas des champs vides
2062 if ($this->multilangs[$key]["label"] || $this->multilangs[$key]["description"] || $this->multilangs[$key]["note"]) {
2063 dol_syslog(get_class($this).'::setMultiLangs', LOG_DEBUG);
2064 }
2065 if (!$this->db->query($sql2)) {
2066 $this->error = $this->db->lasterror();
2067 return -1;
2068 }
2069 }
2070 }
2071
2072 // Call trigger
2073 if (!$notrigger) {
2074 $result = $this->call_trigger('CATEGORY_SET_MULTILANGS', $user);
2075 if ($result < 0) {
2076 $this->error = $this->db->lasterror();
2077 return -1;
2078 }
2079 }
2080 // End call triggers
2081
2082 return 1;
2083 }
2084
2093 public function delMultiLangs($langtodelete, $user)
2094 {
2095 $sql = "DELETE FROM ".$this->db->prefix()."categorie_lang";
2096 $sql .= " WHERE fk_category = ".((int) $this->id)." AND lang = '".$this->db->escape($langtodelete)."'";
2097
2098 dol_syslog(get_class($this).'::delMultiLangs', LOG_DEBUG);
2099 $result = $this->db->query($sql);
2100 if ($result) {
2101 // Call trigger
2102 $result = $this->call_trigger('CATEGORY_DEL_MULTILANGS', $user);
2103 if ($result < 0) {
2104 $this->error = $this->db->lasterror();
2105 dol_syslog(get_class($this).'::delMultiLangs error='.$this->error, LOG_ERR);
2106 return -1;
2107 }
2108 // End call triggers
2109 return 1;
2110 } else {
2111 $this->error = $this->db->lasterror();
2112 dol_syslog(get_class($this).'::delMultiLangs error='.$this->error, LOG_ERR);
2113 return -1;
2114 }
2115 }
2116
2122 public function getMultiLangs()
2123 {
2124 global $langs;
2125
2126 $current_lang = $langs->getDefaultLang();
2127
2128 $sql = "SELECT lang, label, description";
2129 $sql .= " FROM ".MAIN_DB_PREFIX."categorie_lang";
2130 $sql .= " WHERE fk_category=".((int) $this->id);
2131
2132 $result = $this->db->query($sql);
2133 if ($result) {
2134 while ($obj = $this->db->fetch_object($result)) {
2135 //print 'lang='.$obj->lang.' current='.$current_lang.'<br>';
2136 if ($obj->lang == $current_lang) { // si on a les traduct. dans la langue courante on les charge en infos principales.
2137 $this->label = $obj->label;
2138 $this->description = $obj->description;
2139 }
2140 $this->multilangs[$obj->lang]["label"] = $obj->label;
2141 $this->multilangs[$obj->lang]["description"] = $obj->description;
2142 }
2143 return 1;
2144 } else {
2145 $this->error = $langs->trans("Error")." : ".$this->db->error()." - ".$sql;
2146 return -1;
2147 }
2148 }
2149
2156 public function getLibStatut($mode)
2157 {
2158 return '';
2159 }
2160
2161
2169 public function initAsSpecimen()
2170 {
2171 dol_syslog(get_class($this)."::initAsSpecimen");
2172
2173 // Initialise parameters
2174 $this->id = 0;
2175 $this->fk_parent = 0;
2176 $this->label = 'SPECIMEN';
2177 $this->specimen = 1;
2178 $this->description = 'This is a description';
2179 $this->socid = 1;
2180 $this->type = self::TYPE_PRODUCT;
2181
2182 return 1;
2183 }
2184
2193 public static function replaceThirdparty(DoliDB $dbs, $origin_id, $dest_id)
2194 {
2195 $tables = array(
2196 'categorie_societe'
2197 );
2198
2199 return CommonObject::commonReplaceThirdparty($dbs, $origin_id, $dest_id, $tables, 1);
2200 }
2201
2210 public static function getFilterJoinQuery($type, $rowIdName)
2211 {
2212 if ($type == 'bank_account') {
2213 $type = 'account';
2214 }
2215
2216 return " LEFT JOIN ".MAIN_DB_PREFIX."categorie_".$type." as cp ON ".$rowIdName." = cp.fk_".$type;
2217 }
2218
2228 public static function getFilterSelectQuery($type, $rowIdName, $searchList)
2229 {
2230 if ($type == 'bank_account') {
2231 $type = 'account';
2232 }
2233 if ($type == 'customer') {
2234 $type = 'societe';
2235 }
2236 if ($type == 'supplier') {
2237 $type = 'fournisseur';
2238 }
2239
2240 if (empty($searchList) && !is_array($searchList)) {
2241 return "";
2242 }
2243
2244 $searchCategorySqlList = array();
2245 foreach ($searchList as $searchCategory) {
2246 if (intval($searchCategory) == -2) {
2247 $searchCategorySqlList[] = " cp.fk_categorie IS NULL";
2248 } elseif (intval($searchCategory) > 0) {
2249 $searchCategorySqlList[] = " ".$rowIdName." IN (SELECT fk_".$type." FROM ".MAIN_DB_PREFIX."categorie_".$type." WHERE fk_categorie = ".((int) $searchCategory).")";
2250 }
2251 }
2252
2253 if (!empty($searchCategorySqlList)) {
2254 return " AND (".implode(' AND ', $searchCategorySqlList).")";
2255 } else {
2256 return "";
2257 }
2258 }
2259
2265 public function countNbOfCategories()
2266 {
2267 dol_syslog(get_class($this)."::count_all_categories", LOG_DEBUG);
2268 $sql = "SELECT COUNT(rowid) FROM ".MAIN_DB_PREFIX."categorie";
2269 $sql .= " WHERE entity IN (".getEntity('category').")";
2270
2271 $res = $this->db->query($sql);
2272 if ($res) {
2273 $obj = $this->db->fetch_object($res);
2274 return $obj->count;
2275 } else {
2276 dol_print_error($this->db);
2277 return -1;
2278 }
2279 }
2280}
print $object position
Definition edit.php:204
$object ref
Definition info.php:89
Class to manage categories.
getListForItem($id, $type='customer', $sortfield="s.rowid", $sortorder='ASC', $limit=0, $page=0)
List categories of an element id.
get_image_size($file)
Load size of image file.
load_motherof()
Load the array this->motherof that is array(id_son=>id_parent, ...)
get_full_arbo($type, $fromid=0, $include=0)
Rebuilding the category tree as an array Return an array of table('id','id_mere',....
getLibStatut($mode)
Return label of contact status.
delete_photo($file)
Efface la photo de la categorie et sa vignette.
containing($id, $type, $mode='object')
Return list of categories (object instances or labels) linked to element of id $id and type $type Sho...
getTooltipContentArray($params)
getTooltipContentArray
countNbOfCategories()
Count all categories.
del_type($obj, $type)
Delete object from category.
buildPathFromId($id_categ, $protection=1000)
For category id_categ and its children available in this->cats, define property fullpath and fulllabe...
static getFilterSelectQuery($type, $rowIdName, $searchList)
Return the additional SQL SELECT query for filtering a list by a category.
delMultiLangs($langtodelete, $user)
Delete a language for this category.
create($user, $notrigger=0)
Add category into database.
rechercher($id, $nom, $type, $exact=false, $case=false)
Returns categories whose id or name match add wildcards in the name unless $exact = true.
getMultiLangs()
Load array this->multilangs.
getObjectsInCateg($type, $onlyids=0, $limit=0, $offset=0, $sortfield='', $sortorder='ASC', $filter='', $filtermode='AND', $filterlang='')
Return list of fetched instance of elements having this category.
isAnyPhotoAvailable($sdir)
Return if at least one photo is available.
already_exists()
Check if a category with same label already exists for this cat's parent or root and for this cat's t...
get_filles()
Return direct children ids of a category into an array.
initAsSpecimen()
Initialise an instance with random values.
get_all_categories($type=null, $parent=false)
Returns all categories.
static getFilterJoinQuery($type, $rowIdName)
Return the additional SQL JOIN query for filtering a list by a category.
containsObject($type, $object_id)
Check for the presence of an object in a category.
get_main_categories($type=null)
Returns the top level categories (which are not child)
__construct($db)
Constructor.
getMapId()
Get MAP_ID.
static replaceThirdparty(DoliDB $dbs, $origin_id, $dest_id)
Function used to replace a thirdparty id with another one.
setMultiLangs(User $user, $notrigger=0)
Create or Update translations of categories labels.
getMapList()
Get map list.
get_meres()
Returns an array containing the list of parent categories.
add_type($obj, $type='')
Link an object to the category.
update(User $user, $notrigger=0)
Update category.
liste_photos($dir, $nbmax=0)
Return an array with all photos inside the directory.
get_all_ways()
Returns in a table all possible paths to get to the category starting with the major categories repre...
getNomUrl($withpicto=0, $option='', $maxlength=0, $moreparam='', $notooltip=0, $morecss='', $save_lastsearch_value=0)
Return name and link of category (with picto) Use ->id, ->ref, ->label, ->color.
print_all_ways($sep='&gt;&gt;', $url='', $nocolor=0, $addpicto=0)
Returns the path of the category, with the names of the categories separated by $sep (" >> " by defau...
add_photo($sdir, $file)
Add the image uploaded as $file to the directory $sdir/<category>-<id>/photos/.
fetch($id, $label='', $type=null, $ref_ext='')
Load category into memory from database.
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...
deleteExtraFields()
Delete all extra fields values for the current object.
addThumbs($file)
Build thumb.
static commonReplaceThirdparty(DoliDB $dbs, $origin_id, $dest_id, array $tables, $ignoreerrors=0)
Function used to replace a thirdparty id with another one.
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 to manage Dolibarr users.
print $script_file $mode $langs defaultlang(is_numeric($duration_value) ? " delay=". $duration_value :"").(is_numeric($duration_value2) ? " after cd cd cd description as description
Only used if Module[ID]Desc translation string is not found.
dol_delete_file($file, $disableglob=0, $nophperrors=0, $nohook=0, $object=null, $allowdotdot=false, $indexdatabase=1, $nolog=0)
Remove a file or several files with a mask.
dol_move_uploaded_file($src_file, $dest_file, $allowoverwrite, $disablevirusscan=0, $uploaderrorcode=0, $nohook=0, $varfiles='addedfile', $upload_dir='')
Check validity of a file upload from an GUI page, and move it to its final destination.
dol_is_file($pathoffile)
Return if path is a file.
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0)
Show a picto called object_picto (generic function)
dol_osencode($str)
Return a string encoded into OS filesystem encoding.
forgeSQLFromUniversalSearchCriteria($filter, &$errorstr='', $noand=0, $nopar=0, $noerror=0)
forgeSQLFromUniversalSearchCriteria
dol_now($mode='auto')
Return date for now.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
dol_sort_array(&$array, $index, $order='asc', $natsort=0, $case_sensitive=0, $keepindex=0)
Advanced sort array by the value of a given key, which produces ascending (default) or descending out...
colorIsLight($stringcolor)
Return true if the color is light.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
dol_trunc($string, $size=40, $trunc='right', $stringencoding='UTF-8', $nodot=0, $display=0)
Truncate a string to a particular length adding '…' if string larger than length.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
sanitizeVal($out='', $check='alphanohtml', $filter=null, $options=null)
Return a sanitized or empty value after checking value against a rule.
utf8_check($str)
Check if a string is in UTF8.
get_exdir($num, $level, $alpha, $withoutslash, $object, $modulepart='')
Return a path to have a the directory according to object where files are stored.
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_mkdir($dir, $dataroot='', $newmask='')
Creation of a directory (this can create recursive subdir)
image_format_supported($file, $acceptsvg=0)
Return if a filename is file name of a supported image format.
global $conf
The following vars must be defined: $type2label $form $conf, $lang, The following vars may also be de...
Definition member.php:79
if(preg_match('/crypted:/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
Definition repair.php:149