Passed
Push — main ( 29d231...3aa672 )
by Proyecto
02:48
created

SQLiteRepository::castUser()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

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