Completed
Push — EZP-31383 ( 83ce0c )
by
unknown
19:12
created

Handler::copyRole()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 14
c 0
b 0
f 0
cc 2
nc 2
nop 1
rs 9.7998
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
    /** @var \eZ\Publish\Core\Persistence\Legacy\User\Role\LimitationConverter */
51
    protected $limitationConverter;
52
53
    /**
54
     * Construct from userGateway.
55
     *
56
     * @param \eZ\Publish\Core\Persistence\Legacy\User\Gateway $userGateway
57
     * @param \eZ\Publish\Core\Persistence\Legacy\User\Role\Gateway $roleGateway
58
     * @param \eZ\Publish\Core\Persistence\Legacy\User\Mapper $mapper
59
     * @param \eZ\Publish\Core\Persistence\Legacy\User\Role\LimitationConverter $limitationConverter
60
     */
61
    public function __construct(Gateway $userGateway, RoleGateway $roleGateway, Mapper $mapper, LimitationConverter $limitationConverter)
62
    {
63
        $this->userGateway = $userGateway;
64
        $this->roleGateway = $roleGateway;
65
        $this->mapper = $mapper;
66
        $this->limitationConverter = $limitationConverter;
67
    }
68
69
    /**
70
     * Create a user.
71
     *
72
     * The User struct used to create the user will contain an ID which is used
73
     * to reference the user.
74
     *
75
     * @param \eZ\Publish\SPI\Persistence\User $user
76
     *
77
     * @return \eZ\Publish\SPI\Persistence\User
78
     */
79
    public function create(User $user)
80
    {
81
        $this->userGateway->createUser($user);
82
83
        return $user;
84
    }
85
86
    /**
87
     * Loads user with user ID.
88
     *
89
     * @param mixed $userId
90
     *
91
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException If user is not found
92
     *
93
     * @return \eZ\Publish\SPI\Persistence\User
94
     */
95 View Code Duplication
    public function load($userId)
96
    {
97
        $data = $this->userGateway->load($userId);
98
99
        if (empty($data)) {
100
            throw new NotFound('user', $userId);
101
        }
102
103
        return $this->mapper->mapUser(reset($data));
104
    }
105
106
    /**
107
     * Loads user with user login.
108
     *
109
     * @param string $login
110
     *
111
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException If user is not found
112
     *
113
     * @return \eZ\Publish\SPI\Persistence\User
114
     */
115
    public function loadByLogin($login)
116
    {
117
        $data = $this->userGateway->loadByLogin($login);
118
119
        if (empty($data)) {
120
            throw new NotFound('user', $login);
121
        } elseif (isset($data[1])) {
122
            throw new LogicException("Found more then one user with login '{$login}'");
123
        }
124
125
        return $this->mapper->mapUser($data[0]);
126
    }
127
128
    /**
129
     * Loads user(s) with user email.
130
     *
131
     * As earlier eZ Publish versions supported several users having same email (ini config),
132
     * this function may return several users.
133
     *
134
     * @param string $email
135
     *
136
     * @return \eZ\Publish\SPI\Persistence\User[]
137
     */
138
    public function loadByEmail($email)
139
    {
140
        $data = $this->userGateway->loadByEmail($email);
141
142
        if (empty($data)) {
143
            return [];
144
        }
145
146
        return $this->mapper->mapUsers($data);
147
    }
148
149
    /**
150
     * Loads user with user hash.
151
     *
152
     * @param string $hash
153
     *
154
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException If user is not found
155
     *
156
     * @return \eZ\Publish\SPI\Persistence\User
157
     */
158 View Code Duplication
    public function loadUserByToken($hash)
159
    {
160
        $data = $this->userGateway->loadUserByToken($hash);
161
162
        if (empty($data)) {
163
            throw new NotFound('user', $hash);
164
        }
165
166
        return $this->mapper->mapUser(reset($data));
167
    }
168
169
    /**
170
     * Update the user information specified by the user struct.
171
     *
172
     * @param \eZ\Publish\SPI\Persistence\User $user
173
     */
174
    public function update(User $user)
175
    {
176
        $this->userGateway->updateUser($user);
177
    }
178
179
    /**
180
     * Update the user token information specified by the userToken struct.
181
     *
182
     * @param \eZ\Publish\SPI\Persistence\User\UserTokenUpdateStruct $userTokenUpdateStruct
183
     */
184
    public function updateUserToken(UserTokenUpdateStruct $userTokenUpdateStruct)
185
    {
186
        $this->userGateway->updateUserToken($userTokenUpdateStruct);
187
    }
188
189
    /**
190
     * Expires user account key with user hash.
191
     *
192
     * @param string $hash
193
     */
194
    public function expireUserToken($hash)
195
    {
196
        $this->userGateway->expireUserToken($hash);
197
    }
198
199
    /**
200
     * Delete user with the given ID.
201
     *
202
     * @param mixed $userId
203
     */
204
    public function delete($userId)
205
    {
206
        $this->userGateway->deleteUser($userId);
207
    }
208
209
    /**
210
     * Create new role draft.
211
     *
212
     * Sets status to Role::STATUS_DRAFT on the new returned draft.
213
     *
214
     * @param \eZ\Publish\SPI\Persistence\User\RoleCreateStruct $createStruct
215
     *
216
     * @return \eZ\Publish\SPI\Persistence\User\Role
217
     */
218
    public function createRole(RoleCreateStruct $createStruct)
219
    {
220
        return $this->internalCreateRole($createStruct);
221
    }
222
223
    /**
224
     * Creates a draft of existing defined role.
225
     *
226
     * Sets status to Role::STATUS_DRAFT on the new returned draft.
227
     *
228
     * @param mixed $roleId
229
     *
230
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException If role with defined status is not found
231
     *
232
     * @return \eZ\Publish\SPI\Persistence\User\Role
233
     */
234
    public function createRoleDraft($roleId)
235
    {
236
        $createStruct = $this->mapper->createCreateStructFromRole(
237
            $this->loadRole($roleId)
238
        );
239
240
        return $this->internalCreateRole($createStruct, $roleId);
241
    }
242
243
    /**
244
     * Internal method for creating Role.
245
     *
246
     * Used by self::createRole() and self::createRoleDraft()
247
     *
248
     * @param \eZ\Publish\SPI\Persistence\User\RoleCreateStruct $createStruct
249
     * @param mixed|null $roleId Used by self::createRoleDraft() to retain Role id in the draft
250
     *
251
     * @return \eZ\Publish\SPI\Persistence\User\Role
252
     */
253
    protected function internalCreateRole(RoleCreateStruct $createStruct, $roleId = null)
254
    {
255
        $createStruct = clone $createStruct;
256
        $role = $this->mapper->createRoleFromCreateStruct(
257
            $createStruct
258
        );
259
        $role->id = $roleId;
260
        $role->status = Role::STATUS_DRAFT;
261
262
        $this->roleGateway->createRole($role);
263
264
        foreach ($role->policies as $policy) {
265
            $this->addPolicyByRoleDraft($role->id, $policy);
266
        }
267
268
        return $role;
269
    }
270
271
    /**
272
     * Copies an existing role.
273
     *
274
     * @param \eZ\Publish\SPI\Persistence\User\RoleCopyStruct $copyStruct
275
     *
276
     * @return \eZ\Publish\SPI\Persistence\User\Role
277
     */
278
    public function copyRole(User\RoleCopyStruct $copyStruct)
279
    {
280
        $role = $this->mapper->createRoleFromCopyStruct(
281
            $copyStruct
282
        );
283
284
        $this->roleGateway->copyRole($role);
285
286
        foreach ($role->policies as $policy) {
287
            $this->addPolicy($role->id, $policy);
288
        }
289
290
        return $role;
291
    }
292
293
    /**
294
     * Loads a specified role (draft) by $roleId and $status.
295
     *
296
     * @param mixed $roleId
297
     * @param int $status One of Role::STATUS_DEFINED|Role::STATUS_DRAFT
298
     *
299
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException If role with given status does not exist
300
     *
301
     * @return \eZ\Publish\SPI\Persistence\User\Role
302
     */
303 View Code Duplication
    public function loadRole($roleId, $status = Role::STATUS_DEFINED)
304
    {
305
        $data = $this->roleGateway->loadRole($roleId, $status);
306
307
        if (empty($data)) {
308
            throw new RoleNotFound($roleId, $status);
309
        }
310
311
        $role = $this->mapper->mapRole($data);
312
        foreach ($role->policies as $policy) {
313
            $this->limitationConverter->toSPI($policy);
314
        }
315
316
        return $role;
317
    }
318
319
    /**
320
     * Loads a specified role (draft) by $identifier and $status.
321
     *
322
     * @param string $identifier
323
     * @param int $status One of Role::STATUS_DEFINED|Role::STATUS_DRAFT
324
     *
325
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException If role is not found
326
     *
327
     * @return \eZ\Publish\SPI\Persistence\User\Role
328
     */
329 View Code Duplication
    public function loadRoleByIdentifier($identifier, $status = Role::STATUS_DEFINED)
330
    {
331
        $data = $this->roleGateway->loadRoleByIdentifier($identifier, $status);
332
333
        if (empty($data)) {
334
            throw new RoleNotFound($identifier, $status);
335
        }
336
337
        $role = $this->mapper->mapRole($data);
338
        foreach ($role->policies as $policy) {
339
            $this->limitationConverter->toSPI($policy);
340
        }
341
342
        return $role;
343
    }
344
345
    /**
346
     * Loads a role draft by the original role ID.
347
     *
348
     * @param mixed $roleId ID of the role the draft was created from.
349
     *
350
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException If role is not found
351
     *
352
     * @return \eZ\Publish\SPI\Persistence\User\Role
353
     */
354 View Code Duplication
    public function loadRoleDraftByRoleId($roleId)
355
    {
356
        $data = $this->roleGateway->loadRoleDraftByRoleId($roleId);
357
358
        if (empty($data)) {
359
            throw new RoleNotFound($roleId, Role::STATUS_DRAFT);
360
        }
361
362
        $role = $this->mapper->mapRole($data);
363
        foreach ($role->policies as $policy) {
364
            $this->limitationConverter->toSPI($policy);
365
        }
366
367
        return $role;
368
    }
369
370
    /**
371
     * Loads all roles.
372
     *
373
     * @return \eZ\Publish\SPI\Persistence\User\Role[]
374
     */
375 View Code Duplication
    public function loadRoles()
376
    {
377
        $data = $this->roleGateway->loadRoles();
378
379
        $roles = $this->mapper->mapRoles($data);
380
        foreach ($roles as $role) {
381
            foreach ($role->policies as $policy) {
382
                $this->limitationConverter->toSPI($policy);
383
            }
384
        }
385
386
        return $roles;
387
    }
388
389
    /**
390
     * Update role (draft).
391
     *
392
     * @param \eZ\Publish\SPI\Persistence\User\RoleUpdateStruct $role
393
     */
394
    public function updateRole(RoleUpdateStruct $role)
395
    {
396
        $this->roleGateway->updateRole($role);
397
    }
398
399
    /**
400
     * Delete the specified role (draft).
401
     *
402
     * @param mixed $roleId
403
     * @param int $status One of Role::STATUS_DEFINED|Role::STATUS_DRAFT
404
     */
405
    public function deleteRole($roleId, $status = Role::STATUS_DEFINED)
406
    {
407
        $role = $this->loadRole($roleId, $status);
408
409
        foreach ($role->policies as $policy) {
410
            $this->roleGateway->removePolicy($policy->id);
411
        }
412
413
        $this->roleGateway->deleteRole($role->id, $status);
414
    }
415
416
    /**
417
     * Publish the specified role draft.
418
     *
419
     * @param mixed $roleDraftId
420
     */
421
    public function publishRoleDraft($roleDraftId)
422
    {
423
        $roleDraft = $this->loadRole($roleDraftId, Role::STATUS_DRAFT);
424
425
        try {
426
            $originalRoleId = $roleDraft->originalId;
427
            $role = $this->loadRole($originalRoleId);
428
            $roleAssignments = $this->loadRoleAssignmentsByRoleId($role->id);
429
            $this->deleteRole($role->id);
430
431
            foreach ($roleAssignments as $roleAssignment) {
432
                if (empty($roleAssignment->limitationIdentifier)) {
433
                    $this->assignRole($roleAssignment->contentId, $originalRoleId);
434
                } else {
435
                    $this->assignRole(
436
                        $roleAssignment->contentId,
437
                        $originalRoleId,
438
                        [$roleAssignment->limitationIdentifier => $roleAssignment->values]
439
                    );
440
                }
441
            }
442
            $this->roleGateway->publishRoleDraft($roleDraft->id, $role->id);
443
        } catch (NotFound $e) {
444
            // If no published role is found, only publishing is needed, without specifying original role ID as there is none.
445
            $this->roleGateway->publishRoleDraft($roleDraft->id);
446
        }
447
    }
448
449
    /**
450
     * Adds a policy to a role draft.
451
     *
452
     * @param mixed $roleId
453
     * @param \eZ\Publish\SPI\Persistence\User\Policy $policy
454
     *
455
     * @return \eZ\Publish\SPI\Persistence\User\Policy
456
     */
457
    public function addPolicyByRoleDraft($roleId, Policy $policy)
458
    {
459
        $legacyPolicy = clone $policy;
460
        $legacyPolicy->originalId = $policy->id;
461
        $this->limitationConverter->toLegacy($legacyPolicy);
462
463
        $this->roleGateway->addPolicy($roleId, $legacyPolicy);
464
        $policy->id = $legacyPolicy->id;
465
        $policy->originalId = $legacyPolicy->originalId;
466
        $policy->roleId = $legacyPolicy->roleId;
467
468
        return $policy;
469
    }
470
471
    /**
472
     * Adds a policy to a role.
473
     *
474
     * @param mixed $roleId
475
     * @param \eZ\Publish\SPI\Persistence\User\Policy $policy
476
     *
477
     * @return \eZ\Publish\SPI\Persistence\User\Policy
478
     */
479
    public function addPolicy($roleId, Policy $policy)
480
    {
481
        $legacyPolicy = clone $policy;
482
        $this->limitationConverter->toLegacy($legacyPolicy);
483
484
        $this->roleGateway->addPolicy($roleId, $legacyPolicy);
485
        $policy->id = $legacyPolicy->id;
486
        $policy->roleId = $legacyPolicy->roleId;
487
488
        return $policy;
489
    }
490
491
    /**
492
     * Update a policy.
493
     *
494
     * Replaces limitations values with new values.
495
     *
496
     * @param \eZ\Publish\SPI\Persistence\User\Policy $policy
497
     */
498
    public function updatePolicy(Policy $policy)
499
    {
500
        $policy = clone $policy;
501
        $this->limitationConverter->toLegacy($policy);
502
503
        $this->roleGateway->removePolicyLimitations($policy->id);
504
        $this->roleGateway->addPolicyLimitations($policy->id, $policy->limitations === '*' ? [] : $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...
505
    }
506
507
    /**
508
     * Removes a policy from a role.
509
     *
510
     * @param mixed $policyId
511
     * @param mixed $roleId
512
     */
513
    public function deletePolicy($policyId, $roleId)
514
    {
515
        // Each policy can only be associated to exactly one role. Thus it is
516
        // sufficient to use the policyId for identification and just remove
517
        // the policy completely.
518
        $this->roleGateway->removePolicy($policyId);
519
    }
520
521
    /**
522
     * Returns the user policies associated with the user (including inherited policies from user groups).
523
     *
524
     * @param mixed $userId
525
     *
526
     * @return \eZ\Publish\SPI\Persistence\User\Policy[]
527
     */
528 View Code Duplication
    public function loadPoliciesByUserId($userId)
529
    {
530
        $data = $this->roleGateway->loadPoliciesByUserId($userId);
531
532
        $policies = $this->mapper->mapPolicies($data);
533
534
        foreach ($policies as $policy) {
535
            $this->limitationConverter->toSPI($policy);
536
        }
537
538
        return $policies;
539
    }
540
541
    /**
542
     * Assigns role to a user or user group with given limitations.
543
     *
544
     * The limitation array looks like:
545
     * <code>
546
     *  array(
547
     *      'Subtree' => array(
548
     *          '/1/2/',
549
     *          '/1/4/',
550
     *      ),
551
     *      'Foo' => array( 'Bar' ),
552
     *      …
553
     *  )
554
     * </code>
555
     *
556
     * Where the keys are the limitation identifiers, and the respective values
557
     * are an array of limitation values. The limitation parameter is optional.
558
     *
559
     * @param mixed $contentId The groupId or userId to assign the role to.
560
     * @param mixed $roleId
561
     * @param array $limitation
562
     */
563
    public function assignRole($contentId, $roleId, array $limitation = null)
564
    {
565
        $limitation = $limitation ?: ['' => ['']];
566
        $this->userGateway->assignRole($contentId, $roleId, $limitation);
567
    }
568
569
    /**
570
     * Un-assign a role.
571
     *
572
     * @param mixed $contentId The user or user group Id to un-assign the role from.
573
     * @param mixed $roleId
574
     */
575
    public function unassignRole($contentId, $roleId)
576
    {
577
        $this->userGateway->removeRole($contentId, $roleId);
578
    }
579
580
    /**
581
     * Un-assign a role by assignment ID.
582
     *
583
     * @param mixed $roleAssignmentId The assignment ID.
584
     */
585
    public function removeRoleAssignment($roleAssignmentId)
586
    {
587
        $this->userGateway->removeRoleAssignmentById($roleAssignmentId);
588
    }
589
590
    /**
591
     * Loads role assignment for specified assignment ID.
592
     *
593
     * @param mixed $roleAssignmentId
594
     *
595
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException If role assignment is not found
596
     *
597
     * @return \eZ\Publish\SPI\Persistence\User\RoleAssignment
598
     */
599
    public function loadRoleAssignment($roleAssignmentId)
600
    {
601
        $data = $this->roleGateway->loadRoleAssignment($roleAssignmentId);
602
603
        if (empty($data)) {
604
            throw new NotFound('roleAssignment', $roleAssignmentId);
605
        }
606
607
        return $this->mapper->mapRoleAssignments($data)[0];
608
    }
609
610
    /**
611
     * Loads roles assignments Role.
612
     *
613
     * Role Assignments with same roleId and limitationIdentifier will be merged together into one.
614
     *
615
     * @param mixed $roleId
616
     *
617
     * @return \eZ\Publish\SPI\Persistence\User\RoleAssignment[]
618
     */
619 View Code Duplication
    public function loadRoleAssignmentsByRoleId($roleId)
620
    {
621
        $data = $this->roleGateway->loadRoleAssignmentsByRoleId($roleId);
622
623
        if (empty($data)) {
624
            return [];
625
        }
626
627
        return $this->mapper->mapRoleAssignments($data);
628
    }
629
630
    /**
631
     * Loads roles assignments to a user/group.
632
     *
633
     * Role Assignments with same roleId and limitationIdentifier will be merged together into one.
634
     *
635
     * @param mixed $groupId In legacy storage engine this is the content object id roles are assigned to in ezuser_role.
636
     *                      By the nature of legacy this can currently also be used to get by $userId.
637
     * @param bool $inherit If true also return inherited role assignments from user groups.
638
     *
639
     * @return \eZ\Publish\SPI\Persistence\User\RoleAssignment[]
640
     */
641 View Code Duplication
    public function loadRoleAssignmentsByGroupId($groupId, $inherit = false)
642
    {
643
        $data = $this->roleGateway->loadRoleAssignmentsByGroupId($groupId, $inherit);
644
645
        if (empty($data)) {
646
            return [];
647
        }
648
649
        return $this->mapper->mapRoleAssignments($data);
650
    }
651
}
652