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-1580: External storage for field type settings #28

Merged
merged 8 commits into from
Dec 15, 2021
27 changes: 27 additions & 0 deletions src/contracts/FieldType/FieldConstraintsStorage.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

/**
* @copyright Copyright (C) Ibexa AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);

namespace Ibexa\Contracts\Core\FieldType;

use Ibexa\Contracts\Core\Persistence\Content\FieldTypeConstraints;

interface FieldConstraintsStorage
{
public function storeFieldConstraintsData(
int $fieldDefinitionId,
FieldTypeConstraints $fieldTypeConstraints
): void;

public function getFieldConstraintsData(
int $fieldDefinitionId
): FieldTypeConstraints;

public function deleteFieldConstraintsData(
int $fieldDefinitionId
): void;
}
2 changes: 1 addition & 1 deletion src/contracts/Persistence/Content/Type/Handler.php
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ public function addFieldDefinition($contentTypeId, $status, FieldDefinition $fie
*
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException If field is not found
*/
public function removeFieldDefinition($contentTypeId, $status, $fieldDefinitionId);
public function removeFieldDefinition($contentTypeId, $status, $fieldDefinitionId, ?string $fieldTypeIdentifier = null);

/**
* This method updates the given $fieldDefinition on a Type.
Expand Down
5 changes: 3 additions & 2 deletions src/lib/Persistence/Cache/ContentTypeHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -482,13 +482,14 @@ public function addFieldDefinition($typeId, $status, FieldDefinition $struct)
/**
* {@inheritdoc}
*/
public function removeFieldDefinition($typeId, $status, $fieldDefinitionId)
public function removeFieldDefinition($typeId, $status, $fieldDefinitionId, ?string $fieldTypeIdentifier = null)
{
$this->logger->logCall(__METHOD__, ['type' => $typeId, 'status' => $status, 'field' => $fieldDefinitionId]);
$this->persistenceHandler->contentTypeHandler()->removeFieldDefinition(
$typeId,
$status,
$fieldDefinitionId
$fieldDefinitionId,
$fieldTypeIdentifier
);

if ($status === Type::STATUS_DEFINED) {
Expand Down
17 changes: 15 additions & 2 deletions src/lib/Persistence/Legacy/Content/Type/Handler.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ class Handler implements BaseContentTypeHandler
*/
protected $updateHandler;

private StorageDispatcherInterface $storageDispatcher;

/**
* Creates a new content type handler.
*
Expand All @@ -50,11 +52,13 @@ class Handler implements BaseContentTypeHandler
public function __construct(
Gateway $contentTypeGateway,
Mapper $mapper,
UpdateHandler $updateHandler
UpdateHandler $updateHandler,
StorageDispatcherInterface $storageDispatcher
) {
$this->contentTypeGateway = $contentTypeGateway;
$this->mapper = $mapper;
$this->updateHandler = $updateHandler;
$this->storageDispatcher = $storageDispatcher;
}

/**
Expand Down Expand Up @@ -535,6 +539,8 @@ public function addFieldDefinition($contentTypeId, $status, FieldDefinition $fie
$fieldDefinition,
$storageFieldDef
);

$this->storageDispatcher->storeFieldConstraintsData($fieldDefinition);
}

/**
Expand All @@ -549,9 +555,15 @@ public function addFieldDefinition($contentTypeId, $status, FieldDefinition $fie
*
* @return bool
*/
public function removeFieldDefinition($contentTypeId, $status, $fieldDefinitionId)
public function removeFieldDefinition($contentTypeId, $status, $fieldDefinitionId, ?string $fieldTypeIdentifier = null)
adamwojs marked this conversation as resolved.
Show resolved Hide resolved
{
if ($fieldTypeIdentifier === null) {
$fieldTypeIdentifier = $this->getFieldDefinition($fieldDefinitionId, $status)->fieldType;
}
adamwojs marked this conversation as resolved.
Show resolved Hide resolved

$this->storageDispatcher->deleteFieldConstraintsData($fieldTypeIdentifier, $fieldDefinitionId);
$this->contentTypeGateway->deleteFieldDefinition($contentTypeId, $status, $fieldDefinitionId);

// @todo FIXME: Return true only if deletion happened
return true;
}
Expand All @@ -572,6 +584,7 @@ public function updateFieldDefinition($contentTypeId, $status, FieldDefinition $
$storageFieldDef = new StorageFieldDefinition();
$this->mapper->toStorageFieldDefinition($fieldDefinition, $storageFieldDef);
$this->contentTypeGateway->updateFieldDefinition($contentTypeId, $status, $fieldDefinition, $storageFieldDef);
$this->storageDispatcher->storeFieldConstraintsData($fieldDefinition);
}

/**
Expand Down
12 changes: 10 additions & 2 deletions src/lib/Persistence/Legacy/Content/Type/Mapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,22 @@ class Mapper
/** @var \Ibexa\Core\Persistence\Legacy\Content\Language\MaskGenerator */
private $maskGenerator;

private StorageDispatcherInterface $storageDispatcher;

/**
* Creates a new content type mapper.
*
* @param \Ibexa\Core\Persistence\Legacy\Content\FieldValue\ConverterRegistry $converterRegistry
* @param \Ibexa\Core\Persistence\Legacy\Content\Language\MaskGenerator $maskGenerator
*/
public function __construct(ConverterRegistry $converterRegistry, MaskGenerator $maskGenerator)
{
public function __construct(
ConverterRegistry $converterRegistry,
MaskGenerator $maskGenerator,
StorageDispatcherInterface $storageDispatcher
) {
$this->converterRegistry = $converterRegistry;
$this->maskGenerator = $maskGenerator;
$this->storageDispatcher = $storageDispatcher;
}

/**
Expand Down Expand Up @@ -459,6 +465,8 @@ public function toFieldDefinition(
$storageFieldDef,
$fieldDef
);

$this->storageDispatcher->loadFieldConstraintsData($fieldDef);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -340,11 +340,11 @@ public function addFieldDefinition($contentTypeId, $status, FieldDefinition $fie
/**
* {@inheritdoc}
*/
public function removeFieldDefinition($contentTypeId, $status, $fieldDefinitionId)
public function removeFieldDefinition($contentTypeId, $status, $fieldDefinitionId, ?string $fieldTypeIdentifier = null)
{
$this->deleteTypeCache($contentTypeId, $status);

return $this->innerHandler->removeFieldDefinition($contentTypeId, $status, $fieldDefinitionId);
return $this->innerHandler->removeFieldDefinition($contentTypeId, $status, $fieldDefinitionId, $fieldTypeIdentifier);
}

/**
Expand Down
46 changes: 46 additions & 0 deletions src/lib/Persistence/Legacy/Content/Type/StorageDispatcher.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php

/**
* @copyright Copyright (C) Ibexa AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);

namespace Ibexa\Core\Persistence\Legacy\Content\Type;

use Ibexa\Contracts\Core\Persistence\Content\Type\FieldDefinition;

final class StorageDispatcher implements StorageDispatcherInterface
{
private StorageRegistryInterface $registry;

public function __construct(StorageRegistryInterface $registry)
{
$this->registry = $registry;
}

public function storeFieldConstraintsData(FieldDefinition $fieldDefinition): void
{
if ($this->registry->hasStorage($fieldDefinition->fieldType)) {
$storage = $this->registry->getStorage($fieldDefinition->fieldType);
$storage->storeFieldConstraintsData($fieldDefinition->id, $fieldDefinition->fieldTypeConstraints);
}
}

public function loadFieldConstraintsData(FieldDefinition $fieldDefinition): void
{
if ($this->registry->hasStorage($fieldDefinition->fieldType)) {
$storage = $this->registry->getStorage($fieldDefinition->fieldType);

$fieldDefinition->fieldTypeConstraints = $storage->getFieldConstraintsData($fieldDefinition->id);
}
}

public function deleteFieldConstraintsData(string $fieldTypeIdentifier, int $fieldDefinitionId): void
{
if ($this->registry->hasStorage($fieldTypeIdentifier)) {
$storage = $this->registry->getStorage($fieldTypeIdentifier);
$storage->deleteFieldConstraintsData($fieldDefinitionId);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

/**
* @copyright Copyright (C) Ibexa AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);

namespace Ibexa\Core\Persistence\Legacy\Content\Type;

use Ibexa\Contracts\Core\Persistence\Content\Type\FieldDefinition;

interface StorageDispatcherInterface
{
public function storeFieldConstraintsData(FieldDefinition $fieldDefinition): void;

public function loadFieldConstraintsData(FieldDefinition $fieldDefinition): void;

public function deleteFieldConstraintsData(string $fieldTypeIdentifier, int $fieldDefinitionId): void;
}
55 changes: 55 additions & 0 deletions src/lib/Persistence/Legacy/Content/Type/StorageRegistry.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php

/**
* @copyright Copyright (C) Ibexa AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);

namespace Ibexa\Core\Persistence\Legacy\Content\Type;

use Ibexa\Contracts\Core\Exception\InvalidArgumentException;
use Ibexa\Contracts\Core\FieldType\FieldConstraintsStorage;

final class StorageRegistry implements StorageRegistryInterface
{
/** @var iterable<string,\Ibexa\Contracts\Core\FieldType\FieldConstraintsStorage> */
private iterable $storages;

public function __construct(iterable $storages)
{
$this->storages = $storages;
}

public function hasStorage(string $fieldTypeName): bool
{
return $this->findStorage($fieldTypeName) !== null;
}

/**
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\InvalidArgumentException
*/
public function getStorage(string $fieldTypeName): FieldConstraintsStorage
{
$storage = $this->findStorage($fieldTypeName);
if ($storage === null) {
throw new InvalidArgumentException(
'$typeName',
sprintf('Undefined %s for "%s" field type', FieldConstraintsStorage::class, $fieldTypeName)
);
}

return $storage;
}

private function findStorage(string $needle): ?FieldConstraintsStorage
{
foreach ($this->storages as $fieldTypeName => $storage) {
if ($fieldTypeName === $needle) {
return $storage;
}
}

return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

/**
* @copyright Copyright (C) Ibexa AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);

namespace Ibexa\Core\Persistence\Legacy\Content\Type;

use Ibexa\Contracts\Core\FieldType\FieldConstraintsStorage;

interface StorageRegistryInterface
{
public function hasStorage(string $fieldTypeName): bool;

/**
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\InvalidArgumentException
*/
public function getStorage(string $fieldTypeName): FieldConstraintsStorage;
}
3 changes: 2 additions & 1 deletion src/lib/Repository/ContentTypeService.php
Original file line number Diff line number Diff line change
Expand Up @@ -1383,7 +1383,8 @@ public function removeFieldDefinition(APIContentTypeDraft $contentTypeDraft, API
$this->contentTypeHandler->removeFieldDefinition(
$contentTypeDraft->id,
SPIContentType::STATUS_DRAFT,
$fieldDefinition->id
$fieldDefinition->id,
$fieldDefinition->fieldTypeIdentifier
);
$this->repository->commit();
} catch (Exception $e) {
Expand Down
16 changes: 16 additions & 0 deletions src/lib/Resources/settings/storage_engines/legacy/content_type.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ services:
arguments:
- "@ezpublish.persistence.legacy.field_value_converter.registry"
- '@ezpublish.persistence.legacy.language.mask_generator'
- '@Ibexa\Core\Persistence\Legacy\Content\Type\StorageDispatcherInterface'

ezpublish.persistence.legacy.content_type.content_updater:
class: Ibexa\Core\Persistence\Legacy\Content\Type\ContentUpdater
Expand Down Expand Up @@ -49,6 +50,7 @@ services:
- "@ezpublish.persistence.legacy.content_type.gateway"
- "@ezpublish.persistence.legacy.content_type.mapper"
- "@ezpublish.persistence.legacy.content_type.update_handler"
- '@Ibexa\Core\Persistence\Legacy\Content\Type\StorageDispatcherInterface'

ezpublish.spi.persistence.legacy.content_type.handler.caching:
class: Ibexa\Core\Persistence\Legacy\Content\Type\MemoryCachingHandler
Expand All @@ -59,3 +61,17 @@ services:

ezpublish.spi.persistence.legacy.content_type.handler:
alias: ezpublish.spi.persistence.legacy.content_type.handler.caching

Ibexa\Core\Persistence\Legacy\Content\Type\StorageRegistryInterface:
alias: Ibexa\Core\Persistence\Legacy\Content\Type\StorageRegistry

Ibexa\Core\Persistence\Legacy\Content\Type\StorageRegistry:
arguments:
$storages: !tagged_iterator { tag: ibexa.field_type.external_constraints_storage, index_by: alias }
alongosz marked this conversation as resolved.
Show resolved Hide resolved

Ibexa\Core\Persistence\Legacy\Content\Type\StorageDispatcherInterface:
alias: Ibexa\Core\Persistence\Legacy\Content\Type\StorageDispatcher

Ibexa\Core\Persistence\Legacy\Content\Type\StorageDispatcher:
arguments:
$registry: '@Ibexa\Core\Persistence\Legacy\Content\Type\StorageRegistryInterface'
Loading