Passed
Branch develop (c36c8e)
by
unknown
39:14
created

Categorie::print_all_ways()   C

Complexity

Conditions 12
Paths 32

Size

Total Lines 48
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 12
eloc 27
nc 32
nop 4
dl 0
loc 48
rs 6.9666
c 0
b 0
f 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/* Copyright (C) 2005       Matthieu Valleton       <[email protected]>
3
 * Copyright (C) 2005       Davoleau Brice          <[email protected]>
4
 * Copyright (C) 2005       Rodolphe Quiedeville    <[email protected]>
5
 * Copyright (C) 2006-2012  Regis Houssin           <[email protected]>
6
 * Copyright (C) 2006-2012  Laurent Destailleur     <[email protected]>
7
 * Copyright (C) 2007       Patrick Raguin          <[email protected]>
8
 * Copyright (C) 2013-2016  Juanjo Menent           <[email protected]>
9
 * Copyright (C) 2013-2018  Philippe Grand          <[email protected]>
10
 * Copyright (C) 2015       Marcos García           <[email protected]>
11
 * Copyright (C) 2015       Raphaël Doursenaud      <[email protected]>
12
 * Copyright (C) 2016       Charlie Benke           <[email protected]>
13
 * Copyright (C) 2018-2019  Frédéric France         <[email protected]>
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
29
/**
30
 *	\file       htdocs/categories/class/categorie.class.php
31
 *	\ingroup    categorie
32
 *	\brief      File of class to manage categories
33
 */
34
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.'/fourn/class/fournisseur.class.php';
38
require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php';
39
40
41
/**
42
 *	Class to manage categories
43
 */
44
class Categorie extends CommonObject
45
{
46
	// Categories types (we use string because we want to accept any modules/types in a future)
47
	const TYPE_PRODUCT   = 'product';
48
	const TYPE_SUPPLIER  = 'supplier';
49
	const TYPE_CUSTOMER  = 'customer';
50
	const TYPE_MEMBER    = 'member';
51
	const TYPE_CONTACT   = 'contact';
52
	const TYPE_USER      = 'user';
53
	const TYPE_PROJECT   = 'project';
54
	const TYPE_ACCOUNT   = 'bank_account';
55
    const TYPE_BANK_LINE = 'bank_line';
56
    const TYPE_WAREHOUSE = 'warehouse';
57
    const TYPE_ACTIONCOMM = 'actioncomm';
58
    const TYPE_WEBSITE_PAGE = 'website_page';
59
60
	/**
61
	 * @var string String with name of icon for myobject. Must be the part after the 'object_' into object_myobject.png
62
	 */
63
	public $picto = 'category';
64
65
66
	/**
67
	 * @var array Table of mapping between type string and ID used for field 'type' in table llx_categories
68
	 */
69
	protected $MAP_ID = array(
70
		'product'      => 0,
71
		'supplier'     => 1,
72
		'customer'     => 2,
73
		'member'       => 3,
74
		'contact'      => 4,
75
		'bank_account' => 5,
76
        'project'      => 6,
77
		'user'         => 7,
78
		'bank_line'    => 8,
79
		'warehouse'    => 9,
80
        'actioncomm'   => 10,
81
		'website_page' => 11
82
	);
83
84
    /**
85
	 * @var array Code mapping from ID
86
	 *
87
	 * @note This array should be removed in future, once previous constants are moved to the string value. Deprecated
88
	 */
89
	public static $MAP_ID_TO_CODE = array(
90
		0 => 'product',
91
		1 => 'supplier',
92
		2 => 'customer',
93
		3 => 'member',
94
		4 => 'contact',
95
		5 => 'bank_account',
96
		6 => 'project',
97
		7 => 'user',
98
		8 => 'bank_line',
99
		9 => 'warehouse',
100
        10 => 'actioncomm',
101
	);
102
103
	/**
104
	 * @var array Foreign keys mapping from type string when value does not match
105
	 *
106
	 * @todo Move to const array when PHP 5.6 will be our minimum target
107
	 */
108
	protected $MAP_CAT_FK = array(
109
		'customer' => 'soc',
110
		'supplier' => 'soc',
111
		'contact'  => 'socpeople',
112
        'bank_account' => 'account',
113
    );
114
115
    /**
116
	 * @var array Category tables mapping from type string (llx_categorie_...) when value does not match
117
	 *
118
	 * @note Move to const array when PHP 5.6 will be our minimum target
119
	 */
120
	protected $MAP_CAT_TABLE = array(
121
		'customer' => 'societe',
122
		'supplier' => 'fournisseur',
123
        'bank_account'=> 'account',
124
	);
125
126
    /**
127
	 * @var array Object class mapping from type string
128
	 *
129
	 * @note Move to const array when PHP 5.6 will be our minimum target
130
	 */
131
	protected $MAP_OBJ_CLASS = array(
132
		'product'  => 'Product',
133
		'customer' => 'Societe',
134
		'supplier' => 'Fournisseur',
135
		'member'   => 'Adherent',
136
		'contact'  => 'Contact',
137
		'user'     => 'User',
138
		'account'  => 'Account', // old for bank account
139
		'bank_account'  => 'Account',
140
        'project'  => 'Project',
141
        'warehouse'=> 'Entrepot',
142
        'actioncomm' => 'ActionComm',
143
		'website_page' => 'WebsitePage'
144
	);
145
146
    /**
147
     * @var array Title Area mapping from type string
148
     *
149
     * @note Move to const array when PHP 5.6 will be our minimum target
150
     */
151
    public static $MAP_TYPE_TITLE_AREA = array(
152
        'product' => 'ProductsCategoriesArea',
153
        'customer' => 'CustomersCategoriesArea',
154
        'supplier' => 'SuppliersCategoriesArea',
155
        'member' => 'MembersCategoriesArea',
156
        'contact' => 'ContactsCategoriesArea',
157
        'user' => 'UsersCategoriesArea',
158
        'account' => 'AccountsCategoriesArea', // old for bank account
159
        'bank_account' => 'AccountsCategoriesArea',
160
        'project' => 'ProjectsCategoriesArea',
161
        'warehouse'=> 'StocksCategoriesArea',
162
        'actioncomm' => 'ActioncommCategoriesArea',
163
        'website_page' => 'WebsitePageCategoriesArea'
164
    );
165
166
    /**
167
	 * @var array Object table mapping from type string (table llx_...) when value of key does not match table name.
168
	 *
169
	 * @note Move to const array when PHP 5.6 will be our minimum target
170
	 */
171
	protected $MAP_OBJ_TABLE = array(
172
		'customer' => 'societe',
173
		'supplier' => 'societe',
174
		'member'   => 'adherent',
175
		'contact'  => 'socpeople',
176
		'account'  => 'bank_account', // old for bank account
177
		'project'  => 'projet',
178
        'warehouse'=> 'entrepot'
179
	);
180
181
	/**
182
	 * @var string ID to identify managed object
183
	 */
184
	public $element = 'category';
185
186
	/**
187
	 * @var string Name of table without prefix where object is stored
188
	 */
189
	public $table_element = 'categorie';
190
191
	/**
192
     * @var int ID
193
     */
194
	public $fk_parent;
195
196
	/**
197
     * @var string Category label
198
     */
199
   	public $label;
200
201
	/**
202
	 * @var string description
203
	 */
204
	public $description;
205
206
	/**
207
	 * @var string     Color
208
	 */
209
	public $color;
210
211
	/**
212
	 * @var int		  Id of thirdparty when CATEGORY_ASSIGNED_TO_A_CUSTOMER is set
213
	 */
214
	public $socid;
215
216
	/**
217
	 * @var string	Category type
218
	 *
219
	 * @see Categorie::TYPE_ACCOUNT
220
	 * @see Categorie::TYPE_PRODUCT
221
	 * @see Categorie::TYPE_SUPPLIER
222
	 * @see Categorie::TYPE_CUSTOMER
223
	 * @see Categorie::TYPE_MEMBER
224
	 * @see Categorie::TYPE_CONTACT
225
	 * @see Categorie::TYPE_USER
226
	 * @see Categorie::TYPE_PROJECT
227
	 * @see Categorie::TYPE_BANK_LINE
228
     * @see Categorie::TYPE_WAREHOUSE
229
     * @see Categorie::TYPE_ACTIONCOMM
230
	 */
231
	public $type;
232
233
	/**
234
	 * @var array Categories table in memory
235
	 */
236
	public $cats = array();
237
238
    /**
239
	 * @var array Mother of table
240
	 */
241
	public $motherof = array();
242
243
	/**
244
	 *	Constructor
245
	 *
246
	 *  @param		DoliDB		$db     Database handler
247
	 */
248
	public function __construct($db)
249
	{
250
		global $hookmanager;
251
252
		$this->db = $db;
253
254
		if (is_object($hookmanager)) {
255
			$hookmanager->initHooks(array('category'));
256
			$parameters = array();
257
			$reshook = $hookmanager->executeHooks('constructCategory', $parameters, $this); // Note that $action and $object may have been modified by some hooks
258
			if ($reshook >= 0 && !empty($hookmanager->resArray)) {
259
				$mapList = $hookmanager->resArray;
260
				$mapId   = $mapList['id'];
261
				$mapCode = $mapList['code'];
262
				self::$MAP_ID_TO_CODE[$mapId]  = $mapCode;
263
				$this->MAP_ID[$mapCode]        = $mapId;
264
				$this->MAP_CAT_FK[$mapCode]    = $mapList['cat_fk'];
265
				$this->MAP_CAT_TABLE[$mapCode] = $mapList['cat_table'];
266
				$this->MAP_OBJ_CLASS[$mapCode] = $mapList['obj_class'];
267
				$this->MAP_OBJ_TABLE[$mapCode] = $mapList['obj_table'];
268
			}
269
		}
270
	}
271
272
	/**
273
	 * Get map list
274
	 *
275
	 * @return	array
276
	 */
277
	public function getMapList()
278
	{
279
		$mapList = array();
280
281
		foreach ($this->MAP_ID as $mapCode => $mapId) {
282
			$mapList[] = array(
283
				'id'        => $mapId,
284
				'code'      => $mapCode,
285
				'cat_fk'    => (empty($this->MAP_CAT_FK[$mapCode]) ? $mapCode : $this->MAP_CAT_FK[$mapCode]),
286
				'cat_table' => (empty($this->MAP_CAT_TABLE[$mapCode]) ? $mapCode : $this->MAP_CAT_TABLE[$mapCode]),
287
				'obj_class' => (empty($this->MAP_OBJ_CLASS[$mapCode]) ? $mapCode : $this->MAP_OBJ_CLASS[$mapCode]),
288
				'obj_table' => (empty($this->MAP_OBJ_TABLE[$mapCode]) ? $mapCode : $this->MAP_OBJ_TABLE[$mapCode])
289
			);
290
		}
291
292
		return $mapList;
293
	}
294
295
	/**
296
	 * 	Load category into memory from database
297
	 *
298
	 * 	@param		int		$id      Id of category
299
	 *  @param		string	$label   Label of category
300
	 *  @param		string	$type    Type of category ('product', '...') or (0, 1, ...)
301
	 *  @param		string	$ref_ext External reference of object
302
	 * 	@return		int				<0 if KO, >0 if OK
303
	 */
304
	public function fetch($id, $label = '', $type = null, $ref_ext = '')
305
	{
306
		global $conf;
307
308
		// Check parameters
309
		if (empty($id) && empty($label) && empty($ref_ext)) return -1;
310
		if (!is_numeric($type)) $type = $this->MAP_ID[$type];
311
312
		$sql = "SELECT rowid, fk_parent, entity, label, description, color, fk_soc, visible, type, ref_ext";
313
		$sql .= ", date_creation, tms, fk_user_creat, fk_user_modif";
314
		$sql .= " FROM ".MAIN_DB_PREFIX."categorie";
315
		if ($id > 0)
316
		{
317
			$sql .= " WHERE rowid = ".$id;
318
		} elseif (!empty($ref_ext))
319
		{
320
			$sql .= " WHERE ref_ext LIKE '".$this->db->escape($ref_ext)."'";
321
		} else {
322
			$sql .= " WHERE label = '".$this->db->escape($label)."' AND entity IN (".getEntity('category').")";
323
			if (!is_null($type)) $sql .= " AND type = ".$this->db->escape($type);
324
		}
325
326
		dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
327
		$resql = $this->db->query($sql);
328
		if ($resql)
329
		{
330
			if ($this->db->num_rows($resql) > 0)
331
			{
332
				$res = $this->db->fetch_array($resql);
333
334
				$this->id = $res['rowid'];
335
				//$this->ref = $res['rowid'];
336
				$this->fk_parent	= $res['fk_parent'];
337
				$this->label		= $res['label'];
338
				$this->description = $res['description'];
339
				$this->color    	= $res['color'];
340
				$this->socid		= $res['fk_soc'];
341
				$this->visible = $res['visible'];
342
				$this->type = $res['type'];
343
				$this->ref_ext = $res['ref_ext'];
344
				$this->entity = $res['entity'];
345
				$this->date_creation = $this->db->jdate($res['date_creation']);
346
				$this->date_modification = $this->db->jdate($res['tms']);
347
				$this->user_creation = $res['fk_user_creat'];
348
				$this->user_modification = $res['fk_user_modif'];
349
350
				// Retreive all extrafield
351
				// fetch optionals attributes and labels
352
				$this->fetch_optionals();
353
354
				$this->db->free($resql);
355
356
				// multilangs
357
				if (!empty($conf->global->MAIN_MULTILANGS)) $this->getMultiLangs();
358
359
				return 1;
360
			} else {
361
				return 0;
362
			}
363
		} else {
364
			dol_print_error($this->db);
365
			return -1;
366
		}
367
	}
368
369
	/**
370
	 *  Add category into database
371
	 *
372
	 *  @param	User	$user		Object user
373
	 *  @return	int 				-1 : SQL error
374
	 *          					-2 : new ID unknown
375
	 *          					-3 : Invalid category
376
	 * 								-4 : category already exists
377
	 */
378
	public function create($user)
379
	{
380
		global $conf, $langs, $hookmanager;
381
		$langs->load('categories');
382
383
		$type = $this->type;
384
385
		if (!is_numeric($type)) $type = $this->MAP_ID[$type];
386
387
		$error = 0;
388
389
		dol_syslog(get_class($this).'::create', LOG_DEBUG);
390
391
		// Clean parameters
392
		$this->label = trim($this->label);
393
		$this->description = trim($this->description);
394
		$this->color = trim($this->color);
395
		$this->import_key = trim($this->import_key);
396
		$this->ref_ext = trim($this->ref_ext);
397
		if (empty($this->visible)) $this->visible = 0;
398
		$this->fk_parent = ($this->fk_parent != "" ? intval($this->fk_parent) : 0);
399
400
		if ($this->already_exists())
401
		{
402
			$this->error = $langs->trans("ImpossibleAddCat", $this->label);
403
			$this->error .= " : ".$langs->trans("CategoryExistsAtSameLevel");
404
			dol_syslog($this->error, LOG_WARNING);
405
			return -4;
406
		}
407
408
		$this->db->begin();
409
		$now = dol_now();
410
		$sql = "INSERT INTO ".MAIN_DB_PREFIX."categorie (";
411
		$sql .= "fk_parent,";
412
		$sql .= " label,";
413
		$sql .= " description,";
414
		$sql .= " color,";
415
		if (!empty($conf->global->CATEGORY_ASSIGNED_TO_A_CUSTOMER))
416
		{
417
			$sql .= "fk_soc,";
418
		}
419
		$sql .= " visible,";
420
		$sql .= " type,";
421
		$sql .= " import_key,";
422
		$sql .= " ref_ext,";
423
		$sql .= " entity,";
424
		$sql .= " date_creation,";
425
		$sql .= " fk_user_creat";
426
		$sql .= ") VALUES (";
427
		$sql .= $this->db->escape($this->fk_parent).",";
428
		$sql .= "'".$this->db->escape($this->label)."',";
429
		$sql .= "'".$this->db->escape($this->description)."',";
430
		$sql .= "'".$this->db->escape($this->color)."',";
431
		if (!empty($conf->global->CATEGORY_ASSIGNED_TO_A_CUSTOMER))
432
		{
433
			$sql .= ($this->socid != -1 ? $this->socid : 'null').",";
434
		}
435
		$sql .= "'".$this->db->escape($this->visible)."',";
436
		$sql .= $this->db->escape($type).",";
437
		$sql .= (!empty($this->import_key) ? "'".$this->db->escape($this->import_key)."'" : 'null').",";
438
		$sql .= (!empty($this->ref_ext) ? "'".$this->db->escape($this->ref_ext)."'" : 'null').",";
439
		$sql .= $this->db->escape($conf->entity).",";
440
		$sql .= "'".$this->db->idate($now)."', ";
441
		$sql .= (int) $user->id;
442
		$sql .= ")";
443
444
		$res = $this->db->query($sql);
445
		if ($res)
446
		{
447
			$id = $this->db->last_insert_id(MAIN_DB_PREFIX."categorie");
448
449
			if ($id > 0)
450
			{
451
				$this->id = $id;
452
453
				$action = 'create';
454
455
				// Actions on extra fields
456
				if (!$error)
457
				{
458
					$result = $this->insertExtraFields();
459
					if ($result < 0)
460
					{
461
						$error++;
462
					}
463
				}
464
465
				if (!$error)
466
				{
467
	                // Call trigger
468
    	            $result = $this->call_trigger('CATEGORY_CREATE', $user);
469
        	        if ($result < 0) { $error++; }
470
            	    // End call triggers
471
				}
472
473
                if (!$error)
474
                {
475
    				$this->db->commit();
476
    				return $id;
477
                } else {
478
                	$this->db->rollback();
479
                    return -3;
480
                }
481
			} else {
482
				$this->db->rollback();
483
				return -2;
484
			}
485
		} else {
486
			$this->error = $this->db->error();
487
			$this->db->rollback();
488
			return -1;
489
		}
490
	}
491
492
	/**
493
	 * 	Update category
494
	 *
495
	 *	@param	User	$user		Object user
496
	 * 	@return	int		 			1 : OK
497
	 *          					-1 : SQL error
498
	 *          					-2 : invalid category
499
	 */
500
	public function update(User $user)
501
	{
502
		global $conf, $langs, $hookmanager;
503
504
		$error = 0;
505
506
		// Clean parameters
507
		$this->label = trim($this->label);
508
		$this->description = trim($this->description);
509
		$this->ref_ext = trim($this->ref_ext);
510
		$this->fk_parent = ($this->fk_parent != "" ? intval($this->fk_parent) : 0);
511
		$this->visible = ($this->visible != "" ? intval($this->visible) : 0);
512
513
		if ($this->already_exists())
514
		{
515
			$this->error = $langs->trans("ImpossibleUpdateCat");
516
			$this->error .= " : ".$langs->trans("CategoryExistsAtSameLevel");
517
			return -1;
518
		}
519
520
		$this->db->begin();
521
522
		$sql = "UPDATE ".MAIN_DB_PREFIX."categorie";
523
		$sql .= " SET label = '".$this->db->escape($this->label)."',";
524
		$sql .= " description = '".$this->db->escape($this->description)."',";
525
		$sql .= " ref_ext = '".$this->db->escape($this->ref_ext)."',";
526
		$sql .= " color = '".$this->db->escape($this->color)."'";
527
		if (!empty($conf->global->CATEGORY_ASSIGNED_TO_A_CUSTOMER))
528
		{
529
			$sql .= ", fk_soc = ".($this->socid != -1 ? $this->socid : 'null');
530
		}
531
		$sql .= ", visible = '".$this->db->escape($this->visible)."'";
532
		$sql .= ", fk_parent = ".$this->fk_parent;
533
		$sql .= ", fk_user_modif = ".(int) $user->id;
534
		$sql .= " WHERE rowid = ".$this->id;
535
536
		dol_syslog(get_class($this)."::update", LOG_DEBUG);
537
		if ($this->db->query($sql))
538
		{
539
			$action = 'update';
540
541
			// Actions on extra fields
542
			if (!$error)
543
			{
544
				$result = $this->insertExtraFields();
545
				if ($result < 0)
546
				{
547
					$error++;
548
				}
549
			}
550
551
			if (!$error)
552
			{
553
	            // Call trigger
554
    	        $result = $this->call_trigger('CATEGORY_MODIFY', $user);
555
        	    if ($result < 0) { $error++; $this->db->rollback(); return -1; }
556
            	// End call triggers
557
			}
558
559
			$this->db->commit();
560
561
			return 1;
562
		} else {
563
			$this->db->rollback();
564
			dol_print_error($this->db);
565
			return -1;
566
		}
567
	}
568
569
	/**
570
	 * 	Delete a category from database
571
	 *
572
	 * 	@param	User	$user		Object user that ask to delete
573
     *	@param	int		$notrigger	1=Does not execute triggers, 0= execute triggers
574
	 *	@return	int                 <0 KO >0 OK
575
	 */
576
	public function delete($user, $notrigger = 0)
577
	{
578
		global $conf, $langs;
579
580
		$error = 0;
581
582
        // Clean parameters
583
		$this->fk_parent = ($this->fk_parent != "" ? intval($this->fk_parent) : 0);
584
585
		dol_syslog(get_class($this)."::remove");
586
587
		$this->db->begin();
588
589
		if (!$error && !$notrigger)
590
		{
591
		    // Call trigger
592
		    $result = $this->call_trigger('CATEGORY_DELETE', $user);
593
		    if ($result < 0) $error++;
594
		    // End call triggers
595
		}
596
597
		/* FIX #1317 : Check for child category and move up 1 level*/
598
		if (!$error)
599
		{
600
			$sql = "UPDATE ".MAIN_DB_PREFIX."categorie";
601
			$sql .= " SET fk_parent = ".$this->fk_parent;
602
			$sql .= " WHERE fk_parent = ".$this->id;
603
604
			if (!$this->db->query($sql))
605
			{
606
				$this->error = $this->db->lasterror();
607
				$error++;
608
			}
609
		}
610
611
        $arraydelete = array(
612
            'categorie_societe' => 'fk_categorie',
613
            'categorie_fournisseur' => 'fk_categorie',
614
            'categorie_product' => 'fk_categorie',
615
            'categorie_member' => 'fk_categorie',
616
            'categorie_contact' => 'fk_categorie',
617
            'categorie_account' => 'fk_categorie',
618
            'bank_class' => 'fk_categ',
619
            'categorie_lang' => 'fk_category',
620
            'categorie' => 'rowid',
621
        );
622
        foreach ($arraydelete as $key => $value) {
623
            $sql  = "DELETE FROM ".MAIN_DB_PREFIX.$key;
624
            $sql .= " WHERE ".$value." = ".$this->id;
625
            if (!$this->db->query($sql)) {
626
                $this->errors[] = $this->db->lasterror();
627
                dol_syslog("Error sql=".$sql." ".$this->error, LOG_ERR);
628
                $error++;
629
            }
630
        }
631
632
		// Removed extrafields
633
		if (!$error)
634
		{
635
			$result = $this->deleteExtraFields();
636
			if ($result < 0)
637
			{
638
				$error++;
639
				dol_syslog(get_class($this)."::delete erreur ".$this->error, LOG_ERR);
640
			}
641
		}
642
643
		if (!$error)
644
		{
645
			$this->db->commit();
646
			return 1;
647
		} else {
648
			$this->db->rollback();
649
			return -1;
650
		}
651
	}
652
653
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
654
	/**
655
	 * Link an object to the category
656
	 *
657
	 * @param   CommonObject 	$obj  	Object to link to category
658
	 * @param   string     		$type 	Type of category ('product', ...). Use '' to take $obj->element.
659
	 * @return  int                		1 : OK, -1 : erreur SQL, -2 : id not defined, -3 : Already linked
660
	 */
661
	public function add_type($obj, $type = '')
662
	{
663
        // phpcs:enable
664
		global $user, $langs, $conf;
665
666
		$error = 0;
667
668
		if ($this->id == -1) return -2;
669
670
		if (empty($type)) $type = $obj->element;
671
672
        $this->db->begin();
673
674
        $sql = "INSERT INTO ".MAIN_DB_PREFIX."categorie_".(empty($this->MAP_CAT_TABLE[$type]) ? $type : $this->MAP_CAT_TABLE[$type]);
675
		$sql .= " (fk_categorie, fk_".(empty($this->MAP_CAT_FK[$type]) ? $type : $this->MAP_CAT_FK[$type]).")";
676
		$sql .= " VALUES (".$this->id.", ".$obj->id.")";
677
678
		dol_syslog(get_class($this).'::add_type', LOG_DEBUG);
679
		if ($this->db->query($sql))
680
		{
681
			if (!empty($conf->global->CATEGORIE_RECURSIV_ADD))
682
			{
683
				$sql = 'SELECT fk_parent FROM '.MAIN_DB_PREFIX.'categorie';
684
				$sql .= " WHERE rowid = ".$this->id;
685
686
				dol_syslog(get_class($this)."::add_type", LOG_DEBUG);
687
				$resql = $this->db->query($sql);
688
				if ($resql)
689
				{
690
					if ($this->db->num_rows($resql) > 0)
691
					{
692
                        $objparent = $this->db->fetch_object($resql);
693
694
						if (!empty($objparent->fk_parent))
695
						{
696
							$cat = new Categorie($this->db);
697
							$cat->id = $objparent->fk_parent;
698
							if (!$cat->containsObject($type, $obj->id)) {
699
								$result = $cat->add_type($obj, $type);
700
								if ($result < 0)
701
								{
702
									$this->error = $cat->error;
703
									$error++;
704
								}
705
							}
706
						}
707
					}
708
				} else {
709
					$error++;
710
					$this->error = $this->db->lasterror();
711
				}
712
713
				if ($error)
714
				{
715
				    $this->db->rollback();
716
					return -1;
717
				}
718
			}
719
720
721
722
            // Call trigger
723
			$this->context = array('linkto'=>$obj); // Save object we want to link category to into category instance to provide information to trigger
724
			$result = $this->call_trigger('CATEGORY_LINK', $user);
725
            if ($result < 0) { $error++; }
726
            // End call triggers
727
728
			if (!$error)
729
			{
730
			    $this->db->commit();
731
			    return 1;
732
			} else {
733
			    $this->db->rollback();
734
			    return -2;
735
			}
736
		} else {
737
		    $this->db->rollback();
738
			if ($this->db->lasterrno() == 'DB_ERROR_RECORD_ALREADY_EXISTS')
739
			{
740
				$this->error = $this->db->lasterrno();
741
				return -3;
742
			} else {
743
				$this->error = $this->db->lasterror();
744
			}
745
			return -1;
746
		}
747
	}
748
749
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
750
	/**
751
	 * Delete object from category
752
	 *
753
	 * @param   CommonObject $obj  Object
754
	 * @param   string       $type Type of category ('customer', 'supplier', 'contact', 'product', 'member')
755
	 *
756
	 * @return  int          1 if OK, -1 if KO
757
	 */
758
	public function del_type($obj, $type)
759
	{
760
        // phpcs:enable
761
		global $user, $langs, $conf;
762
763
		$error = 0;
764
765
		// For backward compatibility
766
		if ($type == 'societe') {
767
			$type = 'customer';
768
			dol_syslog(get_class($this)."::del_type(): type 'societe' is deprecated, please use 'customer' instead", LOG_WARNING);
769
		} elseif ($type == 'fournisseur') {
770
			$type = 'supplier';
771
			dol_syslog(get_class($this)."::del_type(): type 'fournisseur' is deprecated, please use 'supplier' instead", LOG_WARNING);
772
		}
773
774
        $this->db->begin();
775
776
        $sql = "DELETE FROM ".MAIN_DB_PREFIX."categorie_".(empty($this->MAP_CAT_TABLE[$type]) ? $type : $this->MAP_CAT_TABLE[$type]);
777
		$sql .= " WHERE fk_categorie = ".$this->id;
778
		$sql .= " AND fk_".(empty($this->MAP_CAT_FK[$type]) ? $type : $this->MAP_CAT_FK[$type])." = ".$obj->id;
779
780
		dol_syslog(get_class($this).'::del_type', LOG_DEBUG);
781
		if ($this->db->query($sql))
782
		{
783
            // Call trigger
784
			$this->context = array('unlinkoff'=>$obj); // Save object we want to link category to into category instance to provide information to trigger
785
			$result = $this->call_trigger('CATEGORY_UNLINK', $user);
786
            if ($result < 0) { $error++; }
787
            // End call triggers
788
789
			if (!$error)
790
			{
791
			    $this->db->commit();
792
			    return 1;
793
			} else {
794
			    $this->db->rollback();
795
                return -2;
796
			}
797
		} else {
798
		    $this->db->rollback();
799
			$this->error = $this->db->lasterror();
800
			return -1;
801
		}
802
	}
803
804
	/**
805
	 * Return list of fetched instance of elements having this category
806
	 *
807
	 * @param   string     	$type       Type of category ('customer', 'supplier', 'contact', 'product', 'member', ...)
808
	 * @param   int        	$onlyids    Return only ids of objects (consume less memory)
809
	 * @param	int			$limit		Limit
810
	 * @param	int			$offset		Offset
811
	 * @param	string		$sortfield	Sort fields
812
	 * @param	string		$sortorder	Sort order ('ASC' or 'DESC');
813
	 * @return  array|int              	-1 if KO, array of instance of object if OK
814
	 * @see containsObject()
815
	 */
816
	public function getObjectsInCateg($type, $onlyids = 0, $limit = 0, $offset = 0, $sortfield = '', $sortorder = 'ASC')
817
	{
818
		global $user;
819
820
		$objs = array();
821
822
		$tmpclass = $this->MAP_OBJ_CLASS[$type];
823
		$obj = new $tmpclass($this->db);
824
825
		$sql = "SELECT c.fk_".(empty($this->MAP_CAT_FK[$type]) ? $type : $this->MAP_CAT_FK[$type]);
826
		$sql .= " FROM ".MAIN_DB_PREFIX."categorie_".(empty($this->MAP_CAT_TABLE[$type]) ? $type : $this->MAP_CAT_TABLE[$type])." as c";
827
		$sql .= ", ".MAIN_DB_PREFIX.(empty($this->MAP_OBJ_TABLE[$type]) ? $type : $this->MAP_OBJ_TABLE[$type])." as o";
828
		$sql .= " WHERE o.entity IN (".getEntity($obj->element).")";
829
		$sql .= " AND c.fk_categorie = ".$this->id;
830
		$sql .= " AND c.fk_".(empty($this->MAP_CAT_FK[$type]) ? $type : $this->MAP_CAT_FK[$type])." = o.rowid";
831
		// Protection for external users
832
		if (($type == 'customer' || $type == 'supplier') && $user->socid > 0)
833
		{
834
			$sql .= " AND o.rowid = ".$user->socid;
835
		}
836
		if ($limit > 0 || $offset > 0)  $sql .= $this->db->plimit($limit + 1, $offset);
837
		$sql .= $this->db->order($sortfield, $sortorder);
838
839
		dol_syslog(get_class($this)."::getObjectsInCateg", LOG_DEBUG);
840
		$resql = $this->db->query($sql);
841
		if ($resql)
842
		{
843
			while ($rec = $this->db->fetch_array($resql))
844
			{
845
			    if ($onlyids)
846
			    {
847
			    	$objs[] = $rec['fk_'.(empty($this->MAP_CAT_FK[$type]) ? $type : $this->MAP_CAT_FK[$type])];
848
			    } else {
849
				    $obj = new $this->MAP_OBJ_CLASS[$type]($this->db);
850
				    $obj->fetch($rec['fk_'.(empty($this->MAP_CAT_FK[$type]) ? $type : $this->MAP_CAT_FK[$type])]);
851
				    $objs[] = $obj;
852
			    }
853
			}
854
			return $objs;
855
		} else {
856
			$this->error = $this->db->error().' sql='.$sql;
857
			return -1;
858
		}
859
	}
860
861
	/**
862
	 * Check for the presence of an object in a category
863
	 *
864
	 * @param   string $type      		Type of category ('customer', 'supplier', 'contact', 'product', 'member')
865
	 * @param   int    $object_id 		Id of the object to search
866
	 * @return  int                     Number of occurrences
867
	 * @see getObjectsInCateg()
868
	 */
869
	public function containsObject($type, $object_id)
870
	{
871
		$sql = "SELECT COUNT(*) as nb FROM ".MAIN_DB_PREFIX."categorie_".(empty($this->MAP_CAT_TABLE[$type]) ? $type : $this->MAP_CAT_TABLE[$type]);
872
		$sql .= " WHERE fk_categorie = ".$this->id." AND fk_".(empty($this->MAP_CAT_FK[$type]) ? $type : $this->MAP_CAT_FK[$type])." = ".$object_id;
873
		dol_syslog(get_class($this)."::containsObject", LOG_DEBUG);
874
		$resql = $this->db->query($sql);
875
		if ($resql) {
876
			return $this->db->fetch_object($resql)->nb;
877
		} else {
878
			$this->error = $this->db->error().' sql='.$sql;
879
			return -1;
880
		}
881
	}
882
883
	/**
884
	 * List categories of an element id
885
	 *
886
	 * @param	int		$id			Id of element
887
	 * @param	string	$type		Type of category ('member', 'customer', 'supplier', 'product', 'contact')
888
	 * @param	string	$sortfield	Sort field
889
	 * @param	string	$sortorder	Sort order
890
	 * @param	int		$limit		Limit for list
891
	 * @param	int		$page		Page number
892
	 * @return	array|int			Array of categories, 0 if no cat, -1 on error
893
	 */
894
	public function getListForItem($id, $type = 'customer', $sortfield = "s.rowid", $sortorder = 'ASC', $limit = 0, $page = 0)
895
	{
896
		global $conf;
897
898
		$categories = array();
899
900
		$sub_type = $type;
901
		$subcol_name = "fk_".$type;
902
		if ($type == "customer") {
903
			$sub_type = "societe";
904
			$subcol_name = "fk_soc";
905
		}
906
		if ($type == "supplier") {
907
			$sub_type = "fournisseur";
908
			$subcol_name = "fk_soc";
909
		}
910
		if ($type == "contact") {
911
			$subcol_name = "fk_socpeople";
912
		}
913
914
		$idoftype = array_search($type, self::$MAP_ID_TO_CODE);
915
916
		$sql = "SELECT s.rowid";
917
		$sql .= " FROM ".MAIN_DB_PREFIX."categorie as s";
918
		$sql .= " , ".MAIN_DB_PREFIX."categorie_".$sub_type." as sub ";
919
		$sql .= ' WHERE s.entity IN ('.getEntity('category').')';
920
		$sql .= ' AND s.type='.$idoftype;
921
		$sql .= ' AND s.rowid = sub.fk_categorie';
922
		$sql .= ' AND sub.'.$subcol_name.' = '.$id;
923
924
		$sql .= $this->db->order($sortfield, $sortorder);
925
926
		$offset = 0;
927
		$nbtotalofrecords = '';
928
		if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST))
929
		{
930
			$result = $this->db->query($sql);
931
			$nbtotalofrecords = $this->db->num_rows($result);
932
			if (($page * $limit) > $nbtotalofrecords)	// if total resultset is smaller then paging size (filtering), goto and load page 0
933
			{
934
				$page = 0;
935
				$offset = 0;
936
			}
937
		}
938
939
		if ($limit) {
940
			if ($page < 0)
941
			{
942
				$page = 0;
943
			}
944
			$offset = $limit * $page;
945
946
			$sql .= $this->db->plimit($limit + 1, $offset);
947
		}
948
949
		$result = $this->db->query($sql);
950
		if ($result)
951
		{
952
			$i = 0;
953
			$num = $this->db->num_rows($result);
954
			$min = min($num, ($limit <= 0 ? $num : $limit));
955
			while ($i < $min)
956
			{
957
				$obj = $this->db->fetch_object($result);
958
				$category_static = new Categorie($this->db);
959
				if ($category_static->fetch($obj->rowid))
960
				{
961
					$categories[$i]['id'] = $category_static->id;
962
					$categories[$i]['fk_parent']		= $category_static->fk_parent;
963
					$categories[$i]['label']			= $category_static->label;
964
					$categories[$i]['description'] = $category_static->description;
965
					$categories[$i]['color']    		= $category_static->color;
966
					$categories[$i]['socid']			= $category_static->socid;
967
					$categories[$i]['ref_ext'] = $category_static->ref_ext;
968
					$categories[$i]['visible'] = $category_static->visible;
969
					$categories[$i]['type'] = $category_static->type;
970
					$categories[$i]['entity'] = $category_static->entity;
971
					$categories[$i]['array_options'] = $category_static->array_options;
972
973
					// multilangs
974
					if (!empty($conf->global->MAIN_MULTILANGS)) {
975
						$categories[$i]['multilangs'] = $category_static->multilangs;
976
					}
977
				}
978
				$i++;
979
			}
980
		} else {
981
			$this->error = $this->db->lasterror();
982
			return -1;
983
		}
984
		if (!count($categories)) {
985
			return 0;
986
		}
987
988
		return $categories;
989
	}
990
991
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
992
	/**
993
	 * Return direct childs id of a category into an array
994
	 *
995
	 * @return	array|int   <0 KO, array ok
996
	 */
997
	public function get_filles()
998
	{
999
        // phpcs:enable
1000
		$sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."categorie";
1001
		$sql .= " WHERE fk_parent = ".$this->id;
1002
		$sql .= " AND entity IN (".getEntity('category').")";
1003
1004
		$res = $this->db->query($sql);
1005
		if ($res)
1006
		{
1007
			$cats = array();
1008
			while ($rec = $this->db->fetch_array($res))
1009
			{
1010
				$cat = new Categorie($this->db);
1011
				$cat->fetch($rec['rowid']);
1012
				$cats[] = $cat;
1013
			}
1014
			return $cats;
1015
		} else {
1016
			dol_print_error($this->db);
1017
			return -1;
1018
		}
1019
	}
1020
1021
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1022
	/**
1023
	 * 	Load the array this->motherof that is array(id_son=>id_parent, ...)
1024
	 *
1025
	 *	@return		int		<0 if KO, >0 if OK
1026
	 */
1027
	protected function load_motherof()
1028
	{
1029
        // phpcs:enable
1030
	    $this->motherof = array();
1031
1032
		// Load array[child]=parent
1033
		$sql = "SELECT fk_parent as id_parent, rowid as id_son";
1034
		$sql .= " FROM ".MAIN_DB_PREFIX."categorie";
1035
		$sql .= " WHERE fk_parent != 0";
1036
		$sql .= " AND entity IN (".getEntity('category').")";
1037
1038
		dol_syslog(get_class($this)."::load_motherof", LOG_DEBUG);
1039
		$resql = $this->db->query($sql);
1040
		if ($resql)
1041
		{
1042
			while ($obj = $this->db->fetch_object($resql))
1043
			{
1044
				$this->motherof[$obj->id_son] = $obj->id_parent;
1045
			}
1046
			return 1;
1047
		} else {
1048
			dol_print_error($this->db);
1049
			return -1;
1050
		}
1051
	}
1052
1053
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1054
	/**
1055
	 * Rebuilding the category tree as an array
1056
	 * Return an array of table('id','id_mere',...) trie selon arbre et avec:
1057
	 *                id = id de la categorie
1058
	 *                id_mere = id de la categorie mere
1059
	 *                id_children = tableau des id enfant
1060
	 *                label = nom de la categorie
1061
	 *                fulllabel = nom avec chemin complet de la categorie
1062
	 *                fullpath = chemin complet compose des id
1063
	 *
1064
	 * @param   string                  $type                   Type of categories ('customer', 'supplier', 'contact', 'product', 'member', ...)
1065
	 * @param   int|string|array        $markafterid            Keep only or removed all categories including the leaf $markafterid in category tree (exclude) or Keep only of category is inside the leaf starting with this id.
1066
     *                                                          $markafterid can be an :
1067
     *                                                          - int (id of category)
1068
     *                                                          - string (categories ids separated by comma)
1069
     *                                                          - array (list of categories ids)
1070
     * @param   int                     $include                [=0] Removed or 1=Keep only
1071
	 * @return  array|int               Array of categories. this->cats and this->motherof are set, -1 on error
1072
	 */
1073
	public function get_full_arbo($type, $markafterid = 0, $include = 0)
1074
	{
1075
        // phpcs:enable
1076
	    global $conf, $langs;
1077
1078
		if (!is_numeric($type)) $type = $this->MAP_ID[$type];
1079
		if (is_null($type)) {
1080
			$this->error = 'BadValueForParameterType';
1081
			return -1;
1082
		}
1083
1084
        if (is_string($markafterid))
1085
        {
1086
            $markafterid = explode(',', $markafterid);
1087
        } elseif (is_numeric($markafterid))
1088
        {
1089
            if ($markafterid > 0)
1090
            {
1091
                $markafterid = array($markafterid);
1092
            } else {
1093
                $markafterid = array();
1094
            }
1095
        } elseif (!is_array($markafterid))
1096
        {
1097
            $markafterid = array();
1098
        }
1099
1100
        $this->cats = array();
1101
1102
		// Init this->motherof that is array(id_son=>id_parent, ...)
1103
		$this->load_motherof();
1104
		$current_lang = $langs->getDefaultLang();
1105
1106
		// Init $this->cats array
1107
		$sql = "SELECT DISTINCT c.rowid, c.label, c.description, c.color, c.fk_parent, c.visible"; // Distinct reduce pb with old tables with duplicates
1108
		if (!empty($conf->global->MAIN_MULTILANGS)) $sql .= ", t.label as label_trans, t.description as description_trans";
1109
		$sql .= " FROM ".MAIN_DB_PREFIX."categorie as c";
1110
		if (!empty($conf->global->MAIN_MULTILANGS)) $sql .= " LEFT  JOIN ".MAIN_DB_PREFIX."categorie_lang as t ON t.fk_category=c.rowid AND t.lang='".$this->db->escape($current_lang)."'";
1111
		$sql .= " WHERE c.entity IN (".getEntity('category').")";
1112
		$sql .= " AND c.type = ".(int) $type;
1113
1114
		dol_syslog(get_class($this)."::get_full_arbo get category list", LOG_DEBUG);
1115
		$resql = $this->db->query($sql);
1116
		if ($resql)
1117
		{
1118
			$i = 0;
1119
			while ($obj = $this->db->fetch_object($resql))
1120
			{
1121
				$this->cats[$obj->rowid]['rowid'] = $obj->rowid;
1122
				$this->cats[$obj->rowid]['id'] = $obj->rowid;
1123
				$this->cats[$obj->rowid]['fk_parent'] = $obj->fk_parent;
1124
				$this->cats[$obj->rowid]['label'] = !empty($obj->label_trans) ? $obj->label_trans : $obj->label;
1125
				$this->cats[$obj->rowid]['description'] = !empty($obj->description_trans) ? $obj->description_trans : $obj->description;
1126
				$this->cats[$obj->rowid]['color'] = $obj->color;
1127
				$this->cats[$obj->rowid]['visible'] = $obj->visible;
1128
				$this->cats[$obj->rowid]['ref_ext'] = $obj->ref_ext;
1129
				$i++;
1130
			}
1131
		} else {
1132
			dol_print_error($this->db);
1133
			return -1;
1134
		}
1135
1136
		// We add the fullpath property to each elements of first level (no parent exists)
1137
		dol_syslog(get_class($this)."::get_full_arbo call to build_path_from_id_categ", LOG_DEBUG);
1138
		foreach ($this->cats as $key => $val)
1139
		{
1140
			//print 'key='.$key.'<br>'."\n";
1141
			$this->build_path_from_id_categ($key, 0); // Process a branch from the root category key (this category has no parent)
1142
		}
1143
1144
        // Include or exclude leaf including $markafterid from tree
1145
        if (count($markafterid) > 0)
1146
        {
1147
            $keyfiltercatid = '('.implode('|', $markafterid).')';
1148
1149
            //print "Look to discard category ".$markafterid."\n";
1150
            $keyfilter1 = '^'.$keyfiltercatid.'$';
1151
            $keyfilter2 = '_'.$keyfiltercatid.'$';
1152
            $keyfilter3 = '^'.$keyfiltercatid.'_';
1153
            $keyfilter4 = '_'.$keyfiltercatid.'_';
1154
            foreach ($this->cats as $key => $val)
1155
            {
1156
                $test = (preg_match('/'.$keyfilter1.'/', $val['fullpath']) || preg_match('/'.$keyfilter2.'/', $val['fullpath'])
1157
                    || preg_match('/'.$keyfilter3.'/', $val['fullpath']) || preg_match('/'.$keyfilter4.'/', $val['fullpath']));
1158
1159
                if (($test && !$include) || (!$test && $include))
1160
                {
1161
                    unset($this->cats[$key]);
1162
                }
1163
            }
1164
        }
1165
1166
		dol_syslog(get_class($this)."::get_full_arbo dol_sort_array", LOG_DEBUG);
1167
		$this->cats = dol_sort_array($this->cats, 'fulllabel', 'asc', true, false);
1168
1169
		//$this->debug_cats();
1170
1171
		return $this->cats;
1172
	}
1173
1174
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1175
	/**
1176
	 *	For category id_categ and its childs available in this->cats, define property fullpath and fulllabel.
1177
	 *  It is called by get_full_arbo()
1178
	 *  This function is a memory scan only from $this->cats and $this->motherof, no database access must be done here.
1179
	 *
1180
	 * 	@param		int		$id_categ		id_categ entry to update
1181
	 * 	@param		int		$protection		Deep counter to avoid infinite loop
1182
	 *	@return		void
1183
	 *  @see get_full_arbo()
1184
	 */
1185
    public function build_path_from_id_categ($id_categ, $protection = 1000)
1186
    {
1187
        // phpcs:enable
1188
        dol_syslog(get_class($this)."::build_path_from_id_categ id_categ=".$id_categ." protection=".$protection, LOG_DEBUG);
1189
1190
		if (!empty($this->cats[$id_categ]['fullpath']))
1191
		{
1192
			// Already defined
1193
			dol_syslog(get_class($this)."::build_path_from_id_categ fullpath and fulllabel already defined", LOG_WARNING);
1194
			return;
1195
		}
1196
1197
		// First build full array $motherof
1198
		//$this->load_motherof();	// Disabled because already done by caller of build_path_from_id_categ
1199
1200
		// Define fullpath and fulllabel
1201
		$this->cats[$id_categ]['fullpath'] = '_'.$id_categ;
1202
		$this->cats[$id_categ]['fulllabel'] = $this->cats[$id_categ]['label'];
1203
		$i = 0; $cursor_categ = $id_categ;
1204
		//print 'Work for id_categ='.$id_categ.'<br>'."\n";
1205
		while ((empty($protection) || $i < $protection) && !empty($this->motherof[$cursor_categ]))
1206
		{
1207
			//print '&nbsp; cursor_categ='.$cursor_categ.' i='.$i.' '.$this->motherof[$cursor_categ].'<br>'."\n";
1208
			$this->cats[$id_categ]['fullpath'] = '_'.$this->motherof[$cursor_categ].$this->cats[$id_categ]['fullpath'];
1209
			$this->cats[$id_categ]['fulllabel'] = $this->cats[$this->motherof[$cursor_categ]]['label'].' >> '.$this->cats[$id_categ]['fulllabel'];
1210
			//print '&nbsp; Result for id_categ='.$id_categ.' : '.$this->cats[$id_categ]['fullpath'].' '.$this->cats[$id_categ]['fulllabel'].'<br>'."\n";
1211
			$i++; $cursor_categ = $this->motherof[$cursor_categ];
1212
		}
1213
		//print 'Result for id_categ='.$id_categ.' : '.$this->cats[$id_categ]['fullpath'].'<br>'."\n";
1214
1215
		// We count number of _ to have level
1216
		$this->cats[$id_categ]['level'] = dol_strlen(preg_replace('/[^_]/i', '', $this->cats[$id_categ]['fullpath']));
1217
1218
        return;
1219
    }
1220
1221
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1222
	/**
1223
	 *	Display content of $this->cats
1224
	 *
1225
	 *	@return	void
1226
	 */
1227
	public function debug_cats()
1228
	{
1229
        // phpcs:enable
1230
		// Display $this->cats
1231
		foreach ($this->cats as $key => $val)
1232
		{
1233
			print 'id: '.$this->cats[$key]['id'];
1234
			print ' label: '.$this->cats[$key]['label'];
1235
			print ' mother: '.$this->cats[$key]['fk_parent'];
1236
			//print ' children: '.(is_array($this->cats[$key]['id_children'])?join(',',$this->cats[$key]['id_children']):'');
1237
			print ' fullpath: '.$this->cats[$key]['fullpath'];
1238
			print ' fulllabel: '.$this->cats[$key]['fulllabel'];
1239
			print "<br>\n";
1240
		}
1241
	}
1242
1243
1244
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1245
	/**
1246
	 * 	Returns all categories
1247
	 *
1248
	 *	@param	int			$type		Type of category (0, 1, ...)
1249
	 *	@param	boolean		$parent		Just parent categories if true
1250
	 *	@return	array|int				Table of Object Category, -1 on error
1251
	 */
1252
	public function get_all_categories($type = null, $parent = false)
1253
	{
1254
        // phpcs:enable
1255
		if (!is_numeric($type)) $type = $this->MAP_ID[$type];
1256
1257
		$sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."categorie";
1258
		$sql .= " WHERE entity IN (".getEntity('category').")";
1259
		if (!is_null($type))
1260
			$sql .= " AND type = ".$type;
1261
		if ($parent)
1262
			$sql .= " AND fk_parent = 0";
1263
1264
		$res = $this->db->query($sql);
1265
		if ($res)
1266
		{
1267
			$cats = array();
1268
			while ($rec = $this->db->fetch_array($res))
1269
			{
1270
				$cat = new Categorie($this->db);
1271
				$cat->fetch($rec['rowid']);
1272
				$cats[$rec['rowid']] = $cat;
1273
			}
1274
			return $cats;
1275
		} else {
1276
			dol_print_error($this->db);
1277
			return -1;
1278
		}
1279
	}
1280
1281
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1282
	/**
1283
	 *	Returns the top level categories (which are not child)
1284
	 *
1285
	 *	@param		int		$type		Type of category (0, 1, ...)
1286
	 *	@return		array
1287
	 */
1288
	public function get_main_categories($type = null)
1289
	{
1290
	    // phpcs:enable
1291
	    return $this->get_all_categories($type, true);
1292
	}
1293
1294
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1295
	/**
1296
	 * 	Check if no category with same label already exists for this cat's parent or root and for this cat's type
1297
	 *
1298
	 * 	@return		integer		1 if already exist, 0 otherwise, -1 if error
1299
	 */
1300
	public function already_exists()
1301
	{
1302
        // phpcs:enable
1303
		$type = $this->type;
1304
1305
		if (!is_numeric($type)) $type = $this->MAP_ID[$type];
1306
1307
		/* We have to select any rowid from llx_categorie which category's mother and label
1308
		 * are equals to those of the calling category
1309
		 */
1310
		$sql = "SELECT c.rowid";
1311
		$sql .= " FROM ".MAIN_DB_PREFIX."categorie as c ";
1312
		$sql .= " WHERE c.entity IN (".getEntity('category').")";
1313
		$sql .= " AND c.type = ".$type;
1314
		$sql .= " AND c.fk_parent = ".$this->fk_parent;
1315
		$sql .= " AND c.label = '".$this->db->escape($this->label)."'";
1316
1317
		dol_syslog(get_class($this)."::already_exists", LOG_DEBUG);
1318
		$resql = $this->db->query($sql);
1319
		if ($resql)
1320
		{
1321
			if ($this->db->num_rows($resql) > 0)						// Checking for empty resql
1322
			{
1323
				$obj = $this->db->fetch_array($resql);
1324
				/* If object called create, obj cannot have is id.
1325
				 * If object called update, he mustn't have the same label as an other category for this mother.
1326
				 * So if the result have the same id, update is not for label, and if result have an other one,
1327
				 * update may be for label.
1328
				 */
1329
				if ($obj[0] > 0 && $obj[0] != $this->id)
1330
				{
1331
					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);
1332
					return 1;
1333
				}
1334
			}
1335
			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);
1336
			return 0;
1337
		} else {
1338
			$this->error = $this->db->error();
1339
			return -1;
1340
		}
1341
	}
1342
1343
1344
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1345
	/**
1346
	 * Returns the path of the category, with the names of the categories
1347
	 * separated by $sep (" >> " by default)
1348
	 *
1349
	 * @param	string	$sep	     Separator
1350
	 * @param	string	$url	     Url ('', 'none' or 'urltouse')
1351
	 * @param   int     $nocolor     0
1352
	 * @param	string	$addpicto	 Add picto into link
1353
	 * @return	array
1354
	 */
1355
	public function print_all_ways($sep = ' &gt;&gt; ', $url = '', $nocolor = 0, $addpicto = 0)
1356
	{
1357
        // phpcs:enable
1358
		$ways = array();
1359
1360
		$allways = $this->get_all_ways(); // Load array of categories
1361
		foreach ($allways as $way)
1362
		{
1363
			$w = array();
1364
			$i = 0;
1365
			$forced_color = '';
1366
			foreach ($way as $cat)
1367
			{
1368
			    $i++;
1369
1370
			    if (empty($nocolor))
1371
			    {
1372
    			    $forced_color = 'toreplace';
1373
    			    if ($i == count($way))
1374
    			    {
1375
    			        // Check contrast with background and correct text color
1376
    			        $forced_color = 'categtextwhite';
1377
    			        if ($cat->color)
1378
    			        {
1379
    			            if (colorIsLight($cat->color)) $forced_color = 'categtextblack';
1380
    			        }
1381
    			    }
1382
			    }
1383
1384
				if ($url == '')
1385
				{
1386
			        $link = '<a href="'.DOL_URL_ROOT.'/categories/viewcat.php?id='.$cat->id.'&type='.$cat->type.'" class="'.$forced_color.'">';
1387
			        $linkend = '</a>';
1388
			        $w[] = $link.($addpicto ? img_object('', 'category', 'class="paddingright"') : '').$cat->label.$linkend;
1389
				} elseif ($url == 'none') {
1390
					$link = '';
1391
					$linkend = '';
1392
					$w[] = $link.($addpicto ? img_object('', 'category', 'class="paddingright"') : '').$cat->label.$linkend;
1393
				} else {
1394
					$w[] = "<a href='".DOL_URL_ROOT."/".$url."?catid=".$cat->id."'>".($addpicto ? img_object('', 'category') : '').$cat->label."</a>";
1395
				}
1396
			}
1397
			$newcategwithpath = preg_replace('/toreplace/', $forced_color, implode($sep, $w));
1398
1399
			$ways[] = $newcategwithpath;
1400
		}
1401
1402
		return $ways;
1403
	}
1404
1405
1406
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1407
	/**
1408
	 *	Returns an array containing the list of parent categories
1409
	 *
1410
	 *	@return	int|array <0 KO, array OK
1411
	 */
1412
	public function get_meres()
1413
	{
1414
        // phpcs:enable
1415
		$parents = array();
1416
1417
		$sql = "SELECT fk_parent FROM ".MAIN_DB_PREFIX."categorie";
1418
		$sql .= " WHERE rowid = ".$this->id;
1419
1420
		$res = $this->db->query($sql);
1421
1422
		if ($res)
1423
		{
1424
			while ($rec = $this->db->fetch_array($res))
1425
			{
1426
				if ($rec['fk_parent'] > 0)
1427
				{
1428
					$cat = new Categorie($this->db);
1429
					$cat->fetch($rec['fk_parent']);
1430
					$parents[] = $cat;
1431
				}
1432
			}
1433
			return $parents;
1434
		} else {
1435
			dol_print_error($this->db);
1436
			return -1;
1437
		}
1438
	}
1439
1440
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1441
	/**
1442
	 * 	Returns in a table all possible paths to get to the category
1443
	 * 	starting with the major categories represented by Tables of categories
1444
	 *
1445
	 *	@return	array
1446
	 */
1447
	public function get_all_ways()
1448
	{
1449
        // phpcs:enable
1450
		$ways = array();
1451
1452
		$parents = $this->get_meres();
1453
		if (!empty($parents))
1454
		{
1455
			foreach ($parents as $parent)
0 ignored issues
show
Bug introduced by
The expression $parents of type integer is not traversable.
Loading history...
1456
			{
1457
				$allways = $parent->get_all_ways();
1458
				foreach ($allways as $way)
1459
				{
1460
					$w = $way;
1461
					$w[] = $this;
1462
					$ways[] = $w;
1463
				}
1464
			}
1465
		}
1466
1467
		if (count($ways) == 0)
1468
			$ways[0][0] = $this;
1469
1470
		return $ways;
1471
	}
1472
1473
	/**
1474
	 * Return list of categories (object instances or labels) linked to element of id $id and type $type
1475
	 * Should be named getListOfCategForObject
1476
	 *
1477
	 * @param   int    		$id     Id of element
1478
	 * @param   string|int	$type   Type of category ('customer', 'supplier', 'contact', 'product', 'member') or (0, 1, 2, ...)
1479
	 * @param   string 		$mode   'id'=Get array of category ids, 'object'=Get array of fetched category instances, 'label'=Get array of category
1480
	 *                      	    labels, 'id'= Get array of category IDs
1481
	 * @return  Categorie[]|int     Array of category objects or < 0 if KO
1482
	 */
1483
	public function containing($id, $type, $mode = 'object')
1484
	{
1485
		$cats = array();
1486
1487
		if (is_numeric($type)) $type = Categorie::$MAP_ID_TO_CODE[$type];
1488
1489
		if ($type === Categorie::TYPE_BANK_LINE)   // TODO Remove this with standard category code
1490
		{
1491
		    // Load bank groups
1492
		    $sql = "SELECT c.label, c.rowid";
1493
		    $sql .= " FROM ".MAIN_DB_PREFIX."bank_class as a, ".MAIN_DB_PREFIX."bank_categ as c";
1494
		    $sql .= " WHERE a.lineid=".$id." AND a.fk_categ = c.rowid";
1495
		    $sql .= " ORDER BY c.label";
1496
1497
		    $res = $this->db->query($sql);
1498
		    if ($res)
1499
		    {
1500
		        while ($obj = $this->db->fetch_object($res))
1501
		        {
1502
    				if ($mode == 'id') {
1503
    				    $cats[] = $obj->rowid;
1504
    				} elseif ($mode == 'label') {
1505
    				    $cats[] = $obj->label;
1506
    				} else {
1507
    				    $cat = new Categorie($this->db);
1508
    				    $cat->id = $obj->rowid;
1509
    				    $cat->label = $obj->label;
1510
    				    $cats[] = $cat;
1511
    				}
1512
		        }
1513
		    } else {
1514
		        dol_print_error($this->db);
1515
		        return -1;
1516
		    }
1517
		} else {
1518
    		$sql = "SELECT ct.fk_categorie, c.label, c.rowid";
1519
    		$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";
1520
    		$sql .= " WHERE ct.fk_categorie = c.rowid AND ct.fk_".(empty($this->MAP_CAT_FK[$type]) ? $type : $this->MAP_CAT_FK[$type])." = ".(int) $id." AND c.type = ".$this->MAP_ID[$type];
1521
    		$sql .= " AND c.entity IN (".getEntity('category').")";
1522
1523
    		$res = $this->db->query($sql);
1524
    		if ($res)
1525
    		{
1526
    			while ($obj = $this->db->fetch_object($res))
1527
    			{
1528
    				if ($mode == 'id') {
1529
    					$cats[] = $obj->rowid;
1530
    				} elseif ($mode == 'label') {
1531
    					$cats[] = $obj->label;
1532
    				} else {
1533
    					$cat = new Categorie($this->db);
1534
    					$cat->fetch($obj->fk_categorie);
1535
    					$cats[] = $cat;
1536
    				}
1537
    			}
1538
    		} else {
1539
    			dol_print_error($this->db);
1540
    			return -1;
1541
    		}
1542
        }
1543
1544
        return $cats;
1545
	}
1546
1547
1548
	/**
1549
	 * 	Returns categories whose id or name match
1550
	 * 	add wildcards in the name unless $exact = true
1551
	 *
1552
	 * 	@param		int			$id			Id
1553
	 * 	@param		string		$nom		Name
1554
 	 * 	@param		string		$type		Type of category ('member', 'customer', 'supplier', 'product', 'contact'). Old mode (0, 1, 2, ...) is deprecated.
1555
	 * 	@param		boolean		$exact		Exact string search (true/false)
1556
	 * 	@param		boolean		$case		Case sensitive (true/false)
1557
	 * 	@return		Categorie[]|int			Array of Categorie, -1 if error
1558
	 */
1559
	public function rechercher($id, $nom, $type, $exact = false, $case = false)
1560
	{
1561
		// Deprecation warning
1562
		if (is_numeric($type)) {
1563
			dol_syslog(__METHOD__.': using numeric types is deprecated.', LOG_WARNING);
1564
		}
1565
1566
		$cats = array();
1567
1568
        // For backward compatibility
1569
        if (is_numeric($type)) {
1570
            // We want to reverse lookup
1571
            $map_type = array_flip($this->MAP_ID);
1572
            $type = $map_type[$type];
1573
            dol_syslog(get_class($this)."::rechercher(): numeric types are deprecated, please use string instead", LOG_WARNING);
1574
        }
1575
1576
        // Generation requete recherche
1577
		$sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."categorie";
1578
		$sql .= " WHERE type = ".$this->MAP_ID[$type];
1579
		$sql .= " AND entity IN (".getEntity('category').")";
1580
		if ($nom)
1581
		{
1582
			if (!$exact)
1583
				$nom = '%'.str_replace('*', '%', $nom).'%';
1584
			if (!$case)
1585
				$sql .= " AND label LIKE '".$this->db->escape($nom)."'";
1586
			else $sql .= " AND label LIKE BINARY '".$this->db->escape($nom)."'";
1587
		}
1588
		if ($id)
1589
		{
1590
			$sql .= " AND rowid = '".$id."'";
1591
		}
1592
1593
		$res = $this->db->query($sql);
1594
		if ($res)
1595
		{
1596
			while ($rec = $this->db->fetch_array($res))
1597
			{
1598
				$cat = new Categorie($this->db);
1599
				$cat->fetch($rec['rowid']);
1600
				$cats[] = $cat;
1601
			}
1602
1603
			return $cats;
1604
		} else {
1605
			$this->error = $this->db->error().' sql='.$sql;
1606
			return -1;
1607
		}
1608
	}
1609
1610
	/**
1611
	 *	Return name and link of category (with picto)
1612
	 *  Use ->id, ->ref, ->label, ->color
1613
	 *
1614
	 *	@param		int		$withpicto		0=No picto, 1=Include picto into link, 2=Only picto
1615
	 *	@param		string	$option			Sur quoi pointe le lien ('', 'xyz')
1616
	 * 	@param		int		$maxlength		Max length of text
1617
	 *	@return		string					Chaine avec URL
1618
	 */
1619
	public function getNomUrl($withpicto = 0, $option = '', $maxlength = 0)
1620
	{
1621
		global $langs;
1622
1623
		$result = '';
1624
		$label = $langs->trans("ShowCategory").': '.($this->ref ? $this->ref : $this->label);
1625
1626
		// Check contrast with background and correct text color
1627
		$forced_color = 'categtextwhite';
1628
		if ($this->color)
1629
		{
1630
			if (colorIsLight($this->color)) $forced_color = 'categtextblack';
1631
		}
1632
1633
		$link = '<a href="'.DOL_URL_ROOT.'/categories/viewcat.php?id='.$this->id.'&type='.$this->type.'&backtopage='.urlencode($_SERVER['PHP_SELF']).'" title="'.dol_escape_htmltag($label, 1).'" class="classfortooltip '.$forced_color.'">';
1634
		$linkend = '</a>';
1635
1636
		$picto = 'category';
1637
1638
1639
        if ($withpicto) $result .= ($link.img_object($label, $picto, 'class="classfortooltip"').$linkend);
1640
		if ($withpicto && $withpicto != 2) $result .= ' ';
1641
		if ($withpicto != 2) $result .= $link.dol_trunc(($this->ref ? $this->ref : $this->label), $maxlength).$linkend;
1642
		return $result;
1643
	}
1644
1645
1646
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1647
	/**
1648
	 *  Deplace fichier uploade sous le nom $files dans le repertoire sdir
1649
	 *
1650
	 *  @param      string	$sdir       Repertoire destination finale
1651
	 *  @param      string	$file		Nom du fichier uploade
1652
	 *	@return		void
1653
	 */
1654
	public function add_photo($sdir, $file)
1655
	{
1656
        // phpcs:enable
1657
		require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
1658
1659
		$dir = $sdir.'/'.get_exdir($this->id, 2, 0, 0, $this, 'category').$this->id."/";
1660
		$dir .= "photos/";
1661
1662
		if (!file_exists($dir))
1663
		{
1664
			dol_mkdir($dir);
1665
		}
1666
1667
		if (file_exists($dir)) {
1668
			if (is_array($file['name']) && count($file['name']) > 0)
1669
			{
1670
				$nbfile = count($file['name']);
1671
				for ($i = 0; $i <= $nbfile; $i++) {
1672
					$originImage = $dir.$file['name'][$i];
1673
1674
					// Cree fichier en taille origine
1675
					dol_move_uploaded_file($file['tmp_name'][$i], $originImage, 1, 0, 0);
1676
1677
					if (file_exists($originImage)) {
1678
						// Create thumbs
1679
						$this->addThumbs($originImage);
1680
					}
1681
				}
1682
			} else {
1683
				$originImage = $dir.$file['name'];
1684
1685
				// Cree fichier en taille origine
1686
				dol_move_uploaded_file($file['tmp_name'], $originImage, 1, 0, 0);
1687
1688
				if (file_exists($originImage)) {
1689
					// Create thumbs
1690
					$this->addThumbs($originImage);
1691
				}
1692
			}
1693
		}
1694
	}
1695
1696
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1697
	/**
1698
	 *    Return tableau de toutes les photos de la categorie
1699
	 *
1700
	 *    @param      string	$dir        Repertoire a scanner
1701
	 *    @param      int		$nbmax      Nombre maximum de photos (0=pas de max)
1702
	 *    @return     array       			Tableau de photos
1703
	 */
1704
	public function liste_photos($dir, $nbmax = 0)
1705
	{
1706
        // phpcs:enable
1707
		include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
1708
1709
		$nbphoto = 0;
1710
		$tabobj = array();
1711
1712
		$dirthumb = $dir.'thumbs/';
1713
1714
		if (file_exists($dir))
1715
		{
1716
			$handle = opendir($dir);
1717
            if (is_resource($handle))
1718
            {
1719
    			while (($file = readdir($handle)) !== false)
1720
    			{
1721
    				if (dol_is_file($dir.$file) && preg_match('/(\.jpeg|\.jpg|\.bmp|\.gif|\.png|\.tiff)$/i', $dir.$file))
1722
    				{
1723
    					$nbphoto++;
1724
    					$photo = $file;
1725
1726
    					// On determine nom du fichier vignette
1727
    					$photo_vignette = '';
1728
    					if (preg_match('/(\.jpeg|\.jpg|\.bmp|\.gif|\.png|\.tiff)$/i', $photo, $regs))
1729
    					{
1730
    						$photo_vignette = preg_replace('/'.$regs[0].'/i', '', $photo).'_small'.$regs[0];
1731
    					}
1732
1733
    					// Objet
1734
    					$obj = array();
1735
    					$obj['photo'] = $photo;
1736
    					if ($photo_vignette && is_file($dirthumb.$photo_vignette)) $obj['photo_vignette'] = 'thumbs/'.$photo_vignette;
1737
    					else $obj['photo_vignette'] = "";
1738
1739
    					$tabobj[$nbphoto - 1] = $obj;
1740
1741
    					// On continue ou on arrete de boucler
1742
    					if ($nbmax && $nbphoto >= $nbmax) break;
1743
    				}
1744
    			}
1745
1746
    			closedir($handle);
1747
            }
1748
		}
1749
1750
		return $tabobj;
1751
	}
1752
1753
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1754
	/**
1755
	 *    Efface la photo de la categorie et sa vignette
1756
	 *
1757
	 *    @param	string		$file		Path to file
1758
	 *    @return	void
1759
	 */
1760
	public function delete_photo($file)
1761
	{
1762
        // phpcs:enable
1763
        require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
1764
1765
	    $dir = dirname($file).'/'; // Chemin du dossier contenant l'image d'origine
1766
		$dirthumb = $dir.'/thumbs/'; // Chemin du dossier contenant la vignette
1767
		$filename = preg_replace('/'.preg_quote($dir, '/').'/i', '', $file); // Nom du fichier
1768
1769
		// On efface l'image d'origine
1770
		dol_delete_file($file, 1);
1771
1772
		// Si elle existe, on efface la vignette
1773
		if (preg_match('/(\.jpeg|\.jpg|\.bmp|\.gif|\.png|\.tiff)$/i', $filename, $regs))
1774
		{
1775
			$photo_vignette = preg_replace('/'.$regs[0].'/i', '', $filename).'_small'.$regs[0];
1776
			if (file_exists($dirthumb.$photo_vignette))
1777
			{
1778
				dol_delete_file($dirthumb.$photo_vignette, 1);
1779
			}
1780
		}
1781
	}
1782
1783
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1784
	/**
1785
	 *  Load size of image file
1786
	 *
1787
	 *  @param    	string	$file        Path to file
1788
	 *  @return		void
1789
	 */
1790
	public function get_image_size($file)
1791
	{
1792
        // phpcs:enable
1793
		$infoImg = getimagesize($file); // Recuperation des infos de l'image
1794
		$this->imgWidth = $infoImg[0]; // Largeur de l'image
1795
		$this->imgHeight = $infoImg[1]; // Hauteur de l'image
1796
	}
1797
1798
	/**
1799
	 *	Update ou cree les traductions des infos produits
1800
	 *
1801
	 *	@param	User	$user		Object user
1802
	 *
1803
	 *	@return		int		<0 if KO, >0 if OK
1804
	 */
1805
	public function setMultiLangs($user)
1806
	{
1807
	    global $langs;
1808
1809
	    $langs_available = $langs->get_available_languages();
1810
	    $current_lang = $langs->getDefaultLang();
1811
1812
	    foreach ($langs_available as $key => $value)
1813
	    {
1814
	        $sql = "SELECT rowid";
1815
	        $sql .= " FROM ".MAIN_DB_PREFIX."categorie_lang";
1816
	        $sql .= " WHERE fk_category=".$this->id;
1817
	        $sql .= " AND lang='".$key."'";
1818
1819
	        $result = $this->db->query($sql);
1820
1821
	        if ($key == $current_lang)
1822
	        {
1823
	            if ($this->db->num_rows($result)) // si aucune ligne dans la base
1824
	            {
1825
	                $sql2 = "UPDATE ".MAIN_DB_PREFIX."categorie_lang";
1826
	                $sql2 .= " SET label='".$this->db->escape($this->label)."',";
1827
	                $sql2 .= " description='".$this->db->escape($this->description)."'";
1828
	                $sql2 .= " WHERE fk_category=".$this->id." AND lang='".$this->db->escape($key)."'";
1829
	            } else {
1830
	                $sql2 = "INSERT INTO ".MAIN_DB_PREFIX."categorie_lang (fk_category, lang, label, description)";
1831
	                $sql2 .= " VALUES(".$this->id.",'".$key."','".$this->db->escape($this->label);
1832
	                $sql2 .= "','".$this->db->escape($this->multilangs["$key"]["description"])."')";
1833
	            }
1834
	            dol_syslog(get_class($this).'::setMultiLangs', LOG_DEBUG);
1835
	            if (!$this->db->query($sql2))
1836
	            {
1837
	                $this->error = $this->db->lasterror();
1838
	                return -1;
1839
	            }
1840
	        } elseif (isset($this->multilangs["$key"]))
1841
	        {
1842
	            if ($this->db->num_rows($result)) // si aucune ligne dans la base
1843
	            {
1844
	                $sql2 = "UPDATE ".MAIN_DB_PREFIX."categorie_lang";
1845
	                $sql2 .= " SET label='".$this->db->escape($this->multilangs["$key"]["label"])."',";
1846
	                $sql2 .= " description='".$this->db->escape($this->multilangs["$key"]["description"])."'";
1847
	                $sql2 .= " WHERE fk_category=".$this->id." AND lang='".$this->db->escape($key)."'";
1848
	            } else {
1849
	                $sql2 = "INSERT INTO ".MAIN_DB_PREFIX."categorie_lang (fk_category, lang, label, description)";
1850
	                $sql2 .= " VALUES(".$this->id.",'".$key."','".$this->db->escape($this->multilangs["$key"]["label"]);
1851
	                $sql2 .= "','".$this->db->escape($this->multilangs["$key"]["description"])."')";
1852
	            }
1853
1854
	            // on ne sauvegarde pas des champs vides
1855
	            if ($this->multilangs["$key"]["label"] || $this->multilangs["$key"]["description"] || $this->multilangs["$key"]["note"])
1856
	                dol_syslog(get_class($this).'::setMultiLangs', LOG_DEBUG);
1857
	            if (!$this->db->query($sql2))
1858
	            {
1859
	                $this->error = $this->db->lasterror();
1860
	                return -1;
1861
	            }
1862
	        }
1863
	    }
1864
1865
		// Call trigger
1866
		$result = $this->call_trigger('CATEGORY_SET_MULTILANGS', $user);
1867
		if ($result < 0) {
1868
			$this->error = $this->db->lasterror();
1869
			return -1;
1870
		}
1871
		// End call triggers
1872
1873
	    return 1;
1874
	}
1875
1876
	/**
1877
	 *	Load array this->multilangs
1878
	 *
1879
	 *	@return		int		<0 if KO, >0 if OK
1880
	 */
1881
	public function getMultiLangs()
1882
	{
1883
	    global $langs;
1884
1885
	    $current_lang = $langs->getDefaultLang();
1886
1887
	    $sql = "SELECT lang, label, description";
1888
	    $sql .= " FROM ".MAIN_DB_PREFIX."categorie_lang";
1889
	    $sql .= " WHERE fk_category=".$this->id;
1890
1891
	    $result = $this->db->query($sql);
1892
	    if ($result)
1893
	    {
1894
	        while ($obj = $this->db->fetch_object($result))
1895
	        {
1896
	            //print 'lang='.$obj->lang.' current='.$current_lang.'<br>';
1897
	            if ($obj->lang == $current_lang) // si on a les traduct. dans la langue courante on les charge en infos principales.
1898
	            {
1899
	                $this->label = $obj->label;
1900
	                $this->description = $obj->description;
1901
	            }
1902
	            $this->multilangs["$obj->lang"]["label"] = $obj->label;
1903
	            $this->multilangs["$obj->lang"]["description"] = $obj->description;
1904
	        }
1905
	        return 1;
1906
	    } else {
1907
	        $this->error = $langs->trans("Error")." : ".$this->db->error()." - ".$sql;
1908
	        return -1;
1909
	    }
1910
	}
1911
1912
	/**
1913
	 *	Return label of contact status
1914
	 *
1915
	 *	@param      int		$mode       0=Long label, 1=Short label, 2=Picto + Short label, 3=Picto, 4=Picto + Long label, 5=Short label + Picto, 6=Long label + Picto
1916
	 * 	@return 	string				Label of contact status
1917
	 */
1918
	public function getLibStatut($mode)
1919
	{
1920
	    return '';
1921
	}
1922
1923
1924
    /**
1925
     *  Initialise an instance with random values.
1926
     *  Used to build previews or test instances.
1927
     *	id must be 0 if object instance is a specimen.
1928
     *
1929
     *  @return	void
1930
     */
1931
    public function initAsSpecimen()
1932
    {
1933
        dol_syslog(get_class($this)."::initAsSpecimen");
1934
1935
        // Initialise parametres
1936
        $this->id = 0;
1937
        $this->fk_parent = 0;
1938
        $this->label = 'SPECIMEN';
1939
        $this->specimen = 1;
1940
        $this->description = 'This is a description';
1941
        $this->socid = 1;
1942
        $this->type = self::TYPE_PRODUCT;
1943
    }
1944
1945
    /**
1946
     * Function used to replace a thirdparty id with another one.
1947
     *
1948
     * @param DoliDB $db Database handler
1949
     * @param int $origin_id Old thirdparty id
1950
     * @param int $dest_id New thirdparty id
1951
     * @return bool
1952
     */
1953
    public static function replaceThirdparty(DoliDB $db, $origin_id, $dest_id)
1954
    {
1955
        $tables = array(
1956
            'categorie_societe'
1957
        );
1958
1959
        return CommonObject::commonReplaceThirdparty($db, $origin_id, $dest_id, $tables, 1);
1960
    }
1961
1962
	/**
1963
	 * Return the addtional SQL JOIN query for filtering a list by a category
1964
	 *
1965
	 * @param string	$type			The category type (e.g Categorie::TYPE_WAREHOUSE)
1966
	 * @param string	$rowIdName		The name of the row id inside the whole sql query (e.g. "e.rowid")
1967
	 * @return string					A additional SQL JOIN query
1968
	 */
1969
	public static function getFilterJoinQuery($type, $rowIdName)
1970
	{
1971
		if ($type == 'bank_account') $type = 'account';
1972
1973
		return " LEFT JOIN ".MAIN_DB_PREFIX."categorie_".$type." as cp ON ".$rowIdName." = cp.fk_".$type;
1974
	}
1975
1976
	/**
1977
	 * Return the addtional SQL SELECT query for filtering a list by a category
1978
	 *
1979
	 * @param string	$type			The category type (e.g Categorie::TYPE_WAREHOUSE)
1980
	 * @param string	$rowIdName		The name of the row id inside the whole sql query (e.g. "e.rowid")
1981
	 * @param Array		$searchList		A list with the selected categories
1982
	 * @return string					A additional SQL SELECT query
1983
	 */
1984
	public static function getFilterSelectQuery($type, $rowIdName, $searchList)
1985
	{
1986
		if ($type == 'bank_account') $type = 'account';
1987
1988
		if (empty($searchList) && !is_array($searchList))
1989
		{
1990
			return "";
1991
		}
1992
1993
		foreach ($searchList as $searchCategory)
1994
		{
1995
			if (intval($searchCategory) == -2)
1996
			{
1997
				$searchCategorySqlList[] = " cp.fk_categorie IS NULL";
1998
			} elseif (intval($searchCategory) > 0)
1999
			{
2000
				$searchCategorySqlList[] = " ".$rowIdName
2001
										." IN (SELECT fk_".$type." FROM ".MAIN_DB_PREFIX."categorie_".$type
2002
										." WHERE fk_categorie = ".$searchCategory.")";
2003
			}
2004
		}
2005
2006
		if (!empty($searchCategorySqlList))
2007
		{
2008
			return " AND (".implode(' AND ', $searchCategorySqlList).")";
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $searchCategorySqlList seems to be defined by a foreach iteration on line 1993. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
2009
		} else {
2010
			return "";
2011
		}
2012
	}
2013
}
2014