Completed
Push — master ( 59965c...4339a8 )
by
unknown
114:08 queued 95:41
created

Handler::assignRole()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 3
nc 2
nop 3
dl 0
loc 5
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * File containing the UserHandler interface.
5
 *
6
 * @copyright Copyright (C) eZ Systems AS. All rights reserved.
7
 * @license For full copyright and license information view LICENSE file distributed with this source code.
8
 */
9
namespace eZ\Publish\Core\Persistence\Legacy\User;
10
11
use eZ\Publish\SPI\Persistence\User;
12
use eZ\Publish\SPI\Persistence\User\UserTokenUpdateStruct;
13
use eZ\Publish\SPI\Persistence\User\Handler as BaseUserHandler;
14
use eZ\Publish\SPI\Persistence\User\Role;
15
use eZ\Publish\SPI\Persistence\User\RoleCreateStruct;
16
use eZ\Publish\SPI\Persistence\User\RoleUpdateStruct;
17
use eZ\Publish\SPI\Persistence\User\Policy;
18
use eZ\Publish\Core\Persistence\Legacy\Exception\RoleNotFound;
19
use eZ\Publish\Core\Persistence\Legacy\User\Role\Gateway as RoleGateway;
20
use eZ\Publish\Core\Persistence\Legacy\User\Role\LimitationConverter;
21
use eZ\Publish\Core\Base\Exceptions\NotFoundException as NotFound;
22
use LogicException;
23
24
/**
25
 * Storage Engine handler for user module.
26
 */
27
class Handler implements BaseUserHandler
28
{
29
    /**
30
     * Gateway for storing user data.
31
     *
32
     * @var \eZ\Publish\Core\Persistence\Legacy\User\Gateway
33
     */
34
    protected $userGateway;
35
36
    /**
37
     * Gateway for storing role data.
38
     *
39
     * @var \eZ\Publish\Core\Persistence\Legacy\User\Role\Gateway
40
     */
41
    protected $roleGateway;
42
43
    /**
44
     * Mapper for user related objects.
45
     *
46
     * @var \eZ\Publish\Core\Persistence\Legacy\User\Mapper
47
     */
48
    protected $mapper;
49
50
    /**
51
     * @var \eZ\Publish\Core\Persistence\Legacy\User\Role\LimitationConverter
52
     */
53
    protected $limitationConverter;
54
55
    /**
56
     * Construct from userGateway.
57
     *
58
     * @param \eZ\Publish\Core\Persistence\Legacy\User\Gateway $userGateway
59
     * @param \eZ\Publish\Core\Persistence\Legacy\User\Role\Gateway $roleGateway
60
     * @param \eZ\Publish\Core\Persistence\Legacy\User\Mapper $mapper
61
     * @param \eZ\Publish\Core\Persistence\Legacy\User\Role\LimitationConverter $limitationConverter
62
     */
63
    public function __construct(Gateway $userGateway, RoleGateway $roleGateway, Mapper $mapper, LimitationConverter $limitationConverter)
64
    {
65
        $this->userGateway = $userGateway;
66
        $this->roleGateway = $roleGateway;
67
        $this->mapper = $mapper;
68
        $this->limitationConverter = $limitationConverter;
69
    }
70
71
    /**
72
     * Create a user.
73
     *
74
     * The User struct used to create the user will contain an ID which is used
75
     * to reference the user.
76
     *
77
     * @param \eZ\Publish\SPI\Persistence\User $user
78
     *
79
     * @return \eZ\Publish\SPI\Persistence\User
80
     */
81
    public function create(User $user)
82
    {
83
        $this->userGateway->createUser($user);
84
85
        return $user;
86
    }
87
88
    /**
89
     * Loads user with user ID.
90
     *
91
     * @param mixed $userId
92
     *
93
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException If user is not found
94
     *
95
     * @return \eZ\Publish\SPI\Persistence\User
96
     */
97 View Code Duplication
    public function load($userId)
98
    {
99
        $data = $this->userGateway->load($userId);
100
101
        if (empty($data)) {
102
            throw new NotFound('user', $userId);
103
        }
104
105
        return $this->mapper->mapUser(reset($data));
106
    }
107
108
    /**
109
     * Loads user with user login.
110
     *
111
     * @param string $login
112
     *
113
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException If user is not found
114
     *
115
     * @return \eZ\Publish\SPI\Persistence\User
116
     */
117
    public function loadByLogin($login)
118
    {
119
        $data = $this->userGateway->loadByLogin($login);
120
121
        if (empty($data)) {
122
            throw new NotFound('user', $login);
123
        } elseif (isset($data[1])) {
124
            throw new LogicException("Found more then one user with login '{$login}'");
125
        }
126
127
        return $this->mapper->mapUser($data[0]);
128
    }
129
130
    /**
131
     * Loads user(s) with user email.
132
     *
133
     * As earlier eZ Publish versions supported several users having same email (ini config),
134
     * this function may return several users.
135
     *
136
     * @param string $email
137
     *
138
     * @return \eZ\Publish\SPI\Persistence\User[]
139
     */
140
    public function loadByEmail($email)
141
    {
142
        $data = $this->userGateway->loadByEmail($email);
143
144
        if (empty($data)) {
145
            return array();
146
        }
147
148
        return $this->mapper->mapUsers($data);
149
    }
150
151
    /**
152
     * Loads user with user hash.
153
     *
154
     * @param string $hash
155
     *
156
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException If user is not found
157
     *
158
     * @return \eZ\Publish\SPI\Persistence\User
159
     */
160 View Code Duplication
    public function loadUserByToken($hash)
161
    {
162
        $data = $this->userGateway->loadUserByToken($hash);
163
164
        if (empty($data)) {
165
            throw new NotFound('user', $hash);
166
        }
167
168
        return $this->mapper->mapUser(reset($data));
169
    }
170
171
    /**
172
     * Update the user information specified by the user struct.
173
     *
174
     * @param \eZ\Publish\SPI\Persistence\User $user
175
     */
176
    public function update(User $user)
177
    {
178
        $this->userGateway->updateUser($user);
179
    }
180
181
    /**
182
     * Update the user token information specified by the userToken struct.
183
     *
184
     * @param \eZ\Publish\SPI\Persistence\User\UserTokenUpdateStruct $userTokenUpdateStruct
185
     */
186
    public function updateUserToken(UserTokenUpdateStruct $userTokenUpdateStruct)
187
    {
188
        $this->userGateway->updateUserToken($userTokenUpdateStruct);
189
    }
190
191
    /**
192
     * Expires user account key with user hash.
193
     *
194
     * @param string $hash
195
     */
196
    public function expireUserToken($hash)
197
    {
198
        $this->userGateway->expireUserToken($hash);
199
    }
200
201
    /**
202
     * Delete user with the given ID.
203
     *
204
     * @param mixed $userId
205
     */
206
    public function delete($userId)
207
    {
208
        $this->userGateway->deleteUser($userId);
209
    }
210
211
    /**
212
     * Create new role draft.
213
     *
214
     * Sets status to Role::STATUS_DRAFT on the new returned draft.
215
     *
216
     * @param \eZ\Publish\SPI\Persistence\User\RoleCreateStruct $createStruct
217
     *
218
     * @return \eZ\Publish\SPI\Persistence\User\Role
219
     */
220
    public function createRole(RoleCreateStruct $createStruct)
221
    {
222
        return $this->internalCreateRole($createStruct);
223
    }
224
225
    /**
226
     * Creates a draft of existing defined role.
227
     *
228
     * Sets status to Role::STATUS_DRAFT on the new returned draft.
229
     *
230
     * @param mixed $roleId
231
     *
232
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException If role with defined status is not found
233
     *
234
     * @return \eZ\Publish\SPI\Persistence\User\Role
235
     */
236
    public function createRoleDraft($roleId)
237
    {
238
        $createStruct = $this->mapper->createCreateStructFromRole(
239
            $this->loadRole($roleId)
240
        );
241
242
        return $this->internalCreateRole($createStruct, $roleId);
243
    }
244
245
    /**
246
     * Internal method for creating Role.
247
     *
248
     * Used by self::createRole() and self::createRoleDraft()
249
     *
250
     * @param \eZ\Publish\SPI\Persistence\User\RoleCreateStruct $createStruct
251
     * @param mixed|null $roleId Used by self::createRoleDraft() to retain Role id in the draft
252
     *
253
     * @return \eZ\Publish\SPI\Persistence\User\Role
254
     */
255
    protected function internalCreateRole(RoleCreateStruct $createStruct, $roleId = null)
256
    {
257
        $createStruct = clone $createStruct;
258
        $role = $this->mapper->createRoleFromCreateStruct(
259
            $createStruct
260
        );
261
        $role->id = $roleId;
262
        $role->status = Role::STATUS_DRAFT;
263
264
        $this->roleGateway->createRole($role);
265
266
        foreach ($role->policies as $policy) {
267
            $this->addPolicyByRoleDraft($role->id, $policy);
268
        }
269
270
        return $role;
271
    }
272
273
    /**
274
     * Loads a specified role (draft) by $roleId and $status.
275
     *
276
     * @param mixed $roleId
277
     * @param int $status One of Role::STATUS_DEFINED|Role::STATUS_DRAFT
278
     *
279
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException If role with given status does not exist
280
     *
281
     * @return \eZ\Publish\SPI\Persistence\User\Role
282
     */
283 View Code Duplication
    public function loadRole($roleId, $status = Role::STATUS_DEFINED)
284
    {
285
        $data = $this->roleGateway->loadRole($roleId, $status);
286
287
        if (empty($data)) {
288
            throw new RoleNotFound($roleId, $status);
289
        }
290
291
        $role = $this->mapper->mapRole($data);
292
        foreach ($role->policies as $policy) {
293
            $this->limitationConverter->toSPI($policy);
294
        }
295
296
        return $role;
297
    }
298
299
    /**
300
     * Loads a specified role (draft) by $identifier and $status.
301
     *
302
     * @param string $identifier
303
     * @param int $status One of Role::STATUS_DEFINED|Role::STATUS_DRAFT
304
     *
305
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException If role is not found
306
     *
307
     * @return \eZ\Publish\SPI\Persistence\User\Role
308
     */
309 View Code Duplication
    public function loadRoleByIdentifier($identifier, $status = Role::STATUS_DEFINED)
310
    {
311
        $data = $this->roleGateway->loadRoleByIdentifier($identifier, $status);
312
313
        if (empty($data)) {
314
            throw new RoleNotFound($identifier, $status);
315
        }
316
317
        $role = $this->mapper->mapRole($data);
318
        foreach ($role->policies as $policy) {
319
            $this->limitationConverter->toSPI($policy);
320
        }
321
322
        return $role;
323
    }
324
325
    /**
326
     * Loads a role draft by the original role ID.
327
     *
328
     * @param mixed $roleId ID of the role the draft was created from.
329
     *
330
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException If role is not found
331
     *
332
     * @return \eZ\Publish\SPI\Persistence\User\Role
333
     */
334 View Code Duplication
    public function loadRoleDraftByRoleId($roleId)
335
    {
336
        $data = $this->roleGateway->loadRoleDraftByRoleId($roleId);
337
338
        if (empty($data)) {
339
            throw new RoleNotFound($roleId, Role::STATUS_DRAFT);
340
        }
341
342
        $role = $this->mapper->mapRole($data);
343
        foreach ($role->policies as $policy) {
344
            $this->limitationConverter->toSPI($policy);
345
        }
346
347
        return $role;
348
    }
349
350
    /**
351
     * Loads all roles.
352
     *
353
     * @return \eZ\Publish\SPI\Persistence\User\Role[]
354
     */
355 View Code Duplication
    public function loadRoles()
356
    {
357
        $data = $this->roleGateway->loadRoles();
358
359
        $roles = $this->mapper->mapRoles($data);
360
        foreach ($roles as $role) {
361
            foreach ($role->policies as $policy) {
362
                $this->limitationConverter->toSPI($policy);
363
            }
364
        }
365
366
        return $roles;
367
    }
368
369
    /**
370
     * Update role (draft).
371
     *
372
     * @param \eZ\Publish\SPI\Persistence\User\RoleUpdateStruct $role
373
     */
374
    public function updateRole(RoleUpdateStruct $role)
375
    {
376
        $this->roleGateway->updateRole($role);
377
    }
378
379
    /**
380
     * Delete the specified role (draft).
381
     *
382
     * @param mixed $roleId
383
     * @param int $status One of Role::STATUS_DEFINED|Role::STATUS_DRAFT
384
     */
385
    public function deleteRole($roleId, $status = Role::STATUS_DEFINED)
386
    {
387
        $role = $this->loadRole($roleId, $status);
388
389
        foreach ($role->policies as $policy) {
390
            $this->roleGateway->removePolicy($policy->id);
391
        }
392
393
        $this->roleGateway->deleteRole($role->id, $status);
394
    }
395
396
    /**
397
     * Publish the specified role draft.
398
     *
399
     * @param mixed $roleDraftId
400
     */
401
    public function publishRoleDraft($roleDraftId)
402
    {
403
        $roleDraft = $this->loadRole($roleDraftId, Role::STATUS_DRAFT);
404
405
        try {
406
            $originalRoleId = $roleDraft->originalId;
407
            $role = $this->loadRole($originalRoleId);
408
            $roleAssignments = $this->loadRoleAssignmentsByRoleId($role->id);
409
            $this->deleteRole($role->id);
410
411
            foreach ($roleAssignments as $roleAssignment) {
412
                if (empty($roleAssignment->limitationIdentifier)) {
413
                    $this->assignRole($roleAssignment->contentId, $originalRoleId);
414
                } else {
415
                    $this->assignRole(
416
                        $roleAssignment->contentId,
417
                        $originalRoleId,
418
                        [$roleAssignment->limitationIdentifier => $roleAssignment->values]
419
                    );
420
                }
421
            }
422
            $this->roleGateway->publishRoleDraft($roleDraft->id, $role->id);
423
        } catch (NotFound $e) {
424
            // If no published role is found, only publishing is needed, without specifying original role ID as there is none.
425
            $this->roleGateway->publishRoleDraft($roleDraft->id);
426
        }
427
    }
428
429
    /**
430
     * Adds a policy to a role draft.
431
     *
432
     * @param mixed $roleId
433
     * @param \eZ\Publish\SPI\Persistence\User\Policy $policy
434
     *
435
     * @return \eZ\Publish\SPI\Persistence\User\Policy
436
     */
437
    public function addPolicyByRoleDraft($roleId, Policy $policy)
438
    {
439
        $legacyPolicy = clone $policy;
440
        $legacyPolicy->originalId = $policy->id;
441
        $this->limitationConverter->toLegacy($legacyPolicy);
442
443
        $this->roleGateway->addPolicy($roleId, $legacyPolicy);
444
        $policy->id = $legacyPolicy->id;
445
        $policy->originalId = $legacyPolicy->originalId;
446
        $policy->roleId = $legacyPolicy->roleId;
447
448
        return $policy;
449
    }
450
451
    /**
452
     * Adds a policy to a role.
453
     *
454
     * @param mixed $roleId
455
     * @param \eZ\Publish\SPI\Persistence\User\Policy $policy
456
     *
457
     * @return \eZ\Publish\SPI\Persistence\User\Policy
458
     */
459
    public function addPolicy($roleId, Policy $policy)
460
    {
461
        $legacyPolicy = clone $policy;
462
        $this->limitationConverter->toLegacy($legacyPolicy);
463
464
        $this->roleGateway->addPolicy($roleId, $legacyPolicy);
465
        $policy->id = $legacyPolicy->id;
466
        $policy->roleId = $legacyPolicy->roleId;
467
468
        return $policy;
469
    }
470
471
    /**
472
     * Update a policy.
473
     *
474
     * Replaces limitations values with new values.
475
     *
476
     * @param \eZ\Publish\SPI\Persistence\User\Policy $policy
477
     */
478
    public function updatePolicy(Policy $policy)
479
    {
480
        $policy = clone $policy;
481
        $this->limitationConverter->toLegacy($policy);
482
483
        $this->roleGateway->removePolicyLimitations($policy->id);
484
        $this->roleGateway->addPolicyLimitations($policy->id, $policy->limitations === '*' ? array() : $policy->limitations);
0 ignored issues
show
Bug introduced by
It seems like $policy->limitations ===... : $policy->limitations can also be of type string; however, eZ\Publish\Core\Persiste...:addPolicyLimitations() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
485
    }
486
487
    /**
488
     * Removes a policy from a role.
489
     *
490
     * @param mixed $policyId
491
     * @param mixed $roleId
492
     */
493
    public function deletePolicy($policyId, $roleId)
494
    {
495
        // Each policy can only be associated to exactly one role. Thus it is
496
        // sufficient to use the policyId for identification and just remove
497
        // the policy completely.
498
        $this->roleGateway->removePolicy($policyId);
499
    }
500
501
    /**
502
     * Returns the user policies associated with the user (including inherited policies from user groups).
503
     *
504
     * @param mixed $userId
505
     *
506
     * @return \eZ\Publish\SPI\Persistence\User\Policy[]
507
     */
508 View Code Duplication
    public function loadPoliciesByUserId($userId)
509
    {
510
        $data = $this->roleGateway->loadPoliciesByUserId($userId);
511
512
        $policies = $this->mapper->mapPolicies($data);
513
514
        foreach ($policies as $policy) {
515
            $this->limitationConverter->toSPI($policy);
516
        }
517
518
        return $policies;
519
    }
520
521
    /**
522
     * Assigns role to a user or user group with given limitations.
523
     *
524
     * The limitation array looks like:
525
     * <code>
526
     *  array(
527
     *      'Subtree' => array(
528
     *          '/1/2/',
529
     *          '/1/4/',
530
     *      ),
531
     *      'Foo' => array( 'Bar' ),
532
     *      …
533
     *  )
534
     * </code>
535
     *
536
     * Where the keys are the limitation identifiers, and the respective values
537
     * are an array of limitation values. The limitation parameter is optional.
538
     *
539
     * @param mixed $contentId The groupId or userId to assign the role to.
540
     * @param mixed $roleId
541
     * @param array $limitation
542
     */
543
    public function assignRole($contentId, $roleId, array $limitation = null)
544
    {
545
        $limitation = $limitation ?: array('' => array(''));
546
        $this->userGateway->assignRole($contentId, $roleId, $limitation);
547
    }
548
549
    /**
550
     * Un-assign a role.
551
     *
552
     * @param mixed $contentId The user or user group Id to un-assign the role from.
553
     * @param mixed $roleId
554
     */
555
    public function unassignRole($contentId, $roleId)
556
    {
557
        $this->userGateway->removeRole($contentId, $roleId);
558
    }
559
560
    /**
561
     * Un-assign a role by assignment ID.
562
     *
563
     * @param mixed $roleAssignmentId The assignment ID.
564
     */
565
    public function removeRoleAssignment($roleAssignmentId)
566
    {
567
        $this->userGateway->removeRoleAssignmentById($roleAssignmentId);
568
    }
569
570
    /**
571
     * Loads role assignment for specified assignment ID.
572
     *
573
     * @param mixed $roleAssignmentId
574
     *
575
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException If role assignment is not found
576
     *
577
     * @return \eZ\Publish\SPI\Persistence\User\RoleAssignment
578
     */
579
    public function loadRoleAssignment($roleAssignmentId)
580
    {
581
        $data = $this->roleGateway->loadRoleAssignment($roleAssignmentId);
582
583
        if (empty($data)) {
584
            throw new NotFound('roleAssignment', $roleAssignmentId);
585
        }
586
587
        return $this->mapper->mapRoleAssignments($data)[0];
588
    }
589
590
    /**
591
     * Loads roles assignments Role.
592
     *
593
     * Role Assignments with same roleId and limitationIdentifier will be merged together into one.
594
     *
595
     * @param mixed $roleId
596
     *
597
     * @return \eZ\Publish\SPI\Persistence\User\RoleAssignment[]
598
     */
599 View Code Duplication
    public function loadRoleAssignmentsByRoleId($roleId)
600
    {
601
        $data = $this->roleGateway->loadRoleAssignmentsByRoleId($roleId);
602
603
        if (empty($data)) {
604
            return array();
605
        }
606
607
        return $this->mapper->mapRoleAssignments($data);
608
    }
609
610
    /**
611
     * Loads roles assignments to a user/group.
612
     *
613
     * Role Assignments with same roleId and limitationIdentifier will be merged together into one.
614
     *
615
     * @param mixed $groupId In legacy storage engine this is the content object id roles are assigned to in ezuser_role.
616
     *                      By the nature of legacy this can currently also be used to get by $userId.
617
     * @param bool $inherit If true also return inherited role assignments from user groups.
618
     *
619
     * @return \eZ\Publish\SPI\Persistence\User\RoleAssignment[]
620
     */
621 View Code Duplication
    public function loadRoleAssignmentsByGroupId($groupId, $inherit = false)
622
    {
623
        $data = $this->roleGateway->loadRoleAssignmentsByGroupId($groupId, $inherit);
624
625
        if (empty($data)) {
626
            return array();
627
        }
628
629
        return $this->mapper->mapRoleAssignments($data);
630
    }
631
}
632