Test Failed
Push — master ( 3b9b23...4cf4fc )
by Maximo
02:05
created

Manager   C

Complexity

Total Complexity 53

Size/Duplication

Total Lines 546
Duplicated Lines 0 %

Test Coverage

Coverage 4.05%

Importance

Changes 0
Metric Value
eloc 157
dl 0
loc 546
ccs 7
cts 173
cp 0.0405
rs 6.96
c 0
b 0
f 0
wmc 53

20 Methods

Rating   Name   Duplication   Size   Complexity  
A getResources() 0 8 2
A getNoArgumentsDefaultAction() 0 3 1
A addResource() 0 36 6
A allow() 0 3 1
B insertOrUpdateAccess() 0 41 6
A addRole() 0 29 5
A isAllowed() 0 32 2
A addInherit() 0 16 3
A getApp() 0 9 2
A deny() 0 3 1
A setApp() 0 3 1
A isRole() 0 8 1
A setNoArgumentsDefaultAction() 0 3 1
A dropResourceAccess() 0 3 1
A addResourceAccess() 0 21 5
A getRoles() 0 8 2
A allowOrDeny() 0 10 4
A setCompany() 0 3 1
B __construct() 0 16 7
A isResource() 0 8 1

How to fix   Complexity   

Complex Class

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

1
<?php
0 ignored issues
show
Coding Style introduced by
End of line character is invalid; expected "\n" but found "\r\n"
Loading history...
2
declare(strict_types=1);
3
4
namespace Gewaer\Acl;
5
6
use Phalcon\Db;
7
use Phalcon\Db\AdapterInterface as DbAdapter;
8
use Phalcon\Acl\Exception;
9
use Phalcon\Acl\Resource;
10
use Phalcon\Acl;
11
use Phalcon\Acl\Role;
12
use Phalcon\Acl\RoleInterface;
13
use Gewaer\Models\Companies;
14
use Gewaer\Models\Apps;
15
use Phalcon\Acl\Adapter\Database as PhalconAclDatabaseAdapter;
16
use Phalcon\Acl\Adapter;
17
use BadMethodCallException;
18
19
/**
20
 * Phalcon\Acl\Adapter\Database
21
 * Manages Geweaer Multi tenant ACL lists in database
22
 * 
23
 * #extends PhalconAclDatabaseAdapter #had to comments it out testing breaking
24
 */
25
class Manager extends Adapter
26
{
27
    /**
28
     * @var DbAdapter
29
     */
30
    protected $connection;
31
32
    /**
33
     * Roles table
34
     * @var string
35
     */
36
    protected $roles;
37
38
    /**
39
     * Resources table
40
     * @var string
41
     */
42
    protected $resources;
43
44
    /**
45
     * Resources Accesses table
46
     * @var string
47
     */
48
    protected $resourcesAccesses;
49
50
    /**
51
     * Access List table
52
     * @var string
53
     */
54
    protected $accessList;
55
56
    /**
57
     * Roles Inherits table
58
     * @var string
59
     */
60
    protected $rolesInherits;
61
62
    /**
63
     * Default action for no arguments is allow
64
     * @var int
65
     */
66
    protected $noArgumentsDefaultAction = Acl::ALLOW;
67
68
    /**
69
     * Company Object
70
     *
71
     * @var Companies
72
     */
73
    protected $company;
74
75
    /**
76
     * App Objc
77
     *
78
     * @var Apps
79
     */
80
    protected $app;
81
82
      /**
83
     * Class constructor.
84
     *
85
     * @param  array $options Adapter config
86
     * @throws Exception
87
     */
88 1
    public function __construct(array $options)
89
    {
90 1
        if (!isset($options['db']) || !$options['db'] instanceof DbAdapter) {
91
            throw new Exception(
92
                'Parameter "db" is required and it must be an instance of Phalcon\Acl\AdapterInterface'
93
            );
94
        }
95
96 1
        $this->connection = $options['db'];
97
98 1
        foreach (['roles', 'resources', 'resourcesAccesses', 'accessList', 'rolesInherits'] as $table) {
99 1
            if (!isset($options[$table]) || empty($options[$table]) || !is_string($options[$table])) {
100
                throw new Exception("Parameter '{$table}' is required and it must be a non empty string");
101
            }
102
103 1
            $this->{$table} = $this->connection->escapeIdentifier($options[$table]);
104
        }
105 1
    }
106
107
    /**
108
     * Set current user Company
109
     *
110
     * @param Companies $company
111
     * @return void
112
     */
113
    public function setCompany(Companies $company): void
114
    {
115
        $this->company = $company;
116
    }
117
118
    /**
119
     * Set current user app
120
     *
121
     * @param Apps $app
122
     * @return void
123
     */
124
    public function setApp(Apps $app): void
125
    {
126
        $this->app = $app;
127
    }
128
129
    /**
130
     * Get the current App
131
     *
132
     * @return void
133
     */
134
    public function getApp(): Apps
135
    {
136
        if (!is_object($this->app)) {
137
            $this->app = new Apps();
138
            $this->app->id = 0;
139
            $this->app->name = 'Canvas';
140
        }
141
142
        return $this->app;
1 ignored issue
show
Bug Best Practice introduced by
The expression return $this->app returns the type Gewaer\Models\Apps which is incompatible with the documented return type void.
Loading history...
143
    }
144
145
    /**
146
     * {@inheritdoc}
147
     *
148
     * Example:
149
     * <code>
150
     * $acl->addRole(new Phalcon\Acl\Role('administrator'), 'consultor');
151
     * $acl->addRole('administrator', 'consultor');
152
     * </code>
153
     *
154
     * @param  \Phalcon\Acl\Role|string $role
155
     * @param  string                   $accessInherits
156
     * @return boolean
157
     * @throws \Phalcon\Acl\Exception
158
     */
159
    public function addRole($role, $accessInherits = null): bool
160
    {
161
        if (is_string($role)) {
162
            $role = new Role($role, ucwords($role) . ' Role');
163
        }
164
        if (!$role instanceof RoleInterface) {
1 ignored issue
show
introduced by
$role is always a sub-type of Phalcon\Acl\RoleInterface.
Loading history...
165
            throw new Exception('Role must be either an string or implement RoleInterface');
166
        }
167
168
        $exists = $this->connection->fetchOne(
169
            "SELECT COUNT(*) FROM {$this->roles} WHERE name = ?",
170
            null,
171
            [$role->getName()]
1 ignored issue
show
Bug introduced by
array($role->getName()) of type array<integer,string> is incompatible with the type integer expected by parameter $placeholders of Phalcon\Db\AdapterInterface::fetchOne(). ( Ignorable by Annotation )

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

171
            /** @scrutinizer ignore-type */ [$role->getName()]
Loading history...
172
        );
173
174
        if (!$exists[0]) {
175
            $this->connection->execute(
176
                "INSERT INTO {$this->roles} (name, description, apps_id, created_at) VALUES (?, ?, ?, ?)",
177
                [$role->getName(), $role->getDescription(), $this->getApp()->getId(), date('Y-m-d H:i:s')]
178
            );
179
            $this->connection->execute(
180
                "INSERT INTO {$this->accessList} (roles_name, resources_name, access_name, allowed, apps_id, created_at) VALUES (?, ?, ?, ?, ?, ?)",
181
                [$role->getName(), '*', '*', $this->_defaultAccess, $this->getApp()->getId(), date('Y-m-d H:i:s')]
182
            );
183
        }
184
        if ($accessInherits) {
185
            return $this->addInherit($role->getName(), $accessInherits);
186
        }
187
        return true;
188
    }
189
190
    /**
191
     * {@inheritdoc}
192
     *
193
     * @param  string $roleName
194
     * @param  string $roleToInherit
195
     * @throws \Phalcon\Acl\Exception
196
     */
197
    public function addInherit($roleName, $roleToInherit): bool
198
    {
199
        $sql = "SELECT COUNT(*) FROM {$this->roles} WHERE name = ?";
200
        $exists = $this->connection->fetchOne($sql, null, [$roleName]);
0 ignored issues
show
Bug introduced by
array($roleName) of type array<integer,string> is incompatible with the type integer expected by parameter $placeholders of Phalcon\Db\AdapterInterface::fetchOne(). ( Ignorable by Annotation )

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

200
        $exists = $this->connection->fetchOne($sql, null, /** @scrutinizer ignore-type */ [$roleName]);
Loading history...
201
        if (!$exists[0]) {
202
            throw new Exception("Role '{$roleName}' does not exist in the role list");
203
        }
204
        $exists = $this->connection->fetchOne(
205
            "SELECT COUNT(*) FROM {$this->rolesInherits} WHERE roles_name = ? AND roles_inherit = ?",
206
            null,
207
            [$roleName, $roleToInherit]
0 ignored issues
show
Bug introduced by
array($roleName, $roleToInherit) of type array<integer,string> is incompatible with the type integer expected by parameter $placeholders of Phalcon\Db\AdapterInterface::fetchOne(). ( Ignorable by Annotation )

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

207
            /** @scrutinizer ignore-type */ [$roleName, $roleToInherit]
Loading history...
208
        );
209
        if (!$exists[0]) {
210
            $this->connection->execute(
211
                "INSERT INTO {$this->rolesInherits} VALUES (?, ?)",
212
                [$roleName, $roleToInherit]
213
            );
1 ignored issue
show
Bug Best Practice introduced by
In this branch, the function will implicitly return null which is incompatible with the type-hinted return boolean. Consider adding a return statement or allowing null as return value.

For hinted functions/methods where all return statements with the correct type are only reachable via conditions, ?null? gets implicitly returned which may be incompatible with the hinted type. Let?s take a look at an example:

interface ReturnsInt {
    public function returnsIntHinted(): int;
}

class MyClass implements ReturnsInt {
    public function returnsIntHinted(): int
    {
        if (foo()) {
            return 123;
        }
        // here: null is implicitly returned
    }
}
Loading history...
214
        }
215
    }
216
217
    /**
218
     * {@inheritdoc}
219
     *
220
     * @param  string  $roleName
221
     * @return boolean
222
     */
223
    public function isRole($roleName): bool
224
    {
225
        $exists = $this->connection->fetchOne(
226
            "SELECT COUNT(*) FROM {$this->roles} WHERE name = ?",
227
            null,
228
            [$roleName]
0 ignored issues
show
Bug introduced by
array($roleName) of type array<integer,string> is incompatible with the type integer expected by parameter $placeholders of Phalcon\Db\AdapterInterface::fetchOne(). ( Ignorable by Annotation )

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

228
            /** @scrutinizer ignore-type */ [$roleName]
Loading history...
229
        );
230
        return (bool) $exists[0];
231
    }
232
233
    /**
234
     * {@inheritdoc}
235
     *
236
     * @param  string  $resourceName
237
     * @return boolean
238
     */
239
    public function isResource($resourceName): bool
240
    {
241
        $exists = $this->connection->fetchOne(
242
            "SELECT COUNT(*) FROM {$this->resources} WHERE name = ?",
243
            null,
244
            [$resourceName]
0 ignored issues
show
Bug introduced by
array($resourceName) of type array<integer,string> is incompatible with the type integer expected by parameter $placeholders of Phalcon\Db\AdapterInterface::fetchOne(). ( Ignorable by Annotation )

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

244
            /** @scrutinizer ignore-type */ [$resourceName]
Loading history...
245
        );
246
        return (bool) $exists[0];
247
    }
248
249
    /**
250
     * {@inheritdoc}
251
     * Example:
252
     * <code>
253
     * //Add a resource to the the list allowing access to an action
254
     * $acl->addResource(new Phalcon\Acl\Resource('customers'), 'search');
255
     * $acl->addResource('customers', 'search');
256
     * //Add a resource  with an access list
257
     * $acl->addResource(new Phalcon\Acl\Resource('customers'), ['create', 'search']);
258
     * $acl->addResource('customers', ['create', 'search']);
259
     * $acl->addResource('App.customers', ['create', 'search']);
260
     * </code>
261
     *
262
     * @param  \Phalcon\Acl\Resource|string $resource
263
     * @param  array|string                 $accessList
264
     * @return boolean
265
     */
266
    public function addResource($resource, $accessList = null): bool
267
    {
268
        if (!is_object($resource)) {
269
            //echeck if we have a dot , taht means we are sending the specific app to use
270
            if (strpos($resource, '.') !== false) {
271
                $appResource = explode('.', $resource);
272
                $resource = $appResource[1];
273
                $appName = $appResource[0];
274
275
                //look for the app and set it
276
                if ($app = Apps::findFirstByName($appName)) {
0 ignored issues
show
Bug introduced by
The method findFirstByName() does not exist on Gewaer\Models\Apps. Since you implemented __callStatic, consider adding a @method annotation. ( Ignorable by Annotation )

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

276
                if ($app = Apps::/** @scrutinizer ignore-call */ findFirstByName($appName)) {
Loading history...
277
                    $this->setApp($app);
278
                }
279
            }
280
281
            $resource = new Resource($resource);
282
        }
283
284
        $exists = $this->connection->fetchOne(
285
            "SELECT COUNT(*) FROM {$this->resources} WHERE name = ?",
286
            null,
287
            [$resource->getName()]
0 ignored issues
show
Bug introduced by
array($resource->getName()) of type array<integer,string> is incompatible with the type integer expected by parameter $placeholders of Phalcon\Db\AdapterInterface::fetchOne(). ( Ignorable by Annotation )

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

287
            /** @scrutinizer ignore-type */ [$resource->getName()]
Loading history...
288
        );
289
290
        if (!$exists[0]) {
291
            $this->connection->execute(
292
                "INSERT INTO {$this->resources} (name, description, apps_id, created_at) VALUES (?, ?, ?, ?)",
293
                [$resource->getName(), $resource->getDescription(), $this->getApp()->getId(), date('Y-m-d H:i:s')]
294
            );
295
        }
296
297
        if ($accessList) {
298
            return $this->addResourceAccess($resource->getName(), $accessList);
299
        }
300
301
        return true;
302
    }
303
304
    /**
305
     * {@inheritdoc}
306
     *
307
     * @param  string       $resourceName
308
     * @param  array|string $accessList
309
     * @return boolean
310
     * @throws \Phalcon\Acl\Exception
311
     */
312
    public function addResourceAccess($resourceName, $accessList): bool
313
    {
314
        if (!$this->isResource($resourceName)) {
315
            throw new Exception("Resource '{$resourceName}' does not exist in ACL");
316
        }
317
318
        $sql = "SELECT COUNT(*) FROM {$this->resourcesAccesses} WHERE resources_name = ? AND access_name = ? AND apps_id = ?";
319
        if (!is_array($accessList)) {
320
            $accessList = [$accessList];
321
        }
322
323
        foreach ($accessList as $accessName) {
324
            $exists = $this->connection->fetchOne($sql, null, [$resourceName, $accessName, $this->getApp()->getId()]);
0 ignored issues
show
Bug introduced by
array($resourceName, $ac...his->getApp()->getId()) of type array<integer,integer|mixed|string> is incompatible with the type integer expected by parameter $placeholders of Phalcon\Db\AdapterInterface::fetchOne(). ( Ignorable by Annotation )

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

324
            $exists = $this->connection->fetchOne($sql, null, /** @scrutinizer ignore-type */ [$resourceName, $accessName, $this->getApp()->getId()]);
Loading history...
325
            if (!$exists[0]) {
326
                $this->connection->execute(
327
                    'INSERT INTO ' . $this->resourcesAccesses . ' (resources_name, access_name, apps_id, created_at) VALUES (?, ?, ?, ?)',
328
                    [$resourceName, $accessName, $this->getApp()->getId(), date('Y-m-d H:i:s')]
329
                );
330
            }
331
        }
332
        return true;
333
    }
334
335
    /**
336
     * {@inheritdoc}
337
     *
338
     * @return \Phalcon\Acl\Resource[]
339
     */
340
    public function getResources(): \Phalcon\Acl\ResourceInterface
341
    {
342
        $resources = [];
343
        $sql = "SELECT * FROM {$this->resources}";
344
        foreach ($this->connection->fetchAll($sql, Db::FETCH_ASSOC) as $row) {
345
            $resources[] = new Resource($row['name'], $row['description']);
346
        }
347
        return $resources;
1 ignored issue
show
Bug Best Practice introduced by
The expression return $resources returns the type Phalcon\Acl\Resource[]|array which is incompatible with the type-hinted return Phalcon\Acl\ResourceInterface.
Loading history...
348
    }
349
350
    /**
351
     * {@inheritdoc}
352
     *
353
     * @return RoleInterface[]
354
     */
355
    public function getRoles(): \Phalcon\Acl\RoleInterface
356
    {
357
        $roles = [];
358
        $sql = "SELECT * FROM {$this->roles}";
359
        foreach ($this->connection->fetchAll($sql, Db::FETCH_ASSOC) as $row) {
360
            $roles[] = new Role($row['name'], $row['description']);
361
        }
362
        return $roles;
1 ignored issue
show
Bug Best Practice introduced by
The expression return $roles returns the type Phalcon\Acl\Role[]|array which is incompatible with the type-hinted return Phalcon\Acl\RoleInterface.
Loading history...
363
    }
364
365
    /**
366
     * {@inheritdoc}
367
     *
368
     * @param string       $resourceName
369
     * @param array|string $accessList
370
     */
371
    public function dropResourceAccess($resourceName, $accessList)
372
    {
373
        throw new BadMethodCallException('Not implemented yet.');
374
    }
375
376
    /**
377
     * {@inheritdoc}
378
     * You can use '*' as wildcard
379
     * Example:
380
     * <code>
381
     * //Allow access to guests to search on customers
382
     * $acl->allow('guests', 'customers', 'search');
383
     * //Allow access to guests to search or create on customers
384
     * $acl->allow('guests', 'customers', ['search', 'create']);
385
     * //Allow access to any role to browse on products
386
     * $acl->allow('*', 'products', 'browse');
387
     * //Allow access to any role to browse on any resource
388
     * $acl->allow('*', '*', 'browse');
389
     * </code>
390
     *
391
     * @param string       $roleName
392
     * @param string       $resourceName
393
     * @param array|string $access
394
     * @param mixed $func
395
     */
396
    public function allow($roleName, $resourceName, $access, $func = null)
397
    {
398
        $this->allowOrDeny($roleName, $resourceName, $access, Acl::ALLOW);
399
    }
400
401
    /**
402
     * {@inheritdoc}
403
     * You can use '*' as wildcard
404
     * Example:
405
     * <code>
406
     * //Deny access to guests to search on customers
407
     * $acl->deny('guests', 'customers', 'search');
408
     * //Deny access to guests to search or create on customers
409
     * $acl->deny('guests', 'customers', ['search', 'create']);
410
     * //Deny access to any role to browse on products
411
     * $acl->deny('*', 'products', 'browse');
412
     * //Deny access to any role to browse on any resource
413
     * $acl->deny('*', '*', 'browse');
414
     * </code>
415
     *
416
     * @param  string       $roleName
417
     * @param  string       $resourceName
418
     * @param  array|string $access
419
     * @param  mixed $func
420
     * @return boolean
421
     */
422
    public function deny($roleName, $resourceName, $access, $func = null)
423
    {
424
        $this->allowOrDeny($roleName, $resourceName, $access, Acl::DENY);
425
    }
426
427
    /**
428
     * {@inheritdoc}
429
     * Example:
430
     * <code>
431
     * //Does Andres have access to the customers resource to create?
432
     * $acl->isAllowed('Andres', 'Products', 'create');
433
     * //Do guests have access to any resource to edit?
434
     * $acl->isAllowed('guests', '*', 'edit');
435
     * </code>
436
     *
437
     * @param string $role
438
     * @param string $resource
439
     * @param string $access
440
     * @param array  $parameters
441
     * @return bool
442
     */
443
    public function isAllowed($role, $resource, $access, array $parameters = null): bool
444
    {
445
        $sql = implode(' ', [
446
            'SELECT ' . $this->connection->escapeIdentifier('allowed') . " FROM {$this->accessList} AS a",
447
            // role_name in:
448
            'WHERE roles_name IN (',
449
                // given 'role'-parameter
450
            'SELECT ? ',
451
                // inherited role_names
452
            "UNION SELECT roles_inherit FROM {$this->rolesInherits} WHERE roles_name = ?",
453
                // or 'any'
454
            "UNION SELECT '*'",
455
            ')',
456
            // resources_name should be given one or 'any'
457
            "AND resources_name IN (?, '*')",
458
            // access_name should be given one or 'any'
459
            "AND access_name IN (?, '*')",
460
            'AND apps_id = ? ',
461
            // order be the sum of bools for 'literals' before 'any'
462
            'ORDER BY ' . $this->connection->escapeIdentifier('allowed') . ' DESC',
463
            // get only one...
464
            'LIMIT 1'
465
        ]);
466
        // fetch one entry...
467
        $allowed = $this->connection->fetchOne($sql, Db::FETCH_NUM, [$role, $role, $resource, $access, $this->getApp()->getId()]);
1 ignored issue
show
Bug introduced by
array($role, $role, $res...his->getApp()->getId()) of type array<integer,integer|string> is incompatible with the type integer expected by parameter $placeholders of Phalcon\Db\AdapterInterface::fetchOne(). ( Ignorable by Annotation )

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

467
        $allowed = $this->connection->fetchOne($sql, Db::FETCH_NUM, /** @scrutinizer ignore-type */ [$role, $role, $resource, $access, $this->getApp()->getId()]);
Loading history...
468
        if (is_array($allowed)) {
1 ignored issue
show
introduced by
The condition is_array($allowed) is always true.
Loading history...
469
            return (bool) $allowed[0];
470
        }
471
        /**
472
         * Return the default access action
473
         */
474
        return $this->_defaultAccess;
475
    }
476
477
    /**
478
     * Returns the default ACL access level for no arguments provided
479
     * in isAllowed action if there exists func for accessKey
480
     *
481
     * @return int
482
     */
483
    public function getNoArgumentsDefaultAction(): int
484
    {
485
        return $this->noArgumentsDefaultAction;
486
    }
487
488
    /**
489
     * Sets the default access level for no arguments provided
490
     * in isAllowed action if there exists func for accessKey
491
     *
492
     * @param int $defaultAccess Phalcon\Acl::ALLOW or Phalcon\Acl::DENY
493
     */
494
    public function setNoArgumentsDefaultAction($defaultAccess)
495
    {
496
        $this->noArgumentsDefaultAction = intval($defaultAccess);
497
    }
498
499
    /**
500
     * Inserts/Updates a permission in the access list
501
     *
502
     * @param  string  $roleName
503
     * @param  string  $resourceName
504
     * @param  string  $accessName
505
     * @param  integer $action
506
     * @return boolean
507
     * @throws \Phalcon\Acl\Exception
508
     */
509
    protected function insertOrUpdateAccess($roleName, $resourceName, $accessName, $action)
510
    {
511
        /**
512
         * Check if the access is valid in the resource unless wildcard
513
         */
514
        if ($resourceName !== '*' && $accessName !== '*') {
515
            $sql = "SELECT COUNT(*) FROM {$this->resourcesAccesses} WHERE resources_name = ? AND access_name = ?";
516
            $exists = $this->connection->fetchOne($sql, null, [$resourceName, $accessName]);
0 ignored issues
show
Bug introduced by
array($resourceName, $accessName) of type array<integer,string> is incompatible with the type integer expected by parameter $placeholders of Phalcon\Db\AdapterInterface::fetchOne(). ( Ignorable by Annotation )

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

516
            $exists = $this->connection->fetchOne($sql, null, /** @scrutinizer ignore-type */ [$resourceName, $accessName]);
Loading history...
517
            if (!$exists[0]) {
518
                throw new Exception(
519
                    "Access '{$accessName}' does not exist in resource '{$resourceName}' in ACL"
520
                );
521
            }
522
        }
523
        /**
524
         * Update the access in access_list
525
         */
526
        $sql = "SELECT COUNT(*) FROM {$this->accessList} "
527
            . ' WHERE roles_name = ? AND resources_name = ? AND access_name = ? AND apps_id = ?';
528
        $exists = $this->connection->fetchOne($sql, null, [$roleName, $resourceName, $accessName, $this->getApp()->getId()]);
1 ignored issue
show
Bug introduced by
array($roleName, $resour...his->getApp()->getId()) of type array<integer,integer|string> is incompatible with the type integer expected by parameter $placeholders of Phalcon\Db\AdapterInterface::fetchOne(). ( Ignorable by Annotation )

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

528
        $exists = $this->connection->fetchOne($sql, null, /** @scrutinizer ignore-type */ [$roleName, $resourceName, $accessName, $this->getApp()->getId()]);
Loading history...
529
        if (!$exists[0]) {
530
            $sql = "INSERT INTO {$this->accessList} (roles_name, resources_name, access_name, allowed, apps_id) VALUES (?, ?, ?, ?, ?)";
531
            $params = [$roleName, $resourceName, $accessName, $action, $this->getApp()->getId()];
532
        } else {
533
            $sql = "UPDATE {$this->accessList} SET allowed = ? " .
534
                'WHERE roles_name = ? AND resources_name = ? AND access_name = ? AND apps_id = ?';
535
            $params = [$action, $roleName, $resourceName, $accessName, $this->getApp()->getId()];
536
        }
537
        $this->connection->execute($sql, $params);
538
539
        /**
540
         * Update the access '*' in access_list
541
         */
542
        $sql = "SELECT COUNT(*) FROM {$this->accessList} " .
543
            'WHERE roles_name = ? AND resources_name = ? AND access_name = ? and apps_id = ?';
544
        $exists = $this->connection->fetchOne($sql, null, [$roleName, $resourceName, '*', $this->getApp()->getId()]);
545
        if (!$exists[0]) {
546
            $sql = "INSERT INTO {$this->accessList} (roles_name, resources_name, access_name, allowed, apps_id) VALUES (?, ?, ?, ?, ?)";
547
            $this->connection->execute($sql, [$roleName, $resourceName, '*', $this->_defaultAccess, $this->getApp()->getId()]);
548
        }
549
        return true;
550
    }
551
552
    /**
553
     * Inserts/Updates a permission in the access list
554
     *
555
     * @param  string       $roleName
556
     * @param  string       $resourceName
557
     * @param  array|string $access
558
     * @param  integer      $action
559
     * @throws \Phalcon\Acl\Exception
560
     */
561
    protected function allowOrDeny($roleName, $resourceName, $access, $action)
562
    {
563
        if (!$this->isRole($roleName)) {
564
            throw new Exception("Role '{$roleName}' does not exist in the list");
565
        }
566
        if (!is_array($access)) {
567
            $access = [$access];
568
        }
569
        foreach ($access as $accessName) {
570
            $this->insertOrUpdateAccess($roleName, $resourceName, $accessName, $action);
571
        }
572
    }
573
}
574