dolibarr  x.y.z
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-2022 Frédéric France <frederic.france@netlogic.fr>
14  *
15  * This program is free software; you can redistribute it and/or modify
16  * it under the terms of the GNU General Public License as published by
17  * the Free Software Foundation; either version 3 of the License, or
18  * (at your option) any later version.
19  *
20  * This program is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23  * GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License
26  * along with this program. If not, see <https://www.gnu.org/licenses/>.
27  */
28 
35 require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
36 require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
37 require_once DOL_DOCUMENT_ROOT.'/ticket/class/ticket.class.php';
38 require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.class.php';
39 require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php';
40 require_once DOL_DOCUMENT_ROOT.'/knowledgemanagement/class/knowledgerecord.class.php';
41 
42 
46 class Categorie extends CommonObject
47 {
48  // Categories types (we use string because we want to accept any modules/types in a future)
49  const TYPE_PRODUCT = 'product';
50  const TYPE_SUPPLIER = 'supplier';
51  const TYPE_CUSTOMER = 'customer';
52  const TYPE_MEMBER = 'member';
53  const TYPE_CONTACT = 'contact';
54  const TYPE_USER = 'user';
55  const TYPE_PROJECT = 'project';
56  const TYPE_ACCOUNT = 'bank_account';
57  const TYPE_BANK_LINE = 'bank_line';
58  const TYPE_WAREHOUSE = 'warehouse';
59  const TYPE_ACTIONCOMM = 'actioncomm';
60  const TYPE_WEBSITE_PAGE = 'website_page';
61  const TYPE_TICKET = 'ticket';
62  const TYPE_KNOWLEDGEMANAGEMENT = 'knowledgemanagement';
63 
67  public $picto = 'category';
68 
69 
73  protected $MAP_ID = array(
74  'product' => 0,
75  'supplier' => 1,
76  'customer' => 2,
77  'member' => 3,
78  'contact' => 4,
79  'bank_account' => 5,
80  'project' => 6,
81  'user' => 7,
82  'bank_line' => 8,
83  'warehouse' => 9,
84  'actioncomm' => 10,
85  'website_page' => 11,
86  'ticket' => 12,
87  'knowledgemanagement' => 13
88  );
89 
95  public static $MAP_ID_TO_CODE = array(
96  0 => 'product',
97  1 => 'supplier',
98  2 => 'customer',
99  3 => 'member',
100  4 => 'contact',
101  5 => 'bank_account',
102  6 => 'project',
103  7 => 'user',
104  8 => 'bank_line',
105  9 => 'warehouse',
106  10 => 'actioncomm',
107  11 => 'website_page',
108  12 => 'ticket',
109  13 => 'knowledgemanagement'
110  );
111 
117  public $MAP_CAT_FK = array(
118  'customer' => 'soc',
119  'supplier' => 'soc',
120  'contact' => 'socpeople',
121  'bank_account' => 'account',
122  );
123 
129  public $MAP_CAT_TABLE = array(
130  'customer' => 'societe',
131  'supplier' => 'fournisseur',
132  'bank_account'=> 'account',
133  );
134 
140  public $MAP_OBJ_CLASS = array(
141  'product' => 'Product',
142  'customer' => 'Societe',
143  'supplier' => 'Fournisseur',
144  'member' => 'Adherent',
145  'contact' => 'Contact',
146  'user' => 'User',
147  'account' => 'Account', // old for bank account
148  'bank_account' => 'Account',
149  'project' => 'Project',
150  'warehouse'=> 'Entrepot',
151  'actioncomm' => 'ActionComm',
152  'website_page' => 'WebsitePage',
153  'ticket' => 'Ticket',
154  'knowledgemanagement' => 'KnowledgeRecord'
155  );
156 
162  public static $MAP_TYPE_TITLE_AREA = array(
163  'product' => 'ProductsCategoriesArea',
164  'customer' => 'CustomersCategoriesArea',
165  'supplier' => 'SuppliersCategoriesArea',
166  'member' => 'MembersCategoriesArea',
167  'contact' => 'ContactsCategoriesArea',
168  'user' => 'UsersCategoriesArea',
169  'account' => 'AccountsCategoriesArea', // old for bank account
170  'bank_account' => 'AccountsCategoriesArea',
171  'project' => 'ProjectsCategoriesArea',
172  'warehouse'=> 'StocksCategoriesArea',
173  'actioncomm' => 'ActioncommCategoriesArea',
174  'website_page' => 'WebsitePageCategoriesArea'
175  );
176 
181  public $MAP_OBJ_TABLE = array(
182  'customer' => 'societe',
183  'supplier' => 'societe',
184  'member' => 'adherent',
185  'contact' => 'socpeople',
186  'account' => 'bank_account', // old for bank account
187  'project' => 'projet',
188  'warehouse'=> 'entrepot',
189  'knowledgemanagement' => 'knowledgemanagement_knowledgerecord'
190  );
191 
195  public $element = 'category';
196 
200  public $table_element = 'categorie';
201 
205  public $fk_parent;
206 
210  public $label;
211 
215  public $description;
216 
220  public $color;
221 
225  public $visible;
226 
230  public $socid;
231 
249  public $type;
250 
254  public $cats = array();
255 
259  public $motherof = array();
260 
264  public $childs = array();
265 
266 
272  public function __construct($db)
273  {
274  global $hookmanager;
275 
276  $this->db = $db;
277 
278  if (is_object($hookmanager)) {
279  $hookmanager->initHooks(array('category'));
280  $parameters = array();
281  $reshook = $hookmanager->executeHooks('constructCategory', $parameters, $this); // Note that $action and $object may have been modified by some hooks
282  if ($reshook >= 0 && !empty($hookmanager->resArray)) {
283  foreach ($hookmanager->resArray as $mapList) {
284  $mapId = $mapList['id'];
285  $mapCode = $mapList['code'];
286  self::$MAP_ID_TO_CODE[$mapId] = $mapCode;
287  $this->MAP_ID[$mapCode] = $mapId;
288  $this->MAP_CAT_FK[$mapCode] = $mapList['cat_fk'];
289  $this->MAP_CAT_TABLE[$mapCode] = $mapList['cat_table'];
290  $this->MAP_OBJ_CLASS[$mapCode] = $mapList['obj_class'];
291  $this->MAP_OBJ_TABLE[$mapCode] = $mapList['obj_table'];
292  }
293  }
294  }
295  }
296 
302  public function getMapList()
303  {
304  $mapList = array();
305 
306  foreach ($this->MAP_ID as $mapCode => $mapId) {
307  $mapList[] = array(
308  'id' => $mapId,
309  'code' => $mapCode,
310  'cat_fk' => (empty($this->MAP_CAT_FK[$mapCode]) ? $mapCode : $this->MAP_CAT_FK[$mapCode]),
311  'cat_table' => (empty($this->MAP_CAT_TABLE[$mapCode]) ? $mapCode : $this->MAP_CAT_TABLE[$mapCode]),
312  'obj_class' => (empty($this->MAP_OBJ_CLASS[$mapCode]) ? $mapCode : $this->MAP_OBJ_CLASS[$mapCode]),
313  'obj_table' => (empty($this->MAP_OBJ_TABLE[$mapCode]) ? $mapCode : $this->MAP_OBJ_TABLE[$mapCode])
314  );
315  }
316 
317  return $mapList;
318  }
319 
329  public function fetch($id, $label = '', $type = null, $ref_ext = '')
330  {
331  global $conf;
332 
333  // Check parameters
334  if (empty($id) && empty($label) && empty($ref_ext)) {
335  $this->error = "No category to search for";
336  return -1;
337  }
338  if (!is_null($type) && !is_numeric($type)) {
339  $type = $this->MAP_ID[$type];
340  }
341 
342  $sql = "SELECT rowid, fk_parent, entity, label, description, color, fk_soc, visible, type, ref_ext";
343  $sql .= ", date_creation, tms, fk_user_creat, fk_user_modif";
344  $sql .= " FROM ".MAIN_DB_PREFIX."categorie";
345  if ($id) {
346  $sql .= " WHERE rowid = ".((int) $id);
347  } elseif (!empty($ref_ext)) {
348  $sql .= " WHERE ref_ext LIKE '".$this->db->escape($ref_ext)."'";
349  } else {
350  $sql .= " WHERE label = '".$this->db->escape($label)."' AND entity IN (".getEntity('category').")";
351  if (!is_null($type)) {
352  $sql .= " AND type = ".((int) $type);
353  }
354  }
355 
356  dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
357  $resql = $this->db->query($sql);
358  if ($resql) {
359  if ($this->db->num_rows($resql) > 0) {
360  $res = $this->db->fetch_array($resql);
361 
362  $this->id = $res['rowid'];
363  //$this->ref = $res['rowid'];
364  $this->fk_parent = (int) $res['fk_parent'];
365  $this->label = $res['label'];
366  $this->description = $res['description'];
367  $this->color = $res['color'];
368  $this->socid = (int) $res['fk_soc'];
369  $this->visible = (int) $res['visible'];
370  $this->type = (int) $res['type'];
371  $this->ref_ext = $res['ref_ext'];
372  $this->entity = (int) $res['entity'];
373  $this->date_creation = $this->db->jdate($res['date_creation']);
374  $this->date_modification = $this->db->jdate($res['tms']);
375  $this->user_creation_id = (int) $res['fk_user_creat'];
376  $this->user_modification_id = (int) $res['fk_user_modif'];
377  $this->user_creation = (int) $res['fk_user_creat'];
378  $this->user_modification = (int) $res['fk_user_modif'];
379 
380  // Retrieve all extrafield
381  // fetch optionals attributes and labels
382  $this->fetch_optionals();
383 
384  $this->db->free($resql);
385 
386  // multilangs
387  if (getDolGlobalInt('MAIN_MULTILANGS')) {
388  $this->getMultiLangs();
389  }
390 
391  return 1;
392  } else {
393  $this->error = "No category found";
394  return 0;
395  }
396  } else {
397  dol_print_error($this->db);
398  $this->error = $this->db->lasterror;
399  $this->errors[] = $this->db->lasterror;
400  return -1;
401  }
402  }
403 
413  public function create($user)
414  {
415  global $conf, $langs, $hookmanager;
416  $langs->load('categories');
417 
418  $type = $this->type;
419 
420  if (!is_numeric($type)) {
421  $type = $this->MAP_ID[$type];
422  }
423 
424  $error = 0;
425 
426  dol_syslog(get_class($this).'::create', LOG_DEBUG);
427 
428  // Clean parameters
429  $this->label = trim($this->label);
430  $this->description = trim($this->description);
431  $this->color = trim($this->color);
432  $this->import_key = trim($this->import_key);
433  $this->ref_ext = trim($this->ref_ext);
434  if (empty($this->visible)) {
435  $this->visible = 0;
436  }
437  $this->fk_parent = ($this->fk_parent != "" ? intval($this->fk_parent) : 0);
438 
439  if ($this->already_exists()) {
440  $this->error = $langs->trans("ImpossibleAddCat", $this->label);
441  $this->error .= " : ".$langs->trans("CategoryExistsAtSameLevel");
442  dol_syslog($this->error, LOG_WARNING);
443  return -4;
444  }
445 
446  $this->db->begin();
447  $now = dol_now();
448  $sql = "INSERT INTO ".MAIN_DB_PREFIX."categorie (";
449  $sql .= "fk_parent,";
450  $sql .= " label,";
451  $sql .= " description,";
452  $sql .= " color,";
453  if (!empty($conf->global->CATEGORY_ASSIGNED_TO_A_CUSTOMER)) {
454  $sql .= "fk_soc,";
455  }
456  $sql .= " visible,";
457  $sql .= " type,";
458  $sql .= " import_key,";
459  $sql .= " ref_ext,";
460  $sql .= " entity,";
461  $sql .= " date_creation,";
462  $sql .= " fk_user_creat";
463  $sql .= ") VALUES (";
464  $sql .= (int) $this->fk_parent.",";
465  $sql .= "'".$this->db->escape($this->label)."', ";
466  $sql .= "'".$this->db->escape($this->description)."', ";
467  $sql .= "'".$this->db->escape($this->color)."', ";
468  if (!empty($conf->global->CATEGORY_ASSIGNED_TO_A_CUSTOMER)) {
469  $sql .= ($this->socid > 0 ? $this->socid : 'null').", ";
470  }
471  $sql .= "'".$this->db->escape($this->visible)."', ";
472  $sql .= ((int) $type).", ";
473  $sql .= (!empty($this->import_key) ? "'".$this->db->escape($this->import_key)."'" : 'null').", ";
474  $sql .= (!empty($this->ref_ext) ? "'".$this->db->escape($this->ref_ext)."'" : 'null').", ";
475  $sql .= (int) $conf->entity.", ";
476  $sql .= "'".$this->db->idate($now)."', ";
477  $sql .= (int) $user->id;
478  $sql .= ")";
479 
480  $res = $this->db->query($sql);
481  if ($res) {
482  $id = $this->db->last_insert_id(MAIN_DB_PREFIX."categorie");
483 
484  if ($id > 0) {
485  $this->id = $id;
486 
487  $action = 'create';
488 
489  // Actions on extra fields
490  if (!$error) {
491  $result = $this->insertExtraFields();
492  if ($result < 0) {
493  $error++;
494  }
495  }
496 
497  if (!$error) {
498  // Call trigger
499  $result = $this->call_trigger('CATEGORY_CREATE', $user);
500  if ($result < 0) {
501  $error++;
502  }
503  // End call triggers
504  }
505 
506  if (!$error) {
507  $this->db->commit();
508  return $id;
509  } else {
510  $this->db->rollback();
511  return -3;
512  }
513  } else {
514  $this->db->rollback();
515  return -2;
516  }
517  } else {
518  $this->error = $this->db->error();
519  $this->db->rollback();
520  return -1;
521  }
522  }
523 
532  public function update(User $user)
533  {
534  global $conf, $langs, $hookmanager;
535 
536  $error = 0;
537 
538  // Clean parameters
539  $this->label = trim($this->label);
540  $this->description = trim($this->description);
541  $this->ref_ext = trim($this->ref_ext);
542  $this->fk_parent = ($this->fk_parent != "" ? intval($this->fk_parent) : 0);
543  $this->visible = ($this->visible != "" ? intval($this->visible) : 0);
544 
545  if ($this->already_exists()) {
546  $this->error = $langs->trans("ImpossibleUpdateCat");
547  $this->error .= " : ".$langs->trans("CategoryExistsAtSameLevel");
548  return -1;
549  }
550 
551  $this->db->begin();
552 
553  $sql = "UPDATE ".MAIN_DB_PREFIX."categorie";
554  $sql .= " SET label = '".$this->db->escape($this->label)."',";
555  $sql .= " description = '".$this->db->escape($this->description)."',";
556  $sql .= " ref_ext = '".$this->db->escape($this->ref_ext)."',";
557  $sql .= " color = '".$this->db->escape($this->color)."'";
558  if (!empty($conf->global->CATEGORY_ASSIGNED_TO_A_CUSTOMER)) {
559  $sql .= ", fk_soc = ".($this->socid > 0 ? $this->socid : 'null');
560  }
561  $sql .= ", visible = ".(int) $this->visible;
562  $sql .= ", fk_parent = ".(int) $this->fk_parent;
563  $sql .= ", fk_user_modif = ".(int) $user->id;
564  $sql .= " WHERE rowid = ".((int) $this->id);
565 
566  dol_syslog(get_class($this)."::update", LOG_DEBUG);
567  if ($this->db->query($sql)) {
568  $action = 'update';
569 
570  // Actions on extra fields
571  if (!$error) {
572  $result = $this->insertExtraFields();
573  if ($result < 0) {
574  $error++;
575  }
576  }
577 
578  if (!$error) {
579  // Call trigger
580  $result = $this->call_trigger('CATEGORY_MODIFY', $user);
581  if ($result < 0) {
582  $error++; $this->db->rollback(); return -1;
583  }
584  // End call triggers
585  }
586 
587  $this->db->commit();
588 
589  return 1;
590  } else {
591  $this->db->rollback();
592  dol_print_error($this->db);
593  return -1;
594  }
595  }
596 
604  public function delete($user, $notrigger = 0)
605  {
606  global $conf, $langs;
607 
608  $error = 0;
609 
610  // Clean parameters
611  $this->fk_parent = ($this->fk_parent != "" ? intval($this->fk_parent) : 0);
612 
613  dol_syslog(get_class($this)."::remove");
614 
615  $this->db->begin();
616 
617  if (!$error && !$notrigger) {
618  // Call trigger
619  $result = $this->call_trigger('CATEGORY_DELETE', $user);
620  if ($result < 0) {
621  $error++;
622  }
623  // End call triggers
624  }
625 
626  /* FIX #1317 : Check for child category and move up 1 level*/
627  if (!$error) {
628  $sql = "UPDATE ".MAIN_DB_PREFIX."categorie";
629  $sql .= " SET fk_parent = ".((int) $this->fk_parent);
630  $sql .= " WHERE fk_parent = ".((int) $this->id);
631 
632  if (!$this->db->query($sql)) {
633  $this->error = $this->db->lasterror();
634  $error++;
635  }
636  }
637 
638  $arraydelete = array(
639  'categorie_account' => 'fk_categorie',
640  'categorie_actioncomm' => 'fk_categorie',
641  'categorie_contact' => 'fk_categorie',
642  'categorie_fournisseur' => 'fk_categorie',
643  'categorie_knowledgemanagement' => array('field' => 'fk_categorie', 'enabled' => isModEnabled('knowledgemanagement')),
644  'categorie_member' => 'fk_categorie',
645  'categorie_user' => 'fk_categorie',
646  'categorie_product' => 'fk_categorie',
647  'categorie_project' => 'fk_categorie',
648  'categorie_societe' => 'fk_categorie',
649  'categorie_ticket' => array('field' => 'fk_categorie', 'enabled' => isModEnabled('ticket')),
650  'categorie_warehouse' => 'fk_categorie',
651  'categorie_website_page' => array('field' => 'fk_categorie', 'enabled' => isModEnabled('website')),
652  'bank_class' => 'fk_categ',
653  'categorie_lang' => 'fk_category',
654  'categorie' => 'rowid',
655  );
656  foreach ($arraydelete as $key => $value) {
657  if (is_array($value)) {
658  if (empty($value['enabled'])) {
659  continue;
660  }
661  $value = $value['field'];
662  }
663  $sql = "DELETE FROM ".MAIN_DB_PREFIX.$key;
664  $sql .= " WHERE ".$value." = ".((int) $this->id);
665  if (!$this->db->query($sql)) {
666  $this->errors[] = $this->db->lasterror();
667  dol_syslog("Error sql=".$sql." ".$this->error, LOG_ERR);
668  $error++;
669  }
670  }
671 
672  // Removed extrafields
673  if (!$error) {
674  $result = $this->deleteExtraFields();
675  if ($result < 0) {
676  $error++;
677  dol_syslog(get_class($this)."::delete erreur ".$this->error, LOG_ERR);
678  }
679  }
680 
681  if (!$error) {
682  $this->db->commit();
683  return 1;
684  } else {
685  $this->db->rollback();
686  return -1;
687  }
688  }
689 
690  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
699  public function add_type($obj, $type = '')
700  {
701  // phpcs:enable
702  global $user, $langs, $conf;
703 
704  $error = 0;
705 
706  if ($this->id == -1) {
707  return -2;
708  }
709 
710  if (empty($type)) {
711  $type = $obj->element;
712  }
713 
714  dol_syslog(get_class($this).'::add_type', LOG_DEBUG);
715 
716  $this->db->begin();
717 
718  $sql = "INSERT INTO ".MAIN_DB_PREFIX."categorie_".(empty($this->MAP_CAT_TABLE[$type]) ? $type : $this->MAP_CAT_TABLE[$type]);
719  $sql .= " (fk_categorie, fk_".(empty($this->MAP_CAT_FK[$type]) ? $type : $this->MAP_CAT_FK[$type]).")";
720  $sql .= " VALUES (".((int) $this->id).", ".((int) $obj->id).")";
721 
722  if ($this->db->query($sql)) {
723  if (!empty($conf->global->CATEGORIE_RECURSIV_ADD)) {
724  $sql = 'SELECT fk_parent FROM '.MAIN_DB_PREFIX.'categorie';
725  $sql .= " WHERE rowid = ".((int) $this->id);
726 
727  dol_syslog(get_class($this)."::add_type", LOG_DEBUG);
728  $resql = $this->db->query($sql);
729  if ($resql) {
730  if ($this->db->num_rows($resql) > 0) {
731  $objparent = $this->db->fetch_object($resql);
732 
733  if (!empty($objparent->fk_parent)) {
734  $cat = new Categorie($this->db);
735  $cat->id = $objparent->fk_parent;
736  if (!$cat->containsObject($type, $obj->id)) {
737  $result = $cat->add_type($obj, $type);
738  if ($result < 0) {
739  $this->error = $cat->error;
740  $error++;
741  }
742  }
743  }
744  }
745  } else {
746  $error++;
747  $this->error = $this->db->lasterror();
748  }
749 
750  if ($error) {
751  $this->db->rollback();
752  return -1;
753  }
754  }
755 
756  // Call trigger
757  $this->context = array('linkto'=>$obj); // Save object we want to link category to into category instance to provide information to trigger
758  $result = $this->call_trigger('CATEGORY_LINK', $user);
759  if ($result < 0) {
760  $error++;
761  }
762  // End call triggers
763 
764  if (!$error) {
765  $this->db->commit();
766  return 1;
767  } else {
768  $this->db->rollback();
769  return -2;
770  }
771  } else {
772  $this->db->rollback();
773  if ($this->db->lasterrno() == 'DB_ERROR_RECORD_ALREADY_EXISTS') {
774  $this->error = $this->db->lasterrno();
775  return -3;
776  } else {
777  $this->error = $this->db->lasterror();
778  }
779  return -1;
780  }
781  }
782 
783  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
792  public function del_type($obj, $type)
793  {
794  // phpcs:enable
795  global $user, $langs, $conf;
796 
797  $error = 0;
798 
799  // For backward compatibility
800  if ($type == 'societe') {
801  $type = 'customer';
802  dol_syslog(get_class($this)."::del_type(): type 'societe' is deprecated, please use 'customer' instead", LOG_WARNING);
803  } elseif ($type == 'fournisseur') {
804  $type = 'supplier';
805  dol_syslog(get_class($this)."::del_type(): type 'fournisseur' is deprecated, please use 'supplier' instead", LOG_WARNING);
806  }
807 
808  $this->db->begin();
809 
810  $sql = "DELETE FROM ".MAIN_DB_PREFIX."categorie_".(empty($this->MAP_CAT_TABLE[$type]) ? $type : $this->MAP_CAT_TABLE[$type]);
811  $sql .= " WHERE fk_categorie = ".((int) $this->id);
812  $sql .= " AND fk_".(empty($this->MAP_CAT_FK[$type]) ? $type : $this->MAP_CAT_FK[$type])." = ".((int) $obj->id);
813 
814  dol_syslog(get_class($this).'::del_type', LOG_DEBUG);
815  if ($this->db->query($sql)) {
816  // Call trigger
817  $this->context = array('unlinkoff'=>$obj); // Save object we want to link category to into category instance to provide information to trigger
818  $result = $this->call_trigger('CATEGORY_UNLINK', $user);
819  if ($result < 0) {
820  $error++;
821  }
822  // End call triggers
823 
824  if (!$error) {
825  $this->db->commit();
826  return 1;
827  } else {
828  $this->db->rollback();
829  return -2;
830  }
831  } else {
832  $this->db->rollback();
833  $this->error = $this->db->lasterror();
834  return -1;
835  }
836  }
837 
850  public function getObjectsInCateg($type, $onlyids = 0, $limit = 0, $offset = 0, $sortfield = '', $sortorder = 'ASC')
851  {
852  global $user;
853 
854  $objs = array();
855 
856  $classnameforobj = $this->MAP_OBJ_CLASS[$type];
857  $obj = new $classnameforobj($this->db);
858 
859  $sql = "SELECT c.fk_".(empty($this->MAP_CAT_FK[$type]) ? $type : $this->MAP_CAT_FK[$type]);
860  $sql .= " FROM ".MAIN_DB_PREFIX."categorie_".(empty($this->MAP_CAT_TABLE[$type]) ? $type : $this->MAP_CAT_TABLE[$type])." as c";
861  $sql .= ", ".MAIN_DB_PREFIX.(empty($this->MAP_OBJ_TABLE[$type]) ? $type : $this->MAP_OBJ_TABLE[$type])." as o";
862  $sql .= " WHERE o.entity IN (".getEntity($obj->element).")";
863  $sql .= " AND c.fk_categorie = ".((int) $this->id);
864  $sql .= " AND c.fk_".(empty($this->MAP_CAT_FK[$type]) ? $type : $this->MAP_CAT_FK[$type])." = o.rowid";
865  // Protection for external users
866  if (($type == 'customer' || $type == 'supplier') && $user->socid > 0) {
867  $sql .= " AND o.rowid = ".((int) $user->socid);
868  }
869  if ($limit > 0 || $offset > 0) {
870  $sql .= $this->db->plimit($limit + 1, $offset);
871  }
872  $sql .= $this->db->order($sortfield, $sortorder);
873 
874  dol_syslog(get_class($this)."::getObjectsInCateg", LOG_DEBUG);
875  $resql = $this->db->query($sql);
876  if ($resql) {
877  while ($rec = $this->db->fetch_array($resql)) {
878  if ($onlyids) {
879  $objs[] = $rec['fk_'.(empty($this->MAP_CAT_FK[$type]) ? $type : $this->MAP_CAT_FK[$type])];
880  } else {
881  $classnameforobj = $this->MAP_OBJ_CLASS[$type];
882 
883  $obj = new $classnameforobj($this->db);
884  $obj->fetch($rec['fk_'.(empty($this->MAP_CAT_FK[$type]) ? $type : $this->MAP_CAT_FK[$type])]);
885 
886  $objs[] = $obj;
887  }
888  }
889  return $objs;
890  } else {
891  $this->error = $this->db->error().' sql='.$sql;
892  return -1;
893  }
894  }
895 
904  public function containsObject($type, $object_id)
905  {
906  $sql = "SELECT COUNT(*) as nb FROM ".MAIN_DB_PREFIX."categorie_".(empty($this->MAP_CAT_TABLE[$type]) ? $type : $this->MAP_CAT_TABLE[$type]);
907  $sql .= " WHERE fk_categorie = ".((int) $this->id)." AND fk_".(empty($this->MAP_CAT_FK[$type]) ? $type : $this->MAP_CAT_FK[$type])." = ".((int) $object_id);
908  dol_syslog(get_class($this)."::containsObject", LOG_DEBUG);
909  $resql = $this->db->query($sql);
910  if ($resql) {
911  return $this->db->fetch_object($resql)->nb;
912  } else {
913  $this->error = $this->db->error().' sql='.$sql;
914  return -1;
915  }
916  }
917 
929  public function getListForItem($id, $type = 'customer', $sortfield = "s.rowid", $sortorder = 'ASC', $limit = 0, $page = 0)
930  {
931  global $conf;
932 
933  $categories = array();
934 
935  $type = sanitizeVal($type, 'aZ09');
936 
937  $sub_type = $type;
938  $subcol_name = "fk_".$type;
939  if ($type == "customer") {
940  $sub_type = "societe";
941  $subcol_name = "fk_soc";
942  }
943  if ($type == "supplier") {
944  $sub_type = "fournisseur";
945  $subcol_name = "fk_soc";
946  }
947  if ($type == "contact") {
948  $subcol_name = "fk_socpeople";
949  }
950 
951  $idoftype = array_search($type, self::$MAP_ID_TO_CODE);
952 
953  $sql = "SELECT s.rowid";
954  $sql .= " FROM ".MAIN_DB_PREFIX."categorie as s, ".MAIN_DB_PREFIX."categorie_".$sub_type." as sub";
955  $sql .= ' WHERE s.entity IN ('.getEntity('category').')';
956  $sql .= ' AND s.type='.((int) $idoftype);
957  $sql .= ' AND s.rowid = sub.fk_categorie';
958  $sql .= " AND sub.".$subcol_name." = ".((int) $id);
959 
960  $sql .= $this->db->order($sortfield, $sortorder);
961 
962  $offset = 0;
963  $nbtotalofrecords = '';
964  if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) {
965  $result = $this->db->query($sql);
966  $nbtotalofrecords = $this->db->num_rows($result);
967  if (($page * $limit) > $nbtotalofrecords) { // if total resultset is smaller then paging size (filtering), goto and load page 0
968  $page = 0;
969  $offset = 0;
970  }
971  }
972 
973  if ($limit) {
974  if ($page < 0) {
975  $page = 0;
976  }
977  $offset = $limit * $page;
978 
979  $sql .= $this->db->plimit($limit + 1, $offset);
980  }
981 
982  $result = $this->db->query($sql);
983  if ($result) {
984  $i = 0;
985  $num = $this->db->num_rows($result);
986  $min = min($num, ($limit <= 0 ? $num : $limit));
987  while ($i < $min) {
988  $obj = $this->db->fetch_object($result);
989  $category_static = new Categorie($this->db);
990  if ($category_static->fetch($obj->rowid)) {
991  $categories[$i]['id'] = $category_static->id;
992  $categories[$i]['fk_parent'] = $category_static->fk_parent;
993  $categories[$i]['label'] = $category_static->label;
994  $categories[$i]['description'] = $category_static->description;
995  $categories[$i]['color'] = $category_static->color;
996  $categories[$i]['socid'] = $category_static->socid;
997  $categories[$i]['ref_ext'] = $category_static->ref_ext;
998  $categories[$i]['visible'] = $category_static->visible;
999  $categories[$i]['type'] = $category_static->type;
1000  $categories[$i]['entity'] = $category_static->entity;
1001  $categories[$i]['array_options'] = $category_static->array_options;
1002 
1003  // multilangs
1004  if (getDolGlobalInt('MAIN_MULTILANGS') && isset($category_static->multilangs)) {
1005  $categories[$i]['multilangs'] = $category_static->multilangs;
1006  }
1007  }
1008  $i++;
1009  }
1010  } else {
1011  $this->error = $this->db->lasterror();
1012  return -1;
1013  }
1014  if (!count($categories)) {
1015  return 0;
1016  }
1017 
1018  return $categories;
1019  }
1020 
1021  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1027  public function get_filles()
1028  {
1029  // phpcs:enable
1030  $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."categorie";
1031  $sql .= " WHERE fk_parent = ".((int) $this->id);
1032  $sql .= " AND entity IN (".getEntity('category').")";
1033 
1034  $res = $this->db->query($sql);
1035  if ($res) {
1036  $cats = array();
1037  while ($rec = $this->db->fetch_array($res)) {
1038  $cat = new Categorie($this->db);
1039  $cat->fetch($rec['rowid']);
1040  $cats[] = $cat;
1041  }
1042  return $cats;
1043  } else {
1044  dol_print_error($this->db);
1045  return -1;
1046  }
1047  }
1048 
1049  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1055  protected function load_motherof()
1056  {
1057  // phpcs:enable
1058  $this->motherof = array();
1059 
1060  // Load array[child]=parent
1061  $sql = "SELECT fk_parent as id_parent, rowid as id_son";
1062  $sql .= " FROM ".MAIN_DB_PREFIX."categorie";
1063  $sql .= " WHERE fk_parent != 0";
1064  $sql .= " AND entity IN (".getEntity('category').")";
1065 
1066  dol_syslog(get_class($this)."::load_motherof", LOG_DEBUG);
1067  $resql = $this->db->query($sql);
1068  if ($resql) {
1069  while ($obj = $this->db->fetch_object($resql)) {
1070  $this->motherof[$obj->id_son] = $obj->id_parent;
1071  }
1072  return 1;
1073  } else {
1074  dol_print_error($this->db);
1075  return -1;
1076  }
1077  }
1078 
1079  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1099  public function get_full_arbo($type, $markafterid = 0, $include = 0)
1100  {
1101  // phpcs:enable
1102  global $conf, $langs;
1103 
1104  if (!is_numeric($type)) {
1105  $type = $this->MAP_ID[$type];
1106  }
1107  if (is_null($type)) {
1108  $this->error = 'BadValueForParameterType';
1109  return -1;
1110  }
1111 
1112  if (is_string($markafterid)) {
1113  $markafterid = explode(',', $markafterid);
1114  } elseif (is_numeric($markafterid)) {
1115  if ($markafterid > 0) {
1116  $markafterid = array($markafterid);
1117  } else {
1118  $markafterid = array();
1119  }
1120  } elseif (!is_array($markafterid)) {
1121  $markafterid = array();
1122  }
1123 
1124  $this->cats = array();
1125 
1126  // Init this->motherof that is array(id_son=>id_parent, ...)
1127  $this->load_motherof();
1128  $current_lang = $langs->getDefaultLang();
1129 
1130  // Init $this->cats array
1131  $sql = "SELECT DISTINCT c.rowid, c.label, c.ref_ext, c.description, c.color, c.fk_parent, c.visible"; // Distinct reduce pb with old tables with duplicates
1132  if (getDolGlobalInt('MAIN_MULTILANGS')) {
1133  $sql .= ", t.label as label_trans, t.description as description_trans";
1134  }
1135  $sql .= " FROM ".MAIN_DB_PREFIX."categorie as c";
1136  if (getDolGlobalInt('MAIN_MULTILANGS')) {
1137  $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."categorie_lang as t ON t.fk_category=c.rowid AND t.lang='".$this->db->escape($current_lang)."'";
1138  }
1139  $sql .= " WHERE c.entity IN (".getEntity('category').")";
1140  $sql .= " AND c.type = ".(int) $type;
1141 
1142  dol_syslog(get_class($this)."::get_full_arbo get category list", LOG_DEBUG);
1143  $resql = $this->db->query($sql);
1144  if ($resql) {
1145  $i = 0;
1146  while ($obj = $this->db->fetch_object($resql)) {
1147  $this->cats[$obj->rowid]['rowid'] = $obj->rowid;
1148  $this->cats[$obj->rowid]['id'] = $obj->rowid;
1149  $this->cats[$obj->rowid]['fk_parent'] = $obj->fk_parent;
1150  $this->cats[$obj->rowid]['label'] = !empty($obj->label_trans) ? $obj->label_trans : $obj->label;
1151  $this->cats[$obj->rowid]['description'] = !empty($obj->description_trans) ? $obj->description_trans : $obj->description;
1152  $this->cats[$obj->rowid]['color'] = $obj->color;
1153  $this->cats[$obj->rowid]['visible'] = $obj->visible;
1154  $this->cats[$obj->rowid]['ref_ext'] = $obj->ref_ext;
1155  $this->cats[$obj->rowid]['picto'] = 'category';
1156  $i++;
1157  }
1158  } else {
1159  dol_print_error($this->db);
1160  return -1;
1161  }
1162 
1163  // We add the fullpath property to each elements of first level (no parent exists)
1164  dol_syslog(get_class($this)."::get_full_arbo call to buildPathFromId", LOG_DEBUG);
1165  foreach ($this->cats as $key => $val) {
1166  //print 'key='.$key.'<br>'."\n";
1167  $this->buildPathFromId($key, 0); // Process a branch from the root category key (this category has no parent)
1168  }
1169 
1170  // Include or exclude leaf including $markafterid from tree
1171  if (count($markafterid) > 0) {
1172  $keyfiltercatid = '('.implode('|', $markafterid).')';
1173 
1174  //print "Look to discard category ".$markafterid."\n";
1175  $keyfilter1 = '^'.$keyfiltercatid.'$';
1176  $keyfilter2 = '_'.$keyfiltercatid.'$';
1177  $keyfilter3 = '^'.$keyfiltercatid.'_';
1178  $keyfilter4 = '_'.$keyfiltercatid.'_';
1179  foreach ($this->cats as $key => $val) {
1180  $test = (preg_match('/'.$keyfilter1.'/', $val['fullpath']) || preg_match('/'.$keyfilter2.'/', $val['fullpath'])
1181  || preg_match('/'.$keyfilter3.'/', $val['fullpath']) || preg_match('/'.$keyfilter4.'/', $val['fullpath']));
1182 
1183  if (($test && !$include) || (!$test && $include)) {
1184  unset($this->cats[$key]);
1185  }
1186  }
1187  }
1188 
1189  dol_syslog(get_class($this)."::get_full_arbo dol_sort_array", LOG_DEBUG);
1190  $this->cats = dol_sort_array($this->cats, 'fulllabel', 'asc', true, false);
1191 
1192  //$this->debug_cats();
1193 
1194  return $this->cats;
1195  }
1196 
1207  private function buildPathFromId($id_categ, $protection = 1000)
1208  {
1209  //dol_syslog(get_class($this)."::buildPathFromId id_categ=".$id_categ." protection=".$protection, LOG_DEBUG);
1210 
1211  if (!empty($this->cats[$id_categ]['fullpath'])) {
1212  // Already defined
1213  dol_syslog(get_class($this)."::buildPathFromId fullpath and fulllabel already defined", LOG_WARNING);
1214  return;
1215  }
1216 
1217  // First build full array $motherof
1218  //$this->load_motherof(); // Disabled because already done by caller of buildPathFromId
1219 
1220  // $this->cats[$id_categ] is supposed to be already an array. We just want to complete it with property fullpath and fulllabel
1221 
1222  // Define fullpath and fulllabel
1223  $this->cats[$id_categ]['fullpath'] = '_'.$id_categ;
1224  $this->cats[$id_categ]['fulllabel'] = $this->cats[$id_categ]['label'];
1225  $i = 0; $cursor_categ = $id_categ;
1226  //print 'Work for id_categ='.$id_categ.'<br>'."\n";
1227  while ((empty($protection) || $i < $protection) && !empty($this->motherof[$cursor_categ])) {
1228  //print '&nbsp; cursor_categ='.$cursor_categ.' i='.$i.' '.$this->motherof[$cursor_categ].'<br>'."\n";
1229  $this->cats[$id_categ]['fullpath'] = '_'.$this->motherof[$cursor_categ].$this->cats[$id_categ]['fullpath'];
1230  $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'];
1231  //print '&nbsp; Result for id_categ='.$id_categ.' : '.$this->cats[$id_categ]['fullpath'].' '.$this->cats[$id_categ]['fulllabel'].'<br>'."\n";
1232  $i++;
1233  $cursor_categ = $this->motherof[$cursor_categ];
1234  }
1235  //print 'Result for id_categ='.$id_categ.' : '.$this->cats[$id_categ]['fullpath'].'<br>'."\n";
1236 
1237  // We count number of _ to have level
1238  $nbunderscore = substr_count($this->cats[$id_categ]['fullpath'], '_');
1239  $this->cats[$id_categ]['level'] = ($nbunderscore ? $nbunderscore : null);
1240 
1241  return;
1242  }
1243 
1244  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1250  public function debug_cats()
1251  {
1252  // phpcs:enable
1253  // Display $this->cats
1254  foreach ($this->cats as $key => $val) {
1255  print 'id: '.$this->cats[$key]['id'];
1256  print ' label: '.$this->cats[$key]['label'];
1257  print ' mother: '.$this->cats[$key]['fk_parent'];
1258  //print ' children: '.(is_array($this->cats[$key]['id_children'])?join(',',$this->cats[$key]['id_children']):'');
1259  print ' fullpath: '.$this->cats[$key]['fullpath'];
1260  print ' fulllabel: '.$this->cats[$key]['fulllabel'];
1261  print "<br>\n";
1262  }
1263  }
1264 
1265 
1266  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1274  public function get_all_categories($type = null, $parent = false)
1275  {
1276  // phpcs:enable
1277  if (!is_numeric($type)) {
1278  $type = $this->MAP_ID[$type];
1279  }
1280 
1281  $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."categorie";
1282  $sql .= " WHERE entity IN (".getEntity('category').")";
1283  if (!is_null($type)) {
1284  $sql .= " AND type = ".(int) $type;
1285  }
1286  if ($parent) {
1287  $sql .= " AND fk_parent = 0";
1288  }
1289 
1290  $res = $this->db->query($sql);
1291  if ($res) {
1292  $cats = array();
1293  while ($rec = $this->db->fetch_array($res)) {
1294  $cat = new Categorie($this->db);
1295  $cat->fetch($rec['rowid']);
1296  $cats[$rec['rowid']] = $cat;
1297  }
1298  return $cats;
1299  } else {
1300  dol_print_error($this->db);
1301  return -1;
1302  }
1303  }
1304 
1305  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1312  public function get_main_categories($type = null)
1313  {
1314  // phpcs:enable
1315  return $this->get_all_categories($type, true);
1316  }
1317 
1318  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1324  public function already_exists()
1325  {
1326  // phpcs:enable
1327  $type = $this->type;
1328 
1329  if (!is_numeric($type)) {
1330  $type = $this->MAP_ID[$type];
1331  }
1332 
1333  /* We have to select any rowid from llx_categorie which category's mother and label
1334  * are equals to those of the calling category
1335  */
1336  $sql = "SELECT c.rowid";
1337  $sql .= " FROM ".MAIN_DB_PREFIX."categorie as c ";
1338  $sql .= " WHERE c.entity IN (".getEntity('category').")";
1339  $sql .= " AND c.type = ".((int) $type);
1340  $sql .= " AND c.fk_parent = ".((int) $this->fk_parent);
1341  $sql .= " AND c.label = '".$this->db->escape($this->label)."'";
1342 
1343  dol_syslog(get_class($this)."::already_exists", LOG_DEBUG);
1344  $resql = $this->db->query($sql);
1345  if ($resql) {
1346  if ($this->db->num_rows($resql) > 0) { // Checking for empty resql
1347  $obj = $this->db->fetch_array($resql);
1348  /* If object called create, obj cannot have is id.
1349  * If object called update, he mustn't have the same label as an other category for this mother.
1350  * So if the result have the same id, update is not for label, and if result have an other one,
1351  * update may be for label.
1352  */
1353  if ($obj[0] > 0 && $obj[0] != $this->id) {
1354  dol_syslog(get_class($this)."::already_exists category with name=".$this->label." and parent ".$this->fk_parent." exists: rowid=".$obj[0]." current_id=".$this->id, LOG_DEBUG);
1355  return 1;
1356  }
1357  }
1358  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);
1359  return 0;
1360  } else {
1361  $this->error = $this->db->error();
1362  return -1;
1363  }
1364  }
1365 
1366 
1367  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1378  public function print_all_ways($sep = '&gt;&gt;', $url = '', $nocolor = 0, $addpicto = 0)
1379  {
1380  // phpcs:enable
1381  $ways = array();
1382 
1383  $allways = $this->get_all_ways(); // Load array of categories
1384  foreach ($allways as $way) {
1385  $w = array();
1386  $i = 0;
1387  $forced_color = '';
1388  foreach ($way as $cat) {
1389  $i++;
1390 
1391  if (empty($nocolor)) {
1392  $forced_color = 'colortoreplace';
1393  if ($i == count($way)) { // Last category in hierarchy
1394  // Check contrast with background and correct text color
1395  $forced_color = 'categtextwhite';
1396  if ($cat->color) {
1397  if (colorIsLight($cat->color)) {
1398  $forced_color = 'categtextblack';
1399  }
1400  }
1401  }
1402  }
1403 
1404  if ($url == '') {
1405  $link = '<a href="'.DOL_URL_ROOT.'/categories/viewcat.php?id='.$cat->id.'&type='.$cat->type.'" class="'.$forced_color.'">';
1406  $linkend = '</a>';
1407  $w[] = $link.(($addpicto && $i == 1) ? img_object('', 'category', 'class="paddingright"') : '').$cat->label.$linkend;
1408  } elseif ($url == 'none') {
1409  $link = '<span class="'.$forced_color.'">';
1410  $linkend = '</span>';
1411  $w[] = $link.(($addpicto && $i == 1) ? img_object('', 'category', 'class="paddingright"') : '').$cat->label.$linkend;
1412  } else {
1413  $w[] = '<a class="'.$forced_color.'" href="'.DOL_URL_ROOT.'/'.$url.'?catid='.$cat->id.'">'.($addpicto ? img_object('', 'category') : '').$cat->label.'</a>';
1414  }
1415  }
1416  $newcategwithpath = preg_replace('/colortoreplace/', $forced_color, implode('<span class="inline-block valignmiddle paddingleft paddingright '.$forced_color.'">'.$sep.'</span>', $w));
1417 
1418  $ways[] = $newcategwithpath;
1419  }
1420 
1421  return $ways;
1422  }
1423 
1424 
1425  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1431  public function get_meres()
1432  {
1433  // phpcs:enable
1434  $parents = array();
1435 
1436  $sql = "SELECT fk_parent FROM ".MAIN_DB_PREFIX."categorie";
1437  $sql .= " WHERE rowid = ".((int) $this->id);
1438 
1439  $res = $this->db->query($sql);
1440 
1441  if ($res) {
1442  while ($rec = $this->db->fetch_array($res)) {
1443  if ($rec['fk_parent'] > 0) {
1444  $cat = new Categorie($this->db);
1445  $cat->fetch($rec['fk_parent']);
1446  $parents[] = $cat;
1447  }
1448  }
1449  return $parents;
1450  } else {
1451  dol_print_error($this->db);
1452  return -1;
1453  }
1454  }
1455 
1456  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1463  public function get_all_ways()
1464  {
1465  // phpcs:enable
1466  $ways = array();
1467 
1468  $parents = $this->get_meres();
1469  if (!empty($parents)) {
1470  foreach ($parents as $parent) {
1471  $allways = $parent->get_all_ways();
1472  foreach ($allways as $way) {
1473  $w = $way;
1474  $w[] = $this;
1475  $ways[] = $w;
1476  }
1477  }
1478  }
1479 
1480  if (count($ways) == 0) {
1481  $ways[0][0] = $this;
1482  }
1483 
1484  return $ways;
1485  }
1486 
1497  public function containing($id, $type, $mode = 'object')
1498  {
1499  $cats = array();
1500 
1501  if (is_numeric($type)) {
1502  $type = Categorie::$MAP_ID_TO_CODE[$type];
1503  }
1504 
1505  if ($type === Categorie::TYPE_BANK_LINE) { // TODO Remove this with standard category code after migration of llx_bank_categ into llx_categorie
1506  // Load bank categories
1507  $sql = "SELECT c.label, c.rowid";
1508  $sql .= " FROM ".MAIN_DB_PREFIX."bank_class as a, ".MAIN_DB_PREFIX."bank_categ as c";
1509  $sql .= " WHERE a.lineid=".((int) $id)." AND a.fk_categ = c.rowid";
1510  $sql .= " AND c.entity IN (".getEntity('category').")";
1511  $sql .= " ORDER BY c.label";
1512 
1513  $res = $this->db->query($sql);
1514  if ($res) {
1515  while ($obj = $this->db->fetch_object($res)) {
1516  if ($mode == 'id') {
1517  $cats[] = $obj->rowid;
1518  } elseif ($mode == 'label') {
1519  $cats[] = $obj->label;
1520  } else {
1521  $cat = new Categorie($this->db);
1522  $cat->id = $obj->rowid;
1523  $cat->label = $obj->label;
1524  $cats[] = $cat;
1525  }
1526  }
1527  } else {
1528  dol_print_error($this->db);
1529  return -1;
1530  }
1531  } else {
1532  $sql = "SELECT ct.fk_categorie, c.label, c.rowid";
1533  $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";
1534  $sql .= " WHERE ct.fk_categorie = c.rowid AND ct.fk_".(empty($this->MAP_CAT_FK[$type]) ? $type : $this->MAP_CAT_FK[$type])." = ".(int) $id;
1535  // This seems useless because the table already contains id of category of 1 unique type. So commented.
1536  // So now it works also with external added categories.
1537  //$sql .= " AND c.type = ".((int) $this->MAP_ID[$type]);
1538  $sql .= " AND c.entity IN (".getEntity('category').")";
1539 
1540  $res = $this->db->query($sql);
1541  if ($res) {
1542  while ($obj = $this->db->fetch_object($res)) {
1543  if ($mode == 'id') {
1544  $cats[] = $obj->rowid;
1545  } elseif ($mode == 'label') {
1546  $cats[] = $obj->label;
1547  } else {
1548  $cat = new Categorie($this->db);
1549  $cat->fetch($obj->fk_categorie);
1550  $cats[] = $cat;
1551  }
1552  }
1553  } else {
1554  dol_print_error($this->db);
1555  return -1;
1556  }
1557  }
1558 
1559  return $cats;
1560  }
1561 
1573  public function rechercher($id, $nom, $type, $exact = false, $case = false)
1574  {
1575  // Deprecation warning
1576  if (is_numeric($type)) {
1577  dol_syslog(__METHOD__.': using numeric types is deprecated.', LOG_WARNING);
1578  }
1579 
1580  $cats = array();
1581 
1582  // For backward compatibility
1583  if (is_numeric($type)) {
1584  // We want to reverse lookup
1585  $map_type = array_flip($this->MAP_ID);
1586  $type = $map_type[$type];
1587  dol_syslog(get_class($this)."::rechercher(): numeric types are deprecated, please use string instead", LOG_WARNING);
1588  }
1589 
1590  // Generation requete recherche
1591  $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."categorie";
1592  $sql .= " WHERE type = ".((int) $this->MAP_ID[$type]);
1593  $sql .= " AND entity IN (".getEntity('category').")";
1594  if ($nom) {
1595  if (!$exact) {
1596  $nom = '%'.$this->db->escape(str_replace('*', '%', $nom)).'%';
1597  }
1598  if (!$case) {
1599  $sql .= " AND label LIKE '".$this->db->escape($nom)."'";
1600  } else {
1601  $sql .= " AND label LIKE BINARY '".$this->db->escape($nom)."'";
1602  }
1603  }
1604  if ($id) {
1605  $sql .= " AND rowid = ".((int) $id);
1606  }
1607 
1608  $res = $this->db->query($sql);
1609  if ($res) {
1610  while ($rec = $this->db->fetch_array($res)) {
1611  $cat = new Categorie($this->db);
1612  $cat->fetch($rec['rowid']);
1613  $cats[] = $cat;
1614  }
1615 
1616  return $cats;
1617  } else {
1618  $this->error = $this->db->error().' sql='.$sql;
1619  return -1;
1620  }
1621  }
1622 
1633  public function getNomUrl($withpicto = 0, $option = '', $maxlength = 0, $moreparam = '')
1634  {
1635  global $langs, $hookmanager;
1636 
1637  $result = '';
1638  $label = $langs->trans("ShowCategory").': '.($this->ref ? $this->ref : $this->label);
1639 
1640  // Check contrast with background and correct text color
1641  $forced_color = 'categtextwhite';
1642  if ($this->color) {
1643  if (colorIsLight($this->color)) {
1644  $forced_color = 'categtextblack';
1645  }
1646  }
1647 
1648  $link = '<a href="'.DOL_URL_ROOT.'/categories/viewcat.php?id='.$this->id.'&type='.$this->type.$moreparam.'&backtopage='.urlencode($_SERVER['PHP_SELF'].($moreparam ? '?'.$moreparam : '')).'" title="'.dol_escape_htmltag($label, 1).'" class="classfortooltip '.$forced_color.'">';
1649  $linkend = '</a>';
1650 
1651  $picto = 'category';
1652 
1653 
1654  if ($withpicto) {
1655  $result .= ($link.img_object($label, $picto, 'class="classfortooltip"').$linkend);
1656  }
1657  if ($withpicto && $withpicto != 2) {
1658  $result .= ' ';
1659  }
1660  if ($withpicto != 2) {
1661  $result .= $link.dol_trunc(($this->ref ? $this->ref : $this->label), $maxlength).$linkend;
1662  }
1663  global $action;
1664  $hookmanager->initHooks(array($this->element . 'dao'));
1665  $parameters = array('id'=>$this->id, 'getnomurl' => &$result);
1666  $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
1667  if ($reshook > 0) {
1668  $result = $hookmanager->resPrint;
1669  } else {
1670  $result .= $hookmanager->resPrint;
1671  }
1672  return $result;
1673  }
1674 
1675 
1676  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1684  public function add_photo($sdir, $file)
1685  {
1686  // phpcs:enable
1687  require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
1688 
1689  $dir = $sdir.'/'.get_exdir($this->id, 2, 0, 0, $this, 'category').$this->id."/";
1690  $dir .= "photos/";
1691 
1692  if (!file_exists($dir)) {
1693  dol_mkdir($dir);
1694  }
1695 
1696  if (file_exists($dir)) {
1697  if (is_array($file['name']) && count($file['name']) > 0) {
1698  $nbfile = count($file['name']);
1699  for ($i = 0; $i <= $nbfile; $i++) {
1700  $originImage = $dir.$file['name'][$i];
1701 
1702  // Cree fichier en taille origine
1703  dol_move_uploaded_file($file['tmp_name'][$i], $originImage, 1, 0, 0);
1704 
1705  if (file_exists($originImage)) {
1706  // Create thumbs
1707  $this->addThumbs($originImage);
1708  }
1709  }
1710  } else {
1711  $originImage = $dir.$file['name'];
1712 
1713  // Cree fichier en taille origine
1714  dol_move_uploaded_file($file['tmp_name'], $originImage, 1, 0, 0);
1715 
1716  if (file_exists($originImage)) {
1717  // Create thumbs
1718  $this->addThumbs($originImage);
1719  }
1720  }
1721  }
1722  }
1723 
1724  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1732  public function liste_photos($dir, $nbmax = 0)
1733  {
1734  // phpcs:enable
1735  include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
1736 
1737  $nbphoto = 0;
1738  $tabobj = array();
1739 
1740  $dirthumb = $dir.'thumbs/';
1741 
1742  if (file_exists($dir)) {
1743  $handle = opendir($dir);
1744  if (is_resource($handle)) {
1745  while (($file = readdir($handle)) !== false) {
1746  if (dol_is_file($dir.$file) && preg_match('/(\.jpeg|\.jpg|\.bmp|\.gif|\.png|\.tiff)$/i', $dir.$file)) {
1747  $nbphoto++;
1748  $photo = $file;
1749 
1750  // On determine nom du fichier vignette
1751  $photo_vignette = '';
1752  if (preg_match('/(\.jpeg|\.jpg|\.bmp|\.gif|\.png|\.tiff)$/i', $photo, $regs)) {
1753  $photo_vignette = preg_replace('/'.$regs[0].'/i', '', $photo).'_small'.$regs[0];
1754  }
1755 
1756  // Objet
1757  $obj = array();
1758  $obj['photo'] = $photo;
1759  if ($photo_vignette && is_file($dirthumb.$photo_vignette)) {
1760  $obj['photo_vignette'] = 'thumbs/'.$photo_vignette;
1761  } else {
1762  $obj['photo_vignette'] = "";
1763  }
1764 
1765  $tabobj[$nbphoto - 1] = $obj;
1766 
1767  // On continue ou on arrete de boucler
1768  if ($nbmax && $nbphoto >= $nbmax) {
1769  break;
1770  }
1771  }
1772  }
1773 
1774  closedir($handle);
1775  }
1776  }
1777 
1778  return $tabobj;
1779  }
1780 
1781  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1788  public function delete_photo($file)
1789  {
1790  // phpcs:enable
1791  require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
1792 
1793  $dir = dirname($file).'/'; // Chemin du dossier contenant l'image d'origine
1794  $dirthumb = $dir.'/thumbs/'; // Chemin du dossier contenant la vignette
1795  $filename = preg_replace('/'.preg_quote($dir, '/').'/i', '', $file); // Nom du fichier
1796 
1797  // On efface l'image d'origine
1798  dol_delete_file($file, 1);
1799 
1800  // Si elle existe, on efface la vignette
1801  if (preg_match('/(\.jpeg|\.jpg|\.bmp|\.gif|\.png|\.tiff)$/i', $filename, $regs)) {
1802  $photo_vignette = preg_replace('/'.$regs[0].'/i', '', $filename).'_small'.$regs[0];
1803  if (file_exists($dirthumb.$photo_vignette)) {
1804  dol_delete_file($dirthumb.$photo_vignette, 1);
1805  }
1806  }
1807  }
1808 
1809  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1816  public function get_image_size($file)
1817  {
1818  // phpcs:enable
1819  $infoImg = getimagesize($file); // Recuperation des infos de l'image
1820  $this->imgWidth = $infoImg[0]; // Largeur de l'image
1821  $this->imgHeight = $infoImg[1]; // Hauteur de l'image
1822  }
1823 
1831  public function setMultiLangs($user)
1832  {
1833  global $langs;
1834 
1835  $langs_available = $langs->get_available_languages();
1836  $current_lang = $langs->getDefaultLang();
1837 
1838  foreach ($langs_available as $key => $value) {
1839  $sql = "SELECT rowid";
1840  $sql .= " FROM ".MAIN_DB_PREFIX."categorie_lang";
1841  $sql .= " WHERE fk_category=".((int) $this->id);
1842  $sql .= " AND lang = '".$this->db->escape($key)."'";
1843 
1844  $result = $this->db->query($sql);
1845 
1846  if ($key == $current_lang) {
1847  if ($this->db->num_rows($result)) { // si aucune ligne dans la base
1848  $sql2 = "UPDATE ".MAIN_DB_PREFIX."categorie_lang";
1849  $sql2 .= " SET label = '".$this->db->escape($this->label)."',";
1850  $sql2 .= " description = '".$this->db->escape($this->description)."'";
1851  $sql2 .= " WHERE fk_category = ".((int) $this->id)." AND lang = '".$this->db->escape($key)."'";
1852  } else {
1853  $sql2 = "INSERT INTO ".MAIN_DB_PREFIX."categorie_lang (fk_category, lang, label, description)";
1854  $sql2 .= " VALUES(".((int) $this->id).", '".$this->db->escape($key)."', '".$this->db->escape($this->label)."'";
1855  $sql2 .= ", '".$this->db->escape($this->multilangs["$key"]["description"])."')";
1856  }
1857  dol_syslog(get_class($this).'::setMultiLangs', LOG_DEBUG);
1858  if (!$this->db->query($sql2)) {
1859  $this->error = $this->db->lasterror();
1860  return -1;
1861  }
1862  } elseif (isset($this->multilangs["$key"])) {
1863  if ($this->db->num_rows($result)) { // si aucune ligne dans la base
1864  $sql2 = "UPDATE ".MAIN_DB_PREFIX."categorie_lang";
1865  $sql2 .= " SET label='".$this->db->escape($this->multilangs["$key"]["label"])."',";
1866  $sql2 .= " description='".$this->db->escape($this->multilangs["$key"]["description"])."'";
1867  $sql2 .= " WHERE fk_category=".((int) $this->id)." AND lang='".$this->db->escape($key)."'";
1868  } else {
1869  $sql2 = "INSERT INTO ".MAIN_DB_PREFIX."categorie_lang (fk_category, lang, label, description)";
1870  $sql2 .= " VALUES(".((int) $this->id).", '".$this->db->escape($key)."', '".$this->db->escape($this->multilangs["$key"]["label"])."'";
1871  $sql2 .= ",'".$this->db->escape($this->multilangs["$key"]["description"])."')";
1872  }
1873 
1874  // on ne sauvegarde pas des champs vides
1875  if ($this->multilangs["$key"]["label"] || $this->multilangs["$key"]["description"] || $this->multilangs["$key"]["note"]) {
1876  dol_syslog(get_class($this).'::setMultiLangs', LOG_DEBUG);
1877  }
1878  if (!$this->db->query($sql2)) {
1879  $this->error = $this->db->lasterror();
1880  return -1;
1881  }
1882  }
1883  }
1884 
1885  // Call trigger
1886  $result = $this->call_trigger('CATEGORY_SET_MULTILANGS', $user);
1887  if ($result < 0) {
1888  $this->error = $this->db->lasterror();
1889  return -1;
1890  }
1891  // End call triggers
1892 
1893  return 1;
1894  }
1895 
1901  public function getMultiLangs()
1902  {
1903  global $langs;
1904 
1905  $current_lang = $langs->getDefaultLang();
1906 
1907  $sql = "SELECT lang, label, description";
1908  $sql .= " FROM ".MAIN_DB_PREFIX."categorie_lang";
1909  $sql .= " WHERE fk_category=".((int) $this->id);
1910 
1911  $result = $this->db->query($sql);
1912  if ($result) {
1913  while ($obj = $this->db->fetch_object($result)) {
1914  //print 'lang='.$obj->lang.' current='.$current_lang.'<br>';
1915  if ($obj->lang == $current_lang) { // si on a les traduct. dans la langue courante on les charge en infos principales.
1916  $this->label = $obj->label;
1917  $this->description = $obj->description;
1918  }
1919  $this->multilangs["$obj->lang"]["label"] = $obj->label;
1920  $this->multilangs["$obj->lang"]["description"] = $obj->description;
1921  }
1922  return 1;
1923  } else {
1924  $this->error = $langs->trans("Error")." : ".$this->db->error()." - ".$sql;
1925  return -1;
1926  }
1927  }
1928 
1935  public function getLibStatut($mode)
1936  {
1937  return '';
1938  }
1939 
1940 
1948  public function initAsSpecimen()
1949  {
1950  dol_syslog(get_class($this)."::initAsSpecimen");
1951 
1952  // Initialise parametres
1953  $this->id = 0;
1954  $this->fk_parent = 0;
1955  $this->label = 'SPECIMEN';
1956  $this->specimen = 1;
1957  $this->description = 'This is a description';
1958  $this->socid = 1;
1959  $this->type = self::TYPE_PRODUCT;
1960  }
1961 
1970  public static function replaceThirdparty(DoliDB $dbs, $origin_id, $dest_id)
1971  {
1972  $tables = array(
1973  'categorie_societe'
1974  );
1975 
1976  return CommonObject::commonReplaceThirdparty($dbs, $origin_id, $dest_id, $tables, 1);
1977  }
1978 
1987  public static function getFilterJoinQuery($type, $rowIdName)
1988  {
1989  if ($type == 'bank_account') {
1990  $type = 'account';
1991  }
1992 
1993  return " LEFT JOIN ".MAIN_DB_PREFIX."categorie_".$type." as cp ON ".$rowIdName." = cp.fk_".$type;
1994  }
1995 
2005  public static function getFilterSelectQuery($type, $rowIdName, $searchList)
2006  {
2007  if ($type == 'bank_account') {
2008  $type = 'account';
2009  }
2010  if ($type == 'customer') {
2011  $type = 'societe';
2012  }
2013  if ($type == 'supplier') {
2014  $type = 'fournisseur';
2015  }
2016 
2017  if (empty($searchList) && !is_array($searchList)) {
2018  return "";
2019  }
2020 
2021  $searchCategorySqlList = array();
2022  foreach ($searchList as $searchCategory) {
2023  if (intval($searchCategory) == -2) {
2024  $searchCategorySqlList[] = " cp.fk_categorie IS NULL";
2025  } elseif (intval($searchCategory) > 0) {
2026  $searchCategorySqlList[] = " ".$rowIdName." IN (SELECT fk_".$type." FROM ".MAIN_DB_PREFIX."categorie_".$type." WHERE fk_categorie = ".((int) $searchCategory).")";
2027  }
2028  }
2029 
2030  if (!empty($searchCategorySqlList)) {
2031  return " AND (".implode(' AND ', $searchCategorySqlList).")";
2032  } else {
2033  return "";
2034  }
2035  }
2036 
2042  public function countNbOfCategories()
2043  {
2044  dol_syslog(get_class($this)."::count_all_categories", LOG_DEBUG);
2045  $sql = "SELECT COUNT(rowid) FROM ".MAIN_DB_PREFIX."categorie";
2046  $sql .= " WHERE entity IN (".getEntity('category').")";
2047 
2048  $res = $this->db->query($sql);
2049  if ($res) {
2050  $obj = $this->db->fetch_object($res);
2051  return $obj->count;
2052  } else {
2053  dol_print_error($this->db);
2054  return -1;
2055  }
2056  }
2057 }
$object ref
Definition: info.php:78
Class to manage categories.
setMultiLangs($user)
Update ou cree les traductions des infos produits.
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, ...)
debug_cats()
Display content of $this->cats.
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...
countNbOfCategories()
Count all categories.
del_type($obj, $type)
Delete object from category.
buildPathFromId($id_categ, $protection=1000)
For category id_categ and its childs available in this->cats, define property fullpath and fulllabel.
static getFilterSelectQuery($type, $rowIdName, $searchList)
Return the addtional SQL SELECT query for filtering a list by a category.
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.
already_exists()
Check if no category with same label already exists for this cat's parent or root and for this cat's ...
get_filles()
Return direct childs id 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 addtional 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.
getObjectsInCateg($type, $onlyids=0, $limit=0, $offset=0, $sortfield='', $sortorder='ASC')
Return list of fetched instance of elements having this category.
static replaceThirdparty(DoliDB $dbs, $origin_id, $dest_id)
Function used to replace a thirdparty id with another one.
getMapList()
Get map list.
get_full_arbo($type, $markafterid=0, $include=0)
Rebuilding the category tree as an array Return an array of table('id','id_mere',....
get_meres()
Returns an array containing the list of parent categories.
add_type($obj, $type='')
Link an object to the category.
create($user)
Add category into database.
update(User $user)
Update category.
liste_photos($dir, $nbmax=0)
Return tableau de toutes les photos de la categorie.
get_all_ways()
Returns in a table all possible paths to get to the category starting with the major categories repre...
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...
getNomUrl($withpicto=0, $option='', $maxlength=0, $moreparam='')
Return name and link of category (with picto) Use ->id, ->ref, ->label, ->color.
add_photo($sdir, $file)
Deplace fichier uploade sous le nom $file dans le repertoire sdir.
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.
Definition: user.class.php:45
if(isModEnabled('facture') &&!empty($user->rights->facture->lire)) if((isModEnabled('fournisseur') &&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->hasRight("fournisseur", "facture", "lire"))||(isModEnabled('supplier_invoice') && $user->hasRight("supplier_invoice", "lire"))) if(isModEnabled('don') &&!empty($user->rights->don->lire)) if(isModEnabled('tax') &&!empty($user->rights->tax->charges->lire)) if(isModEnabled('facture') &&isModEnabled('commande') && $user->hasRight("commande", "lire") &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) $resql
Social contributions to pay.
Definition: index.php:745
print *****$script_file(".$version.") pid 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.
Definition: files.lib.php:1250
dol_move_uploaded_file($src_file, $dest_file, $allowoverwrite, $disablevirusscan=0, $uploaderrorcode=0, $nohook=0, $varfiles='addedfile', $upload_dir='')
Make control on an uploaded file from an GUI page and move it to final destination.
Definition: files.lib.php:1111
dol_is_file($pathoffile)
Return if path is a file.
Definition: files.lib.php:480
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0)
Returns text escaped for inclusion in HTML alt or title tags, or into values of HTML input fields.
dol_print_error($db='', $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0)
Show a picto called object_picto (generic function)
dol_now($mode='auto')
Return date for now.
getDolGlobalInt($key, $default=0)
Return dolibarr global constant int value.
dol_sort_array(&$array, $index, $order='asc', $natsort=0, $case_sensitive=0, $keepindex=0)
Advanced sort array by second index function, which produces ascending (default) or descending output...
colorIsLight($stringcolor)
Return true if the color is light.
sanitizeVal($out='', $check='alphanohtml', $filter=null, $options=null)
Return a sanitized or empty value after checking value against a rule.
isModEnabled($module)
Is Dolibarr module enabled.
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)
$nbtotalofrecords
Count total nb of records.
Definition: list.php:329
if(preg_match('/crypted:/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
Definition: repair.php:119
$conf db
API class for accounts.
Definition: inc.php:41