Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
98.08% covered (success)
98.08%
102 / 104
71.43% covered (warning)
71.43%
5 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 1
Role
98.08% covered (success)
98.08%
102 / 104
71.43% covered (warning)
71.43%
5 / 7
23
0.00% covered (danger)
0.00%
0 / 1
 readRoleById
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
2
 readRoleByName
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
2
 readAllRoles
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
3
 addRole
100.00% covered (success)
100.00%
21 / 21
100.00% covered (success)
100.00%
1 / 1
2
 updateRole
100.00% covered (success)
100.00%
28 / 28
100.00% covered (success)
100.00%
1 / 1
4
 fetchPermissionsByNamesOrFail
93.75% covered (success)
93.75%
15 / 16
0.00% covered (danger)
0.00%
0 / 1
4.00
 deleteRole
91.67% covered (success)
91.67%
11 / 12
0.00% covered (danger)
0.00%
0 / 1
6.02
1<?php
2
3namespace BO\Zmsbackend\Role\Service;
4
5use BO\Zmsentities\Collection\RoleList as Collection;
6use BO\Zmsentities\Permission as PermissionEntity;
7use BO\Zmsentities\Role as Entity;
8
9class Role extends \BO\Zmsbackend\Base
10{
11    public function readRoleById(int $roleId, int $resolveReferences = 1): ?Entity
12    {
13        $query = new \BO\Zmsbackend\Role\Repository\Role(\BO\Zmsbackend\Query\Base::SELECT);
14        $query->addEntityMapping()
15            ->addResolvedReferences($resolveReferences)
16            ->addConditionRoleId($roleId);
17        $role = $this->fetchOne($query, new Entity());
18
19        if (! $role->hasId()) {
20            return null;
21        }
22
23        return $role;
24    }
25
26    public function readRoleByName(string $name, int $resolveReferences = 1): ?Entity
27    {
28        $query = new \BO\Zmsbackend\Role\Repository\Role(\BO\Zmsbackend\Query\Base::SELECT);
29        $query->addEntityMapping()
30            ->addResolvedReferences($resolveReferences)
31            ->addConditionName($name);
32
33        $role = $this->fetchOne($query, new Entity());
34        if (! $role->hasId()) {
35            return null;
36        }
37
38        return $role;
39    }
40
41    public function readAllRoles(string $order = 'ASC', int $resolveReferences = 1): Collection
42    {
43        $roleList = new Collection();
44        $query = new \BO\Zmsbackend\Role\Repository\Role(\BO\Zmsbackend\Query\Base::SELECT);
45        $query->addEntityMapping()
46            ->addResolvedReferences($resolveReferences)
47            ->addOrderBy('id', $order);
48        $result = $this->fetchList($query, new Entity());
49        if (count($result)) {
50            foreach ($result as $entity) {
51                $entity = $this->readResolvedReferences($entity, $resolveReferences);
52                $roleList->addEntity($entity);
53            }
54        }
55        return $roleList;
56    }
57
58    public function addRole(Entity $role, int $resolveReferences = 1): ?Entity
59    {
60        $permissionNames = array_values(array_unique($role['permissions'] ?? []));
61        $permissions = $this->fetchPermissionsByNamesOrFail($permissionNames);
62
63        $query = new \BO\Zmsbackend\Role\Repository\Role(\BO\Zmsbackend\Query\Base::INSERT);
64        $query->addValues(
65            [
66                'name' => $role['name'],
67                'description' => $role['description'],
68            ]
69        );
70        $this->writeItem($query);
71        $newId = (int) $this->getWriter()->lastInsertId();
72
73        foreach ($permissions as $permission) {
74            $link = new \BO\Zmsbackend\Role\Repository\RolePermission(\BO\Zmsbackend\Query\Base::INSERT);
75            $link->addValues(
76                [
77                    'role_id' => $newId,
78                    'permission_id' => $permission['id'],
79                ]
80            );
81            $this->writeItem($link);
82        }
83
84        return $this->readRoleById($newId, $resolveReferences);
85    }
86
87    public function updateRole(int $roleId, Entity $role, int $resolveReferences = 1): ?Entity
88    {
89        $existing = $this->readRoleById($roleId);
90        if (!$existing || !$existing->hasId()) {
91            return null;
92        }
93
94        $permissionNames = array_values(array_unique($role['permissions'] ?? []));
95        $permissions = $this->fetchPermissionsByNamesOrFail($permissionNames);
96
97        $query = new \BO\Zmsbackend\Role\Repository\Role(\BO\Zmsbackend\Query\Base::UPDATE);
98        $query->addConditionRoleId($roleId);
99        $query->addValues(
100            [
101                'name' => $role['name'],
102                'description' => $role['description'],
103            ]
104        );
105        $this->writeItem($query);
106
107        $delLinks = new \BO\Zmsbackend\Role\Repository\RolePermission(\BO\Zmsbackend\Query\Base::DELETE);
108        $delLinks->addConditionRoleId($roleId);
109        $this->deleteItem($delLinks);
110
111        foreach ($permissions as $permission) {
112            $link = new \BO\Zmsbackend\Role\Repository\RolePermission(\BO\Zmsbackend\Query\Base::INSERT);
113            $link->addValues(
114                [
115                    'role_id' => $roleId,
116                    'permission_id' => $permission['id'],
117                ]
118            );
119            $this->writeItem($link);
120        }
121
122        (new \BO\Zmsbackend\Useraccount\Service\Useraccount())->invalidateAllCaches();
123
124        return $this->readRoleById($roleId, $resolveReferences);
125    }
126
127    private function fetchPermissionsByNamesOrFail(array $permissionNames): array
128    {
129        if ($permissionNames === []) {
130            return [];
131        }
132        $permQuery = new \BO\Zmsbackend\Permission\Repository\Permission(\BO\Zmsbackend\Query\Base::SELECT);
133        $permQuery->addEntityMapping()
134            ->addResolvedReferences(0)
135            ->addConditionNames($permissionNames);
136        $permissions = $this->fetchList($permQuery, new PermissionEntity());
137        if (count($permissions) !== count($permissionNames)) {
138            $found = [];
139            foreach ($permissions as $p) {
140                $found[$p['name']] = true;
141            }
142            $missing = array_values(array_filter($permissionNames, static fn($n) => !isset($found[$n])));
143            throw new \InvalidArgumentException(
144                'Unknown permission name(s): ' . implode(', ', $missing)
145            );
146        }
147        return $permissions;
148    }
149
150    public function deleteRole(int $roleId): ?Entity
151    {
152        $entity = $this->readRoleById($roleId);
153        if (! $entity || ! $entity->hasId()) {
154            return null;
155        }
156
157        $assignedUserCount = (int) ($entity['assignedUserCount'] ?? 0);
158        if ($assignedUserCount > 0) {
159            throw new \BO\Zmsbackend\Role\Exception\AssignedUserListNotEmpty();
160        }
161
162        $query = new \BO\Zmsbackend\Role\Repository\Role(\BO\Zmsbackend\Query\Base::DELETE);
163
164        $query->addConditionRoleId($roleId);
165        $deleted = ($this->deleteItem($query)) ? $entity : null;
166
167        if ($deleted) {
168            (new \BO\Zmsbackend\Useraccount\Service\Useraccount())->invalidateAllCaches();
169        }
170        return $deleted;
171    }
172}