Passed
Push — EXTRACT_CLASSES ( 231cec...0382f2 )
by Rafael
65:54 queued 05:18
created

Setup   F

Complexity

Total Complexity 360

Size/Duplication

Total Lines 2640
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 1174
dl 0
loc 2640
rs 0.904
c 0
b 0
f 0
wmc 360

47 Methods

Rating   Name   Duplication   Size   Complexity  
B getShippingModes() 0 44 8
A getEstablishments() 0 26 4
A getCountryByISO() 0 3 1
B getListOfTowns() 0 47 10
A _fetchCregion() 0 12 3
F getCheckIntegrity() 0 308 53
A _fetchCcountry() 0 15 3
A _cleanObjectDatas() 0 9 1
A getCountryByID() 0 3 1
B getListOfIncoterms() 0 44 8
C getListOfRegions() 0 51 12
B getTicketsCategories() 0 44 8
A getRegionByID() 0 3 1
A getStateByCode() 0 3 1
B getListOfContactTypes() 0 49 10
B getPaymentTypes() 0 46 11
B getListOfLegalForm() 0 44 9
B getListOfsocialNetworks() 0 48 9
A getModules() 0 14 4
B getListOfStaff() 0 41 8
A _fetchCstate() 0 12 3
B getPaymentTerms() 0 46 11
B getAvailability() 0 45 9
B getListOfExpenseReportsTypes() 0 44 9
A getRegionByCode() 0 3 1
B getListOfMeasuringUnits() 0 41 8
B getConf() 0 19 7
A __construct() 0 4 1
A getCountryByCode() 0 3 1
C getListOfCurrencies() 0 54 13
C getListOfStates() 0 53 13
B postExtrafields() 0 73 9
A getStateByID() 0 3 1
A translateLabel() 0 16 6
B getOrderingMethods() 0 45 9
B getListOfCivilities() 0 46 9
B getTicketsTypes() 0 45 8
A getCompany() 0 46 4
B getOrderingOrigins() 0 45 9
B updateExtrafields() 0 70 9
B getExtrafields() 0 62 8
A getEtablishmentByID() 0 12 3
B getListOfEventTypes() 0 47 10
B getListOfCountries() 0 51 11
A deleteExtrafieldsFromNames() 0 21 4
B getTicketsSeverities() 0 44 8
C getListOfExtrafields() 0 71 11

How to fix   Complexity   

Complex Class

Complex classes like Setup often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Setup, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/* Copyright (C) 2016       Xebax Christy               <[email protected]>
4
 * Copyright (C) 2016	    Laurent Destailleur		    <[email protected]>
5
 * Copyright (C) 2017	    Regis Houssin	            <[email protected]>
6
 * Copyright (C) 2017	    Neil Orley	                <[email protected]>
7
 * Copyright (C) 2018-2021  Frédéric France             <[email protected]>
8
 * Copyright (C) 2018-2022  Thibault FOUCART            <[email protected]>
9
 * Copyright (C) 2024       Jon Bendtsen                <[email protected]>
10
 * Copyright (C) 2024       Rafael San José             <[email protected]>
11
 *
12
 * This program is free software; you can redistribute it and/or modify
13
 * it under the terms of the GNU General Public License as published by
14
 * the Free Software Foundation; either version 3 of the License, or
15
 * (at your option) any later version.
16
 *
17
 * This program is distributed in the hope that it will be useful,
18
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20
 * GNU General Public License for more details.
21
 *
22
 * You should have received a copy of the GNU General Public License
23
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
24
 */
25
26
namespace Dolibarr\Code\Api\Api;
27
28
use Luracast\Restler\RestException;
29
30
require_once constant('DOL_DOCUMENT_ROOT') . '/main.inc.php';
31
require_once constant('DOL_DOCUMENT_ROOT') . '/api/class/api.class.php';
32
require_once constant('DOL_DOCUMENT_ROOT') . '/core/class/cstate.class.php';
33
require_once constant('DOL_DOCUMENT_ROOT') . '/core/class/cregion.class.php';
34
require_once constant('DOL_DOCUMENT_ROOT') . '/core/class/ccountry.class.php';
35
require_once constant('DOL_DOCUMENT_ROOT') . '/hrm/class/establishment.class.php';
36
37
/**
38
 * API class for dictionaries
39
 *
40
 * @access protected
41
 * @class DolibarrApiAccess {@requires user,external}
42
 */
43
class Setup extends DolibarrApi
44
{
45
    private $translations = null;
46
47
    /**
48
     * Constructor
49
     */
50
    public function __construct()
51
    {
52
        global $db;
53
        $this->db = $db;
54
    }
55
56
    /**
57
     * Get the list of ordering methods.
58
     *
59
     * @param string    $sortfield  Sort field
60
     * @param string    $sortorder  Sort order
61
     * @param int       $limit      Number of items per page
62
     * @param int       $page       Page number {@min 0}
63
     * @param int       $active     Payment type is active or not {@min 0} {@max 1}
64
     * @param string    $sqlfilters SQL criteria to filter with. Syntax example "(t.code:=:'OrderByWWW')"
65
     *
66
     * @url     GET dictionary/ordering_methods
67
     *
68
     * @return array [List of ordering methods]
69
     *
70
     * @throws  RestException   400     Bad value for sqlfilters
71
     * @throws  RestException   403     Access denied
72
     * @throws  RestException   503     Error retrieving list of ordering methods
73
     */
74
    public function getOrderingMethods($sortfield = "code", $sortorder = 'ASC', $limit = 100, $page = 0, $active = 1, $sqlfilters = '')
75
    {
76
        $list = array();
77
78
        if (!DolibarrApiAccess::$user->hasRight('commande', 'lire')) {
79
            throw new RestException(403);
80
        }
81
82
        $sql = "SELECT rowid, code, libelle as label, module";
83
        $sql .= " FROM " . MAIN_DB_PREFIX . "c_input_method as t";
84
        $sql .= " WHERE t.active = " . ((int) $active);
85
        // Add sql filters
86
        if ($sqlfilters) {
87
            $errormessage = '';
88
            $sql .= forgeSQLFromUniversalSearchCriteria($sqlfilters, $errormessage);
89
            if ($errormessage) {
90
                throw new RestException(400, 'Error when validating parameter sqlfilters -> ' . $errormessage);
91
            }
92
        }
93
94
95
        $sql .= $this->db->order($sortfield, $sortorder);
96
97
        if ($limit) {
98
            if ($page < 0) {
99
                $page = 0;
100
            }
101
            $offset = $limit * $page;
102
103
            $sql .= $this->db->plimit($limit, $offset);
104
        }
105
106
        $result = $this->db->query($sql);
107
108
        if ($result) {
109
            $num = $this->db->num_rows($result);
110
            $min = min($num, ($limit <= 0 ? $num : $limit));
111
            for ($i = 0; $i < $min; $i++) {
112
                $list[] = $this->db->fetch_object($result);
113
            }
114
        } else {
115
            throw new RestException(503, $this->db->lasterror());
116
        }
117
118
        return $list;
119
    }
120
121
    /**
122
     * Get the list of ordering origins.
123
     *
124
     * @param string    $sortfield  Sort field
125
     * @param string    $sortorder  Sort order
126
     * @param int       $limit      Number of items per page
127
     * @param int       $page       Page number {@min 0}
128
     * @param int       $active     Payment type is active or not {@min 0} {@max 1}
129
     * @param string    $sqlfilters SQL criteria to filter with. Syntax example "(t.code:=:'OrderByWWW')"
130
     * @return array [List of ordering reasons]
131
     *
132
     * @url     GET dictionary/ordering_origins
133
     *
134
     * @throws  RestException   400     Bad value for sqlfilters
135
     * @throws  RestException   403     Access denied
136
     * @throws  RestException   503     Error retrieving list of ordering origins
137
     */
138
    public function getOrderingOrigins($sortfield = "code", $sortorder = 'ASC', $limit = 100, $page = 0, $active = 1, $sqlfilters = '')
139
    {
140
        $list = array();
141
142
        if (!DolibarrApiAccess::$user->hasRight('commande', 'lire')) {
143
            throw new RestException(403);
144
        }
145
146
        $sql = "SELECT rowid, code, label, module";
147
        $sql .= " FROM " . MAIN_DB_PREFIX . "c_input_reason as t";
148
        $sql .= " WHERE t.active = " . ((int) $active);
149
        // Add sql filters
150
        if ($sqlfilters) {
151
            $errormessage = '';
152
            $sql .= forgeSQLFromUniversalSearchCriteria($sqlfilters, $errormessage);
153
            if ($errormessage) {
154
                throw new RestException(400, 'Error when validating parameter sqlfilters -> ' . $errormessage);
155
            }
156
        }
157
158
159
        $sql .= $this->db->order($sortfield, $sortorder);
160
161
        if ($limit) {
162
            if ($page < 0) {
163
                $page = 0;
164
            }
165
            $offset = $limit * $page;
166
167
            $sql .= $this->db->plimit($limit, $offset);
168
        }
169
170
        $result = $this->db->query($sql);
171
172
        if ($result) {
173
            $num = $this->db->num_rows($result);
174
            $min = min($num, ($limit <= 0 ? $num : $limit));
175
            for ($i = 0; $i < $min; $i++) {
176
                $list[] = $this->db->fetch_object($result);
177
            }
178
        } else {
179
            throw new RestException(503, $this->db->lasterror());
180
        }
181
182
        return $list;
183
    }
184
185
    /**
186
     * Get the list of payments types.
187
     *
188
     * @param string    $sortfield  Sort field
189
     * @param string    $sortorder  Sort order
190
     * @param int       $limit      Number of items per page
191
     * @param int       $page       Page number {@min 0}
192
     * @param int       $active     Payment type is active or not {@min 0} {@max 1}
193
     * @param string    $sqlfilters SQL criteria to filter with. Syntax example "(t.code:=:'CHQ')"
194
     *
195
     * @url     GET dictionary/payment_types
196
     *
197
     * @return array [List of payment types]
198
     *
199
     * @throws  RestException   400     Bad value for sqlfilters
200
     * @throws  RestException   403     Access denied
201
     * @throws  RestException   503     Error retrieving list of payment types
202
     */
203
    public function getPaymentTypes($sortfield = "code", $sortorder = 'ASC', $limit = 100, $page = 0, $active = 1, $sqlfilters = '')
204
    {
205
        $list = array();
206
207
        if (!DolibarrApiAccess::$user->hasRight('propal', 'lire') && !DolibarrApiAccess::$user->hasRight('commande', 'lire') && !DolibarrApiAccess::$user->hasRight('facture', 'lire')) {
208
            throw new RestException(403);
209
        }
210
211
        $sql = "SELECT id, code, type, libelle as label, module";
212
        $sql .= " FROM " . MAIN_DB_PREFIX . "c_paiement as t";
213
        $sql .= " WHERE t.entity IN (" . getEntity('c_paiement') . ")";
214
        $sql .= " AND t.active = " . ((int) $active);
215
        // Add sql filters
216
        if ($sqlfilters) {
217
            $errormessage = '';
218
            $sql .= forgeSQLFromUniversalSearchCriteria($sqlfilters, $errormessage);
219
            if ($errormessage) {
220
                throw new RestException(400, 'Error when validating parameter sqlfilters -> ' . $errormessage);
221
            }
222
        }
223
224
225
        $sql .= $this->db->order($sortfield, $sortorder);
226
227
        if ($limit) {
228
            if ($page < 0) {
229
                $page = 0;
230
            }
231
            $offset = $limit * $page;
232
233
            $sql .= $this->db->plimit($limit, $offset);
234
        }
235
236
        $result = $this->db->query($sql);
237
238
        if ($result) {
239
            $num = $this->db->num_rows($result);
240
            $min = min($num, ($limit <= 0 ? $num : $limit));
241
            for ($i = 0; $i < $min; $i++) {
242
                $list[] = $this->db->fetch_object($result);
243
            }
244
        } else {
245
            throw new RestException(503, $this->db->lasterror());
246
        }
247
248
        return $list;
249
    }
250
    /**
251
     * Get the list of regions.
252
     *
253
     * The returned list is sorted by region ID.
254
     *
255
     * @param string    $sortfield  Sort field
256
     * @param string    $sortorder  Sort order
257
     * @param int       $limit      Number of items per page
258
     * @param int       $page       Page number (starting from zero)
259
     * @param int       $country    To filter on country
260
     * @param string    $filter     To filter the regions by name
261
     * @param string    $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.code:like:'A%') and (t.active:>=:0)"
262
     * @return array                List of regions
263
     *
264
     * @url     GET dictionary/regions
265
     *
266
     * @throws  RestException   400     Bad value for sqlfilters
267
     * @throws  RestException   503     Error retrieving list of regions
268
     */
269
    public function getListOfRegions($sortfield = "code_region", $sortorder = 'ASC', $limit = 100, $page = 0, $country = 0, $filter = '', $sqlfilters = '')
270
    {
271
        $list = array();
272
273
        // Note: The filter is not applied in the SQL request because it must
274
        // be applied to the translated names, not to the names in database.
275
        $sql = "SELECT t.rowid FROM " . MAIN_DB_PREFIX . "c_regions as t";
276
        $sql .= " WHERE 1 = 1";
277
        if ($country) {
278
            $sql .= " AND t.fk_pays = " . ((int) $country);
279
        }
280
        // Add sql filters
281
        if ($sqlfilters) {
282
            $errormessage = '';
283
            if (!DolibarrApi::_checkFilters($sqlfilters, $errormessage)) {
284
                throw new RestException(400, 'Error when validating parameter sqlfilters -> ' . $errormessage);
285
            }
286
            $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)';
287
            $sql .= " AND (" . preg_replace_callback('/' . $regexstring . '/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters) . ")";
288
        }
289
290
        $sql .= $this->db->order($sortfield, $sortorder);
291
292
        if ($limit) {
293
            if ($page < 0) {
294
                $page = 0;
295
            }
296
            $offset = $limit * $page;
297
298
            $sql .= $this->db->plimit($limit, $offset);
299
        }
300
301
        $result = $this->db->query($sql);
302
303
        if ($result) {
304
            $num = $this->db->num_rows($result);
305
            $min = min($num, ($limit <= 0 ? $num : $limit));
306
            for ($i = 0; $i < $min; $i++) {
307
                $obj = $this->db->fetch_object($result);
308
                $region = new Cregion($this->db);
0 ignored issues
show
Bug introduced by
The type Dolibarr\Code\Api\Api\Cregion was not found. Did you mean Cregion? If so, make sure to prefix the type with \.
Loading history...
309
                if ($region->fetch($obj->rowid) > 0) {
310
                    if (empty($filter) || stripos($region->name, $filter) !== false) {
311
                        $list[] = $this->_cleanObjectDatas($region);
312
                    }
313
                }
314
            }
315
        } else {
316
            throw new RestException(503, 'Error when retrieving list of regions');
317
        }
318
319
        return $list;
320
    }
321
322
    /**
323
     * Get region by ID.
324
     *
325
     * @param   int       $id       ID of region
326
     * @return  Object              Object with cleaned properties
327
     *
328
     * @url     GET dictionary/regions/{id}
329
     *
330
     * @throws  RestException   404     Region not found
331
     * @throws  RestException   503     Error retrieving region
332
     */
333
    public function getRegionByID($id)
334
    {
335
        return $this->_fetchCregion($id, '');
336
    }
337
338
    /**
339
     * Get region by Code.
340
     *
341
     * @param   string    $code     Code of region
342
     * @return  Object              Object with cleaned properties
343
     *
344
     * @url     GET dictionary/regions/byCode/{code}
345
     *
346
     * @throws  RestException   404     Region not found
347
     * @throws  RestException   503     Error when retrieving region
348
     */
349
    public function getRegionByCode($code)
350
    {
351
        return $this->_fetchCregion('', $code);
352
    }
353
354
    /**
355
     * Get the list of states/provinces.
356
     *
357
     * The names of the states will be translated to the given language if
358
     * the $lang parameter is provided. The value of $lang must be a language
359
     * code supported by Dolibarr, for example 'en_US' or 'fr_FR'.
360
     * The returned list is sorted by state ID.
361
     *
362
     * @param string    $sortfield  Sort field
363
     * @param string    $sortorder  Sort order
364
     * @param int       $limit      Number of items per page
365
     * @param int       $page       Page number (starting from zero)
366
     * @param int       $country    To filter on country
367
     * @param string    $filter     To filter the states by name
368
     * @param string    $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.code:like:'A%') and (t.active:>=:0)"
369
     * @return array                List of states
370
     *
371
     * @url     GET dictionary/states
372
     *
373
     * @throws  RestException   400     Bad value for sqlfilters
374
     * @throws  RestException   503     Error retrieving list of states
375
     */
376
    public function getListOfStates($sortfield = "code_departement", $sortorder = 'ASC', $limit = 100, $page = 0, $country = 0, $filter = '', $sqlfilters = '')
377
    {
378
        $list = array();
379
380
        // Note: The filter is not applied in the SQL request because it must
381
        // be applied to the translated names, not to the names in database.
382
        $sql = "SELECT t.rowid FROM " . MAIN_DB_PREFIX . "c_departements as t";
383
        if ($country) {
384
            $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "c_regions as d ON t.fk_region = d.code_region";
385
        }
386
        $sql .= " WHERE 1 = 1";
387
        if ($country) {
388
            $sql .= " AND d.fk_pays = " . ((int) $country);
389
        }
390
        // Add sql filters
391
        if ($sqlfilters) {
392
            $errormessage = '';
393
            $sql .= forgeSQLFromUniversalSearchCriteria($sqlfilters, $errormessage);
394
            if ($errormessage) {
395
                throw new RestException(400, 'Error when validating parameter sqlfilters -> ' . $errormessage);
396
            }
397
        }
398
399
        $sql .= $this->db->order($sortfield, $sortorder);
400
401
        if ($limit) {
402
            if ($page < 0) {
403
                $page = 0;
404
            }
405
            $offset = $limit * $page;
406
407
            $sql .= $this->db->plimit($limit, $offset);
408
        }
409
410
        $result = $this->db->query($sql);
411
412
        if ($result) {
413
            $num = $this->db->num_rows($result);
414
            $min = min($num, ($limit <= 0 ? $num : $limit));
415
            for ($i = 0; $i < $min; $i++) {
416
                $obj = $this->db->fetch_object($result);
417
                $state = new Cstate($this->db);
0 ignored issues
show
Bug introduced by
The type Dolibarr\Code\Api\Api\Cstate was not found. Did you mean Cstate? If so, make sure to prefix the type with \.
Loading history...
418
                if ($state->fetch($obj->rowid) > 0) {
419
                    if (empty($filter) || stripos($state->label, $filter) !== false) {
420
                        $list[] = $this->_cleanObjectDatas($state);
421
                    }
422
                }
423
            }
424
        } else {
425
            throw new RestException(503, 'Error when retrieving list of states');
426
        }
427
428
        return $list;
429
    }
430
431
    /**
432
     * Get state by ID.
433
     *
434
     * @param   int       $id           ID of state
435
     * @return  Object                  Object with cleaned properties
436
     *
437
     * @url     GET dictionary/states/{id}
438
     *
439
     * @throws  RestException   404     State not found
440
     * @throws  RestException   503     Error retrieving state
441
     */
442
    public function getStateByID($id)
443
    {
444
        return $this->_fetchCstate($id, '');
445
    }
446
447
    /**
448
     * Get state by Code.
449
     *
450
     * @param   string    $code         Code of state
451
     * @return  Object                  Object with cleaned properties
452
     *
453
     * @url     GET dictionary/states/byCode/{code}
454
     *
455
     * @throws  RestException   404     State not found
456
     * @throws  RestException   503     Error retrieving state
457
     */
458
    public function getStateByCode($code)
459
    {
460
        return $this->_fetchCstate('', $code);
461
    }
462
463
    /**
464
     * Get the list of countries.
465
     *
466
     * The names of the countries will be translated to the given language if
467
     * the $lang parameter is provided. The value of $lang must be a language
468
     * code supported by Dolibarr, for example 'en_US' or 'fr_FR'.
469
     * The returned list is sorted by country ID.
470
     *
471
     * @param string    $sortfield  Sort field
472
     * @param string    $sortorder  Sort order
473
     * @param int       $limit      Number of items per page
474
     * @param int       $page       Page number (starting from zero)
475
     * @param string    $filter     To filter the countries by name
476
     * @param string    $lang       Code of the language the label of the countries must be translated to
477
     * @param string    $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.code:like:'A%') and (t.active:>=:0)"
478
     * @return array                List of countries
479
     *
480
     * @url     GET dictionary/countries
481
     *
482
     * @throws  RestException   400     Bad value for sqlfilters
483
     * @throws  RestException   503     Error retrieving list of countries
484
     */
485
    public function getListOfCountries($sortfield = "code", $sortorder = 'ASC', $limit = 100, $page = 0, $filter = '', $lang = '', $sqlfilters = '')
486
    {
487
        $list = array();
488
489
        // Note: The filter is not applied in the SQL request because it must
490
        // be applied to the translated names, not to the names in database.
491
        $sql = "SELECT rowid FROM " . MAIN_DB_PREFIX . "c_country as t";
492
        $sql .= " WHERE 1 = 1";
493
        // Add sql filters
494
        if ($sqlfilters) {
495
            $errormessage = '';
496
            $sql .= forgeSQLFromUniversalSearchCriteria($sqlfilters, $errormessage);
497
            if ($errormessage) {
498
                throw new RestException(400, 'Error when validating parameter sqlfilters -> ' . $errormessage);
499
            }
500
        }
501
502
        $sql .= $this->db->order($sortfield, $sortorder);
503
504
        if ($limit) {
505
            if ($page < 0) {
506
                $page = 0;
507
            }
508
            $offset = $limit * $page;
509
510
            $sql .= $this->db->plimit($limit, $offset);
511
        }
512
513
        $result = $this->db->query($sql);
514
515
        if ($result) {
516
            $num = $this->db->num_rows($result);
517
            $min = min($num, ($limit <= 0 ? $num : $limit));
518
            for ($i = 0; $i < $min; $i++) {
519
                $obj = $this->db->fetch_object($result);
520
                $country = new Ccountry($this->db);
0 ignored issues
show
Bug introduced by
The type Dolibarr\Code\Api\Api\Ccountry was not found. Did you mean Ccountry? If so, make sure to prefix the type with \.
Loading history...
521
                if ($country->fetch($obj->rowid) > 0) {
522
                    // Translate the name of the country if needed
523
                    // and then apply the filter if there is one.
524
                    $this->translateLabel($country, $lang, 'Country');
525
526
                    if (empty($filter) || stripos($country->label, $filter) !== false) {
527
                        $list[] = $this->_cleanObjectDatas($country);
528
                    }
529
                }
530
            }
531
        } else {
532
            throw new RestException(503, 'Error when retrieving list of countries');
533
        }
534
535
        return $list;
536
    }
537
538
    /**
539
     * Get country by ID.
540
     *
541
     * @param   int       $id           ID of country
542
     * @param   string    $lang         Code of the language the name of the country must be translated to
543
     * @return  Object                  Object with cleaned properties
544
     *
545
     * @url     GET dictionary/countries/{id}
546
     *
547
     * @throws  RestException   404     Country not found
548
     * @throws  RestException   503     Error retrieving country
549
     */
550
    public function getCountryByID($id, $lang = '')
551
    {
552
        return $this->_fetchCcountry($id, '', '', $lang);
553
    }
554
555
    /**
556
     * Get country by Code.
557
     *
558
     * @param   string    $code         Code of country (2 characters)
559
     * @param   string    $lang         Code of the language the name of the country must be translated to
560
     * @return  Object                  Object with cleaned properties
561
     *
562
     * @url     GET dictionary/countries/byCode/{code}
563
     *
564
     * @throws  RestException   404     Country not found
565
     * @throws  RestException   503     Error retrieving country
566
     */
567
    public function getCountryByCode($code, $lang = '')
568
    {
569
        return $this->_fetchCcountry('', $code, '', $lang);
570
    }
571
572
    /**
573
     * Get country by Iso.
574
     *
575
     * @param   string    $iso          ISO of country (3 characters)
576
     * @param   string    $lang         Code of the language the name of the country must be translated to
577
     * @return  Object                  Object with cleaned properties
578
     *
579
     * @url     GET dictionary/countries/byISO/{iso}
580
     *
581
     * @throws  RestException   404     Country not found
582
     * @throws  RestException   503     Error retrieving country
583
     */
584
    public function getCountryByISO($iso, $lang = '')
585
    {
586
        return $this->_fetchCcountry('', '', $iso, $lang);
587
    }
588
589
    /**
590
     * Get region.
591
     *
592
     * @param   int       $id       ID of region
593
     * @param   string    $code     Code of region
594
     * @return  Object              Object with cleaned properties
595
     *
596
     * @throws RestException
597
     */
598
    private function _fetchCregion($id, $code = '')
599
    {
600
        $region = new Cregion($this->db);
601
602
        $result = $region->fetch($id, $code);
603
        if ($result < 0) {
604
            throw new RestException(503, 'Error when retrieving region : ' . $region->error);
605
        } elseif ($result == 0) {
606
            throw new RestException(404, 'Region not found');
607
        }
608
609
        return $this->_cleanObjectDatas($region);
610
    }
611
612
    /**
613
     * Get state.
614
     *
615
     * @param   int       $id           ID of state
616
     * @param   string    $code         Code of state
617
     * @return  Object                  Object with cleaned properties
618
     *
619
     * @throws RestException
620
     */
621
    private function _fetchCstate($id, $code = '')
622
    {
623
        $state = new Cstate($this->db);
624
625
        $result = $state->fetch($id, $code);
626
        if ($result < 0) {
627
            throw new RestException(503, 'Error when retrieving state : ' . $state->error);
628
        } elseif ($result == 0) {
629
            throw new RestException(404, 'State not found');
630
        }
631
632
        return $this->_cleanObjectDatas($state);
633
    }
634
635
    /**
636
     * Get country.
637
     *
638
     * @param   int       $id           ID of country
639
     * @param   string    $code         Code of country (2 characters)
640
     * @param   string    $iso          ISO of country (3 characters)
641
     * @param   string    $lang         Code of the language the name of the country must be translated to
642
     * @return  Object                  Object with cleaned properties
643
     *
644
     * @throws RestException
645
     */
646
    private function _fetchCcountry($id, $code = '', $iso = '', $lang = '')
647
    {
648
        $country = new Ccountry($this->db);
649
650
        $result = $country->fetch($id, $code, $iso);
651
652
        if ($result < 0) {
653
            throw new RestException(503, 'Error when retrieving country : ' . $country->error);
654
        } elseif ($result == 0) {
655
            throw new RestException(404, 'Country not found');
656
        }
657
658
        $this->translateLabel($country, $lang, 'Country');
659
660
        return $this->_cleanObjectDatas($country);
661
    }
662
663
    /**
664
     * Get the list of delivery times.
665
     *
666
     * @param string    $sortfield      Sort field
667
     * @param string    $sortorder      Sort order
668
     * @param int       $limit          Number of items per page
669
     * @param int       $page           Page number {@min 0}
670
     * @param int       $active         Delivery times is active or not {@min 0} {@max 1}
671
     * @param string    $sqlfilters     SQL criteria to filter with.
672
     *
673
     * @url     GET dictionary/availability
674
     *
675
     * @return array [List of availability]
676
     *
677
     * @throws  RestException   400     Bad value for sqlfilters
678
     * @throws  RestException   403     Access denied
679
     * @throws  RestException   503     Error when retrieving list of availabilities
680
     */
681
    public function getAvailability($sortfield = "code", $sortorder = 'ASC', $limit = 100, $page = 0, $active = 1, $sqlfilters = '')
682
    {
683
        $list = array();
684
685
        if (!DolibarrApiAccess::$user->hasRight('commande', 'lire')) {
686
            throw new RestException(403);
687
        }
688
689
        $sql = "SELECT rowid, code, label";
690
        $sql .= " FROM " . MAIN_DB_PREFIX . "c_availability as t";
691
        $sql .= " WHERE t.active = " . ((int) $active);
692
        // Add sql filters
693
        if ($sqlfilters) {
694
            $errormessage = '';
695
            $sql .= forgeSQLFromUniversalSearchCriteria($sqlfilters, $errormessage);
696
            if ($errormessage) {
697
                throw new RestException(400, 'Error when validating parameter sqlfilters -> ' . $errormessage);
698
            }
699
        }
700
701
702
        $sql .= $this->db->order($sortfield, $sortorder);
703
704
        if ($limit) {
705
            if ($page < 0) {
706
                $page = 0;
707
            }
708
            $offset = $limit * $page;
709
710
            $sql .= $this->db->plimit($limit, $offset);
711
        }
712
713
        $result = $this->db->query($sql);
714
715
        if ($result) {
716
            $num = $this->db->num_rows($result);
717
            $min = min($num, ($limit <= 0 ? $num : $limit));
718
            for ($i = 0; $i < $min; $i++) {
719
                $list[] = $this->db->fetch_object($result);
720
            }
721
        } else {
722
            throw new RestException(503, $this->db->lasterror());
723
        }
724
725
        return $list;
726
    }
727
728
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
729
    /**
730
     * Clean sensible object datas
731
     *
732
     * @param   Object    $object       Object to clean
733
     * @return  Object                  Object with cleaned properties
734
     */
735
    protected function _cleanObjectDatas($object)
736
    {
737
		// phpcs:enable
738
        $object = parent::_cleanObjectDatas($object);
739
740
        unset($object->error);
741
        unset($object->errors);
742
743
        return $object;
744
    }
745
746
    /**
747
     * Translate the name of the object to the given language.
748
     *
749
     * @param object   $object    Object with label to translate
750
     * @param string   $lang      Code of the language the name of the object must be translated to
751
     * @param string   $prefix    Prefix for translation key
752
     * @param array    $dict      Array of dictionary for translation
753
     * @return void
754
     */
755
    private function translateLabel($object, $lang, $prefix = 'Country', $dict = array('dict'))
756
    {
757
        if (!empty($lang)) {
758
            // Load the translations if this is a new language.
759
            if ($this->translations == null || $this->translations->getDefaultLang() !== $lang) {
760
                global $conf;
761
                $this->translations = new Translate('', $conf);
0 ignored issues
show
Bug introduced by
The type Dolibarr\Code\Api\Api\Translate was not found. Did you mean Translate? If so, make sure to prefix the type with \.
Loading history...
762
                $this->translations->setDefaultLang($lang);
763
                $this->translations->loadLangs($dict);
764
            }
765
            if ($object->code) {
766
                $key = $prefix . $object->code;
767
768
                $translation = $this->translations->trans($key);
769
                if ($translation != $key) {
770
                    $object->label = html_entity_decode($translation);
771
                }
772
            }
773
        }
774
    }
775
776
    /**
777
     * Get the list of events types.
778
     *
779
     * @param string    $sortfield  Sort field
780
     * @param string    $sortorder  Sort order
781
     * @param int       $limit      Number of items per page
782
     * @param int       $page       Page number (starting from zero)
783
     * @param string    $type       To filter on type of event
784
     * @param string    $module     To filter on module events
785
     * @param int       $active     Event's type is active or not {@min 0} {@max 1}
786
     * @param string    $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.code:like:'A%') and (t.active:>=:0)"
787
     * @return array                List of events types
788
     *
789
     * @url     GET dictionary/event_types
790
     *
791
     * @throws  RestException   400     Bad value for sqlfilters
792
     * @throws  RestException   503     Error when retrieving list of events types
793
     */
794
    public function getListOfEventTypes($sortfield = "code", $sortorder = 'ASC', $limit = 100, $page = 0, $type = '', $module = '', $active = 1, $sqlfilters = '')
795
    {
796
        $list = array();
797
798
        $sql = "SELECT id, code, type, libelle as label, module";
799
        $sql .= " FROM " . MAIN_DB_PREFIX . "c_actioncomm as t";
800
        $sql .= " WHERE t.active = " . ((int) $active);
801
        if ($type) {
802
            $sql .= " AND t.type LIKE '%" . $this->db->escape($type) . "%'";
803
        }
804
        if ($module) {
805
            $sql .= " AND t.module LIKE '%" . $this->db->escape($module) . "%'";
806
        }
807
        // Add sql filters
808
        if ($sqlfilters) {
809
            $errormessage = '';
810
            $sql .= forgeSQLFromUniversalSearchCriteria($sqlfilters, $errormessage);
811
            if ($errormessage) {
812
                throw new RestException(400, 'Error when validating parameter sqlfilters -> ' . $errormessage);
813
            }
814
        }
815
816
817
        $sql .= $this->db->order($sortfield, $sortorder);
818
819
        if ($limit) {
820
            if ($page < 0) {
821
                $page = 0;
822
            }
823
            $offset = $limit * $page;
824
825
            $sql .= $this->db->plimit($limit, $offset);
826
        }
827
828
        $result = $this->db->query($sql);
829
830
        if ($result) {
831
            $num = $this->db->num_rows($result);
832
            $min = min($num, ($limit <= 0 ? $num : $limit));
833
            for ($i = 0; $i < $min; $i++) {
834
                $list[] = $this->db->fetch_object($result);
835
            }
836
        } else {
837
            throw new RestException(503, 'Error when retrieving list of events types : ' . $this->db->lasterror());
838
        }
839
840
        return $list;
841
    }
842
843
844
    /**
845
     * Get the list of Expense Report types.
846
     *
847
     * @param string    $sortfield  Sort field
848
     * @param string    $sortorder  Sort order
849
     * @param int       $limit      Number of items per page
850
     * @param int       $page       Page number (starting from zero)
851
     * @param string    $module     To filter on module
852
     * @param int       $active     Event's type is active or not {@min 0} {@max 1}
853
     * @param string    $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.code:like:'A%') and (t.active:>=:0)"
854
     * @return array                List of expense report types
855
     *
856
     * @url     GET dictionary/expensereport_types
857
     *
858
     * @throws  RestException   400     Bad value for sqlfilters
859
     * @throws  RestException   503     Error when retrieving list of expense report types
860
     */
861
    public function getListOfExpenseReportsTypes($sortfield = "code", $sortorder = 'ASC', $limit = 100, $page = 0, $module = '', $active = 1, $sqlfilters = '')
862
    {
863
        $list = array();
864
865
        $sql = "SELECT id, code, label, accountancy_code, active, module, position";
866
        $sql .= " FROM " . MAIN_DB_PREFIX . "c_type_fees as t";
867
        $sql .= " WHERE t.active = " . ((int) $active);
868
        if ($module) {
869
            $sql .= " AND t.module LIKE '%" . $this->db->escape($module) . "%'";
870
        }
871
        // Add sql filters
872
        if ($sqlfilters) {
873
            $errormessage = '';
874
            $sql .= forgeSQLFromUniversalSearchCriteria($sqlfilters, $errormessage);
875
            if ($errormessage) {
876
                throw new RestException(400, 'Error when validating parameter sqlfilters -> ' . $errormessage);
877
            }
878
        }
879
880
881
        $sql .= $this->db->order($sortfield, $sortorder);
882
883
        if ($limit) {
884
            if ($page < 0) {
885
                $page = 0;
886
            }
887
            $offset = $limit * $page;
888
889
            $sql .= $this->db->plimit($limit, $offset);
890
        }
891
892
        $result = $this->db->query($sql);
893
894
        if ($result) {
895
            $num = $this->db->num_rows($result);
896
            $min = min($num, ($limit <= 0 ? $num : $limit));
897
            for ($i = 0; $i < $min; $i++) {
898
                $list[] = $this->db->fetch_object($result);
899
            }
900
        } else {
901
            throw new RestException(503, 'Error when retrieving list of expense report types : ' . $this->db->lasterror());
902
        }
903
904
        return $list;
905
    }
906
907
908
    /**
909
     * Get the list of contacts types.
910
     *
911
     * @param string    $sortfield  Sort field
912
     * @param string    $sortorder  Sort order
913
     * @param int       $limit      Number of items per page
914
     * @param int       $page       Page number (starting from zero)
915
     * @param string    $type       To filter on type of contact
916
     * @param string    $module     To filter on module contacts
917
     * @param int       $active     Contact's type is active or not {@min 0} {@max 1}
918
     * @param string    $lang       Code of the language the label of the civility must be translated to
919
     * @param string    $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.code:like:'A%') and (t.active:>=:0)"
920
     * @return array      List of Contacts types
921
     *
922
     * @url     GET dictionary/contact_types
923
     *
924
     * @throws  RestException   400     Bad value for sqlfilters
925
     * @throws  RestException   503     Error when retrieving list of contacts types
926
     */
927
    public function getListOfContactTypes($sortfield = "code", $sortorder = 'ASC', $limit = 100, $page = 0, $type = '', $module = '', $active = 1, $lang = '', $sqlfilters = '')
928
    {
929
        $list = array();
930
931
        $sql = "SELECT rowid, code, element as type, libelle as label, source, module, position";
932
        $sql .= " FROM " . MAIN_DB_PREFIX . "c_type_contact as t";
933
        $sql .= " WHERE t.active = " . ((int) $active);
934
        if ($type) {
935
            $sql .= " AND type LIKE '%" . $this->db->escape($type) . "%'";
936
        }
937
        if ($module) {
938
            $sql .= " AND t.module LIKE '%" . $this->db->escape($module) . "%'";
939
        }
940
        // Add sql filters
941
        if ($sqlfilters) {
942
            $errormessage = '';
943
            $sql .= forgeSQLFromUniversalSearchCriteria($sqlfilters, $errormessage);
944
            if ($errormessage) {
945
                throw new RestException(400, 'Error when validating parameter sqlfilters -> ' . $errormessage);
946
            }
947
        }
948
949
950
        $sql .= $this->db->order($sortfield, $sortorder);
951
952
        if ($limit) {
953
            if ($page < 0) {
954
                $page = 0;
955
            }
956
            $offset = $limit * $page;
957
958
            $sql .= $this->db->plimit($limit, $offset);
959
        }
960
961
        $result = $this->db->query($sql);
962
963
        if ($result) {
964
            $num = $this->db->num_rows($result);
965
            $min = min($num, ($limit <= 0 ? $num : $limit));
966
            for ($i = 0; $i < $min; $i++) {
967
                $contact_type = $this->db->fetch_object($result);
968
                $this->translateLabel($contact_type, $lang, 'TypeContact_' . $contact_type->type . '_' . $contact_type->source . '_', array("eventorganization", "resource", "projects", "contracts", "bills", "orders", "agenda", "propal", "stocks", "supplier_proposal", "interventions", "sendings", "ticket"));
969
                $list[] = $contact_type;
970
            }
971
        } else {
972
            throw new RestException(503, 'Error when retrieving list of contacts types : ' . $this->db->lasterror());
973
        }
974
975
        return $list;
976
    }
977
978
    /**
979
     * Get the list of civilities.
980
     *
981
     * @param string    $sortfield  Sort field
982
     * @param string    $sortorder  Sort order
983
     * @param int       $limit      Number of items per page
984
     * @param int       $page       Page number (starting from zero)
985
     * @param string    $module     To filter on module events
986
     * @param int       $active     Civility is active or not {@min 0} {@max 1}
987
     * @param string    $lang       Code of the language the label of the civility must be translated to
988
     * @param string    $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.code:like:'A%') and (t.active:>=:0)"
989
     * @return array        List of civility types
990
     *
991
     * @url     GET dictionary/civilities
992
     *
993
     * @throws  RestException   400     Bad value for sqlfilters
994
     * @throws  RestException   503     Error when retrieving list of civilities
995
     */
996
    public function getListOfCivilities($sortfield = "code", $sortorder = 'ASC', $limit = 100, $page = 0, $module = '', $active = 1, $lang = '', $sqlfilters = '')
997
    {
998
        $list = array();
999
1000
        $sql = "SELECT rowid, code, label, module";
1001
        $sql .= " FROM " . MAIN_DB_PREFIX . "c_civility as t";
1002
        $sql .= " WHERE t.active = " . ((int) $active);
1003
        if ($module) {
1004
            $sql .= " AND t.module LIKE '%" . $this->db->escape($module) . "%'";
1005
        }
1006
        // Add sql filters
1007
        if ($sqlfilters) {
1008
            $errormessage = '';
1009
            $sql .= forgeSQLFromUniversalSearchCriteria($sqlfilters, $errormessage);
1010
            if ($errormessage) {
1011
                throw new RestException(400, 'Error when validating parameter sqlfilters -> ' . $errormessage);
1012
            }
1013
        }
1014
1015
1016
        $sql .= $this->db->order($sortfield, $sortorder);
1017
1018
        if ($limit) {
1019
            if ($page < 0) {
1020
                $page = 0;
1021
            }
1022
            $offset = $limit * $page;
1023
1024
            $sql .= $this->db->plimit($limit, $offset);
1025
        }
1026
1027
        $result = $this->db->query($sql);
1028
1029
        if ($result) {
1030
            $num = $this->db->num_rows($result);
1031
            $min = min($num, ($limit <= 0 ? $num : $limit));
1032
            for ($i = 0; $i < $min; $i++) {
1033
                $civility = $this->db->fetch_object($result);
1034
                $this->translateLabel($civility, $lang, 'Civility', array('dict'));
1035
                $list[] = $civility;
1036
            }
1037
        } else {
1038
            throw new RestException(503, 'Error when retrieving list of civility : ' . $this->db->lasterror());
1039
        }
1040
1041
        return $list;
1042
    }
1043
1044
    /**
1045
     * Get the list of currencies.
1046
     *
1047
     * @param int       $multicurrency  Multicurrency rates (0: no multicurrency, 1: last rate, 2: all rates) {@min 0} {@max 2}
1048
     * @param string    $sortfield  Sort field
1049
     * @param string    $sortorder  Sort order
1050
     * @param int       $limit      Number of items per page
1051
     * @param int       $page       Page number (starting from zero)
1052
     * @param int       $active     Payment term is active or not {@min 0} {@max 1}
1053
     * @param string    $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.code:like:'A%') and (t.active:>=:0)"
1054
     * @return array                List of currencies
1055
     *
1056
     * @url     GET dictionary/currencies
1057
     *
1058
     * @throws  RestException   400     Bad value for sqlfilters
1059
     * @throws  RestException   503     Error when retrieving list of currencies
1060
     */
1061
    public function getListOfCurrencies($multicurrency = 0, $sortfield = "code_iso", $sortorder = 'ASC', $limit = 100, $page = 0, $active = 1, $sqlfilters = '')
1062
    {
1063
        $list = array();
1064
        $sql = "SELECT t.code_iso, t.label, t.unicode";
1065
        if (!empty($multicurrency)) {
1066
            $sql .= " , cr.date_sync, cr.rate ";
1067
        }
1068
        $sql .= " FROM " . MAIN_DB_PREFIX . "c_currencies as t";
1069
        if (!empty($multicurrency)) {
1070
            $sql .= " JOIN " . MAIN_DB_PREFIX . "multicurrency as m ON m.code=t.code_iso";
1071
            $sql .= " JOIN " . MAIN_DB_PREFIX . "multicurrency_rate as cr ON (m.rowid = cr.fk_multicurrency)";
1072
        }
1073
        $sql .= " WHERE t.active = " . ((int) $active);
1074
        if (!empty($multicurrency)) {
1075
            $sql .= " AND m.entity IN (" . getEntity('multicurrency') . ")";
1076
            if (!empty($multicurrency) && $multicurrency != 2) {
1077
                $sql .= " AND cr.date_sync = (SELECT MAX(cr2.date_sync) FROM " . MAIN_DB_PREFIX . "multicurrency_rate AS cr2 WHERE cr2.fk_multicurrency = m.rowid)";
1078
            }
1079
        }
1080
1081
        // Add sql filters
1082
        if ($sqlfilters) {
1083
            $errormessage = '';
1084
            $sql .= forgeSQLFromUniversalSearchCriteria($sqlfilters, $errormessage);
1085
            if ($errormessage) {
1086
                throw new RestException(400, 'Error when validating parameter sqlfilters -> ' . $errormessage);
1087
            }
1088
        }
1089
1090
1091
        $sql .= $this->db->order($sortfield, $sortorder);
1092
1093
        if ($limit) {
1094
            if ($page < 0) {
1095
                $page = 0;
1096
            }
1097
            $offset = $limit * $page;
1098
1099
            $sql .= $this->db->plimit($limit, $offset);
1100
        }
1101
1102
        $result = $this->db->query($sql);
1103
1104
        if ($result) {
1105
            $num = $this->db->num_rows($result);
1106
            $min = min($num, ($limit <= 0 ? $num : $limit));
1107
            for ($i = 0; $i < $min; $i++) {
1108
                $list[] = $this->db->fetch_object($result);
1109
            }
1110
        } else {
1111
            throw new RestException(503, 'Error when retrieving list of currency : ' . $this->db->lasterror());
1112
        }
1113
1114
        return $list;
1115
    }
1116
1117
    /**
1118
     * Get the list of extra fields.
1119
     *
1120
     * @param string    $sortfield  Sort field
1121
     * @param string    $sortorder  Sort order
1122
     * @param string    $elementtype       Type of element ('adherent', 'commande', 'thirdparty', 'facture', 'propal', 'product', ...)
1123
     * @param string    $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.label:like:'SO-%')"
1124
     * @return array                List of extra fields
1125
     *
1126
     * @url     GET extrafields
1127
     *
1128
     * @throws  RestException   400     Bad value for sqlfilters
1129
     * @throws  RestException   503     Error when retrieving list of extra fields
1130
     */
1131
    public function getListOfExtrafields($sortfield = "t.pos", $sortorder = 'ASC', $elementtype = '', $sqlfilters = '')
1132
    {
1133
        $list = array();
1134
1135
        if (!DolibarrApiAccess::$user->admin) {
1136
            throw new RestException(403, 'Only an admin user can get list of extrafields');
1137
        }
1138
1139
        if ($elementtype == 'thirdparty') {
1140
            $elementtype = 'societe';
1141
        }
1142
        if ($elementtype == 'contact') {
1143
            $elementtype = 'socpeople';
1144
        }
1145
1146
        $sql = "SELECT t.rowid as id, t.name, t.entity, t.elementtype, t.label, t.type, t.size, t.fieldcomputed, t.fielddefault,";
1147
        $sql .= " t.fieldunique, t.fieldrequired, t.perms, t.enabled, t.pos, t.alwayseditable, t.param, t.list, t.printable,";
1148
        $sql .= " t.totalizable, t.langs, t.help, t.css, t.cssview, t.fk_user_author, t.fk_user_modif, t.datec, t.tms";
1149
        $sql .= " FROM " . MAIN_DB_PREFIX . "extrafields as t";
1150
        $sql .= " WHERE t.entity IN (" . getEntity('extrafields') . ")";
1151
        if (!empty($elementtype)) {
1152
            $sql .= " AND t.elementtype = '" . $this->db->escape($elementtype) . "'";
1153
        }
1154
        // Add sql filters
1155
        if ($sqlfilters) {
1156
            $errormessage = '';
1157
            $sql .= forgeSQLFromUniversalSearchCriteria($sqlfilters, $errormessage);
1158
            if ($errormessage) {
1159
                throw new RestException(400, 'Error when validating parameter sqlfilters -> ' . $errormessage);
1160
            }
1161
        }
1162
1163
        $sql .= $this->db->order($sortfield, $sortorder);
1164
1165
        $resql = $this->db->query($sql);
1166
        if ($resql) {
1167
            if ($this->db->num_rows($resql)) {
1168
                while ($tab = $this->db->fetch_object($resql)) {
1169
                    // New usage
1170
                    $list[$tab->elementtype][$tab->name]['id'] = $tab->id;
1171
                    $list[$tab->elementtype][$tab->name]['type'] = $tab->type;
1172
                    $list[$tab->elementtype][$tab->name]['label'] = $tab->label;
1173
                    $list[$tab->elementtype][$tab->name]['size'] = $tab->size;
1174
                    $list[$tab->elementtype][$tab->name]['elementtype'] = $tab->elementtype;
1175
                    $list[$tab->elementtype][$tab->name]['default'] = $tab->fielddefault;
1176
                    $list[$tab->elementtype][$tab->name]['computed'] = $tab->fieldcomputed;
1177
                    $list[$tab->elementtype][$tab->name]['unique'] = $tab->fieldunique;
1178
                    $list[$tab->elementtype][$tab->name]['required'] = $tab->fieldrequired;
1179
                    $list[$tab->elementtype][$tab->name]['param'] = ($tab->param ? jsonOrUnserialize($tab->param) : '');    // This may be a string encoded with serialise() or json_encode()
1180
                    $list[$tab->elementtype][$tab->name]['pos'] = $tab->pos;
1181
                    $list[$tab->elementtype][$tab->name]['alwayseditable'] = $tab->alwayseditable;
1182
                    $list[$tab->elementtype][$tab->name]['perms'] = $tab->perms;
1183
                    $list[$tab->elementtype][$tab->name]['list'] = $tab->list;
1184
                    $list[$tab->elementtype][$tab->name]['printable'] = $tab->printable;
1185
                    $list[$tab->elementtype][$tab->name]['totalizable'] = $tab->totalizable;
1186
                    $list[$tab->elementtype][$tab->name]['langs'] = $tab->langs;
1187
                    $list[$tab->elementtype][$tab->name]['help'] = $tab->help;
1188
                    $list[$tab->elementtype][$tab->name]['css'] = $tab->css;
1189
                    $list[$tab->elementtype][$tab->name]['cssview'] = $tab->cssview;
1190
                    $list[$tab->elementtype][$tab->name]['csslist'] = $tab->csslist;
1191
                    $list[$tab->elementtype][$tab->name]['fk_user_author'] = $tab->fk_user_author;
1192
                    $list[$tab->elementtype][$tab->name]['fk_user_modif'] = $tab->fk_user_modif;
1193
                    $list[$tab->elementtype][$tab->name]['datec'] = $tab->datec;
1194
                    $list[$tab->elementtype][$tab->name]['tms'] = $tab->tms;
1195
                }
1196
            }
1197
        } else {
1198
            throw new RestException(503, 'Error when retrieving list of extra fields : ' . $this->db->lasterror());
1199
        }
1200
1201
        return $list;
1202
    }
1203
1204
    /**
1205
     * Delete extrafield
1206
     *
1207
     * @param   string     $attrname         extrafield attrname
1208
     * @param   string     $elementtype      extrafield elementtype
1209
     * @return  array
1210
     *
1211
     * @url     DELETE extrafields/{elementtype}/{attrname}
1212
     *
1213
     */
1214
    public function deleteExtrafieldsFromNames($attrname, $elementtype)
1215
    {
1216
        if (!DolibarrApiAccess::$user->admin) {
1217
            throw new RestException(403, 'Only an admin user can delete an extrafield by attrname and elementtype');
1218
        }
1219
1220
        $extrafields = new ExtraFields($this->db);
0 ignored issues
show
Bug introduced by
The type Dolibarr\Code\Api\Api\ExtraFields was not found. Did you mean ExtraFields? If so, make sure to prefix the type with \.
Loading history...
1221
1222
        $result = $extrafields->fetch_name_optionals_label($elementtype, false, $attrname);
1223
        if (!$result) {
1224
            throw new RestException(404, 'Extrafield not found from attrname and elementtype');
1225
        }
1226
1227
        if (!$extrafields->delete($attrname, $elementtype)) {
1228
            throw new RestException(500, 'Error when delete extrafield : ' . $extrafields->error);
1229
        }
1230
1231
        return array(
1232
            'success' => array(
1233
                'code' => 200,
1234
                'message' => 'Extrafield deleted from attrname and elementtype'
1235
            )
1236
        );
1237
    }
1238
1239
1240
1241
    /** get Extrafield object
1242
     *
1243
     * @param   string  $attrname       extrafield attrname
1244
     * @param   string  $elementtype    extrafield elementtype
1245
     * @return  array                   List of extra fields
1246
     *
1247
     * @url     GET     extrafields/{elementtype}/{attrname}
1248
     *
1249
     * @suppress PhanPluginUnknownArrayMethodParamType  Luracast limitation
1250
     *
1251
     */
1252
    public function getExtrafields($attrname, $elementtype)
1253
    {
1254
        $answer = array();
1255
1256
        if (!DolibarrApiAccess::$user->admin) {
1257
            throw new RestException(403, 'Only an admin user can get list of extrafields');
1258
        }
1259
1260
        if ($elementtype == 'thirdparty') {
1261
            $elementtype = 'societe';
1262
        }
1263
        if ($elementtype == 'contact') {
1264
            $elementtype = 'socpeople';
1265
        }
1266
1267
        $sql = "SELECT t.rowid as id, t.name, t.entity, t.elementtype, t.label, t.type, t.size, t.fieldcomputed, t.fielddefault,";
1268
        $sql .= " t.fieldunique, t.fieldrequired, t.perms, t.enabled, t.pos, t.alwayseditable, t.param, t.list, t.printable,";
1269
        $sql .= " t.totalizable, t.langs, t.help, t.css, t.cssview, t.fk_user_author, t.fk_user_modif, t.datec, t.tms";
1270
        $sql .= " FROM " . MAIN_DB_PREFIX . "extrafields as t";
1271
        $sql .= " WHERE t.entity IN (" . getEntity('extrafields') . ")";
1272
        $sql .= " AND t.elementtype = '" . $this->db->escape($elementtype) . "'";
1273
        $sql .= " AND t.name = '" . $this->db->escape($attrname) . "'";
1274
1275
        $resql = $this->db->query($sql);
1276
        if ($resql) {
1277
            if ($this->db->num_rows($resql)) {
1278
                while ($tab = $this->db->fetch_object($resql)) {
1279
                    // New usage
1280
                    $answer[$tab->elementtype][$tab->name]['id'] = $tab->id;
1281
                    $answer[$tab->elementtype][$tab->name]['type'] = $tab->type;
1282
                    $answer[$tab->elementtype][$tab->name]['label'] = $tab->label;
1283
                    $answer[$tab->elementtype][$tab->name]['size'] = $tab->size;
1284
                    $answer[$tab->elementtype][$tab->name]['elementtype'] = $tab->elementtype;
1285
                    $answer[$tab->elementtype][$tab->name]['default'] = $tab->fielddefault;
1286
                    $answer[$tab->elementtype][$tab->name]['computed'] = $tab->fieldcomputed;
1287
                    $answer[$tab->elementtype][$tab->name]['unique'] = $tab->fieldunique;
1288
                    $answer[$tab->elementtype][$tab->name]['required'] = $tab->fieldrequired;
1289
                    $answer[$tab->elementtype][$tab->name]['param'] = ($tab->param ? jsonOrUnserialize($tab->param) : '');  // This may be a string encoded with serialise() or json_encode()
1290
                    $answer[$tab->elementtype][$tab->name]['pos'] = $tab->pos;
1291
                    $answer[$tab->elementtype][$tab->name]['alwayseditable'] = $tab->alwayseditable;
1292
                    $answer[$tab->elementtype][$tab->name]['perms'] = $tab->perms;
1293
                    $answer[$tab->elementtype][$tab->name]['list'] = $tab->list;
1294
                    $answer[$tab->elementtype][$tab->name]['printable'] = $tab->printable;
1295
                    $answer[$tab->elementtype][$tab->name]['totalizable'] = $tab->totalizable;
1296
                    $answer[$tab->elementtype][$tab->name]['langs'] = $tab->langs;
1297
                    $answer[$tab->elementtype][$tab->name]['help'] = $tab->help;
1298
                    $answer[$tab->elementtype][$tab->name]['css'] = $tab->css;
1299
                    $answer[$tab->elementtype][$tab->name]['cssview'] = $tab->cssview;
1300
                    $answer[$tab->elementtype][$tab->name]['csslist'] = $tab->csslist;
1301
                    $answer[$tab->elementtype][$tab->name]['fk_user_author'] = $tab->fk_user_author;
1302
                    $answer[$tab->elementtype][$tab->name]['fk_user_modif'] = $tab->fk_user_modif;
1303
                    $answer[$tab->elementtype][$tab->name]['datec'] = $tab->datec;
1304
                    $answer[$tab->elementtype][$tab->name]['tms'] = $tab->tms;
1305
                }
1306
            } else {
1307
                throw new RestException(404, 'Extrafield not found from attrname and elementtype');
1308
            }
1309
        } else {
1310
            throw new RestException(503, 'Error when retrieving list of extra fields : ' . $this->db->lasterror());
1311
        }
1312
1313
        return $answer;
1314
    }
1315
1316
    /**
1317
     * Create Extrafield object
1318
     *
1319
     * @param   string  $attrname       extrafield attrname
1320
     * @param   string  $elementtype    extrafield elementtype
1321
     * @param   array   $request_data   Request datas
1322
     * @return  int                     ID of extrafield
1323
     *
1324
     * @url     POST    extrafields/{elementtype}/{attrname}
1325
     *
1326
     * @suppress PhanPluginUnknownArrayMethodParamType  Luracast limitation
1327
     *
1328
     */
1329
    public function postExtrafields($attrname, $elementtype, $request_data = null)
1330
    {
1331
        if (!DolibarrApiAccess::$user->admin) {
1332
            throw new RestException(403, 'Only an admin user can create an extrafield');
1333
        }
1334
1335
        $extrafields = new ExtraFields($this->db);
1336
1337
        $result = $extrafields->fetch_name_optionals_label($elementtype, false, $attrname);
1338
        if ($result) {
1339
            throw new RestException(409, 'Duplicate extrafield already found from attrname and elementtype');
1340
        }
1341
1342
        // Check mandatory fields is not working despise being a modified copy from api_thirdparties.class.php
1343
        // $result = $this->_validateExtrafields($request_data, $extrafields);
1344
1345
        foreach ($request_data as $field => $value) {
1346
            $extrafields->$field = $this->_checkValForAPI($field, $value, $extrafields);
1347
        }
1348
1349
        $entity = DolibarrApiAccess::$user->entity;
1350
        if (empty($entity)) {
1351
            $entity = 1;
1352
        }
1353
1354
        // built in validation
1355
        $enabled = 1; // hardcoded because it seems to always be 1 in every row in the database
1356
1357
        if ($request_data['label']) {
1358
            $label = $request_data['label'];
1359
        } else {
1360
            throw new RestException(400, "label field absent in json at root level");
1361
        }
1362
1363
        $alwayseditable = $request_data['alwayseditable'];
1364
        $default_value = $request_data['default_value'];
1365
        $totalizable = $request_data['totalizable'];
1366
        $printable = $request_data['printable'];
1367
        $required = $request_data['required'];
1368
        $langfile = $request_data['langfile'];
1369
        $computed = $request_data['computed'];
1370
        $unique = $request_data['unique'];
1371
        $param = $request_data['param'];
1372
        $perms = $request_data['perms'];
1373
        $size = $request_data['size'];
1374
        $type = $request_data['type'];
1375
        $list = $request_data['list'];
1376
        $help = $request_data['help'];
1377
        $pos = $request_data['pos'];
1378
        $moreparams = array();
1379
1380
        if (0 > $extrafields->addExtraField($attrname, $label, $type, $pos, $size, $elementtype, $unique, $required, $default_value, $param, $alwayseditable, $perms, $list, $help, $computed, $entity, $langfile, $enabled, $totalizable, $printable, $moreparams)) {
1381
            throw new RestException(500, 'Error creating extrafield', array_merge(array($extrafields->errno), $extrafields->errors));
1382
        }
1383
1384
        $sql = "SELECT t.rowid as id";
1385
        $sql .= " FROM " . MAIN_DB_PREFIX . "extrafields as t";
1386
        $sql .= " WHERE elementtype = '" . $this->db->escape($elementtype) . "'";
1387
        $sql .= " AND name = '" . $this->db->escape($attrname) . "'";
1388
1389
        $resql = $this->db->query($sql);
1390
        if ($resql) {
1391
            if ($this->db->num_rows($resql)) {
1392
                $tab = $this->db->fetch_object($resql);
1393
                $id = (int) $tab->id;
1394
            } else {
1395
                $id = (int) -1;
1396
            }
1397
        } else {
1398
            $id = (int) -2;
1399
        }
1400
1401
        return $id;
1402
    }
1403
1404
    /**
1405
1406
     * Update Extrafield object
1407
     *
1408
     * @param   string  $attrname       extrafield attrname
1409
     * @param   string  $elementtype    extrafield elementtype
1410
     * @param   array   $request_data   Request datas
1411
     * @return  int                     ID of extrafield
1412
     *
1413
     * @url     PUT     extrafields/{elementtype}/{attrname}
1414
     *
1415
     * @suppress PhanPluginUnknownArrayMethodParamType  Luracast limitation
1416
     *
1417
     */
1418
    public function updateExtrafields($attrname, $elementtype, $request_data = null)
1419
    {
1420
        if (!DolibarrApiAccess::$user->admin) {
1421
            throw new RestException(403, 'Only an admin user can create an extrafield');
1422
        }
1423
1424
        $extrafields = new ExtraFields($this->db);
1425
1426
        $result = $extrafields->fetch_name_optionals_label($elementtype, false, $attrname);
1427
        if (!$result) {
1428
            throw new RestException(404, 'Extrafield not found from attrname and elementtype');
1429
        }
1430
1431
        foreach ($request_data as $field => $value) {
1432
            $extrafields->$field = $this->_checkValForAPI($field, $value, $extrafields);
1433
        }
1434
1435
        $entity = DolibarrApiAccess::$user->entity;
1436
        if (empty($entity)) {
1437
            $entity = 1;
1438
        }
1439
1440
        // built in validation
1441
        $enabled = 1; // hardcoded because it seems to always be 1 in every row in the database
1442
        if ($request_data['label']) {
1443
            $label = $request_data['label'];
1444
        } else {
1445
            throw new RestException(400, "label field absent in json at root level");
1446
        }
1447
1448
        $alwayseditable = $request_data['alwayseditable'];
1449
        $default_value = $request_data['default_value'];
1450
        $totalizable = $request_data['totalizable'];
1451
        $printable = $request_data['printable'];
1452
        $required = $request_data['required'];
1453
        $langfile = $request_data['langfile'];
1454
        $computed = $request_data['computed'];
1455
        $unique = $request_data['unique'];
1456
        $param = $request_data['param'];
1457
        $perms = $request_data['perms'];
1458
        $size = $request_data['size'];
1459
        $type = $request_data['type'];
1460
        $list = $request_data['list'];
1461
        $help = $request_data['help'];
1462
        $pos = $request_data['pos'];
1463
        $moreparams = array();
1464
1465
        dol_syslog(get_class($this) . '::updateExtraField', LOG_DEBUG);
1466
        if (0 > $extrafields->updateExtraField($attrname, $label, $type, $pos, $size, $elementtype, $unique, $required, $default_value, $param, $alwayseditable, $perms, $list, $help, $computed, $entity, $langfile, $enabled, $totalizable, $printable, $moreparams)) {
1467
            throw new RestException(500, 'Error updating extrafield', array_merge(array($extrafields->errno), $extrafields->errors));
1468
        }
1469
1470
        $sql = "SELECT t.rowid as id";
1471
        $sql .= " FROM " . MAIN_DB_PREFIX . "extrafields as t";
1472
        $sql .= " WHERE elementtype = '" . $this->db->escape($elementtype) . "'";
1473
        $sql .= " AND name = '" . $this->db->escape($attrname) . "'";
1474
1475
        $resql = $this->db->query($sql);
1476
        if ($resql) {
1477
            if ($this->db->num_rows($resql)) {
1478
                $tab = $this->db->fetch_object($resql);
1479
                $id = (int) $tab->id;
1480
            } else {
1481
                $id = (int) -1;
1482
            }
1483
        } else {
1484
            $id = (int) -2;
1485
        }
1486
1487
        return $id;
1488
    }
1489
1490
    /**
1491
     * Get the list of towns.
1492
     *
1493
     * @param string    $sortfield  Sort field
1494
     * @param string    $sortorder  Sort order
1495
     * @param int       $limit      Number of items per page
1496
     * @param int       $page       Page number (starting from zero)
1497
     * @param string    $zipcode    To filter on zipcode
1498
     * @param string    $town       To filter on city name
1499
     * @param int       $active     Town is active or not {@min 0} {@max 1}
1500
     * @param string    $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.code:like:'A%') and (t.active:>=:0)"
1501
     * @return array                List of towns
1502
     *
1503
     * @url     GET dictionary/towns
1504
     *
1505
     * @throws  RestException   400     Bad value for sqlfilters
1506
     * @throws  RestException   503     Error when retrieving list of towns
1507
     */
1508
    public function getListOfTowns($sortfield = "zip,town", $sortorder = 'ASC', $limit = 100, $page = 0, $zipcode = '', $town = '', $active = 1, $sqlfilters = '')
1509
    {
1510
        $list = array();
1511
1512
        $sql = "SELECT rowid AS id, zip, town, fk_county, fk_pays AS fk_country";
1513
        $sql .= " FROM " . MAIN_DB_PREFIX . "c_ziptown as t";
1514
        $sql .= " WHERE t.active = " . ((int) $active);
1515
        if ($zipcode) {
1516
            $sql .= " AND t.zip LIKE '%" . $this->db->escape($zipcode) . "%'";
1517
        }
1518
        if ($town) {
1519
            $sql .= " AND t.town LIKE '%" . $this->db->escape($town) . "%'";
1520
        }
1521
        // Add sql filters
1522
        if ($sqlfilters) {
1523
            $errormessage = '';
1524
            $sql .= forgeSQLFromUniversalSearchCriteria($sqlfilters, $errormessage);
1525
            if ($errormessage) {
1526
                throw new RestException(400, 'Error when validating parameter sqlfilters -> ' . $errormessage);
1527
            }
1528
        }
1529
1530
1531
        $sql .= $this->db->order($sortfield, $sortorder);
1532
1533
        if ($limit) {
1534
            if ($page < 0) {
1535
                $page = 0;
1536
            }
1537
            $offset = $limit * $page;
1538
1539
            $sql .= $this->db->plimit($limit, $offset);
1540
        }
1541
1542
        $result = $this->db->query($sql);
1543
1544
        if ($result) {
1545
            $num = $this->db->num_rows($result);
1546
            $min = min($num, ($limit <= 0 ? $num : $limit));
1547
            for ($i = 0; $i < $min; $i++) {
1548
                $list[] = $this->db->fetch_object($result);
1549
            }
1550
        } else {
1551
            throw new RestException(503, 'Error when retrieving list of towns : ' . $this->db->lasterror());
1552
        }
1553
1554
        return $list;
1555
    }
1556
1557
    /**
1558
     * Get the list of payments terms.
1559
     *
1560
     * @param string    $sortfield  Sort field
1561
     * @param string    $sortorder  Sort order
1562
     * @param int       $limit      Number of items per page
1563
     * @param int       $page       Page number {@min 0}
1564
     * @param int       $active     Payment term is active or not {@min 0} {@max 1}
1565
     * @param string    $sqlfilters SQL criteria to filter. Syntax example "(t.code:=:'CHQ')"
1566
     *
1567
     * @url     GET dictionary/payment_terms
1568
     *
1569
     * @return array List of payment terms
1570
     *
1571
     * @throws  RestException   400     Bad value for sqlfilters
1572
     * @throws  RestException   403     Access denied
1573
     * @throws  RestException   503     Error when retrieving list of payments terms
1574
     */
1575
    public function getPaymentTerms($sortfield = "sortorder", $sortorder = 'ASC', $limit = 100, $page = 0, $active = 1, $sqlfilters = '')
1576
    {
1577
        $list = array();
1578
1579
        if (!DolibarrApiAccess::$user->hasRight('propal', 'lire') && !DolibarrApiAccess::$user->hasRight('commande', 'lire') && !DolibarrApiAccess::$user->hasRight('facture', 'lire')) {
1580
            throw new RestException(403);
1581
        }
1582
1583
        $sql = "SELECT rowid as id, code, sortorder, libelle as label, libelle_facture as descr, type_cdr, nbjour, decalage, module";
1584
        $sql .= " FROM " . MAIN_DB_PREFIX . "c_payment_term as t";
1585
        $sql .= " WHERE t.entity IN (" . getEntity('c_payment_term') . ")";
1586
        $sql .= " AND t.active = " . ((int) $active);
1587
        // Add sql filters
1588
        if ($sqlfilters) {
1589
            $errormessage = '';
1590
            $sql .= forgeSQLFromUniversalSearchCriteria($sqlfilters, $errormessage);
1591
            if ($errormessage) {
1592
                throw new RestException(400, 'Error when validating parameter sqlfilters -> ' . $errormessage);
1593
            }
1594
        }
1595
1596
1597
        $sql .= $this->db->order($sortfield, $sortorder);
1598
1599
        if ($limit) {
1600
            if ($page < 0) {
1601
                $page = 0;
1602
            }
1603
            $offset = $limit * $page;
1604
1605
            $sql .= $this->db->plimit($limit, $offset);
1606
        }
1607
1608
        $result = $this->db->query($sql);
1609
1610
        if ($result) {
1611
            $num = $this->db->num_rows($result);
1612
            $min = min($num, ($limit <= 0 ? $num : $limit));
1613
            for ($i = 0; $i < $min; $i++) {
1614
                $list[] = $this->db->fetch_object($result);
1615
            }
1616
        } else {
1617
            throw new RestException(503, $this->db->lasterror());
1618
        }
1619
1620
        return $list;
1621
    }
1622
1623
    /**
1624
     * Get the list of shipping methods.
1625
     *
1626
     * @param int       $limit      Number of items per page
1627
     * @param int       $page       Page number {@min 0}
1628
     * @param int       $active     Shipping methodsm is active or not {@min 0} {@max 1}
1629
     * @param string    $lang       Code of the language the label of the method must be translated to
1630
     * @param string    $sqlfilters SQL criteria to filter. Syntax example "(t.code:=:'CHQ')"
1631
     *
1632
     * @url     GET dictionary/shipping_methods
1633
     *
1634
     * @return array List of shipping methods
1635
     *
1636
     * @throws  RestException   400     Bad value for sqlfilters
1637
     * @throws  RestException   503     Error when retrieving list of shipping modes
1638
     */
1639
    public function getShippingModes($limit = 100, $page = 0, $active = 1, $lang = '', $sqlfilters = '')
1640
    {
1641
        $list = array();
1642
1643
        $sql = "SELECT rowid as id, code, libelle as label, description, tracking, module";
1644
        $sql .= " FROM " . MAIN_DB_PREFIX . "c_shipment_mode as t";
1645
        $sql .= " WHERE t.entity IN (" . getEntity('c_shipment_mode') . ")";
1646
        $sql .= " AND t.active = " . ((int) $active);
1647
        // Add sql filters
1648
        if ($sqlfilters) {
1649
            $errormessage = '';
1650
            $sql .= forgeSQLFromUniversalSearchCriteria($sqlfilters, $errormessage);
1651
            if ($errormessage) {
1652
                throw new RestException(400, 'Error when validating parameter sqlfilters -> ' . $errormessage);
1653
            }
1654
        }
1655
1656
1657
        //$sql.= $this->db->order($sortfield, $sortorder);
1658
1659
        if ($limit) {
1660
            if ($page < 0) {
1661
                $page = 0;
1662
            }
1663
            $offset = $limit * $page;
1664
1665
            $sql .= $this->db->plimit($limit, $offset);
1666
        }
1667
1668
        $result = $this->db->query($sql);
1669
1670
        if ($result) {
1671
            $num = $this->db->num_rows($result);
1672
            $min = min($num, ($limit <= 0 ? $num : $limit));
1673
            for ($i = 0; $i < $min; $i++) {
1674
                $method = $this->db->fetch_object($result);
1675
                $this->translateLabel($method, $lang, '', array('dict'));
1676
                $list[] = $method;
1677
            }
1678
        } else {
1679
            throw new RestException(503, $this->db->lasterror());
1680
        }
1681
1682
        return $list;
1683
    }
1684
1685
    /**
1686
     * Get the list of measuring units.
1687
     *
1688
     * @param string    $sortfield  Sort field
1689
     * @param string    $sortorder  Sort order
1690
     * @param int       $limit      Number of items per page
1691
     * @param int       $page       Page number (starting from zero)
1692
     * @param int       $active     Measuring unit is active or not {@min 0} {@max 1}
1693
     * @param string    $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.code:like:'A%') and (t.active:>=:0)"
1694
     * @return array                List of measuring unit
1695
     *
1696
     * @url     GET dictionary/units
1697
     *
1698
     * @throws  RestException   400     Bad value for sqlfilters
1699
     * @throws  RestException   503     Error when retrieving list of measuring units
1700
     */
1701
    public function getListOfMeasuringUnits($sortfield = "rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $active = 1, $sqlfilters = '')
1702
    {
1703
        $list = array();
1704
1705
        $sql = "SELECT t.rowid, t.code, t.label,t.short_label, t.active, t.scale, t.unit_type";
1706
        $sql .= " FROM " . MAIN_DB_PREFIX . "c_units as t";
1707
        $sql .= " WHERE t.active = " . ((int) $active);
1708
        // Add sql filters
1709
        if ($sqlfilters) {
1710
            $errormessage = '';
1711
            $sql .= forgeSQLFromUniversalSearchCriteria($sqlfilters, $errormessage);
1712
            if ($errormessage) {
1713
                throw new RestException(400, 'Error when validating parameter sqlfilters -> ' . $errormessage);
1714
            }
1715
        }
1716
1717
1718
        $sql .= $this->db->order($sortfield, $sortorder);
1719
1720
        if ($limit) {
1721
            if ($page < 0) {
1722
                $page = 0;
1723
            }
1724
            $offset = $limit * $page;
1725
1726
            $sql .= $this->db->plimit($limit, $offset);
1727
        }
1728
1729
        $result = $this->db->query($sql);
1730
1731
        if ($result) {
1732
            $num = $this->db->num_rows($result);
1733
            $min = min($num, ($limit <= 0 ? $num : $limit));
1734
            for ($i = 0; $i < $min; $i++) {
1735
                $list[] = $this->db->fetch_object($result);
1736
            }
1737
        } else {
1738
            throw new RestException(503, 'Error when retrieving list of measuring units: ' . $this->db->lasterror());
1739
        }
1740
1741
        return $list;
1742
    }
1743
1744
    /**
1745
     * Get the list of legal form of business.
1746
     *
1747
     * @param string    $sortfield  Sort field
1748
     * @param string    $sortorder  Sort order
1749
     * @param int       $limit      Number of items per page
1750
     * @param int       $page       Page number (starting from zero)
1751
     * @param int       $country    To filter on country
1752
     * @param int       $active     Lega form is active or not {@min 0} {@max 1}
1753
     * @param string    $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.code:like:'A%') and (t.active:>=:0)"
1754
     * @return array                List of legal form
1755
     *
1756
     * @url     GET dictionary/legal_form
1757
     *
1758
     * @throws  RestException   400     Bad value for sqlfilters
1759
     * @throws  RestException   503     Error when retrieving list of legal form
1760
     */
1761
    public function getListOfLegalForm($sortfield = "rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $country = 0, $active = 1, $sqlfilters = '')
1762
    {
1763
        $list = array();
1764
1765
        $sql = "SELECT t.rowid, t.code, t.fk_pays, t.libelle, t.isvatexempted, t.active, t.module, t.position";
1766
        $sql .= " FROM " . MAIN_DB_PREFIX . "c_forme_juridique as t";
1767
        $sql .= " WHERE t.active = " . ((int) $active);
1768
        if ($country) {
1769
            $sql .= " AND t.fk_pays = " . ((int) $country);
1770
        }
1771
        // Add sql filters
1772
        if ($sqlfilters) {
1773
            $errormessage = '';
1774
            $sql .= forgeSQLFromUniversalSearchCriteria($sqlfilters, $errormessage);
1775
            if ($errormessage) {
1776
                throw new RestException(400, 'Error when validating parameter sqlfilters -> ' . $errormessage);
1777
            }
1778
        }
1779
1780
1781
        $sql .= $this->db->order($sortfield, $sortorder);
1782
1783
        if ($limit) {
1784
            if ($page < 0) {
1785
                $page = 0;
1786
            }
1787
            $offset = $limit * $page;
1788
1789
            $sql .= $this->db->plimit($limit, $offset);
1790
        }
1791
1792
        $result = $this->db->query($sql);
1793
1794
        if ($result) {
1795
            $num = $this->db->num_rows($result);
1796
            $min = min($num, ($limit <= 0 ? $num : $limit));
1797
            for ($i = 0; $i < $min; $i++) {
1798
                $list[] = $this->db->fetch_object($result);
1799
            }
1800
        } else {
1801
            throw new RestException(503, 'Error when retrieving list of legal form: ' . $this->db->lasterror());
1802
        }
1803
1804
        return $list;
1805
    }
1806
1807
    /**
1808
     * Get the list of staff.
1809
     *
1810
     * @param string    $sortfield  Sort field
1811
     * @param string    $sortorder  Sort order
1812
     * @param int       $limit      Number of items per page
1813
     * @param int       $page       Page number (starting from zero)
1814
     * @param int       $active     Staff is active or not {@min 0} {@max 1}
1815
     * @param string    $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.code:like:'A%') and (t.active:>=:0)"
1816
     * @return array                List of staff
1817
     *
1818
     * @url     GET dictionary/staff
1819
     *
1820
     * @throws  RestException   400     Bad value for sqlfilters
1821
     * @throws  RestException   503     Error when retrieving list of staff
1822
     */
1823
    public function getListOfStaff($sortfield = "id", $sortorder = 'ASC', $limit = 100, $page = 0, $active = 1, $sqlfilters = '')
1824
    {
1825
        $list = array();
1826
1827
        $sql = "SELECT t.id, t.code, t.libelle, t.active, t.module";
1828
        $sql .= " FROM " . MAIN_DB_PREFIX . "c_effectif as t";
1829
        $sql .= " WHERE t.active = " . ((int) $active);
1830
        // Add sql filters
1831
        if ($sqlfilters) {
1832
            $errormessage = '';
1833
            $sql .= forgeSQLFromUniversalSearchCriteria($sqlfilters, $errormessage);
1834
            if ($errormessage) {
1835
                throw new RestException(400, 'Error when validating parameter sqlfilters -> ' . $errormessage);
1836
            }
1837
        }
1838
1839
1840
        $sql .= $this->db->order($sortfield, $sortorder);
1841
1842
        if ($limit) {
1843
            if ($page < 0) {
1844
                $page = 0;
1845
            }
1846
            $offset = $limit * $page;
1847
1848
            $sql .= $this->db->plimit($limit, $offset);
1849
        }
1850
1851
        $result = $this->db->query($sql);
1852
1853
        if ($result) {
1854
            $num = $this->db->num_rows($result);
1855
            $min = min($num, ($limit <= 0 ? $num : $limit));
1856
            for ($i = 0; $i < $min; $i++) {
1857
                $list[] = $this->db->fetch_object($result);
1858
            }
1859
        } else {
1860
            throw new RestException(503, 'Error when retrieving list of staff: ' . $this->db->lasterror());
1861
        }
1862
1863
        return $list;
1864
    }
1865
1866
    /**
1867
     * Get the list of social networks.
1868
     *
1869
     * @param string    $sortfield  Sort field
1870
     * @param string    $sortorder  Sort order
1871
     * @param int       $limit      Number of items per page
1872
     * @param int       $page       Page number (starting from zero)
1873
     * @param int       $active     Social network is active or not {@min 0} {@max 1}
1874
     * @param string    $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.code:like:'A%') and (t.active:>=:0)"
1875
     * @return array                List of social networks
1876
     *
1877
     * @url     GET dictionary/socialnetworks
1878
     *
1879
     * @throws  RestException   400     Bad value for sqlfilters
1880
     * @throws  RestException   503     Error when retrieving list of social networks
1881
     */
1882
    public function getListOfsocialNetworks($sortfield = "rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $active = 1, $sqlfilters = '')
1883
    {
1884
        global $conf;
1885
1886
        if (!isModEnabled('socialnetworks')) {
1887
            throw new RestException(400, 'API not available: this dictionary is not enabled by setup');
1888
        }
1889
1890
        $list = array();
1891
        //TODO link with multicurrency module
1892
        $sql = "SELECT t.rowid, t.entity, t.code, t.label, t.url, t.icon, t.active";
1893
        $sql .= " FROM " . MAIN_DB_PREFIX . "c_socialnetworks as t";
1894
        $sql .= " WHERE t.entity IN (" . getEntity('c_socialnetworks') . ")";
1895
        $sql .= " AND t.active = " . ((int) $active);
1896
        // Add sql filters
1897
        if ($sqlfilters) {
1898
            $errormessage = '';
1899
            $sql .= forgeSQLFromUniversalSearchCriteria($sqlfilters, $errormessage);
1900
            if ($errormessage) {
1901
                throw new RestException(400, 'Error when validating parameter sqlfilters -> ' . $errormessage);
1902
            }
1903
        }
1904
1905
1906
        $sql .= $this->db->order($sortfield, $sortorder);
1907
1908
        if ($limit) {
1909
            if ($page < 0) {
1910
                $page = 0;
1911
            }
1912
            $offset = $limit * $page;
1913
1914
            $sql .= $this->db->plimit($limit, $offset);
1915
        }
1916
1917
        $result = $this->db->query($sql);
1918
1919
        if ($result) {
1920
            $num = $this->db->num_rows($result);
1921
            $min = min($num, ($limit <= 0 ? $num : $limit));
1922
            for ($i = 0; $i < $min; $i++) {
1923
                $list[] = $this->db->fetch_object($result);
1924
            }
1925
        } else {
1926
            throw new RestException(503, 'Error when retrieving list of social networks: ' . $this->db->lasterror());
1927
        }
1928
1929
        return $list;
1930
    }
1931
1932
    /**
1933
     * Get the list of tickets categories.
1934
     *
1935
     * @param string    $sortfield  Sort field
1936
     * @param string    $sortorder  Sort order
1937
     * @param int       $limit      Number of items per page
1938
     * @param int       $page       Page number (starting from zero)
1939
     * @param int       $active     Payment term is active or not {@min 0} {@max 1}
1940
     * @param string    $lang       Code of the language the label of the category must be translated to
1941
     * @param string    $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.code:like:'A%') and (t.active:>=:0)"
1942
     * @return array                List of ticket categories
1943
     *
1944
     * @url     GET dictionary/ticket_categories
1945
     *
1946
     * @throws  RestException   400     Bad value for sqlfilters
1947
     * @throws  RestException   503     Error when retrieving list of tickets categories
1948
     */
1949
    public function getTicketsCategories($sortfield = "code", $sortorder = 'ASC', $limit = 100, $page = 0, $active = 1, $lang = '', $sqlfilters = '')
1950
    {
1951
        $list = array();
1952
1953
        $sql = "SELECT rowid, code, pos,  label, use_default, description";
1954
        $sql .= " FROM " . MAIN_DB_PREFIX . "c_ticket_category as t";
1955
        $sql .= " WHERE t.entity IN (" . getEntity('c_ticket_category') . ")";
1956
        $sql .= " AND t.active = " . ((int) $active);
1957
        // Add sql filters
1958
        if ($sqlfilters) {
1959
            $errormessage = '';
1960
            $sql .= forgeSQLFromUniversalSearchCriteria($sqlfilters, $errormessage);
1961
            if ($errormessage) {
1962
                throw new RestException(400, 'Error when validating parameter sqlfilters -> ' . $errormessage);
1963
            }
1964
        }
1965
1966
1967
        $sql .= $this->db->order($sortfield, $sortorder);
1968
1969
        if ($limit) {
1970
            if ($page < 0) {
1971
                $page = 0;
1972
            }
1973
            $offset = $limit * $page;
1974
1975
            $sql .= $this->db->plimit($limit, $offset);
1976
        }
1977
1978
        $result = $this->db->query($sql);
1979
1980
        if ($result) {
1981
            $num = $this->db->num_rows($result);
1982
            $min = min($num, ($limit <= 0 ? $num : $limit));
1983
            for ($i = 0; $i < $min; $i++) {
1984
                $category = $this->db->fetch_object($result);
1985
                $this->translateLabel($category, $lang, 'TicketCategoryShort', array('ticket'));
1986
                $list[] = $category;
1987
            }
1988
        } else {
1989
            throw new RestException(503, 'Error when retrieving list of ticket categories : ' . $this->db->lasterror());
1990
        }
1991
1992
        return $list;
1993
    }
1994
1995
    /**
1996
     * Get the list of tickets severity.
1997
     *
1998
     * @param string    $sortfield  Sort field
1999
     * @param string    $sortorder  Sort order
2000
     * @param int       $limit      Number of items per page
2001
     * @param int       $page       Page number (starting from zero)
2002
     * @param int       $active     Payment term is active or not {@min 0} {@max 1}
2003
     * @param string    $lang       Code of the language the label of the severity must be translated to
2004
     * @param string    $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.code:like:'A%') and (t.active:>=:0)"
2005
     * @return array                List of ticket severities
2006
     *
2007
     * @url     GET dictionary/ticket_severities
2008
     *
2009
     * @throws  RestException   400     Bad value for sqlfilters
2010
     * @throws  RestException   503     Error when retrieving list of tickets severities
2011
     */
2012
    public function getTicketsSeverities($sortfield = "code", $sortorder = 'ASC', $limit = 100, $page = 0, $active = 1, $lang = '', $sqlfilters = '')
2013
    {
2014
        $list = array();
2015
2016
        $sql = "SELECT rowid, code, pos,  label, use_default, color, description";
2017
        $sql .= " FROM " . MAIN_DB_PREFIX . "c_ticket_severity as t";
2018
        $sql .= " WHERE t.entity IN (" . getEntity('c_ticket_severity') . ")";
2019
        $sql .= " AND t.active = " . ((int) $active);
2020
        // Add sql filters
2021
        if ($sqlfilters) {
2022
            $errormessage = '';
2023
            $sql .= forgeSQLFromUniversalSearchCriteria($sqlfilters, $errormessage);
2024
            if ($errormessage) {
2025
                throw new RestException(400, 'Error when validating parameter sqlfilters -> ' . $errormessage);
2026
            }
2027
        }
2028
2029
2030
        $sql .= $this->db->order($sortfield, $sortorder);
2031
2032
        if ($limit) {
2033
            if ($page < 0) {
2034
                $page = 0;
2035
            }
2036
            $offset = $limit * $page;
2037
2038
            $sql .= $this->db->plimit($limit, $offset);
2039
        }
2040
2041
        $result = $this->db->query($sql);
2042
2043
        if ($result) {
2044
            $num = $this->db->num_rows($result);
2045
            $min = min($num, ($limit <= 0 ? $num : $limit));
2046
            for ($i = 0; $i < $min; $i++) {
2047
                $severity = $this->db->fetch_object($result);
2048
                $this->translateLabel($severity, $lang, 'TicketSeverityShort', array('ticket'));
2049
                $list[] = $severity;
2050
            }
2051
        } else {
2052
            throw new RestException(503, 'Error when retrieving list of ticket severities : ' . $this->db->lasterror());
2053
        }
2054
2055
        return $list;
2056
    }
2057
2058
    /**
2059
     * Get the list of tickets types.
2060
     *
2061
     * @param string    $sortfield  Sort field
2062
     * @param string    $sortorder  Sort order
2063
     * @param int       $limit      Number of items per page
2064
     * @param int       $page       Page number (starting from zero)
2065
     * @param int       $active     Payment term is active or not {@min 0} {@max 1}
2066
     * @param string    $lang       Code of the language the label of the type must be translated to
2067
     * @param string    $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.code:like:'A%') and (t.active:>=:0)"
2068
     * @return array                List of ticket types
2069
     *
2070
     * @url     GET dictionary/ticket_types
2071
     *
2072
     * @throws RestException 400 Bad value for sqlfilters
2073
     * @throws RestException 503 Error when retrieving list of tickets types
2074
     */
2075
    public function getTicketsTypes($sortfield = "code", $sortorder = 'ASC', $limit = 100, $page = 0, $active = 1, $lang = '', $sqlfilters = '')
2076
    {
2077
        $list = array();
2078
2079
        $sql = "SELECT rowid, code, pos,  label, use_default, description";
2080
        $sql .= " FROM " . MAIN_DB_PREFIX . "c_ticket_type as t";
2081
        $sql .= " WHERE t.entity IN (" . getEntity('c_ticket_type') . ")";
2082
        $sql .= " AND t.active = " . ((int) $active);
2083
2084
        // Add sql filters
2085
        if ($sqlfilters) {
2086
            $errormessage = '';
2087
            $sql .= forgeSQLFromUniversalSearchCriteria($sqlfilters, $errormessage);
2088
            if ($errormessage) {
2089
                throw new RestException(400, 'Error when validating parameter sqlfilters -> ' . $errormessage);
2090
            }
2091
        }
2092
2093
2094
        $sql .= $this->db->order($sortfield, $sortorder);
2095
2096
        if ($limit) {
2097
            if ($page < 0) {
2098
                $page = 0;
2099
            }
2100
            $offset = $limit * $page;
2101
2102
            $sql .= $this->db->plimit($limit, $offset);
2103
        }
2104
2105
        $result = $this->db->query($sql);
2106
2107
        if ($result) {
2108
            $num = $this->db->num_rows($result);
2109
            $min = min($num, ($limit <= 0 ? $num : $limit));
2110
            for ($i = 0; $i < $min; $i++) {
2111
                $type = $this->db->fetch_object($result);
2112
                $this->translateLabel($type, $lang, 'TicketTypeShort', array('ticket'));
2113
                $list[] = $type;
2114
            }
2115
        } else {
2116
            throw new RestException(503, 'Error when retrieving list of ticket types : ' . $this->db->lasterror());
2117
        }
2118
2119
        return $list;
2120
    }
2121
2122
    /**
2123
     * Get the list of incoterms.
2124
     *
2125
     * @param string    $sortfield  Sort field
2126
     * @param string    $sortorder  Sort order
2127
     * @param int       $limit      Number of items per page
2128
     * @param int       $page       Page number (starting from zero)
2129
     * @param int       $active     Payment term is active or not {@min 0} {@max 1}
2130
     * @param string    $lang       Code of the language the label of the type must be translated to
2131
     * @param string    $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.code:like:'A%') and (t.active:>=:0)"
2132
     * @return array                List of incoterm types
2133
     *
2134
     * @url     GET dictionary/incoterms
2135
     *
2136
     * @throws RestException 503 Error when retrieving list of incoterms types
2137
     */
2138
    public function getListOfIncoterms($sortfield = "code", $sortorder = 'ASC', $limit = 100, $page = 0, $active = 1, $lang = '', $sqlfilters = '')
2139
    {
2140
        $list = array();
2141
2142
        $sql = "SELECT rowid, code, active";
2143
        $sql .= " FROM " . MAIN_DB_PREFIX . "c_incoterms as t";
2144
        $sql .= " WHERE 1=1";
2145
2146
        // Add sql filters
2147
        if ($sqlfilters) {
2148
            $errormessage = '';
2149
            if (!DolibarrApi::_checkFilters($sqlfilters, $errormessage)) {
2150
                throw new RestException(400, 'Error when validating parameter sqlfilters -> ' . $errormessage);
2151
            }
2152
            $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)';
2153
            $sql .= " AND (" . preg_replace_callback('/' . $regexstring . '/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters) . ")";
2154
        }
2155
2156
2157
        $sql .= $this->db->order($sortfield, $sortorder);
2158
2159
        if ($limit) {
2160
            if ($page < 0) {
2161
                $page = 0;
2162
            }
2163
            $offset = $limit * $page;
2164
2165
            $sql .= $this->db->plimit($limit, $offset);
2166
        }
2167
2168
        $result = $this->db->query($sql);
2169
2170
        if ($result) {
2171
            $num = $this->db->num_rows($result);
2172
            $min = min($num, ($limit <= 0 ? $num : $limit));
2173
            for ($i = 0; $i < $min; $i++) {
2174
                $type = $this->db->fetch_object($result);
2175
                $list[] = $type;
2176
            }
2177
        } else {
2178
            throw new RestException(503, 'Error when retrieving list of incoterm types : ' . $this->db->lasterror());
2179
        }
2180
2181
        return $list;
2182
    }
2183
2184
    /**
2185
     * Get properties of company
2186
     *
2187
     * @url GET /company
2188
     *
2189
     * @return  array|mixed Mysoc object
2190
     *
2191
     * @throws RestException 403 Forbidden
2192
     */
2193
    public function getCompany()
2194
    {
2195
        global $conf, $mysoc;
2196
2197
        if (
2198
            !DolibarrApiAccess::$user->admin
2199
            && (!getDolGlobalString('API_LOGINS_ALLOWED_FOR_GET_COMPANY') || DolibarrApiAccess::$user->login != $conf->global->API_LOGINS_ALLOWED_FOR_GET_COMPANY)
2200
        ) {
2201
            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');
2202
        }
2203
2204
        unset($mysoc->pays);
2205
        unset($mysoc->note);
2206
        unset($mysoc->nom);
2207
2208
        unset($mysoc->lines);
2209
2210
        unset($mysoc->effectif);
2211
        unset($mysoc->effectif_id);
2212
        unset($mysoc->forme_juridique_code);
2213
        unset($mysoc->forme_juridique);
2214
        unset($mysoc->mode_reglement_supplier_id);
2215
        unset($mysoc->cond_reglement_supplier_id);
2216
        unset($mysoc->transport_mode_supplier_id);
2217
        unset($mysoc->fk_prospectlevel);
2218
2219
        unset($mysoc->total_ht);
2220
        unset($mysoc->total_tva);
2221
        unset($mysoc->total_localtax1);
2222
        unset($mysoc->total_localtax2);
2223
        unset($mysoc->total_ttc);
2224
2225
        unset($mysoc->lastname);
2226
        unset($mysoc->firstname);
2227
        unset($mysoc->civility_id);
2228
2229
        unset($mysoc->client);
2230
        unset($mysoc->prospect);
2231
        unset($mysoc->fournisseur);
2232
        unset($mysoc->contact_id);
2233
2234
        unset($mysoc->fk_incoterms);
2235
        unset($mysoc->label_incoterms);
2236
        unset($mysoc->location_incoterms);
2237
2238
        return $this->_cleanObjectDatas($mysoc);
2239
    }
2240
2241
    /**
2242
     * Get the list of establishments.
2243
     *
2244
     * @return array                List of establishments
2245
     *
2246
     * @url     GET /establishments
2247
     *
2248
     * @throws RestException 503 Error when retrieving list of establishments
2249
     */
2250
    public function getEstablishments()
2251
    {
2252
        $list = array();
2253
2254
        $limit = 0;
2255
2256
        $sql = "SELECT e.rowid, e.rowid as ref, e.label, e.address, e.zip, e.town, e.status";
2257
        $sql .= " FROM " . MAIN_DB_PREFIX . "establishment as e";
2258
        $sql .= " WHERE e.entity IN (" . getEntity('establishment') . ')';
2259
        // if ($type) $sql .= " AND t.type LIKE '%".$this->db->escape($type)."%'";
2260
        // if ($module)    $sql .= " AND t.module LIKE '%".$this->db->escape($module)."%'";
2261
        // Add sql filters
2262
2263
        $result = $this->db->query($sql);
2264
2265
        if ($result) {
2266
            $num = $this->db->num_rows($result);
2267
            $min = min($num, ($limit <= 0 ? $num : $limit));
2268
            for ($i = 0; $i < $min; $i++) {
2269
                $list[] = $this->db->fetch_object($result);
2270
            }
2271
        } else {
2272
            throw new RestException(503, 'Error when retrieving list of establishments : ' . $this->db->lasterror());
2273
        }
2274
2275
        return $list;
2276
    }
2277
2278
    /**
2279
     * Get establishment by ID.
2280
     *
2281
     * @param   int       $id           ID of establishment
2282
     * @return  Object                  Object with cleaned properties
2283
     *
2284
     * @url     GET establishments/{id}
2285
     *
2286
     * @throws RestException 404 Establishment not found
2287
     * @throws RestException 503 Error when retrieving establishment
2288
     */
2289
    public function getEtablishmentByID($id)
2290
    {
2291
        $establishment = new Establishment($this->db);
0 ignored issues
show
Bug introduced by
The type Dolibarr\Code\Api\Api\Establishment was not found. Did you mean Establishment? If so, make sure to prefix the type with \.
Loading history...
2292
2293
        $result = $establishment->fetch($id);
2294
        if ($result < 0) {
2295
            throw new RestException(503, 'Error when retrieving establishment : ' . $establishment->error);
2296
        } elseif ($result == 0) {
2297
            throw new RestException(404, 'Establishment not found');
2298
        }
2299
2300
        return $this->_cleanObjectDatas($establishment);
2301
    }
2302
2303
    /**
2304
     * Get value of a setup variables
2305
     *
2306
     * Note that conf variables that stores security key or password hashes can't be loaded with API.
2307
     *
2308
     * @param   string          $constantname   Name of conf variable to get
2309
     * @return  string                          Data without useless information
2310
     *
2311
     * @url     GET conf/{constantname}
2312
     *
2313
     * @throws RestException 400 Error Bad or unknown value for constantname
2314
     * @throws RestException 403 Forbidden
2315
     */
2316
    public function getConf($constantname)
2317
    {
2318
        global $conf;
2319
2320
        if (
2321
            !DolibarrApiAccess::$user->admin
2322
            && (!getDolGlobalString('API_LOGINS_ALLOWED_FOR_CONST_READ') || DolibarrApiAccess::$user->login != getDolGlobalString('API_LOGINS_ALLOWED_FOR_CONST_READ'))
2323
        ) {
2324
            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');
2325
        }
2326
2327
        if (!preg_match('/^[a-zA-Z0-9_]+$/', $constantname) || !isset($conf->global->$constantname)) {
2328
            throw new RestException(400, 'Error Bad or unknown value for constantname');
2329
        }
2330
        if (isASecretKey($constantname)) {
2331
            throw new RestException(403, 'Forbidden. This parameter can not be read with APIs');
2332
        }
2333
2334
        return getDolGlobalString($constantname);
2335
    }
2336
2337
    /**
2338
     * Do a test of integrity for files and setup.
2339
     *
2340
     * @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.
2341
     * @return array                    Result of file and setup integrity check
2342
     *
2343
     * @url     GET checkintegrity
2344
     *
2345
     * @throws RestException 403 Forbidden
2346
     * @throws RestException 404 Signature file not found
2347
     * @throws RestException 500 Technical error
2348
     */
2349
    public function getCheckIntegrity($target)
2350
    {
2351
        global $langs, $conf;
2352
2353
        if (
2354
            !DolibarrApiAccess::$user->admin
2355
            && (!getDolGlobalString('API_LOGINS_ALLOWED_FOR_INTEGRITY_CHECK') || DolibarrApiAccess::$user->login != $conf->global->API_LOGINS_ALLOWED_FOR_INTEGRITY_CHECK)
2356
        ) {
2357
            throw new RestException(403, 'Error API open to admin users only or to the users with logins defined into constant API_LOGINS_ALLOWED_FOR_INTEGRITY_CHECK');
2358
        }
2359
2360
        require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/files.lib.php';
2361
        require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/geturl.lib.php';
2362
2363
        $langs->load("admin");
2364
2365
        $outexpectedchecksum = '';
2366
        $outcurrentchecksum = '';
2367
2368
        // Modified or missing files
2369
        $file_list = array('missing' => array(), 'updated' => array());
2370
2371
        // Local file to compare to
2372
        $xmlshortfile = dol_sanitizeFileName('filelist-' . DOL_VERSION . getDolGlobalString('MAIN_FILECHECK_LOCAL_SUFFIX') . '.xml' . getDolGlobalString('MAIN_FILECHECK_LOCAL_EXT'));
2373
2374
        $xmlfile = DOL_DOCUMENT_ROOT . '/install/' . $xmlshortfile;
2375
        if (!preg_match('/\.zip$/i', $xmlfile) && dol_is_file($xmlfile . '.zip')) {
2376
            $xmlfile = $xmlfile . '.zip';
2377
        }
2378
2379
        // Remote file to compare to
2380
        $xmlremote = (($target == 'default' || $target == 'local') ? '' : $target);
2381
        if (empty($xmlremote) && getDolGlobalString('MAIN_FILECHECK_URL')) {
2382
            $xmlremote = getDolGlobalString('MAIN_FILECHECK_URL');
2383
        }
2384
        $param = 'MAIN_FILECHECK_URL_' . DOL_VERSION;
2385
        if (empty($xmlremote) && getDolGlobalString($param)) {
2386
            $xmlremote = getDolGlobalString($param);
2387
        }
2388
        if (empty($xmlremote)) {
2389
            $xmlremote = 'https://www.dolibarr.org/files/stable/signatures/filelist-' . DOL_VERSION . '.xml';
2390
        }
2391
        if ($xmlremote && !preg_match('/^https?:\/\//i', $xmlremote)) {
2392
            $langs->load("errors");
2393
            throw new RestException(500, $langs->trans("ErrorURLMustStartWithHttp", $xmlremote));
2394
        }
2395
        if ($xmlremote && !preg_match('/\.xml$/', $xmlremote)) {
2396
            $langs->load("errors");
2397
            throw new RestException(500, $langs->trans("ErrorURLMustEndWith", $xmlremote, '.xml'));
2398
        }
2399
2400
        if (LIBXML_VERSION < 20900) {
2401
            // Avoid load of external entities (security problem).
2402
            // Required only if LIBXML_VERSION < 20900
2403
            // @phan-suppress-next-line PhanDeprecatedFunctionInternal
2404
            libxml_disable_entity_loader(true);
2405
        }
2406
2407
        if ($target == 'local') {
2408
            if (dol_is_file($xmlfile)) {
2409
                $xml = simplexml_load_file($xmlfile);
2410
            } else {
2411
                throw new RestException(500, $langs->trans('XmlNotFound') . ': /install/' . $xmlshortfile);
2412
            }
2413
        } else {
2414
            $xmlarray = getURLContent($xmlremote, 'GET', '', 1, array(), array('http', 'https'), 0);    // Accept http or https links on external remote server only. Same is used into filecheck.php.
2415
2416
            // Return array('content'=>response,'curl_error_no'=>errno,'curl_error_msg'=>errmsg...)
2417
            if (!$xmlarray['curl_error_no'] && $xmlarray['http_code'] != '400' && $xmlarray['http_code'] != '404') {
2418
                $xmlfile = $xmlarray['content'];
2419
                //print "xmlfilestart".$xmlfile."endxmlfile";
2420
                $xml = simplexml_load_string($xmlfile, 'SimpleXMLElement', LIBXML_NOCDATA | LIBXML_NONET);
2421
            } else {
2422
                $errormsg = $langs->trans('XmlNotFound') . ': ' . $xmlremote . ' - ' . $xmlarray['http_code'] . (($xmlarray['http_code'] == 400 && $xmlarray['content']) ? ' ' . $xmlarray['content'] : '') . ' ' . $xmlarray['curl_error_no'] . ' ' . $xmlarray['curl_error_msg'];
2423
                throw new RestException(500, $errormsg);
2424
            }
2425
        }
2426
2427
        if ($xml) {
2428
            $checksumconcat = array();
2429
            $file_list = array();
2430
            $out = '';
2431
2432
            // Forced constants
2433
            if (is_object($xml->dolibarr_constants[0])) {
2434
                $out .= load_fiche_titre($langs->trans("ForcedConstants"));
2435
2436
                $out .= '<div class="div-table-responsive-no-min">';
2437
                $out .= '<table class="noborder">';
2438
                $out .= '<tr class="liste_titre">';
2439
                $out .= '<td>#</td>';
2440
                $out .= '<td>' . $langs->trans("Constant") . '</td>';
2441
                $out .= '<td class="center">' . $langs->trans("ExpectedValue") . '</td>';
2442
                $out .= '<td class="center">' . $langs->trans("Value") . '</td>';
2443
                $out .= '</tr>' . "\n";
2444
2445
                $i = 0;
2446
                foreach ($xml->dolibarr_constants[0]->constant as $constant) {    // $constant is a simpleXMLElement
2447
                    $constname = $constant['name'];
2448
                    $constvalue = (string) $constant;
2449
                    $constvalue = (empty($constvalue) ? '0' : $constvalue);
2450
                    // Value found
2451
                    $value = '';
2452
                    if ($constname && getDolGlobalString($constname) != '') {
2453
                        $value = getDolGlobalString($constname);
2454
                    }
2455
                    $valueforchecksum = (empty($value) ? '0' : $value);
2456
2457
                    $checksumconcat[] = $valueforchecksum;
2458
2459
                    $i++;
2460
                    $out .= '<tr class="oddeven">';
2461
                    $out .= '<td>' . $i . '</td>' . "\n";
2462
                    $out .= '<td>' . dol_escape_htmltag($constname) . '</td>' . "\n";
2463
                    $out .= '<td class="center">' . dol_escape_htmltag($constvalue) . '</td>' . "\n";
2464
                    $out .= '<td class="center">' . dol_escape_htmltag($valueforchecksum) . '</td>' . "\n";
2465
                    $out .= "</tr>\n";
2466
                }
2467
2468
                if ($i == 0) {
2469
                    $out .= '<tr class="oddeven"><td colspan="4" class="opacitymedium">' . $langs->trans("None") . '</td></tr>';
2470
                }
2471
                $out .= '</table>';
2472
                $out .= '</div>';
2473
2474
                $out .= '<br>';
2475
            }
2476
2477
            // Scan htdocs
2478
            if (is_object($xml->dolibarr_htdocs_dir[0])) {
2479
                $includecustom = (empty($xml->dolibarr_htdocs_dir[0]['includecustom']) ? 0 : $xml->dolibarr_htdocs_dir[0]['includecustom']);
2480
2481
                // Define qualified files (must be same than into generate_filelist_xml.php and in api_setup.class.php)
2482
                $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)$';
2483
                $regextoexclude = '(' . ($includecustom ? '' : 'custom|') . 'documents|conf|install|dejavu-fonts-ttf-.*|public\/test|sabre\/sabre\/.*\/tests|Shared\/PCLZip|nusoap\/lib\/Mail|php\/example|php\/test|geoip\/sample.*\.php|ckeditor\/samples|ckeditor\/adapters)$'; // Exclude dirs
2484
                $scanfiles = dol_dir_list(DOL_DOCUMENT_ROOT, 'files', 1, $regextoinclude, $regextoexclude);
2485
2486
                // Fill file_list with files in signature, new files, modified files
2487
                $ret = getFilesUpdated($file_list, $xml->dolibarr_htdocs_dir[0], '', DOL_DOCUMENT_ROOT, $checksumconcat); // Fill array $file_list
2488
                // Complete with list of new files
2489
                foreach ($scanfiles as $keyfile => $valfile) {
2490
                    $tmprelativefilename = preg_replace('/^' . preg_quote(DOL_DOCUMENT_ROOT, '/') . '/', '', $valfile['fullname']);
2491
                    if (!in_array($tmprelativefilename, $file_list['insignature'])) {
2492
                        $md5newfile = @md5_file($valfile['fullname']); // Can fails if we don't have permission to open/read file
2493
                        $file_list['added'][] = array('filename' => $tmprelativefilename, 'md5' => $md5newfile);
2494
                    }
2495
                }
2496
2497
                // Files missing
2498
                $out .= load_fiche_titre($langs->trans("FilesMissing"));
2499
2500
                $out .= '<div class="div-table-responsive-no-min">';
2501
                $out .= '<table class="noborder">';
2502
                $out .= '<tr class="liste_titre">';
2503
                $out .= '<td>#</td>';
2504
                $out .= '<td>' . $langs->trans("Filename") . '</td>';
2505
                $out .= '<td class="center">' . $langs->trans("ExpectedChecksum") . '</td>';
2506
                $out .= '</tr>' . "\n";
2507
                $tmpfilelist = dol_sort_array($file_list['missing'], 'filename');
2508
                if (is_array($tmpfilelist) && count($tmpfilelist)) {
2509
                    $i = 0;
2510
                    foreach ($tmpfilelist as $file) {
2511
                        $i++;
2512
                        $out .= '<tr class="oddeven">';
2513
                        $out .= '<td>' . $i . '</td>' . "\n";
2514
                        $out .= '<td>' . dol_escape_htmltag($file['filename']) . '</td>' . "\n";
2515
                        $out .= '<td class="center">' . $file['expectedmd5'] . '</td>' . "\n";
2516
                        $out .= "</tr>\n";
2517
                    }
2518
                } else {
2519
                    $out .= '<tr class="oddeven"><td colspan="3" class="opacitymedium">' . $langs->trans("None") . '</td></tr>';
2520
                }
2521
                $out .= '</table>';
2522
                $out .= '</div>';
2523
2524
                $out .= '<br>';
2525
2526
                // Files modified
2527
                $out .= load_fiche_titre($langs->trans("FilesModified"));
2528
2529
                $totalsize = 0;
2530
                $out .= '<div class="div-table-responsive-no-min">';
2531
                $out .= '<table class="noborder">';
2532
                $out .= '<tr class="liste_titre">';
2533
                $out .= '<td>#</td>';
2534
                $out .= '<td>' . $langs->trans("Filename") . '</td>';
2535
                $out .= '<td class="center">' . $langs->trans("ExpectedChecksum") . '</td>';
2536
                $out .= '<td class="center">' . $langs->trans("CurrentChecksum") . '</td>';
2537
                $out .= '<td class="right">' . $langs->trans("Size") . '</td>';
2538
                $out .= '<td class="right">' . $langs->trans("DateModification") . '</td>';
2539
                $out .= '</tr>' . "\n";
2540
                $tmpfilelist2 = dol_sort_array($file_list['updated'], 'filename');
2541
                if (is_array($tmpfilelist2) && count($tmpfilelist2)) {
2542
                    $i = 0;
2543
                    foreach ($tmpfilelist2 as $file) {
2544
                        $i++;
2545
                        $out .= '<tr class="oddeven">';
2546
                        $out .= '<td>' . $i . '</td>' . "\n";
2547
                        $out .= '<td>' . dol_escape_htmltag($file['filename']) . '</td>' . "\n";
2548
                        $out .= '<td class="center">' . $file['expectedmd5'] . '</td>' . "\n";
2549
                        $out .= '<td class="center">' . $file['md5'] . '</td>' . "\n";
2550
                        $size = dol_filesize(DOL_DOCUMENT_ROOT . '/' . $file['filename']);
2551
                        $totalsize += $size;
2552
                        $out .= '<td class="right">' . dol_print_size($size) . '</td>' . "\n";
2553
                        $out .= '<td class="right">' . dol_print_date(dol_filemtime(DOL_DOCUMENT_ROOT . '/' . $file['filename']), 'dayhour') . '</td>' . "\n";
2554
                        $out .= "</tr>\n";
2555
                    }
2556
                    $out .= '<tr class="liste_total">';
2557
                    $out .= '<td></td>' . "\n";
2558
                    $out .= '<td>' . $langs->trans("Total") . '</td>' . "\n";
2559
                    $out .= '<td align="center"></td>' . "\n";
2560
                    $out .= '<td align="center"></td>' . "\n";
2561
                    $out .= '<td class="right">' . dol_print_size($totalsize) . '</td>' . "\n";
2562
                    $out .= '<td class="right"></td>' . "\n";
2563
                    $out .= "</tr>\n";
2564
                } else {
2565
                    $out .= '<tr class="oddeven"><td colspan="5" class="opacitymedium">' . $langs->trans("None") . '</td></tr>';
2566
                }
2567
                $out .= '</table>';
2568
                $out .= '</div>';
2569
2570
                $out .= '<br>';
2571
2572
                // Files added
2573
                $out .= load_fiche_titre($langs->trans("FilesAdded"));
2574
2575
                $totalsize = 0;
2576
                $out .= '<div class="div-table-responsive-no-min">';
2577
                $out .= '<table class="noborder">';
2578
                $out .= '<tr class="liste_titre">';
2579
                $out .= '<td>#</td>';
2580
                $out .= '<td>' . $langs->trans("Filename") . '</td>';
2581
                $out .= '<td class="center">' . $langs->trans("ExpectedChecksum") . '</td>';
2582
                $out .= '<td class="center">' . $langs->trans("CurrentChecksum") . '</td>';
2583
                $out .= '<td class="right">' . $langs->trans("Size") . '</td>';
2584
                $out .= '<td class="right">' . $langs->trans("DateModification") . '</td>';
2585
                $out .= '</tr>' . "\n";
2586
                $tmpfilelist3 = dol_sort_array($file_list['added'], 'filename');
2587
                if (is_array($tmpfilelist3) && count($tmpfilelist3)) {
2588
                    $i = 0;
2589
                    foreach ($tmpfilelist3 as $file) {
2590
                        $i++;
2591
                        $out .= '<tr class="oddeven">';
2592
                        $out .= '<td>' . $i . '</td>' . "\n";
2593
                        $out .= '<td>' . dol_escape_htmltag($file['filename']) . '</td>' . "\n";
2594
                        $out .= '<td class="center">' . $file['expectedmd5'] . '</td>' . "\n";
2595
                        $out .= '<td class="center">' . $file['md5'] . '</td>' . "\n";
2596
                        $size = dol_filesize(DOL_DOCUMENT_ROOT . '/' . $file['filename']);
2597
                        $totalsize += $size;
2598
                        $out .= '<td class="right">' . dol_print_size($size) . '</td>' . "\n";
2599
                        $out .= '<td class="right">' . dol_print_date(dol_filemtime(DOL_DOCUMENT_ROOT . '/' . $file['filename']), 'dayhour') . '</td>' . "\n";
2600
                        $out .= "</tr>\n";
2601
                    }
2602
                    $out .= '<tr class="liste_total">';
2603
                    $out .= '<td></td>' . "\n";
2604
                    $out .= '<td>' . $langs->trans("Total") . '</td>' . "\n";
2605
                    $out .= '<td align="center"></td>' . "\n";
2606
                    $out .= '<td align="center"></td>' . "\n";
2607
                    $out .= '<td class="right">' . dol_print_size($totalsize) . '</td>' . "\n";
2608
                    $out .= '<td class="right"></td>' . "\n";
2609
                    $out .= "</tr>\n";
2610
                } else {
2611
                    $out .= '<tr class="oddeven"><td colspan="5" class="opacitymedium">' . $langs->trans("None") . '</td></tr>';
2612
                }
2613
                $out .= '</table>';
2614
                $out .= '</div>';
2615
2616
2617
                // Show warning
2618
                if (empty($tmpfilelist) && empty($tmpfilelist2) && empty($tmpfilelist3)) {
2619
                    //setEventMessages($langs->trans("FileIntegrityIsStrictlyConformedWithReference"), null, 'mesgs');
2620
                } else {
2621
                    //setEventMessages($langs->trans("FileIntegritySomeFilesWereRemovedOrModified"), null, 'warnings');
2622
                }
2623
            } else {
2624
                throw new RestException(500, 'Error: Failed to found dolibarr_htdocs_dir into XML file ' . $xmlfile);
2625
            }
2626
2627
2628
            // Scan scripts
2629
            asort($checksumconcat); // Sort list of checksum
2630
            $checksumget = md5(implode(',', $checksumconcat));
2631
            $checksumtoget = trim((string) $xml->dolibarr_htdocs_dir_checksum);
2632
2633
            $outexpectedchecksum = ($checksumtoget ? $checksumtoget : $langs->trans("Unknown"));
2634
            if ($checksumget == $checksumtoget) {
2635
                if (count($file_list['added'])) {
2636
                    $resultcode = 'warning';
2637
                    $resultcomment = 'FileIntegrityIsOkButFilesWereAdded';
2638
                    //$outcurrentchecksum =  $checksumget.' - <span class="'.$resultcode.'">'.$langs->trans("FileIntegrityIsOkButFilesWereAdded").'</span>';
2639
                    $outcurrentchecksum = $checksumget;
2640
                } else {
2641
                    $resultcode = 'ok';
2642
                    $resultcomment = 'Success';
2643
                    //$outcurrentchecksum = '<span class="'.$resultcode.'">'.$checksumget.'</span>';
2644
                    $outcurrentchecksum = $checksumget;
2645
                }
2646
            } else {
2647
                $resultcode = 'error';
2648
                $resultcomment = 'Error';
2649
                //$outcurrentchecksum = '<span class="'.$resultcode.'">'.$checksumget.'</span>';
2650
                $outcurrentchecksum = $checksumget;
2651
            }
2652
        } else {
2653
            throw new RestException(404, 'No signature file known');
2654
        }
2655
2656
        return array('resultcode' => $resultcode, 'resultcomment' => $resultcomment, 'expectedchecksum' => $outexpectedchecksum, 'currentchecksum' => $outcurrentchecksum, 'out' => $out);
2657
    }
2658
2659
2660
    /**
2661
     * Get list of enabled modules
2662
     *
2663
     * @url GET /modules
2664
     *
2665
     * @return  array|mixed Data without useless information
2666
     *
2667
     * @throws RestException 403 Forbidden
2668
     */
2669
    public function getModules()
2670
    {
2671
        global $conf;
2672
2673
        if (
2674
            !DolibarrApiAccess::$user->admin
2675
            && (!getDolGlobalString('API_LOGINS_ALLOWED_FOR_GET_MODULES') || DolibarrApiAccess::$user->login != $conf->global->API_LOGINS_ALLOWED_FOR_GET_MODULES)
2676
        ) {
2677
            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_MODULES');
2678
        }
2679
2680
        sort($conf->modules);
2681
2682
        return $this->_cleanObjectDatas($conf->modules);
2683
    }
2684
}
2685