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;
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
370 public function fetch($id, $label = '', $type = null, $ref_ext = '')
371 {
372 // Check parameters
373 if (empty($id) && empty($label) && empty($ref_ext)) {
374 $this->error = "No category to search for";
375 return -1;
376 }
377 if (!is_null($type) && !is_numeric($type)) {
378 $type = $this->MAP_ID[$type];
379 }
380
381 $sql = "SELECT rowid, fk_parent, entity, label, description, color, position, fk_soc, visible, type, ref_ext";
382 $sql .= ", date_creation, tms, fk_user_creat, fk_user_modif";
383 $sql .= " FROM ".MAIN_DB_PREFIX."categorie";
384 if ($id) {
385 $sql .= " WHERE rowid = ".((int) $id);
386 } elseif (!empty($ref_ext)) {
387 $sql .= " WHERE ref_ext LIKE '".$this->db->escape($ref_ext)."'";
388 } else {
389 $sql .= " WHERE label = '".$this->db->escape($label)."' AND entity IN (".getEntity('category').")";
390 if (!is_null($type)) {
391 $sql .= " AND type = ".((int) $type);
392 }
393 }
394
395 dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
396 $resql = $this->db->query($sql);
397 if ($resql) {
398 if ($this->db->num_rows($resql) > 0 && $res = $this->db->fetch_array($resql)) {
399 $this->id = $res['rowid'];
400 //$this->ref = $res['rowid'];
401 $this->fk_parent = (int) $res['fk_parent'];
402 $this->label = $res['label'];
403 $this->description = $res['description'];
404 $this->color = $res['color'];
405 $this->position = $res['position'];
406 $this->socid = (int) $res['fk_soc'];
407 $this->visible = (int) $res['visible'];
408 $this->type = $res['type'];
409 $this->ref_ext = $res['ref_ext'];
410 $this->entity = (int) $res['entity'];
411 $this->date_creation = $this->db->jdate($res['date_creation']);
412 $this->date_modification = $this->db->jdate($res['tms']);
413 $this->user_creation_id = (int) $res['fk_user_creat'];
414 $this->user_modification_id = (int) $res['fk_user_modif'];
415
416 // Retrieve all extrafield
417 // fetch optionals attributes and labels
418 $this->fetch_optionals();
419
420 $this->db->free($resql);
421
422 // multilangs
423 if (getDolGlobalInt('MAIN_MULTILANGS')) {
424 $this->getMultiLangs();
425 }
426
427 return 1;
428 } else {
429 $this->error = "No category found";
430 return 0;
431 }
432 } else {
433 dol_print_error($this->db);
434 $this->error = $this->db->lasterror;
435 $this->errors[] = $this->db->lasterror;
436 return -1;
437 }
438 }
439
450 public function create($user, $notrigger = 0)
451 {
452 global $conf, $langs, $hookmanager;
453 $langs->load('categories');
454
455 $type = $this->type;
456
457 if (!is_numeric($type)) {
458 $type = $this->MAP_ID[$type];
459 }
460
461 $error = 0;
462
463 dol_syslog(get_class($this).'::create', LOG_DEBUG);
464
465 // Clean parameters
466 $this->label = trim($this->label);
467 $this->description = trim($this->description);
468 $this->color = trim($this->color);
469 $this->position = (int) $this->position;
470 $this->import_key = trim($this->import_key);
471 $this->ref_ext = trim($this->ref_ext);
472 if (empty($this->visible)) {
473 $this->visible = 0;
474 }
475 $this->fk_parent = ($this->fk_parent != "" ? intval($this->fk_parent) : 0);
476
477 if ($this->already_exists()) {
478 $this->error = $langs->trans("ImpossibleAddCat", $this->label);
479 $this->error .= " : ".$langs->trans("CategoryExistsAtSameLevel");
480 dol_syslog($this->error, LOG_WARNING);
481 return -4;
482 }
483
484 $this->db->begin();
485 $now = dol_now();
486 $sql = "INSERT INTO ".MAIN_DB_PREFIX."categorie (";
487 $sql .= "fk_parent,";
488 $sql .= " label,";
489 $sql .= " description,";
490 $sql .= " color,";
491 $sql .= " position,";
492 if (getDolGlobalString('CATEGORY_ASSIGNED_TO_A_CUSTOMER')) {
493 $sql .= "fk_soc,";
494 }
495 $sql .= " visible,";
496 $sql .= " type,";
497 $sql .= " import_key,";
498 $sql .= " ref_ext,";
499 $sql .= " entity,";
500 $sql .= " date_creation,";
501 $sql .= " fk_user_creat";
502 $sql .= ") VALUES (";
503 $sql .= (int) $this->fk_parent.",";
504 $sql .= "'".$this->db->escape($this->label)."', ";
505 $sql .= "'".$this->db->escape($this->description)."', ";
506 $sql .= "'".$this->db->escape($this->color)."', ";
507 $sql .= (int) $this->position.",";
508 if (getDolGlobalString('CATEGORY_ASSIGNED_TO_A_CUSTOMER')) {
509 $sql .= ($this->socid > 0 ? $this->socid : 'null').", ";
510 }
511 $sql .= "'".$this->db->escape($this->visible)."', ";
512 $sql .= ((int) $type).", ";
513 $sql .= (!empty($this->import_key) ? "'".$this->db->escape($this->import_key)."'" : 'null').", ";
514 $sql .= (!empty($this->ref_ext) ? "'".$this->db->escape($this->ref_ext)."'" : 'null').", ";
515 $sql .= (int) $conf->entity.", ";
516 $sql .= "'".$this->db->idate($now)."', ";
517 $sql .= (int) $user->id;
518 $sql .= ")";
519
520 $res = $this->db->query($sql);
521 if ($res) {
522 $id = $this->db->last_insert_id(MAIN_DB_PREFIX."categorie");
523
524 if ($id > 0) {
525 $this->id = $id;
526
527 $action = 'create';
528
529 // Actions on extra fields
530 if (!$error) {
531 $result = $this->insertExtraFields();
532 if ($result < 0) {
533 $error++;
534 }
535 }
536
537 if (!$error && !$notrigger) {
538 // Call trigger
539 $result = $this->call_trigger('CATEGORY_CREATE', $user);
540 if ($result < 0) {
541 $error++;
542 }
543 // End call triggers
544 }
545
546 if (!$error) {
547 $this->db->commit();
548 return $id;
549 } else {
550 $this->db->rollback();
551 return -3;
552 }
553 } else {
554 $this->db->rollback();
555 return -2;
556 }
557 } else {
558 $this->error = $this->db->error();
559 $this->db->rollback();
560 return -1;
561 }
562 }
563
573 public function update(User $user, $notrigger = 0)
574 {
575 global $langs;
576
577 $error = 0;
578
579 // Clean parameters
580 $this->label = trim($this->label);
581 $this->description = trim($this->description);
582 $this->ref_ext = trim($this->ref_ext);
583 $this->fk_parent = ($this->fk_parent != "" ? intval($this->fk_parent) : 0);
584 $this->visible = ($this->visible != "" ? intval($this->visible) : 0);
585
586 if ($this->already_exists()) {
587 $this->error = $langs->trans("ImpossibleUpdateCat");
588 $this->error .= " : ".$langs->trans("CategoryExistsAtSameLevel");
589 return -1;
590 }
591
592 $this->db->begin();
593
594 $sql = "UPDATE ".MAIN_DB_PREFIX."categorie";
595 $sql .= " SET label = '".$this->db->escape($this->label)."',";
596 $sql .= " description = '".$this->db->escape($this->description)."',";
597 $sql .= " ref_ext = '".$this->db->escape($this->ref_ext)."',";
598 $sql .= " color = '".$this->db->escape($this->color)."'";
599 $sql .= ", position = ".(int) $this->position;
600 if (getDolGlobalString('CATEGORY_ASSIGNED_TO_A_CUSTOMER')) {
601 $sql .= ", fk_soc = ".($this->socid > 0 ? $this->socid : 'null');
602 }
603 $sql .= ", visible = ".(int) $this->visible;
604 $sql .= ", fk_parent = ".(int) $this->fk_parent;
605 $sql .= ", fk_user_modif = ".(int) $user->id;
606 $sql .= " WHERE rowid = ".((int) $this->id);
607
608 dol_syslog(get_class($this)."::update", LOG_DEBUG);
609 if ($this->db->query($sql)) {
610 $action = 'update';
611
612 // Actions on extra fields
613 if (!$error) {
614 $result = $this->insertExtraFields();
615 if ($result < 0) {
616 $error++;
617 }
618 }
619
620 if (!$error && !$notrigger) {
621 // Call trigger
622 $result = $this->call_trigger('CATEGORY_MODIFY', $user);
623 if ($result < 0) {
624 $error++;
625 }
626 // End call triggers
627 }
628
629 if (!$error) {
630 $this->db->commit();
631 return 1;
632 } else {
633 $this->db->rollback();
634 return -1;
635 }
636 } else {
637 $this->db->rollback();
638 dol_print_error($this->db);
639 return -1;
640 }
641 }
642
650 public function delete($user, $notrigger = 0)
651 {
652 $error = 0;
653
654 // Clean parameters
655 $this->fk_parent = ($this->fk_parent != "" ? intval($this->fk_parent) : 0);
656
657 dol_syslog(get_class($this)."::remove");
658
659 $this->db->begin();
660
661 if (!$error && !$notrigger) {
662 // Call trigger
663 $result = $this->call_trigger('CATEGORY_DELETE', $user);
664 if ($result < 0) {
665 $error++;
666 }
667 // End call triggers
668 }
669
670 /* FIX #1317 : Check for child category and move up 1 level*/
671 if (!$error) {
672 $sql = "UPDATE ".MAIN_DB_PREFIX."categorie";
673 $sql .= " SET fk_parent = ".((int) $this->fk_parent);
674 $sql .= " WHERE fk_parent = ".((int) $this->id);
675
676 if (!$this->db->query($sql)) {
677 $this->error = $this->db->lasterror();
678 $error++;
679 }
680 }
681
682 $arraydelete = array(
683 'categorie_account' => 'fk_categorie',
684 'categorie_actioncomm' => 'fk_categorie',
685 'categorie_contact' => 'fk_categorie',
686 'categorie_fournisseur' => 'fk_categorie',
687 'categorie_knowledgemanagement' => array('field' => 'fk_categorie', 'enabled' => isModEnabled('knowledgemanagement')),
688 'categorie_member' => 'fk_categorie',
689 'categorie_user' => 'fk_categorie',
690 'categorie_product' => 'fk_categorie',
691 'categorie_project' => 'fk_categorie',
692 'categorie_societe' => 'fk_categorie',
693 'categorie_ticket' => array('field' => 'fk_categorie', 'enabled' => isModEnabled('ticket')),
694 'categorie_warehouse' => 'fk_categorie',
695 'categorie_website_page' => array('field' => 'fk_categorie', 'enabled' => isModEnabled('website')),
696 'category_bankline' => 'fk_categ',
697 'categorie_lang' => 'fk_category',
698 'categorie' => 'rowid',
699 );
700 foreach ($arraydelete as $key => $value) {
701 if (is_array($value)) {
702 if (empty($value['enabled'])) {
703 continue;
704 }
705 $value = $value['field'];
706 }
707 $sql = "DELETE FROM ".MAIN_DB_PREFIX.$key;
708 $sql .= " WHERE ".$value." = ".((int) $this->id);
709 if (!$this->db->query($sql)) {
710 $this->errors[] = $this->db->lasterror();
711 dol_syslog("Error sql=".$sql." ".$this->error, LOG_ERR);
712 $error++;
713 }
714 }
715
716 // Removed extrafields
717 if (!$error) {
718 $result = $this->deleteExtraFields();
719 if ($result < 0) {
720 $error++;
721 dol_syslog(get_class($this)."::delete erreur ".$this->error, LOG_ERR);
722 }
723 }
724
725 if (!$error) {
726 $this->db->commit();
727 return 1;
728 } else {
729 $this->db->rollback();
730 return -1;
731 }
732 }
733
734 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
743 public function add_type($obj, $type = '')
744 {
745 // phpcs:enable
746 global $user;
747
748 $error = 0;
749
750 if ($this->id == -1) {
751 return -2;
752 }
753
754 if (empty($type)) {
755 $type = $obj->element;
756 }
757
758 dol_syslog(get_class($this).'::add_type', LOG_DEBUG);
759
760 $this->db->begin();
761
762 $sql = "INSERT INTO ".MAIN_DB_PREFIX."categorie_".(empty($this->MAP_CAT_TABLE[$type]) ? $type : $this->MAP_CAT_TABLE[$type]);
763 $sql .= " (fk_categorie, fk_".(empty($this->MAP_CAT_FK[$type]) ? $type : $this->MAP_CAT_FK[$type]).")";
764 $sql .= " VALUES (".((int) $this->id).", ".((int) $obj->id).")";
765
766 if ($this->db->query($sql)) {
767 if (getDolGlobalString('CATEGORIE_RECURSIV_ADD')) {
768 $sql = 'SELECT fk_parent FROM '.MAIN_DB_PREFIX.'categorie';
769 $sql .= " WHERE rowid = ".((int) $this->id);
770
771 dol_syslog(get_class($this)."::add_type", LOG_DEBUG);
772 $resql = $this->db->query($sql);
773 if ($resql) {
774 if ($this->db->num_rows($resql) > 0) {
775 $objparent = $this->db->fetch_object($resql);
776
777 if (!empty($objparent->fk_parent)) {
778 $cat = new Categorie($this->db);
779 $cat->id = $objparent->fk_parent;
780 if (!$cat->containsObject($type, $obj->id)) {
781 $result = $cat->add_type($obj, $type);
782 if ($result < 0) {
783 $this->error = $cat->error;
784 $error++;
785 }
786 }
787 }
788 }
789 } else {
790 $error++;
791 $this->error = $this->db->lasterror();
792 }
793
794 if ($error) {
795 $this->db->rollback();
796 return -1;
797 }
798 }
799
800 // Call trigger
801 $this->context = array('linkto' => $obj); // Save object we want to link category to into category instance to provide information to trigger
802 $result = $this->call_trigger('CATEGORY_LINK', $user);
803 if ($result < 0) {
804 $error++;
805 }
806 // End call triggers
807
808 if (!$error) {
809 $this->db->commit();
810 return 1;
811 } else {
812 $this->db->rollback();
813 return -2;
814 }
815 } else {
816 $this->db->rollback();
817 if ($this->db->lasterrno() == 'DB_ERROR_RECORD_ALREADY_EXISTS') {
818 $this->error = $this->db->lasterrno();
819 return -3;
820 } else {
821 $this->error = $this->db->lasterror();
822 }
823 return -1;
824 }
825 }
826
827 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
836 public function del_type($obj, $type)
837 {
838 // phpcs:enable
839 global $user;
840
841 $error = 0;
842
843 // For backward compatibility
844 if ($type == 'societe') {
845 $type = 'customer';
846 dol_syslog(get_class($this)."::del_type(): type 'societe' is deprecated, please use 'customer' instead", LOG_WARNING);
847 } elseif ($type == 'fournisseur') {
848 $type = 'supplier';
849 dol_syslog(get_class($this)."::del_type(): type 'fournisseur' is deprecated, please use 'supplier' instead", LOG_WARNING);
850 }
851
852 $this->db->begin();
853
854 $sql = "DELETE FROM ".MAIN_DB_PREFIX."categorie_".(empty($this->MAP_CAT_TABLE[$type]) ? $type : $this->MAP_CAT_TABLE[$type]);
855 $sql .= " WHERE fk_categorie = ".((int) $this->id);
856 $sql .= " AND fk_".(empty($this->MAP_CAT_FK[$type]) ? $type : $this->MAP_CAT_FK[$type])." = ".((int) $obj->id);
857
858 dol_syslog(get_class($this).'::del_type', LOG_DEBUG);
859 if ($this->db->query($sql)) {
860 // Call trigger
861 $this->context = array('unlinkoff' => $obj); // Save object we want to link category to into category instance to provide information to trigger
862 $result = $this->call_trigger('CATEGORY_UNLINK', $user);
863 if ($result < 0) {
864 $error++;
865 }
866 // End call triggers
867
868 if (!$error) {
869 $this->db->commit();
870 return 1;
871 } else {
872 $this->db->rollback();
873 return -2;
874 }
875 } else {
876 $this->db->rollback();
877 $this->error = $this->db->lasterror();
878 return -1;
879 }
880 }
881
899 public function getObjectsInCateg($type, $onlyids = 0, $limit = 0, $offset = 0, $sortfield = '', $sortorder = 'ASC', $filter = '', $filtermode = 'AND', $filterlang = '')
900 {
901 global $user;
902
903 $objs = array();
904
905 $classnameforobj = $this->MAP_OBJ_CLASS[$type];
906 $obj = new $classnameforobj($this->db);
907
908 $sql = "SELECT c.fk_".(empty($this->MAP_CAT_FK[$type]) ? $type : $this->MAP_CAT_FK[$type])." as fk_object";
909 $sql .= " FROM ".MAIN_DB_PREFIX."categorie_".(empty($this->MAP_CAT_TABLE[$type]) ? $type : $this->MAP_CAT_TABLE[$type])." as c";
910 $sql .= ", ".MAIN_DB_PREFIX.(empty($this->MAP_OBJ_TABLE[$type]) ? $type : $this->MAP_OBJ_TABLE[$type])." as o";
911 if (!empty($filterlang)) {
912 $sql .= ", ".MAIN_DB_PREFIX.(empty($this->MAP_OBJ_TABLE[$type]) ? $type : $this->MAP_OBJ_TABLE[$type])."_lang as ol";
913 }
914 $sql .= " WHERE o.entity IN (".getEntity($obj->element).")";
915 $sql .= " AND c.fk_categorie = ".((int) $this->id);
916 // Compatibility with actioncomm table which has id instead of rowid
917 if ((array_key_exists($type, $this->MAP_OBJ_TABLE) && $this->MAP_OBJ_TABLE[$type] == "actioncomm") || $type == "actioncomm") {
918 $sql .= " AND c.fk_".(empty($this->MAP_CAT_FK[$type]) ? $type : $this->MAP_CAT_FK[$type])." = o.id";
919 } else {
920 $sql .= " AND c.fk_".(empty($this->MAP_CAT_FK[$type]) ? $type : $this->MAP_CAT_FK[$type])." = o.rowid";
921 }
922 if (!empty($filterlang)) {
923 $sql .= " AND ol.fk_".(empty($this->MAP_OBJ_TABLE[$type]) ? $type : $this->MAP_OBJ_TABLE[$type])." = o.rowid";
924 $sql .= " AND ol.lang = '".$this->db->escape($filterlang)."'";
925 }
926 // Protection for external users
927 if (($type == 'customer' || $type == 'supplier') && $user->socid > 0) {
928 $sql .= " AND o.rowid = ".((int) $user->socid);
929 }
930
931 $errormessage = '';
932 $sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage);
933 if ($errormessage) {
934 $this->errors[] = $errormessage;
935 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
936 return -1;
937 }
938
939 $sql .= $this->db->order($sortfield, $sortorder);
940 if ($limit > 0 || $offset > 0) {
941 $sql .= $this->db->plimit($limit + 1, $offset);
942 }
943
944 dol_syslog(get_class($this)."::getObjectsInCateg", LOG_DEBUG);
945
946 $resql = $this->db->query($sql);
947 if ($resql) {
948 while ($rec = $this->db->fetch_array($resql)) {
949 if ($onlyids) {
950 $objs[] = $rec['fk_object'];
951 } else {
952 $classnameforobj = $this->MAP_OBJ_CLASS[$type];
953
954 $obj = new $classnameforobj($this->db);
955 $obj->fetch($rec['fk_object']);
956 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.
957 $objs[] = $obj;
958 }
959 }
960 }
961 return $objs;
962 } else {
963 $this->error = $this->db->error().' sql='.$sql;
964 return -1;
965 }
966 }
967
976 public function containsObject($type, $object_id)
977 {
978 $sql = "SELECT COUNT(*) as nb FROM ".MAIN_DB_PREFIX."categorie_".(empty($this->MAP_CAT_TABLE[$type]) ? $type : $this->MAP_CAT_TABLE[$type]);
979 $sql .= " WHERE fk_categorie = ".((int) $this->id)." AND fk_".(empty($this->MAP_CAT_FK[$type]) ? $type : $this->MAP_CAT_FK[$type])." = ".((int) $object_id);
980
981 dol_syslog(get_class($this)."::containsObject", LOG_DEBUG);
982
983 $resql = $this->db->query($sql);
984 if ($resql) {
985 return $this->db->fetch_object($resql)->nb;
986 } else {
987 $this->error = $this->db->error();
988 return -1;
989 }
990 }
991
1003 public function getListForItem($id, $type = 'customer', $sortfield = "s.rowid", $sortorder = 'ASC', $limit = 0, $page = 0)
1004 {
1005 $categories = array();
1006
1007 $type = sanitizeVal($type, 'aZ09');
1008
1009 $sub_type = $type;
1010 $subcol_name = "fk_".$type;
1011 if ($type == "customer") {
1012 $sub_type = "societe";
1013 $subcol_name = "fk_soc";
1014 }
1015 if ($type == "supplier") {
1016 $sub_type = "fournisseur";
1017 $subcol_name = "fk_soc";
1018 }
1019 if ($type == "contact") {
1020 $subcol_name = "fk_socpeople";
1021 }
1022
1023 $idoftype = array_search($type, self::$MAP_ID_TO_CODE);
1024
1025 $sql = "SELECT s.rowid";
1026 $sql .= " FROM ".MAIN_DB_PREFIX."categorie as s, ".MAIN_DB_PREFIX."categorie_".$sub_type." as sub";
1027 $sql .= ' WHERE s.entity IN ('.getEntity('category').')';
1028 $sql .= ' AND s.type='.((int) $idoftype);
1029 $sql .= ' AND s.rowid = sub.fk_categorie';
1030 $sql .= " AND sub.".$subcol_name." = ".((int) $id);
1031
1032 $sql .= $this->db->order($sortfield, $sortorder);
1033
1034 $offset = 0;
1035 $nbtotalofrecords = '';
1036 if (!getDolGlobalInt('MAIN_DISABLE_FULL_SCANLIST')) {
1037 $result = $this->db->query($sql);
1038 $nbtotalofrecords = $this->db->num_rows($result);
1039 if (($page * $limit) > $nbtotalofrecords) { // if total resultset is smaller then paging size (filtering), goto and load page 0
1040 $page = 0;
1041 $offset = 0;
1042 }
1043 }
1044
1045 if ($limit) {
1046 if ($page < 0) {
1047 $page = 0;
1048 }
1049 $offset = $limit * $page;
1050
1051 $sql .= $this->db->plimit($limit + 1, $offset);
1052 }
1053
1054 $result = $this->db->query($sql);
1055 if ($result) {
1056 $i = 0;
1057 $num = $this->db->num_rows($result);
1058 $min = min($num, ($limit <= 0 ? $num : $limit));
1059 while ($i < $min) {
1060 $obj = $this->db->fetch_object($result);
1061 $category_static = new Categorie($this->db);
1062 if ($category_static->fetch($obj->rowid)) {
1063 $categories[$i]['id'] = $category_static->id;
1064 $categories[$i]['fk_parent'] = $category_static->fk_parent;
1065 $categories[$i]['label'] = $category_static->label;
1066 $categories[$i]['description'] = $category_static->description;
1067 $categories[$i]['color'] = $category_static->color;
1068 $categories[$i]['position'] = $category_static->position;
1069 $categories[$i]['socid'] = $category_static->socid;
1070 $categories[$i]['ref_ext'] = $category_static->ref_ext;
1071 $categories[$i]['visible'] = $category_static->visible;
1072 $categories[$i]['type'] = $category_static->type;
1073 $categories[$i]['entity'] = $category_static->entity;
1074 $categories[$i]['array_options'] = $category_static->array_options;
1075
1076 // multilangs
1077 if (getDolGlobalInt('MAIN_MULTILANGS') && isset($category_static->multilangs)) {
1078 $categories[$i]['multilangs'] = $category_static->multilangs;
1079 }
1080 }
1081 $i++;
1082 }
1083 } else {
1084 $this->error = $this->db->lasterror();
1085 return -1;
1086 }
1087 if (!count($categories)) {
1088 return 0;
1089 }
1090
1091 return $categories;
1092 }
1093
1094 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1100 public function get_filles()
1101 {
1102 // phpcs:enable
1103 $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."categorie";
1104 $sql .= " WHERE fk_parent = ".((int) $this->id);
1105 $sql .= " AND entity IN (".getEntity('category').")";
1106
1107 $res = $this->db->query($sql);
1108 if ($res) {
1109 $cats = array();
1110 while ($rec = $this->db->fetch_array($res)) {
1111 $cat = new Categorie($this->db);
1112 $cat->fetch($rec['rowid']);
1113 $cats[] = $cat;
1114 }
1115 return $cats;
1116 } else {
1117 dol_print_error($this->db);
1118 return -1;
1119 }
1120 }
1121
1122 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1128 protected function load_motherof()
1129 {
1130 // phpcs:enable
1131 $this->motherof = array();
1132
1133 // Load array[child]=parent
1134 $sql = "SELECT fk_parent as id_parent, rowid as id_son";
1135 $sql .= " FROM ".MAIN_DB_PREFIX."categorie";
1136 $sql .= " WHERE fk_parent != 0";
1137 $sql .= " AND entity IN (".getEntity('category').")";
1138
1139 dol_syslog(get_class($this)."::load_motherof", LOG_DEBUG);
1140 $resql = $this->db->query($sql);
1141 if ($resql) {
1142 while ($obj = $this->db->fetch_object($resql)) {
1143 $this->motherof[$obj->id_son] = $obj->id_parent;
1144 }
1145 return 1;
1146 } else {
1147 dol_print_error($this->db);
1148 return -1;
1149 }
1150 }
1151
1152 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1172 public function get_full_arbo($type, $fromid = 0, $include = 0)
1173 {
1174 // phpcs:enable
1175 global $langs;
1176
1177 if (!is_numeric($type)) {
1178 $type = $this->MAP_ID[$type];
1179 }
1180 if (is_null($type)) {
1181 $this->error = 'BadValueForParameterType';
1182 return -1;
1183 }
1184
1185 if (is_string($fromid)) {
1186 $fromid = explode(',', $fromid);
1187 } elseif (is_numeric($fromid)) {
1188 if ($fromid > 0) {
1189 $fromid = array($fromid);
1190 } else {
1191 $fromid = array();
1192 }
1193 } elseif (!is_array($fromid)) {
1194 $fromid = array();
1195 }
1196
1197 $this->cats = array();
1198 $nbcateg = 0;
1199
1200 // Init this->motherof that is array(id_son=>id_parent, ...)
1201 $this->load_motherof();
1202 $current_lang = $langs->getDefaultLang();
1203
1204 // Init $this->cats array
1205 $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
1206 if (getDolGlobalInt('MAIN_MULTILANGS')) {
1207 $sql .= ", t.label as label_trans, t.description as description_trans";
1208 }
1209 $sql .= " FROM ".MAIN_DB_PREFIX."categorie as c";
1210 if (getDolGlobalInt('MAIN_MULTILANGS')) {
1211 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."categorie_lang as t ON t.fk_category=c.rowid AND t.lang='".$this->db->escape($current_lang)."'";
1212 }
1213 $sql .= " WHERE c.entity IN (".getEntity('category').")";
1214 $sql .= " AND c.type = ".(int) $type;
1215
1216 dol_syslog(get_class($this)."::get_full_arbo get category list", LOG_DEBUG);
1217 $resql = $this->db->query($sql);
1218 if ($resql) {
1219 $i = 0;
1220 $nbcateg = $this->db->num_rows($resql);
1221
1222 while ($obj = $this->db->fetch_object($resql)) {
1223 $this->cats[$obj->rowid]['rowid'] = $obj->rowid;
1224 $this->cats[$obj->rowid]['id'] = $obj->rowid;
1225 $this->cats[$obj->rowid]['fk_parent'] = $obj->fk_parent;
1226 $this->cats[$obj->rowid]['label'] = !empty($obj->label_trans) ? $obj->label_trans : $obj->label;
1227 $this->cats[$obj->rowid]['description'] = !empty($obj->description_trans) ? $obj->description_trans : $obj->description;
1228 $this->cats[$obj->rowid]['color'] = $obj->color;
1229 $this->cats[$obj->rowid]['position'] = $obj->position;
1230 $this->cats[$obj->rowid]['visible'] = $obj->visible;
1231 $this->cats[$obj->rowid]['ref_ext'] = $obj->ref_ext;
1232 $this->cats[$obj->rowid]['picto'] = 'category';
1233 // fields are filled with buildPathFromId
1234 $this->cats[$obj->rowid]['fullpath'] = '';
1235 $this->cats[$obj->rowid]['fulllabel'] = '';
1236 $i++;
1237 }
1238 } else {
1239 dol_print_error($this->db);
1240 return -1;
1241 }
1242
1243 // We add the fullpath property to each elements of first level (no parent exists)
1244 dol_syslog(get_class($this)."::get_full_arbo call to buildPathFromId", LOG_DEBUG);
1245 foreach ($this->cats as $key => $val) {
1246 //print 'key='.$key.'<br>'."\n";
1247 $this->buildPathFromId($key, $nbcateg); // Process a branch from the root category key (this category has no parent) and adds kevek to $this->cats items
1248 }
1249
1250 // Include or exclude leaf (including $fromid) from tree
1251 if (count($fromid) > 0) {
1252 $keyfiltercatid = '('.implode('|', $fromid).')';
1253
1254 //print "Look to discard category ".$fromid."\n";
1255 $keyfilter1 = '^'.$keyfiltercatid.'$';
1256 $keyfilter2 = '_'.$keyfiltercatid.'$';
1257 $keyfilter3 = '^'.$keyfiltercatid.'_';
1258 $keyfilter4 = '_'.$keyfiltercatid.'_';
1259 foreach (array_keys($this->cats) as $key) {
1260 $fullpath = (string) $this->cats[$key]['fullpath'];
1261 $test = (preg_match('/'.$keyfilter1.'/', $fullpath) || preg_match('/'.$keyfilter2.'/', $fullpath)
1262 || preg_match('/'.$keyfilter3.'/', $fullpath) || preg_match('/'.$keyfilter4.'/', $fullpath));
1263
1264 if (($test && !$include) || (!$test && $include)) {
1265 unset($this->cats[$key]); // @phpstan-ignore-line
1266 }
1267 }
1268 }
1269
1270 dol_syslog(get_class($this)."::get_full_arbo dol_sort_array", LOG_DEBUG);
1271
1272 $this->cats = dol_sort_array($this->cats, 'fulllabel', 'asc', 1, 0, 1); // Sort on full label like "Label 1 >> Sublabel a >> Subsublabel"
1273
1274 return $this->cats;
1275 }
1276
1287 private function buildPathFromId($id_categ, $protection = 1000)
1288 {
1289 //dol_syslog(get_class($this)."::buildPathFromId id_categ=".$id_categ." protection=".$protection, LOG_DEBUG);
1290
1291 if (!empty($this->cats[$id_categ]['fullpath'])) {
1292 // Already defined
1293 dol_syslog(get_class($this)."::buildPathFromId fullpath and fulllabel already defined", LOG_WARNING);
1294 return -1;
1295 }
1296
1297 // First build full array $motherof
1298 //$this->load_motherof(); // Disabled because already done by caller of buildPathFromId
1299
1300 // $this->cats[$id_categ] is supposed to be already an array. We just want to complete it with property fullpath and fulllabel
1301
1302 // Define fullpath and fulllabel
1303 $this->cats[$id_categ]['fullpath'] = '_'.$id_categ;
1304 $this->cats[$id_categ]['fulllabel'] = $this->cats[$id_categ]['label'];
1305 $i = 0;
1306 $cursor_categ = $id_categ;
1307 //print 'Work for id_categ='.$id_categ.'<br>'."\n";
1308 while ((empty($protection) || $i < $protection) && !empty($this->motherof[$cursor_categ])) {
1309 //print '&nbsp; cursor_categ='.$cursor_categ.' i='.$i.' '.$this->motherof[$cursor_categ].'<br>'."\n";
1310 $this->cats[$id_categ]['fullpath'] = '_'.$this->motherof[$cursor_categ].$this->cats[$id_categ]['fullpath'];
1311 $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'];
1312 //print '&nbsp; Result for id_categ='.$id_categ.' : '.$this->cats[$id_categ]['fullpath'].' '.$this->cats[$id_categ]['fulllabel'].'<br>'."\n";
1313 $i++;
1314 $cursor_categ = $this->motherof[$cursor_categ];
1315 }
1316 //print 'Result for id_categ='.$id_categ.' : '.$this->cats[$id_categ]['fullpath'].'<br>'."\n";
1317
1318 // We count number of _ to have level
1319 $nbunderscore = substr_count($this->cats[$id_categ]['fullpath'], '_');
1320 $this->cats[$id_categ]['level'] = ($nbunderscore ? $nbunderscore : null);
1321
1322 return 1;
1323 }
1324
1325
1326 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1334 public function get_all_categories($type = null, $parent = false)
1335 {
1336 // phpcs:enable
1337 if (!is_numeric($type)) {
1338 $type = $this->MAP_ID[$type];
1339 }
1340
1341 $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."categorie";
1342 $sql .= " WHERE entity IN (".getEntity('category').")";
1343 if (!is_null($type)) {
1344 $sql .= " AND type = ".(int) $type;
1345 }
1346 if ($parent) {
1347 $sql .= " AND fk_parent = 0";
1348 }
1349
1350 $res = $this->db->query($sql);
1351 if ($res) {
1352 $cats = array();
1353 while ($rec = $this->db->fetch_array($res)) {
1354 $cat = new Categorie($this->db);
1355 $cat->fetch($rec['rowid']);
1356 $cats[$rec['rowid']] = $cat;
1357 }
1358 return $cats;
1359 } else {
1360 dol_print_error($this->db);
1361 return -1;
1362 }
1363 }
1364
1365 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1372 public function get_main_categories($type = null)
1373 {
1374 // phpcs:enable
1375 return $this->get_all_categories($type, true);
1376 }
1377
1378 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1384 public function already_exists()
1385 {
1386 // phpcs:enable
1387 $type = $this->type;
1388
1389 if (!is_numeric($type)) {
1390 $type = $this->MAP_ID[$type];
1391 }
1392
1393 /* We have to select any rowid from llx_categorie which category's mother and label
1394 * are equals to those of the calling category
1395 */
1396 $sql = "SELECT c.rowid";
1397 $sql .= " FROM ".MAIN_DB_PREFIX."categorie as c ";
1398 $sql .= " WHERE c.entity IN (".getEntity('category').")";
1399 $sql .= " AND c.type = ".((int) $type);
1400 $sql .= " AND c.fk_parent = ".((int) $this->fk_parent);
1401 $sql .= " AND c.label = '".$this->db->escape($this->label)."'";
1402
1403 dol_syslog(get_class($this)."::already_exists", LOG_DEBUG);
1404
1405 $resql = $this->db->query($sql);
1406 if ($resql) {
1407 if ($this->db->num_rows($resql) > 0) { // Checking for empty resql
1408 $obj = $this->db->fetch_object($resql);
1409 /* If object called create, obj cannot have is id.
1410 * If object called update, he mustn't have the same label as an other category for this mother.
1411 * 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.
1412 */
1413 if (!empty($obj) && $obj->rowid > 0 && $obj->rowid != $this->id) {
1414 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);
1415 return 1;
1416 }
1417 }
1418 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);
1419 return 0;
1420 } else {
1421 $this->error = $this->db->error();
1422 return -1;
1423 }
1424 }
1425
1426
1427 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1438 public function print_all_ways($sep = '&gt;&gt;', $url = '', $nocolor = 0, $addpicto = 0)
1439 {
1440 // phpcs:enable
1441 $ways = array();
1442
1443 $all_ways = $this->get_all_ways(); // Load array of categories
1444 foreach ($all_ways as $way) {
1445 $w = array();
1446 $i = 0;
1447 $forced_color = '';
1448 foreach ($way as $cat) {
1449 $i++;
1450
1451 if (empty($nocolor)) {
1452 $forced_color = 'colortoreplace';
1453 if ($i == count($way)) { // Last category in hierarchy
1454 // Check contrast with background and correct text color
1455 $forced_color = 'categtextwhite';
1456 if ($cat->color) {
1457 if (colorIsLight($cat->color)) {
1458 $forced_color = 'categtextblack';
1459 }
1460 }
1461 }
1462 }
1463
1464 if ($url == '') {
1465 $link = '<a href="'.DOL_URL_ROOT.'/categories/viewcat.php?id='.$cat->id.'&type='.$cat->type.'" class="'.$forced_color.'">';
1466 $linkend = '</a>';
1467 $w[] = $link.(($addpicto && $i == 1) ? img_object('', 'category', 'class="paddingright"') : '').$cat->label.$linkend;
1468 } elseif ($url == 'none') {
1469 $link = '<span class="'.$forced_color.'">';
1470 $linkend = '</span>';
1471 $w[] = $link.(($addpicto && $i == 1) ? img_object('', 'category', 'class="paddingright"') : '').$cat->label.$linkend;
1472 } else {
1473 $w[] = '<a class="'.$forced_color.'" href="'.DOL_URL_ROOT.'/'.$url.'?catid='.$cat->id.'">'.($addpicto ? img_object('', 'category') : '').$cat->label.'</a>';
1474 }
1475 }
1476 $newcategwithpath = preg_replace('/colortoreplace/', $forced_color, implode('<span class="inline-block valignmiddle paddingleft paddingright '.$forced_color.'">'.$sep.'</span>', $w));
1477
1478 $ways[] = $newcategwithpath;
1479 }
1480
1481 return $ways;
1482 }
1483
1484
1485 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1491 public function get_meres()
1492 {
1493 // phpcs:enable
1494 $parents = array();
1495
1496 $sql = "SELECT fk_parent FROM ".MAIN_DB_PREFIX."categorie";
1497 $sql .= " WHERE rowid = ".((int) $this->id);
1498
1499 $res = $this->db->query($sql);
1500
1501 if ($res) {
1502 while ($rec = $this->db->fetch_array($res)) {
1503 if ($rec['fk_parent'] > 0) {
1504 $cat = new Categorie($this->db);
1505 $cat->fetch($rec['fk_parent']);
1506 $parents[] = $cat;
1507 }
1508 }
1509 return $parents;
1510 } else {
1511 dol_print_error($this->db);
1512 return -1;
1513 }
1514 }
1515
1516 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1523 public function get_all_ways()
1524 {
1525 // phpcs:enable
1526 $ways = array();
1527
1528 $parents = $this->get_meres();
1529 if (is_array($parents)) {
1530 foreach ($parents as $parent) {
1531 $all_ways = $parent->get_all_ways();
1532 foreach ($all_ways as $way) {
1533 $w = $way;
1534 $w[] = $this;
1535 $ways[] = $w;
1536 }
1537 }
1538 }
1539
1540 if (count($ways) == 0) {
1541 $ways[0][0] = $this;
1542 }
1543
1544 return $ways;
1545 }
1546
1557 public function containing($id, $type, $mode = 'object')
1558 {
1559 $cats = array();
1560
1561 if (is_numeric($type)) {
1562 $type = Categorie::$MAP_ID_TO_CODE[$type];
1563 }
1564
1565 if ($type === Categorie::TYPE_BANK_LINE) { // TODO Remove this with standard category code after migration of llx_category_bank into llx_categorie
1566 // Load bank categories
1567 $sql = "SELECT c.label, c.rowid";
1568 $sql .= " FROM ".MAIN_DB_PREFIX."category_bankline as a, ".MAIN_DB_PREFIX."category_bank as c";
1569 $sql .= " WHERE a.lineid=".((int) $id)." AND a.fk_categ = c.rowid";
1570 $sql .= " AND c.entity IN (".getEntity('category').")";
1571 $sql .= " ORDER BY c.label";
1572
1573 $res = $this->db->query($sql);
1574 if ($res) {
1575 while ($obj = $this->db->fetch_object($res)) {
1576 if ($mode == 'id') {
1577 $cats[] = $obj->rowid;
1578 } elseif ($mode == 'label') {
1579 $cats[] = $obj->label;
1580 } else {
1581 $cat = new Categorie($this->db);
1582 $cat->id = $obj->rowid;
1583 $cat->label = $obj->label;
1584 $cats[] = $cat;
1585 }
1586 }
1587 } else {
1588 dol_print_error($this->db);
1589 return -1;
1590 }
1591 } else {
1592 $sql = "SELECT ct.fk_categorie, c.label, c.rowid";
1593 $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";
1594 $sql .= " WHERE ct.fk_categorie = c.rowid AND ct.fk_".(empty($this->MAP_CAT_FK[$type]) ? $type : $this->MAP_CAT_FK[$type])." = ".(int) $id;
1595 // This seems useless because the table already contains id of category of 1 unique type. So commented.
1596 // So now it works also with external added categories.
1597 //$sql .= " AND c.type = ".((int) $this->MAP_ID[$type]);
1598 $sql .= " AND c.entity IN (".getEntity('category').")";
1599
1600 $res = $this->db->query($sql);
1601 if ($res) {
1602 while ($obj = $this->db->fetch_object($res)) {
1603 if ($mode == 'id') {
1604 $cats[] = $obj->rowid;
1605 } elseif ($mode == 'label') {
1606 $cats[] = $obj->label;
1607 } else {
1608 $cat = new Categorie($this->db);
1609 $cat->fetch($obj->fk_categorie);
1610 $cats[] = $cat;
1611 }
1612 }
1613 } else {
1614 dol_print_error($this->db);
1615 return -1;
1616 }
1617 }
1618
1619 return $cats;
1620 }
1621
1633 public function rechercher($id, $nom, $type, $exact = false, $case = false)
1634 {
1635 // Deprecation warning
1636 if (is_numeric($type)) {
1637 dol_syslog(__METHOD__.': using numeric types is deprecated.', LOG_WARNING);
1638 }
1639
1640 $cats = array();
1641
1642 // For backward compatibility
1643 if (is_numeric($type)) {
1644 // We want to reverse lookup
1645 $map_type = array_flip($this->MAP_ID);
1646 $type = $map_type[$type];
1647 dol_syslog(get_class($this)."::rechercher(): numeric types are deprecated, please use string instead", LOG_WARNING);
1648 }
1649
1650 // Generation requete recherche
1651 $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."categorie";
1652 $sql .= " WHERE type = ".((int) $this->MAP_ID[$type]);
1653 $sql .= " AND entity IN (".getEntity('category').")";
1654 if ($nom) {
1655 if (!$exact) {
1656 $nom = '%'.$this->db->escape(str_replace('*', '%', $nom)).'%';
1657 }
1658 if (!$case) {
1659 $sql .= " AND label LIKE '".$this->db->escape($nom)."'";
1660 } else {
1661 $sql .= " AND label LIKE BINARY '".$this->db->escape($nom)."'";
1662 }
1663 }
1664 if ($id) {
1665 $sql .= " AND rowid = ".((int) $id);
1666 }
1667
1668 $res = $this->db->query($sql);
1669 if ($res) {
1670 while ($rec = $this->db->fetch_array($res)) {
1671 $cat = new Categorie($this->db);
1672 $cat->fetch($rec['rowid']);
1673 $cats[] = $cat;
1674 }
1675
1676 return $cats;
1677 } else {
1678 $this->error = $this->db->error().' sql='.$sql;
1679 return -1;
1680 }
1681 }
1682
1689 public function isAnyPhotoAvailable($sdir)
1690 {
1691 include_once DOL_DOCUMENT_ROOT . '/core/lib/files.lib.php';
1692 include_once DOL_DOCUMENT_ROOT . '/core/lib/images.lib.php';
1693
1694 $sdir .= '/' . get_exdir($this->id, 2, 0, 0, $this, 'category') . $this->id . "/photos/";
1695
1696 $dir_osencoded = dol_osencode($sdir);
1697 if (file_exists($dir_osencoded)) {
1698 $handle = opendir($dir_osencoded);
1699 if (is_resource($handle)) {
1700 while (($file = readdir($handle)) !== false) {
1701 if (!utf8_check($file)) {
1702 $file = mb_convert_encoding($file, 'UTF-8', 'ISO-8859-1'); // To be sure data is stored in UTF8 in memory
1703 }
1704 if (dol_is_file($sdir . $file) && image_format_supported($file) >= 0) {
1705 return true;
1706 }
1707 }
1708 }
1709 }
1710 return false;
1711 }
1712
1719 public function getTooltipContentArray($params)
1720 {
1721 global $langs;
1722
1723 $langs->load('categories');
1724
1725 $datas = [];
1726
1727 $datas['label'] = $langs->trans("ShowCategory").': '.($this->ref ? $this->ref : $this->label);
1728
1729 return $datas;
1730 }
1731
1745 public function getNomUrl($withpicto = 0, $option = '', $maxlength = 0, $moreparam = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = 0)
1746 {
1747 global $conf, $langs, $hookmanager;
1748
1749 if (!empty($conf->dol_no_mouse_hover)) {
1750 $notooltip = 1; // Force disable tooltips
1751 }
1752
1753 $result = '';
1754 $params = [
1755 'id' => $this->id,
1756 'objecttype' => $this->element,
1757 'option' => $option,
1758 ];
1759 $classfortooltip = 'classfortooltip';
1760 $dataparams = '';
1761 if (getDolGlobalInt('MAIN_ENABLE_AJAX_TOOLTIP')) {
1762 $classfortooltip = 'classforajaxtooltip';
1763 $dataparams = ' data-params="'.dol_escape_htmltag(json_encode($params)).'"';
1764 $label = '';
1765 } else {
1766 $label = implode($this->getTooltipContentArray($params));
1767 }
1768
1769 $url = DOL_URL_ROOT.'/categories/viewcat.php?id='.$this->id.'&type='.$this->type.$moreparam.'&backtopage='.urlencode($_SERVER['PHP_SELF'].($moreparam ? '?'.$moreparam : ''));
1770
1771 if ($option !== 'nolink') {
1772 // Add param to save lastsearch_values or not
1773 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
1774 if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
1775 $add_save_lastsearch_values = 1;
1776 }
1777 if ($url && $add_save_lastsearch_values) {
1778 $url .= '&save_lastsearch_values=1';
1779 }
1780 }
1781
1782 // Check contrast with background and correct text color
1783 $forced_color = 'categtextwhite';
1784 if ($this->color) {
1785 if (colorIsLight($this->color)) {
1786 $forced_color = 'categtextblack';
1787 }
1788 }
1789
1790 $linkclose = '';
1791 if (empty($notooltip)) {
1792 if (getDolGlobalInt('MAIN_OPTIMIZEFORTEXTBROWSER')) {
1793 $label = $langs->trans("ShowMyObject");
1794 $linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"';
1795 }
1796 $linkclose .= ($label ? ' title="'.dol_escape_htmltag($label, 1).'"' : ' title="tocomplete"');
1797 $linkclose .= $dataparams.' class="'.$classfortooltip.' '.$forced_color.($morecss ? ' '.$morecss : '').'"';
1798 } else {
1799 $linkclose = ($morecss ? ' class="'.$forced_color.($morecss ? ' '.$morecss : '').'"' : '');
1800 }
1801
1802 if ($option == 'nolink' || empty($url)) {
1803 $linkstart = '<span';
1804 } else {
1805 $linkstart = '<a href="'.$url.'"';
1806 }
1807 $linkstart .= $linkclose.'>';
1808 if ($option == 'nolink' || empty($url)) {
1809 $linkend = '</span>';
1810 } else {
1811 $linkend = '</a>';
1812 }
1813
1814 $result .= $linkstart;
1815
1816 if ($withpicto) {
1817 $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'"'), 0, 0, $notooltip ? 0 : 1);
1818 }
1819
1820 if ($withpicto != 2) {
1821 $result .= dol_trunc(($this->ref ? $this->ref : $this->label), $maxlength);
1822 }
1823
1824 $result .= $linkend;
1825
1826 global $action;
1827 $hookmanager->initHooks(array($this->element . 'dao'));
1828 $parameters = array('id' => $this->id, 'getnomurl' => &$result);
1829 $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
1830 if ($reshook > 0) {
1831 $result = $hookmanager->resPrint;
1832 } else {
1833 $result .= $hookmanager->resPrint;
1834 }
1835 return $result;
1836 }
1837
1838
1839 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1847 public function add_photo($sdir, $file)
1848 {
1849 // phpcs:enable
1850 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
1851
1852 $dir = $sdir.'/'.get_exdir($this->id, 2, 0, 0, $this, 'category').$this->id."/";
1853 $dir .= "photos/";
1854
1855 if (!file_exists($dir)) {
1856 dol_mkdir($dir);
1857 }
1858
1859 if (file_exists($dir)) {
1860 if (is_array($file['name'])) {
1861 $nbfile = count($file['name']);
1862 for ($i = 0; $i < $nbfile; $i++) {
1863 $originImage = $dir.$file['name'][$i];
1864
1865 // Cree fichier en taille origine
1866 dol_move_uploaded_file($file['tmp_name'][$i], $originImage, 1, 0, 0);
1867
1868 if (file_exists($originImage)) {
1869 // Create thumbs
1870 $this->addThumbs($originImage);
1871 }
1872 }
1873 } else {
1874 $originImage = $dir.$file['name'];
1875
1876 // Cree fichier en taille origine
1877 dol_move_uploaded_file($file['tmp_name'], $originImage, 1, 0, 0);
1878
1879 if (file_exists($originImage)) {
1880 // Create thumbs
1881 $this->addThumbs($originImage);
1882 }
1883 }
1884 }
1885 }
1886
1887 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1895 public function liste_photos($dir, $nbmax = 0)
1896 {
1897 // phpcs:enable
1898 include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
1899
1900 $nbphoto = 0;
1901 $tabobj = array();
1902
1903 $dirthumb = $dir.'thumbs/';
1904
1905 if (file_exists($dir)) {
1906 $handle = opendir($dir);
1907 if (is_resource($handle)) {
1908 while (($file = readdir($handle)) !== false) {
1909 if (dol_is_file($dir.$file) && preg_match('/(\.jpeg|\.jpg|\.bmp|\.gif|\.png|\.tiff)$/i', $dir.$file)) {
1910 $nbphoto++;
1911 $photo = $file;
1912
1913 // On determine nom du fichier vignette
1914 $photo_vignette = '';
1915 $regs = array();
1916 if (preg_match('/(\.jpeg|\.jpg|\.bmp|\.gif|\.png|\.tiff)$/i', $photo, $regs)) {
1917 $photo_vignette = preg_replace('/'.$regs[0].'/i', '', $photo).'_small'.$regs[0];
1918 }
1919
1920 // Object
1921 $obj = array();
1922 $obj['photo'] = $photo;
1923 if ($photo_vignette && is_file($dirthumb.$photo_vignette)) {
1924 $obj['photo_vignette'] = 'thumbs/'.$photo_vignette;
1925 } else {
1926 $obj['photo_vignette'] = "";
1927 }
1928
1929 $tabobj[$nbphoto - 1] = $obj;
1930
1931 // On continue ou on arrete de boucler
1932 if ($nbmax && $nbphoto >= $nbmax) {
1933 break;
1934 }
1935 }
1936 }
1937
1938 closedir($handle);
1939 }
1940 }
1941
1942 return $tabobj;
1943 }
1944
1945 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1952 public function delete_photo($file)
1953 {
1954 // phpcs:enable
1955 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
1956
1957 $dir = dirname($file).'/'; // Chemin du dossier contenant l'image d'origine
1958 $dirthumb = $dir.'/thumbs/'; // Chemin du dossier contenant la vignette
1959 $filename = preg_replace('/'.preg_quote($dir, '/').'/i', '', $file); // Nom du fichier
1960
1961 // On efface l'image d'origine
1962 dol_delete_file($file, 1);
1963
1964 // Si elle existe, on efface la vignette
1965 $regs = array();
1966 if (preg_match('/(\.jpeg|\.jpg|\.bmp|\.gif|\.png|\.tiff)$/i', $filename, $regs)) {
1967 $photo_vignette = preg_replace('/'.$regs[0].'/i', '', $filename).'_small'.$regs[0];
1968 if (file_exists($dirthumb.$photo_vignette)) {
1969 dol_delete_file($dirthumb.$photo_vignette, 1);
1970 }
1971 }
1972 }
1973
1974 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1981 public function get_image_size($file)
1982 {
1983 // phpcs:enable
1984 $infoImg = getimagesize($file); // Recuperation des infos de l'image
1985 $this->imgWidth = $infoImg[0]; // Largeur de l'image
1986 $this->imgHeight = $infoImg[1]; // Hauteur de l'image
1987 }
1988
1997 public function setMultiLangs(User $user, $notrigger = 0)
1998 {
1999 global $langs;
2000
2001 $langs_available = $langs->get_available_languages();
2002 $current_lang = $langs->getDefaultLang();
2003
2004 foreach ($langs_available as $key => $value) {
2005 $sql = "SELECT rowid";
2006 $sql .= " FROM ".MAIN_DB_PREFIX."categorie_lang";
2007 $sql .= " WHERE fk_category=".((int) $this->id);
2008 $sql .= " AND lang = '".$this->db->escape($key)."'";
2009
2010 $result = $this->db->query($sql);
2011
2012 if ($key == $current_lang) {
2013 $sql2 = '';
2014 if ($this->db->num_rows($result)) { // si aucune ligne dans la base
2015 $sql2 = "UPDATE ".MAIN_DB_PREFIX."categorie_lang";
2016 $sql2 .= " SET label = '".$this->db->escape($this->label)."',";
2017 $sql2 .= " description = '".$this->db->escape($this->description)."'";
2018 $sql2 .= " WHERE fk_category = ".((int) $this->id)." AND lang = '".$this->db->escape($key)."'";
2019 } elseif (isset($this->multilangs[$key])) {
2020 $sql2 = "INSERT INTO ".MAIN_DB_PREFIX."categorie_lang (fk_category, lang, label, description)";
2021 $sql2 .= " VALUES(".((int) $this->id).", '".$this->db->escape($key)."', '".$this->db->escape($this->label)."'";
2022 $sql2 .= ", '".$this->db->escape($this->multilangs[$key]["description"])."')";
2023 }
2024 dol_syslog(get_class($this).'::setMultiLangs', LOG_DEBUG);
2025 if ($sql2 && !$this->db->query($sql2)) {
2026 $this->error = $this->db->lasterror();
2027 return -1;
2028 }
2029 } elseif (isset($this->multilangs[$key])) {
2030 if ($this->db->num_rows($result)) { // si aucune ligne dans la base
2031 $sql2 = "UPDATE ".MAIN_DB_PREFIX."categorie_lang";
2032 $sql2 .= " SET label='".$this->db->escape($this->multilangs[$key]["label"])."',";
2033 $sql2 .= " description='".$this->db->escape($this->multilangs[$key]["description"])."'";
2034 $sql2 .= " WHERE fk_category=".((int) $this->id)." AND lang='".$this->db->escape($key)."'";
2035 } else {
2036 $sql2 = "INSERT INTO ".MAIN_DB_PREFIX."categorie_lang (fk_category, lang, label, description)";
2037 $sql2 .= " VALUES(".((int) $this->id).", '".$this->db->escape($key)."', '".$this->db->escape($this->multilangs[$key]["label"])."'";
2038 $sql2 .= ",'".$this->db->escape($this->multilangs[$key]["description"])."')";
2039 }
2040
2041 // on ne sauvegarde pas des champs vides
2042 if ($this->multilangs[$key]["label"] || $this->multilangs[$key]["description"] || $this->multilangs[$key]["note"]) {
2043 dol_syslog(get_class($this).'::setMultiLangs', LOG_DEBUG);
2044 }
2045 if (!$this->db->query($sql2)) {
2046 $this->error = $this->db->lasterror();
2047 return -1;
2048 }
2049 }
2050 }
2051
2052 // Call trigger
2053 if (!$notrigger) {
2054 $result = $this->call_trigger('CATEGORY_SET_MULTILANGS', $user);
2055 if ($result < 0) {
2056 $this->error = $this->db->lasterror();
2057 return -1;
2058 }
2059 }
2060 // End call triggers
2061
2062 return 1;
2063 }
2064
2070 public function getMultiLangs()
2071 {
2072 global $langs;
2073
2074 $current_lang = $langs->getDefaultLang();
2075
2076 $sql = "SELECT lang, label, description";
2077 $sql .= " FROM ".MAIN_DB_PREFIX."categorie_lang";
2078 $sql .= " WHERE fk_category=".((int) $this->id);
2079
2080 $result = $this->db->query($sql);
2081 if ($result) {
2082 while ($obj = $this->db->fetch_object($result)) {
2083 //print 'lang='.$obj->lang.' current='.$current_lang.'<br>';
2084 if ($obj->lang == $current_lang) { // si on a les traduct. dans la langue courante on les charge en infos principales.
2085 $this->label = $obj->label;
2086 $this->description = $obj->description;
2087 }
2088 $this->multilangs[$obj->lang]["label"] = $obj->label;
2089 $this->multilangs[$obj->lang]["description"] = $obj->description;
2090 }
2091 return 1;
2092 } else {
2093 $this->error = $langs->trans("Error")." : ".$this->db->error()." - ".$sql;
2094 return -1;
2095 }
2096 }
2097
2104 public function getLibStatut($mode)
2105 {
2106 return '';
2107 }
2108
2109
2117 public function initAsSpecimen()
2118 {
2119 dol_syslog(get_class($this)."::initAsSpecimen");
2120
2121 // Initialise parameters
2122 $this->id = 0;
2123 $this->fk_parent = 0;
2124 $this->label = 'SPECIMEN';
2125 $this->specimen = 1;
2126 $this->description = 'This is a description';
2127 $this->socid = 1;
2128 $this->type = self::TYPE_PRODUCT;
2129
2130 return 1;
2131 }
2132
2141 public static function replaceThirdparty(DoliDB $dbs, $origin_id, $dest_id)
2142 {
2143 $tables = array(
2144 'categorie_societe'
2145 );
2146
2147 return CommonObject::commonReplaceThirdparty($dbs, $origin_id, $dest_id, $tables, 1);
2148 }
2149
2158 public static function getFilterJoinQuery($type, $rowIdName)
2159 {
2160 if ($type == 'bank_account') {
2161 $type = 'account';
2162 }
2163
2164 return " LEFT JOIN ".MAIN_DB_PREFIX."categorie_".$type." as cp ON ".$rowIdName." = cp.fk_".$type;
2165 }
2166
2176 public static function getFilterSelectQuery($type, $rowIdName, $searchList)
2177 {
2178 if ($type == 'bank_account') {
2179 $type = 'account';
2180 }
2181 if ($type == 'customer') {
2182 $type = 'societe';
2183 }
2184 if ($type == 'supplier') {
2185 $type = 'fournisseur';
2186 }
2187
2188 if (empty($searchList) && !is_array($searchList)) {
2189 return "";
2190 }
2191
2192 $searchCategorySqlList = array();
2193 foreach ($searchList as $searchCategory) {
2194 if (intval($searchCategory) == -2) {
2195 $searchCategorySqlList[] = " cp.fk_categorie IS NULL";
2196 } elseif (intval($searchCategory) > 0) {
2197 $searchCategorySqlList[] = " ".$rowIdName." IN (SELECT fk_".$type." FROM ".MAIN_DB_PREFIX."categorie_".$type." WHERE fk_categorie = ".((int) $searchCategory).")";
2198 }
2199 }
2200
2201 if (!empty($searchCategorySqlList)) {
2202 return " AND (".implode(' AND ', $searchCategorySqlList).")";
2203 } else {
2204 return "";
2205 }
2206 }
2207
2213 public function countNbOfCategories()
2214 {
2215 dol_syslog(get_class($this)."::count_all_categories", LOG_DEBUG);
2216 $sql = "SELECT COUNT(rowid) FROM ".MAIN_DB_PREFIX."categorie";
2217 $sql .= " WHERE entity IN (".getEntity('category').")";
2218
2219 $res = $this->db->query($sql);
2220 if ($res) {
2221 $obj = $this->db->fetch_object($res);
2222 return $obj->count;
2223 } else {
2224 dol_print_error($this->db);
2225 return -1;
2226 }
2227 }
2228}
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.
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.
static replaceThirdparty(DoliDB $dbs, $origin_id, $dest_id)
Function used to replace a thirdparty id with another one.
setMultiLangs(User $user, $notrigger=0)
Update ou cree les traductions des infos produits.
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