Completed
Branch develop (1d6b4c)
by
unknown
24:51
created

Orders::putLine()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 45
Code Lines 36

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 36
nc 5
nop 3
dl 0
loc 45
rs 8.439
c 0
b 0
f 0
1
<?php
2
/* Copyright (C) 2015   Jean-François Ferry     <[email protected]>
3
 * Copyright (C) 2016	Laurent Destailleur		<[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 <http://www.gnu.org/licenses/>.
17
 */
18
19
 use Luracast\Restler\RestException;
20
21
 require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
22
23
/**
24
 * API class for orders
25
 *
26
 * @access protected
27
 * @class  DolibarrApiAccess {@requires user,external}
28
 */
29
class Orders extends DolibarrApi
30
{
31
32
    /**
33
     * @var array   $FIELDS     Mandatory fields, checked when create and update object
34
     */
35
    static $FIELDS = array(
36
        'socid'
37
    );
38
39
    /**
40
     * @var Commande $commande {@type Commande}
41
     */
42
    public $commande;
43
44
    /**
45
     * Constructor
46
     */
47
    function __construct()
48
    {
49
		global $db, $conf;
50
		$this->db = $db;
51
        $this->commande = new Commande($this->db);
52
    }
53
54
    /**
55
     * Get properties of a commande object
56
     *
57
     * Return an array with commande informations
58
     *
59
     * @param       int         $id         ID of order
60
     * @return 	array|mixed data without useless information
61
	 *
62
     * @throws 	RestException
63
     */
64
    function get($id)
65
    {
66
		if(! DolibarrApiAccess::$user->rights->commande->lire) {
67
			throw new RestException(401);
68
		}
69
70
        $result = $this->commande->fetch($id);
71
        if( ! $result ) {
72
            throw new RestException(404, 'Order not found');
73
        }
74
75
		if( ! DolibarrApi::_checkAccessToResource('commande',$this->commande->id)) {
76
			throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
77
		}
78
79
        $this->commande->fetchObjectLinked();
80
		return $this->_cleanObjectDatas($this->commande);
81
    }
82
83
    
84
   
85
    /**
86
     * List orders
87
     *
88
     * Get a list of orders
89
     *
90
     * @param string	       $sortfield	        Sort field
91
     * @param string	       $sortorder	        Sort order
92
     * @param int		       $limit		        Limit for list
93
     * @param int		       $page		        Page number
94
     * @param string   	       $thirdparty_ids	    Thirdparty ids to filter orders of. {@example '1' or '1,2,3'} {@pattern /^[0-9,]*$/i}
95
     * @param string           $sqlfilters          Other criteria to filter answers separated by a comma. Syntax example "(t.ref:like:'SO-%') and (t.date_creation:<:'20160101')"
96
     * @return  array                               Array of order objects
97
     *
98
	 * @throws RestException
99
     */
100
    function index($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $thirdparty_ids = '', $sqlfilters = '') {
101
        global $db, $conf;
102
103
        $obj_ret = array();
104
        
105
        // case of external user, $thirdparty_ids param is ignored and replaced by user's socid
106
        $socids = DolibarrApiAccess::$user->societe_id ? DolibarrApiAccess::$user->societe_id : $thirdparty_ids;
107
108
        // If the internal user must only see his customers, force searching by him
109
        $search_sale = 0;
110
        if (! DolibarrApiAccess::$user->rights->societe->client->voir && !$socids) $search_sale = DolibarrApiAccess::$user->id;
111
112
        $sql = "SELECT t.rowid";
113
        if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socids) || $search_sale > 0) $sql .= ", sc.fk_soc, sc.fk_user"; // We need these fields in order to filter by sale (including the case where the user can only see his prospects)
114
        $sql.= " FROM ".MAIN_DB_PREFIX."commande as t";
115
116
        if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socids) || $search_sale > 0) $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; // We need this table joined to the select in order to filter by sale
117
118
        $sql.= ' WHERE t.entity IN ('.getEntity('commande', 1).')';
119
        if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socids) || $search_sale > 0) $sql.= " AND t.fk_soc = sc.fk_soc";
120
        if ($socids) $sql.= " AND t.fk_soc IN (".$socids.")";
121
        if ($search_sale > 0) $sql.= " AND t.rowid = sc.fk_soc";		// Join for the needed table to filter by sale
122
        // Insert sale filter
123
        if ($search_sale > 0)
124
        {
125
            $sql .= " AND sc.fk_user = ".$search_sale;
126
        }
127
        // Add sql filters
128
        if ($sqlfilters) 
129
        {
130
            if (! DolibarrApi::_checkFilters($sqlfilters))
131
            {
132
                throw new RestException(503, 'Error when validating parameter sqlfilters '.$sqlfilters);
133
            }
134
	        $regexstring='\(([^:\'\(\)]+:[^:\'\(\)]+:[^:\(\)]+)\)';
135
            $sql.=" AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")";
136
        }
137
        
138
        $sql.= $db->order($sortfield, $sortorder);
139
        if ($limit)	{
140
            if ($page < 0)
141
            {
142
                $page = 0;
143
            }
144
            $offset = $limit * $page;
145
146
            $sql.= $db->plimit($limit + 1, $offset);
147
        }
148
149
        dol_syslog("API Rest request");
150
        $result = $db->query($sql);
151
152
        if ($result)
153
        {
154
            $num = $db->num_rows($result);
155
            while ($i < min($num, ($limit <= 0 ? $num : $limit)))
0 ignored issues
show
Bug introduced by
The variable $i does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
156
            {
157
                $obj = $db->fetch_object($result);
158
                $commande_static = new Commande($db);
159
                if($commande_static->fetch($obj->rowid)) {
160
                    $obj_ret[] = $this->_cleanObjectDatas($commande_static);
161
                }
162
                $i++;
163
            }
164
        }
165
        else {
166
            throw new RestException(503, 'Error when retrieve commande list : '.$db->lasterror());
167
        }
168
        if( ! count($obj_ret)) {
169
            throw new RestException(404, 'No order found');
170
        }
171
		return $obj_ret;
172
    }
173
174
    /**
175
     * Create order object
176
     *
177
     * @param   array   $request_data   Request data
178
     * @return  int     ID of commande
179
     */
180
    function post($request_data = NULL)
181
    {
182
      if(! DolibarrApiAccess::$user->rights->commande->creer) {
183
			  throw new RestException(401, "Insuffisant rights");
184
		  }
185
        // Check mandatory fields
186
        $result = $this->_validate($request_data);
1 ignored issue
show
Bug introduced by
It seems like $request_data defined by parameter $request_data on line 180 can also be of type null; however, Orders::_validate() does only seem to accept array, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
187
188
        foreach($request_data as $field => $value) {
189
            $this->commande->$field = $value;
190
        }
191
        /*if (isset($request_data["lines"])) {
192
          $lines = array();
193
          foreach ($request_data["lines"] as $line) {
194
            array_push($lines, (object) $line);
195
          }
196
          $this->commande->lines = $lines;
197
        }*/
198
        if ($this->commande->create(DolibarrApiAccess::$user) < 0) {
199
            throw new RestException(500, "Error creating order", array_merge(array($this->commande->error), $this->commande->errors));
200
        }
201
202
        return $this->commande->id;
203
    }
204
205
    /**
206
     * Get lines of an order
207
     *
208
     * @param int   $id             Id of order
209
     *
210
     * @url	GET {id}/lines
211
     *
212
     * @return int
213
     */
214
    function getLines($id) {
215
      if(! DolibarrApiAccess::$user->rights->commande->lire) {
216
		  	throw new RestException(401);
217
		  }
218
219
      $result = $this->commande->fetch($id);
220
      if( ! $result ) {
221
         throw new RestException(404, 'Order not found');
222
      }
223
224
		  if( ! DolibarrApi::_checkAccessToResource('commande',$this->commande->id)) {
225
			  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
226
      }
227
      $this->commande->getLinesArray();
228
      $result = array();
229
      foreach ($this->commande->lines as $line) {
230
        array_push($result,$this->_cleanObjectDatas($line));
231
      }
232
      return $result;
233
    }
234
235
    /**
236
     * Add a line to given order
237
     *
238
     * @param int   $id             Id of commande to update
239
     * @param array $request_data   Orderline data
240
     *
241
     * @url	POST {id}/lines
242
     *
243
     * @return int
244
     */
245
    function postLine($id, $request_data = NULL) {
246
      if(! DolibarrApiAccess::$user->rights->commande->creer) {
247
		  	throw new RestException(401);
248
		  }
249
250
      $result = $this->commande->fetch($id);
251
      if( ! $result ) {
252
         throw new RestException(404, 'Order not found');
253
      }
254
255
		  if( ! DolibarrApi::_checkAccessToResource('commande',$this->commande->id)) {
256
			  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
257
      }
258
			$request_data = (object) $request_data;
259
      $updateRes = $this->commande->addline(
260
                        $request_data->desc,
261
                        $request_data->subprice,
262
                        $request_data->qty,
263
                        $request_data->tva_tx,
264
                        $request_data->localtax1_tx,
265
                        $request_data->localtax2_tx,
266
                        $request_data->fk_product,
267
                        $request_data->remise_percent,
268
                        $request_data->info_bits,
269
                        $request_data->fk_remise_except,
270
                        'HT',
271
                        0,
272
                        $request_data->date_start,
273
                        $request_data->date_end,
274
                        $request_data->product_type,
275
                        $request_data->rang,
276
                        $request_data->special_code,
277
                        $fk_parent_line,
0 ignored issues
show
Bug introduced by
The variable $fk_parent_line does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
278
                        $request_data->fk_fournprice,
279
                        $request_data->pa_ht,
280
                        $request_data->label,
281
                        $request_data->array_options,
282
                        $request_data->fk_unit,
283
                        $this->element,
284
                        $request_data->id
285
      );
286
287
      if ($updateRes > 0) {
288
        return $this->get($id)->line->rowid;
289
290
      }
291
      return false;
292
    }
293
294
    /**
295
     * Update a line to given order
296
     *
297
     * @param int   $id             Id of commande to update
298
     * @param int   $lineid         Id of line to update
299
     * @param array $request_data   Orderline data
300
     *
301
     * @url	PUT {id}/lines/{lineid}
302
     *
303
     * @return object
304
     */
305
    function putLine($id, $lineid, $request_data = NULL) {
306
      if(! DolibarrApiAccess::$user->rights->commande->creer) {
307
		  	throw new RestException(401);
308
		  }
309
310
      $result = $this->commande->fetch($id);
311
      if( ! $result ) {
312
         throw new RestException(404, 'Commande not found');
313
      }
314
315
		  if( ! DolibarrApi::_checkAccessToResource('commande',$this->commande->id)) {
316
			  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
317
      }
318
			$request_data = (object) $request_data;
319
      $updateRes = $this->commande->updateline(
320
                        $lineid,
321
                        $request_data->desc,
322
                        $request_data->subprice,
323
                        $request_data->qty,
324
                        $request_data->remise_percent,
325
                        $request_data->tva_tx,
326
                        $request_data->localtax1_tx,
327
                        $request_data->localtax2_tx,
328
                        'HT',
329
                        $request_data->info_bits,
330
                        $request_data->date_start,
331
                        $request_data->date_end,
332
                        $request_data->product_type,
333
                        $request_data->fk_parent_line,
334
                        0,
335
                        $request_data->fk_fournprice,
336
                        $request_data->pa_ht,
337
                        $request_data->label,
338
                        $request_data->special_code,
339
                        $request_data->array_options,
340
                        $request_data->fk_unit
341
      );
342
343
      if ($updateRes > 0) {
344
        $result = $this->get($id);
345
        unset($result->line);
346
        return $this->_cleanObjectDatas($result);
347
      }
348
      return false;
349
    }
350
351
    /**
352
     * Delete a line to given order
353
     *
354
     *
355
     * @param int   $id             Id of commande to update
356
     * @param int   $lineid         Id of line to delete
357
     *
358
     * @url	DELETE {id}/lines/{lineid}
359
     *
360
     * @return int
361
     */
362
    function delLine($id, $lineid) {
363
      if(! DolibarrApiAccess::$user->rights->commande->creer) {
364
		  	throw new RestException(401);
365
		  }
366
367
      $result = $this->commande->fetch($id);
368
      if( ! $result ) {
369
         throw new RestException(404, 'Commande not found');
370
      }
371
372
		  if( ! DolibarrApi::_checkAccessToResource('commande',$this->commande->id)) {
373
			  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
374
      }
375
			$request_data = (object) $request_data;
0 ignored issues
show
Bug introduced by
The variable $request_data seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
376
      $updateRes = $this->commande->deleteline(DolibarrApiAccess::$user,$lineid);
377
      if ($updateRes > 0) {
378
        return $this->get($id);
379
      }
380
      return false;
381
    }
382
383
    /**
384
     * Update order general fields (won't touch lines of order)
385
     *
386
     * @param int   $id             Id of commande to update
387
     * @param array $request_data   Datas
388
     *
389
     * @return int
390
     */
391
    function put($id, $request_data = NULL) {
392
      if(! DolibarrApiAccess::$user->rights->commande->creer) {
393
		  	throw new RestException(401);
394
		  }
395
396
        $result = $this->commande->fetch($id);
397
        if( ! $result ) {
398
            throw new RestException(404, 'Commande not found');
399
        }
400
401
		if( ! DolibarrApi::_checkAccessToResource('commande',$this->commande->id)) {
402
			throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
403
		}
404
        foreach($request_data as $field => $value) {
405
            if ($field == 'id') continue;
406
            $this->commande->$field = $value;
407
        }
408
409
        if($this->commande->update($id, DolibarrApiAccess::$user, 1, '', '', 'update'))
410
            return $this->get($id);
411
412
        return false;
413
    }
414
415
    /**
416
     * Delete order
417
     *
418
     * @param   int     $id         Order ID
419
     *
420
     * @return  array
421
     */
422
    function delete($id)
423
    {
424
        if(! DolibarrApiAccess::$user->rights->commande->supprimer) {
425
			throw new RestException(401);
426
		}
427
        $result = $this->commande->fetch($id);
428
        if( ! $result ) {
429
            throw new RestException(404, 'Order not found');
430
        }
431
432
		if( ! DolibarrApi::_checkAccessToResource('commande',$this->commande->id)) {
433
			throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
434
		}
435
436
        if( ! $this->commande->delete(DolibarrApiAccess::$user)) {
437
            throw new RestException(500, 'Error when delete order : '.$this->commande->error);
438
        }
439
440
        return array(
441
            'success' => array(
442
                'code' => 200,
443
                'message' => 'Order deleted'
444
            )
445
        );
446
447
    }
448
449
    /**
450
     * Validate an order
451
     *
452
     * @param   int $id             Order ID
453
     * @param   int $idwarehouse    Warehouse ID
454
     * @param   int $notrigger      1=Does not execute triggers, 0= execute triggers
455
     *
456
     * @url POST    {id}/validate
457
     *
458
     * @return  array
459
     * FIXME An error 403 is returned if the request has an empty body.
460
     * Error message: "Forbidden: Content type `text/plain` is not supported."
461
     * Workaround: send this in the body
462
     * {
463
     *   "idwarehouse": 0,
464
     *   "notrigger": 0
465
     * }
466
     */
467
    function validate($id, $idwarehouse=0, $notrigger=0)
468
    {
469
        if(! DolibarrApiAccess::$user->rights->commande->creer) {
470
			throw new RestException(401);
471
		}
472
        $result = $this->commande->fetch($id);
473
        if( ! $result ) {
474
            throw new RestException(404, 'Order not found');
475
        }
476
477
		if( ! DolibarrApi::_checkAccessToResource('commande',$this->commande->id)) {
478
			throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
479
		}
480
481
		$result = $this->commande->valid(DolibarrApiAccess::$user, $idwarehouse, $notrigger);
482
		if ($result == 0) {
483
		    throw new RestException(500, 'Error nothing done. May be object is already validated');
484
		}
485
		if ($result < 0) {
486
		    throw new RestException(500, 'Error when validating Order: '.$this->commande->error);
487
		}
488
489
        return array(
490
            'success' => array(
491
                'code' => 200,
492
                'message' => 'Order validated'
493
            )
494
        );
495
    }
496
497
    /**
498
     * Clean sensible object datas
499
     *
500
     * @param   object  $object    Object to clean
501
     * @return    array    Array of cleaned object properties
502
     */
503
    function _cleanObjectDatas($object) {
504
    
505
        $object = parent::_cleanObjectDatas($object);
506
    
507
        unset($object->address);
508
    
509
        return $object;
510
    }
511
    
512
    /**
513
     * Validate fields before create or update object
514
     *
515
     * @param   array           $data   Array with data to verify
516
     * @return  array
517
     * @throws  RestException
518
     */
519
    function _validate($data)
520
    {
521
        $commande = array();
522
        foreach (Orders::$FIELDS as $field) {
523
            if (!isset($data[$field]))
524
                throw new RestException(400, "$field field missing");
525
            $commande[$field] = $data[$field];
526
527
        }
528
        return $commande;
529
    }
530
}
531