Completed
Push — inmemory-pool-decoration ( 469074...282551 )
by André
25:04
created

UserHandler::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 36

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 1
dl 0
loc 36
rs 9.344
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\SPI\Persistence\User\UserTokenUpdateStruct;
12
use eZ\Publish\SPI\Persistence\User\Handler as UserHandlerInterface;
13
use eZ\Publish\SPI\Persistence\User;
14
use eZ\Publish\SPI\Persistence\User\Role;
15
use eZ\Publish\SPI\Persistence\User\RoleAssignment;
16
use eZ\Publish\SPI\Persistence\User\RoleCreateStruct;
17
use eZ\Publish\SPI\Persistence\User\RoleUpdateStruct;
18
use eZ\Publish\SPI\Persistence\User\Policy;
19
20
/**
21
 * Cache handler for user module.
22
 */
23
class UserHandler extends AbstractInMemoryHandler implements UserHandlerInterface
24
{
25
    /** @var callable */
26
    private $getUserTags;
27
28
    /** @var callable */
29
    private $getUserKeys;
30
31
    /** @var callable */
32
    private $getRoleTags;
33
34
    /** @var callable */
35
    private $getRoleKeys;
36
37
    /** @var callable */
38
    private $getRoleAssignmentTags;
39
40
    /** @var callable */
41
    private $getRoleAssignmentKeys;
42
43
    /**
44
     * Set callback functions for use in cache retrieval.
45
     *
46
     * {@inheritdoc}
47
     */
48
    public function __construct(...$params)
49
    {
50
        parent::__construct(...$params);
0 ignored issues
show
Bug introduced by
The call to AbstractInMemoryHandler::__construct() misses some required arguments starting with $cache.
Loading history...
51
52
        $this->getUserTags = static function (User $user) {
53
            return ['content-' . $user->id, 'user-' . $user->id];
54
        };
55
        $this->getUserKeys = static function (User $user) {
56
            return [
57
                'ez-user-' . $user->id,
58
                'ez-user-' . \str_replace('@', '§', $user->login) . '-by-login',
59
                //'ez-user-' . $hash . '-by-account-key',
60
            ];
61
        };
62
        $this->getRoleTags = static function (Role $role) {
63
            return ['role-' . $role->id];
64
        };
65
        $this->getRoleKeys = static function (Role $role) {
66
            return [
67
                'ez-role-' . $role->id,
68
                'ez-role-' . $role->identifier . '-by-identifier',
69
            ];
70
        };
71
        $this->getRoleAssignmentTags = static function (RoleAssignment $roleAssignment) {
72
            return [
73
                'role-assignment-' . $roleAssignment->id,
74
                'role-assignment-group-list-' . $roleAssignment->contentId,
75
                'role-assignment-role-list-' . $roleAssignment->roleId,
76
            ];
77
        };
78
        $this->getRoleAssignmentKeys = static function (RoleAssignment $roleAssignment) {
79
            return [
80
                'ez-role-assignment-' . $roleAssignment->id,
81
            ];
82
        };
83
    }
84
85
    /**
86
     * {@inheritdoc}
87
     */
88
    public function create(User $user)
89
    {
90
        $this->logger->logCall(__METHOD__, array('struct' => $user));
91
        $return = $this->persistenceHandler->userHandler()->create($user);
92
93
        // Clear corresponding content cache as creation of the User changes it's external data
94
        $this->cache->invalidateTags(['content-fields-' . $user->id]);
95
        $this->cache->deleteItems([
96
            'ez-user-' . $user->id,
97
            'ez-user-' . str_replace('@', '§', $user->login) . '-by-login',
98
            'ez-user-' . str_replace('@', '§', $user->email) . '-by-email',
99
        ]);
100
101
        return $return;
102
    }
103
104
    /**
105
     * {@inheritdoc}
106
     */
107
    public function load($userId)
108
    {
109
        return $this->getCacheValue(
110
            $userId,
111
            'ez-user-',
112
            function ($userId) {
113
                return $this->persistenceHandler->userHandler()->load($userId);
114
            },
115
            $this->getUserTags,
116
            $this->getUserKeys
117
        );
118
    }
119
120
    /**
121
     * {@inheritdoc}
122
     */
123 View Code Duplication
    public function loadByLogin($login)
124
    {
125
        return $this->getCacheValue(
126
            str_replace('@', '§', $login),
127
            'ez-user-',
128
            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...
129
                return $this->persistenceHandler->userHandler()->loadByLogin($login);
130
            },
131
            $this->getUserTags,
132
            $this->getUserKeys,
133
            '-by-login'
134
        );
135
    }
136
137
    /**
138
     * {@inheritdoc}
139
     */
140 View Code Duplication
    public function loadByEmail($email)
141
    {
142
        // As load by email can return several items we threat it like a list here.
143
        return $this->getListCacheValue(
144
            'ez-user-' . str_replace('@', '§', $email) . '-by-email',
145
            function () use ($email) {
146
                return $this->persistenceHandler->userHandler()->loadByEmail($email);
147
            },
148
            $this->getUserTags,
149
            $this->getUserKeys
150
        );
151
    }
152
153
    /**
154
     * {@inheritdoc}
155
     */
156
    public function loadUserByToken($hash)
157
    {
158
        $getUserKeysFn = $this->getUserKeys;
159
        $getUserTagsFn = $this->getUserTags;
160
161
        return $this->getCacheValue(
162
            $hash,
163
            'ez-user-',
164
            function ($hash) {
165
                return $this->persistenceHandler->userHandler()->loadUserByToken($hash);
166
            },
167
            static function (User $user) use ($getUserTagsFn) {
168
                $tags = $getUserTagsFn($user);
169
                // See updateUserToken()
170
                $tags[] = 'user-' . $user->id . '-account-key';
171
172
                return $tags;
173
            },
174
            static function (User $user) use ($hash, $getUserKeysFn) {
175
                $keys = $getUserKeysFn($user);
176
                $keys[] = 'ez-user-' . $hash . '-by-account-key';
177
178
                return $keys;
179
            },
180
            '-by-account-key'
181
        );
182
    }
183
184
    /**
185
     * {@inheritdoc}
186
     */
187
    public function update(User $user)
188
    {
189
        $this->logger->logCall(__METHOD__, array('struct' => $user));
190
        $return = $this->persistenceHandler->userHandler()->update($user);
191
192
        // Clear corresponding content cache as update of the User changes it's external data
193
        $this->cache->invalidateTags(['content-fields-' . $user->id, 'user-' . $user->id]);
194
195
        return $return;
196
    }
197
198
    /**
199
     * {@inheritdoc}
200
     */
201 View Code Duplication
    public function updateUserToken(UserTokenUpdateStruct $userTokenUpdateStruct)
202
    {
203
        $this->logger->logCall(__METHOD__, array('struct' => $userTokenUpdateStruct));
204
        $return = $this->persistenceHandler->userHandler()->updateUserToken($userTokenUpdateStruct);
205
206
        // As we 1. don't know original hash, and 2. hash is not guaranteed to be unique, we do it like this for now
207
        $this->cache->invalidateTags(['user-' . $userTokenUpdateStruct->userId . '-account-key']);
208
        $this->cache->deleteItems(['ez-user-' . $userTokenUpdateStruct->hashKey . '-by-account-key']);
209
210
        return $return;
211
    }
212
213
    /**
214
     * {@inheritdoc}
215
     */
216 View Code Duplication
    public function expireUserToken($hash)
217
    {
218
        $this->logger->logCall(__METHOD__, array('hash' => $hash));
219
        $return = $this->persistenceHandler->userHandler()->expireUserToken($hash);
220
        $this->cache->deleteItems(['ez-user-' . $hash . '-by-account-key']);
221
222
        return $return;
223
    }
224
225
    /**
226
     * {@inheritdoc}
227
     */
228 View Code Duplication
    public function delete($userId)
229
    {
230
        $this->logger->logCall(__METHOD__, array('user' => $userId));
231
        $return = $this->persistenceHandler->userHandler()->delete($userId);
232
233
        // user id == content id == group id
234
        $this->cache->invalidateTags(['content-fields-' . $userId, 'user-' . $userId]);
235
236
        return $return;
237
    }
238
239
    /**
240
     * {@inheritdoc}
241
     */
242
    public function createRole(RoleCreateStruct $createStruct)
243
    {
244
        $this->logger->logCall(__METHOD__, array('struct' => $createStruct));
245
246
        return $this->persistenceHandler->userHandler()->createRole($createStruct);
247
    }
248
249
    /**
250
     * {@inheritdoc}
251
     */
252
    public function createRoleDraft($roleId)
253
    {
254
        $this->logger->logCall(__METHOD__, array('role' => $roleId));
255
256
        return $this->persistenceHandler->userHandler()->createRoleDraft($roleId);
257
    }
258
259
    /**
260
     * {@inheritdoc}
261
     */
262 View Code Duplication
    public function loadRole($roleId, $status = Role::STATUS_DEFINED)
263
    {
264
        if ($status !== Role::STATUS_DEFINED) {
265
            $this->logger->logCall(__METHOD__, array('role' => $roleId));
266
267
            return $this->persistenceHandler->userHandler()->loadRole($roleId, $status);
268
        }
269
270
        return $this->getCacheValue(
271
            $roleId,
272
            'ez-role-',
273
            function ($roleId) {
274
                return $this->persistenceHandler->userHandler()->loadRole($roleId);
275
            },
276
            $this->getRoleTags,
277
            $this->getRoleKeys
278
        );
279
    }
280
281
    /**
282
     * {@inheritdoc}
283
     */
284 View Code Duplication
    public function loadRoleByIdentifier($identifier, $status = Role::STATUS_DEFINED)
285
    {
286
        if ($status !== Role::STATUS_DEFINED) {
287
            $this->logger->logCall(__METHOD__, array('role' => $identifier));
288
289
            return $this->persistenceHandler->userHandler()->loadRoleByIdentifier($identifier, $status);
290
        }
291
292
        return $this->getCacheValue(
293
            $identifier,
294
            'ez-role-',
295
            function ($identifier) {
296
                return $this->persistenceHandler->userHandler()->loadRoleByIdentifier($identifier);
297
            },
298
            $this->getRoleTags,
299
            $this->getRoleKeys,
300
            '-by-identifier'
301
        );
302
    }
303
304
    /**
305
     * {@inheritdoc}
306
     */
307
    public function loadRoleDraftByRoleId($roleId)
308
    {
309
        $this->logger->logCall(__METHOD__, array('role' => $roleId));
310
311
        return $this->persistenceHandler->userHandler()->loadRoleDraftByRoleId($roleId);
312
    }
313
314
    /**
315
     * {@inheritdoc}
316
     */
317
    public function loadRoles()
318
    {
319
        $this->logger->logCall(__METHOD__);
320
321
        return $this->persistenceHandler->userHandler()->loadRoles();
322
    }
323
324
    /**
325
     * {@inheritdoc}
326
     */
327
    public function loadRoleAssignment($roleAssignmentId)
328
    {
329
        return $this->getCacheValue(
330
            $roleAssignmentId,
331
            'ez-role-assignment-',
332
            function ($roleAssignmentId) {
333
                return $this->persistenceHandler->userHandler()->loadRoleAssignment($roleAssignmentId);
334
            },
335
            $this->getRoleAssignmentTags,
336
            $this->getRoleAssignmentKeys
337
        );
338
    }
339
340
    /**
341
     * {@inheritdoc}
342
     */
343
    public function loadRoleAssignmentsByRoleId($roleId)
344
    {
345
        return $this->getListCacheValue(
346
            "ez-role-assignment-${roleId}-by-role",
347
            function () use ($roleId) {
348
                return $this->persistenceHandler->userHandler()->loadRoleAssignmentsByRoleId($roleId);
349
            },
350
            $this->getRoleAssignmentTags,
351
            $this->getRoleAssignmentKeys,
352
            /* Role update (policies) changes role assignment id, also need list tag in case of empty result */
353
            static function () use ($roleId) {
354
                return ['role-assignment-role-list-' . $roleId, 'role-' . $roleId];
355
            },
356
            [$roleId]
357
        );
358
    }
359
360
    /**
361
     * {@inheritdoc}
362
     */
363
    public function loadRoleAssignmentsByGroupId($groupId, $inherit = false)
364
    {
365
        $innerHandler = $this->persistenceHandler;
366
        if ($inherit) {
367
            $key = "ez-role-assignment-${groupId}-by-group-inherited";
368
        } else {
369
            $key = "ez-role-assignment-${groupId}-by-group";
370
        }
371
372
        return $this->getListCacheValue(
373
            $key,
374
            function () use ($groupId, $inherit) {
375
                return $this->persistenceHandler->userHandler()->loadRoleAssignmentsByGroupId($groupId, $inherit);
376
            },
377
            $this->getRoleAssignmentTags,
378
            $this->getRoleAssignmentKeys,
379
            static function () use ($groupId, $innerHandler) {
380
                // Tag needed for empty results, if not empty will alse be added by getRoleAssignmentTags().
381
                $cacheTags = ['role-assignment-group-list-' . $groupId];
382
                // To make sure tree operations affecting this can clear the permission cache
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->cache->invalidateTags(['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->cache->invalidateTags(['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->cache->invalidateTags(['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 View Code Duplication
    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->cache->invalidateTags(['role-' . $roleId]);
459
460
        return $return;
461
    }
462
463
    /**
464
     * {@inheritdoc}
465
     */
466
    public function updatePolicy(Policy $policy)
467
    {
468
        $this->logger->logCall(__METHOD__, array('struct' => $policy));
469
        $return = $this->persistenceHandler->userHandler()->updatePolicy($policy);
470
471
        $this->cache->invalidateTags(['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->cache->invalidateTags(['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->cache->invalidateTags($tags);
512
513
        return $return;
514
    }
515
516
    /**
517
     * {@inheritdoc}
518
     */
519
    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->cache->invalidateTags(['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->cache->invalidateTags(['role-assignment-' . $roleAssignmentId]);
538
539
        return $return;
540
    }
541
}
542