dolibarr 21.0.0-alpha
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 Charlie Benke <charlie@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
69 public $picto = 'category';
70
71
75 protected $MAP_ID = array(
76 'product' => 0,
77 'supplier' => 1,
78 'customer' => 2,
79 'member' => 3,
80 'contact' => 4,
81 'bank_account' => 5,
82 'project' => 6,
83 'user' => 7,
84 'bank_line' => 8,
85 'warehouse' => 9,
86 'actioncomm' => 10,
87 'website_page' => 11,
88 'ticket' => 12,
89 'knowledgemanagement' => 13
90 );
91
97 public static $MAP_ID_TO_CODE = array(
98 0 => 'product',
99 1 => 'supplier',
100 2 => 'customer',
101 3 => 'member',
102 4 => 'contact',
103 5 => 'bank_account',
104 6 => 'project',
105 7 => 'user',
106 8 => 'bank_line',
107 9 => 'warehouse',
108 10 => 'actioncomm',
109 11 => 'website_page',
110 12 => 'ticket',
111 13 => 'knowledgemanagement'
112 );
113
119 public $MAP_CAT_FK = array(
120 'customer' => 'soc',
121 'supplier' => 'soc',
122 'contact' => 'socpeople',
123 'bank_account' => 'account',
124 );
125
131 public $MAP_CAT_TABLE = array(
132 'customer' => 'societe',
133 'supplier' => 'fournisseur',
134 'bank_account' => 'account',
135 );
136
142 public $MAP_OBJ_CLASS = array(
143 'product' => 'Product',
144 'customer' => 'Societe',
145 'supplier' => 'Fournisseur',
146 'member' => 'Adherent',
147 'contact' => 'Contact',
148 'user' => 'User',
149 'account' => 'Account', // old for bank account
150 'bank_account' => 'Account',
151 'project' => 'Project',
152 'warehouse' => 'Entrepot',
153 'actioncomm' => 'ActionComm',
154 'website_page' => 'WebsitePage',
155 'ticket' => 'Ticket',
156 'knowledgemanagement' => 'KnowledgeRecord'
157 );
158
164 public static $MAP_TYPE_TITLE_AREA = array(
165 'product' => 'ProductsCategoriesArea',
166 'customer' => 'CustomersCategoriesArea',
167 'supplier' => 'SuppliersCategoriesArea',
168 'member' => 'MembersCategoriesArea',
169 'contact' => 'ContactsCategoriesArea',
170 'user' => 'UsersCategoriesArea',
171 'account' => 'AccountsCategoriesArea', // old for bank account
172 'bank_account' => 'AccountsCategoriesArea',
173 'project' => 'ProjectsCategoriesArea',
174 'warehouse' => 'StocksCategoriesArea',
175 'actioncomm' => 'ActioncommCategoriesArea',
176 'website_page' => 'WebsitePageCategoriesArea',
177 'ticket' => 'TicketCategoriesArea',
178 'knowledgemanagement' => 'KnowledgemanagementCategoriesArea'
179 );
180
185 public $MAP_OBJ_TABLE = array(
186 'customer' => 'societe',
187 'supplier' => 'societe',
188 'member' => 'adherent',
189 'contact' => 'socpeople',
190 'account' => 'bank_account', // old for bank account
191 'project' => 'projet',
192 'warehouse' => 'entrepot',
193 'knowledgemanagement' => 'knowledgemanagement_knowledgerecord'
194 );
195
199 public $element = 'category';
200
204 public $table_element = 'categorie';
205
209 public $fk_parent;
210
214 public $label;
215
219 public $description;
220
224 public $color;
225
229 public $position;
230
234 public $visible;
235
239 public $socid;
240
258 public $type;
259
263 public $cats = array();
264
268 public $motherof = array();
269
273 public $childs = array();
274
278 public $multilangs = array();
279
283 public $imgWidth;
284
288 public $imgHeight;
289
290 public $fields = array(
291 "rowid" => array("type" => "integer", "label" => "TechnicalID", "enabled" => "1", 'position' => 10, 'notnull' => 1, "visible" => "-1",),
292 "fk_parent" => array("type" => "integer", "label" => "Fkparent", "enabled" => "1", 'position' => 20, 'notnull' => 1, "visible" => "-1", "css" => "maxwidth500 widthcentpercentminusxx",),
293 "label" => array("type" => "varchar(180)", "label" => "Label", "enabled" => "1", 'position' => 25, 'notnull' => 1, "visible" => "-1", "alwayseditable" => "1", "css" => "minwidth300", "cssview" => "wordbreak", "csslist" => "tdoverflowmax150",),
294 "ref_ext" => array("type" => "varchar(255)", "label" => "Refext", "enabled" => "1", 'position' => 30, 'notnull' => 0, "visible" => "0", "alwayseditable" => "1",),
295 "type" => array("type" => "integer", "label" => "Type", "enabled" => "1", 'position' => 35, 'notnull' => 1, "visible" => "-1", "alwayseditable" => "1",),
296 "description" => array("type" => "text", "label" => "Description", "enabled" => "1", 'position' => 40, 'notnull' => 0, "visible" => "-1", "alwayseditable" => "1",),
297 "color" => array("type" => "varchar(8)", "label" => "Color", "enabled" => "1", 'position' => 45, 'notnull' => 0, "visible" => "-1", "alwayseditable" => "1",),
298 "position" => array("type" => "integer", "label" => "Position", "enabled" => "1", 'position' => 50, 'notnull' => 0, "visible" => "-1", "alwayseditable" => "1",),
299 "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",),
300 "visible" => array("type" => "integer", "label" => "Visible", "enabled" => "1", 'position' => 60, 'notnull' => 1, "visible" => "-1", "alwayseditable" => "1",),
301 "import_key" => array("type" => "varchar(14)", "label" => "ImportId", "enabled" => "1", 'position' => 900, 'notnull' => 0, "visible" => "-2", "alwayseditable" => "1",),
302 "date_creation" => array("type" => "datetime", "label" => "Datecreation", "enabled" => "1", 'position' => 70, 'notnull' => 0, "visible" => "-1", "alwayseditable" => "1",),
303 "tms" => array("type" => "timestamp", "label" => "DateModification", "enabled" => "1", 'position' => 75, 'notnull' => 1, "visible" => "-1", "alwayseditable" => "1",),
304 "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",),
305 "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",),
306 );
307
313 public function __construct($db)
314 {
315 global $hookmanager;
316
317 $this->db = $db;
318
319 if (is_object($hookmanager)) {
320 $hookmanager->initHooks(array('category'));
321 $parameters = array();
322 $reshook = $hookmanager->executeHooks('constructCategory', $parameters, $this); // Note that $action and $object may have been modified by some hooks
323 if ($reshook >= 0 && !empty($hookmanager->resArray)) {
324 foreach ($hookmanager->resArray as $mapList) {
325 $mapId = $mapList['id'];
326 $mapCode = $mapList['code'];
327 self::$MAP_ID_TO_CODE[$mapId] = $mapCode;
328 $this->MAP_ID[$mapCode] = $mapId;
329 $this->MAP_CAT_FK[$mapCode] = isset($mapList['cat_fk']) ? $mapList['cat_fk'] : null;
330 $this->MAP_CAT_TABLE[$mapCode] = isset($mapList['cat_table']) ? $mapList['cat_table'] : null;
331 $this->MAP_OBJ_CLASS[$mapCode] = $mapList['obj_class'];
332 $this->MAP_OBJ_TABLE[$mapCode] = $mapList['obj_table'];
333 }
334 }
335 }
336 }
337
343 public function getMapList()
344 {
345 $mapList = array();
346
347 foreach ($this->MAP_ID as $mapCode => $mapId) {
348 $mapList[] = array(
349 'id' => $mapId,
350 'code' => $mapCode,
351 'cat_fk' => (empty($this->MAP_CAT_FK[$mapCode]) ? $mapCode : $this->MAP_CAT_FK[$mapCode]),
352 'cat_table' => (empty($this->MAP_CAT_TABLE[$mapCode]) ? $mapCode : $this->MAP_CAT_TABLE[$mapCode]),
353 'obj_class' => (empty($this->MAP_OBJ_CLASS[$mapCode]) ? $mapCode : $this->MAP_OBJ_CLASS[$mapCode]),
354 'obj_table' => (empty($this->MAP_OBJ_TABLE[$mapCode]) ? $mapCode : $this->MAP_OBJ_TABLE[$mapCode])
355 );
356 }
357
358 return $mapList;
359 }
360
366 public function getMapId()
367 {
368 return $this->MAP_ID;
369 }
370
380 public function fetch($id, $label = '', $type = null, $ref_ext = '')
381 {
382 // Check parameters
383 if (empty($id) && empty($label) && empty($ref_ext)) {
384 $this->error = "No category to search for";
385 return -1;
386 }
387 if (!is_null($type) && !is_numeric($type)) {
388 $type = $this->MAP_ID[$type];
389 }
390
391 $sql = "SELECT rowid, fk_parent, entity, label, description, color, position, fk_soc, visible, type, ref_ext";
392 $sql .= ", date_creation, tms, fk_user_creat, fk_user_modif";
393 $sql .= " FROM ".MAIN_DB_PREFIX."categorie";
394 if ($id) {
395 $sql .= " WHERE rowid = ".((int) $id);
396 } elseif (!empty($ref_ext)) {
397 $sql .= " WHERE ref_ext LIKE '".$this->db->escape($ref_ext)."'";
398 } else {
399 $sql .= " WHERE label = '".$this->db->escape($label)."' AND entity IN (".getEntity('category').")";
400 if (!is_null($type)) {
401 $sql .= " AND type = ".((int) $type);
402 }
403 }
404
405 dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
406 $resql = $this->db->query($sql);
407 if ($resql) {
408 if ($this->db->num_rows($resql) > 0 && $res = $this->db->fetch_array($resql)) {
409 $this->id = $res['rowid'];
410 //$this->ref = $res['rowid'];
411 $this->fk_parent = (int) $res['fk_parent'];
412 $this->label = $res['label'];
413 $this->description = $res['description'];
414 $this->color = $res['color'];
415 $this->position = $res['position'];
416 $this->socid = (int) $res['fk_soc'];
417 $this->visible = (int) $res['visible'];
418 $this->type = $res['type'];
419 $this->ref_ext = $res['ref_ext'];
420 $this->entity = (int) $res['entity'];
421 $this->date_creation = $this->db->jdate($res['date_creation']);
422 $this->date_modification = $this->db->jdate($res['tms']);
423 $this->user_creation_id = (int) $res['fk_user_creat'];
424 $this->user_modification_id = (int) $res['fk_user_modif'];
425
426 // Retrieve all extrafield
427 // fetch optionals attributes and labels
428 $this->fetch_optionals();
429
430 $this->db->free($resql);
431
432 // multilangs
433 if (getDolGlobalInt('MAIN_MULTILANGS')) {
434 $this->getMultiLangs();
435 }
436
437 return 1;
438 } else {
439 $this->error = "No category found";
440 return 0;
441 }
442 } else {
443 dol_print_error($this->db);
444 $this->error = $this->db->lasterror;
445 $this->errors[] = $this->db->lasterror;
446 return -1;
447 }
448 }
449
460 public function create($user, $notrigger = 0)
461 {
462 global $conf, $langs;
463 $langs->load('categories');
464
465 $type = $this->type;
466
467 if (!is_numeric($type)) {
468 $type = $this->MAP_ID[$type];
469 }
470
471 $error = 0;
472
473 dol_syslog(get_class($this).'::create', LOG_DEBUG);
474
475 // Clean parameters
476 $this->label = trim($this->label);
477 $this->description = trim($this->description);
478 $this->color = trim($this->color);
479 $this->position = (int) $this->position;
480 $this->import_key = trim($this->import_key);
481 $this->ref_ext = trim($this->ref_ext);
482 if (empty($this->visible)) {
483 $this->visible = 0;
484 }
485 $this->fk_parent = ($this->fk_parent != "" ? intval($this->fk_parent) : 0);
486
487 if ($this->already_exists()) {
488 $this->error = $langs->trans("ImpossibleAddCat", $this->label);
489 $this->error .= " : ".$langs->trans("CategoryExistsAtSameLevel");
490 dol_syslog($this->error, LOG_WARNING);
491 return -4;
492 }
493
494 $this->db->begin();
495 $now = dol_now();
496 $sql = "INSERT INTO ".MAIN_DB_PREFIX."categorie (";
497 $sql .= "fk_parent,";
498 $sql .= " label,";
499 $sql .= " description,";
500 $sql .= " color,";
501 $sql .= " position,";
502 if (getDolGlobalString('CATEGORY_ASSIGNED_TO_A_CUSTOMER')) {
503 $sql .= "fk_soc,";
504 }
505 $sql .= " visible,";
506 $sql .= " type,";
507 $sql .= " import_key,";
508 $sql .= " ref_ext,";
509 $sql .= " entity,";
510 $sql .= " date_creation,";
511 $sql .= " fk_user_creat";
512 $sql .= ") VALUES (";
513 $sql .= (int) $this->fk_parent.",";
514 $sql .= "'".$this->db->escape($this->label)."', ";
515 $sql .= "'".$this->db->escape($this->description)."', ";
516 $sql .= "'".$this->db->escape($this->color)."', ";
517 $sql .= (int) $this->position.",";
518 if (getDolGlobalString('CATEGORY_ASSIGNED_TO_A_CUSTOMER')) {
519 $sql .= ($this->socid > 0 ? $this->socid : 'null').", ";
520 }
521 $sql .= "'".$this->db->escape($this->visible)."', ";
522 $sql .= ((int) $type).", ";
523 $sql .= (!empty($this->import_key) ? "'".$this->db->escape($this->import_key)."'" : 'null').", ";
524 $sql .= (!empty($this->ref_ext) ? "'".$this->db->escape($this->ref_ext)."'" : 'null').", ";
525 $sql .= (int) $conf->entity.", ";
526 $sql .= "'".$this->db->idate($now)."', ";
527 $sql .= (int) $user->id;
528 $sql .= ")";
529
530 $res = $this->db->query($sql);
531 if ($res) {
532 $id = $this->db->last_insert_id(MAIN_DB_PREFIX."categorie");
533
534 if ($id > 0) {
535 $this->id = $id;
536
537 $action = 'create';
538
539 // Actions on extra fields
540 if (!$error) {
541 $result = $this->insertExtraFields();
542 if ($result < 0) {
543 $error++;
544 }
545 }
546
547 if (!$error && !$notrigger) {
548 // Call trigger
549 $result = $this->call_trigger('CATEGORY_CREATE', $user);
550 if ($result < 0) {
551 $error++;
552 }
553 // End call triggers
554 }
555
556 if (!$error) {
557 $this->db->commit();
558 return $id;
559 } else {
560 $this->db->rollback();
561 return -3;
562 }
563 } else {
564 $this->db->rollback();
565 return -2;
566 }
567 } else {
568 $this->error = $this->db->error();
569 $this->db->rollback();
570 return -1;
571 }
572 }
573
583 public function update(User $user, $notrigger = 0)
584 {
585 global $langs;
586
587 $error = 0;
588
589 // Clean parameters
590 $this->label = trim($this->label);
591 $this->description = trim($this->description);
592 $this->ref_ext = trim($this->ref_ext);
593 $this->fk_parent = ($this->fk_parent != "" ? intval($this->fk_parent) : 0);
594 $this->visible = ($this->visible != "" ? intval($this->visible) : 0);
595
596 if ($this->already_exists()) {
597 $this->error = $langs->trans("ImpossibleUpdateCat");
598 $this->error .= " : ".$langs->trans("CategoryExistsAtSameLevel");
599 return -1;
600 }
601
602 $this->db->begin();
603
604 $sql = "UPDATE ".MAIN_DB_PREFIX."categorie";
605 $sql .= " SET label = '".$this->db->escape($this->label)."',";
606 $sql .= " description = '".$this->db->escape($this->description)."',";
607 $sql .= " ref_ext = '".$this->db->escape($this->ref_ext)."',";
608 $sql .= " color = '".$this->db->escape($this->color)."'";
609 $sql .= ", position = ".(int) $this->position;
610 if (getDolGlobalString('CATEGORY_ASSIGNED_TO_A_CUSTOMER')) {
611 $sql .= ", fk_soc = ".($this->socid > 0 ? $this->socid : 'null');
612 }
613 $sql .= ", visible = ".(int) $this->visible;
614 $sql .= ", fk_parent = ".(int) $this->fk_parent;
615 $sql .= ", fk_user_modif = ".(int) $user->id;
616 $sql .= " WHERE rowid = ".((int) $this->id);
617
618 dol_syslog(get_class($this)."::update", LOG_DEBUG);
619 if ($this->db->query($sql)) {
620 $action = 'update';
621
622 // Actions on extra fields
623 if (!$error) {
624 $result = $this->insertExtraFields();
625 if ($result < 0) {
626 $error++;
627 }
628 }
629
630 if (!$error && !$notrigger) {
631 // Call trigger
632 $result = $this->call_trigger('CATEGORY_MODIFY', $user);
633 if ($result < 0) {
634 $error++;
635 }
636 // End call triggers
637 }
638
639 if (!$error) {
640 $this->db->commit();
641 return 1;
642 } else {
643 $this->db->rollback();
644 return -1;
645 }
646 } else {
647 $this->db->rollback();
648 dol_print_error($this->db);
649 return -1;
650 }
651 }
652
660 public function delete($user, $notrigger = 0)
661 {
662 $error = 0;
663
664 // Clean parameters
665 $this->fk_parent = ($this->fk_parent != "" ? intval($this->fk_parent) : 0);
666
667 dol_syslog(get_class($this)."::remove");
668
669 $this->db->begin();
670
671 if (!$error && !$notrigger) {
672 // Call trigger
673 $result = $this->call_trigger('CATEGORY_DELETE', $user);
674 if ($result < 0) {
675 $error++;
676 }
677 // End call triggers
678 }
679
680 /* FIX #1317 : Check for child category and move up 1 level*/
681 if (!$error) {
682 $sql = "UPDATE ".MAIN_DB_PREFIX."categorie";
683 $sql .= " SET fk_parent = ".((int) $this->fk_parent);
684 $sql .= " WHERE fk_parent = ".((int) $this->id);
685
686 if (!$this->db->query($sql)) {
687 $this->error = $this->db->lasterror();
688 $error++;
689 }
690 }
691
692 $arraydelete = array(
693 'categorie_account' => 'fk_categorie',
694 'categorie_actioncomm' => 'fk_categorie',
695 'categorie_contact' => 'fk_categorie',
696 'categorie_fournisseur' => 'fk_categorie',
697 'categorie_knowledgemanagement' => array('field' => 'fk_categorie', 'enabled' => isModEnabled('knowledgemanagement')),
698 'categorie_member' => 'fk_categorie',
699 'categorie_user' => 'fk_categorie',
700 'categorie_product' => 'fk_categorie',
701 'categorie_project' => 'fk_categorie',
702 'categorie_societe' => 'fk_categorie',
703 'categorie_ticket' => array('field' => 'fk_categorie', 'enabled' => isModEnabled('ticket')),
704 'categorie_warehouse' => 'fk_categorie',
705 'categorie_website_page' => array('field' => 'fk_categorie', 'enabled' => isModEnabled('website')),
706 'category_bankline' => 'fk_categ',
707 'categorie_lang' => 'fk_category',
708 'categorie' => 'rowid',
709 );
710 foreach ($arraydelete as $key => $value) {
711 if (is_array($value)) {
712 if (empty($value['enabled'])) {
713 continue;
714 }
715 $value = $value['field'];
716 }
717 $sql = "DELETE FROM ".MAIN_DB_PREFIX.$key;
718 $sql .= " WHERE ".$value." = ".((int) $this->id);
719 if (!$this->db->query($sql)) {
720 $this->errors[] = $this->db->lasterror();
721 dol_syslog("Error sql=".$sql." ".$this->error, LOG_ERR);
722 $error++;
723 }
724 }
725
726 // Removed extrafields
727 if (!$error) {
728 $result = $this->deleteExtraFields();
729 if ($result < 0) {
730 $error++;
731 dol_syslog(get_class($this)."::delete erreur ".$this->error, LOG_ERR);
732 }
733 }
734
735 if (!$error) {
736 $this->db->commit();
737 return 1;
738 } else {
739 $this->db->rollback();
740 return -1;
741 }
742 }
743
744 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
753 public function add_type($obj, $type = '')
754 {
755 // phpcs:enable
756 global $user;
757
758 $error = 0;
759
760 if ($this->id == -1) {
761 return -2;
762 }
763
764 if (empty($type)) {
765 $type = $obj->element;
766 }
767
768 dol_syslog(get_class($this).'::add_type', LOG_DEBUG);
769
770 $this->db->begin();
771
772 $sql = "INSERT INTO ".MAIN_DB_PREFIX."categorie_".(empty($this->MAP_CAT_TABLE[$type]) ? $type : $this->MAP_CAT_TABLE[$type]);
773 $sql .= " (fk_categorie, fk_".(empty($this->MAP_CAT_FK[$type]) ? $type : $this->MAP_CAT_FK[$type]).")";
774 $sql .= " VALUES (".((int) $this->id).", ".((int) $obj->id).")";
775
776 if ($this->db->query($sql)) {
777 if (getDolGlobalString('CATEGORIE_RECURSIV_ADD')) {
778 $sql = 'SELECT fk_parent FROM '.MAIN_DB_PREFIX.'categorie';
779 $sql .= " WHERE rowid = ".((int) $this->id);
780
781 dol_syslog(get_class($this)."::add_type", LOG_DEBUG);
782 $resql = $this->db->query($sql);
783 if ($resql) {
784 if ($this->db->num_rows($resql) > 0) {
785 $objparent = $this->db->fetch_object($resql);
786
787 if (!empty($objparent->fk_parent)) {
788 $cat = new Categorie($this->db);
789 $cat->id = $objparent->fk_parent;
790 if (!$cat->containsObject($type, $obj->id)) {
791 $result = $cat->add_type($obj, $type);
792 if ($result < 0) {
793 $this->error = $cat->error;
794 $error++;
795 }
796 }
797 }
798 }
799 } else {
800 $error++;
801 $this->error = $this->db->lasterror();
802 }
803
804 if ($error) {
805 $this->db->rollback();
806 return -1;
807 }
808 }
809
810 // Call trigger
811 $this->context = array('linkto' => $obj); // Save object we want to link category to into category instance to provide information to trigger
812 $result = $this->call_trigger('CATEGORY_MODIFY', $user);
813 if ($result < 0) {
814 $error++;
815 }
816 // End call triggers
817
818 if (!$error) {
819 $this->db->commit();
820 return 1;
821 } else {
822 $this->db->rollback();
823 return -2;
824 }
825 } else {
826 $this->db->rollback();
827 if ($this->db->lasterrno() == 'DB_ERROR_RECORD_ALREADY_EXISTS') {
828 $this->error = $this->db->lasterrno();
829 return -3;
830 } else {
831 $this->error = $this->db->lasterror();
832 }
833 return -1;
834 }
835 }
836
837 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
846 public function del_type($obj, $type)
847 {
848 // phpcs:enable
849 global $user;
850
851 $error = 0;
852
853 // For backward compatibility
854 if ($type == 'societe') {
855 $type = 'customer';
856 dol_syslog(get_class($this)."::del_type(): type 'societe' is deprecated, please use 'customer' instead", LOG_WARNING);
857 } elseif ($type == 'fournisseur') {
858 $type = 'supplier';
859 dol_syslog(get_class($this)."::del_type(): type 'fournisseur' is deprecated, please use 'supplier' instead", LOG_WARNING);
860 }
861
862 $this->db->begin();
863
864 $sql = "DELETE FROM ".MAIN_DB_PREFIX."categorie_".(empty($this->MAP_CAT_TABLE[$type]) ? $type : $this->MAP_CAT_TABLE[$type]);
865 $sql .= " WHERE fk_categorie = ".((int) $this->id);
866 $sql .= " AND fk_".(empty($this->MAP_CAT_FK[$type]) ? $type : $this->MAP_CAT_FK[$type])." = ".((int) $obj->id);
867
868 dol_syslog(get_class($this).'::del_type', LOG_DEBUG);
869 if ($this->db->query($sql)) {
870 // Call trigger
871 $this->context = array('unlinkoff' => $obj); // Save object we want to link category to into category instance to provide information to trigger
872 $result = $this->call_trigger('CATEGORY_MODIFY', $user);
873 if ($result < 0) {
874 $error++;
875 }
876 // End call triggers
877
878 if (!$error) {
879 $this->db->commit();
880 return 1;
881 } else {
882 $this->db->rollback();
883 return -2;
884 }
885 } else {
886 $this->db->rollback();
887 $this->error = $this->db->lasterror();
888 return -1;
889 }
890 }
891
909 public function getObjectsInCateg($type, $onlyids = 0, $limit = 0, $offset = 0, $sortfield = '', $sortorder = 'ASC', $filter = '', $filtermode = 'AND', $filterlang = '')
910 {
911 global $user;
912
913 $objs = array();
914
915 $classnameforobj = $this->MAP_OBJ_CLASS[$type];
916 $obj = new $classnameforobj($this->db);
917
918 $sql = "SELECT c.fk_".(empty($this->MAP_CAT_FK[$type]) ? $type : $this->MAP_CAT_FK[$type])." as fk_object";
919 $sql .= " FROM ".MAIN_DB_PREFIX."categorie_".(empty($this->MAP_CAT_TABLE[$type]) ? $type : $this->MAP_CAT_TABLE[$type])." as c";
920 $sql .= ", ".MAIN_DB_PREFIX.(empty($this->MAP_OBJ_TABLE[$type]) ? $type : $this->MAP_OBJ_TABLE[$type])." as o";
921 if (!empty($filterlang)) {
922 $sql .= ", ".MAIN_DB_PREFIX.(empty($this->MAP_OBJ_TABLE[$type]) ? $type : $this->MAP_OBJ_TABLE[$type])."_lang as ol";
923 }
924 $sql .= " WHERE o.entity IN (".getEntity($obj->element).")";
925 $sql .= " AND c.fk_categorie = ".((int) $this->id);
926 // Compatibility with actioncomm table which has id instead of rowid
927 if ((array_key_exists($type, $this->MAP_OBJ_TABLE) && $this->MAP_OBJ_TABLE[$type] == "actioncomm") || $type == "actioncomm") {
928 $sql .= " AND c.fk_".(empty($this->MAP_CAT_FK[$type]) ? $type : $this->MAP_CAT_FK[$type])." = o.id";
929 } else {
930 $sql .= " AND c.fk_".(empty($this->MAP_CAT_FK[$type]) ? $type : $this->MAP_CAT_FK[$type])." = o.rowid";
931 }
932 if (!empty($filterlang)) {
933 $sql .= " AND ol.fk_".(empty($this->MAP_OBJ_TABLE[$type]) ? $type : $this->MAP_OBJ_TABLE[$type])." = o.rowid";
934 $sql .= " AND ol.lang = '".$this->db->escape($filterlang)."'";
935 }
936 // Protection for external users
937 if (($type == 'customer' || $type == 'supplier') && $user->socid > 0) {
938 $sql .= " AND o.rowid = ".((int) $user->socid);
939 }
940
941 $errormessage = '';
942 $sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage);
943 if ($errormessage) {
944 $this->errors[] = $errormessage;
945 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
946 return -1;
947 }
948
949 $sql .= $this->db->order($sortfield, $sortorder);
950 if ($limit > 0 || $offset > 0) {
951 $sql .= $this->db->plimit($limit + 1, $offset);
952 }
953
954 dol_syslog(get_class($this)."::getObjectsInCateg", LOG_DEBUG);
955
956 $resql = $this->db->query($sql);
957 if ($resql) {
958 while ($rec = $this->db->fetch_array($resql)) {
959 if ($onlyids) {
960 $objs[] = $rec['fk_object'];
961 } else {
962 $classnameforobj = $this->MAP_OBJ_CLASS[$type];
963
964 $obj = new $classnameforobj($this->db);
965 $obj->fetch($rec['fk_object']);
966 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.
967 $objs[] = $obj;
968 }
969 }
970 }
971 return $objs;
972 } else {
973 $this->error = $this->db->error().' sql='.$sql;
974 return -1;
975 }
976 }
977
986 public function containsObject($type, $object_id)
987 {
988 $sql = "SELECT COUNT(*) as nb FROM ".MAIN_DB_PREFIX."categorie_".(empty($this->MAP_CAT_TABLE[$type]) ? $type : $this->MAP_CAT_TABLE[$type]);
989 $sql .= " WHERE fk_categorie = ".((int) $this->id)." AND fk_".(empty($this->MAP_CAT_FK[$type]) ? $type : $this->MAP_CAT_FK[$type])." = ".((int) $object_id);
990
991 dol_syslog(get_class($this)."::containsObject", LOG_DEBUG);
992
993 $resql = $this->db->query($sql);
994 if ($resql) {
995 return $this->db->fetch_object($resql)->nb;
996 } else {
997 $this->error = $this->db->error();
998 return -1;
999 }
1000 }
1001
1013 public function getListForItem($id, $type = 'customer', $sortfield = "s.rowid", $sortorder = 'ASC', $limit = 0, $page = 0)
1014 {
1015 $categories = array();
1016
1017 $type = sanitizeVal($type, 'aZ09');
1018
1019 $sub_type = $type;
1020 $subcol_name = "fk_".$type;
1021 if ($type == "customer") {
1022 $sub_type = "societe";
1023 $subcol_name = "fk_soc";
1024 }
1025 if ($type == "supplier") {
1026 $sub_type = "fournisseur";
1027 $subcol_name = "fk_soc";
1028 }
1029 if ($type == "contact") {
1030 $subcol_name = "fk_socpeople";
1031 }
1032
1033 $idoftype = array_search($type, self::$MAP_ID_TO_CODE);
1034
1035 $sql = "SELECT s.rowid";
1036 $sql .= " FROM ".MAIN_DB_PREFIX."categorie as s, ".MAIN_DB_PREFIX."categorie_".$sub_type." as sub";
1037 $sql .= ' WHERE s.entity IN ('.getEntity('category').')';
1038 $sql .= ' AND s.type='.((int) $idoftype);
1039 $sql .= ' AND s.rowid = sub.fk_categorie';
1040 $sql .= " AND sub.".$subcol_name." = ".((int) $id);
1041
1042 $sql .= $this->db->order($sortfield, $sortorder);
1043
1044 $offset = 0;
1045 $nbtotalofrecords = '';
1046 if (!getDolGlobalInt('MAIN_DISABLE_FULL_SCANLIST')) {
1047 $result = $this->db->query($sql);
1048 $nbtotalofrecords = $this->db->num_rows($result);
1049 if (($page * $limit) > $nbtotalofrecords) { // if total resultset is smaller then paging size (filtering), goto and load page 0
1050 $page = 0;
1051 $offset = 0;
1052 }
1053 }
1054
1055 if ($limit) {
1056 if ($page < 0) {
1057 $page = 0;
1058 }
1059 $offset = $limit * $page;
1060
1061 $sql .= $this->db->plimit($limit + 1, $offset);
1062 }
1063
1064 $result = $this->db->query($sql);
1065 if ($result) {
1066 $i = 0;
1067 $num = $this->db->num_rows($result);
1068 $min = min($num, ($limit <= 0 ? $num : $limit));
1069 while ($i < $min) {
1070 $obj = $this->db->fetch_object($result);
1071 $category_static = new Categorie($this->db);
1072 if ($category_static->fetch($obj->rowid)) {
1073 $categories[$i]['id'] = $category_static->id;
1074 $categories[$i]['fk_parent'] = $category_static->fk_parent;
1075 $categories[$i]['label'] = $category_static->label;
1076 $categories[$i]['description'] = $category_static->description;
1077 $categories[$i]['color'] = $category_static->color;
1078 $categories[$i]['position'] = $category_static->position;
1079 $categories[$i]['socid'] = $category_static->socid;
1080 $categories[$i]['ref_ext'] = $category_static->ref_ext;
1081 $categories[$i]['visible'] = $category_static->visible;
1082 $categories[$i]['type'] = $category_static->type;
1083 $categories[$i]['entity'] = $category_static->entity;
1084 $categories[$i]['array_options'] = $category_static->array_options;
1085
1086 // multilangs
1087 if (getDolGlobalInt('MAIN_MULTILANGS') && isset($category_static->multilangs)) {
1088 $categories[$i]['multilangs'] = $category_static->multilangs;
1089 }
1090 }
1091 $i++;
1092 }
1093 } else {
1094 $this->error = $this->db->lasterror();
1095 return -1;
1096 }
1097 if (!count($categories)) {
1098 return 0;
1099 }
1100
1101 return $categories;
1102 }
1103
1104 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1110 public function get_filles()
1111 {
1112 // phpcs:enable
1113 $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."categorie";
1114 $sql .= " WHERE fk_parent = ".((int) $this->id);
1115 $sql .= " AND entity IN (".getEntity('category').")";
1116
1117 $res = $this->db->query($sql);
1118 if ($res) {
1119 $cats = array();
1120 while ($rec = $this->db->fetch_array($res)) {
1121 $cat = new Categorie($this->db);
1122 $cat->fetch($rec['rowid']);
1123 $cats[] = $cat;
1124 }
1125 return $cats;
1126 } else {
1127 dol_print_error($this->db);
1128 return -1;
1129 }
1130 }
1131
1132 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1138 protected function load_motherof()
1139 {
1140 // phpcs:enable
1141 $this->motherof = array();
1142
1143 // Load array[child]=parent
1144 $sql = "SELECT fk_parent as id_parent, rowid as id_son";
1145 $sql .= " FROM ".MAIN_DB_PREFIX."categorie";
1146 $sql .= " WHERE fk_parent != 0";
1147 $sql .= " AND entity IN (".getEntity('category').")";
1148
1149 dol_syslog(get_class($this)."::load_motherof", LOG_DEBUG);
1150 $resql = $this->db->query($sql);
1151 if ($resql) {
1152 while ($obj = $this->db->fetch_object($resql)) {
1153 $this->motherof[$obj->id_son] = $obj->id_parent;
1154 }
1155 return 1;
1156 } else {
1157 dol_print_error($this->db);
1158 return -1;
1159 }
1160 }
1161
1162 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1182 public function get_full_arbo($type, $fromid = 0, $include = 0)
1183 {
1184 // phpcs:enable
1185 global $langs;
1186
1187 if (!is_numeric($type)) {
1188 $type = $this->MAP_ID[$type];
1189 }
1190 if (is_null($type)) {
1191 $this->error = 'BadValueForParameterType';
1192 return -1;
1193 }
1194
1195 if (is_string($fromid)) {
1196 $fromid = explode(',', $fromid);
1197 } elseif (is_numeric($fromid)) {
1198 if ($fromid > 0) {
1199 $fromid = array($fromid);
1200 } else {
1201 $fromid = array();
1202 }
1203 } elseif (!is_array($fromid)) {
1204 $fromid = array();
1205 }
1206
1207 $this->cats = array();
1208 $nbcateg = 0;
1209
1210 // Init this->motherof that is array(id_son=>id_parent, ...)
1211 $this->load_motherof();
1212 $current_lang = $langs->getDefaultLang();
1213
1214 // Init $this->cats array
1215 $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
1216 if (getDolGlobalInt('MAIN_MULTILANGS')) {
1217 $sql .= ", t.label as label_trans, t.description as description_trans";
1218 }
1219 $sql .= " FROM ".MAIN_DB_PREFIX."categorie as c";
1220 if (getDolGlobalInt('MAIN_MULTILANGS')) {
1221 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."categorie_lang as t ON t.fk_category=c.rowid AND t.lang='".$this->db->escape($current_lang)."'";
1222 }
1223 $sql .= " WHERE c.entity IN (".getEntity('category').")";
1224 $sql .= " AND c.type = ".(int) $type;
1225
1226 dol_syslog(get_class($this)."::get_full_arbo get category list", LOG_DEBUG);
1227 $resql = $this->db->query($sql);
1228 if ($resql) {
1229 $i = 0;
1230 $nbcateg = $this->db->num_rows($resql);
1231
1232 while ($obj = $this->db->fetch_object($resql)) {
1233 $this->cats[$obj->rowid]['rowid'] = $obj->rowid;
1234 $this->cats[$obj->rowid]['id'] = $obj->rowid;
1235 $this->cats[$obj->rowid]['fk_parent'] = $obj->fk_parent;
1236 $this->cats[$obj->rowid]['label'] = !empty($obj->label_trans) ? $obj->label_trans : $obj->label;
1237 $this->cats[$obj->rowid]['description'] = !empty($obj->description_trans) ? $obj->description_trans : $obj->description;
1238 $this->cats[$obj->rowid]['color'] = $obj->color;
1239 $this->cats[$obj->rowid]['position'] = $obj->position;
1240 $this->cats[$obj->rowid]['visible'] = $obj->visible;
1241 $this->cats[$obj->rowid]['ref_ext'] = $obj->ref_ext;
1242 $this->cats[$obj->rowid]['picto'] = 'category';
1243 // fields are filled with buildPathFromId
1244 $this->cats[$obj->rowid]['fullpath'] = '';
1245 $this->cats[$obj->rowid]['fulllabel'] = '';
1246 $i++;
1247 }
1248 } else {
1249 dol_print_error($this->db);
1250 return -1;
1251 }
1252
1253 // We add the fullpath property to each elements of first level (no parent exists)
1254 dol_syslog(get_class($this)."::get_full_arbo call to buildPathFromId", LOG_DEBUG);
1255 foreach ($this->cats as $key => $val) {
1256 //print 'key='.$key.'<br>'."\n";
1257 $this->buildPathFromId($key, $nbcateg); // Process a branch from the root category key (this category has no parent) and adds kevek to $this->cats items
1258 }
1259
1260 // Include or exclude leaf (including $fromid) from tree
1261 if (count($fromid) > 0) {
1262 $keyfiltercatid = '('.implode('|', $fromid).')';
1263
1264 //print "Look to discard category ".$fromid."\n";
1265 $keyfilter1 = '^'.$keyfiltercatid.'$';
1266 $keyfilter2 = '_'.$keyfiltercatid.'$';
1267 $keyfilter3 = '^'.$keyfiltercatid.'_';
1268 $keyfilter4 = '_'.$keyfiltercatid.'_';
1269 foreach (array_keys($this->cats) as $key) {
1270 $fullpath = (string) $this->cats[$key]['fullpath'];
1271 $test = (preg_match('/'.$keyfilter1.'/', $fullpath) || preg_match('/'.$keyfilter2.'/', $fullpath)
1272 || preg_match('/'.$keyfilter3.'/', $fullpath) || preg_match('/'.$keyfilter4.'/', $fullpath));
1273
1274 if (($test && !$include) || (!$test && $include)) {
1275 unset($this->cats[$key]); // @phpstan-ignore-line
1276 }
1277 }
1278 }
1279
1280 dol_syslog(get_class($this)."::get_full_arbo dol_sort_array", LOG_DEBUG);
1281
1282 $this->cats = dol_sort_array($this->cats, 'fulllabel', 'asc', 1, 0, 1); // Sort on full label like "Label 1 >> Sublabel a >> Subsublabel"
1283
1284 return $this->cats;
1285 }
1286
1297 private function buildPathFromId($id_categ, $protection = 1000)
1298 {
1299 //dol_syslog(get_class($this)."::buildPathFromId id_categ=".$id_categ." protection=".$protection, LOG_DEBUG);
1300
1301 if (!empty($this->cats[$id_categ]['fullpath'])) {
1302 // Already defined
1303 dol_syslog(get_class($this)."::buildPathFromId fullpath and fulllabel already defined", LOG_WARNING);
1304 return -1;
1305 }
1306
1307 // First build full array $motherof
1308 //$this->load_motherof(); // Disabled because already done by caller of buildPathFromId
1309
1310 // $this->cats[$id_categ] is supposed to be already an array. We just want to complete it with property fullpath and fulllabel
1311
1312 // Define fullpath and fulllabel
1313 $this->cats[$id_categ]['fullpath'] = '_'.$id_categ;
1314 $this->cats[$id_categ]['fulllabel'] = $this->cats[$id_categ]['label'];
1315 $i = 0;
1316 $cursor_categ = $id_categ;
1317 //print 'Work for id_categ='.$id_categ.'<br>'."\n";
1318 while ((empty($protection) || $i < $protection) && !empty($this->motherof[$cursor_categ])) {
1319 //print '&nbsp; cursor_categ='.$cursor_categ.' i='.$i.' '.$this->motherof[$cursor_categ].'<br>'."\n";
1320 $this->cats[$id_categ]['fullpath'] = '_'.$this->motherof[$cursor_categ].$this->cats[$id_categ]['fullpath'];
1321 $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'];
1322 //print '&nbsp; Result for id_categ='.$id_categ.' : '.$this->cats[$id_categ]['fullpath'].' '.$this->cats[$id_categ]['fulllabel'].'<br>'."\n";
1323 $i++;
1324 $cursor_categ = $this->motherof[$cursor_categ];
1325 }
1326 //print 'Result for id_categ='.$id_categ.' : '.$this->cats[$id_categ]['fullpath'].'<br>'."\n";
1327
1328 // We count number of _ to have level
1329 $nbunderscore = substr_count($this->cats[$id_categ]['fullpath'], '_');
1330 $this->cats[$id_categ]['level'] = ($nbunderscore ? $nbunderscore : null);
1331
1332 return 1;
1333 }
1334
1335
1336 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1344 public function get_all_categories($type = null, $parent = false)
1345 {
1346 // phpcs:enable
1347 if (!is_numeric($type) && !is_null($type)) {
1348 $type = $this->MAP_ID[$type];
1349 }
1350
1351 $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."categorie";
1352 $sql .= " WHERE entity IN (".getEntity('category').")";
1353 if (!is_null($type)) {
1354 $sql .= " AND type = ".(int) $type;
1355 }
1356 if ($parent) {
1357 $sql .= " AND fk_parent = 0";
1358 }
1359
1360 $res = $this->db->query($sql);
1361 if ($res) {
1362 $cats = array();
1363 while ($rec = $this->db->fetch_array($res)) {
1364 $cat = new Categorie($this->db);
1365 $cat->fetch($rec['rowid']);
1366 $cats[$rec['rowid']] = $cat;
1367 }
1368 return $cats;
1369 } else {
1370 dol_print_error($this->db);
1371 return -1;
1372 }
1373 }
1374
1375 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1382 public function get_main_categories($type = null)
1383 {
1384 // phpcs:enable
1385 return $this->get_all_categories($type, true);
1386 }
1387
1388 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1394 public function already_exists()
1395 {
1396 // phpcs:enable
1397 $type = $this->type;
1398
1399 if (!is_numeric($type)) {
1400 $type = $this->MAP_ID[$type];
1401 }
1402
1403 /* We have to select any rowid from llx_categorie which category's mother and label
1404 * are equals to those of the calling category
1405 */
1406 $sql = "SELECT c.rowid";
1407 $sql .= " FROM ".MAIN_DB_PREFIX."categorie as c ";
1408 $sql .= " WHERE c.entity IN (".getEntity('category').")";
1409 $sql .= " AND c.type = ".((int) $type);
1410 $sql .= " AND c.fk_parent = ".((int) $this->fk_parent);
1411 $sql .= " AND c.label = '".$this->db->escape($this->label)."'";
1412
1413 dol_syslog(get_class($this)."::already_exists", LOG_DEBUG);
1414
1415 $resql = $this->db->query($sql);
1416 if ($resql) {
1417 if ($this->db->num_rows($resql) > 0) { // Checking for empty resql
1418 $obj = $this->db->fetch_object($resql);
1419 /* If object called create, obj cannot have is id.
1420 * If object called update, he mustn't have the same label as an other category for this mother.
1421 * 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.
1422 */
1423 if (!empty($obj) && $obj->rowid > 0 && $obj->rowid != $this->id) {
1424 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);
1425 return 1;
1426 }
1427 }
1428 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);
1429 return 0;
1430 } else {
1431 $this->error = $this->db->error();
1432 return -1;
1433 }
1434 }
1435
1436
1437 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1448 public function print_all_ways($sep = '&gt;&gt;', $url = '', $nocolor = 0, $addpicto = 0)
1449 {
1450 // phpcs:enable
1451 $ways = array();
1452
1453 $all_ways = $this->get_all_ways(); // Load array of categories
1454 foreach ($all_ways as $way) {
1455 $w = array();
1456 $i = 0;
1457 $forced_color = '';
1458 foreach ($way as $cat) {
1459 $i++;
1460
1461 if (empty($nocolor)) {
1462 $forced_color = 'colortoreplace';
1463 if ($i == count($way)) { // Last category in hierarchy
1464 // Check contrast with background and correct text color
1465 $forced_color = 'categtextwhite';
1466 if ($cat->color) {
1467 if (colorIsLight($cat->color)) {
1468 $forced_color = 'categtextblack';
1469 }
1470 }
1471 }
1472 }
1473
1474 if ($url == '') {
1475 $link = '<a href="'.DOL_URL_ROOT.'/categories/viewcat.php?id='.$cat->id.'&type='.$cat->type.'" class="'.$forced_color.'">';
1476 $linkend = '</a>';
1477 $w[] = $link.(($addpicto && $i == 1) ? img_object('', 'category', 'class="paddingright"') : '').$cat->label.$linkend;
1478 } elseif ($url == 'none') {
1479 $link = '<span class="'.$forced_color.'">';
1480 $linkend = '</span>';
1481 $w[] = $link.(($addpicto && $i == 1) ? img_object('', 'category', 'class="paddingright"') : '').$cat->label.$linkend;
1482 } else {
1483 $w[] = '<a class="'.$forced_color.'" href="'.DOL_URL_ROOT.'/'.$url.'?catid='.$cat->id.'">'.($addpicto ? img_object('', 'category') : '').$cat->label.'</a>';
1484 }
1485 }
1486 $newcategwithpath = preg_replace('/colortoreplace/', $forced_color, implode('<span class="inline-block valignmiddle paddingleft paddingright '.$forced_color.'">'.$sep.'</span>', $w));
1487
1488 $ways[] = $newcategwithpath;
1489 }
1490
1491 return $ways;
1492 }
1493
1494
1495 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1501 public function get_meres()
1502 {
1503 // phpcs:enable
1504 $parents = array();
1505
1506 $sql = "SELECT fk_parent FROM ".MAIN_DB_PREFIX."categorie";
1507 $sql .= " WHERE rowid = ".((int) $this->id);
1508
1509 $res = $this->db->query($sql);
1510
1511 if ($res) {
1512 while ($rec = $this->db->fetch_array($res)) {
1513 if ($rec['fk_parent'] > 0) {
1514 $cat = new Categorie($this->db);
1515 $cat->fetch($rec['fk_parent']);
1516 $parents[] = $cat;
1517 }
1518 }
1519 return $parents;
1520 } else {
1521 dol_print_error($this->db);
1522 return -1;
1523 }
1524 }
1525
1526 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1533 public function get_all_ways()
1534 {
1535 // phpcs:enable
1536 $ways = array();
1537
1538 $parents = $this->get_meres();
1539 if (is_array($parents)) {
1540 foreach ($parents as $parent) {
1541 $all_ways = $parent->get_all_ways();
1542 foreach ($all_ways as $way) {
1543 $w = $way;
1544 $w[] = $this;
1545 $ways[] = $w;
1546 }
1547 }
1548 }
1549
1550 if (count($ways) == 0) {
1551 $ways[0][0] = $this;
1552 }
1553
1554 return $ways;
1555 }
1556
1567 public function containing($id, $type, $mode = 'object')
1568 {
1569 $cats = array();
1570
1571 if (is_numeric($type)) {
1572 $type = Categorie::$MAP_ID_TO_CODE[$type];
1573 }
1574
1575 if ($type === Categorie::TYPE_BANK_LINE) { // TODO Remove this after migration of llx_category_bankline into llx_categorie_bankline
1576 // Load bank categories
1577 $sql = "SELECT c.label, c.rowid";
1578 $sql .= " FROM ".MAIN_DB_PREFIX."category_bankline as a, ".MAIN_DB_PREFIX."categorie as c";
1579 $sql .= " WHERE a.lineid=".((int) $id)." AND a.fk_categ = c.rowid";
1580 $sql .= " AND c.entity IN (".getEntity('category').")";
1581 $sql .= " ORDER BY c.label";
1582
1583 $res = $this->db->query($sql);
1584 if ($res) {
1585 while ($obj = $this->db->fetch_object($res)) {
1586 if ($mode == 'id') {
1587 $cats[] = $obj->rowid;
1588 } elseif ($mode == 'label') {
1589 $cats[] = $obj->label;
1590 } else {
1591 $cat = new Categorie($this->db);
1592 $cat->id = $obj->rowid;
1593 $cat->label = $obj->label;
1594 $cats[] = $cat;
1595 }
1596 }
1597 } else {
1598 dol_print_error($this->db);
1599 return -1;
1600 }
1601 } else {
1602 $sql = "SELECT ct.fk_categorie, c.label, c.rowid";
1603 $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";
1604 $sql .= " WHERE ct.fk_categorie = c.rowid AND ct.fk_".(empty($this->MAP_CAT_FK[$type]) ? $type : $this->MAP_CAT_FK[$type])." = ".(int) $id;
1605 // This seems useless because the table already contains id of category of 1 unique type. So commented.
1606 // So now it works also with external added categories.
1607 //$sql .= " AND c.type = ".((int) $this->MAP_ID[$type]);
1608 $sql .= " AND c.entity IN (".getEntity('category').")";
1609
1610 $res = $this->db->query($sql);
1611 if ($res) {
1612 while ($obj = $this->db->fetch_object($res)) {
1613 if ($mode == 'id') {
1614 $cats[] = $obj->rowid;
1615 } elseif ($mode == 'label') {
1616 $cats[] = $obj->label;
1617 } else {
1618 $cat = new Categorie($this->db);
1619 $cat->fetch($obj->fk_categorie);
1620 $cats[] = $cat;
1621 }
1622 }
1623 } else {
1624 dol_print_error($this->db);
1625 return -1;
1626 }
1627 }
1628
1629 return $cats;
1630 }
1631
1643 public function rechercher($id, $nom, $type, $exact = false, $case = false)
1644 {
1645 // Deprecation warning
1646 if (is_numeric($type)) {
1647 dol_syslog(__METHOD__.': using numeric types is deprecated.', LOG_WARNING);
1648 }
1649
1650 $cats = array();
1651
1652 // For backward compatibility
1653 if (is_numeric($type)) {
1654 // We want to reverse lookup
1655 $map_type = array_flip($this->MAP_ID);
1656 $type = $map_type[$type];
1657 dol_syslog(get_class($this)."::rechercher(): numeric types are deprecated, please use string instead", LOG_WARNING);
1658 }
1659
1660 // Generation requete recherche
1661 $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."categorie";
1662 $sql .= " WHERE type = ".((int) $this->MAP_ID[$type]);
1663 $sql .= " AND entity IN (".getEntity('category').")";
1664 if ($nom) {
1665 if (!$exact) {
1666 $nom = '%'.$this->db->escape(str_replace('*', '%', $nom)).'%';
1667 }
1668 if (!$case) {
1669 $sql .= " AND label LIKE '".$this->db->escape($nom)."'";
1670 } else {
1671 $sql .= " AND label LIKE BINARY '".$this->db->escape($nom)."'";
1672 }
1673 }
1674 if ($id) {
1675 $sql .= " AND rowid = ".((int) $id);
1676 }
1677
1678 $res = $this->db->query($sql);
1679 if ($res) {
1680 while ($rec = $this->db->fetch_array($res)) {
1681 $cat = new Categorie($this->db);
1682 $cat->fetch($rec['rowid']);
1683 $cats[] = $cat;
1684 }
1685
1686 return $cats;
1687 } else {
1688 $this->error = $this->db->error().' sql='.$sql;
1689 return -1;
1690 }
1691 }
1692
1699 public function isAnyPhotoAvailable($sdir)
1700 {
1701 include_once DOL_DOCUMENT_ROOT . '/core/lib/files.lib.php';
1702 include_once DOL_DOCUMENT_ROOT . '/core/lib/images.lib.php';
1703
1704 $sdir .= '/' . get_exdir($this->id, 2, 0, 0, $this, 'category') . $this->id . "/photos/";
1705
1706 $dir_osencoded = dol_osencode($sdir);
1707 if (file_exists($dir_osencoded)) {
1708 $handle = opendir($dir_osencoded);
1709 if (is_resource($handle)) {
1710 while (($file = readdir($handle)) !== false) {
1711 if (!utf8_check($file)) {
1712 $file = mb_convert_encoding($file, 'UTF-8', 'ISO-8859-1'); // To be sure data is stored in UTF8 in memory
1713 }
1714 if (dol_is_file($sdir . $file) && image_format_supported($file) >= 0) {
1715 return true;
1716 }
1717 }
1718 }
1719 }
1720 return false;
1721 }
1722
1729 public function getTooltipContentArray($params)
1730 {
1731 global $langs;
1732
1733 $langs->load('categories');
1734
1735 $datas = [];
1736
1737 $datas['label'] = $langs->trans("ShowCategory").': '.($this->ref ? $this->ref : $this->label);
1738
1739 return $datas;
1740 }
1741
1755 public function getNomUrl($withpicto = 0, $option = '', $maxlength = 0, $moreparam = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = 0)
1756 {
1757 global $conf, $langs, $hookmanager;
1758
1759 if (!empty($conf->dol_no_mouse_hover)) {
1760 $notooltip = 1; // Force disable tooltips
1761 }
1762
1763 $result = '';
1764 $params = [
1765 'id' => $this->id,
1766 'objecttype' => $this->element,
1767 'option' => $option,
1768 ];
1769 $classfortooltip = 'classfortooltip';
1770 $dataparams = '';
1771 if (getDolGlobalInt('MAIN_ENABLE_AJAX_TOOLTIP')) {
1772 $classfortooltip = 'classforajaxtooltip';
1773 $dataparams = ' data-params="'.dol_escape_htmltag(json_encode($params)).'"';
1774 $label = '';
1775 } else {
1776 $label = implode($this->getTooltipContentArray($params));
1777 }
1778
1779 $url = DOL_URL_ROOT.'/categories/viewcat.php?id='.$this->id.'&type='.$this->type.$moreparam.'&backtopage='.urlencode($_SERVER['PHP_SELF'].($moreparam ? '?'.$moreparam : ''));
1780
1781 if ($option !== 'nolink') {
1782 // Add param to save lastsearch_values or not
1783 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
1784 if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
1785 $add_save_lastsearch_values = 1;
1786 }
1787 if ($url && $add_save_lastsearch_values) {
1788 $url .= '&save_lastsearch_values=1';
1789 }
1790 }
1791
1792 // Check contrast with background and correct text color
1793 $forced_color = 'categtextwhite';
1794 if ($this->color) {
1795 if (colorIsLight($this->color)) {
1796 $forced_color = 'categtextblack';
1797 }
1798 }
1799
1800 $linkclose = '';
1801 if (empty($notooltip)) {
1802 if (getDolGlobalInt('MAIN_OPTIMIZEFORTEXTBROWSER')) {
1803 $label = $langs->trans("ShowMyObject");
1804 $linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"';
1805 }
1806 $linkclose .= ($label ? ' title="'.dol_escape_htmltag($label, 1).'"' : ' title="tocomplete"');
1807 $linkclose .= $dataparams.' class="'.$classfortooltip.' '.$forced_color.($morecss ? ' '.$morecss : '').'"';
1808 } else {
1809 $linkclose = ($morecss ? ' class="'.$forced_color.($morecss ? ' '.$morecss : '').'"' : '');
1810 }
1811
1812 if ($option == 'nolink' || empty($url)) {
1813 $linkstart = '<span';
1814 } else {
1815 $linkstart = '<a href="'.$url.'"';
1816 }
1817 $linkstart .= $linkclose.'>';
1818 if ($option == 'nolink' || empty($url)) {
1819 $linkend = '</span>';
1820 } else {
1821 $linkend = '</a>';
1822 }
1823
1824 $result .= $linkstart;
1825
1826 if ($withpicto) {
1827 $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'"'), 0, 0, $notooltip ? 0 : 1);
1828 }
1829
1830 if ($withpicto != 2) {
1831 $result .= dol_trunc(($this->ref ? $this->ref : $this->label), $maxlength);
1832 }
1833
1834 $result .= $linkend;
1835
1836 global $action;
1837 $hookmanager->initHooks(array($this->element . 'dao'));
1838 $parameters = array('id' => $this->id, 'getnomurl' => &$result);
1839 $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
1840 if ($reshook > 0) {
1841 $result = $hookmanager->resPrint;
1842 } else {
1843 $result .= $hookmanager->resPrint;
1844 }
1845 return $result;
1846 }
1847
1848
1849 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1857 public function add_photo($sdir, $file)
1858 {
1859 // phpcs:enable
1860 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
1861
1862 $dir = $sdir.'/'.get_exdir($this->id, 2, 0, 0, $this, 'category').$this->id."/";
1863 $dir .= "photos/";
1864
1865 if (!file_exists($dir)) {
1866 dol_mkdir($dir);
1867 }
1868
1869 if (file_exists($dir)) {
1870 if (is_array($file['name'])) {
1871 $nbfile = count($file['name']);
1872 for ($i = 0; $i < $nbfile; $i++) {
1873 $originImage = $dir.$file['name'][$i];
1874
1875 // Cree fichier en taille origine
1876 dol_move_uploaded_file($file['tmp_name'][$i], $originImage, 1, 0, 0);
1877
1878 if (file_exists($originImage)) {
1879 // Create thumbs
1880 $this->addThumbs($originImage);
1881 }
1882 }
1883 } else {
1884 $originImage = $dir.$file['name'];
1885
1886 // Cree fichier en taille origine
1887 dol_move_uploaded_file($file['tmp_name'], $originImage, 1, 0, 0);
1888
1889 if (file_exists($originImage)) {
1890 // Create thumbs
1891 $this->addThumbs($originImage);
1892 }
1893 }
1894 }
1895 }
1896
1897 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1905 public function liste_photos($dir, $nbmax = 0)
1906 {
1907 // phpcs:enable
1908 include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
1909
1910 $nbphoto = 0;
1911 $tabobj = array();
1912
1913 $dirthumb = $dir.'thumbs/';
1914
1915 if (file_exists($dir)) {
1916 $handle = opendir($dir);
1917 if (is_resource($handle)) {
1918 while (($file = readdir($handle)) !== false) {
1919 if (dol_is_file($dir.$file) && preg_match('/(\.jpeg|\.jpg|\.bmp|\.gif|\.png|\.tiff)$/i', $dir.$file)) {
1920 $nbphoto++;
1921 $photo = $file;
1922
1923 // On determine nom du fichier vignette
1924 $photo_vignette = '';
1925 $regs = array();
1926 if (preg_match('/(\.jpeg|\.jpg|\.bmp|\.gif|\.png|\.tiff)$/i', $photo, $regs)) {
1927 $photo_vignette = preg_replace('/'.$regs[0].'/i', '', $photo).'_small'.$regs[0];
1928 }
1929
1930 // Object
1931 $obj = array();
1932 $obj['photo'] = $photo;
1933 if ($photo_vignette && is_file($dirthumb.$photo_vignette)) {
1934 $obj['photo_vignette'] = 'thumbs/'.$photo_vignette;
1935 } else {
1936 $obj['photo_vignette'] = "";
1937 }
1938
1939 $tabobj[$nbphoto - 1] = $obj;
1940
1941 // On continue ou on arrete de boucler
1942 if ($nbmax && $nbphoto >= $nbmax) {
1943 break;
1944 }
1945 }
1946 }
1947
1948 closedir($handle);
1949 }
1950 }
1951
1952 return $tabobj;
1953 }
1954
1955 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1962 public function delete_photo($file)
1963 {
1964 // phpcs:enable
1965 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
1966
1967 $dir = dirname($file).'/'; // Chemin du dossier contenant l'image d'origine
1968 $dirthumb = $dir.'/thumbs/'; // Chemin du dossier contenant la vignette
1969 $filename = preg_replace('/'.preg_quote($dir, '/').'/i', '', $file); // Nom du fichier
1970
1971 // On efface l'image d'origine
1972 dol_delete_file($file, 1);
1973
1974 // Si elle existe, on efface la vignette
1975 $regs = array();
1976 if (preg_match('/(\.jpeg|\.jpg|\.bmp|\.gif|\.png|\.tiff)$/i', $filename, $regs)) {
1977 $photo_vignette = preg_replace('/'.$regs[0].'/i', '', $filename).'_small'.$regs[0];
1978 if (file_exists($dirthumb.$photo_vignette)) {
1979 dol_delete_file($dirthumb.$photo_vignette, 1);
1980 }
1981 }
1982 }
1983
1984 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1991 public function get_image_size($file)
1992 {
1993 // phpcs:enable
1994 $infoImg = getimagesize($file); // Recuperation des infos de l'image
1995 $this->imgWidth = $infoImg[0]; // Largeur de l'image
1996 $this->imgHeight = $infoImg[1]; // Hauteur de l'image
1997 }
1998
2007 public function setMultiLangs(User $user, $notrigger = 0)
2008 {
2009 global $langs;
2010
2011 $langs_available = $langs->get_available_languages();
2012 $current_lang = $langs->getDefaultLang();
2013
2014 foreach ($langs_available as $key => $value) {
2015 $sql = "SELECT rowid";
2016 $sql .= " FROM ".MAIN_DB_PREFIX."categorie_lang";
2017 $sql .= " WHERE fk_category=".((int) $this->id);
2018 $sql .= " AND lang = '".$this->db->escape($key)."'";
2019
2020 $result = $this->db->query($sql);
2021
2022 if ($key == $current_lang) {
2023 $sql2 = '';
2024 if ($this->db->num_rows($result)) { // if no line in database
2025 $sql2 = "UPDATE ".MAIN_DB_PREFIX."categorie_lang";
2026 $sql2 .= " SET label = '".$this->db->escape($this->label)."',";
2027 $sql2 .= " description = '".$this->db->escape($this->description)."'";
2028 $sql2 .= " WHERE fk_category = ".((int) $this->id)." AND lang = '".$this->db->escape($key)."'";
2029 } elseif (isset($this->multilangs[$key])) {
2030 $sql2 = "INSERT INTO ".MAIN_DB_PREFIX."categorie_lang (fk_category, lang, label, description)";
2031 $sql2 .= " VALUES(".((int) $this->id).", '".$this->db->escape($key)."', '".$this->db->escape($this->label)."'";
2032 $sql2 .= ", '".$this->db->escape($this->multilangs[$key]["description"])."')";
2033 }
2034 dol_syslog(get_class($this).'::setMultiLangs', LOG_DEBUG);
2035 if ($sql2 && !$this->db->query($sql2)) {
2036 $this->error = $this->db->lasterror();
2037 return -1;
2038 }
2039 } elseif (isset($this->multilangs[$key])) {
2040 if ($this->db->num_rows($result)) { // if no line in database
2041 $sql2 = "UPDATE ".MAIN_DB_PREFIX."categorie_lang";
2042 $sql2 .= " SET label='".$this->db->escape($this->multilangs[$key]["label"])."',";
2043 $sql2 .= " description='".$this->db->escape($this->multilangs[$key]["description"])."'";
2044 $sql2 .= " WHERE fk_category=".((int) $this->id)." AND lang='".$this->db->escape($key)."'";
2045 } else {
2046 $sql2 = "INSERT INTO ".MAIN_DB_PREFIX."categorie_lang (fk_category, lang, label, description)";
2047 $sql2 .= " VALUES(".((int) $this->id).", '".$this->db->escape($key)."', '".$this->db->escape($this->multilangs[$key]["label"])."'";
2048 $sql2 .= ",'".$this->db->escape($this->multilangs[$key]["description"])."')";
2049 }
2050
2051 // on ne sauvegarde pas des champs vides
2052 if ($this->multilangs[$key]["label"] || $this->multilangs[$key]["description"] || $this->multilangs[$key]["note"]) {
2053 dol_syslog(get_class($this).'::setMultiLangs', LOG_DEBUG);
2054 }
2055 if (!$this->db->query($sql2)) {
2056 $this->error = $this->db->lasterror();
2057 return -1;
2058 }
2059 }
2060 }
2061
2062 // Call trigger
2063 if (!$notrigger) {
2064 $result = $this->call_trigger('CATEGORY_SET_MULTILANGS', $user);
2065 if ($result < 0) {
2066 $this->error = $this->db->lasterror();
2067 return -1;
2068 }
2069 }
2070 // End call triggers
2071
2072 return 1;
2073 }
2074
2083 public function delMultiLangs($langtodelete, $user)
2084 {
2085 $sql = "DELETE FROM ".$this->db->prefix()."categorie_lang";
2086 $sql .= " WHERE fk_category = ".((int) $this->id)." AND lang = '".$this->db->escape($langtodelete)."'";
2087
2088 dol_syslog(get_class($this).'::delMultiLangs', LOG_DEBUG);
2089 $result = $this->db->query($sql);
2090 if ($result) {
2091 // Call trigger
2092 $result = $this->call_trigger('CATEGORY_DEL_MULTILANGS', $user);
2093 if ($result < 0) {
2094 $this->error = $this->db->lasterror();
2095 dol_syslog(get_class($this).'::delMultiLangs error='.$this->error, LOG_ERR);
2096 return -1;
2097 }
2098 // End call triggers
2099 return 1;
2100 } else {
2101 $this->error = $this->db->lasterror();
2102 dol_syslog(get_class($this).'::delMultiLangs error='.$this->error, LOG_ERR);
2103 return -1;
2104 }
2105 }
2106
2112 public function getMultiLangs()
2113 {
2114 global $langs;
2115
2116 $current_lang = $langs->getDefaultLang();
2117
2118 $sql = "SELECT lang, label, description";
2119 $sql .= " FROM ".MAIN_DB_PREFIX."categorie_lang";
2120 $sql .= " WHERE fk_category=".((int) $this->id);
2121
2122 $result = $this->db->query($sql);
2123 if ($result) {
2124 while ($obj = $this->db->fetch_object($result)) {
2125 //print 'lang='.$obj->lang.' current='.$current_lang.'<br>';
2126 if ($obj->lang == $current_lang) { // si on a les traduct. dans la langue courante on les charge en infos principales.
2127 $this->label = $obj->label;
2128 $this->description = $obj->description;
2129 }
2130 $this->multilangs[$obj->lang]["label"] = $obj->label;
2131 $this->multilangs[$obj->lang]["description"] = $obj->description;
2132 }
2133 return 1;
2134 } else {
2135 $this->error = $langs->trans("Error")." : ".$this->db->error()." - ".$sql;
2136 return -1;
2137 }
2138 }
2139
2146 public function getLibStatut($mode)
2147 {
2148 return '';
2149 }
2150
2151
2159 public function initAsSpecimen()
2160 {
2161 dol_syslog(get_class($this)."::initAsSpecimen");
2162
2163 // Initialise parameters
2164 $this->id = 0;
2165 $this->fk_parent = 0;
2166 $this->label = 'SPECIMEN';
2167 $this->specimen = 1;
2168 $this->description = 'This is a description';
2169 $this->socid = 1;
2170 $this->type = self::TYPE_PRODUCT;
2171
2172 return 1;
2173 }
2174
2183 public static function replaceThirdparty(DoliDB $dbs, $origin_id, $dest_id)
2184 {
2185 $tables = array(
2186 'categorie_societe'
2187 );
2188
2189 return CommonObject::commonReplaceThirdparty($dbs, $origin_id, $dest_id, $tables, 1);
2190 }
2191
2200 public static function getFilterJoinQuery($type, $rowIdName)
2201 {
2202 if ($type == 'bank_account') {
2203 $type = 'account';
2204 }
2205
2206 return " LEFT JOIN ".MAIN_DB_PREFIX."categorie_".$type." as cp ON ".$rowIdName." = cp.fk_".$type;
2207 }
2208
2218 public static function getFilterSelectQuery($type, $rowIdName, $searchList)
2219 {
2220 if ($type == 'bank_account') {
2221 $type = 'account';
2222 }
2223 if ($type == 'customer') {
2224 $type = 'societe';
2225 }
2226 if ($type == 'supplier') {
2227 $type = 'fournisseur';
2228 }
2229
2230 if (empty($searchList) && !is_array($searchList)) {
2231 return "";
2232 }
2233
2234 $searchCategorySqlList = array();
2235 foreach ($searchList as $searchCategory) {
2236 if (intval($searchCategory) == -2) {
2237 $searchCategorySqlList[] = " cp.fk_categorie IS NULL";
2238 } elseif (intval($searchCategory) > 0) {
2239 $searchCategorySqlList[] = " ".$rowIdName." IN (SELECT fk_".$type." FROM ".MAIN_DB_PREFIX."categorie_".$type." WHERE fk_categorie = ".((int) $searchCategory).")";
2240 }
2241 }
2242
2243 if (!empty($searchCategorySqlList)) {
2244 return " AND (".implode(' AND ', $searchCategorySqlList).")";
2245 } else {
2246 return "";
2247 }
2248 }
2249
2255 public function countNbOfCategories()
2256 {
2257 dol_syslog(get_class($this)."::count_all_categories", LOG_DEBUG);
2258 $sql = "SELECT COUNT(rowid) FROM ".MAIN_DB_PREFIX."categorie";
2259 $sql .= " WHERE entity IN (".getEntity('category').")";
2260
2261 $res = $this->db->query($sql);
2262 if ($res) {
2263 $obj = $this->db->fetch_object($res);
2264 return $obj->count;
2265 } else {
2266 dol_print_error($this->db);
2267 return -1;
2268 }
2269 }
2270}
print $object position
Definition edit.php:195
$object ref
Definition info.php:79
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.
if(preg_match('/crypted:/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
Definition repair.php:137