Passed
Branch develop (05352a)
by
unknown
27:04
created

Products   F

Complexity

Total Complexity 115

Size/Duplication

Total Lines 748
Duplicated Lines 0 %

Importance

Changes 5
Bugs 0 Features 0
Metric Value
eloc 269
dl 0
loc 748
rs 2
c 5
b 0
f 0
wmc 115

19 Methods

Rating   Name   Duplication   Size   Complexity  
A get() 0 3 1
A getCustomerPricesPerCustomer() 0 22 5
F index() 0 67 15
F getSupplierProducts() 0 68 16
F put() 0 82 23
B getPurchasePrices() 0 27 10
A _cleanObjectDatas() 0 19 1
B _fetch() 0 26 10
A __construct() 0 6 1
A getCustomerPricesPerQuantity() 0 24 5
A getByRefExt() 0 3 1
A delete() 0 19 4
A getByRef() 0 3 1
A getByBarcode() 0 3 1
A _validate() 0 10 3
A getCategories() 0 19 4
A getCustomerPricesPerSegment() 0 28 5
A deletePurchasePrice() 0 20 5
A post() 0 16 4

How to fix   Complexity   

Complex Class

Complex classes like Products 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 Products, and based on these observations, apply Extract Interface, too.

1
<?php
2
/* Copyright (C) 2015   Jean-François Ferry     <[email protected]>
3
 * Copyright (C) 2019   Cedric Ancelin          <[email protected]>
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation; either version 3 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
17
 */
18
19
use Luracast\Restler\RestException;
20
21
require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
22
require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.product.class.php';
23
require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
24
25
/**
26
 * API class for products
27
 *
28
 * @access protected
29
 * @class  DolibarrApiAccess {@requires user,external}
30
 */
31
class Products extends DolibarrApi
32
{
33
    /**
34
     * @var array   $FIELDS     Mandatory fields, checked when create and update object
35
     */
36
    static $FIELDS = array(
37
        'ref',
38
        'label'
39
    );
40
41
    /**
42
     * @var Product $product {@type Product}
43
     */
44
    public $product;
45
46
    /**
47
     * @var ProductFournisseur $productsupplier {@type ProductFournisseur}
48
     */
49
    public $productsupplier;
50
51
    /**
52
     * Constructor
53
     */
54
    public function __construct()
55
    {
56
        global $db, $conf;
57
        $this->db = $db;
58
        $this->product = new Product($this->db);
59
        $this->productsupplier = new ProductFournisseur($this->db);
60
    }
61
62
    /**
63
     * Get properties of a product object by id
64
     *
65
     * Return an array with product information.
66
     *
67
     * @param  int    $id               ID of product
68
     * @param  int    $includestockdata Load also information about stock (slower)
69
     * @return array|mixed                 Data without useless information
70
     *
71
     * @throws 401
72
     * @throws 403
73
     * @throws 404
74
     */
75
    public function get($id, $includestockdata = 0)
76
    {
77
        return $this->_fetch($id, '', '', '', $includestockdata);
78
    }
79
80
    /**
81
     * Get properties of a product object by ref
82
     *
83
     * Return an array with product information.
84
     *
85
     * @param string $ref Ref of element
86
     * @param int $includestockdata Load also information about stock (slower)
87
     *
88
     * @return array|mixed                 Data without useless information
89
     *
90
     * @url GET byRef/{ref}
91
     *
92
     * @throws 401
93
     * @throws 403
94
     * @throws 404
95
     */
96
    public function getByRef($ref, $includestockdata = 0)
97
    {
98
        return $this->_fetch('', $ref, '', '', $includestockdata);
99
    }
100
101
    /**
102
     * Get properties of a product object by ref_ext
103
     *
104
     * Return an array with product information.
105
     *
106
     * @param string $ref_ext Ref_ext of element
107
     * @param int $includestockdata Load also information about stock (slower)
108
     *
109
     * @return array|mixed Data without useless information
110
     *
111
     * @url GET byRefExt/{ref_ext}
112
     *
113
     * @throws 401
114
     * @throws 403
115
     * @throws 404
116
     */
117
    public function getByRefExt($ref_ext, $includestockdata = 0)
118
    {
119
        return $this->_fetch('', '', $ref_ext, '', $includestockdata);
120
    }
121
122
    /**
123
     * Get properties of a product object by barcode
124
     *
125
     * Return an array with product information.
126
     *
127
     * @param string $barcode Barcode of element
128
     * @param int $includestockdata Load also information about stock (slower)
129
     *
130
     * @return array|mixed Data without useless information
131
     *
132
     * @url GET byBarcode/{barcode}
133
     *
134
     * @throws 401
135
     * @throws 403
136
     * @throws 404
137
     */
138
    public function getByBarcode($barcode, $includestockdata = 0)
139
    {
140
        return $this->_fetch('', '', '', $barcode, $includestockdata);
141
    }
142
143
    /**
144
     * List products
145
     *
146
     * Get a list of products
147
     *
148
     * @param  string $sortfield  Sort field
149
     * @param  string $sortorder  Sort order
150
     * @param  int    $limit      Limit for list
151
     * @param  int    $page       Page number
152
     * @param  int    $mode       Use this param to filter list (0 for all, 1 for only product, 2 for only service)
153
     * @param  int    $category   Use this param to filter list by category
154
     * @param  string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.tobuy:=:0) and (t.tosell:=:1)"
155
     * @return array                Array of product objects
156
     */
157
    public function index($sortfield = "t.ref", $sortorder = 'ASC', $limit = 100, $page = 0, $mode = 0, $category = 0, $sqlfilters = '')
158
    {
159
        global $db, $conf;
160
161
        $obj_ret = array();
162
163
        $socid = DolibarrApiAccess::$user->socid ? DolibarrApiAccess::$user->socid : '';
164
165
        $sql = "SELECT t.rowid, t.ref, t.ref_ext";
166
        $sql.= " FROM ".MAIN_DB_PREFIX."product as t";
167
        if ($category > 0) {
168
            $sql.= ", ".MAIN_DB_PREFIX."categorie_product as c";
169
        }
170
        $sql.= ' WHERE t.entity IN ('.getEntity('product').')';
171
        // Select products of given category
172
        if ($category > 0) {
173
            $sql.= " AND c.fk_categorie = ".$db->escape($category);
174
            $sql.= " AND c.fk_product = t.rowid ";
175
        }
176
        if ($mode == 1) {
177
            // Show only products
178
            $sql.= " AND t.fk_product_type = 0";
179
        } elseif ($mode == 2) {
180
            // Show only services
181
            $sql.= " AND t.fk_product_type = 1";
182
        }
183
        // Add sql filters
184
        if ($sqlfilters) {
185
            if (! DolibarrApi::_checkFilters($sqlfilters)) {
186
                throw new RestException(503, 'Error when validating parameter sqlfilters '.$sqlfilters);
187
            }
188
            $regexstring='\(([^:\'\(\)]+:[^:\'\(\)]+:[^:\(\)]+)\)';
189
            $sql.=" AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")";
190
        }
191
192
        $sql.= $db->order($sortfield, $sortorder);
193
        if ($limit) {
194
            if ($page < 0) {
195
                $page = 0;
196
            }
197
            $offset = $limit * $page;
198
199
            $sql.= $db->plimit($limit + 1, $offset);
200
        }
201
202
        $result = $db->query($sql);
203
        if ($result) {
204
            $num = $db->num_rows($result);
205
            $min = min($num, ($limit <= 0 ? $num : $limit));
206
            $i = 0;
207
            while ($i < $min)
208
            {
209
                $obj = $db->fetch_object($result);
210
                $product_static = new Product($db);
211
                if($product_static->fetch($obj->rowid)) {
212
                    $obj_ret[] = $this->_cleanObjectDatas($product_static);
213
                }
214
                $i++;
215
            }
216
        }
217
        else {
218
            throw new RestException(503, 'Error when retrieve product list : '.$db->lasterror());
219
        }
220
        if(! count($obj_ret)) {
221
            throw new RestException(404, 'No product found');
222
        }
223
        return $obj_ret;
224
    }
225
226
    /**
227
     * Create product object
228
     *
229
     * @param  array $request_data Request data
230
     * @return int     ID of product
231
     */
232
    public function post($request_data = null)
233
    {
234
        if(! DolibarrApiAccess::$user->rights->produit->creer) {
235
            throw new RestException(401);
236
        }
237
        // Check mandatory fields
238
        $result = $this->_validate($request_data);
239
240
        foreach($request_data as $field => $value) {
241
            $this->product->$field = $value;
242
        }
243
        if ($this->product->create(DolibarrApiAccess::$user) < 0) {
244
            throw new RestException(500, "Error creating product", array_merge(array($this->product->error), $this->product->errors));
245
        }
246
247
        return $this->product->id;
248
    }
249
250
    /**
251
     * Update product.
252
     * Price will be updated by this API only if option is set on "One price per product". See other APIs for other price modes.
253
     *
254
     * @param  int   $id           Id of product to update
255
     * @param  array $request_data Datas
256
     * @return int
257
     *
258
     * @throws RestException
259
     * @throws 401
260
     * @throws 404
261
     */
262
    public function put($id, $request_data = null)
263
    {
264
        global $conf;
265
266
        if(! DolibarrApiAccess::$user->rights->produit->creer) {
267
            throw new RestException(401);
268
        }
269
270
        $result = $this->product->fetch($id);
271
        if(! $result ) {
272
            throw new RestException(404, 'Product not found');
273
        }
274
275
        if(! DolibarrApi::_checkAccessToResource('product', $this->product->id)) {
276
            throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
277
        }
278
279
        $oldproduct = dol_clone($this->product, 0);
280
281
        foreach($request_data as $field => $value) {
282
            if ($field == 'id') { continue;
283
            }
284
            $this->product->$field = $value;
285
        }
286
287
        $updatetype = false;
288
        if ($this->product->type != $oldproduct->type && ($this->product->isProduct() || $this->product->isService())) {
289
            $updatetype = true;
290
        }
291
292
        $result = $this->product->update($id, DolibarrApiAccess::$user, 1, 'update', $updatetype);
293
294
        // If price mode is 1 price per product
295
        if ($result > 0 && ! empty($conf->global->PRODUCT_PRICE_UNIQ)) {
296
            // We update price only if it was changed
297
            $pricemodified = false;
298
            if ($this->product->price_base_type != $oldproduct->price_base_type) { $pricemodified = true;
299
            } else
300
            {
301
                if ($this->product->tva_tx != $oldproduct->tva_tx) { $pricemodified = true;
302
                }
303
                if ($this->product->tva_npr != $oldproduct->tva_npr) { $pricemodified = true;
304
                }
305
                if ($this->product->default_vat_code != $oldproduct->default_vat_code) { $pricemodified = true;
306
                }
307
308
                if ($this->product->price_base_type == 'TTC') {
309
                    if ($this->product->price_ttc != $oldproduct->price_ttc) { $pricemodified = true;
310
                    }
311
                    if ($this->product->price_min_ttc != $oldproduct->price_min_ttc) { $pricemodified = true;
312
                    }
313
                }
314
                else
315
                {
316
                    if ($this->product->price != $oldproduct->price) { $pricemodified = true;
317
                    }
318
                    if ($this->product->price_min != $oldproduct->price_min) { $pricemodified = true;
319
                    }
320
                }
321
            }
322
323
            if ($pricemodified) {
324
                $newvat = $this->product->tva_tx;
325
                $newnpr = $this->product->tva_npr;
326
                $newvatsrccode = $this->product->default_vat_code;
327
328
                $newprice = $this->product->price;
329
                $newpricemin = $this->product->price_min;
330
                if ($this->product->price_base_type == 'TTC') {
331
                    $newprice = $this->product->price_ttc;
332
                    $newpricemin = $this->product->price_min_ttc;
333
                }
334
335
                $result = $this->product->updatePrice($newprice, $this->product->price_base_type, DolibarrApiAccess::$user, $newvat, $newpricemin, 0, $newnpr, 0, 0, array(), $newvatsrccode);
336
            }
337
        }
338
339
        if ($result <= 0) {
340
            throw new RestException(500, "Error updating product", array_merge(array($this->product->error), $this->product->errors));
341
        }
342
343
        return $this->get($id);
344
    }
345
346
    /**
347
     * Delete product
348
     *
349
     * @param  int $id Product ID
350
     * @return array
351
     */
352
    public function delete($id)
353
    {
354
        if(! DolibarrApiAccess::$user->rights->produit->supprimer) {
355
            throw new RestException(401);
356
        }
357
        $result = $this->product->fetch($id);
358
        if(! $result ) {
359
            throw new RestException(404, 'Product not found');
360
        }
361
362
        if(! DolibarrApi::_checkAccessToResource('product', $this->product->id)) {
363
            throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
364
        }
365
366
        // The Product::delete() method uses the global variable $user.
367
        global $user;
368
        $user = DolibarrApiAccess::$user;
369
370
        return $this->product->delete(DolibarrApiAccess::$user);
371
    }
372
373
374
    /**
375
     * Get categories for a product
376
     *
377
     * @param int    $id        ID of product
378
     * @param string $sortfield Sort field
379
     * @param string $sortorder Sort order
380
     * @param int    $limit     Limit for list
381
     * @param int    $page      Page number
382
     *
383
     * @return mixed
384
     *
385
     * @url GET {id}/categories
386
     */
387
    public function getCategories($id, $sortfield = "s.rowid", $sortorder = 'ASC', $limit = 0, $page = 0)
388
    {
389
        if (! DolibarrApiAccess::$user->rights->categorie->lire) {
390
            throw new RestException(401);
391
        }
392
393
        $categories = new Categorie($this->db);
394
395
        $result = $categories->getListForItem($id, 'product', $sortfield, $sortorder, $limit, $page);
396
397
        if (empty($result)) {
398
            throw new RestException(404, 'No category found');
399
        }
400
401
        if ($result < 0) {
402
            throw new RestException(503, 'Error when retrieve category list : '.array_merge(array($categories->error), $categories->errors));
403
        }
404
405
        return $result;
406
    }
407
408
    /**
409
     * Get prices per segment for a product
410
     *
411
     * @param int $id ID of product
412
     *
413
     * @return mixed
414
     *
415
     * @url GET {id}/selling_multiprices/per_segment
416
     */
417
    public function getCustomerPricesPerSegment($id)
418
    {
419
        global $conf;
420
421
        if (! DolibarrApiAccess::$user->rights->produit->lire) {
422
            throw new RestException(401);
423
        }
424
425
        if (empty($conf->global->PRODUIT_MULTIPRICES)) {
426
            throw new RestException(400, 'API not available: this mode of pricing is not enabled by setup');
427
        }
428
429
        $result = $this->product->fetch($id);
430
        if (! $result ) {
431
            throw new RestException(404, 'Product not found');
432
        }
433
434
        if ($result < 0) {
435
            throw new RestException(503, 'Error when retrieve prices list : '.array_merge(array($this->product->error), $this->product->errors));
436
        }
437
438
        return array(
439
            'multiprices'=>$this->product->multiprices,
440
            'multiprices_inc_tax'=>$this->product->multiprices_ttc,
441
            'multiprices_min'=>$this->product->multiprices_min,
442
            'multiprices_min_inc_tax'=>$this->product->multiprices_min_ttc,
443
            'multiprices_vat'=>$this->product->multiprices_tva_tx,
444
            'multiprices_base_type'=>$this->product->multiprices_base_type,
445
            //'multiprices_default_vat_code'=>$this->product->multiprices_default_vat_code
446
        );
447
    }
448
449
    /**
450
     * Get prices per customer for a product
451
     *
452
     * @param int $id ID of product
453
     *
454
     * @return mixed
455
     *
456
     * @url GET {id}/selling_multiprices/per_customer
457
     */
458
    public function getCustomerPricesPerCustomer($id)
459
    {
460
        global $conf;
461
462
        if (! DolibarrApiAccess::$user->rights->produit->lire) {
463
            throw new RestException(401);
464
        }
465
466
        if (empty($conf->global->PRODUIT_CUSTOMER_PRICES)) {
467
            throw new RestException(400, 'API not available: this mode of pricing is not enabled by setup');
468
        }
469
470
        $result = $this->product->fetch($id);
471
        if (! $result ) {
472
            throw new RestException(404, 'Product not found');
473
        }
474
475
        if ($result < 0) {
476
            throw new RestException(503, 'Error when retrieve prices list : '.array_merge(array($this->product->error), $this->product->errors));
477
        }
478
479
        throw new RestException(501, 'Feature not yet available');
480
        //return $result;
481
    }
482
483
    /**
484
     * Get prices per quantity for a product
485
     *
486
     * @param int $id ID of product
487
     *
488
     * @return mixed
489
     *
490
     * @url GET {id}/selling_multiprices/per_quantity
491
     */
492
    public function getCustomerPricesPerQuantity($id)
493
    {
494
        global $conf;
495
496
        if (! DolibarrApiAccess::$user->rights->produit->lire) {
497
            throw new RestException(401);
498
        }
499
500
        if (empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY)) {
501
            throw new RestException(400, 'API not available: this mode of pricing is not enabled by setup');
502
        }
503
504
        $result = $this->product->fetch($id);
505
        if (! $result ) {
506
            throw new RestException(404, 'Product not found');
507
        }
508
509
        if ($result < 0) {
510
            throw new RestException(503, 'Error when retrieve prices list : '.array_merge(array($this->product->error), $this->product->errors));
511
        }
512
513
        return array(
514
        'prices_by_qty'=>$this->product->prices_by_qty[0],                // 1 if price by quantity was activated for the product
515
        'prices_by_qty_list'=>$this->product->prices_by_qty_list[0]
516
        );
517
    }
518
519
    /**
520
     * Delete purchase price for a product
521
     *
522
     * @param  int $id Product ID
523
     * @param  int $priceid purchase price ID
524
     *
525
     * @url DELETE {id}/purchase_prices/{priceid}
526
     *
527
     * @return int
528
     *
529
     * @throws 401
530
     * @throws 404
531
     *
532
     */
533
    public function deletePurchasePrice($id, $priceid)
534
    {
535
        if(! DolibarrApiAccess::$user->rights->produit->supprimer) {
536
            throw new RestException(401);
537
        }
538
        $result = $this->product->fetch($id);
539
        if(! $result ) {
540
            throw new RestException(404, 'Product not found');
541
        }
542
543
        if(! DolibarrApi::_checkAccessToResource('product', $this->product->id)) {
544
            throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
545
        }
546
        $resultsupplier = 0;
547
        if ($result) {
548
            $this->productsupplier->fetch($id);
549
            $resultsupplier = $this->product->remove_product_fournisseur_price($priceid);
0 ignored issues
show
introduced by
The method remove_product_fournisseur_price() does not exist on Product. Maybe you want to declare this class abstract? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

549
            /** @scrutinizer ignore-call */ 
550
            $resultsupplier = $this->product->remove_product_fournisseur_price($priceid);
Loading history...
550
        }
551
552
        return $resultsupplier;
553
    }
554
555
    /**
556
     * List purchase prices
557
     *
558
     * Get a list of all purchase prices of products
559
     *
560
     * @param  string $sortfield  Sort field
561
     * @param  string $sortorder  Sort order
562
     * @param  int    $limit      Limit for list
563
     * @param  int    $page       Page number
564
     * @param  int    $mode       Use this param to filter list (0 for all, 1 for only product, 2 for only service)
565
     * @param  int    $category   Use this param to filter list by category of product
566
     * @param  int    $supplier   Use this param to filter list by supplier
567
     * @param  string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.tobuy:=:0) and (t.tosell:=:1)"
568
     * @return array              Array of product objects
569
     *
570
     * @url GET purchase_prices
571
     */
572
    public function getSupplierProducts($sortfield = "t.ref", $sortorder = 'ASC', $limit = 100, $page = 0, $mode = 0, $category = 0, $supplier = 0, $sqlfilters = '')
573
    {
574
    	global $db, $conf;
575
    	$obj_ret = array();
576
    	$socid = DolibarrApiAccess::$user->societe_id ? DolibarrApiAccess::$user->societe_id : '';
1 ignored issue
show
Deprecated Code introduced by
The property User::$societe_id has been deprecated. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

576
    	$socid = /** @scrutinizer ignore-deprecated */ DolibarrApiAccess::$user->societe_id ? DolibarrApiAccess::$user->societe_id : '';
Loading history...
577
    	$sql = "SELECT t.rowid, t.ref, t.ref_ext";
578
    	$sql.= " FROM ".MAIN_DB_PREFIX."product as t";
579
    	if ($category > 0) {
580
    		$sql.= ", ".MAIN_DB_PREFIX."categorie_product as c";
581
    	}
582
    	$sql.= ", ".MAIN_DB_PREFIX."product_fournisseur_price as s";
583
584
    	$sql.= ' WHERE t.entity IN ('.getEntity('product').')';
585
586
    	if ($supplier > 0) {
587
    		$sql.= " AND s.fk_soc = ".$db->escape($supplier);
588
    	}
589
    	$sql.= " AND s.fk_product = t.rowid ";
590
    	// Select products of given category
591
    	if ($category > 0) {
592
    		$sql.= " AND c.fk_categorie = ".$db->escape($category);
593
    		$sql.= " AND c.fk_product = t.rowid ";
594
    	}
595
    	if ($mode == 1) {
596
    		// Show only products
597
    		$sql.= " AND t.fk_product_type = 0";
598
    	} elseif ($mode == 2) {
599
    		// Show only services
600
    		$sql.= " AND t.fk_product_type = 1";
601
    	}
602
    	// Add sql filters
603
    	if ($sqlfilters) {
604
    		if (! DolibarrApi::_checkFilters($sqlfilters)) {
605
    			throw new RestException(503, 'Error when validating parameter sqlfilters '.$sqlfilters);
606
    		}
607
    		$regexstring='\(([^:\'\(\)]+:[^:\'\(\)]+:[^:\(\)]+)\)';
608
    		$sql.=" AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")";
609
    	}
610
    	$sql.= $db->order($sortfield, $sortorder);
611
    	if ($limit) {
612
    		if ($page < 0) {
613
    			$page = 0;
614
    		}
615
    		$offset = $limit * $page;
616
    		$sql.= $db->plimit($limit + 1, $offset);
617
    	}
618
    	$result = $db->query($sql);
619
    	if ($result) {
620
    		$num = $db->num_rows($result);
621
    		$min = min($num, ($limit <= 0 ? $num : $limit));
622
    		$i = 0;
623
    		while ($i < $min)
624
    		{
625
    			$obj = $db->fetch_object($result);
626
    			$product_static = new Product($db);
627
    			if($product_static->fetch($obj->rowid)) {
628
    				$obj_ret[] = $this->_cleanObjectDatas($product_static);
629
    			}
630
    			$i++;
631
    		}
632
    	}
633
    	else {
634
    		throw new RestException(503, 'Error when retrieve product list : '.$db->lasterror());
635
    	}
636
    	if(! count($obj_ret)) {
637
    		throw new RestException(404, 'No product found');
638
    	}
639
    	return $obj_ret;
640
    }
641
642
    /**
643
     * Get purchase prices for a product
644
     *
645
     * Return an array with product information.
646
     * TODO implement getting a product by ref or by $ref_ext
647
     *
648
     * @param  int    $id               ID of product
649
     * @param  string $ref              Ref of element
650
     * @param  string $ref_ext          Ref ext of element
651
     * @param  string $barcode          Barcode of element
652
     * @return array|mixed                 Data without useless information
653
     *
654
     * @url GET {id}/purchase_prices
655
     *
656
     * @throws 401
657
     * @throws 403
658
     * @throws 404
659
     *
660
     */
661
    public function getPurchasePrices($id, $ref = '', $ref_ext = '', $barcode = '')
662
    {
663
        if (empty($id) && empty($ref) && empty($ref_ext) && empty($barcode)) {
664
            throw new RestException(400, 'bad value for parameter id, ref, ref_ext or barcode');
665
        }
666
667
        $id = (empty($id)?0:$id);
668
669
        if(! DolibarrApiAccess::$user->rights->produit->lire) {
670
            throw new RestException(403);
671
        }
672
673
        $result = $this->product->fetch($id, $ref, $ref_ext, $barcode);
674
        if(! $result ) {
675
            throw new RestException(404, 'Product not found');
676
        }
677
678
        if(! DolibarrApi::_checkAccessToResource('product', $this->product->id)) {
679
            throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
680
        }
681
682
        if ($result) {
683
            $this->productsupplier->fetch($id, $ref);
684
            $this->productsupplier->list_product_fournisseur_price($id, '', '', 0, 0);
685
        }
686
687
        return $this->_cleanObjectDatas($this->productsupplier);
688
    }
689
690
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
691
    /**
692
     * Clean sensible object datas
693
     *
694
     * @param  object $object Object to clean
695
     * @return array    Array of cleaned object properties
696
     */
697
    protected function _cleanObjectDatas($object)
698
    {
699
        // phpcs:enable
700
        $object = parent::_cleanObjectDatas($object);
701
702
        unset($object->regeximgext);
703
        unset($object->price_by_qty);
704
        unset($object->prices_by_qty_id);
705
        unset($object->libelle);
706
        unset($object->product_id_already_linked);
707
708
        unset($object->name);
709
        unset($object->firstname);
710
        unset($object->lastname);
711
        unset($object->civility_id);
712
713
        unset($object->recuperableonly);
714
715
        return $object;
716
    }
717
718
    /**
719
     * Validate fields before create or update object
720
     *
721
     * @param  array $data Datas to validate
722
     * @return array
723
     * @throws RestException
724
     */
725
    private function _validate($data)
726
    {
727
        $product = array();
728
        foreach (Products::$FIELDS as $field) {
729
            if (!isset($data[$field])) {
730
                throw new RestException(400, "$field field missing");
731
            }
732
            $product[$field] = $data[$field];
733
        }
734
        return $product;
735
    }
736
737
    /**
738
     * Get properties of a product object
739
     *
740
     * Return an array with product information.
741
     *
742
     * @param  int    $id               ID of product
743
     * @param  string $ref              Ref of element
744
     * @param  string $ref_ext          Ref ext of element
745
     * @param  string $barcode          Barcode of element
746
     * @param  int    $includestockdata Load also information about stock (slower)
747
     * @return array|mixed                 Data without useless information
748
     *
749
     * @throws 401
750
     * @throws 403
751
     * @throws 404
752
     */
753
    private function _fetch($id, $ref = '', $ref_ext = '', $barcode = '', $includestockdata = 0)
754
    {
755
        if (empty($id) && empty($ref) && empty($ref_ext) && empty($barcode)) {
756
            throw new RestException(400, 'bad value for parameter id, ref, ref_ext or barcode');
757
        }
758
759
        $id = (empty($id)?0:$id);
760
761
        if(! DolibarrApiAccess::$user->rights->produit->lire) {
762
            throw new RestException(403);
763
        }
764
765
        $result = $this->product->fetch($id, $ref, $ref_ext, $barcode);
766
        if(! $result ) {
767
            throw new RestException(404, 'Product not found');
768
        }
769
770
        if(! DolibarrApi::_checkAccessToResource('product', $this->product->id)) {
771
            throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
772
        }
773
774
        if ($includestockdata) {
775
               $this->product->load_stock();
776
        }
777
778
        return $this->_cleanObjectDatas($this->product);
779
    }
780
}
781