Completed
Push — in-memory-cache2 ( 0f2241...bf3815 )
by André
18:53
created

UserHandler::create()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 1
dl 0
loc 15
rs 9.7666
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * File containing a User Handler impl.
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\Cache;
10
11
use eZ\Publish\Core\Persistence\Cache\InMemory\InMemoryCache;
12
use eZ\Publish\SPI\Persistence\Handler as PersistenceHandler;
13
use eZ\Publish\SPI\Persistence\User\UserTokenUpdateStruct;
14
use eZ\Publish\SPI\Persistence\User\Handler as UserHandlerInterface;
15
use eZ\Publish\SPI\Persistence\User;
16
use eZ\Publish\SPI\Persistence\User\Role;
17
use eZ\Publish\SPI\Persistence\User\RoleAssignment;
18
use eZ\Publish\SPI\Persistence\User\RoleCreateStruct;
19
use eZ\Publish\SPI\Persistence\User\RoleUpdateStruct;
20
use eZ\Publish\SPI\Persistence\User\Policy;
21
use Symfony\Component\Cache\Adapter\TagAwareAdapterInterface;
22
23
/**
24
 * Cache handler for user module.
25
 */
26
class UserHandler extends AbstractInMemoryHandler implements UserHandlerInterface
27
{
28
    /** @var callable */
29
    private $getUserTags;
30
31
    /** @var callable */
32
    private $getUserKeys;
33
34
    /** @var callable */
35
    private $getRoleTags;
36
37
    /** @var callable */
38
    private $getRoleKeys;
39
40
    /** @var callable */
41
    private $getRoleAssignmentTags;
42
43
    /** @var callable */
44
    private $getRoleAssignmentKeys;
45
46
    public function __construct(
47
        TagAwareAdapterInterface $cache,
48
        PersistenceHandler $persistenceHandler,
49
        PersistenceLogger $logger,
50
        InMemoryCache $inMemory
51
    ) {
52
        parent::__construct($cache, $persistenceHandler, $logger, $inMemory);
53
54
        $this->getUserTags = static function (User $user) {
55
            return ['content-' . $user->id, 'user-' . $user->id];
56
        };
57
        $this->getUserKeys = static function (User $user) {
58
            return [
59
                'ez-user-' . $user->id,
60
                'ez-user-' . \str_replace('@', '§', $user->login) . '-by-login',
61
                //'ez-user-' . $hash . '-by-account-key',
62
            ];
63
        };
64
        $this->getRoleTags = static function (Role $role) {
65
            return ['role-' . $role->id];
66
        };
67
        $this->getRoleKeys = static function (Role $role) {
68
            return [
69
                'ez-role-' . $role->id,
70
                'ez-role-' . $role->identifier . '-by-identifier',
71
            ];
72
        };
73
        $this->getRoleAssignmentTags = static function (RoleAssignment $roleAssignment) {
74
            return [
75
                'role-assignment-' . $roleAssignment->id,
76
                'role-assignment-group-list-' . $roleAssignment->contentId,
77
                'role-assignment-role-list-' . $roleAssignment->roleId,
78
            ];
79
        };
80
        $this->getRoleAssignmentKeys = static function (RoleAssignment $roleAssignment) {
81
            return [
82
                'ez-role-assignment-' . $roleAssignment->id,
83
            ];
84
        };
85
    }
86
87
    /**
88
     * {@inheritdoc}
89
     */
90
    public function create(User $user)
91
    {
92
        $this->logger->logCall(__METHOD__, array('struct' => $user));
93
        $return = $this->persistenceHandler->userHandler()->create($user);
94
95
        // Clear corresponding content cache as creation of the User changes it's external data
96
        $this->invalidateCache(['content-fields-' . $user->id]);
97
        $this->deleteCache([
98
            'ez-user-' . $user->id,
99
            'ez-user-' . str_replace('@', '§', $user->login) . '-by-login',
100
            'ez-user-' . str_replace('@', '§', $user->email) . '-by-email',
101
        ]);
102
103
        return $return;
104
    }
105
106
    /**
107
     * {@inheritdoc}
108
     */
109
    public function load($userId)
110
    {
111
        return $this->getCacheValue(
112
            $userId,
113
            'ez-user-',
114
            function ($userId) {
115
                return $this->persistenceHandler->userHandler()->load($userId);
116
            },
117
            $this->getUserTags,
118
            $this->getUserKeys
119
        );
120
    }
121
122
    /**
123
     * {@inheritdoc}
124
     */
125 View Code Duplication
    public function loadByLogin($login)
126
    {
127
        return $this->getCacheValue(
128
            str_replace('@', '§', $login),
129
            'ez-user-',
130
            function ($escapedLogin) use ($login) {
0 ignored issues
show
Unused Code introduced by
The parameter $escapedLogin is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
131
                return $this->persistenceHandler->userHandler()->loadByLogin($login);
132
            },
133
            $this->getUserTags,
134
            $this->getUserKeys,
135
            '-by-login'
136
        );
137
    }
138
139
    /**
140
     * {@inheritdoc}
141
     */
142 View Code Duplication
    public function loadByEmail($email)
143
    {
144
        // As load by email can return several items we threat it like a list here.
145
        return $this->getListCacheValue(
146
            'ez-user-' . str_replace('@', '§', $email) . '-by-email',
147
            function () use ($email) {
148
                return $this->persistenceHandler->userHandler()->loadByEmail($email);
149
            },
150
            $this->getUserTags,
151
            $this->getUserKeys
152
        );
153
    }
154
155
    /**
156
     * {@inheritdoc}
157
     */
158
    public function loadUserByToken($hash)
159
    {
160
        $getUserKeysFn = $this->getUserKeys;
161
        $getUserTagsFn = $this->getUserTags;
162
163
        return $this->getCacheValue(
164
            $hash,
165
            'ez-user-',
166
            function ($hash) {
167
                return $this->persistenceHandler->userHandler()->loadUserByToken($hash);
168
            },
169
            static function (User $user) use ($getUserTagsFn) {
170
                $tags = $getUserTagsFn($user);
171
                // See updateUserToken()
172
                $tags[] = 'user-' . $user->id . '-account-key';
173
174
                return $tags;
175
            },
176
            static function (User $user) use ($hash, $getUserKeysFn) {
177
                $keys = $getUserKeysFn($user);
178
                $keys[] = 'ez-user-' . $hash . '-by-account-key';
179
180
                return $keys;
181
            },
182
            '-by-account-key'
183
        );
184
    }
185
186
    /**
187
     * {@inheritdoc}
188
     */
189 View Code Duplication
    public function update(User $user)
190
    {
191
        $this->logger->logCall(__METHOD__, array('struct' => $user));
192
        $return = $this->persistenceHandler->userHandler()->update($user);
193
194
        // Clear corresponding content cache as update of the User changes it's external data
195
        $this->invalidateCache(['content-fields-' . $user->id, 'user-' . $user->id]);
196
197
        return $return;
198
    }
199
200
    /**
201
     * {@inheritdoc}
202
     */
203 View Code Duplication
    public function updateUserToken(UserTokenUpdateStruct $userTokenUpdateStruct)
204
    {
205
        $this->logger->logCall(__METHOD__, array('struct' => $userTokenUpdateStruct));
206
        $return = $this->persistenceHandler->userHandler()->updateUserToken($userTokenUpdateStruct);
207
208
        // As we 1. don't know original hash, and 2. hash is not guaranteed to be unique, we do it like this for now
209
        $this->invalidateCache(['user-' . $userTokenUpdateStruct->userId . '-account-key']);
210
        $this->deleteCache(['ez-user-' . $userTokenUpdateStruct->hashKey . '-by-account-key']);
211
212
        return $return;
213
    }
214
215
    /**
216
     * {@inheritdoc}
217
     */
218
    public function expireUserToken($hash)
219
    {
220
        $this->logger->logCall(__METHOD__, array('hash' => $hash));
221
        $return = $this->persistenceHandler->userHandler()->expireUserToken($hash);
222
        $this->deleteCache(['ez-user-' . $hash . '-by-account-key']);
223
224
        return $return;
225
    }
226
227
    /**
228
     * {@inheritdoc}
229
     */
230
    public function delete($userId)
231
    {
232
        $this->logger->logCall(__METHOD__, array('user' => $userId));
233
        $return = $this->persistenceHandler->userHandler()->delete($userId);
234
235
        // user id == content id == group id
236
        $this->invalidateCache(['content-fields-' . $userId, 'user-' . $userId]);
237
238
        return $return;
239
    }
240
241
    /**
242
     * {@inheritdoc}
243
     */
244
    public function createRole(RoleCreateStruct $createStruct)
245
    {
246
        $this->logger->logCall(__METHOD__, array('struct' => $createStruct));
247
248
        return $this->persistenceHandler->userHandler()->createRole($createStruct);
249
    }
250
251
    /**
252
     * {@inheritdoc}
253
     */
254
    public function createRoleDraft($roleId)
255
    {
256
        $this->logger->logCall(__METHOD__, array('role' => $roleId));
257
258
        return $this->persistenceHandler->userHandler()->createRoleDraft($roleId);
259
    }
260
261
    /**
262
     * {@inheritdoc}
263
     */
264 View Code Duplication
    public function loadRole($roleId, $status = Role::STATUS_DEFINED)
265
    {
266
        if ($status !== Role::STATUS_DEFINED) {
267
            $this->logger->logCall(__METHOD__, array('role' => $roleId));
268
269
            return $this->persistenceHandler->userHandler()->loadRole($roleId, $status);
270
        }
271
272
        return $this->getCacheValue(
273
            $roleId,
274
            'ez-role-',
275
            function ($roleId) {
276
                return $this->persistenceHandler->userHandler()->loadRole($roleId);
277
            },
278
            $this->getRoleTags,
279
            $this->getRoleKeys
280
        );
281
    }
282
283
    /**
284
     * {@inheritdoc}
285
     */
286 View Code Duplication
    public function loadRoleByIdentifier($identifier, $status = Role::STATUS_DEFINED)
287
    {
288
        if ($status !== Role::STATUS_DEFINED) {
289
            $this->logger->logCall(__METHOD__, array('role' => $identifier));
290
291
            return $this->persistenceHandler->userHandler()->loadRoleByIdentifier($identifier, $status);
292
        }
293
294
        return $this->getCacheValue(
295
            $identifier,
296
            'ez-role-',
297
            function ($identifier) {
298
                return $this->persistenceHandler->userHandler()->loadRoleByIdentifier($identifier);
299
            },
300
            $this->getRoleTags,
301
            $this->getRoleKeys,
302
            '-by-identifier'
303
        );
304
    }
305
306
    /**
307
     * {@inheritdoc}
308
     */
309
    public function loadRoleDraftByRoleId($roleId)
310
    {
311
        $this->logger->logCall(__METHOD__, array('role' => $roleId));
312
313
        return $this->persistenceHandler->userHandler()->loadRoleDraftByRoleId($roleId);
314
    }
315
316
    /**
317
     * {@inheritdoc}
318
     */
319
    public function loadRoles()
320
    {
321
        $this->logger->logCall(__METHOD__);
322
323
        return $this->persistenceHandler->userHandler()->loadRoles();
324
    }
325
326
    /**
327
     * {@inheritdoc}
328
     */
329
    public function loadRoleAssignment($roleAssignmentId)
330
    {
331
        return $this->getCacheValue(
332
            $roleAssignmentId,
333
            'ez-role-assignment-',
334
            function ($roleAssignmentId) {
335
                return $this->persistenceHandler->userHandler()->loadRoleAssignment($roleAssignmentId);
336
            },
337
            $this->getRoleAssignmentTags,
338
            $this->getRoleAssignmentKeys
339
        );
340
    }
341
342
    /**
343
     * {@inheritdoc}
344
     */
345
    public function loadRoleAssignmentsByRoleId($roleId)
346
    {
347
        return $this->getListCacheValue(
348
            "ez-role-assignment-${roleId}-by-role",
349
            function () use ($roleId) {
350
                return $this->persistenceHandler->userHandler()->loadRoleAssignmentsByRoleId($roleId);
351
            },
352
            $this->getRoleAssignmentTags,
353
            $this->getRoleAssignmentKeys,
354
            [
355
                'role-' . $roleId, /* Role update (policies) changes role assignment id */
356
            ],
357
            [$roleId]
358
        );
359
    }
360
361
    /**
362
     * {@inheritdoc}
363
     */
364
    public function loadRoleAssignmentsByGroupId($groupId, $inherit = false)
365
    {
366
        $innerHandler = $this->persistenceHandler;
367
        if ($inherit) {
368
            $key = "ez-role-assignment-${groupId}-by-group-inherited";
369
        } else {
370
            $key = "ez-role-assignment-${groupId}-by-group";
371
        }
372
373
        return $this->getListCacheValue(
374
            $key,
375
            function () use ($groupId, $inherit) {
376
                return $this->persistenceHandler->userHandler()->loadRoleAssignmentsByGroupId($groupId, $inherit);
377
            },
378
            $this->getRoleAssignmentTags,
379
            $this->getRoleAssignmentKeys,
380
            static function () use ($groupId, $innerHandler) {
381
                // To make sure tree operations affecting this can clear the permission cache
382
                $cacheTags = [];
383
                $locations = $innerHandler->locationHandler()->loadLocationsByContent($groupId);
384
                foreach ($locations as $location) {
385
                    foreach (explode('/', trim($location->pathString, '/')) as $pathId) {
386
                        $cacheTags[] = 'location-path-' . $pathId;
387
                    }
388
                }
389
390
                return $cacheTags;
391
            },
392
            [$groupId, $inherit]
393
        );
394
    }
395
396
    /**
397
     * {@inheritdoc}
398
     */
399 View Code Duplication
    public function updateRole(RoleUpdateStruct $struct)
400
    {
401
        $this->logger->logCall(__METHOD__, array('struct' => $struct));
402
        $this->persistenceHandler->userHandler()->updateRole($struct);
403
404
        $this->invalidateCache(['role-' . $struct->id]);
405
    }
406
407
    /**
408
     * {@inheritdoc}
409
     */
410 View Code Duplication
    public function deleteRole($roleId, $status = Role::STATUS_DEFINED)
411
    {
412
        $this->logger->logCall(__METHOD__, array('role' => $roleId));
413
        $return = $this->persistenceHandler->userHandler()->deleteRole($roleId, $status);
414
415
        if ($status === Role::STATUS_DEFINED) {
416
            $this->invalidateCache(['role-' . $roleId, 'role-assignment-role-list-' . $roleId]);
417
        }
418
419
        return $return;
420
    }
421
422
    /**
423
     * {@inheritdoc}
424
     */
425
    public function publishRoleDraft($roleDraftId)
426
    {
427
        $this->logger->logCall(__METHOD__, array('role' => $roleDraftId));
428
        $userHandler = $this->persistenceHandler->userHandler();
429
        $roleDraft = $userHandler->loadRole($roleDraftId, Role::STATUS_DRAFT);
430
        $return = $userHandler->publishRoleDraft($roleDraftId);
431
432
        // If there was a original role for the draft, then we clean cache for it
433
        if ($roleDraft->originalId > -1) {
434
            $this->invalidateCache(['role-' . $roleDraft->originalId]);
435
        }
436
437
        return $return;
438
    }
439
440
    /**
441
     * {@inheritdoc}
442
     */
443
    public function addPolicyByRoleDraft($roleId, Policy $policy)
444
    {
445
        $this->logger->logCall(__METHOD__, array('role' => $roleId, 'struct' => $policy));
446
447
        return $this->persistenceHandler->userHandler()->addPolicyByRoleDraft($roleId, $policy);
448
    }
449
450
    /**
451
     * {@inheritdoc}
452
     */
453
    public function addPolicy($roleId, Policy $policy)
454
    {
455
        $this->logger->logCall(__METHOD__, array('role' => $roleId, 'struct' => $policy));
456
        $return = $this->persistenceHandler->userHandler()->addPolicy($roleId, $policy);
457
458
        $this->invalidateCache(['role-' . $roleId]);
459
460
        return $return;
461
    }
462
463
    /**
464
     * {@inheritdoc}
465
     */
466 View Code Duplication
    public function updatePolicy(Policy $policy)
467
    {
468
        $this->logger->logCall(__METHOD__, array('struct' => $policy));
469
        $return = $this->persistenceHandler->userHandler()->updatePolicy($policy);
470
471
        $this->invalidateCache(['policy-' . $policy->id, 'role-' . $policy->roleId]);
472
473
        return $return;
474
    }
475
476
    /**
477
     * {@inheritdoc}
478
     */
479 View Code Duplication
    public function deletePolicy($policyId, $roleId)
480
    {
481
        $this->logger->logCall(__METHOD__, array('policy' => $policyId));
482
        $this->persistenceHandler->userHandler()->deletePolicy($policyId, $roleId);
483
484
        $this->invalidateCache(['policy-' . $policyId, 'role-' . $roleId]);
485
    }
486
487
    /**
488
     * {@inheritdoc}
489
     */
490
    public function loadPoliciesByUserId($userId)
491
    {
492
        $this->logger->logCall(__METHOD__, array('user' => $userId));
493
494
        return $this->persistenceHandler->userHandler()->loadPoliciesByUserId($userId);
0 ignored issues
show
Deprecated Code introduced by
The method eZ\Publish\SPI\Persisten...:loadPoliciesByUserId() has been deprecated with message: Since 6.8, not currently in use as permission system needs to know about role assignment limitations.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
495
    }
496
497
    /**
498
     * {@inheritdoc}
499
     */
500
    public function assignRole($contentId, $roleId, array $limitation = null)
501
    {
502
        $this->logger->logCall(__METHOD__, array('group' => $contentId, 'role' => $roleId, 'limitation' => $limitation));
503
        $return = $this->persistenceHandler->userHandler()->assignRole($contentId, $roleId, $limitation);
504
505
        $tags = ['role-assignment-group-list-' . $contentId, 'role-assignment-role-list-' . $roleId];
506
        $locations = $this->persistenceHandler->locationHandler()->loadLocationsByContent($contentId);
507
        foreach ($locations as $location) {
508
            $tags[] = 'location-path-' . $location->id;
509
        }
510
511
        $this->invalidateCache($tags);
512
513
        return $return;
514
    }
515
516
    /**
517
     * {@inheritdoc}
518
     */
519 View Code Duplication
    public function unassignRole($contentId, $roleId)
520
    {
521
        $this->logger->logCall(__METHOD__, array('group' => $contentId, 'role' => $roleId));
522
        $return = $this->persistenceHandler->userHandler()->unassignRole($contentId, $roleId);
523
524
        $this->invalidateCache(['role-assignment-group-list-' . $contentId, 'role-assignment-role-list-' . $roleId]);
525
526
        return $return;
527
    }
528
529
    /**
530
     * {@inheritdoc}
531
     */
532 View Code Duplication
    public function removeRoleAssignment($roleAssignmentId)
533
    {
534
        $this->logger->logCall(__METHOD__, array('assignment' => $roleAssignmentId));
535
        $return = $this->persistenceHandler->userHandler()->removeRoleAssignment($roleAssignmentId);
536
537
        $this->invalidateCache(['role-assignment-' . $roleAssignmentId]);
538
539
        return $return;
540
    }
541
}
542