Completed
Push — inmemory-pool-decoration ( 282551...25eaa5 )
by André
66:29 queued 45:47
created

UserHandler::init()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 34

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 34
rs 9.376
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 retrival.
45
     */
46
    public function init(): void
47
    {
48
        $this->getUserTags = static function (User $user) {
49
            return ['content-' . $user->id, 'user-' . $user->id];
50
        };
51
        $this->getUserKeys = static function (User $user) {
52
            return [
53
                'ez-user-' . $user->id,
54
                'ez-user-' . \str_replace('@', '§', $user->login) . '-by-login',
55
                //'ez-user-' . $hash . '-by-account-key',
56
            ];
57
        };
58
        $this->getRoleTags = static function (Role $role) {
59
            return ['role-' . $role->id];
60
        };
61
        $this->getRoleKeys = static function (Role $role) {
62
            return [
63
                'ez-role-' . $role->id,
64
                'ez-role-' . $role->identifier . '-by-identifier',
65
            ];
66
        };
67
        $this->getRoleAssignmentTags = static function (RoleAssignment $roleAssignment) {
68
            return [
69
                'role-assignment-' . $roleAssignment->id,
70
                'role-assignment-group-list-' . $roleAssignment->contentId,
71
                'role-assignment-role-list-' . $roleAssignment->roleId,
72
            ];
73
        };
74
        $this->getRoleAssignmentKeys = static function (RoleAssignment $roleAssignment) {
75
            return [
76
                'ez-role-assignment-' . $roleAssignment->id,
77
            ];
78
        };
79
    }
80
81
    /**
82
     * {@inheritdoc}
83
     */
84
    public function create(User $user)
85
    {
86
        $this->logger->logCall(__METHOD__, array('struct' => $user));
87
        $return = $this->persistenceHandler->userHandler()->create($user);
88
89
        // Clear corresponding content cache as creation of the User changes it's external data
90
        $this->cache->invalidateTags(['content-fields-' . $user->id]);
91
        $this->cache->deleteItems([
92
            'ez-user-' . $user->id,
93
            'ez-user-' . str_replace('@', '§', $user->login) . '-by-login',
94
            'ez-user-' . str_replace('@', '§', $user->email) . '-by-email',
95
        ]);
96
97
        return $return;
98
    }
99
100
    /**
101
     * {@inheritdoc}
102
     */
103
    public function load($userId)
104
    {
105
        return $this->getCacheValue(
106
            $userId,
107
            'ez-user-',
108
            function ($userId) {
109
                return $this->persistenceHandler->userHandler()->load($userId);
110
            },
111
            $this->getUserTags,
112
            $this->getUserKeys
113
        );
114
    }
115
116
    /**
117
     * {@inheritdoc}
118
     */
119 View Code Duplication
    public function loadByLogin($login)
120
    {
121
        return $this->getCacheValue(
122
            str_replace('@', '§', $login),
123
            'ez-user-',
124
            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...
125
                return $this->persistenceHandler->userHandler()->loadByLogin($login);
126
            },
127
            $this->getUserTags,
128
            $this->getUserKeys,
129
            '-by-login'
130
        );
131
    }
132
133
    /**
134
     * {@inheritdoc}
135
     */
136 View Code Duplication
    public function loadByEmail($email)
137
    {
138
        // As load by email can return several items we threat it like a list here.
139
        return $this->getListCacheValue(
140
            'ez-user-' . str_replace('@', '§', $email) . '-by-email',
141
            function () use ($email) {
142
                return $this->persistenceHandler->userHandler()->loadByEmail($email);
143
            },
144
            $this->getUserTags,
145
            $this->getUserKeys
146
        );
147
    }
148
149
    /**
150
     * {@inheritdoc}
151
     */
152
    public function loadUserByToken($hash)
153
    {
154
        $getUserKeysFn = $this->getUserKeys;
155
        $getUserTagsFn = $this->getUserTags;
156
157
        return $this->getCacheValue(
158
            $hash,
159
            'ez-user-',
160
            function ($hash) {
161
                return $this->persistenceHandler->userHandler()->loadUserByToken($hash);
162
            },
163
            static function (User $user) use ($getUserTagsFn) {
164
                $tags = $getUserTagsFn($user);
165
                // See updateUserToken()
166
                $tags[] = 'user-' . $user->id . '-account-key';
167
168
                return $tags;
169
            },
170
            static function (User $user) use ($hash, $getUserKeysFn) {
171
                $keys = $getUserKeysFn($user);
172
                $keys[] = 'ez-user-' . $hash . '-by-account-key';
173
174
                return $keys;
175
            },
176
            '-by-account-key'
177
        );
178
    }
179
180
    /**
181
     * {@inheritdoc}
182
     */
183
    public function update(User $user)
184
    {
185
        $this->logger->logCall(__METHOD__, array('struct' => $user));
186
        $return = $this->persistenceHandler->userHandler()->update($user);
187
188
        // Clear corresponding content cache as update of the User changes it's external data
189
        $this->cache->invalidateTags(['content-fields-' . $user->id, 'user-' . $user->id]);
190
191
        return $return;
192
    }
193
194
    /**
195
     * {@inheritdoc}
196
     */
197 View Code Duplication
    public function updateUserToken(UserTokenUpdateStruct $userTokenUpdateStruct)
198
    {
199
        $this->logger->logCall(__METHOD__, array('struct' => $userTokenUpdateStruct));
200
        $return = $this->persistenceHandler->userHandler()->updateUserToken($userTokenUpdateStruct);
201
202
        // As we 1. don't know original hash, and 2. hash is not guaranteed to be unique, we do it like this for now
203
        $this->cache->invalidateTags(['user-' . $userTokenUpdateStruct->userId . '-account-key']);
204
        $this->cache->deleteItems(['ez-user-' . $userTokenUpdateStruct->hashKey . '-by-account-key']);
205
206
        return $return;
207
    }
208
209
    /**
210
     * {@inheritdoc}
211
     */
212 View Code Duplication
    public function expireUserToken($hash)
213
    {
214
        $this->logger->logCall(__METHOD__, array('hash' => $hash));
215
        $return = $this->persistenceHandler->userHandler()->expireUserToken($hash);
216
        $this->cache->deleteItems(['ez-user-' . $hash . '-by-account-key']);
217
218
        return $return;
219
    }
220
221
    /**
222
     * {@inheritdoc}
223
     */
224 View Code Duplication
    public function delete($userId)
225
    {
226
        $this->logger->logCall(__METHOD__, array('user' => $userId));
227
        $return = $this->persistenceHandler->userHandler()->delete($userId);
228
229
        // user id == content id == group id
230
        $this->cache->invalidateTags(['content-fields-' . $userId, 'user-' . $userId]);
231
232
        return $return;
233
    }
234
235
    /**
236
     * {@inheritdoc}
237
     */
238
    public function createRole(RoleCreateStruct $createStruct)
239
    {
240
        $this->logger->logCall(__METHOD__, array('struct' => $createStruct));
241
242
        return $this->persistenceHandler->userHandler()->createRole($createStruct);
243
    }
244
245
    /**
246
     * {@inheritdoc}
247
     */
248
    public function createRoleDraft($roleId)
249
    {
250
        $this->logger->logCall(__METHOD__, array('role' => $roleId));
251
252
        return $this->persistenceHandler->userHandler()->createRoleDraft($roleId);
253
    }
254
255
    /**
256
     * {@inheritdoc}
257
     */
258 View Code Duplication
    public function loadRole($roleId, $status = Role::STATUS_DEFINED)
259
    {
260
        if ($status !== Role::STATUS_DEFINED) {
261
            $this->logger->logCall(__METHOD__, array('role' => $roleId));
262
263
            return $this->persistenceHandler->userHandler()->loadRole($roleId, $status);
264
        }
265
266
        return $this->getCacheValue(
267
            $roleId,
268
            'ez-role-',
269
            function ($roleId) {
270
                return $this->persistenceHandler->userHandler()->loadRole($roleId);
271
            },
272
            $this->getRoleTags,
273
            $this->getRoleKeys
274
        );
275
    }
276
277
    /**
278
     * {@inheritdoc}
279
     */
280 View Code Duplication
    public function loadRoleByIdentifier($identifier, $status = Role::STATUS_DEFINED)
281
    {
282
        if ($status !== Role::STATUS_DEFINED) {
283
            $this->logger->logCall(__METHOD__, array('role' => $identifier));
284
285
            return $this->persistenceHandler->userHandler()->loadRoleByIdentifier($identifier, $status);
286
        }
287
288
        return $this->getCacheValue(
289
            $identifier,
290
            'ez-role-',
291
            function ($identifier) {
292
                return $this->persistenceHandler->userHandler()->loadRoleByIdentifier($identifier);
293
            },
294
            $this->getRoleTags,
295
            $this->getRoleKeys,
296
            '-by-identifier'
297
        );
298
    }
299
300
    /**
301
     * {@inheritdoc}
302
     */
303
    public function loadRoleDraftByRoleId($roleId)
304
    {
305
        $this->logger->logCall(__METHOD__, array('role' => $roleId));
306
307
        return $this->persistenceHandler->userHandler()->loadRoleDraftByRoleId($roleId);
308
    }
309
310
    /**
311
     * {@inheritdoc}
312
     */
313
    public function loadRoles()
314
    {
315
        $this->logger->logCall(__METHOD__);
316
317
        return $this->persistenceHandler->userHandler()->loadRoles();
318
    }
319
320
    /**
321
     * {@inheritdoc}
322
     */
323
    public function loadRoleAssignment($roleAssignmentId)
324
    {
325
        return $this->getCacheValue(
326
            $roleAssignmentId,
327
            'ez-role-assignment-',
328
            function ($roleAssignmentId) {
329
                return $this->persistenceHandler->userHandler()->loadRoleAssignment($roleAssignmentId);
330
            },
331
            $this->getRoleAssignmentTags,
332
            $this->getRoleAssignmentKeys
333
        );
334
    }
335
336
    /**
337
     * {@inheritdoc}
338
     */
339
    public function loadRoleAssignmentsByRoleId($roleId)
340
    {
341
        return $this->getListCacheValue(
342
            "ez-role-assignment-${roleId}-by-role",
343
            function () use ($roleId) {
344
                return $this->persistenceHandler->userHandler()->loadRoleAssignmentsByRoleId($roleId);
345
            },
346
            $this->getRoleAssignmentTags,
347
            $this->getRoleAssignmentKeys,
348
            /* Role update (policies) changes role assignment id, also need list tag in case of empty result */
349
            static function () use ($roleId) {
350
                return ['role-assignment-role-list-' . $roleId, 'role-' . $roleId];
351
            },
352
            [$roleId]
353
        );
354
    }
355
356
    /**
357
     * {@inheritdoc}
358
     */
359
    public function loadRoleAssignmentsByGroupId($groupId, $inherit = false)
360
    {
361
        $innerHandler = $this->persistenceHandler;
362
        if ($inherit) {
363
            $key = "ez-role-assignment-${groupId}-by-group-inherited";
364
        } else {
365
            $key = "ez-role-assignment-${groupId}-by-group";
366
        }
367
368
        return $this->getListCacheValue(
369
            $key,
370
            function () use ($groupId, $inherit) {
371
                return $this->persistenceHandler->userHandler()->loadRoleAssignmentsByGroupId($groupId, $inherit);
372
            },
373
            $this->getRoleAssignmentTags,
374
            $this->getRoleAssignmentKeys,
375
            static function () use ($groupId, $innerHandler) {
376
                // Tag needed for empty results, if not empty will alse be added by getRoleAssignmentTags().
377
                $cacheTags = ['role-assignment-group-list-' . $groupId];
378
                // To make sure tree operations affecting this can clear the permission cache
379
                $locations = $innerHandler->locationHandler()->loadLocationsByContent($groupId);
380
                foreach ($locations as $location) {
381
                    foreach (explode('/', trim($location->pathString, '/')) as $pathId) {
382
                        $cacheTags[] = 'location-path-' . $pathId;
383
                    }
384
                }
385
386
                return $cacheTags;
387
            },
388
            [$groupId, $inherit]
389
        );
390
    }
391
392
    /**
393
     * {@inheritdoc}
394
     */
395 View Code Duplication
    public function updateRole(RoleUpdateStruct $struct)
396
    {
397
        $this->logger->logCall(__METHOD__, array('struct' => $struct));
398
        $this->persistenceHandler->userHandler()->updateRole($struct);
399
400
        $this->cache->invalidateTags(['role-' . $struct->id]);
401
    }
402
403
    /**
404
     * {@inheritdoc}
405
     */
406 View Code Duplication
    public function deleteRole($roleId, $status = Role::STATUS_DEFINED)
407
    {
408
        $this->logger->logCall(__METHOD__, array('role' => $roleId));
409
        $return = $this->persistenceHandler->userHandler()->deleteRole($roleId, $status);
410
411
        if ($status === Role::STATUS_DEFINED) {
412
            $this->cache->invalidateTags(['role-' . $roleId, 'role-assignment-role-list-' . $roleId]);
413
        }
414
415
        return $return;
416
    }
417
418
    /**
419
     * {@inheritdoc}
420
     */
421
    public function publishRoleDraft($roleDraftId)
422
    {
423
        $this->logger->logCall(__METHOD__, array('role' => $roleDraftId));
424
        $userHandler = $this->persistenceHandler->userHandler();
425
        $roleDraft = $userHandler->loadRole($roleDraftId, Role::STATUS_DRAFT);
426
        $return = $userHandler->publishRoleDraft($roleDraftId);
427
428
        // If there was a original role for the draft, then we clean cache for it
429
        if ($roleDraft->originalId > -1) {
430
            $this->cache->invalidateTags(['role-' . $roleDraft->originalId]);
431
        }
432
433
        return $return;
434
    }
435
436
    /**
437
     * {@inheritdoc}
438
     */
439
    public function addPolicyByRoleDraft($roleId, Policy $policy)
440
    {
441
        $this->logger->logCall(__METHOD__, array('role' => $roleId, 'struct' => $policy));
442
443
        return $this->persistenceHandler->userHandler()->addPolicyByRoleDraft($roleId, $policy);
444
    }
445
446
    /**
447
     * {@inheritdoc}
448
     */
449 View Code Duplication
    public function addPolicy($roleId, Policy $policy)
450
    {
451
        $this->logger->logCall(__METHOD__, array('role' => $roleId, 'struct' => $policy));
452
        $return = $this->persistenceHandler->userHandler()->addPolicy($roleId, $policy);
453
454
        $this->cache->invalidateTags(['role-' . $roleId]);
455
456
        return $return;
457
    }
458
459
    /**
460
     * {@inheritdoc}
461
     */
462
    public function updatePolicy(Policy $policy)
463
    {
464
        $this->logger->logCall(__METHOD__, array('struct' => $policy));
465
        $return = $this->persistenceHandler->userHandler()->updatePolicy($policy);
466
467
        $this->cache->invalidateTags(['policy-' . $policy->id, 'role-' . $policy->roleId]);
468
469
        return $return;
470
    }
471
472
    /**
473
     * {@inheritdoc}
474
     */
475 View Code Duplication
    public function deletePolicy($policyId, $roleId)
476
    {
477
        $this->logger->logCall(__METHOD__, array('policy' => $policyId));
478
        $this->persistenceHandler->userHandler()->deletePolicy($policyId, $roleId);
479
480
        $this->cache->invalidateTags(['policy-' . $policyId, 'role-' . $roleId]);
481
    }
482
483
    /**
484
     * {@inheritdoc}
485
     */
486
    public function loadPoliciesByUserId($userId)
487
    {
488
        $this->logger->logCall(__METHOD__, array('user' => $userId));
489
490
        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...
491
    }
492
493
    /**
494
     * {@inheritdoc}
495
     */
496
    public function assignRole($contentId, $roleId, array $limitation = null)
497
    {
498
        $this->logger->logCall(__METHOD__, array('group' => $contentId, 'role' => $roleId, 'limitation' => $limitation));
499
        $return = $this->persistenceHandler->userHandler()->assignRole($contentId, $roleId, $limitation);
500
501
        $tags = ['role-assignment-group-list-' . $contentId, 'role-assignment-role-list-' . $roleId];
502
        $locations = $this->persistenceHandler->locationHandler()->loadLocationsByContent($contentId);
503
        foreach ($locations as $location) {
504
            $tags[] = 'location-path-' . $location->id;
505
        }
506
507
        $this->cache->invalidateTags($tags);
508
509
        return $return;
510
    }
511
512
    /**
513
     * {@inheritdoc}
514
     */
515
    public function unassignRole($contentId, $roleId)
516
    {
517
        $this->logger->logCall(__METHOD__, array('group' => $contentId, 'role' => $roleId));
518
        $return = $this->persistenceHandler->userHandler()->unassignRole($contentId, $roleId);
519
520
        $this->cache->invalidateTags(['role-assignment-group-list-' . $contentId, 'role-assignment-role-list-' . $roleId]);
521
522
        return $return;
523
    }
524
525
    /**
526
     * {@inheritdoc}
527
     */
528 View Code Duplication
    public function removeRoleAssignment($roleAssignmentId)
529
    {
530
        $this->logger->logCall(__METHOD__, array('assignment' => $roleAssignmentId));
531
        $return = $this->persistenceHandler->userHandler()->removeRoleAssignment($roleAssignmentId);
532
533
        $this->cache->invalidateTags(['role-assignment-' . $roleAssignmentId]);
534
535
        return $return;
536
    }
537
}
538