Completed
Pull Request — master (#65)
by
unknown
06:34
created

RoleManager::delete()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 12
c 0
b 0
f 0
rs 9.4285
ccs 8
cts 8
cp 1
nc 2
cc 2
eloc 6
nop 0
crap 2
1
<?php
2
3
namespace Kaliop\eZMigrationBundle\Core\Executor;
4
5
use eZ\Publish\API\Repository\Values\User\Role;
6
use eZ\Publish\API\Repository\RoleService;
7
use eZ\Publish\API\Repository\UserService;
8
use eZ\Publish\API\Repository\Exceptions\InvalidArgumentException;
9
use Kaliop\eZMigrationBundle\API\Collection\RoleCollection;
10
use Kaliop\eZMigrationBundle\Core\Helper\RoleHandler;
11
use Kaliop\eZMigrationBundle\Core\Matcher\RoleMatcher;
12
13
/**
14
 * Handles the role migration definitions.
15
 */
16
class RoleManager extends RepositoryExecutor
17
{
18
    protected $supportedStepTypes = array('role');
19
20 20
    protected $roleHandler;
21
    protected $roleMatcher;
22 20
23 20
    public function __construct(RoleMatcher $roleMatcher, RoleHandler $roleHandler)
24
    {
25
        $this->roleMatcher = $roleMatcher;
26
        $this->roleHandler = $roleHandler;
27
    }
28 1
29
    /**
30 1
     * Method to handle the create operation of the migration instructions
31 1
     */
32
    protected function create()
33 1
    {
34
        $roleService = $this->repository->getRoleService();
35
        $userService = $this->repository->getUserService();
36 1
37
        $roleCreateStruct = $roleService->newRoleCreateStruct($this->dsl['name']);
38 1
39 1
        // Publish new role
40 1
        $role = $roleService->createRole($roleCreateStruct);
41 1
        if(is_callable(array($roleService, 'publishRoleDraft')) {
0 ignored issues
show
Bug introduced by
Avoid IF statements that are always true or false
Loading history...
42 1
            $roleService->publishRoleDraft($role);
0 ignored issues
show
Bug introduced by
This code did not parse for me. Apparently, there is an error somewhere around this line:

Syntax error, unexpected ';'
Loading history...
43 1
        }
44
45 1
        if (array_key_exists('policies', $this->dsl)) {
46
            foreach($this->dsl['policies'] as $key => $ymlPolicy) {
47
                $this->addPolicy($role, $roleService, $ymlPolicy);
48
            }
49 1
        }
50 1
51
        if (array_key_exists('assign', $this->dsl)) {
52
            $this->assignRole($role, $roleService, $userService, $this->dsl['assign']);
53
        }
54
55 1
        $this->setReferences($role);
56
57 1
        return $role;
58 1
    }
59
60 1
    /**
61
     * Method to handle the update operation of the migration instructions
62 1
     */
63
    protected function update()
64
    {
65 1
        $roleCollection = $this->matchRoles('update');
66
67
        if (count($roleCollection) > 1 && array_key_exists('references', $this->dsl)) {
68
            throw new \Exception("Can not execute Role update because multiple roles match, and a references section is specified in the dsl. References can be set when only 1 role matches");
69
        }
70
71 1
        if (count($roleCollection) > 1 && array_key_exists('new_name', $this->dsl)) {
72 1
            throw new \Exception("Can not execute Role update because multiple roles match, and a new_name is specified in the dsl.");
73
        }
74
75
        $roleService = $this->repository->getRoleService();
76 1
        $userService = $this->repository->getUserService();
77 1
78
        foreach ($roleCollection as $key => $role) {
79 1
80
            /** @var \eZ\Publish\API\Repository\Values\User\Role $role */
81 1
            $role = $roleService->loadRoleByIdentifier($this->dsl['name']);
82 1
83 1
            // Updating role name
84 1
            if (array_key_exists('new_name', $this->dsl)) {
85
                $update = $roleService->newRoleUpdateStruct();
86 1
                $update->identifier = $this->dsl['new_name'];
87 1
                $role = $roleService->updateRole($role, $update);
88 1
            }
89
90 1
            if (array_key_exists('policies', $this->dsl)) {
91 1
                $ymlPolicies = $this->dsl['policies'];
92
93 1
                // Removing all policies so we can add them back.
94
                // TODO: Check and update policies instead of remove and add.
95
                $policies = $role->getPolicies();
96
                foreach($policies as $policy) {
97
                    $roleService->deletePolicy($policy);
98 1
                }
99
100
                foreach($ymlPolicies as $ymlPolicy) {
101 1
                    $this->addPolicy($role, $roleService, $ymlPolicy);
102
                }
103 1
            }
104 1
105 1
            if (array_key_exists('assign', $this->dsl)) {
106 1
                $this->assignRole($role, $roleService, $userService, $this->dsl['assign']);
107 1
            }
108
109
            $roleCollection[$key] = $role;
110
        }
111
112
        $this->setReferences($roleCollection);
113
114
        return $roleCollection;
115
    }
116
117
    /**
118 1
     * Method to handle the delete operation of the migration instructions
119
     */
120 1
    protected function delete()
121 1
    {
122
        $roleCollection = $this->matchRoles('delete');
123
124 1
        $roleService = $this->repository->getRoleService();
125 1
126 1
        foreach ($roleCollection as $role) {
127 1
            $roleService->deleteRole($role);
128 1
        }
129 1
130 1
        return $roleCollection;
131 1
    }
132 1
133 1
    /**
134
     * @param string $action
135 1
     * @return RoleCollection
136 1
     * @throws \Exception
137
     */
138 1
    protected function matchRoles($action)
139 1
    {
140
        if (!isset($this->dsl['name']) && !isset($this->dsl['match'])) {
141 1
            throw new \Exception("The name of a role or a match condition is required to $action it.");
142
        }
143
144
        // Backwards compat
145
        if (!isset($this->dsl['match'])) {
146
            $this->dsl['match'] = array('identifier' => $this->dsl['name']);
147
        }
148
149
        $match = $this->dsl['match'];
150
151
        // convert the references passed in the match
152
        foreach ($match as $condition => $values) {
153
            if (is_array($values)) {
154
                foreach ($values as $position => $value) {
155
                    if ($this->referenceResolver->isReference($value)) {
156
                        $match[$condition][$position] = $this->referenceResolver->getReferenceValue($value);
157
                    }
158 1
                }
159
            } else {
160 1
                if ($this->referenceResolver->isReference($values)) {
161
                    $match[$condition] = $this->referenceResolver->getReferenceValue($values);
162 1
                }
163
            }
164 1
        }
165 1
166
        return $this->roleMatcher->match($match);
167
    }
168
169 1
    /**
170 1
     * Set references to object attributes to be retrieved later.
171 1
     *
172
     * The Role Manager currently support setting references to role_ids.
173
     *
174
     * @param \eZ\Publish\API\Repository\Values\User\Role|RoleCollection $role
175
     * @throws \InvalidArgumentException When trying to assign a reference to an unsupported attribute
176
     * @return boolean
177
     */
178
    protected function setReferences($role)
179
    {
180
        if (!array_key_exists('references', $this->dsl)) {
181
            return false;
182
        }
183
184
        if ($role instanceof RoleCollection) {
185
            if (count($role) > 1) {
186
                throw new \InvalidArgumentException('Role Manager does not support setting references for creating/updating of multiple roles');
187
            }
188
            $role = reset($role);
189
        }
190
191
        foreach ($this->dsl['references'] as $reference) {
192 1
            switch ($reference['attribute']) {
193
                case 'role_id':
194 1
                case 'id':
195 1
                    $value = $role->id;
196 1
                    break;
197 1
                case 'identifier':
198 1
                case 'role_identifier':
199
                    $value = $role->identifier;
200 1
                    break;
201
                default:
202
                    throw new \InvalidArgumentException('Role Manager does not support setting references for attribute ' . $reference['attribute']);
203 1
            }
204 1
205 1
            $this->referenceResolver->addReference($reference['identifier'], $value);
206 1
        }
207
208 1
        return true;
209 1
    }
210
211
    /**
212
     * Create a new Limitation object based on the type and value in the $limitation array.
213
     *
214
     * <pre>
215
     * $limitation = array(
216
     *  'identifier' => Type of the limitation
217
     *  'values' => array(Values to base the limitation on)
218
     * )
219
     * </pre>
220
     *
221
     * @param \eZ\Publish\API\Repository\RoleService $roleService
222
     * @param array $limitation
223
     * @return \eZ\Publish\API\Repository\Values\User\Limitation
224
     */
225
    private function createLimitation(RoleService $roleService, array $limitation)
226
    {
227
        $limitationType = $roleService->getLimitationType($limitation['identifier']);
228 1
229 1
        $limitationValue = is_array($limitation['values']) ? $limitation['values'] : array($limitation['values']);
230 1
231
        foreach($limitationValue as $id => $value) {
232
            if ($this->referenceResolver->isReference($value)) {
233
                $value = $this->referenceResolver->getReferenceValue($value);
234
                $limitationValue[$id] = $value;
235
            }
236
        }
237
        $limitationValue = $this->roleHandler->convertLimitationToValue($limitation['identifier'], $limitationValue);
238
        return $limitationType->buildValue($limitationValue);
239
    }
240
241
    /**
242
     * Assign a role to users and groups in the assignment array.
243
     *
244
     * <pre>
245
     * $assignments = array(
246
     *      array(
247
     *          'type' => 'user',
248
     *          'ids' => array(user ids),
249
     *          'limitation' => array(limitations)
250
     *      )
251
     * )
252
     * </pre>
253
     *
254
     * @param \eZ\Publish\API\Repository\Values\User\Role $role
255
     * @param \eZ\Publish\API\Repository\RoleService $roleService
256
     * @param \eZ\Publish\API\Repository\UserService $userService
257
     * @param array $assignments
258
     */
259
    private function assignRole(Role $role, RoleService $roleService, UserService $userService, array $assignments)
260
    {
261
        foreach ($assignments as $assign) {
262
            switch ($assign['type']) {
263
                case 'user':
264
                    foreach ($assign['ids'] as $userId) {
265
                        $user = $userService->loadUser($userId);
266
267
                        if (!array_key_exists('limitation', $assign)) {
268
                            $roleService->assignRoleToUser($role, $user);
269
                        } else {
270
                            foreach ($assign['limitation'] as $limitation) {
271
                                $limitationObject = $this->createLimitation($roleService, $limitation);
272
                                $roleService->assignRoleToUser($role, $user, $limitationObject);
273
                            }
274
                        }
275
                    }
276
                    break;
277
                case 'group':
278
                    foreach ($assign['ids'] as $groupId) {
279 1
                        $group = $userService->loadUserGroup($groupId);
280
281 1
                        if (!array_key_exists('limitation', $assign)) {
282
                            try {
283 1
                                $roleService->assignRoleToUserGroup($role, $group);
284
                            } catch (InvalidArgumentException $e) {}
285
                        } else {
286
                            foreach ($assign['limitation'] as $limitation) {
287
                                $limitationObject = $this->createLimitation($roleService, $limitation);
288
                                try {
289
                                    $roleService->assignRoleToUserGroup($role, $group, $limitationObject);
290 1
                                } catch (InvalidArgumentException $e) {}
291 1
                            }
292
                        }
293
                    }
294
                    break;
295
            }
296
        }
297
    }
298
299
    /**
300
     * Unassign a role from a list of users based on their user ids.
301
     *
302
     * @param Role $role
303
     * @param RoleService $roleService
304
     * @param UserService $userService
305
     * @param array $userIds
306
     */
307
    private function unassignRoleFromUsers(
308
        Role $role,
309
        RoleService $roleService,
310
        UserService $userService,
311
        array $userIds
312
    ) {
313
        foreach ($userIds as $userId) {
314
            $user = $userService->loadUser($userId);
315
            $roleService->unassignRoleFromUser($role, $user);
316
        }
317
    }
318
319
    /**
320
     * Unassign a role from a list of user groups based on their id.
321
     *
322
     * @param Role $role
323
     * @param RoleService $roleService
324
     * @param UserService $userService
325
     * @param array $userGroupIds
326
     */
327
    private function unassignRoleFromGroups(
328
        Role $role,
329
        RoleService $roleService,
330
        UserService $userService,
331
        array $userGroupIds
332
    ) {
333
        foreach ($userGroupIds as $userGroupId) {
334
            $userGroup = $userService->loadUserGroup($userGroupId);
335
            $roleService->unassignRoleFromUserGroup($role, $userGroup);
336
        }
337
    }
338
339
    /**
340
     * Add new policies to the $role Role.
341
     *
342
     * @param \eZ\Publish\API\Repository\Values\User\Role $role
343
     * @param \eZ\Publish\API\Repository\RoleService $roleService
344
     * @param array $policy
345
     */
346
    private function addPolicy(Role $role, RoleService $roleService, array $policy)
347
    {
348
        $policyCreateStruct = $roleService->newPolicyCreateStruct($policy['module'], $policy['function']);
349
350
        if (array_key_exists('limitations', $policy)) {
351
            foreach ($policy['limitations'] as $limitation) {
352
                $limitationObject = $this->createLimitation($roleService, $limitation);
353
                $policyCreateStruct->addLimitation($limitationObject);
354
            }
355
        }
356
357
        $roleService->addPolicy($role, $policyCreateStruct);
358
    }
359
}
360