Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -46299,13 +46299,13 @@ parameters:
-
message: '#^Parameter \#1 \$originalClassName of method PHPUnit\\Framework\\TestCase\:\:createMock\(\) expects class\-string\<mixed\>, string given\.$#'
identifier: argument.type
count: 4
count: 3
path: tests/lib/Persistence/Cache/TrashHandlerTest.php

-
message: '#^Unable to resolve the template type T in call to method PHPUnit\\Framework\\TestCase\:\:createMock\(\)$#'
identifier: argument.templateType
count: 4
count: 3
path: tests/lib/Persistence/Cache/TrashHandlerTest.php

-
Expand Down
1 change: 1 addition & 0 deletions src/bundle/Core/Resources/config/services.yml
Original file line number Diff line number Diff line change
Expand Up @@ -371,3 +371,4 @@ services:
decoration_priority: 500
arguments:
$inner: '@.inner'

40 changes: 30 additions & 10 deletions src/lib/Persistence/Cache/TrashHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@

use Ibexa\Contracts\Core\Persistence\Content\Location\Trash\Handler as TrashHandlerInterface;
use Ibexa\Contracts\Core\Persistence\Content\Relation;
use Ibexa\Contracts\Core\Persistence\User\RoleAssignment;
use Ibexa\Contracts\Core\Repository\Values\Content\Query\CriterionInterface;

class TrashHandler extends AbstractHandler implements TrashHandlerInterface
{
private const EMPTY_TRASH_BULK_SIZE = 100;
private const CONTENT_IDENTIFIER = 'content';
private const LOCATION_PATH_IDENTIFIER = 'location_path';
private const ROLE_ASSIGNMENT_ROLE_LIST_IDENTIFIER = 'role_assignment_role_list';

/**
* {@inheritdoc}
Expand All @@ -34,13 +36,14 @@ public function trashSubtree($locationId)
{
$this->logger->logCall(__METHOD__, ['locationId' => $locationId]);

$location = $this->persistenceHandler->locationHandler()->load($locationId);
$contentId = $this->persistenceHandler->locationHandler()->load($locationId)->contentId;
$roleAssignments = $this->persistenceHandler->userHandler()->loadRoleAssignmentsByGroupId($contentId);
$limit = $this->persistenceHandler->contentHandler()->countRelations(
$location->contentId
$contentId
);

$reverseRelations = $this->persistenceHandler->contentHandler()->loadRelationList(
$location->contentId,
$contentId,
$limit
);
$return = $this->persistenceHandler->trashHandler()->trashSubtree($locationId);
Expand All @@ -55,12 +58,20 @@ public function trashSubtree($locationId)
}, $reverseRelations);
}

$roleAssignmentTags = array_map(function (RoleAssignment $roleAssignment): string {
return $this->cacheIdentifierGenerator->generateTag(
self::ROLE_ASSIGNMENT_ROLE_LIST_IDENTIFIER,
[$roleAssignment->roleId]
);
}, $roleAssignments);

$tags = array_merge(
[
$this->cacheIdentifierGenerator->generateTag(self::CONTENT_IDENTIFIER, [$location->contentId]),
$this->cacheIdentifierGenerator->generateTag(self::CONTENT_IDENTIFIER, [$contentId]),
$this->cacheIdentifierGenerator->generateTag(self::LOCATION_PATH_IDENTIFIER, [$locationId]),
],
$relationTags
$relationTags,
$roleAssignmentTags
);
$this->cache->invalidateTags(array_values(array_unique($tags)));

Expand All @@ -76,14 +87,15 @@ public function recover($trashedId, $newParentId)

$return = $this->persistenceHandler->trashHandler()->recover($trashedId, $newParentId);

$location = $this->persistenceHandler->locationHandler()->load($return);
$contentId = $this->persistenceHandler->locationHandler()->load($return)->contentId;
$roleAssignments = $this->persistenceHandler->userHandler()->loadRoleAssignmentsByGroupId($contentId);

$limit = $this->persistenceHandler->contentHandler()->countRelations(
$location->contentId
$contentId
);

$reverseRelations = $this->persistenceHandler->contentHandler()->loadRelationList(
$location->contentId,
$contentId,
$limit
);

Expand All @@ -94,12 +106,20 @@ public function recover($trashedId, $newParentId)
}, $reverseRelations);
}

$roleAssignmentTags = array_map(function (RoleAssignment $roleAssignment): string {
return $this->cacheIdentifierGenerator->generateTag(
self::ROLE_ASSIGNMENT_ROLE_LIST_IDENTIFIER,
[$roleAssignment->roleId]
);
}, $roleAssignments);

$tags = array_merge(
[
$this->cacheIdentifierGenerator->generateTag(self::CONTENT_IDENTIFIER, [$location->contentId]),
$this->cacheIdentifierGenerator->generateTag(self::CONTENT_IDENTIFIER, [$contentId]),
$this->cacheIdentifierGenerator->generateTag(self::LOCATION_PATH_IDENTIFIER, [$trashedId]),
],
$relationTags
$relationTags,
$roleAssignmentTags
);
$this->cache->invalidateTags(array_values(array_unique($tags)));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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\Content\Location\Gateway as LocationGateway;
use Ibexa\Core\Persistence\Legacy\User\Role\Gateway;
Expand Down Expand Up @@ -371,16 +372,20 @@ 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')
->innerJoin(
'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)
)
Expand Down
101 changes: 45 additions & 56 deletions tests/lib/Persistence/Cache/TrashHandlerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
use Ibexa\Contracts\Core\Persistence\Content\Location\Trash\Handler as TrashHandler;
use Ibexa\Contracts\Core\Persistence\Content\Location\Trashed;
use Ibexa\Contracts\Core\Persistence\Content\Relation;
use Ibexa\Contracts\Core\Persistence\User\Handler as PersistenceUserHandler;
use Ibexa\Contracts\Core\Persistence\User\RoleAssignment;
use Ibexa\Contracts\Core\Repository\Values\Content\Trash\TrashItemDeleteResult;
use Ibexa\Core\Persistence\Cache\ContentHandler;
use Ibexa\Core\Persistence\Cache\LocationHandler;
Expand Down Expand Up @@ -57,86 +59,71 @@
$originalLocationId = 6;
$targetLocationId = 2;
$contentId = 42;

$tags = [
'c-' . $contentId,
'lp-' . $originalLocationId,
];

$handlerMethodName = $this->getHandlerMethodName();
$roleId = 1;

$this->loggerMock->expects(self::once())->method('logCall');

$innerHandler = $this->createMock($this->getHandlerClassName());
$contentHandlerMock = $this->createMock(ContentHandler::class);
$locationHandlerMock = $this->createMock(LocationHandler::class);

$locationHandlerMock
->method('load')
->willReturn(new Location(['id' => $originalLocationId, 'contentId' => $contentId]));

$this->persistenceHandlerMock
->method('contentHandler')
->willReturn($contentHandlerMock);

$this->persistenceHandlerMock
->method('locationHandler')
->willReturn($locationHandlerMock);

$this->persistenceHandlerMock
->expects(self::once())
->method($handlerMethodName)
->willReturn($innerHandler);
$innerHandler = $this->setUpRoleAssignmentInvalidation($originalLocationId, $contentId, $roleId);

$innerHandler
->expects(self::once())
->method('recover')
->with($originalLocationId, $targetLocationId)
->willReturn(null);

$this->cacheIdentifierGeneratorMock
->expects(self::exactly(2))
->method('generateTag')
->withConsecutive(
['content', [$contentId], false],
['location_path', [$originalLocationId], false]
)
->willReturnOnConsecutiveCalls(
'c-' . $contentId,
'lp-' . $originalLocationId
);

$this->cacheMock
->expects(self::once())
->method('invalidateTags')
->with($tags);

$handler = $this->persistenceCacheHandler->$handlerMethodName();
$handler = $this->persistenceCacheHandler->{$this->getHandlerMethodName()}();
$handler->recover($originalLocationId, $targetLocationId);
}

public function testTrashSubtree()
{
$locationId = 6;
$contentId = 42;
$roleId = 1;

$this->loggerMock->expects($this->once())->method('logCall');

$innerHandler = $this->setUpRoleAssignmentInvalidation($locationId, $contentId, $roleId);

$innerHandler
->expects(self::once())
->method('trashSubtree')
->with($locationId)
->willReturn(null);

$handler = $this->persistenceCacheHandler->{$this->getHandlerMethodName()}();
$handler->trashSubtree($locationId);
}

/**
* @return \PHPUnit\Framework\MockObject\MockObject
*/
private function setUpRoleAssignmentInvalidation(int $locationId, int $contentId, int $roleId): object
{
$tags = [
'c-' . $contentId,
'lp-' . $locationId,
'rarl-' . $roleId,
];

$handlerMethodName = $this->getHandlerMethodName();

Check warning on line 109 in tests/lib/Persistence/Cache/TrashHandlerTest.php

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this unused "$handlerMethodName" local variable.

See more on https://sonarcloud.io/project/issues?id=ibexa_core&issues=AZ27CnRGxBog4OQfC6HM&open=AZ27CnRGxBog4OQfC6HM&pullRequest=747

$this->loggerMock->expects(self::once())->method('logCall');

$innerHandler = $this->createMock($this->getHandlerClassName());
$contentHandlerMock = $this->createMock(ContentHandler::class);
$locationHandlerMock = $this->createMock(LocationHandler::class);
$userHandlerMock = $this->createMock(PersistenceUserHandler::class);

$locationHandlerMock
->method('load')
->willReturn(new Location(['id' => $locationId, 'contentId' => $contentId]));

$userHandlerMock
->method('loadRoleAssignmentsByGroupId')
->with($contentId)
->willReturn([new RoleAssignment(['roleId' => $roleId, 'contentId' => $contentId])]);

$this->persistenceHandlerMock
->method('contentHandler')
->willReturn($contentHandlerMock);
Expand All @@ -146,32 +133,34 @@
->willReturn($locationHandlerMock);

$this->persistenceHandlerMock
->expects(self::once())
->method($handlerMethodName)
->willReturn($innerHandler);
->method('userHandler')
->willReturn($userHandlerMock);

$innerHandler
$this->persistenceHandlerMock
->expects(self::once())
->method('trashSubtree')
->with($locationId)
->willReturn(null);
->method($this->getHandlerMethodName())
->willReturn($innerHandler);

$this->cacheIdentifierGeneratorMock
->expects(self::exactly(2))
->expects(self::exactly(3))
->method('generateTag')
->withConsecutive(
['role_assignment_role_list', [$roleId], false],
['content', [$contentId], false],
['location_path', [$locationId], false]
)
->willReturnOnConsecutiveCalls(...$tags);
->willReturnOnConsecutiveCalls(
'rarl-' . $roleId,
'c-' . $contentId,
'lp-' . $locationId
);

$this->cacheMock
->expects(self::once())
->method('invalidateTags')
->with($tags);

$handler = $this->persistenceCacheHandler->$handlerMethodName();
$handler->trashSubtree($locationId);
return $innerHandler;
}

public function testDeleteTrashItem()
Expand Down
2 changes: 2 additions & 0 deletions tests/lib/Persistence/Legacy/User/_fixtures/roles.php
Original file line number Diff line number Diff line change
Expand Up @@ -134,9 +134,11 @@
ContentGateway::CONTENT_ITEM_TABLE => [
[
'id' => '11',
'status' => '1',
],
[
'id' => '42',
'status' => '1',
],
],
];
Loading