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

Setup::getConf()   B

Complexity

Conditions 7
Paths 4

Size

Total Lines 17
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 7
eloc 9
nc 4
nop 1
dl 0
loc 17
rs 8.8333
c 1
b 0
f 0
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