Issues (51)

Security Analysis    no request data  

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

src/GoodTillSystem.php (9 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace FLAIRUK\GoodTillSystem;
4
5
use Illuminate\Support\Facades\Http;
6
use Illuminate\Support\Facades\Config;
7
use FLAIRUK\GoodTillSystem\RESTInterface;
8
9
use FLAIRUK\GoodTillSystem\Models\Sale;
10
use FLAIRUK\GoodTillSystem\Models\Staff;
11
use FLAIRUK\GoodTillSystem\Models\Brand;
12
use FLAIRUK\GoodTillSystem\Models\Report;
13
use FLAIRUK\GoodTillSystem\Models\Outlet;
14
use FLAIRUK\GoodTillSystem\Models\VATRate;
15
use FLAIRUK\GoodTillSystem\Models\Voucher;
16
use FLAIRUK\GoodTillSystem\Models\Product;
17
use FLAIRUK\GoodTillSystem\Models\Loyalty;
18
use FLAIRUK\GoodTillSystem\Models\Customer;
19
use FLAIRUK\GoodTillSystem\Models\Register;
20
use FLAIRUK\GoodTillSystem\Models\Category;
21
use FLAIRUK\GoodTillSystem\Models\StaffClock;
22
use FLAIRUK\GoodTillSystem\Models\PaymentType;
23
use FLAIRUK\GoodTillSystem\Models\ExternalSale;
24
25
class GoodTillSystem extends Authorize {
26
        
27
    /**
28
     * Good Till: Connect
29
     * 
30
     * @param string $subdomain
31
     * @param string $username
32
     * @param string $password
33
     * @return void
34
     */
35
    public static function connect(
36
        string $subdomain, string $username, string $password
0 ignored issues
show
The parameter $subdomain is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
The parameter $username is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
The parameter $password is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
37
    ): void {
38
        // self::authorize()); WIPO
39
    }
40
41
    /**
42
     * Good Till: Prepare
43
     * 
44
     * @param RESTInterface $model
45
     * @return RESTInterface
46
     */
47
    public static function prepare(RESTInterface $model, string $id = null): RESTInterface {
48
        if ($id) $model->setID($id);
0 ignored issues
show
Bug Best Practice introduced by
The expression $id of type null|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
It seems like you code against a concrete implementation and not the interface FLAIRUK\GoodTillSystem\RESTInterface as the method setID() does only exist in the following implementations of said interface: FLAIRUK\GoodTillSystem\Models\Brand, FLAIRUK\GoodTillSystem\Models\Customer, FLAIRUK\GoodTillSystem\Models\Loyalty, FLAIRUK\GoodTillSystem\Models\Outlet, FLAIRUK\GoodTillSystem\Models\Product, FLAIRUK\GoodTillSystem\Models\Register, FLAIRUK\GoodTillSystem\Models\Staff, FLAIRUK\GoodTillSystem\Models\VATRate, FLAIRUK\GoodTillSystem\Models\Voucher.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
49
        
50
        $model->setURL($id);
0 ignored issues
show
It seems like you code against a concrete implementation and not the interface FLAIRUK\GoodTillSystem\RESTInterface as the method setURL() does only exist in the following implementations of said interface: FLAIRUK\GoodTillSystem\Models\Brand, FLAIRUK\GoodTillSystem\Models\Customer, FLAIRUK\GoodTillSystem\Models\ExternalSale, FLAIRUK\GoodTillSystem\Models\Loyalty, FLAIRUK\GoodTillSystem\Models\Outlet, FLAIRUK\GoodTillSystem\Models\PaymentType, FLAIRUK\GoodTillSystem\Models\Product, FLAIRUK\GoodTillSystem\Models\Register, FLAIRUK\GoodTillSystem\Models\Report, FLAIRUK\GoodTillSystem\Models\Sale, FLAIRUK\GoodTillSystem\Models\Staff, FLAIRUK\GoodTillSystem\Models\VATRate, FLAIRUK\GoodTillSystem\Models\Voucher.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
51
        return $model;
52
    }
53
54
    /**
55
     * Good Till: API
56
     * 
57
     * @param RESTInterface $model
58
     * @return RESTInterface
59
     */
60
    public static function api(RESTInterface $model): RESTInterface {
61
        return $model;
62
    }
63
64
    /**
65
     * Good Till API: Customer
66
     * 
67
     * @param string $id
68
     * @return Customer
69
     * 
70
     * @source https://apidoc.thegoodtill.com/#api-Customer
71
     */
72
    public static function customer(string $id): Customer {
73
        return self::customers($id);
74
    }
75
76
    /**
77
     * Good Till API: Customers
78
     * 
79
     * @param null|string $id
80
     * @return Customer
81
     * 
82
     * @source https://apidoc.thegoodtill.com/#api-Customer
83
     */
84
    public static function customers(string $id = null): Customer {
85
        return self::api(self::prepare(new Customer(self::authorize()), $id ?? $id));
86
    }
87
88
    /**
89
     * Good Till API: Customer Group
90
     * 
91
     * @param null|string $id
92
     * @return CustomerGroup
93
     * 
94
     * @source https://apidoc.thegoodtill.com/#api-CustomerGroup
95
     */
96
    public static function customerGroup(string $id): CustomerGroup {
97
        return self::customerGroups($id);
98
    }
99
100
    /**
101
     * Good Till API: Customer Group
102
     * 
103
     * @param null|string $id
104
     * @return CustomerGroup
105
     * 
106
     * @source https://apidoc.thegoodtill.com/#api-CustomerGroup
107
     */
108
    public static function customerGroups(string $id = null): CustomerGroup {
109
        return self::api(self::prepare(new CustomerGroup(self::authorize()), $id ?? $id));
110
    }
111
112
    /**
113
     * Good Till API: Product
114
     * 
115
     * @param string $id
116
     * @return Product
117
     * 
118
     * @source https://apidoc.thegoodtill.com/#api-Product
119
     */  
120
    public static function product(string $id): Product {
121
        return self::products($id);
122
    }
123
124
    /**
125
     * Good Till API: Products
126
     * 
127
     * @param null|string $id
128
     * @return Product
129
     * 
130
     * @source https://apidoc.thegoodtill.com/#api-Product
131
     */
132
    public static function products(string $id = null): Product {
133
        return self::api(self::prepare(new Product(self::authorize()), $id ?? $id));
134
    }
135
136
    /**
137
     * Good Till API: Brand
138
     * 
139
     * @param string $id
140
     * @return Brand
141
     * 
142
     * @source https://apidoc.thegoodtill.com/#api-Brand
143
     */
144
    public static function brand(string $id): Brand {
145
        return self::brands($id);
146
    }
147
148
    /**
149
    * Create a new GoodTill instance.
150
     * @param null|string $id
151
     * @return Brand
152
     * 
153
     * @source https://apidoc.thegoodtill.com/#api-Brand
154
     */
155
    public static function brands(string $id = null): Brand {
156
        return self::api(self::prepare(new Brand(self::authorize()), $id ?? $id));
157
    }
158
159
    /**
160
     * Good Till API: Category
161
     * 
162
     * @param string $id
163
     * @return Category
164
     * 
165
     * @source https://apidoc.thegoodtill.com/#api-Category
166
     */
167
    public static function category(string $id): Category {
168
        return self::categories($id);
169
    }
170
171
    /**
172
     * Good Till API: Categories
173
     * 
174
     * @param null|string $id
175
     * @return Category
176
     * 
177
     * @source https://apidoc.thegoodtill.com/#api-Category
178
     */
179
    public static function categories(string $id = null): Category {
180
        return self::api(self::prepare(new Category(self::authorize()), $id ?? $id));
0 ignored issues
show
The call to Category::__construct() misses a required argument $url.

This check looks for function calls that miss required arguments.

Loading history...
181
    }
182
183
    /**
184
     * Good Till API: Tag
185
     * 
186
     * @param string $id
187
     * @return Tag
188
     * 
189
     * @source https://apidoc.thegoodtill.com/#api-Tag
190
     */
191
    public static function tag(string $id): Tag {
192
        return self::tags($id);
193
    }
194
195
    /**
196
     * Good Till API: Tags
197
     * 
198
     * @param null|string $id
199
     * @return Tag
200
     * 
201
     * @source https://apidoc.thegoodtill.com/#api-Tag
202
     */
203
    public static function tags(string $id = null): Tag {
204
        return self::api(self::prepare(new Tag(self::authorize()), $id ?? $id));
205
    }
206
207
    /**
208
     * Good Till API: Outlets
209
     * 
210
     * @param string $id
211
     * @return Supplier
212
     * 
213
     * @source https://apidoc.thegoodtill.com/#api-Supplier
214
     */
215
    public static function supplier(string $id): Supplier {
216
        return self::suppliers($id);
217
    }
218
219
    /**
220
     * Good Till API: Suppliers
221
     * 
222
     * @param null|string $id
223
     * @return Supplier
224
     * 
225
     * @source https://apidoc.thegoodtill.com/#api-Supplier
226
     */
227
    public static function suppliers(string $id = null): Supplier {
228
        return self::api(self::prepare(new Supplier(self::authorize()), $id ?? $id));
229
    }
230
231
    /**
232
     * Good Till API: Ingredient
233
     * 
234
     * @param string $id
235
     * @return Ingredient
236
     * 
237
     * @source https://apidoc.thegoodtill.com/#api-Ingredient
238
     */
239
    public static function ingredient(string $id): Ingredient {
240
        return self::ingredients($id);
241
    }
242
243
    /**
244
     * Good Till API: Ingredients
245
     * 
246
     * @param null|string $id
247
     * @return Ingredient
248
     * 
249
     * @source https://apidoc.thegoodtill.com/#api-Ingredient
250
     */
251
    public static function ingredients(string $id = null): Ingredient {
252
        return self::api(self::prepare(new Ingredient(self::authorize()), $id ?? $id));
253
    }
254
255
    /**
256
     * Good Till API: Selling Layout
257
     * 
258
     * @param string $id
259
     * @return SellingLayout
260
     * 
261
     * @source https://apidoc.thegoodtill.com/#api-SellingLayout
262
     */
263
    public static function sellingLayout(string $id): SellingLayout {
264
        return self::sellingLayouts($id);
265
    }
266
267
    /**
268
     * Good Till API: Selling Layout
269
     * 
270
     * @param null|string $id
271
     * @return SellingLayout
272
     * 
273
     * @source https://apidoc.thegoodtill.com/#api-SellingLayout
274
     */
275
    public static function sellingLayouts(string $id = null): SellingLayout {
276
        return self::api(self::prepare(new SellingLayout(self::authorize()), $id ?? $id));
277
    }
278
279
    /**
280
     * Good Till API: Ecommerce
281
     * 
282
     * @param null|string $id
283
     * @return Ecommerce
284
     * 
285
     * @source https://apidoc.thegoodtill.com/#api-Ecommerce
286
     */
287
    public static function ecommerce(string $id = null): Ecommerce {
288
        return self::api(self::prepare(new Ecommerce(self::authorize()), $id ?? $id));
289
    }
290
291
    /**
292
     * Good Till API: Staff
293
     * 
294
     * @param null|string $id
295
     * @return Staff
296
     * 
297
     * @source https://apidoc.thegoodtill.com/#api-Staff
298
     */
299
    public static function staff(string $id = null): Staff {
300
        return self::api(self::prepare(new Staff(self::authorize()), $id ?? $id));
301
    }
302
303
    /**
304
     * Good Till API: Outlets
305
     * 
306
     * @param null|string $id
307
     * @return Outlet
308
     * 
309
     * @source https://apidoc.thegoodtill.com/#api-Tag
310
     */
311
    public static function staffClock(string $id = null) {
0 ignored issues
show
The parameter $id is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
312
        return new OutletService;
313
    }
314
315
    /**
316
     * Good Till API: Sale
317
     * 
318
     * @param string $id
319
     * @return Sale
320
     * 
321
     * @source https://apidoc.thegoodtill.com/#api-Tag
322
     */
323
    public static function sale(string $id): Sales {
324
        return self::sales($id);
325
    }
326
327
    /**
328
     * Good Till API: Sales
329
     * 
330
     * @param null|string $id
331
     * @return Sale
332
     * 
333
     * @source https://apidoc.thegoodtill.com/#api-Tag
334
     */
335
    public static function sales(string $id = null): Sale {
336
        return self::api(self::prepare(new Sale(self::authorize()), $id ?? $id));
337
    }
338
339
    /**
340
     * Good Till API: External Sale
341
     * 
342
     * @param null|string $id
343
     * @return ExternalSale
344
     * 
345
     * @source https://apidoc.thegoodtill.com/#api-ExternalSale
346
     */
347
    public static function externalSale(string $id = null): ExternalSale {
348
        return self::api(self::prepare(new ExternalSale(self::authorize()), $id ?? $id));
349
    }
350
    
351
    /**
352
     * Good Till API: External Sale
353
     * 
354
     * @param null|string $id
0 ignored issues
show
There is no parameter named $id. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
355
     * @return ExternalSale
356
     * 
357
     * @source https://apidoc.thegoodtill.com/#api-ExternalSale
358
     */
359
    public static function external(): ExternalSale {
360
        return self::externalSale();
361
    }
362
363
    /**
364
     * Good Till API: VAT Rate
365
     * 
366
     * @param string $id
367
     * @return VATRate
368
     * 
369
     * @source https://apidoc.thegoodtill.com/#api-VatRate
370
     */
371
    public static function vatRate(string $id): VATRate {
372
        return self::vatRates($id);
373
    }
374
375
    /**
376
     * Good Till API: VAT Rates
377
     * 
378
     * @param string|null $id
379
     * @return VATRate
380
     * 
381
     * @source https://apidoc.thegoodtill.com/#api-VatRate
382
     */
383
    public static function vatRates(string $id = null): VATRate {
384
        return self::api(self::prepare(new VATRate(self::authorize()), $id ?? $id));
385
    }
386
387
    /**
388
     * Good Till API: Payment Type
389
     * 
390
     * @param string $id
391
     * @return PaymentType
392
     * 
393
     * @source https://apidoc.thegoodtill.com/#api-PaymentType
394
     */
395
    public static function paymentType(string $id): PaymentType {
396
        return self::paymentTypes($id);
397
    }
398
399
    /**
400
     * Good Till API: Payment Types
401
     * 
402
     * @param null|string $id
403
     * @return PaymentType
404
     * 
405
     * @source https://apidoc.thegoodtill.com/#api-PaymentType
406
     */
407
    public static function paymentTypes(string $id = null): PaymentType {
408
        return self::api(self::prepare(new PaymentType(self::authorize()), $id ?? $id));
409
    }
410
411
    /**
412
     * Good Till API: Register
413
     * 
414
     * @return Register
415
     * 
416
     * @source Undocument Feature
417
     * @source https://apidoc.thegoodtill.com/#api-Register
418
     */
419
    public static function register(string $id): Register {
420
        return self::registers($id);
421
    }
422
423
    /**
424
     * Good Till API: Registers
425
     * 
426
     * @param string|null $id
427
     * @return Register
428
     * 
429
     * @source https://apidoc.thegoodtill.com/#api-Register
430
     */
431
    public static function registers(string $id = null): Register {
432
        return self::api(self::prepare(new Register(self::authorize()), $id ?? $id));
433
    }
434
435
    /**
436
     * Good Till API: Vouchers
437
     * 
438
     * @return Voucher
439
     * 
440
     * @source Good Till Pro Feature
441
     * @source https://apidoc.thegoodtill.com/#api-Voucher
442
     */
443
    public static function vouchers(string $id = null): Voucher {
444
        return self::api(self::prepare(new Voucher(self::authorize()), $id ?? $id));
445
    }
446
447
    /**
448
     * Good Till API: Loyalty
449
     * 
450
     * @param string $id
451
     * @return Loyalty
452
     * 
453
     * @source https://apidoc.thegoodtill.com/#api-Loyalty
454
     */
455
    public static function loyalty(string $id): Loyalty {
456
        return self::loyalties($id);
457
    }
458
459
    /**
460
     * Good Till API: Loyalties
461
     * 
462
     * @return Loyalty
463
     * 
464
     * @source https://apidoc.thegoodtill.com/#api-Loyalty
465
     */
466
    public static function loyalties(string $id = null): Loyalty {
467
        return self::api(self::prepare(new Loyalty(self::authorize()), $id ?? $id));
468
    }
469
470
    /**
471
     * Good Till API: Report
472
     * 
473
     * @param string $id
474
     * @return Report
475
     * 
476
     * @source https://apidoc.thegoodtill.com/#api-Report
477
     */
478
    public static function report(string $id): Report {
479
        return self::reports($id);
480
    }
481
482
    /**
483
     * Good Till API: Reports
484
     * 
485
     * @return Report
486
     * 
487
     * @source https://apidoc.thegoodtill.com/#api-Report
488
     */
489
    public static function reports(string $id = null): Report {
490
        return self::api(self::prepare(new Report(self::authorize()), $id ?? $id));
491
    }
492
493
    /**
494
     * Good Till API: Outlet
495
     * 
496
     * @param string $id
497
     * @return Outlet
498
     * 
499
     * @source https://apidoc.thegoodtill.com/#api-Outlet
500
     */
501
    public static function outlet(string $id): Outlet {
502
        return self::outlets($id);
503
    }
504
505
    /**
506
     * Good Till API: Outlets
507
     * 
508
     * @param null|string $id
509
     * @return Outlet
510
     * 
511
     * @source https://apidoc.thegoodtill.com/#api-Outlet
512
     */
513
    public static function outlets(string $id = null): Outlet {
514
        return self::api(self::prepare(new Outlet(self::authorize()), $id ?? $id));
515
    }
516
}
517