SQLiteRepository::executeOrFail()   A
last analyzed

Complexity

Conditions 5
Paths 12

Size

Total Lines 29
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 18.2613

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 22
c 1
b 0
f 0
dl 0
loc 29
ccs 4
cts 21
cp 0.1905
rs 9.2568
cc 5
nc 12
nop 3
crap 18.2613
1
<?php
2
3
namespace ProyectoTAU\TAU\Common;
4
5
use PDO;
6
use PDOException;
7
use ProyectoTAU\TAU\Module\Administration\User\Domain\User;
8
use ProyectoTAU\TAU\Module\Administration\Group\Domain\Group;
9
use ProyectoTAU\TAU\Module\Administration\Role\Domain\Role;
10
use ProyectoTAU\TAU\Module\Administration\Module\Domain\Module;
11
12
/*
13
 * @see https://phpenthusiast.com/blog/the-singleton-design-pattern-in-php
14
 */
15
16
// General singleton class.
17
class SQLiteRepository implements Repository
18
{
19
    // Hold the class instance.
20
    private static ?Repository $instance = null;
21
    private static ?PDO $db = null;
22
23
    // Primary Keys Cache
24
    private $userDataStore = [];
25
    private $groupDataStore = [];
26
    private $roleDataStore = [];
27
    private $moduleDataStore = [];
28
29
    // The constructor is private
30
    // to prevent initiation with outer code.
31
    private function __construct()
32
    {
33
        // The expensive process (e.g.,db connection) goes here.
34
        $dbname = __DIR__ . '/admin.sqlite3';
35
        try {
36
            self::$db = new PDO('sqlite:' . $dbname);
37
            self::$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
38
            //self::$db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);
39
        } catch (PDOException $e) {
40
            die($e->getMessage().' ('.$dbname.')');
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
41
        }
42
    }
43
44
    // The object is created from within the class itself
45
    // only if the class has no instance.
46 38
    public static function getInstance(): Repository
47
    {
48 38
        if (self::$instance == null)
49
        {
50
            self::$instance = new static();
51
        }
52
53 38
        return self::$instance;
0 ignored issues
show
Bug Best Practice introduced by
The expression return self::instance could return the type null which is incompatible with the type-hinted return ProyectoTAU\TAU\Common\Repository. Consider adding an additional type-check to rule them out.
Loading history...
54
    }
55
56
    /*
57
     * Transactions
58
     */
59 38
    public function begin(): void
60
    {
61 38
        self::$db->beginTransaction();
0 ignored issues
show
Bug introduced by
The method beginTransaction() does not exist on null. ( Ignorable by Annotation )

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

61
        self::$db->/** @scrutinizer ignore-call */ 
62
                   beginTransaction();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
62 38
    }
63
64 38
    public function commit(): void
65
    {
66 38
        self::$db->commit();
67 38
    }
68
69
    public function rollBack(): void
70
    {
71
        self::$db->rollBack();
72
    }
73
74
75
    /*
76
     * @see https://www.tutorialspoint.com/sqlite/sqlite_truncate_table.htm
77
     */
78 11
    public function clearUser(): void
79
    {
80 11
        $ps = self::$db->query('DELETE FROM user_group;');
81 11
        $this->executeOrFail($ps);
82 11
        $ps = self::$db->query('DELETE FROM User;');
83 11
        $this->executeOrFail($ps);
84 11
    }
85
86 17
    public function clearGroup(): void
87
    {
88 17
        $ps = self::$db->query('DELETE FROM user_group;');
89 17
        $this->executeOrFail($ps);
90 17
        $ps = self::$db->query('DELETE FROM group_role;');
91 17
        $this->executeOrFail($ps);
92 17
        $ps = self::$db->query('DELETE FROM "Group";');
93 17
        $this->executeOrFail($ps);
94 17
    }
95
96 17
    public function clearRole(): void
97
    {
98 17
        $ps = self::$db->query('DELETE FROM group_role;');
99 17
        $this->executeOrFail($ps);
100 17
        $ps = self::$db->query('DELETE FROM role_module;');
101 17
        $this->executeOrFail($ps);
102 17
        $ps = self::$db->query('DELETE FROM Role;');
103 17
        $this->executeOrFail($ps);
104 17
    }
105
106 11
    public function clearModule(): void
107
    {
108 11
        $ps = self::$db->query('DELETE FROM role_module;');
109 11
        $this->executeOrFail($ps);
110 11
        $ps = self::$db->query('DELETE FROM Module;');
111 11
        $this->executeOrFail($ps);
112 11
    }
113
114
    /*
115
     * User
116
     */
117
118 11
    public function createUser(User $user): void
119
    {
120 11
        $ps = self::$db->prepare('INSERT INTO User (user_id, name, surname, login)'.
121 11
                                            ' VALUES(:user_id, :name, :surname, :login);');
122 11
        $this->executeOrFail($ps, [
123 11
            ':user_id' => $user->getId(),
124 11
            ':name' => $user->getName(),
125 11
            ':surname' => $user->getSurname(),
126 11
            ':login' => $user->getLogin()
127
        ]);
128
129 11
        $this->userDataStore[$user->getId()] = self::$db->lastInsertId();
130 11
    }
131
132 7
    public function readUser($id): User
133
    {
134 7
        $ps = self::$db->prepare('SELECT user_pk, user_id, name, surname, login FROM User WHERE user_id = :user_id;');
135
136 7
        $this->executeOrFail($ps, [':user_id' => $id]);
137
138 7
        $resultSet = $ps->fetch(PDO::FETCH_ASSOC);
139 7
        if( $resultSet === false )
140
            throw new \InvalidArgumentException("User with id = $id not found");
141
142 7
        $ref = new \ReflectionClass(User::class);
143 7
        $user = $this->castUser($ref->newInstanceWithoutConstructor());
144
145 7
        $user->setId($resultSet['user_id']);
146 7
        $user->setName($resultSet['name']);
147 7
        $user->setSurname($resultSet['surname']);
148 7
        $user->setLogin($resultSet['login']);
149
150 7
        $this->userDataStore[$user->getId()] = $resultSet['user_pk'];
151
152 7
        return $user;
153
    }
154
155 1
    public function readAllUsers(): array
156
    {
157 1
        return $this->getAllUsers();
158
    }
159
160 1
    public function updateUser($id, $name, $surname, $login): void
161
    {
162 1
        $ps = self::$db->prepare('UPDATE User SET '.
163
                                            'name = :name,'.
164
                                            'surname = :surname,'.
165
                                            'login = :login'.
166 1
                                            ' WHERE user_id = :user_id;');
167
168 1
        $this->executeOrFail($ps, [
169 1
            ':user_id' => $id,
170 1
            ':name' => $name,
171 1
            ':surname' => $surname,
172 1
            ':login' => $login
173
        ]);
174 1
    }
175
176 1
    public function deleteUser($id): void
177
    {
178 1
        $ps = self::$db->prepare('DELETE FROM User WHERE user_id = :user_id;');
179
180 1
        $this->executeOrFail($ps, [':user_id' => $id]);
181
182 1
        unset($this->userDataStore[$id]);
183 1
    }
184
185 2
    public function getGroupsFromUser(User $user): array
186
    {
187 2
        $ps = self::$db->prepare('SELECT group_pk, g.group_id, name, description FROM "Group" g'.
188
                                        ' INNER JOIN user_group rel ON g.group_pk = rel.group_fk'.
189 2
                                        ' WHERE rel.user_id = :user_id;');
190
191 2
        $resultSet = $this->queryOrFail($ps, [
192 2
            ':user_id' => $user->getid()
193
        ]);
194
195 2
        $groups = [];
196 2
        foreach ($resultSet as $entry) {
197 1
            $ref = new \ReflectionClass(Group::class);
198 1
            $group = $this->castGroup($ref->newInstanceWithoutConstructor());
199
200 1
            $group->setPropertiesBag(['id', 'name', 'desc']);
201 1
            $group->setSettersBag($group->getPropertiesBag());
202
203 1
            $group->setId($entry['group_id']);
204 1
            $group->setName($entry['name']);
205 1
            $group->setDesc($entry['description']);
206
207 1
            $groups[$entry['group_id']] = $group;
208
        }
209
210 2
        $available = array_diff_assoc($this->getAllGroups(), $groups);
211
        $r = [
212 2
            'belongsto' => $groups,
213 2
            'available' => $available
214
        ];
215
216 2
        return $r;
217
    }
218
219 8
    private function castUser($o): User
220
    {
221 8
        return $o;
222
    }
223
224 14
    private function castGroup($o): Group
225
    {
226 14
        return $o;
227
    }
228
229 12
    private function queryOrFail($ps, $params = [], $debug = 0): array
230
    {
231 12
        $this->executeOrFail($ps, $params, $debug);
232 12
        $resultSet =  $ps->fetchAll(PDO::FETCH_ASSOC);
233
234 12
        return $resultSet;
235
    }
236
237 38
    private function executeOrFail($ps, $params = [], $debug = 0): void
238
    {
239 38
        if($debug) { //TODO: toggle to enable
240
            $sql = $ps->queryString;
241
            $b = str_replace(array_keys($params), array_values($params), $sql);
242
            echo "\n$b\n";
243
        }
244
245
        try {
246 38
            $result = $ps->execute($params);
247
        } catch (PDOException $e){
248
            $result = false;
249
        }
250
251 38
        if( $result === false ) {
252
            $debug = 1;
253
            if($debug) {
254
                $sql = $ps->queryString;
255
                $b = str_replace(array_keys($params), array_values($params), $sql);
256
                echo "\n$b\n";
257
            }
258
            $errorInfo = $ps->errorInfo();
259
            $SQLSTATE_error_code = $errorInfo[0];
260
            $Driver_specific_error_code = $errorInfo[1];
261
            $Driver_specific_error_message = $errorInfo[2];
262
            throw new \Exception(
263
                '['.$SQLSTATE_error_code.'] '.$Driver_specific_error_message.
264
                ' (Driver specific error code: '.$Driver_specific_error_code.')',
265
                $SQLSTATE_error_code);
266
        }
267 38
    }
268
269 4
    private function getAllGroups(): array
270
    {
271 4
        $ps = self::$db->prepare('SELECT group_pk, group_id, group_id, name, description FROM "Group";');
272
273 4
        $resultSet = $this->queryOrFail($ps);
274
275 4
        $groups = [];
276 4
        foreach ($resultSet as $entry) {
277 4
            $ref = new \ReflectionClass(Group::class);
278 4
            $group = $this->castGroup($ref->newInstanceWithoutConstructor());
279
280 4
            $group->setPropertiesBag(['id', 'name', 'desc']);
281 4
            $group->setSettersBag($group->getPropertiesBag());
282
283 4
            $group->setId($entry['group_id']);
284 4
            $group->setName($entry['name']);
285 4
            $group->setDesc($entry['description']);
286
287 4
            $this->groupDataStore[$entry['group_id']] = $entry['group_pk'];
288
289 4
            $groups[$entry['group_id']] = $group;
290
        }
291
292 4
        return $groups;
293
    }
294
295 17
    public function createGroup(Group $group): void
296
    {
297 17
        $ps = self::$db->prepare('INSERT INTO "Group" (group_id, name, description)'.
298 17
                                            ' VALUES(:group_id, :name, :description);');
299 17
        $this->executeOrFail($ps, [
300 17
            ':group_id' => $group->getId(),
301 17
            ':name' => $group->getName(),
302 17
            ':description' => $group->getDesc()
303
        ]);
304
305 17
        $this->groupDataStore[$group->getId()] = self::$db->lastInsertId();
306 17
    }
307
308 12
    public function readGroup($id): Group
309
    {
310 12
        $ps = self::$db->prepare('SELECT group_pk, group_id, name, description FROM "Group" WHERE group_id = :group_id;');
311
312 12
        $this->executeOrFail($ps, [':group_id' => $id]);
313
314 12
        $resultSet = $ps->fetch(PDO::FETCH_ASSOC);
315 12
        if( $resultSet === false )
316
            throw new \InvalidArgumentException("Group with id = $id not found");
317
318 12
        $ref = new \ReflectionClass(Group::class);
319 12
        $group = $this->castGroup($ref->newInstanceWithoutConstructor());
320
321 12
        $group->setPropertiesBag(['id', 'name', 'desc']);
322 12
        $group->setSettersBag($group->getPropertiesBag());
323
324 12
        $group->setId($resultSet['group_id']);
325 12
        $group->setName($resultSet['name']);
326 12
        $group->setDesc($resultSet['description']);
327
328 12
        $this->groupDataStore[$group->getId()] = $resultSet['group_pk'];
329
330 12
        return $group;
331
    }
332
333 1
    public function readAllGroups(): array
334
    {
335 1
        return $this->getAllGroups();
336
    }
337
338 1
    public function updateGroup($id, $name, $desc): void
339
    {
340 1
        $ps = self::$db->prepare('UPDATE "Group" SET '.
341
                                            'name = :name,'.
342
                                            'description = :description'.
343 1
                                            ' WHERE group_id = :group_id;');
344
345 1
        $this->executeOrFail($ps, [
346 1
            ':group_id' => $id,
347 1
            ':name' => $name,
348 1
            ':description' => $desc
349
        ]);
350 1
    }
351
352 1
    public function deleteGroup($id): void
353
    {
354 1
        $ps = self::$db->prepare('DELETE FROM "Group" WHERE group_id = :group_id;');
355
356 1
        $this->executeOrFail($ps, [':group_id' => $id]);
357
358 1
        unset($this->groupDataStore[$id]);
359 1
    }
360
361 1
    public function getUsersFromGroup(Group $group): array
362
    {
363 1
        $ps = self::$db->prepare('SELECT user_pk, u.user_id, name, surname, login FROM User u'.
364
                                        ' INNER JOIN user_group rel ON u.user_pk = rel.user_fk'.
365 1
                                        ' WHERE rel.group_id = :group_id;');
366
367 1
        $resultSet = $this->queryOrFail($ps, [
368 1
            ':group_id' => $group->getId()
369
        ]);
370
371 1
        $users = [];
372 1
        foreach ($resultSet as $entry) {
373 1
            $ref = new \ReflectionClass(User::class);
374 1
            $user = $this->castUser($ref->newInstanceWithoutConstructor());
375
376 1
            $user->setId($entry['user_id']);
377 1
            $user->setName($entry['name']);
378 1
            $user->setSurname($entry['surname']);
379 1
            $user->setLogin($entry['login']);
380
381 1
            $users[$entry['user_id']] = $user;
382
        }
383
384 1
        $available = array_diff_assoc($this->getAllUsers(), $users);
385
        $r = [
386 1
            'members' => $users,
387 1
            'available' => $available
388
        ];
389
390 1
        return $r;
391
    }
392
393 2
    private function getAllUsers(): array
394
    {
395 2
        $ps = self::$db->prepare('SELECT user_pk, user_id, name, surname, login FROM User;');
396
397 2
        $resultSet = $this->queryOrFail($ps);
398
399 2
        $users = [];
400 2
        foreach ($resultSet as $entry) {
401 2
            $ref = new \ReflectionClass(User::class);
402 2
            $user = $this->castUser($ref->newInstanceWithoutConstructor());
403
404 2
            $user->setId($entry['user_id']);
405 2
            $user->setName($entry['name']);
406 2
            $user->setSurname($entry['surname']);
407 2
            $user->setLogin($entry['login']);
408
409 2
            $this->userDataStore[$entry['user_id']] = $entry['user_pk'];
410
411 2
            $users[$entry['user_id']] = $user;
412
        }
413
414 2
        return $users;
415
    }
416
417 3
    public function addUserToGroup(User $user, Group $group)
418
    {
419 3
        $ps = self::$db->prepare('INSERT INTO user_group (user_fk, group_fk, user_id, group_id)'.
420 3
                                        ' VALUES (:user_fk, :group_fk, :user_id, :group_id);');
421
422 3
        $this->executeOrFail($ps, [
423 3
            ':user_fk' => $this->userDataStore[$user->getId()],
424 3
            ':group_fk' => $this->groupDataStore[$group->getId()],
425 3
            ':user_id' => $user->getId(),
426 3
            ':group_id' => $group->getId()
427
        ]);
428 3
    }
429
430 1
    public function removeUserFromGroup(User $user, Group $group)
431
    {
432 1
        $ps = self::$db->prepare('DELETE FROM user_group'.
433
                                        ' WHERE user_id = :user_id'.
434 1
                                        ' AND group_id = :group_id;');
435
436 1
        $this->executeOrFail($ps, [
437 1
            ':user_id' => $user->getId(),
438 1
            ':group_id' => $group->getId()
439
        ]);
440 1
    }
441
442 17
    public function createRole(Role $role): void
443
    {
444 17
        $ps = self::$db->prepare('INSERT INTO Role (role_id, name, description)'.
445 17
                                        ' VALUES(:role_id, :name, :description);');
446
447 17
        $this->executeOrFail($ps, [
448 17
            ':role_id' => $role->getId(),
449 17
            ':name' => $role->getName(),
450 17
            ':description' => $role->getDesc()
451
        ]);
452
453 17
        $this->roleDataStore[$role->getId()] = self::$db->lastInsertId();
454 17
    }
455
456 13
    public function readRole($id): Role
457
    {
458 13
        $ps = self::$db->prepare('SELECT role_pk, role_id, name, description FROM Role WHERE role_id = :role_id;');
459
460 13
        $this->executeOrFail($ps, [':role_id' => $id]);
461
462 13
        $resultSet = $ps->fetch(PDO::FETCH_ASSOC);
463 13
        if( $resultSet === false )
464
            throw new \InvalidArgumentException("Role with id = $id not found");
465
466 13
        $ref = new \ReflectionClass(Role::class);
467 13
        $role = $this->castRole($ref->newInstanceWithoutConstructor());
468
469 13
        $role->setPropertiesBag(['id', 'name', 'desc']);
470 13
        $role->setSettersBag($role->getPropertiesBag());
471
472 13
        $role->setId($resultSet['role_id']);
473 13
        $role->setName($resultSet['name']);
474 13
        $role->setDesc($resultSet['description']);
475
476 13
        $this->roleDataStore[$role->getId()] = $resultSet['role_pk'];
477
478 13
        return $role;
479
    }
480
481 1
    public function readAllRoles(): array
482
    {
483 1
        return $this->getAllRoles();
484
    }
485
486 14
    private function castRole($o): Role
487
    {
488 14
        return $o;
489
    }
490
491 3
    public function addGroupToRole(Group $group, Role $role)
492
    {
493 3
        $ps = self::$db->prepare('INSERT INTO group_role (group_fk, role_fk, group_id, role_id)'.
494 3
                                        ' VALUES (:group_fk, :role_fk, :group_id, :role_id);');
495
496 3
        $this->executeOrFail($ps, [
497 3
            ':group_fk' => $this->groupDataStore[$group->getId()],
498 3
            ':role_fk' => $this->roleDataStore[$role->getId()],
499 3
            ':group_id' => $group->getId(),
500 3
            ':role_id' => $role->getId()
501
        ]);
502 3
    }
503
504 1
    public function getGroupsFromRole(Role $role): array
505
    {
506 1
        $ps = self::$db->prepare('SELECT group_pk, g.group_id, name, description FROM "Group" g'.
507
                                        ' INNER JOIN group_role rel ON g.group_pk = rel.group_fk'.
508 1
                                        ' WHERE rel.role_id = :role_id;');
509
510 1
        $resultSet = $this->queryOrFail($ps, [
511 1
            ':role_id' => $role->getId()
512
        ]);
513
514 1
        $groups = [];
515 1
        foreach ($resultSet as $entry) {
516 1
            $ref = new \ReflectionClass(Group::class);
517 1
            $group = $this->castGroup($ref->newInstanceWithoutConstructor());
518
519 1
            $group->setPropertiesBag(['id', 'name', 'desc']);
520 1
            $group->setSettersBag($group->getPropertiesBag());
521
522 1
            $group->setId($entry['group_id']);
523 1
            $group->setName($entry['name']);
524 1
            $group->setDesc($entry['description']);
525
526 1
            $groups[$entry['group_id']] = $group;
527
        }
528
529 1
        $available = array_diff_assoc($this->getAllGroups(), $groups);
530
        $r = [
531 1
            'grantedby' => $groups,
532 1
            'available' => $available
533
        ];
534
535 1
        return $r;
536
    }
537
538 1
    public function removeGroupFromRole(Group $group, Role $role)
539
    {
540 1
        $ps = self::$db->prepare('DELETE FROM group_role'.
541
                                        ' WHERE group_id = :group_id'.
542 1
                                        ' AND role_id = :role_id;');
543
544 1
        $this->executeOrFail($ps, [
545 1
            ':group_id' => $group->getId(),
546 1
            ':role_id' => $role->getId()
547
        ]);
548 1
    }
549
550 2
    public function addGroupToUser(Group $group, User $user)
551
    {
552 2
        $ps = self::$db->prepare('INSERT INTO user_group (user_fk, group_fk, user_id, group_id)'.
553 2
                                        ' VALUES (:user_fk, :group_fk, :user_id, :group_id);');
554
555 2
        $this->executeOrFail($ps, [
556 2
            ':user_fk' => $this->userDataStore[$user->getId()],
557 2
            ':group_fk' => $this->groupDataStore[$group->getId()],
558 2
            ':user_id' => $user->getId(),
559 2
            ':group_id' => $group->getId()
560
        ]);
561 2
    }
562
563 1
    public function removeGroupFromUser(Group $group, User $user)
564
    {
565 1
        $ps = self::$db->prepare('DELETE FROM user_group'.
566
                                        ' WHERE user_id = :user_id'.
567 1
                                        ' AND group_id = :group_id;');
568
569 1
        $this->executeOrFail($ps, [
570 1
            ':user_id' => $user->getId(),
571 1
            ':group_id' => $group->getId()
572
        ]);
573 1
    }
574
575 1
    public function updateRole($id, $name, $desc): void
576
    {
577 1
        $ps = self::$db->prepare('UPDATE Role SET '.
578
                                        'name = :name,'.
579
                                        'description = :description'.
580 1
                                        ' WHERE role_id = :role_id;');
581
582 1
        $this->executeOrFail($ps, [
583 1
            ':role_id' => $id,
584 1
            ':name' => $name,
585 1
            ':description' => $desc
586
        ]);
587 1
    }
588
589 1
    public function deleteRole($id): void
590
    {
591 1
        $ps = self::$db->prepare('DELETE FROM Role WHERE role_id = :role_id;');
592
593 1
        $this->executeOrFail($ps, [
594 1
            ':role_id' => $id
595
        ]);
596
597 1
        unset($this->roleDataStore[$id]);
598 1
    }
599
600 3
    public function addRoleToGroup(Role $role, Group $group)
601
    {
602 3
        $ps = self::$db->prepare('INSERT INTO group_role (group_fk, role_fk, group_id, role_id)'.
603 3
                                        ' VALUES (:group_fk, :role_fk, :group_id, :role_id);');
604
605 3
        $this->executeOrFail($ps, [
606 3
            ':group_fk' => $this->groupDataStore[$group->getId()],
607 3
            ':role_fk' => $this->roleDataStore[$role->getId()],
608 3
            ':group_id' => $group->getId(),
609 3
            ':role_id' => $role->getId()
610
        ]);
611 3
    }
612
613 1
    public function getRolesFromGroup(Group $group): array
614
    {
615 1
        $ps = self::$db->prepare('SELECT role_pk, r.role_id, name, description FROM Role r'.
616
                                        ' INNER JOIN group_role rel ON r.role_pk = rel.role_fk'.
617 1
                                        ' WHERE rel.group_id = :group_id;');
618
619 1
        $resultSet = $this->queryOrFail($ps, [
620 1
            ':group_id' => $group->getId()
621
        ]);
622
623 1
        $roles = [];
624 1
        foreach ($resultSet as $entry) {
625 1
            $ref = new \ReflectionClass(Role::class);
626 1
            $role = $this->castRole($ref->newInstanceWithoutConstructor());
627
628 1
            $role->setPropertiesBag(['id', 'name', 'desc']);
629 1
            $role->setSettersBag($role->getPropertiesBag());
630
631 1
            $role->setId($entry['role_id']);
632 1
            $role->setName($entry['name']);
633 1
            $role->setDesc($entry['description']);
634
635 1
            $roles[$entry['role_id']] = $role;
636
        }
637
638 1
        $available = array_diff_assoc($this->getAllRoles(), $roles);
639
        $r = [
640 1
            'plays' => $roles,
641 1
            'available' => $available
642
        ];
643
644 1
        return $r;
645
    }
646
647 3
    private function getAllRoles(): array
648
    {
649 3
        $ps = self::$db->prepare('SELECT role_pk, role_id, role_id, name, description FROM Role;');
650
651 3
        $resultSet = $this->queryOrFail($ps);
652
653 3
        $roles = [];
654 3
        foreach ($resultSet as $entry) {
655 3
            $ref = new \ReflectionClass(Role::class);
656 3
            $role = $this->castRole($ref->newInstanceWithoutConstructor());
657
658 3
            $role->setPropertiesBag(['id', 'name', 'desc']);
659 3
            $role->setSettersBag($role->getPropertiesBag());
660
661 3
            $role->setId($entry['role_id']);
662 3
            $role->setName($entry['name']);
663 3
            $role->setDesc($entry['description']);
664
665 3
            $this->roleDataStore[$entry['role_id']] = $entry['role_pk'];
666
667 3
            $roles[$entry['role_id']] = $role;
668
        }
669
670 3
        return $roles;
671
    }
672
673 1
    public function removeRoleFromGroup(Role $role, Group $group)
674
    {
675 1
        $ps = self::$db->prepare('DELETE FROM group_role'.
676
                                        ' WHERE role_id = :role_id'.
677 1
                                        ' AND group_id = :group_id;');
678
679 1
        $this->executeOrFail($ps, [
680 1
            ':role_id' => $role->getId(),
681 1
            ':group_id' => $group->getId()
682
        ]);
683 1
    }
684
685 6
    public function addModuleToRole(Module $module, Role $role)
686
    {
687 6
        $ps = self::$db->prepare('INSERT INTO role_module (role_fk, module_fk, role_id, module_id)'.
688 6
                                        ' VALUES (:role_fk, :module_fk, :role_id, :module_id);');
689
690 6
        $this->executeOrFail($ps, [
691 6
            ':role_fk' => $this->roleDataStore[$role->getId()],
692 6
            ':module_fk' => $this->moduleDataStore[$module->getId()],
693 6
            ':role_id' => $role->getId(),
694 6
            ':module_id' => $module->getId()
695
        ]);
696 6
    }
697
698 2
    public function removeModuleFromRole(Module $module, Role $role)
699
    {
700 2
        $ps = self::$db->prepare('DELETE FROM role_module'.
701
                                        ' WHERE role_id = :role_id'.
702 2
                                        ' AND module_id = :module_id;');
703
704 2
        $this->executeOrFail($ps, [
705 2
            ':module_id' => $module->getId(),
706 2
            ':role_id' => $role->getId()
707
        ]);
708 2
    }
709
710 2
    public function getModulesFromRole(Role $role): array
711
    {
712 2
        $ps = self::$db->prepare('SELECT module_pk, m.module_id, name, description FROM Module m'.
713
                                        ' INNER JOIN role_module rel ON m.module_pk = rel.module_fk'.
714 2
                                        ' WHERE rel.role_id = :role_id;');
715
716 2
        $resultSet = $this->queryOrFail($ps, [
717 2
            ':role_id' => $role->getId()
718
        ]);
719
720 2
        $modules = [];
721 2
        foreach ($resultSet as $entry) {
722 2
            $ref = new \ReflectionClass(Module::class);
723 2
            $module = $this->castModule($ref->newInstanceWithoutConstructor());
724
725 2
            $module->setPropertiesBag(['id', 'name', 'desc']);
726 2
            $module->setSettersBag($module->getPropertiesBag());
727
728 2
            $module->setId($entry['module_id']);
729 2
            $module->setName($entry['name']);
730 2
            $module->setDesc($entry['description']);
731
732 2
            $modules[$entry['module_id']] = $module;
733
        }
734
735 2
        $available = array_diff_assoc($this->getAllModules(), $modules);
736
        $r = [
737 2
            'canrun' => $modules,
738 2
            'available' => $available
739
        ];
740
741 2
        return $r;
742
    }
743
744 8
    private function castModule($o): Module
745
    {
746 8
        return $o;
747
    }
748
749 3
    private function getAllModules()
750
    {
751 3
        $ps = self::$db->prepare('SELECT module_pk, module_id, module_id, name, description FROM Module;');
752
753 3
        $resultSet = $this->queryOrFail($ps);
754
755 3
        $modules = [];
756 3
        foreach ($resultSet as $entry) {
757 3
            $ref = new \ReflectionClass(Module::class);
758 3
            $module = $this->castModule($ref->newInstanceWithoutConstructor());
759
760 3
            $module->setPropertiesBag(['id', 'name', 'desc']);
761 3
            $module->setSettersBag($module->getPropertiesBag());
762
763 3
            $module->setId($entry['module_id']);
764 3
            $module->setName($entry['name']);
765 3
            $module->setDesc($entry['description']);
766
767 3
            $this->moduleDataStore[$entry['module_id']] = $entry['module_pk'];
768
769 3
            $modules[$entry['module_id']] = $module;
770
        }
771
772 3
        return $modules;
773
    }
774
775 11
    public function createModule(Module $module): void
776
    {
777 11
        $ps = self::$db->prepare('INSERT INTO Module (module_id, name, description)'.
778 11
                                        ' VALUES(:module_id, :name, :description);');
779 11
        $this->executeOrFail($ps, [
780 11
            ':module_id' => $module->getId(),
781 11
            ':name' => $module->getName(),
782 11
            ':description' => $module->getDesc()
783
        ]);
784
785 11
        $this->moduleDataStore[$module->getId()] = self::$db->lastInsertId();
786 11
    }
787
788 7
    public function readModule($id): Module
789
    {
790 7
        $ps = self::$db->prepare('SELECT module_pk, module_id, name, description FROM Module'.
791 7
                                        ' WHERE module_id = :module_id;');
792
793 7
        $this->executeOrFail($ps, [
794 7
            ':module_id' => $id
795
        ]);
796
797 7
        $resultSet = $ps->fetch(PDO::FETCH_ASSOC);
798 7
        if( $resultSet === false )
799
            throw new \InvalidArgumentException("Module with id = $id not found");
800
801 7
        $ref = new \ReflectionClass(Module::class);
802 7
        $module = $this->castModule($ref->newInstanceWithoutConstructor());
803
804 7
        $module->setPropertiesBag(['id', 'name', 'desc']);
805 7
        $module->setSettersBag($module->getPropertiesBag());
806
807 7
        $module->setId($resultSet['module_id']);
808 7
        $module->setName($resultSet['name']);
809 7
        $module->setDesc($resultSet['description']);
810
811 7
        $this->moduleDataStore[$module->getId()] = $resultSet['module_pk'];
812
813 7
        return $module;
814
    }
815
816 1
    public function readAllModules(): array
817
    {
818 1
        return $this->getAllModules();
819
    }
820
821 1
    public function updateModule($id, $name, $desc): void
822
    {
823 1
        $ps = self::$db->prepare('UPDATE Module SET '.
824
                                        'name = :name,'.
825
                                        'description = :description'.
826 1
                                        ' WHERE module_id = :module_id;');
827
828 1
        $this->executeOrFail($ps, [
829 1
            ':module_id' => $id,
830 1
            ':name' => $name,
831 1
            ':description' => $desc
832
        ]);
833 1
    }
834
835 1
    public function deleteModule($id): void
836
    {
837 1
        $ps = self::$db->prepare('DELETE FROM Module WHERE module_id = :module_id;');
838
839 1
        $this->executeOrFail($ps, [
840 1
            ':module_id' => $id
841
        ]);
842
843 1
        unset($this->moduleDataStore[$id]);
844 1
    }
845
846 3
    public function addRoleToModule(Role $role, Module $module)
847
    {
848 3
        $this->addModuleToRole($module, $role);
849 3
    }
850
851 1
    public function removeRoleFromModule(Role $role, Module $module)
852
    {
853 1
        $this->removeModuleFromRole($module, $role);
854 1
    }
855
856 1
    public function getRolesFromModule(Module $module): array
857
    {
858 1
        $ps = self::$db->prepare('SELECT role_pk, r.role_id, name, description FROM Role r'.
859
                                        ' INNER JOIN role_module rel ON r.role_pk = rel.role_fk'.
860 1
                                        ' WHERE rel.module_id = :module_id;');
861
862 1
        $resultSet = $this->queryOrFail($ps, [
863 1
            ':module_id' => $module->getId()
864
        ]);
865
866 1
        $roles = [];
867 1
        foreach ($resultSet as $entry) {
868 1
            $ref = new \ReflectionClass(Role::class);
869 1
            $role = $this->castRole($ref->newInstanceWithoutConstructor());
870
871 1
            $role->setPropertiesBag(['id', 'name', 'desc']);
872 1
            $role->setSettersBag($role->getPropertiesBag());
873
874 1
            $role->setId($entry['role_id']);
875 1
            $role->setName($entry['name']);
876 1
            $role->setDesc($entry['description']);
877
878 1
            $roles[$entry['role_id']] = $role;
879
        }
880
881 1
        $available = array_diff_assoc($this->getAllRoles(), $roles);
882
        $r = [
883 1
            'authorizedby' => $roles,
884 1
            'available' => $available
885
        ];
886
887 1
        return $r;
888
    }
889
}
890