diff --git a/src/bundle/Core/Resources/config/services.yml b/src/bundle/Core/Resources/config/services.yml index 166b1940cc..3c5fbe3c8c 100644 --- a/src/bundle/Core/Resources/config/services.yml +++ b/src/bundle/Core/Resources/config/services.yml @@ -390,3 +390,9 @@ services: decoration_priority: 500 arguments: $inner: '@.inner' + + Ibexa\Core\Persistence\Cache\EventSubscriber\RoleAssignmentCacheInvalidationListener: + autowire: true + autoconfigure: true + arguments: + $cache: '@ibexa.cache_pool' diff --git a/src/lib/Persistence/Cache/EventSubscriber/RoleAssignmentCacheInvalidationListener.php b/src/lib/Persistence/Cache/EventSubscriber/RoleAssignmentCacheInvalidationListener.php new file mode 100644 index 0000000000..ce30ea407a --- /dev/null +++ b/src/lib/Persistence/Cache/EventSubscriber/RoleAssignmentCacheInvalidationListener.php @@ -0,0 +1,105 @@ +cache = $cache; + $this->identifierGenerator = $identifierGenerator; + $this->roleService = $roleService; + $this->userService = $userService; + } + + public static function getSubscribedEvents(): array + { + return [ + TrashEvent::class => 'onTrashContent', + RecoverEvent::class => 'onRecoverContent', + ]; + } + + public function onRecoverContent(RecoverEvent $event): void + { + $this->clearCache($event->getTrashItem()); + } + + public function onTrashContent(TrashEvent $event): void + { + $item = $event->getTrashItem(); + + if ($item !== null) { + $this->clearCache($item); + } + } + + private function clearCache(Location $item): void + { + $tags = $this->buildCacheTags($item); + + if (!empty($tags)) { + $this->cache->invalidateTags($tags); + } + } + + /** + * @return array + */ + private function buildCacheTags(Location $item): array + { + $contentId = $item->getContentId(); + + try { + $userGroup = $this->userService->loadUserGroup($contentId); + $roleAssignments = $this->roleService->getRoleAssignmentsForUserGroup($userGroup); + } catch (APINotFoundException $e) { + try { + $user = $this->userService->loadUser($contentId); + $roleAssignments = $this->roleService->getRoleAssignmentsForUser($user, true); + } catch (APINotFoundException $e) { + return []; + } + } + + $tags = []; + foreach ($roleAssignments as $roleAssignment) { + $tags[] = $this->identifierGenerator->generateTag( + self::ROLE_ASSIGNMENT_ROLE_LIST_IDENTIFIER, + [$roleAssignment->getRole()->id] + ); + } + + return $tags; + } +} diff --git a/src/lib/Persistence/Legacy/User/Role/Gateway/DoctrineDatabase.php b/src/lib/Persistence/Legacy/User/Role/Gateway/DoctrineDatabase.php index a6d535e3f3..5c1c377b37 100644 --- a/src/lib/Persistence/Legacy/User/Role/Gateway/DoctrineDatabase.php +++ b/src/lib/Persistence/Legacy/User/Role/Gateway/DoctrineDatabase.php @@ -15,6 +15,7 @@ use Ibexa\Contracts\Core\Persistence\User\Policy; use Ibexa\Contracts\Core\Persistence\User\Role; use Ibexa\Contracts\Core\Persistence\User\RoleUpdateStruct; +use Ibexa\Contracts\Core\Repository\Values\Content\ContentInfo; use Ibexa\Core\Persistence\Legacy\Content\Gateway as ContentGateway; use Ibexa\Core\Persistence\Legacy\User\Role\Gateway; @@ -393,6 +394,7 @@ public function countRoleAssignments(int $roleId): int private function buildLoadRoleAssignmentsQuery(array $columns, int $roleId): QueryBuilder { $query = $this->connection->createQueryBuilder(); + $expr = $query->expr(); $query ->select(...$columns) ->from(self::USER_ROLE_TABLE, 'user_role') @@ -400,9 +402,12 @@ private function buildLoadRoleAssignmentsQuery(array $columns, int $roleId): Que 'user_role', ContentGateway::CONTENT_ITEM_TABLE, 'content_object', - 'user_role.contentobject_id = content_object.id' + (string) $expr->and( + $expr->eq('user_role.contentobject_id', 'content_object.id'), + $expr->eq('content_object.status', ContentInfo::STATUS_PUBLISHED) + ) )->where( - $query->expr()->eq( + $expr->eq( 'role_id', $query->createPositionalParameter($roleId, ParameterType::INTEGER) ) diff --git a/tests/lib/Persistence/Legacy/User/_fixtures/roles.php b/tests/lib/Persistence/Legacy/User/_fixtures/roles.php index d1c9fe209a..ff68ab28b7 100644 --- a/tests/lib/Persistence/Legacy/User/_fixtures/roles.php +++ b/tests/lib/Persistence/Legacy/User/_fixtures/roles.php @@ -131,9 +131,11 @@ 'ezcontentobject' => [ [ 'id' => '11', + 'status' => '1', ], [ 'id' => '42', + 'status' => '1', ], ], ];