Passed
Branch develop (30d2c8)
by
unknown
26:49
created

Setup::getListOfTowns()   B

Complexity

Conditions 10
Paths 76

Size

Total Lines 47
Code Lines 28

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
cc 10
eloc 28
c 1
b 1
f 0
nc 76
nop 8
dl 0
loc 47
rs 7.6666

How to fix   Complexity    Many Parameters   

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:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
/* Copyright (C) 2016   Xebax Christy           <[email protected]>
3
 * Copyright (C) 2016	Laurent Destailleur		<[email protected]>
4
 * Copyright (C) 2017	Regis Houssin	        <[email protected]>
5
 * Copyright (C) 2017	Neil Orley	            <[email protected]>
6
 * Copyright (C) 2018-2020   Frédéric France         <[email protected]>
7
 * Copyright (C) 2018-2020   Thibault FOUCART        <[email protected]>
8
 *
9
 *
10
 * This program is free software; you can redistribute it and/or modify
11
 * it under the terms of the GNU General Public License as published by
12
 * the Free Software Foundation; either version 3 of the License, or
13
 * (at your option) any later version.
14
 *
15
 * This program is distributed in the hope that it will be useful,
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
 * GNU General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU General Public License
21
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
22
 */
23
24
use Luracast\Restler\RestException;
25
26
require_once DOL_DOCUMENT_ROOT.'/main.inc.php';
27
require_once DOL_DOCUMENT_ROOT.'/core/class/cstate.class.php';
28
require_once DOL_DOCUMENT_ROOT.'/core/class/ccountry.class.php';
29
30
31
/**
32
 * API class for dictionaries
33
 *
34
 * @access protected
35
 * @class DolibarrApiAccess {@requires user,external}
36
 */
37
class Setup extends DolibarrApi
38
{
39
	private $translations = null;
40
41
	/**
42
	 * Constructor
43
	 */
44
	public function __construct()
45
	{
46
		global $db;
47
		$this->db = $db;
48
	}
49
50
	/**
51
	 * Get the list of ordering methods.
52
	 *
53
	 * @param string    $sortfield  Sort field
54
	 * @param string    $sortorder  Sort order
55
	 * @param int       $limit      Number of items per page
56
	 * @param int       $page       Page number {@min 0}
57
	 * @param int       $active     Payment type is active or not {@min 0} {@max 1}
58
	 * @param string    $sqlfilters SQL criteria to filter with. Syntax example "(t.code:=:'OrderByWWW')"
59
	 *
60
	 * @url     GET dictionary/ordering_methods
61
	 *
62
	 * @return array [List of ordering methods]
63
	 *
64
	 * @throws RestException 400
65
	 */
66
	public function getOrderingMethods($sortfield = "code", $sortorder = 'ASC', $limit = 100, $page = 0, $active = 1, $sqlfilters = '')
67
	{
68
		$list = array();
69
70
		if (!DolibarrApiAccess::$user->rights->commande->lire) {
71
			throw new RestException(401);
72
		}
73
74
		$sql = "SELECT rowid, code, libelle as label, module";
75
		$sql .= " FROM ".MAIN_DB_PREFIX."c_input_method as t";
76
		$sql .= " WHERE t.active = ".$active;
77
		// Add sql filters
78
		if ($sqlfilters) {
79
			if (!DolibarrApi::_checkFilters($sqlfilters)) {
80
				throw new RestException(400, 'error when validating parameter sqlfilters '.$sqlfilters);
81
			}
82
			$regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^:\(\)]+)\)';
83
			$sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")";
84
		}
85
86
87
		$sql .= $this->db->order($sortfield, $sortorder);
88
89
		if ($limit) {
90
			if ($page < 0) {
91
				$page = 0;
92
			}
93
			$offset = $limit * $page;
94
95
			$sql .= $this->db->plimit($limit, $offset);
96
		}
97
98
		$result = $this->db->query($sql);
99
100
		if ($result) {
101
			$num = $this->db->num_rows($result);
102
			$min = min($num, ($limit <= 0 ? $num : $limit));
103
			for ($i = 0; $i < $min; $i++) {
104
				$list[] = $this->db->fetch_object($result);
105
			}
106
		} else {
107
			throw new RestException(400, $this->db->lasterror());
108
		}
109
110
		return $list;
111
	}
112
113
	/**
114
	 * Get the list of ordering origins.
115
	 *
116
	 * @param string    $sortfield  Sort field
117
	 * @param string    $sortorder  Sort order
118
	 * @param int       $limit      Number of items per page
119
	 * @param int       $page       Page number {@min 0}
120
	 * @param int       $active     Payment type is active or not {@min 0} {@max 1}
121
	 * @param string    $sqlfilters SQL criteria to filter with. Syntax example "(t.code:=:'OrderByWWW')"
122
	 *
123
	 * @url     GET dictionary/ordering_origins
124
	 *
125
	 * @return array [List of ordering reasons]
126
	 *
127
	 * @throws RestException 400
128
	 */
129
	public function getOrderingOrigins($sortfield = "code", $sortorder = 'ASC', $limit = 100, $page = 0, $active = 1, $sqlfilters = '')
130
	{
131
		$list = array();
132
133
		if (!DolibarrApiAccess::$user->rights->commande->lire) {
134
			throw new RestException(401);
135
		}
136
137
		$sql = "SELECT rowid, code, label, module";
138
		$sql .= " FROM ".MAIN_DB_PREFIX."c_input_reason as t";
139
		$sql .= " WHERE t.active = ".$active;
140
		// Add sql filters
141
		if ($sqlfilters) {
142
			if (!DolibarrApi::_checkFilters($sqlfilters)) {
143
				throw new RestException(400, 'error when validating parameter sqlfilters '.$sqlfilters);
144
			}
145
			$regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^:\(\)]+)\)';
146
			$sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")";
147
		}
148
149
150
		$sql .= $this->db->order($sortfield, $sortorder);
151
152
		if ($limit) {
153
			if ($page < 0) {
154
				$page = 0;
155
			}
156
			$offset = $limit * $page;
157
158
			$sql .= $this->db->plimit($limit, $offset);
159
		}
160
161
		$result = $this->db->query($sql);
162
163
		if ($result) {
164
			$num = $this->db->num_rows($result);
165
			$min = min($num, ($limit <= 0 ? $num : $limit));
166
			for ($i = 0; $i < $min; $i++) {
167
				$list[] = $this->db->fetch_object($result);
168
			}
169
		} else {
170
			throw new RestException(400, $this->db->lasterror());
171
		}
172
173
		return $list;
174
	}
175
176
	/**
177
	 * Get the list of payments types.
178
	 *
179
	 * @param string    $sortfield  Sort field
180
	 * @param string    $sortorder  Sort order
181
	 * @param int       $limit      Number of items per page
182
	 * @param int       $page       Page number {@min 0}
183
	 * @param int       $active     Payment type is active or not {@min 0} {@max 1}
184
	 * @param string    $sqlfilters SQL criteria to filter with. Syntax example "(t.code:=:'CHQ')"
185
	 *
186
	 * @url     GET dictionary/payment_types
187
	 *
188
	 * @return array [List of payment types]
189
	 *
190
	 * @throws RestException 400
191
	 */
192
	public function getPaymentTypes($sortfield = "code", $sortorder = 'ASC', $limit = 100, $page = 0, $active = 1, $sqlfilters = '')
193
	{
194
		$list = array();
195
196
		if (!DolibarrApiAccess::$user->rights->propal->lire && !DolibarrApiAccess::$user->rights->commande->lire && !DolibarrApiAccess::$user->rights->facture->lire) {
197
			throw new RestException(401);
198
		}
199
200
		$sql = "SELECT id, code, type, libelle as label, module";
201
		$sql .= " FROM ".MAIN_DB_PREFIX."c_paiement as t";
202
		$sql .= " WHERE t.entity IN (".getEntity('c_paiement').")";
203
		$sql .= " AND t.active = ".$active;
204
		// Add sql filters
205
		if ($sqlfilters) {
206
			if (!DolibarrApi::_checkFilters($sqlfilters)) {
207
				throw new RestException(400, 'error when validating parameter sqlfilters '.$sqlfilters);
208
			}
209
			  $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^:\(\)]+)\)';
210
			$sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")";
211
		}
212
213
214
		$sql .= $this->db->order($sortfield, $sortorder);
215
216
		if ($limit) {
217
			if ($page < 0) {
218
				$page = 0;
219
			}
220
			$offset = $limit * $page;
221
222
			$sql .= $this->db->plimit($limit, $offset);
223
		}
224
225
		$result = $this->db->query($sql);
226
227
		if ($result) {
228
			$num = $this->db->num_rows($result);
229
			$min = min($num, ($limit <= 0 ? $num : $limit));
230
			for ($i = 0; $i < $min; $i++) {
231
				$list[] = $this->db->fetch_object($result);
232
			}
233
		} else {
234
			throw new RestException(400, $this->db->lasterror());
235
		}
236
237
		return $list;
238
	}
239
240
	/**
241
	 * Get the list of states/provinces.
242
	 *
243
	 * The names of the states will be translated to the given language if
244
	 * the $lang parameter is provided. The value of $lang must be a language
245
	 * code supported by Dolibarr, for example 'en_US' or 'fr_FR'.
246
	 * The returned list is sorted by state ID.
247
	 *
248
	 * @param string    $sortfield  Sort field
249
	 * @param string    $sortorder  Sort order
250
	 * @param int       $limit      Number of items per page
251
	 * @param int       $page       Page number (starting from zero)
252
	 * @param string    $filter     To filter the countries by name
253
	 * @param string    $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.code:like:'A%') and (t.active:>=:0)"
254
	 * @return array                List of countries
255
	 *
256
	 * @url     GET dictionary/states
257
	 *
258
	 * @throws RestException
259
	 */
260
	public function getListOfStates($sortfield = "code_departement", $sortorder = 'ASC', $limit = 100, $page = 0, $filter = '', $sqlfilters = '')
261
	{
262
		$list = array();
263
264
		// Note: The filter is not applied in the SQL request because it must
265
		// be applied to the translated names, not to the names in database.
266
		$sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."c_departements as t";
267
		$sql .= " WHERE 1 = 1";
268
		// Add sql filters
269
		if ($sqlfilters) {
270
			if (!DolibarrApi::_checkFilters($sqlfilters)) {
271
				throw new RestException(503, 'Error when validating parameter sqlfilters '.$sqlfilters);
272
			}
273
			$regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^:\(\)]+)\)';
274
			$sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")";
275
		}
276
277
		$sql .= $this->db->order($sortfield, $sortorder);
278
279
		if ($limit) {
280
			if ($page < 0) {
281
				$page = 0;
282
			}
283
			$offset = $limit * $page;
284
285
			$sql .= $this->db->plimit($limit, $offset);
286
		}
287
288
		$result = $this->db->query($sql);
289
290
		if ($result) {
291
			$num = $this->db->num_rows($result);
292
			$min = min($num, ($limit <= 0 ? $num : $limit));
293
			for ($i = 0; $i < $min; $i++) {
294
				$obj = $this->db->fetch_object($result);
295
				$state = new Cstate($this->db);
296
				if ($state->fetch($obj->rowid) > 0) {
297
					if (empty($filter) || stripos($state->label, $filter) !== false) {
298
						$list[] = $this->_cleanObjectDatas($state);
299
					}
300
				}
301
			}
302
		} else {
303
			throw new RestException(503, 'Error when retrieving list of states');
304
		}
305
306
		return $list;
307
	}
308
309
	/**
310
	 * Get state by ID.
311
	 *
312
	 * @param int       $id        ID of state
313
	 * @return array 			   Array of cleaned object properties
314
	 *
315
	 * @url     GET dictionary/states/{id}
316
	 *
317
	 * @throws RestException
318
	 */
319
	public function getStateByID($id)
320
	{
321
		return $this->_fetchCstate($id, '');
322
	}
323
324
	/**
325
	 * Get state by Code.
326
	 *
327
	 * @param string    $code      Code of state
328
	 * @return array 			   Array of cleaned object properties
329
	 *
330
	 * @url     GET dictionary/states/byCode/{code}
331
	 *
332
	 * @throws RestException
333
	 */
334
	public function getStateByCode($code)
335
	{
336
		return $this->_fetchCstate('', $code);
337
	}
338
339
	/**
340
	 * Get the list of countries.
341
	 *
342
	 * The names of the countries will be translated to the given language if
343
	 * the $lang parameter is provided. The value of $lang must be a language
344
	 * code supported by Dolibarr, for example 'en_US' or 'fr_FR'.
345
	 * The returned list is sorted by country ID.
346
	 *
347
	 * @param string    $sortfield  Sort field
348
	 * @param string    $sortorder  Sort order
349
	 * @param int       $limit      Number of items per page
350
	 * @param int       $page       Page number (starting from zero)
351
	 * @param string    $filter     To filter the countries by name
352
	 * @param string    $lang       Code of the language the label of the countries must be translated to
353
	 * @param string    $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.code:like:'A%') and (t.active:>=:0)"
354
	 * @return array                List of countries
355
	 *
356
	 * @url     GET dictionary/countries
357
	 *
358
	 * @throws RestException
359
	 */
360
	public function getListOfCountries($sortfield = "code", $sortorder = 'ASC', $limit = 100, $page = 0, $filter = '', $lang = '', $sqlfilters = '')
361
	{
362
		$list = array();
363
364
		// Note: The filter is not applied in the SQL request because it must
365
		// be applied to the translated names, not to the names in database.
366
		$sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."c_country as t";
367
		$sql .= " WHERE 1 = 1";
368
		// Add sql filters
369
		if ($sqlfilters) {
370
			if (!DolibarrApi::_checkFilters($sqlfilters)) {
371
				throw new RestException(503, 'Error when validating parameter sqlfilters '.$sqlfilters);
372
			}
373
			$regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^:\(\)]+)\)';
374
			$sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")";
375
		}
376
377
		$sql .= $this->db->order($sortfield, $sortorder);
378
379
		if ($limit) {
380
			if ($page < 0) {
381
				$page = 0;
382
			}
383
			$offset = $limit * $page;
384
385
			$sql .= $this->db->plimit($limit, $offset);
386
		}
387
388
		$result = $this->db->query($sql);
389
390
		if ($result) {
391
			$num = $this->db->num_rows($result);
392
			$min = min($num, ($limit <= 0 ? $num : $limit));
393
			for ($i = 0; $i < $min; $i++) {
394
				$obj = $this->db->fetch_object($result);
395
				$country = new Ccountry($this->db);
396
				if ($country->fetch($obj->rowid) > 0) {
397
					// Translate the name of the country if needed
398
					// and then apply the filter if there is one.
399
					$this->translateLabel($country, $lang, 'Country');
400
401
					if (empty($filter) || stripos($country->label, $filter) !== false) {
402
						$list[] = $this->_cleanObjectDatas($country);
403
					}
404
				}
405
			}
406
		} else {
407
			throw new RestException(503, 'Error when retrieving list of countries');
408
		}
409
410
		return $list;
411
	}
412
413
	/**
414
	 * Get country by ID.
415
	 *
416
	 * @param int       $id        ID of country
417
	 * @param string    $lang      Code of the language the name of the
418
	 *                             country must be translated to
419
	 * @return array 			   Array of cleaned object properties
420
	 *
421
	 * @url     GET dictionary/countries/{id}
422
	 *
423
	 * @throws RestException
424
	 */
425
	public function getCountryByID($id, $lang = '')
426
	{
427
		return $this->_fetchCcountry($id, '', '', $lang);
428
	}
429
430
	/**
431
	 * Get country by Code.
432
	 *
433
	 * @param string    $code      Code of country (2 characters)
434
	 * @param string    $lang      Code of the language the name of the
435
	 *                             country must be translated to
436
	 * @return array 			   Array of cleaned object properties
437
	 *
438
	 * @url     GET dictionary/countries/byCode/{code}
439
	 *
440
	 * @throws RestException
441
	 */
442
	public function getCountryByCode($code, $lang = '')
443
	{
444
		return $this->_fetchCcountry('', $code, '', $lang);
445
	}
446
447
	/**
448
	 * Get country by Iso.
449
	 *
450
	 * @param string    $iso       ISO of country (3 characters)
451
	 * @param string    $lang      Code of the language the name of the
452
	 *                             country must be translated to
453
	 * @return array 			   Array of cleaned object properties
454
	 *
455
	 * @url     GET dictionary/countries/byISO/{iso}
456
	 *
457
	 * @throws RestException
458
	 */
459
	public function getCountryByISO($iso, $lang = '')
460
	{
461
		return $this->_fetchCcountry('', '', $iso, $lang);
462
	}
463
464
	/**
465
	 * Get state.
466
	 *
467
	 * @param int       $id        ID of state
468
	 * @param string    $code      Code of state
469
	 * @return array 			   Array of cleaned object properties
470
	 *
471
	 * @throws RestException
472
	 */
473
	private function _fetchCstate($id, $code = '')
474
	{
475
		$state = new Cstate($this->db);
476
477
		$result = $state->fetch($id, $code);
478
		if ($result < 0) {
479
			throw new RestException(503, 'Error when retrieving state : '.$state->error);
480
		} elseif ($result == 0) {
481
			throw new RestException(404, 'State not found');
482
		}
483
484
		return $this->_cleanObjectDatas($state);
485
	}
486
487
	/**
488
	 * Get country.
489
	 *
490
	 * @param int       $id        ID of country
491
	 * @param string    $code      Code of country (2 characters)
492
	 * @param string    $iso       ISO of country (3 characters)
493
	 * @param string    $lang      Code of the language the name of the
494
	 *                             country must be translated to
495
	 * @return array 			   Array of cleaned object properties
496
	 *
497
	 * @throws RestException
498
	 */
499
	private function _fetchCcountry($id, $code = '', $iso = '', $lang = '')
500
	{
501
		$country = new Ccountry($this->db);
502
503
		$result = $country->fetch($id, $code, $iso);
504
505
		if ($result < 0) {
506
			throw new RestException(503, 'Error when retrieving country : '.$country->error);
507
		} elseif ($result == 0) {
508
			throw new RestException(404, 'Country not found');
509
		}
510
511
		$this->translateLabel($country, $lang, 'Country');
512
513
		return $this->_cleanObjectDatas($country);
514
	}
515
516
	/**
517
	 * Get the list of delivery times.
518
	 *
519
	 * @param string    $sortfield  Sort field
520
	 * @param string    $sortorder  Sort order
521
	 * @param int       $limit      Number of items per page
522
	 * @param int       $page       Page number {@min 0}
523
	 * @param int       $active     Delivery times is active or not {@min 0} {@max 1}
524
	 * @param string    $sqlfilters SQL criteria to filter with.
525
	 *
526
	 * @url     GET dictionary/availability
527
	 *
528
	 * @return array [List of availability]
529
	 *
530
	 * @throws RestException 400
531
	 */
532
	public function getAvailability($sortfield = "code", $sortorder = 'ASC', $limit = 100, $page = 0, $active = 1, $sqlfilters = '')
533
	{
534
		$list = array();
535
536
		if (!DolibarrApiAccess::$user->rights->commande->lire) {
537
			throw new RestException(401);
538
		}
539
540
		$sql = "SELECT rowid, code, label";
541
		$sql .= " FROM ".MAIN_DB_PREFIX."c_availability as t";
542
		$sql .= " WHERE t.active = ".$active;
543
		// Add sql filters
544
		if ($sqlfilters) {
545
			if (!DolibarrApi::_checkFilters($sqlfilters)) {
546
				throw new RestException(400, 'error when validating parameter sqlfilters '.$sqlfilters);
547
			}
548
				  $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^:\(\)]+)\)';
549
			$sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")";
550
		}
551
552
553
		$sql .= $this->db->order($sortfield, $sortorder);
554
555
		if ($limit) {
556
			if ($page < 0) {
557
				$page = 0;
558
			}
559
			$offset = $limit * $page;
560
561
			$sql .= $this->db->plimit($limit, $offset);
562
		}
563
564
		$result = $this->db->query($sql);
565
566
		if ($result) {
567
			$num = $this->db->num_rows($result);
568
			$min = min($num, ($limit <= 0 ? $num : $limit));
569
			for ($i = 0; $i < $min; $i++) {
570
				$list[] = $this->db->fetch_object($result);
571
			}
572
		} else {
573
			throw new RestException(400, $this->db->lasterror());
574
		}
575
576
		return $list;
577
	}
578
579
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
580
	/**
581
	 * Clean sensible object datas
582
	 *
583
	 * @param Object    $object    Object to clean
584
	 * @return Object 				Object with cleaned properties
585
	 */
586
	protected function _cleanObjectDatas($object)
587
	{
588
		// phpcs:enable
589
		$object = parent::_cleanObjectDatas($object);
590
591
		unset($object->error);
592
		unset($object->errors);
593
594
		return $object;
595
	}
596
597
	/**
598
	 * Translate the name of the object to the given language.
599
	 *
600
	 * @param object   $object    Object with label to translate
601
	 * @param string   $lang      Code of the language the name of the object must be translated to
602
	 * @param string   $prefix 	  Prefix for translation key
603
	 *
604
	 * @return void
605
	 */
606
	private function translateLabel($object, $lang, $prefix = 'Country')
607
	{
608
		if (!empty($lang)) {
609
			// Load the translations if this is a new language.
610
			if ($this->translations == null || $this->translations->getDefaultLang() !== $lang) {
611
				global $conf;
612
				$this->translations = new Translate('', $conf);
613
				$this->translations->setDefaultLang($lang);
614
				$this->translations->load('dict');
615
			}
616
			if ($object->code) {
617
				$key = $prefix.$object->code;
618
619
				$translation = $this->translations->trans($key);
620
				if ($translation != $key) {
621
					$object->label = html_entity_decode($translation);
622
				}
623
			}
624
		}
625
	}
626
627
	/**
628
	 * Get the list of shipment methods.
629
	 *
630
	 * @param string    $sortfield  Sort field
631
	 * @param string    $sortorder  Sort order
632
	 * @param int       $limit      Number of items per page
633
	 * @param int       $page       Page number (starting from zero)
634
	 * @param int       $active     Payment term is active or not {@min 0} {@max 1}
635
	 * @param string    $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.code:like:'A%') and (t.active:>=:0)"
636
	 *
637
	 * @return array List of shipment methods
638
	 *
639
	 * @url     GET dictionary/shipment_methods
640
	 *
641
	 * @throws RestException
642
	 */
643
	public function getListOfShipmentMethods($sortfield = "rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $active = 1, $sqlfilters = '')
644
	{
645
		$list = array();
646
		$sql = "SELECT t.rowid, t.code, t.libelle, t.description, t.tracking";
647
		$sql .= " FROM ".MAIN_DB_PREFIX."c_shipment_mode as t";
648
		$sql .= " WHERE t.active = ".$active;
649
		// Add sql filters
650
		if ($sqlfilters) {
651
			if (!DolibarrApi::_checkFilters($sqlfilters)) {
652
				throw new RestException(503, 'Error when validating parameter sqlfilters '.$sqlfilters);
653
			}
654
			$regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^:\(\)]+)\)';
655
			$sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")";
656
		}
657
658
659
		$sql .= $this->db->order($sortfield, $sortorder);
660
661
		if ($limit) {
662
			if ($page < 0) {
663
				$page = 0;
664
			}
665
			$offset = $limit * $page;
666
667
			$sql .= $this->db->plimit($limit, $offset);
668
		}
669
670
		$result = $this->db->query($sql);
671
672
		if ($result) {
673
			$num = $this->db->num_rows($result);
674
			$min = min($num, ($limit <= 0 ? $num : $limit));
675
			for ($i = 0; $i < $min; $i++) {
676
				$list[] = $this->db->fetch_object($result);
677
			}
678
		} else {
679
			throw new RestException(503, 'Error when retrieving list of shipment methods : '.$this->db->lasterror());
680
		}
681
682
		return $list;
683
	}
684
685
	/**
686
	 * Get the list of events types.
687
	 *
688
	 * @param string    $sortfield  Sort field
689
	 * @param string    $sortorder  Sort order
690
	 * @param int       $limit      Number of items per page
691
	 * @param int       $page       Page number (starting from zero)
692
	 * @param string    $type       To filter on type of event
693
	 * @param string    $module     To filter on module events
694
	 * @param int       $active     Event's type is active or not {@min 0} {@max 1}
695
	 * @param string    $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.code:like:'A%') and (t.active:>=:0)"
696
	 * @return array				List of events types
697
	 *
698
	 * @url     GET dictionary/event_types
699
	 *
700
	 * @throws RestException
701
	 */
702
	public function getListOfEventTypes($sortfield = "code", $sortorder = 'ASC', $limit = 100, $page = 0, $type = '', $module = '', $active = 1, $sqlfilters = '')
703
	{
704
		$list = array();
705
706
		$sql = "SELECT id, code, type, libelle as label, module";
707
		$sql .= " FROM ".MAIN_DB_PREFIX."c_actioncomm as t";
708
		$sql .= " WHERE t.active = ".$active;
709
		if ($type) {
710
			$sql .= " AND t.type LIKE '%".$this->db->escape($type)."%'";
711
		}
712
		if ($module) {
713
			$sql .= " AND t.module LIKE '%".$this->db->escape($module)."%'";
714
		}
715
		// Add sql filters
716
		if ($sqlfilters) {
717
			if (!DolibarrApi::_checkFilters($sqlfilters)) {
718
				throw new RestException(503, 'Error when validating parameter sqlfilters '.$sqlfilters);
719
			}
720
			$regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^:\(\)]+)\)';
721
			$sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")";
722
		}
723
724
725
		$sql .= $this->db->order($sortfield, $sortorder);
726
727
		if ($limit) {
728
			if ($page < 0) {
729
				$page = 0;
730
			}
731
			$offset = $limit * $page;
732
733
			$sql .= $this->db->plimit($limit, $offset);
734
		}
735
736
		$result = $this->db->query($sql);
737
738
		if ($result) {
739
			$num = $this->db->num_rows($result);
740
			$min = min($num, ($limit <= 0 ? $num : $limit));
741
			for ($i = 0; $i < $min; $i++) {
742
				$list[] = $this->db->fetch_object($result);
743
			}
744
		} else {
745
			throw new RestException(503, 'Error when retrieving list of events types : '.$this->db->lasterror());
746
		}
747
748
		return $list;
749
	}
750
751
752
	/**
753
	 * Get the list of Expense Report types.
754
	 *
755
	 * @param string    $sortfield  Sort field
756
	 * @param string    $sortorder  Sort order
757
	 * @param int       $limit      Number of items per page
758
	 * @param int       $page       Page number (starting from zero)
759
	 * @param string    $module     To filter on module
760
	 * @param int       $active     Event's type is active or not {@min 0} {@max 1}
761
	 * @param string    $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.code:like:'A%') and (t.active:>=:0)"
762
	 * @return array				List of expense report types
763
	 *
764
	 * @url     GET dictionary/expensereport_types
765
	 *
766
	 * @throws RestException
767
	 */
768
	public function getListOfExpenseReportsTypes($sortfield = "code", $sortorder = 'ASC', $limit = 100, $page = 0, $module = '', $active = 1, $sqlfilters = '')
769
	{
770
		$list = array();
771
772
		$sql = "SELECT id, code, label, accountancy_code, active, module, position";
773
		$sql .= " FROM ".MAIN_DB_PREFIX."c_type_fees as t";
774
		$sql .= " WHERE t.active = ".$active;
775
		if ($module) {
776
			$sql .= " AND t.module LIKE '%".$this->db->escape($module)."%'";
777
		}
778
		// Add sql filters
779
		if ($sqlfilters) {
780
			if (!DolibarrApi::_checkFilters($sqlfilters)) {
781
				throw new RestException(503, 'Error when validating parameter sqlfilters '.$sqlfilters);
782
			}
783
			$regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^:\(\)]+)\)';
784
			$sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")";
785
		}
786
787
788
		$sql .= $this->db->order($sortfield, $sortorder);
789
790
		if ($limit) {
791
			if ($page < 0) {
792
				$page = 0;
793
			}
794
			$offset = $limit * $page;
795
796
			$sql .= $this->db->plimit($limit, $offset);
797
		}
798
799
		$result = $this->db->query($sql);
800
801
		if ($result) {
802
			$num = $this->db->num_rows($result);
803
			$min = min($num, ($limit <= 0 ? $num : $limit));
804
			for ($i = 0; $i < $min; $i++) {
805
				$list[] = $this->db->fetch_object($result);
806
			}
807
		} else {
808
			throw new RestException(503, 'Error when retrieving list of expense report types : '.$this->db->lasterror());
809
		}
810
811
		return $list;
812
	}
813
814
815
	/**
816
	 * Get the list of contacts types.
817
	 *
818
	 * @param string    $sortfield  Sort field
819
	 * @param string    $sortorder  Sort order
820
	 * @param int       $limit      Number of items per page
821
	 * @param int       $page       Page number (starting from zero)
822
	 * @param string    $type       To filter on type of contact
823
	 * @param string    $module     To filter on module contacts
824
	 * @param int       $active     Contact's type is active or not {@min 0} {@max 1}
825
	 * @param string    $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.code:like:'A%') and (t.active:>=:0)"
826
	 * @return array	  List of Contacts types
827
	 *
828
	 * @url     GET dictionary/contact_types
829
	 *
830
	 * @throws RestException
831
	 */
832
	public function getListOfContactTypes($sortfield = "code", $sortorder = 'ASC', $limit = 100, $page = 0, $type = '', $module = '', $active = 1, $sqlfilters = '')
833
	{
834
		$list = array();
835
836
		$sql = "SELECT rowid, code, element as type, libelle as label, source, module, position";
837
		$sql .= " FROM ".MAIN_DB_PREFIX."c_type_contact as t";
838
		$sql .= " WHERE t.active = ".$active;
839
		if ($type) {
840
			$sql .= " AND type LIKE '%".$this->db->escape($type)."%'";
841
		}
842
		if ($module) {
843
			$sql .= " AND t.module LIKE '%".$this->db->escape($module)."%'";
844
		}
845
		// Add sql filters
846
		if ($sqlfilters) {
847
			if (!DolibarrApi::_checkFilters($sqlfilters)) {
848
				throw new RestException(503, 'Error when validating parameter sqlfilters '.$sqlfilters);
849
			}
850
			$regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^:\(\)]+)\)';
851
			$sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")";
852
		}
853
854
855
		$sql .= $this->db->order($sortfield, $sortorder);
856
857
		if ($limit) {
858
			if ($page < 0) {
859
				$page = 0;
860
			}
861
			$offset = $limit * $page;
862
863
			$sql .= $this->db->plimit($limit, $offset);
864
		}
865
866
		$result = $this->db->query($sql);
867
868
		if ($result) {
869
			$num = $this->db->num_rows($result);
870
			$min = min($num, ($limit <= 0 ? $num : $limit));
871
			for ($i = 0; $i < $min; $i++) {
872
				$list[] = $this->db->fetch_object($result);
873
			}
874
		} else {
875
			throw new RestException(503, 'Error when retrieving list of contacts types : '.$this->db->lasterror());
876
		}
877
878
		return $list;
879
	}
880
881
	/**
882
	 * Get the list of civilities.
883
	 *
884
	 * @param string    $sortfield  Sort field
885
	 * @param string    $sortorder  Sort order
886
	 * @param int       $limit      Number of items per page
887
	 * @param int       $page       Page number (starting from zero)
888
	 * @param string    $module     To filter on module events
889
	 * @param int       $active     Civility is active or not {@min 0} {@max 1}
890
	 * @param string    $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.code:like:'A%') and (t.active:>=:0)"
891
	 * @return array		List of civility types
892
	 *
893
	 * @url     GET dictionary/civilities
894
	 *
895
	 * @throws RestException
896
	 */
897
	public function getListOfCivilities($sortfield = "code", $sortorder = 'ASC', $limit = 100, $page = 0, $module = '', $active = 1, $sqlfilters = '')
898
	{
899
		$list = array();
900
901
		$sql = "SELECT rowid, code, label, module";
902
		$sql .= " FROM ".MAIN_DB_PREFIX."c_civility as t";
903
		$sql .= " WHERE t.active = ".$active;
904
		if ($module) {
905
			$sql .= " AND t.module LIKE '%".$this->db->escape($module)."%'";
906
		}
907
		// Add sql filters
908
		if ($sqlfilters) {
909
			if (!DolibarrApi::_checkFilters($sqlfilters)) {
910
				throw new RestException(503, 'Error when validating parameter sqlfilters '.$sqlfilters);
911
			}
912
			$regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^:\(\)]+)\)';
913
			$sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")";
914
		}
915
916
917
		$sql .= $this->db->order($sortfield, $sortorder);
918
919
		if ($limit) {
920
			if ($page < 0) {
921
				$page = 0;
922
			}
923
			$offset = $limit * $page;
924
925
			$sql .= $this->db->plimit($limit, $offset);
926
		}
927
928
		$result = $this->db->query($sql);
929
930
		if ($result) {
931
			$num = $this->db->num_rows($result);
932
			$min = min($num, ($limit <= 0 ? $num : $limit));
933
			for ($i = 0; $i < $min; $i++) {
934
				$list[] = $this->db->fetch_object($result);
935
			}
936
		} else {
937
			throw new RestException(503, 'Error when retrieving list of civility : '.$this->db->lasterror());
938
		}
939
940
		return $list;
941
	}
942
943
	/**
944
	 * Get the list of currencies.
945
	 *
946
	 * @param int       $multicurrency  Multicurrency rates (0: no multicurrency, 1: last rate, 2: all rates) {@min 0} {@max 2}
947
	 * @param string    $sortfield  Sort field
948
	 * @param string    $sortorder  Sort order
949
	 * @param int       $limit      Number of items per page
950
	 * @param int       $page       Page number (starting from zero)
951
	 * @param int       $active     Payment term is active or not {@min 0} {@max 1}
952
	 * @param string    $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.code:like:'A%') and (t.active:>=:0)"
953
	 * @return array				List of currencies
954
	 *
955
	 * @url     GET dictionary/currencies
956
	 *
957
	 * @throws RestException
958
	 */
959
	public function getListOfCurrencies($multicurrency = 0, $sortfield = "code_iso", $sortorder = 'ASC', $limit = 100, $page = 0, $active = 1, $sqlfilters = '')
960
	{
961
		$list = array();
962
		$sql = "SELECT t.code_iso, t.label, t.unicode";
963
		if (!empty($multicurrency)) {
964
			$sql .= " , cr.date_sync, cr.rate ";
965
		}
966
		$sql .= " FROM ".MAIN_DB_PREFIX."c_currencies as t";
967
		if (!empty($multicurrency)) {
968
			$sql .= " JOIN ".MAIN_DB_PREFIX."multicurrency as m ON m.code=t.code_iso";
969
			$sql .= " JOIN ".MAIN_DB_PREFIX."multicurrency_rate as cr ON (m.rowid = cr.fk_multicurrency)";
970
		}
971
		$sql .= " WHERE t.active = ".$active;
972
		if (!empty($multicurrency)) {
973
			$sql .= " AND m.entity IN (".getEntity('multicurrency').")";
974
			if (!empty($multicurrency) && $multicurrency != 2) {
975
				$sql .= " AND cr.date_sync = (SELECT MAX(cr2.date_sync) FROM ".MAIN_DB_PREFIX."multicurrency_rate AS cr2 WHERE cr2.fk_multicurrency = m.rowid)";
976
			}
977
		}
978
979
		// Add sql filters
980
		if ($sqlfilters) {
981
			if (!DolibarrApi::_checkFilters($sqlfilters)) {
982
				throw new RestException(503, 'Error when validating parameter sqlfilters '.$sqlfilters);
983
			}
984
			$regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^:\(\)]+)\)';
985
			$sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")";
986
		}
987
988
989
		$sql .= $this->db->order($sortfield, $sortorder);
990
991
		if ($limit) {
992
			if ($page < 0) {
993
				$page = 0;
994
			}
995
			$offset = $limit * $page;
996
997
			$sql .= $this->db->plimit($limit, $offset);
998
		}
999
1000
		$result = $this->db->query($sql);
1001
1002
		if ($result) {
1003
			$num = $this->db->num_rows($result);
1004
			$min = min($num, ($limit <= 0 ? $num : $limit));
1005
			for ($i = 0; $i < $min; $i++) {
1006
				$list[] = $this->db->fetch_object($result);
1007
			}
1008
		} else {
1009
			throw new RestException(503, 'Error when retrieving list of currency : '.$this->db->lasterror());
1010
		}
1011
1012
		return $list;
1013
	}
1014
1015
	/**
1016
	 * Get the list of extra fields.
1017
	 *
1018
	 * @param string	$sortfield	Sort field
1019
	 * @param string	$sortorder	Sort order
1020
	 * @param string    $type       Type of element ('adherent', 'commande', 'thirdparty', 'facture', 'propal', 'product', ...)
1021
	 * @param string    $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.label:like:'SO-%')"
1022
	 * @return array				List of extra fields
1023
	 *
1024
	 * @url     GET extrafields
1025
	 *
1026
	 * @throws RestException
1027
	 */
1028
	public function getListOfExtrafields($sortfield = "t.pos", $sortorder = 'ASC', $type = '', $sqlfilters = '')
1029
	{
1030
		$list = array();
1031
1032
		if (!DolibarrApiAccess::$user->admin) {
1033
			throw new RestException(401, 'Only an admin user can get list of extrafields');
1034
		}
1035
1036
		if ($type == 'thirdparty') {
1037
			$type = 'societe';
1038
		}
1039
		if ($type == 'contact') {
1040
			$type = 'socpeople';
1041
		}
1042
1043
		$sql = "SELECT t.rowid, t.name, t.label, t.type, t.size, t.elementtype, t.fieldunique, t.fieldrequired, t.param, t.pos, t.alwayseditable, t.perms, t.list, t.fielddefault, t.fieldcomputed";
1044
		$sql .= " FROM ".MAIN_DB_PREFIX."extrafields as t";
1045
		$sql .= " WHERE t.entity IN (".getEntity('extrafields').")";
1046
		if (!empty($type)) {
1047
			$sql .= " AND t.elementtype = '".$this->db->escape($type)."'";
1048
		}
1049
		// Add sql filters
1050
		if ($sqlfilters) {
1051
			if (!DolibarrApi::_checkFilters($sqlfilters)) {
1052
				throw new RestException(503, 'Error when validating parameter sqlfilters '.$sqlfilters);
1053
			}
1054
			$regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^:\(\)]+)\)';
1055
			$sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")";
1056
		}
1057
1058
		$sql .= $this->db->order($sortfield, $sortorder);
1059
1060
		$resql = $this->db->query($sql);
1061
		if ($resql) {
1062
			if ($this->db->num_rows($resql)) {
1063
				while ($tab = $this->db->fetch_object($resql)) {
1064
					// New usage
1065
					$list[$tab->elementtype][$tab->name]['type'] = $tab->type;
1066
					$list[$tab->elementtype][$tab->name]['label'] = $tab->label;
1067
					$list[$tab->elementtype][$tab->name]['size'] = $tab->size;
1068
					$list[$tab->elementtype][$tab->name]['elementtype'] = $tab->elementtype;
1069
					$list[$tab->elementtype][$tab->name]['default'] = $tab->fielddefault;
1070
					$list[$tab->elementtype][$tab->name]['computed'] = $tab->fieldcomputed;
1071
					$list[$tab->elementtype][$tab->name]['unique'] = $tab->fieldunique;
1072
					$list[$tab->elementtype][$tab->name]['required'] = $tab->fieldrequired;
1073
					$list[$tab->elementtype][$tab->name]['param'] = ($tab->param ? unserialize($tab->param) : '');
1074
					$list[$tab->elementtype][$tab->name]['pos'] = $tab->pos;
1075
					$list[$tab->elementtype][$tab->name]['alwayseditable'] = $tab->alwayseditable;
1076
					$list[$tab->elementtype][$tab->name]['perms'] = $tab->perms;
1077
					$list[$tab->elementtype][$tab->name]['list'] = $tab->list;
1078
				}
1079
			}
1080
		} else {
1081
			throw new RestException(503, 'Error when retrieving list of extra fields : '.$this->db->lasterror());
1082
		}
1083
1084
		if (!count($list)) {
1085
			throw new RestException(404, 'No extrafield found');
1086
		}
1087
1088
		return $list;
1089
	}
1090
1091
1092
	/**
1093
	 * Get the list of towns.
1094
	 *
1095
	 * @param string    $sortfield  Sort field
1096
	 * @param string    $sortorder  Sort order
1097
	 * @param int       $limit      Number of items per page
1098
	 * @param int       $page       Page number (starting from zero)
1099
	 * @param string    $zipcode    To filter on zipcode
1100
	 * @param string    $town       To filter on city name
1101
	 * @param int       $active     Payment term is active or not {@min 0} {@max 1}
1102
	 * @param string    $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.code:like:'A%') and (t.active:>=:0)"
1103
	 * @return array				List of towns
1104
	 *
1105
	 * @url     GET dictionary/towns
1106
	 *
1107
	 * @throws RestException
1108
	 */
1109
	public function getListOfTowns($sortfield = "zip,town", $sortorder = 'ASC', $limit = 100, $page = 0, $zipcode = '', $town = '', $active = 1, $sqlfilters = '')
1110
	{
1111
		$list = array();
1112
1113
		$sql = "SELECT rowid AS id, zip, town, fk_county, fk_pays AS fk_country";
1114
		$sql .= " FROM ".MAIN_DB_PREFIX."c_ziptown as t";
1115
		$sql .= " AND t.active = ".$active;
1116
		if ($zipcode) {
1117
			$sql .= " AND t.zip LIKE '%".$this->db->escape($zipcode)."%'";
1118
		}
1119
		if ($town) {
1120
			$sql .= " AND t.town LIKE '%".$this->db->escape($town)."%'";
1121
		}
1122
		// Add sql filters
1123
		if ($sqlfilters) {
1124
			if (!DolibarrApi::_checkFilters($sqlfilters)) {
1125
				throw new RestException(503, 'Error when validating parameter sqlfilters '.$sqlfilters);
1126
			}
1127
			$regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^:\(\)]+)\)';
1128
			$sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")";
1129
		}
1130
1131
1132
		$sql .= $this->db->order($sortfield, $sortorder);
1133
1134
		if ($limit) {
1135
			if ($page < 0) {
1136
				$page = 0;
1137
			}
1138
			$offset = $limit * $page;
1139
1140
			$sql .= $this->db->plimit($limit, $offset);
1141
		}
1142
1143
		$result = $this->db->query($sql);
1144
1145
		if ($result) {
1146
			$num = $this->db->num_rows($result);
1147
			$min = min($num, ($limit <= 0 ? $num : $limit));
1148
			for ($i = 0; $i < $min; $i++) {
1149
				$list[] = $this->db->fetch_object($result);
1150
			}
1151
		} else {
1152
			throw new RestException(503, 'Error when retrieving list of towns : '.$this->db->lasterror());
1153
		}
1154
1155
		return $list;
1156
	}
1157
1158
	/**
1159
	 * Get the list of payments terms.
1160
	 *
1161
	 * @param string    $sortfield  Sort field
1162
	 * @param string    $sortorder  Sort order
1163
	 * @param int       $limit      Number of items per page
1164
	 * @param int       $page       Page number {@min 0}
1165
	 * @param int       $active     Payment term is active or not {@min 0} {@max 1}
1166
	 * @param string    $sqlfilters SQL criteria to filter. Syntax example "(t.code:=:'CHQ')"
1167
	 *
1168
	 * @url     GET dictionary/payment_terms
1169
	 *
1170
	 * @return array List of payment terms
1171
	 *
1172
	 * @throws RestException 400
1173
	 */
1174
	public function getPaymentTerms($sortfield = "sortorder", $sortorder = 'ASC', $limit = 100, $page = 0, $active = 1, $sqlfilters = '')
1175
	{
1176
		$list = array();
1177
1178
		if (!DolibarrApiAccess::$user->rights->propal->lire && !DolibarrApiAccess::$user->rights->commande->lire && !DolibarrApiAccess::$user->rights->facture->lire) {
1179
			throw new RestException(401);
1180
		}
1181
1182
		$sql = "SELECT rowid as id, code, sortorder, libelle as label, libelle_facture as descr, type_cdr, nbjour, decalage, module";
1183
		$sql .= " FROM ".MAIN_DB_PREFIX."c_payment_term as t";
1184
		$sql .= " WHERE t.entity IN (".getEntity('c_payment_term').")";
1185
		$sql .= " AND t.active = ".$active;
1186
		// Add sql filters
1187
		if ($sqlfilters) {
1188
			if (!DolibarrApi::_checkFilters($sqlfilters)) {
1189
				throw new RestException(400, 'Error when validating parameter sqlfilters '.$sqlfilters);
1190
			}
1191
				$regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^:\(\)]+)\)';
1192
			$sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")";
1193
		}
1194
1195
1196
		$sql .= $this->db->order($sortfield, $sortorder);
1197
1198
		if ($limit) {
1199
			if ($page < 0) {
1200
				$page = 0;
1201
			}
1202
			$offset = $limit * $page;
1203
1204
			$sql .= $this->db->plimit($limit, $offset);
1205
		}
1206
1207
		$result = $this->db->query($sql);
1208
1209
		if ($result) {
1210
			$num = $this->db->num_rows($result);
1211
			$min = min($num, ($limit <= 0 ? $num : $limit));
1212
			for ($i = 0; $i < $min; $i++) {
1213
				$list[] = $this->db->fetch_object($result);
1214
			}
1215
		} else {
1216
			throw new RestException(400, $this->db->lasterror());
1217
		}
1218
1219
		return $list;
1220
	}
1221
1222
	/**
1223
	 * Get the list of shipping methods.
1224
	 *
1225
	 * @param int       $limit      Number of items per page
1226
	 * @param int       $page       Page number {@min 0}
1227
	 * @param int       $active     Shipping methodsm is active or not {@min 0} {@max 1}
1228
	 * @param string    $sqlfilters SQL criteria to filter. Syntax example "(t.code:=:'CHQ')"
1229
	 *
1230
	 * @url     GET dictionary/shipping_methods
1231
	 *
1232
	 * @return array List of shipping methods
1233
	 *
1234
	 * @throws RestException 400
1235
	 */
1236
	public function getShippingModes($limit = 100, $page = 0, $active = 1, $sqlfilters = '')
1237
	{
1238
		$list = array();
1239
1240
		$sql = "SELECT rowid as id, code, libelle as label, description, tracking, module";
1241
		$sql .= " FROM ".MAIN_DB_PREFIX."c_shipment_mode as t";
1242
		$sql .= " WHERE t.entity IN (".getEntity('c_shipment_mode').")";
1243
		$sql .= " AND t.active = ".$active;
1244
		// Add sql filters
1245
		if ($sqlfilters) {
1246
			if (!DolibarrApi::_checkFilters($sqlfilters)) {
1247
				throw new RestException(400, 'Error when validating parameter sqlfilters '.$sqlfilters);
1248
			}
1249
				$regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^:\(\)]+)\)';
1250
			$sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")";
1251
		}
1252
1253
1254
		//$sql.= $this->db->order($sortfield, $sortorder);
1255
1256
		if ($limit) {
1257
			if ($page < 0) {
1258
				$page = 0;
1259
			}
1260
			$offset = $limit * $page;
1261
1262
			$sql .= $this->db->plimit($limit, $offset);
1263
		}
1264
1265
		$result = $this->db->query($sql);
1266
1267
		if ($result) {
1268
			$num = $this->db->num_rows($result);
1269
			$min = min($num, ($limit <= 0 ? $num : $limit));
1270
			for ($i = 0; $i < $min; $i++) {
1271
				$list[] = $this->db->fetch_object($result);
1272
			}
1273
		} else {
1274
			throw new RestException(400, $this->db->lasterror());
1275
		}
1276
1277
		return $list;
1278
	}
1279
1280
	/**
1281
	 * Get the list of measuring units.
1282
	 *
1283
	 * @param string    $sortfield  Sort field
1284
	 * @param string    $sortorder  Sort order
1285
	 * @param int       $limit      Number of items per page
1286
	 * @param int       $page       Page number (starting from zero)
1287
	 * @param int       $active     Measuring unit is active or not {@min 0} {@max 1}
1288
	 * @param string    $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.code:like:'A%') and (t.active:>=:0)"
1289
	 * @return array				List of measuring unit
1290
	 *
1291
	 * @url     GET dictionary/units
1292
	 *
1293
	 * @throws RestException
1294
	 */
1295
	public function getListOfMeasuringUnits($sortfield = "rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $active = 1, $sqlfilters = '')
1296
	{
1297
		$list = array();
1298
1299
		//TODO link with multicurrency module
1300
		$sql = "SELECT t.rowid, t.code, t.label,t.short_label, t.active, t.scale, t.unit_type";
1301
		$sql .= " FROM ".MAIN_DB_PREFIX."c_units as t";
1302
		$sql .= " WHERE t.active = ".$active;
1303
		// Add sql filters
1304
		if ($sqlfilters) {
1305
			if (!DolibarrApi::_checkFilters($sqlfilters)) {
1306
				throw new RestException(503, 'Error when validating parameter sqlfilters '.$sqlfilters);
1307
			}
1308
			$regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^:\(\)]+)\)';
1309
			$sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")";
1310
		}
1311
1312
1313
		$sql .= $this->db->order($sortfield, $sortorder);
1314
1315
		if ($limit) {
1316
			if ($page < 0) {
1317
				$page = 0;
1318
			}
1319
			$offset = $limit * $page;
1320
1321
			$sql .= $this->db->plimit($limit, $offset);
1322
		}
1323
1324
		$result = $this->db->query($sql);
1325
1326
		if ($result) {
1327
			$num = $this->db->num_rows($result);
1328
			$min = min($num, ($limit <= 0 ? $num : $limit));
1329
			for ($i = 0; $i < $min; $i++) {
1330
				$list[] = $this->db->fetch_object($result);
1331
			}
1332
		} else {
1333
			throw new RestException(503, 'Error when retrieving list of measuring units: '.$this->db->lasterror());
1334
		}
1335
1336
		return $list;
1337
	}
1338
1339
	/**
1340
	 * Get the list of social networks.
1341
	 *
1342
	 * @param string    $sortfield  Sort field
1343
	 * @param string    $sortorder  Sort order
1344
	 * @param int       $limit      Number of items per page
1345
	 * @param int       $page       Page number (starting from zero)
1346
	 * @param int       $active     Social network is active or not {@min 0} {@max 1}
1347
	 * @param string    $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.code:like:'A%') and (t.active:>=:0)"
1348
	 * @return array				List of social networks
1349
	 *
1350
	 * @url     GET dictionary/socialnetworks
1351
	 *
1352
	 * @throws RestException
1353
	 */
1354
	public function getListOfsocialNetworks($sortfield = "rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $active = 1, $sqlfilters = '')
1355
	{
1356
		global $conf;
1357
1358
		if (empty($conf->socialnetworks->enabled)) {
1359
			throw new RestException(400, 'API not available: this dictionary is not enabled by setup');
1360
		}
1361
1362
		$list = array();
1363
		//TODO link with multicurrency module
1364
		$sql = "SELECT t.rowid, t.entity, t.code, t.label, t.url, t.icon, t.active";
1365
		$sql .= " FROM ".MAIN_DB_PREFIX."c_socialnetworks as t";
1366
		$sql .= " WHERE t.entity IN (".getEntity('c_socialnetworks').")";
1367
		$sql .= " AND t.active = ".$active;
1368
		// Add sql filters
1369
		if ($sqlfilters) {
1370
			if (!DolibarrApi::_checkFilters($sqlfilters)) {
1371
				throw new RestException(503, 'Error when validating parameter sqlfilters '.$sqlfilters);
1372
			}
1373
			$regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^:\(\)]+)\)';
1374
			$sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")";
1375
		}
1376
1377
1378
		$sql .= $this->db->order($sortfield, $sortorder);
1379
1380
		if ($limit) {
1381
			if ($page < 0) {
1382
				$page = 0;
1383
			}
1384
			$offset = $limit * $page;
1385
1386
			$sql .= $this->db->plimit($limit, $offset);
1387
		}
1388
1389
		$result = $this->db->query($sql);
1390
1391
		if ($result) {
1392
			$num = $this->db->num_rows($result);
1393
			$min = min($num, ($limit <= 0 ? $num : $limit));
1394
			for ($i = 0; $i < $min; $i++) {
1395
				$list[] = $this->db->fetch_object($result);
1396
			}
1397
		} else {
1398
			throw new RestException(503, 'Error when retrieving list of social networks: '.$this->db->lasterror());
1399
		}
1400
1401
		return $list;
1402
	}
1403
1404
	 /**
1405
	  * Get the list of tickets categories.
1406
	  *
1407
	  * @param string    $sortfield  Sort field
1408
	  * @param string    $sortorder  Sort order
1409
	  * @param int       $limit      Number of items per page
1410
	  * @param int       $page       Page number (starting from zero)
1411
	  * @param int       $active     Payment term is active or not {@min 0} {@max 1}
1412
	  * @param string    $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.code:like:'A%') and (t.active:>=:0)"
1413
	  * @return array				List of ticket categories
1414
	  *
1415
	  * @url     GET dictionary/ticket_categories
1416
	  *
1417
	  * @throws RestException
1418
	  */
1419
	public function getTicketsCategories($sortfield = "code", $sortorder = 'ASC', $limit = 100, $page = 0, $active = 1, $sqlfilters = '')
1420
	{
1421
		$list = array();
1422
1423
		$sql = "SELECT rowid, code, pos,  label, use_default, description";
1424
		$sql .= " FROM ".MAIN_DB_PREFIX."c_ticket_category as t";
1425
		$sql .= " WHERE t.active = ".$active;
1426
		// Add sql filters
1427
		if ($sqlfilters) {
1428
			if (!DolibarrApi::_checkFilters($sqlfilters)) {
1429
				throw new RestException(503, 'Error when validating parameter sqlfilters '.$sqlfilters);
1430
			}
1431
			$regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^:\(\)]+)\)';
1432
			$sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")";
1433
		}
1434
1435
1436
		$sql .= $this->db->order($sortfield, $sortorder);
1437
1438
		if ($limit) {
1439
			if ($page < 0) {
1440
				$page = 0;
1441
			}
1442
			$offset = $limit * $page;
1443
1444
			$sql .= $this->db->plimit($limit, $offset);
1445
		}
1446
1447
		$result = $this->db->query($sql);
1448
1449
		if ($result) {
1450
			$num = $this->db->num_rows($result);
1451
			$min = min($num, ($limit <= 0 ? $num : $limit));
1452
			for ($i = 0; $i < $min; $i++) {
1453
				$list[] = $this->db->fetch_object($result);
1454
			}
1455
		} else {
1456
			throw new RestException(503, 'Error when retrieving list of ticket categories : '.$this->db->lasterror());
1457
		}
1458
1459
		return $list;
1460
	}
1461
1462
	/**
1463
	 * Get the list of tickets severity.
1464
	 *
1465
	 * @param string    $sortfield  Sort field
1466
	 * @param string    $sortorder  Sort order
1467
	 * @param int       $limit      Number of items per page
1468
	 * @param int       $page       Page number (starting from zero)
1469
	 * @param int       $active     Payment term is active or not {@min 0} {@max 1}
1470
	 * @param string    $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.code:like:'A%') and (t.active:>=:0)"
1471
	 * @return array				List of ticket severities
1472
	 *
1473
	 * @url     GET dictionary/ticket_severities
1474
	 *
1475
	 * @throws RestException
1476
	 */
1477
	public function getTicketsSeverities($sortfield = "code", $sortorder = 'ASC', $limit = 100, $page = 0, $active = 1, $sqlfilters = '')
1478
	{
1479
		$list = array();
1480
1481
		$sql = "SELECT rowid, code, pos,  label, use_default, color, description";
1482
		$sql .= " FROM ".MAIN_DB_PREFIX."c_ticket_severity as t";
1483
		$sql .= " WHERE t.active = ".$active;
1484
		// Add sql filters
1485
		if ($sqlfilters) {
1486
			if (!DolibarrApi::_checkFilters($sqlfilters)) {
1487
				throw new RestException(503, 'Error when validating parameter sqlfilters '.$sqlfilters);
1488
			}
1489
			$regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^:\(\)]+)\)';
1490
			$sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")";
1491
		}
1492
1493
1494
		$sql .= $this->db->order($sortfield, $sortorder);
1495
1496
		if ($limit) {
1497
			if ($page < 0) {
1498
				$page = 0;
1499
			}
1500
			$offset = $limit * $page;
1501
1502
			$sql .= $this->db->plimit($limit, $offset);
1503
		}
1504
1505
		$result = $this->db->query($sql);
1506
1507
		if ($result) {
1508
			$num = $this->db->num_rows($result);
1509
			$min = min($num, ($limit <= 0 ? $num : $limit));
1510
			for ($i = 0; $i < $min; $i++) {
1511
				$list[] = $this->db->fetch_object($result);
1512
			}
1513
		} else {
1514
			throw new RestException(503, 'Error when retrieving list of ticket severities : '.$this->db->lasterror());
1515
		}
1516
1517
		return $list;
1518
	}
1519
1520
	/**
1521
	 * Get the list of tickets types.
1522
	 *
1523
	 * @param string    $sortfield  Sort field
1524
	 * @param string    $sortorder  Sort order
1525
	 * @param int       $limit      Number of items per page
1526
	 * @param int       $page       Page number (starting from zero)
1527
	 * @param int       $active     Payment term is active or not {@min 0} {@max 1}
1528
	 * @param string    $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.code:like:'A%') and (t.active:>=:0)"
1529
	 * @return array				List of ticket types
1530
	 *
1531
	 * @url     GET dictionary/ticket_types
1532
	 *
1533
	 * @throws RestException
1534
	 */
1535
	public function getTicketsTypes($sortfield = "code", $sortorder = 'ASC', $limit = 100, $page = 0, $active = 1, $sqlfilters = '')
1536
	{
1537
		$list = array();
1538
1539
		$sql = "SELECT rowid, code, pos,  label, use_default, description";
1540
		$sql .= " FROM ".MAIN_DB_PREFIX."c_ticket_type as t";
1541
		$sql .= " WHERE t.active = ".(int) $active;
1542
		// if ($type) $sql .= " AND t.type LIKE '%".$this->db->escape($type)."%'";
1543
		// if ($module)    $sql .= " AND t.module LIKE '%".$this->db->escape($module)."%'";
1544
		// Add sql filters
1545
		if ($sqlfilters) {
1546
			if (!DolibarrApi::_checkFilters($sqlfilters)) {
1547
				throw new RestException(503, 'Error when validating parameter sqlfilters '.$sqlfilters);
1548
			}
1549
			$regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^:\(\)]+)\)';
1550
			$sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")";
1551
		}
1552
1553
1554
		$sql .= $this->db->order($sortfield, $sortorder);
1555
1556
		if ($limit) {
1557
			if ($page < 0) {
1558
				$page = 0;
1559
			}
1560
			$offset = $limit * $page;
1561
1562
			$sql .= $this->db->plimit($limit, $offset);
1563
		}
1564
1565
		$result = $this->db->query($sql);
1566
1567
		if ($result) {
1568
			$num = $this->db->num_rows($result);
1569
			$min = min($num, ($limit <= 0 ? $num : $limit));
1570
			for ($i = 0; $i < $min; $i++) {
1571
				$list[] = $this->db->fetch_object($result);
1572
			}
1573
		} else {
1574
			throw new RestException(503, 'Error when retrieving list of ticket types : '.$this->db->lasterror());
1575
		}
1576
1577
		return $list;
1578
	}
1579
1580
	/**
1581
	 * Get properties of company
1582
	 *
1583
	 * @url	GET /company
1584
	 *
1585
	 * @return  array|mixed Mysoc object
1586
	 *
1587
	 * @throws RestException 403 Forbidden
1588
	 */
1589
	public function getCompany()
1590
	{
1591
		global $conf, $mysoc;
1592
1593
		if (!DolibarrApiAccess::$user->admin
1594
			&& (empty($conf->global->API_LOGINS_ALLOWED_FOR_GET_COMPANY) || DolibarrApiAccess::$user->login != $conf->global->API_LOGINS_ALLOWED_FOR_GET_COMPANY)) {
1595
				throw new RestException(403, 'Error API open to admin users only or to the users with logins defined into constant API_LOGINS_ALLOWED_FOR_GET_COMPANY');
1596
		}
1597
1598
		unset($mysoc->skype);
1599
		unset($mysoc->twitter);
1600
		unset($mysoc->facebook);
1601
		unset($mysoc->linkedin);
1602
1603
		unset($mysoc->pays);
1604
		unset($mysoc->note);
1605
		unset($mysoc->nom);
1606
1607
		unset($mysoc->lines);
1608
1609
		unset($mysoc->effectif);
1610
		unset($mysoc->effectif_id);
1611
		unset($mysoc->forme_juridique_code);
1612
		unset($mysoc->forme_juridique);
1613
		unset($mysoc->mode_reglement_supplier_id);
1614
		unset($mysoc->cond_reglement_supplier_id);
1615
		unset($mysoc->transport_mode_supplier_id);
1616
		unset($mysoc->fk_prospectlevel);
1617
1618
		unset($mysoc->total_ht);
1619
		unset($mysoc->total_tva);
1620
		unset($mysoc->total_localtax1);
1621
		unset($mysoc->total_localtax2);
1622
		unset($mysoc->total_ttc);
1623
1624
		unset($mysoc->lastname);
1625
		unset($mysoc->firstname);
1626
		unset($mysoc->civility_id);
1627
1628
		unset($mysoc->client);
1629
		unset($mysoc->prospect);
1630
		unset($mysoc->fournisseur);
1631
		unset($mysoc->contact_id);
1632
1633
		unset($mysoc->fk_incoterms);
1634
		unset($mysoc->label_incoterms);
1635
		unset($mysoc->location_incoterms);
1636
1637
		return $this->_cleanObjectDatas($mysoc);
1638
	}
1639
1640
1641
	/**
1642
	 * Get value of a setup variables
1643
	 *
1644
	 * Note that conf variables that stores security key or password hashes can't be loaded with API.
1645
	 *
1646
	 * @param	string			$constantname	Name of conf variable to get
1647
	 * @return  array|mixed 				Data without useless information
1648
	 *
1649
	 * @url     GET conf/{constantname}
1650
	 *
1651
	 * @throws RestException 403 Forbidden
1652
	 * @throws RestException 404 Error Bad or unknown value for constantname
1653
	 */
1654
	public function getConf($constantname)
1655
	{
1656
		global $conf;
1657
1658
		if (!DolibarrApiAccess::$user->admin
1659
			&& (empty($conf->global->API_LOGINS_ALLOWED_FOR_CONST_READ) || DolibarrApiAccess::$user->login != $conf->global->API_LOGINS_ALLOWED_FOR_CONST_READ)) {
1660
			throw new RestException(403, 'Error API open to admin users only or to the users with logins defined into constant API_LOGINS_ALLOWED_FOR_CONST_READ');
1661
		}
1662
1663
		if (!preg_match('/^[a-zA-Z0-9_]+$/', $constantname) || !isset($conf->global->$constantname)) {
1664
			throw new RestException(404, 'Error Bad or unknown value for constantname');
1665
		}
1666
		if (isASecretKey($constantname)) {
1667
			throw new RestException(403, 'Forbidden. This parameter cant be read with APIs');
1668
		}
1669
1670
		return $conf->global->$constantname;
1671
	}
1672
1673
	/**
1674
	 * Do a test of integrity for files and setup.
1675
	 *
1676
	 * @param string	$target			Can be 'local' or 'default' or Url of the signatures file to use for the test. Must be reachable by the tested Dolibarr.
1677
	 * @return array					Result of file and setup integrity check
1678
	 *
1679
	 * @url     GET checkintegrity
1680
	 *
1681
	 * @throws RestException 403 Forbidden
1682
	 * @throws RestException 404 Signature file not found
1683
	 * @throws RestException 500 Technical error
1684
	 * @throws RestException 503 Forbidden
1685
	 */
1686
	public function getCheckIntegrity($target)
1687
	{
1688
		global $langs, $conf;
1689
1690
		if (!DolibarrApiAccess::$user->admin
1691
			&& (empty($conf->global->API_LOGIN_ALLOWED_FOR_INTEGRITY_CHECK) || DolibarrApiAccess::$user->login != $conf->global->API_LOGIN_ALLOWED_FOR_INTEGRITY_CHECK)) {
1692
			throw new RestException(403, 'Error API open to admin users only or to the users with logins defined into constant API_LOGIN_ALLOWED_FOR_INTEGRITY_CHECK');
1693
		}
1694
1695
		require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
1696
		require_once DOL_DOCUMENT_ROOT.'/core/lib/geturl.lib.php';
1697
1698
		$langs->load("admin");
1699
1700
		$outexpectedchecksum = '';
1701
		$outcurrentchecksum = '';
1702
1703
		// Modified or missing files
1704
		$file_list = array('missing' => array(), 'updated' => array());
1705
1706
		// Local file to compare to
1707
		$xmlshortfile = GETPOST('xmlshortfile') ?GETPOST('xmlshortfile') : '/install/filelist-'.DOL_VERSION.'.xml';
1708
		$xmlfile = DOL_DOCUMENT_ROOT.$xmlshortfile;
1709
		// Remote file to compare to
1710
		$xmlremote = ($target == 'default' ? '' : $target);
1711
		if (empty($xmlremote) && !empty($conf->global->MAIN_FILECHECK_URL)) {
1712
			$xmlremote = $conf->global->MAIN_FILECHECK_URL;
1713
		}
1714
		$param = 'MAIN_FILECHECK_URL_'.DOL_VERSION;
1715
		if (empty($xmlremote) && !empty($conf->global->$param)) {
1716
			$xmlremote = $conf->global->$param;
1717
		}
1718
		if (empty($xmlremote)) {
1719
			$xmlremote = 'https://www.dolibarr.org/files/stable/signatures/filelist-'.DOL_VERSION.'.xml';
1720
		}
1721
1722
		if ($target == 'local') {
1723
			if (dol_is_file($xmlfile)) {
1724
				$xml = simplexml_load_file($xmlfile);
1725
			} else {
1726
				throw new RestException(500, $langs->trans('XmlNotFound').': '.$xmlfile);
1727
			}
1728
		} else {
1729
			$xmlarray = getURLContent($xmlremote);
1730
1731
			// Return array('content'=>response,'curl_error_no'=>errno,'curl_error_msg'=>errmsg...)
1732
			if (!$xmlarray['curl_error_no'] && $xmlarray['http_code'] != '400' && $xmlarray['http_code'] != '404') {
1733
				$xmlfile = $xmlarray['content'];
1734
				//print "xmlfilestart".$xmlfile."endxmlfile";
1735
				$xml = simplexml_load_string($xmlfile);
1736
			} else {
1737
				$errormsg = $langs->trans('XmlNotFound').': '.$xmlremote.' - '.$xmlarray['http_code'].' '.$xmlarray['curl_error_no'].' '.$xmlarray['curl_error_msg'];
1738
				throw new RestException(500, $errormsg);
1739
			}
1740
		}
1741
1742
		if ($xml) {
1743
			$checksumconcat = array();
1744
			$file_list = array();
1745
			$out = '';
1746
1747
			// Forced constants
1748
			if (is_object($xml->dolibarr_constants[0])) {
1749
				$out .= load_fiche_titre($langs->trans("ForcedConstants"));
1750
1751
				$out .= '<div class="div-table-responsive-no-min">';
1752
				$out .= '<table class="noborder">';
1753
				$out .= '<tr class="liste_titre">';
1754
				$out .= '<td>#</td>';
1755
				$out .= '<td>'.$langs->trans("Constant").'</td>';
1756
				$out .= '<td class="center">'.$langs->trans("ExpectedValue").'</td>';
1757
				$out .= '<td class="center">'.$langs->trans("Value").'</td>';
1758
				$out .= '</tr>'."\n";
1759
1760
				$i = 0;
1761
				foreach ($xml->dolibarr_constants[0]->constant as $constant) {    // $constant is a simpleXMLElement
1762
					$constname = $constant['name'];
1763
					$constvalue = (string) $constant;
1764
					$constvalue = (empty($constvalue) ? '0' : $constvalue);
1765
					// Value found
1766
					$value = '';
1767
					if ($constname && $conf->global->$constname != '') {
1768
						$value = $conf->global->$constname;
1769
					}
1770
					$valueforchecksum = (empty($value) ? '0' : $value);
1771
1772
					$checksumconcat[] = $valueforchecksum;
1773
1774
					$i++;
1775
					$out .= '<tr class="oddeven">';
1776
					$out .= '<td>'.$i.'</td>'."\n";
1777
					$out .= '<td>'.$constname.'</td>'."\n";
1778
					$out .= '<td class="center">'.$constvalue.'</td>'."\n";
1779
					$out .= '<td class="center">'.$valueforchecksum.'</td>'."\n";
1780
					$out .= "</tr>\n";
1781
				}
1782
1783
				if ($i == 0) {
1784
					$out .= '<tr class="oddeven"><td colspan="4" class="opacitymedium">'.$langs->trans("None").'</td></tr>';
1785
				}
1786
				$out .= '</table>';
1787
				$out .= '</div>';
1788
1789
				$out .= '<br>';
1790
			}
1791
1792
			// Scan htdocs
1793
			if (is_object($xml->dolibarr_htdocs_dir[0])) {
1794
				$includecustom = (empty($xml->dolibarr_htdocs_dir[0]['includecustom']) ? 0 : $xml->dolibarr_htdocs_dir[0]['includecustom']);
1795
1796
				// Defined qualified files (must be same than into generate_filelist_xml.php)
1797
				$regextoinclude = '\.(php|php3|php4|php5|phtml|phps|phar|inc|css|scss|html|xml|js|json|tpl|jpg|jpeg|png|gif|ico|sql|lang|txt|yml|bak|md|mp3|mp4|wav|mkv|z|gz|zip|rar|tar|less|svg|eot|woff|woff2|ttf|manifest)$';
1798
				$regextoexclude = '('.($includecustom ? '' : 'custom|').'documents|conf|install|public\/test|Shared\/PCLZip|nusoap\/lib\/Mail|php\/example|php\/test|geoip\/sample.*\.php|ckeditor\/samples|ckeditor\/adapters)$'; // Exclude dirs
1799
				$scanfiles = dol_dir_list(DOL_DOCUMENT_ROOT, 'files', 1, $regextoinclude, $regextoexclude);
1800
1801
				// Fill file_list with files in signature, new files, modified files
1802
				$ret = getFilesUpdated($file_list, $xml->dolibarr_htdocs_dir[0], '', DOL_DOCUMENT_ROOT, $checksumconcat); // Fill array $file_list
1803
				// Complete with list of new files
1804
				foreach ($scanfiles as $keyfile => $valfile) {
1805
					$tmprelativefilename = preg_replace('/^'.preg_quote(DOL_DOCUMENT_ROOT, '/').'/', '', $valfile['fullname']);
1806
					if (!in_array($tmprelativefilename, $file_list['insignature'])) {
1807
						$md5newfile = @md5_file($valfile['fullname']); // Can fails if we don't have permission to open/read file
1808
						$file_list['added'][] = array('filename'=>$tmprelativefilename, 'md5'=>$md5newfile);
1809
					}
1810
				}
1811
1812
				// Files missings
1813
				$out .= load_fiche_titre($langs->trans("FilesMissing"));
1814
1815
				$out .= '<div class="div-table-responsive-no-min">';
1816
				$out .= '<table class="noborder">';
1817
				$out .= '<tr class="liste_titre">';
1818
				$out .= '<td>#</td>';
1819
				$out .= '<td>'.$langs->trans("Filename").'</td>';
1820
				$out .= '<td class="center">'.$langs->trans("ExpectedChecksum").'</td>';
1821
				$out .= '</tr>'."\n";
1822
				$tmpfilelist = dol_sort_array($file_list['missing'], 'filename');
1823
				if (is_array($tmpfilelist) && count($tmpfilelist)) {
1824
					$i = 0;
1825
					foreach ($tmpfilelist as $file) {
1826
						$i++;
1827
						$out .= '<tr class="oddeven">';
1828
						$out .= '<td>'.$i.'</td>'."\n";
1829
						$out .= '<td>'.$file['filename'].'</td>'."\n";
1830
						$out .= '<td class="center">'.$file['expectedmd5'].'</td>'."\n";
1831
						$out .= "</tr>\n";
1832
					}
1833
				} else {
1834
					$out .= '<tr class="oddeven"><td colspan="3" class="opacitymedium">'.$langs->trans("None").'</td></tr>';
1835
				}
1836
				$out .= '</table>';
1837
				$out .= '</div>';
1838
1839
				$out .= '<br>';
1840
1841
				// Files modified
1842
				$out .= load_fiche_titre($langs->trans("FilesModified"));
1843
1844
				$totalsize = 0;
1845
				$out .= '<div class="div-table-responsive-no-min">';
1846
				$out .= '<table class="noborder">';
1847
				$out .= '<tr class="liste_titre">';
1848
				$out .= '<td>#</td>';
1849
				$out .= '<td>'.$langs->trans("Filename").'</td>';
1850
				$out .= '<td class="center">'.$langs->trans("ExpectedChecksum").'</td>';
1851
				$out .= '<td class="center">'.$langs->trans("CurrentChecksum").'</td>';
1852
				$out .= '<td class="right">'.$langs->trans("Size").'</td>';
1853
				$out .= '<td class="right">'.$langs->trans("DateModification").'</td>';
1854
				$out .= '</tr>'."\n";
1855
				$tmpfilelist2 = dol_sort_array($file_list['updated'], 'filename');
1856
				if (is_array($tmpfilelist2) && count($tmpfilelist2)) {
1857
					$i = 0;
1858
					foreach ($tmpfilelist2 as $file) {
1859
						$i++;
1860
						$out .= '<tr class="oddeven">';
1861
						$out .= '<td>'.$i.'</td>'."\n";
1862
						$out .= '<td>'.$file['filename'].'</td>'."\n";
1863
						$out .= '<td class="center">'.$file['expectedmd5'].'</td>'."\n";
1864
						$out .= '<td class="center">'.$file['md5'].'</td>'."\n";
1865
						$size = dol_filesize(DOL_DOCUMENT_ROOT.'/'.$file['filename']);
1866
						$totalsize += $size;
1867
						$out .= '<td class="right">'.dol_print_size($size).'</td>'."\n";
1868
						$out .= '<td class="right">'.dol_print_date(dol_filemtime(DOL_DOCUMENT_ROOT.'/'.$file['filename']), 'dayhour').'</td>'."\n";
1869
						$out .= "</tr>\n";
1870
					}
1871
					$out .= '<tr class="liste_total">';
1872
					$out .= '<td></td>'."\n";
1873
					$out .= '<td>'.$langs->trans("Total").'</td>'."\n";
1874
					$out .= '<td align="center"></td>'."\n";
1875
					$out .= '<td align="center"></td>'."\n";
1876
					$out .= '<td class="right">'.dol_print_size($totalsize).'</td>'."\n";
1877
					$out .= '<td class="right"></td>'."\n";
1878
					$out .= "</tr>\n";
1879
				} else {
1880
					$out .= '<tr class="oddeven"><td colspan="5" class="opacitymedium">'.$langs->trans("None").'</td></tr>';
1881
				}
1882
				$out .= '</table>';
1883
				$out .= '</div>';
1884
1885
				$out .= '<br>';
1886
1887
				// Files added
1888
				$out .= load_fiche_titre($langs->trans("FilesAdded"));
1889
1890
				$totalsize = 0;
1891
				$out .= '<div class="div-table-responsive-no-min">';
1892
				$out .= '<table class="noborder">';
1893
				$out .= '<tr class="liste_titre">';
1894
				$out .= '<td>#</td>';
1895
				$out .= '<td>'.$langs->trans("Filename").'</td>';
1896
				$out .= '<td class="center">'.$langs->trans("ExpectedChecksum").'</td>';
1897
				$out .= '<td class="center">'.$langs->trans("CurrentChecksum").'</td>';
1898
				$out .= '<td class="right">'.$langs->trans("Size").'</td>';
1899
				$out .= '<td class="right">'.$langs->trans("DateModification").'</td>';
1900
				$out .= '</tr>'."\n";
1901
				$tmpfilelist3 = dol_sort_array($file_list['added'], 'filename');
1902
				if (is_array($tmpfilelist3) && count($tmpfilelist3)) {
1903
					$i = 0;
1904
					foreach ($tmpfilelist3 as $file) {
1905
						$i++;
1906
						$out .= '<tr class="oddeven">';
1907
						$out .= '<td>'.$i.'</td>'."\n";
1908
						$out .= '<td>'.$file['filename'].'</td>'."\n";
1909
						$out .= '<td class="center">'.$file['expectedmd5'].'</td>'."\n";
1910
						$out .= '<td class="center">'.$file['md5'].'</td>'."\n";
1911
						$size = dol_filesize(DOL_DOCUMENT_ROOT.'/'.$file['filename']);
1912
						$totalsize += $size;
1913
						$out .= '<td class="right">'.dol_print_size($size).'</td>'."\n";
1914
						$out .= '<td class="right">'.dol_print_date(dol_filemtime(DOL_DOCUMENT_ROOT.'/'.$file['filename']), 'dayhour').'</td>'."\n";
1915
						$out .= "</tr>\n";
1916
					}
1917
					$out .= '<tr class="liste_total">';
1918
					$out .= '<td></td>'."\n";
1919
					$out .= '<td>'.$langs->trans("Total").'</td>'."\n";
1920
					$out .= '<td align="center"></td>'."\n";
1921
					$out .= '<td align="center"></td>'."\n";
1922
					$out .= '<td class="right">'.dol_print_size($totalsize).'</td>'."\n";
1923
					$out .= '<td class="right"></td>'."\n";
1924
					$out .= "</tr>\n";
1925
				} else {
1926
					$out .= '<tr class="oddeven"><td colspan="5" class="opacitymedium">'.$langs->trans("None").'</td></tr>';
1927
				}
1928
				$out .= '</table>';
1929
				$out .= '</div>';
1930
1931
1932
				// Show warning
1933
				if (empty($tmpfilelist) && empty($tmpfilelist2) && empty($tmpfilelist3)) {
1934
					//setEventMessages($langs->trans("FileIntegrityIsStrictlyConformedWithReference"), null, 'mesgs');
1935
				} else {
1936
					//setEventMessages($langs->trans("FileIntegritySomeFilesWereRemovedOrModified"), null, 'warnings');
1937
				}
1938
			} else {
1939
				throw new RestException(500, 'Error: Failed to found dolibarr_htdocs_dir into XML file '.$xmlfile);
1940
			}
1941
1942
1943
			// Scan scripts
1944
			asort($checksumconcat); // Sort list of checksum
1945
			$checksumget = md5(join(',', $checksumconcat));
1946
			$checksumtoget = trim((string) $xml->dolibarr_htdocs_dir_checksum);
1947
1948
			$outexpectedchecksum = ($checksumtoget ? $checksumtoget : $langs->trans("Unknown"));
1949
			if ($checksumget == $checksumtoget) {
1950
				if (count($file_list['added'])) {
1951
					$resultcode = 'warning';
1952
					$resultcomment = 'FileIntegrityIsOkButFilesWereAdded';
1953
					//$outcurrentchecksum =  $checksumget.' - <span class="'.$resultcode.'">'.$langs->trans("FileIntegrityIsOkButFilesWereAdded").'</span>';
1954
					$outcurrentchecksum = $checksumget;
1955
				} else {
1956
					$resultcode = 'ok';
1957
					$resultcomment = 'Success';
1958
					//$outcurrentchecksum = '<span class="'.$resultcode.'">'.$checksumget.'</span>';
1959
					$outcurrentchecksum = $checksumget;
1960
				}
1961
			} else {
1962
				$resultcode = 'error';
1963
				$resultcomment = 'Error';
1964
				//$outcurrentchecksum = '<span class="'.$resultcode.'">'.$checksumget.'</span>';
1965
				$outcurrentchecksum = $checksumget;
1966
			}
1967
		} else {
1968
			throw new RestException(404, 'No signature file known');
1969
		}
1970
1971
		return array('resultcode'=>$resultcode, 'resultcomment'=>$resultcomment, 'expectedchecksum'=> $outexpectedchecksum, 'currentchecksum'=> $outcurrentchecksum, 'out'=>$out);
1972
	}
1973
1974
1975
	/**
1976
	 * Get list of enabled modules
1977
	 *
1978
	 * @url	GET /modules
1979
	 *
1980
	 * @return  array|mixed Data without useless information
1981
	 *
1982
	 * @throws RestException 403 Forbidden
1983
	 */
1984
	public function getModules()
1985
	{
1986
		global $conf;
1987
1988
		if (!DolibarrApiAccess::$user->admin
1989
			&& (empty($conf->global->API_LOGIN_ALLOWED_FOR_GET_MODULES) || DolibarrApiAccess::$user->login != $conf->global->API_LOGIN_ALLOWED_FOR_GET_MODULES)) {
1990
			throw new RestException(403, 'Error API open to admin users only or to the users with logins defined into constant API_LOGIN_ALLOWED_FOR_GET_MODULES');
1991
		}
1992
1993
		sort($conf->modules);
1994
1995
		return $this->_cleanObjectDatas($conf->modules);
1996
	}
1997
}
1998