Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IBX-2823: Added loadRelation method #115

Merged
merged 21 commits into from
Jun 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
0fb0392
IBX-2823: Added loadRelation method
ciastektk May 27, 2022
92c53c4
Update src/lib/Resources/settings/storage_engines/cache.yml
ciastektk May 30, 2022
80eee5a
Update src/lib/Resources/settings/storage_engines/cache.yml
ciastektk May 30, 2022
67cb972
Fixed invalidate tags in removeRelation
ciastektk May 30, 2022
5cbc85b
Added tests
ciastektk May 30, 2022
cba5903
Update src/lib/Persistence/Legacy/Content/Gateway/DoctrineDatabase.php
ciastektk Jun 2, 2022
75c2038
Update tests/lib/Persistence/Legacy/Content/ContentHandlerTest.php
ciastektk Jun 2, 2022
d035fd1
Update tests/lib/Persistence/Legacy/Content/ContentHandlerTest.php
ciastektk Jun 2, 2022
6ca3f5c
Update tests/lib/Persistence/Legacy/Content/Gateway/DoctrineDatabaseT…
ciastektk Jun 2, 2022
b5612fe
Update src/lib/Persistence/Legacy/Content/Gateway/DoctrineDatabase.php
ciastektk Jun 2, 2022
9635428
Update tests/lib/Persistence/Legacy/Content/ContentHandlerTest.php
ciastektk Jun 2, 2022
8059fa0
Update tests/lib/Persistence/Legacy/Content/Gateway/DoctrineDatabaseT…
ciastektk Jun 2, 2022
eb8c399
Update src/lib/Persistence/Legacy/Content/Handler.php
ciastektk Jun 2, 2022
9ddfbaa
Added deprecated info when destinationContentId is not passed
ciastektk Jun 2, 2022
dc43e24
Fixed phpdoc for removeRelation method
ciastektk Jun 2, 2022
a7d3474
Used const for relationId
ciastektk Jun 2, 2022
80a45c5
Fixed cs
ciastektk Jun 2, 2022
bb9f768
Update src/lib/Persistence/Cache/ContentHandler.php
ciastektk Jun 3, 2022
d7195d8
Update src/lib/Persistence/Legacy/Content/Handler.php
ciastektk Jun 3, 2022
79e6d11
Fixes after review
ciastektk Jun 3, 2022
e6ad2c6
Fixed ContentHandlerTest::testLoadRelation
ciastektk Jun 3, 2022
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
10 changes: 8 additions & 2 deletions src/contracts/Persistence/Content/Handler.php
Original file line number Diff line number Diff line change
Expand Up @@ -261,18 +261,24 @@ public function copy($contentId, $versionNo = null, $newOwnerId = null);
*/
public function addRelation(RelationCreateStruct $createStruct);

/**
* Load a relation by $relationId.
*/
public function loadRelation(int $relationId): Relation;

/**
* Removes a relation by relation Id.
*
* @todo Should the existence verifications happen here or is this supposed to be handled at a higher level?
*
* @param mixed $relationId
* @param int $relationId
* @param int $type {@see \Ibexa\Contracts\Core\Repository\Values\Content\Relation::COMMON,
* \Ibexa\Contracts\Core\Repository\Values\Content\Relation::EMBED,
* \Ibexa\Contracts\Core\Repository\Values\Content\Relation::LINK,
* \Ibexa\Contracts\Core\Repository\Values\Content\Relation::FIELD}
* @param ?int $destinationContentId Content id to invalidate cache tag related to content reverse relations count
*/
public function removeRelation($relationId, $type);
public function removeRelation($relationId, $type, ?int $destinationContentId = null);
ciastektk marked this conversation as resolved.
Show resolved Hide resolved

/**
* Loads relations from $sourceContentId. Optionally, loads only those with $type and $sourceContentVersionNo.
Expand Down
85 changes: 81 additions & 4 deletions src/lib/Persistence/Cache/ContentHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use Ibexa\Contracts\Core\Persistence\Content\CreateStruct;
use Ibexa\Contracts\Core\Persistence\Content\Handler as ContentHandlerInterface;
use Ibexa\Contracts\Core\Persistence\Content\MetadataUpdateStruct;
use Ibexa\Contracts\Core\Persistence\Content\Relation;
use Ibexa\Contracts\Core\Persistence\Content\Relation\CreateStruct as RelationCreateStruct;
use Ibexa\Contracts\Core\Persistence\Content\UpdateStruct;
use Ibexa\Contracts\Core\Persistence\Content\VersionInfo;
Expand All @@ -30,6 +31,8 @@ class ContentHandler extends AbstractInMemoryPersistenceHandler implements Conte
private const CONTENT_VERSION_LIST_IDENTIFIER = 'content_version_list';
private const CONTENT_VERSION_INFO_IDENTIFIER = 'content_version_info';
private const CONTENT_VERSION_IDENTIFIER = 'content_version';
private const CONTENT_REVERSE_RELATIONS_COUNT_IDENTIFIER = 'content_reverse_relations_count';
private const RELATION_IDENTIFIER = 'relation';

public const ALL_TRANSLATIONS_KEY = '0';

Expand Down Expand Up @@ -433,16 +436,68 @@ public function addRelation(RelationCreateStruct $relation)
{
$this->logger->logCall(__METHOD__, ['struct' => $relation]);

$this->cache->invalidateTags([
$this->cacheIdentifierGenerator->generateTag(
self::CONTENT_IDENTIFIER,
[$relation->destinationContentId]
),
]);

return $this->persistenceHandler->contentHandler()->addRelation($relation);
}

/**
* {@inheritdoc}
*/
public function removeRelation($relationId, $type)
public function removeRelation($relationId, $type, ?int $destinationContentId = null): void
{
if (null === $destinationContentId) {
@trigger_error('Expecting to pass $destinationContentId argument since version 4.1.5', E_USER_DEPRECATED);
}

$this->logger->logCall(__METHOD__, ['relation' => $relationId, 'type' => $type]);
$this->persistenceHandler->contentHandler()->removeRelation($relationId, $type);

$this->cache->invalidateTags([
$this->cacheIdentifierGenerator->generateTag(
self::CONTENT_IDENTIFIER,
[$destinationContentId ?? $this->loadRelation($relationId)->destinationContentId]
ciastektk marked this conversation as resolved.
Show resolved Hide resolved
),
$this->cacheIdentifierGenerator->generateTag(
self::RELATION_IDENTIFIER,
[$relationId]
),
]);

$this->persistenceHandler->contentHandler()->removeRelation($relationId, $type, $destinationContentId);
}

public function loadRelation(int $relationId): Relation
{
$cacheItem = $this->cache->getItem(
$this->cacheIdentifierGenerator->generateKey(
self::RELATION_IDENTIFIER,
[$relationId],
true
)
);

if ($cacheItem->isHit()) {
$this->logger->logCacheHit(['relationId' => $relationId]);

return $cacheItem->get();
}

$this->logger->logCacheMiss(['relationId' => $relationId]);
$relation = $this->persistenceHandler->contentHandler()->loadRelation($relationId);
$cacheItem->set($relation);
$tags = [
$this->cacheIdentifierGenerator->generateTag(self::RELATION_IDENTIFIER, [$relationId]),
];

$cacheItem->tag($tags);
$this->cache->save($cacheItem);

return $relation;
}

/**
Expand All @@ -467,9 +522,31 @@ public function loadRelations($sourceContentId, $sourceContentVersionNo = null,
*/
public function countReverseRelations(int $destinationContentId, ?int $type = null): int
{
$this->logger->logCall(__METHOD__, ['content' => $destinationContentId, 'type' => $type]);
$cacheItem = $this->cache->getItem(
$this->cacheIdentifierGenerator->generateKey(
self::CONTENT_REVERSE_RELATIONS_COUNT_IDENTIFIER,
[$destinationContentId],
true
)
);

if ($cacheItem->isHit()) {
$this->logger->logCacheHit(['content' => $destinationContentId]);

return $cacheItem->get();
}

$this->logger->logCacheMiss(['content' => $destinationContentId]);
$reverseRelationsCount = $this->persistenceHandler->contentHandler()->countReverseRelations($destinationContentId, $type);
$cacheItem->set($reverseRelationsCount);
$tags = [
$this->cacheIdentifierGenerator->generateTag(self::CONTENT_IDENTIFIER, [$destinationContentId]),
];

$cacheItem->tag($tags);
$this->cache->save($cacheItem);

return $this->persistenceHandler->contentHandler()->countReverseRelations($destinationContentId, $type);
return $reverseRelationsCount;
}

/**
Expand Down
8 changes: 8 additions & 0 deletions src/lib/Persistence/Legacy/Content/Gateway.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
use Ibexa\Contracts\Core\Persistence\Content\Relation\CreateStruct as RelationCreateStruct;
use Ibexa\Contracts\Core\Persistence\Content\UpdateStruct;
use Ibexa\Contracts\Core\Persistence\Content\VersionInfo;
use Ibexa\Contracts\Core\Repository\Values\Content\Relation;

/**
* Base class for content gateways.
Expand Down Expand Up @@ -395,6 +396,13 @@ abstract public function deleteRelation(int $relationId, int $type): void;
*/
abstract public function insertRelation(RelationCreateStruct $createStruct): int;

/**
* Load Relation object.
*
* @see \Ibexa\Contracts\Core\Persistence\Content\Relation
*/
abstract public function loadRelation(int $relationId): array;

/**
* Return all Content IDs for the given $contentTypeId.
*
Expand Down
31 changes: 31 additions & 0 deletions src/lib/Persistence/Legacy/Content/Gateway/DoctrineDatabase.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,14 @@
use Ibexa\Contracts\Core\Repository\Values\Content\Relation;
use Ibexa\Contracts\Core\Repository\Values\Content\VersionInfo as APIVersionInfo;
use Ibexa\Core\Base\Exceptions\BadStateException;
use Ibexa\Core\Base\Exceptions\NotFoundException;
use Ibexa\Core\Base\Exceptions\NotFoundException as NotFound;
use Ibexa\Core\Persistence\Legacy\Content\Gateway;
use Ibexa\Core\Persistence\Legacy\Content\Gateway\DoctrineDatabase\QueryBuilder;
use Ibexa\Core\Persistence\Legacy\Content\Language\MaskGenerator as LanguageMaskGenerator;
use Ibexa\Core\Persistence\Legacy\Content\StorageFieldValue;
use Ibexa\Core\Persistence\Legacy\SharedGateway\Gateway as SharedGateway;
use LogicException;

/**
* Doctrine database based content gateway.
Expand Down Expand Up @@ -1609,6 +1611,35 @@ public function insertRelation(RelationCreateStruct $createStruct): int
return (int)$this->connection->lastInsertId(self::CONTENT_RELATION_SEQ);
}

/**
* @throws \Doctrine\DBAL\Driver\Exception
* @throws \Doctrine\DBAL\Exception
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException
*/
public function loadRelation(int $relationId): array
ciastektk marked this conversation as resolved.
Show resolved Hide resolved
{
$query = $this->queryBuilder->createRelationFindQueryBuilder();
$expr = $query->expr();

$query
->andWhere(
$expr->eq('id', ':relationId')
)
->setParameter('relationId', $relationId, ParameterType::INTEGER);

$result = $query->execute()->fetchAllAssociative();
$resultCount = count($result);
if ($resultCount === 0) {
throw new NotFoundException('Relation', $relationId);
}

if ($resultCount > 1) {
throw new LogicException('More then one row found for the relation id: ' . $relationId);
}

return current($result);
}

public function deleteRelation(int $relationId, int $type): void
{
// Legacy Storage stores COMMON, LINK and EMBED types using bitmask, therefore first load
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,15 @@ public function insertRelation(RelationCreateStruct $struct): int
}
}

public function loadRelation(int $relationId): array
{
try {
return $this->innerGateway->loadRelation($relationId);
} catch (DBALException | PDOException $e) {
throw DatabaseException::wrap($e);
}
}

public function getContentIdsByContentTypeId($contentTypeId): array
{
try {
Expand Down
13 changes: 12 additions & 1 deletion src/lib/Persistence/Legacy/Content/Handler.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use Ibexa\Contracts\Core\Persistence\Content\Field;
use Ibexa\Contracts\Core\Persistence\Content\Handler as BaseContentHandler;
use Ibexa\Contracts\Core\Persistence\Content\MetadataUpdateStruct;
use Ibexa\Contracts\Core\Persistence\Content\Relation;
use Ibexa\Contracts\Core\Persistence\Content\Relation\CreateStruct as RelationCreateStruct;
use Ibexa\Contracts\Core\Persistence\Content\Type\Handler as ContentTypeHandler;
use Ibexa\Contracts\Core\Persistence\Content\UpdateStruct;
Expand Down Expand Up @@ -776,6 +777,16 @@ public function addRelation(RelationCreateStruct $createStruct)
return $relation;
}

/**
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException
*/
public function loadRelation(int $relationId): Relation
ciastektk marked this conversation as resolved.
Show resolved Hide resolved
{
return $this->mapper->extractRelationFromRow(
$this->contentGateway->loadRelation($relationId)
);
}

/**
* Removes a relation by relation Id.
*
Expand All @@ -787,7 +798,7 @@ public function addRelation(RelationCreateStruct $createStruct)
* \Ibexa\Contracts\Core\Repository\Values\Content\Relation::LINK,
* \Ibexa\Contracts\Core\Repository\Values\Content\Relation::FIELD}
*/
public function removeRelation($relationId, $type)
public function removeRelation($relationId, $type, ?int $destinationContentId = null): void
{
$this->contentGateway->deleteRelation($relationId, $type);
}
Expand Down
2 changes: 1 addition & 1 deletion src/lib/Persistence/Legacy/Content/Mapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -542,7 +542,7 @@ public function extractRelationsFromRows(array $rows)
*
* @return \Ibexa\Contracts\Core\Persistence\Content\Relation
*/
protected function extractRelationFromRow(array $row)
public function extractRelationFromRow(array $row)
{
$relation = new Relation();
$relation->id = (int)$row['ezcontentobject_link_id'];
Expand Down
3 changes: 2 additions & 1 deletion src/lib/Repository/ContentService.php
Original file line number Diff line number Diff line change
Expand Up @@ -2128,7 +2128,8 @@ public function deleteRelation(APIVersionInfo $sourceVersion, ContentInfo $desti
if ($spiRelation->destinationContentId == $destinationContent->id) {
$this->persistenceHandler->contentHandler()->removeRelation(
$spiRelation->id,
APIRelation::COMMON
APIRelation::COMMON,
$spiRelation->destinationContentId
);
}
}
Expand Down
6 changes: 4 additions & 2 deletions src/lib/Repository/Helper/RelationProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -192,15 +192,17 @@ public function processFieldRelations(
foreach ($relationEntry as $relation) {
$this->persistenceHandler->contentHandler()->removeRelation(
$relation->id,
$relationType
$relationType,
$relation->destinationContentInfo->id
);
}
break;
case Relation::LINK:
case Relation::EMBED:
$this->persistenceHandler->contentHandler()->removeRelation(
$relationEntry->id,
$relationType
$relationType,
$relationEntry->destinationContentInfo->id
);
}
}
Expand Down
3 changes: 3 additions & 0 deletions src/lib/Resources/settings/storage_engines/cache.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ parameters:
notification_count: 'nc-%s'
notification_pending_count: 'npc-%s'
policy: 'p-%s'
relation: 're-%s'
role: 'r-%s'
role_assignment: 'ra-%s'
role_assignment_group_list: 'ragl-%s'
Expand Down Expand Up @@ -114,6 +115,7 @@ parameters:
content_info: 'ci-%s'
content_info_by_remote_id: 'cibri-%s'
content_locations: 'cl-%s'
content_reverse_relations_count: 'crrc-%s'
content_version_info: 'cvi-%s'
content_version_list: 'c-%s-vl'
content_version: 'c-%%s-v-%%s'
Expand Down Expand Up @@ -141,6 +143,7 @@ parameters:
notification_count: 'nc-%s'
notification_pending_count: 'npc-%s'
policy: 'p-%s'
relation: 're-%s'
role: 'r-%s'
role_assignment: 'ra-%s'
role_assignment_group_list: 'ragl-%s'
Expand Down
Loading