From e24c72b545b4d30bdbed585152eeb1403709ce49 Mon Sep 17 00:00:00 2001 From: Nattfarinn Date: Tue, 9 Apr 2024 10:20:59 +0200 Subject: [PATCH] fix: External Storage --- .../Persistence/Legacy/Content/Mapper.php | 66 ++------ .../storage_engines/legacy/content.yml | 8 + .../Event/Mapper/ResolveMissingFieldEvent.php | 69 ++++++++ .../Mapper/ResolveVirtualFieldSubscriber.php | 154 ++++++++++++++++++ 4 files changed, 246 insertions(+), 51 deletions(-) create mode 100644 src/contracts/Event/Mapper/ResolveMissingFieldEvent.php create mode 100644 src/lib/Persistence/Legacy/Content/Mapper/ResolveVirtualFieldSubscriber.php diff --git a/eZ/Publish/Core/Persistence/Legacy/Content/Mapper.php b/eZ/Publish/Core/Persistence/Legacy/Content/Mapper.php index 67351e809f..b394df0216 100644 --- a/eZ/Publish/Core/Persistence/Legacy/Content/Mapper.php +++ b/eZ/Publish/Core/Persistence/Legacy/Content/Mapper.php @@ -16,9 +16,10 @@ use eZ\Publish\SPI\Persistence\Content\Language\Handler as LanguageHandler; use eZ\Publish\SPI\Persistence\Content\Relation; use eZ\Publish\SPI\Persistence\Content\Relation\CreateStruct as RelationCreateStruct; -use eZ\Publish\SPI\Persistence\Content\Type\FieldDefinition; use eZ\Publish\SPI\Persistence\Content\Type\Handler as ContentTypeHandler; use eZ\Publish\SPI\Persistence\Content\VersionInfo; +use Ibexa\Contracts\Core\Event\Mapper\ResolveMissingFieldEvent; +use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; /** * Mapper for Content Handler. @@ -79,20 +80,20 @@ class Mapper private $contentTypeHandler; /** - * @var StorageRegistry + * @var EventDispatcherInterface */ - private $storageRegistry; + private $eventDispatcher; public function __construct( Registry $converterRegistry, LanguageHandler $languageHandler, ContentTypeHandler $contentTypeHandler, - StorageRegistry $storageRegistry + EventDispatcherInterface $eventDispatcher ) { $this->converterRegistry = $converterRegistry; $this->languageHandler = $languageHandler; $this->contentTypeHandler = $contentTypeHandler; - $this->storageRegistry = $storageRegistry; + $this->eventDispatcher = $eventDispatcher; } /** @@ -319,19 +320,19 @@ private function buildContentObjects( $missingVersionFieldDefinitions = $missingFieldDefinitions[$contentId][$versionId]; foreach ($missingVersionFieldDefinitions as $languageCode => $versionFieldDefinitions) { foreach ($versionFieldDefinitions as $fieldDefinition) { - $emptyField = $this->createEmptyField( - $versionInfo, - $fieldDefinition, - $languageCode + $event = $this->eventDispatcher->dispatch( + new ResolveMissingFieldEvent( + $content, + $fieldDefinition, + $languageCode + ) ); - $externalStorage = $this->storageRegistry->getStorage($fieldDefinition->fieldType); - if ($externalStorage->hasFieldData()) { - $externalStorage->getFieldData($versionInfo, $emptyField, []); + $field = $event->getField(); + if ($field !== null) { + $content->fields[] = $field; } - $emptyField->id = null; - $content->fields[] = $emptyField; } } @@ -722,41 +723,4 @@ public function createRelationFromCreateStruct(RelationCreateStruct $struct) return $relation; } - - private function createEmptyField(VersionInfo $versionInfo, FieldDefinition $fieldDefinition, string $languageCode): Field - { - $field = new Field(); - $field->id = self::EMPTY_FIELD_ID; - $field->fieldDefinitionId = $fieldDefinition->id; - $field->type = $fieldDefinition->fieldType; - $field->value = $this->getDefaultValue($fieldDefinition); - $field->languageCode = $languageCode; - $field->versionNo = $versionInfo->versionNo; - - return $field; - } - - private function getDefaultValue(FieldDefinition $fieldDefinition): FieldValue - { - $value = clone $fieldDefinition->defaultValue; - $storageValue = $this->getDefaultStorageValue(); - - $converter = $this->converterRegistry->getConverter($fieldDefinition->fieldType); - $converter->toStorageValue($value, $storageValue); - $converter->toFieldValue($storageValue, $value); - - return $value; - } - - private function getDefaultStorageValue(): StorageFieldValue - { - $storageValue = new StorageFieldValue(); - $storageValue->dataFloat = null; - $storageValue->dataInt = null; - $storageValue->dataText = ''; - $storageValue->sortKeyInt = 0; - $storageValue->sortKeyString = ''; - - return $storageValue; - } } diff --git a/eZ/Publish/Core/settings/storage_engines/legacy/content.yml b/eZ/Publish/Core/settings/storage_engines/legacy/content.yml index 98b87859ea..14463e9d9b 100644 --- a/eZ/Publish/Core/settings/storage_engines/legacy/content.yml +++ b/eZ/Publish/Core/settings/storage_engines/legacy/content.yml @@ -10,7 +10,15 @@ services: - "@ezpublish.persistence.legacy.field_value_converter.registry" - "@ezpublish.spi.persistence.legacy.language.handler" - '@ezpublish.spi.persistence.legacy.content_type.handler' + - "@event_dispatcher" + + Ibexa\Core\Persistence\Legacy\Content\Mapper\ResolveVirtualFieldSubscriber: + arguments: + - "@ezpublish.persistence.legacy.field_value_converter.registry" - "@ezpublish.persistence.external_storage_registry" + - "@ezpublish.persistence.legacy.content.gateway" + tags: + - { name: kernel.event_subscriber } ezpublish.persistence.legacy.content.gateway.inner: class: eZ\Publish\Core\Persistence\Legacy\Content\Gateway\DoctrineDatabase diff --git a/src/contracts/Event/Mapper/ResolveMissingFieldEvent.php b/src/contracts/Event/Mapper/ResolveMissingFieldEvent.php new file mode 100644 index 0000000000..c36011f24c --- /dev/null +++ b/src/contracts/Event/Mapper/ResolveMissingFieldEvent.php @@ -0,0 +1,69 @@ +content = $content; + $this->fieldDefinition = $fieldDefinition; + $this->languageCode = $languageCode; + $this->context = $context; + $this->field = null; + } + + public function getContent(): Content + { + return $this->content; + } + + public function getFieldDefinition(): FieldDefinition + { + return $this->fieldDefinition; + } + + public function getLanguageCode(): string + { + return $this->languageCode; + } + + public function getContext(): array + { + return $this->context; + } + + public function setField(?Field $field): void + { + $this->field = $field; + } + + public function getField(): ?Field + { + return $this->field; + } +} \ No newline at end of file diff --git a/src/lib/Persistence/Legacy/Content/Mapper/ResolveVirtualFieldSubscriber.php b/src/lib/Persistence/Legacy/Content/Mapper/ResolveVirtualFieldSubscriber.php new file mode 100644 index 0000000000..e517083058 --- /dev/null +++ b/src/lib/Persistence/Legacy/Content/Mapper/ResolveVirtualFieldSubscriber.php @@ -0,0 +1,154 @@ +converterRegistry = $converterRegistry; + $this->storageRegistry = $storageRegistry; + $this->contentGateway = $contentGateway; + } + + public static function getSubscribedEvents(): array + { + return [ + ResolveMissingFieldEvent::class => [ + ['persistExternalStorageField', -100], + ['resolveVirtualField', 0], + ] + ]; + } + + public function resolveVirtualField(ResolveMissingFieldEvent $event): void + { + if ($event->getField()) { + return; + } + + $content = $event->getContent(); + + try { + $emptyField = $this->createEmptyField( + $content->versionInfo, + $event->getFieldDefinition(), + $event->getLanguageCode() + ); + + $event->setField($emptyField); + } catch (NotFound $exception) { + return; + } + } + + public function persistExternalStorageField(ResolveMissingFieldEvent $event): void + { + $field = $event->getField(); + + if ($field && $field->id !== null) { + // Not a virtual field + return; + } + + $fieldDefinition = $event->getFieldDefinition(); + $storage = $this->storageRegistry->getStorage($fieldDefinition->fieldType); + + if ($storage instanceof NullStorage) { + // Not an external storage + return; + } + + $content = $event->getContent(); + + $field->id = $this->contentGateway->insertNewField( + $content, + $field, + $this->getDefaultStorageValue() + ); + + $storage->getFieldData( + $content->versionInfo, + $field, + $event->getContext() + ); + + $event->setField($field); + } + + /** + * @throws NotFound + */ + private function createEmptyField( + VersionInfo $versionInfo, + FieldDefinition $fieldDefinition, + string $languageCode + ): Field { + $field = new Field(); + $field->fieldDefinitionId = $fieldDefinition->id; + $field->type = $fieldDefinition->fieldType; + $field->value = $this->getDefaultValue($fieldDefinition); + $field->languageCode = $languageCode; + $field->versionNo = $versionInfo->versionNo; + + return $field; + } + + /** + * @throws NotFound + */ + private function getDefaultValue(FieldDefinition $fieldDefinition): FieldValue + { + $value = clone $fieldDefinition->defaultValue; + $storageValue = $this->getDefaultStorageValue(); + + $converter = $this->converterRegistry->getConverter($fieldDefinition->fieldType); + $converter->toStorageValue($value, $storageValue); + $converter->toFieldValue($storageValue, $value); + + return $value; + } + + private function getDefaultStorageValue(): StorageFieldValue + { + $storageValue = new StorageFieldValue(); + $storageValue->dataFloat = null; + $storageValue->dataInt = null; + $storageValue->dataText = ''; + $storageValue->sortKeyInt = 0; + $storageValue->sortKeyString = ''; + + return $storageValue; + } +} \ No newline at end of file