From 15057fa1bb6dfb1a91c58ab74087d4d94b459bbe Mon Sep 17 00:00:00 2001 From: Nattfarinn Date: Tue, 28 Nov 2023 10:21:47 +0100 Subject: [PATCH 1/8] WIP: Part I --- .../Legacy/Content/FieldHandler.php | 4 ++ src/lib/Persistence/Legacy/Content/Mapper.php | 53 +++++++++++++++++-- .../Legacy/Content/Type/Handler.php | 1 - .../storage_engines/legacy/content.yml | 1 + 4 files changed, 55 insertions(+), 4 deletions(-) diff --git a/src/lib/Persistence/Legacy/Content/FieldHandler.php b/src/lib/Persistence/Legacy/Content/FieldHandler.php index da16face3b..592fd861ba 100644 --- a/src/lib/Persistence/Legacy/Content/FieldHandler.php +++ b/src/lib/Persistence/Legacy/Content/FieldHandler.php @@ -151,6 +151,10 @@ protected function getEmptyField(FieldDefinition $fieldDefinition, $languageCode public function createExistingFieldsInNewVersion(Content $content) { foreach ($content->fields as $field) { + if ($field->id === null) { + // Virtual field with default value, skip creating field as it has no id + continue; + } $this->createExistingFieldInNewVersion($field, $content); } } diff --git a/src/lib/Persistence/Legacy/Content/Mapper.php b/src/lib/Persistence/Legacy/Content/Mapper.php index b7cf7823be..c5e107fc97 100644 --- a/src/lib/Persistence/Legacy/Content/Mapper.php +++ b/src/lib/Persistence/Legacy/Content/Mapper.php @@ -14,6 +14,8 @@ use Ibexa\Contracts\Core\Persistence\Content\Language\Handler as LanguageHandler; use Ibexa\Contracts\Core\Persistence\Content\Relation; use Ibexa\Contracts\Core\Persistence\Content\Relation\CreateStruct as RelationCreateStruct; +use Ibexa\Contracts\Core\Persistence\Content\Type\FieldDefinition; +use Ibexa\Contracts\Core\Persistence\Content\Type\Handler as ContentTypeHandler; use Ibexa\Contracts\Core\Persistence\Content\VersionInfo; use Ibexa\Core\Base\Exceptions\NotFoundException; use Ibexa\Core\Persistence\Legacy\Content\FieldValue\ConverterRegistry as Registry; @@ -39,16 +41,22 @@ class Mapper */ protected $languageHandler; + private ContentTypeHandler $contentTypeHandler; + /** * Creates a new mapper. * * @param \Ibexa\Core\Persistence\Legacy\Content\FieldValue\ConverterRegistry $converterRegistry * @param \Ibexa\Contracts\Core\Persistence\Content\Language\Handler $languageHandler */ - public function __construct(Registry $converterRegistry, LanguageHandler $languageHandler) - { + public function __construct( + Registry $converterRegistry, + LanguageHandler $languageHandler, + ContentTypeHandler $contentTypeHandler + ) { $this->converterRegistry = $converterRegistry; $this->languageHandler = $languageHandler; + $this->contentTypeHandler = $contentTypeHandler; } /** @@ -191,15 +199,23 @@ public function extractContentFromRows(array $rows, array $nameRows, $prefix = ' $contentInfos = []; $versionInfos = []; $fields = []; + $fieldDefinitions = []; foreach ($rows as $row) { $contentId = (int)$row["{$prefix}id"]; + $contentTypeId = (int)$row["{$prefix}contentclass_id"]; if (!isset($contentInfos[$contentId])) { $contentInfos[$contentId] = $this->extractContentInfoFromRow($row, $prefix); } if (!isset($versionInfos[$contentId])) { $versionInfos[$contentId] = []; } + if (!isset($fieldDefinitions[$contentId])) { + $contentType = $this->contentTypeHandler->load($contentTypeId); + foreach ($contentType->fieldDefinitions as $fieldDefinition) { + $fieldDefinitions[$contentId][$fieldDefinition->id] = $fieldDefinition; + } + } $versionId = (int)$row['ezcontentobject_version_id']; if (!isset($versionInfos[$contentId][$versionId])) { @@ -207,8 +223,10 @@ public function extractContentFromRows(array $rows, array $nameRows, $prefix = ' } $fieldId = (int)$row['ezcontentobject_attribute_id']; - if (!isset($fields[$contentId][$versionId][$fieldId])) { + $fieldDefinitionId = (int)$row["ezcontentobject_attribute_contentclassattribute_id"]; + if (!isset($fields[$contentId][$versionId][$fieldId]) && isset($fieldDefinitions[$contentId][$fieldDefinitionId])) { $fields[$contentId][$versionId][$fieldId] = $this->extractFieldFromRow($row); + unset($fieldDefinitions[$contentId][$fieldDefinitionId]); } } @@ -227,6 +245,15 @@ public function extractContentFromRows(array $rows, array $nameRows, $prefix = ' $content->versionInfo->names = $names; $content->versionInfo->contentInfo = $contentInfo; $content->fields = array_values($fields[$contentId][$versionId]); + + foreach ($fieldDefinitions[$contentId] as $fieldDefinition) { + $languageCode = $this->determineEmptyFieldLanguageCode($content); + $content->fields[] = $this->createEmptyField( + $fieldDefinition, + $languageCode + ); + } + $results[] = $content; } } @@ -578,6 +605,26 @@ public function createRelationFromCreateStruct(RelationCreateStruct $struct) return $relation; } + + private function createEmptyField(FieldDefinition $fieldDefinition, string $languageCode): Field + { + $field = new Field(); + $field->fieldDefinitionId = $fieldDefinition->id; + $field->type = $fieldDefinition->fieldType; + $field->value = $fieldDefinition->defaultValue; + $field->languageCode = $languageCode; + + return $field; + } + + private function determineEmptyFieldLanguageCode(Content $content): string + { + foreach ($content->fields as $field) { + return $field->languageCode; + } + + return $content->versionInfo->initialLanguageCode;; + } } class_alias(Mapper::class, 'eZ\Publish\Core\Persistence\Legacy\Content\Mapper'); diff --git a/src/lib/Persistence/Legacy/Content/Type/Handler.php b/src/lib/Persistence/Legacy/Content/Type/Handler.php index 8ade46c4bd..3573a35231 100644 --- a/src/lib/Persistence/Legacy/Content/Type/Handler.php +++ b/src/lib/Persistence/Legacy/Content/Type/Handler.php @@ -632,7 +632,6 @@ public function publish($contentTypeId) try { $fromType = $this->load($contentTypeId, Type::STATUS_DEFINED); - $this->updateHandler->updateContentObjects($fromType, $toType); $this->updateHandler->deleteOldType($fromType); } catch (Exception\TypeNotFound $e) { // If no old type is found, no updates are necessary to it diff --git a/src/lib/Resources/settings/storage_engines/legacy/content.yml b/src/lib/Resources/settings/storage_engines/legacy/content.yml index df3457e00e..639f675f3a 100644 --- a/src/lib/Resources/settings/storage_engines/legacy/content.yml +++ b/src/lib/Resources/settings/storage_engines/legacy/content.yml @@ -9,6 +9,7 @@ services: arguments: - '@Ibexa\Core\Persistence\Legacy\Content\FieldValue\ConverterRegistry' - '@ibexa.spi.persistence.legacy.language.handler' + - '@ibexa.spi.persistence.legacy.content_type.handler' Ibexa\Core\Persistence\Legacy\Content\Gateway\DoctrineDatabase.inner: class: Ibexa\Core\Persistence\Legacy\Content\Gateway\DoctrineDatabase From 42980545dc3e55f66ff3e2eacbe10c572c59cda2 Mon Sep 17 00:00:00 2001 From: Nattfarinn Date: Tue, 28 Nov 2023 10:24:40 +0100 Subject: [PATCH 2/8] WIP: Part II (Circular-reference) --- .../Type/Update/Handler/DoctrineDatabase.php | 11 ++------- .../Persistence/Legacy/Content/MapperTest.php | 24 +++++++++++++++---- .../Legacy/Content/HandlerContentSortTest.php | 1 + .../Legacy/Content/HandlerContentTest.php | 1 + 4 files changed, 23 insertions(+), 14 deletions(-) diff --git a/src/lib/Persistence/Legacy/Content/Type/Update/Handler/DoctrineDatabase.php b/src/lib/Persistence/Legacy/Content/Type/Update/Handler/DoctrineDatabase.php index 15d3d38558..0f5fd63171 100644 --- a/src/lib/Persistence/Legacy/Content/Type/Update/Handler/DoctrineDatabase.php +++ b/src/lib/Persistence/Legacy/Content/Type/Update/Handler/DoctrineDatabase.php @@ -23,21 +23,14 @@ final class DoctrineDatabase extends Handler /** @var \Ibexa\Core\Persistence\Legacy\Content\Type\Gateway */ protected $contentTypeGateway; - /** @var \Ibexa\Core\Persistence\Legacy\Content\Type\ContentUpdater */ - protected $contentUpdater; - - public function __construct(Gateway $contentTypeGateway, ContentUpdater $contentUpdater) + public function __construct(Gateway $contentTypeGateway) { $this->contentTypeGateway = $contentTypeGateway; - $this->contentUpdater = $contentUpdater; } public function updateContentObjects(Type $fromType, Type $toType): void { - $this->contentUpdater->applyUpdates( - $fromType->id, - $this->contentUpdater->determineActions($fromType, $toType) - ); + // Do nothing, content objects are no longer updated } public function deleteOldType(Type $fromType): void diff --git a/tests/lib/Persistence/Legacy/Content/MapperTest.php b/tests/lib/Persistence/Legacy/Content/MapperTest.php index 806767f9e4..7f8dbd3ebd 100644 --- a/tests/lib/Persistence/Legacy/Content/MapperTest.php +++ b/tests/lib/Persistence/Legacy/Content/MapperTest.php @@ -140,7 +140,7 @@ public function testConvertToStorageValue() $field->type = 'some-type'; $field->value = new FieldValue(); - $mapper = new Mapper($reg, $this->getLanguageHandler()); + $mapper = new Mapper($reg, $this->getLanguageHandler(), $this->getContentTypeHandler()); $res = $mapper->convertToStorageValue($field); $this->assertInstanceOf( @@ -178,7 +178,7 @@ public function testExtractContentFromRows() ] ); - $mapper = new Mapper($reg, $this->getLanguageHandler()); + $mapper = new Mapper($reg, $this->getLanguageHandler(), $this->getContentTypeHandler()); $result = $mapper->extractContentFromRows($rowsFixture, $nameRowsFixture); $this->assertEquals( @@ -206,7 +206,7 @@ public function testExtractContentFromRowsMultipleVersions() $rowsFixture = $this->getMultipleVersionsExtractFixture(); $nameRowsFixture = $this->getMultipleVersionsNamesExtractFixture(); - $mapper = new Mapper($reg, $this->getLanguageHandler()); + $mapper = new Mapper($reg, $this->getLanguageHandler(), $this->getContentTypeHandler()); $result = $mapper->extractContentFromRows($rowsFixture, $nameRowsFixture); $this->assertCount( @@ -351,7 +351,8 @@ public function testExtractContentInfoFromRow(array $fixtures, $prefix) $contentInfoReference = $this->getContentExtractReference()->versionInfo->contentInfo; $mapper = new Mapper( $this->getValueConverterRegistryMock(), - $this->getLanguageHandler() + $this->getLanguageHandler(), + $this->getContentTypeHandler() ); self::assertEquals($contentInfoReference, $mapper->extractContentInfoFromRow($fixtures, $prefix)); } @@ -508,7 +509,8 @@ protected function getMapper($valueConverter = null) { return new Mapper( $this->getValueConverterRegistryMock(), - $this->getLanguageHandler() + $this->getLanguageHandler(), + $this->getContentTypeHandler() ); } @@ -603,6 +605,18 @@ static function ($languageCode) use ($languages) { return $this->languageHandler; } + + protected function getContentTypeHandler(): Content\Type\Handler + { + $mock = $this->createMock(Content\Type\Handler::class); + $mock + ->method('load') + ->willReturn( + $this->createMock(Content\Type::class) + ); + + return $mock; + } } class_alias(MapperTest::class, 'eZ\Publish\Core\Persistence\Legacy\Tests\Content\MapperTest'); diff --git a/tests/lib/Search/Legacy/Content/HandlerContentSortTest.php b/tests/lib/Search/Legacy/Content/HandlerContentSortTest.php index 1194ceb488..a5fdb7eb59 100644 --- a/tests/lib/Search/Legacy/Content/HandlerContentSortTest.php +++ b/tests/lib/Search/Legacy/Content/HandlerContentSortTest.php @@ -101,6 +101,7 @@ protected function getContentMapperMock() [ $this->getFieldRegistry(), $this->getLanguageHandler(), + $this->getContentTypeHandler(), ] ) ->setMethods(['extractContentInfoFromRows']) diff --git a/tests/lib/Search/Legacy/Content/HandlerContentTest.php b/tests/lib/Search/Legacy/Content/HandlerContentTest.php index b5166e9a09..c4c279ef3f 100644 --- a/tests/lib/Search/Legacy/Content/HandlerContentTest.php +++ b/tests/lib/Search/Legacy/Content/HandlerContentTest.php @@ -200,6 +200,7 @@ protected function getContentMapperMock() [ $this->getConverterRegistry(), $this->getLanguageHandler(), + $this->getContentTypeHandler(), ] ) ->setMethods(['extractContentInfoFromRows']) From 56915768c512aa50695c5c8f99a39f4b683a3296 Mon Sep 17 00:00:00 2001 From: Nattfarinn Date: Tue, 28 Nov 2023 10:27:05 +0100 Subject: [PATCH 3/8] WIP: Part III (Playground test) --- .../Core/Repository/ProofOfConceptTest.php | 82 +++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 tests/integration/Core/Repository/ProofOfConceptTest.php diff --git a/tests/integration/Core/Repository/ProofOfConceptTest.php b/tests/integration/Core/Repository/ProofOfConceptTest.php new file mode 100644 index 0000000000..bc9de328e2 --- /dev/null +++ b/tests/integration/Core/Repository/ProofOfConceptTest.php @@ -0,0 +1,82 @@ +contentService = $this->getRepository()->getContentService(); + $this->contentTypeService = $this->getRepository()->getContentTypeService(); + $this->languageService = $this->getRepository()->getContentLanguageService(); + } + + public function testProofOfConcept() + { + $contentType = $this->contentTypeService->loadContentTypeByIdentifier('folder'); + + // Create content + $contentCreateStruct = $this->contentService->newContentCreateStruct($contentType, self::ENG_US); + $contentCreateStruct->setField('name', 'PoC', self::ENG_US); + $contentCreateStruct->setField('short_name', 'PoC', self::ENG_US); + $contentDraft = $this->contentService->createContent($contentCreateStruct); + $content = $this->contentService->publishVersion($contentDraft->getVersionInfo()); + + // Update content type definition + $contentTypeDraft = $this->contentTypeService->createContentTypeDraft($contentType); + $fieldDefCreateStruct = $this->contentTypeService->newFieldDefinitionCreateStruct( + 'poc_field', + 'ezstring' + ); + $fieldDefCreateStruct->names = [self::ENG_US => 'PoC Field']; + $fieldDefCreateStruct->descriptions = [self::ENG_US => 'PoC Field']; + $fieldDefCreateStruct->fieldGroup = 'content'; + $fieldDefCreateStruct->position = 2; + $fieldDefCreateStruct->isTranslatable = true; + $fieldDefCreateStruct->isRequired = true; + $fieldDefCreateStruct->isInfoCollector = false; + $fieldDefCreateStruct->validatorConfiguration = [ + 'StringLengthValidator' => [ + 'minStringLength' => 0, + 'maxStringLength' => 0, + ], + ]; + $fieldDefCreateStruct->fieldSettings = []; + $fieldDefCreateStruct->isSearchable = true; + $fieldDefCreateStruct->defaultValue = 'Default PoC Value'; + + $this->contentTypeService->addFieldDefinition($contentTypeDraft, $fieldDefCreateStruct); + $this->contentTypeService->publishContentTypeDraft($contentTypeDraft); + $contentType = $this->contentTypeService->loadContentType($contentTypeDraft->id); + + // Translate content + $contentDraft = $this->contentService->createContentDraft($content->contentInfo); + $contentUpdateStruct = $this->contentService->newContentUpdateStruct(); + $contentUpdateStruct->initialLanguageCode = self::ENG_GB; + $contentUpdateStruct->fields = $contentDraft->getFields(); + $contentUpdateStruct->setField('name', 'PoC GB', self::ENG_GB); + $this->contentService->updateContent($contentDraft->versionInfo, $contentUpdateStruct); + $content = $this->contentService->publishVersion($contentDraft->versionInfo); + } +} From ee0d373a83b7018a49a271070a7ee03543c838ab Mon Sep 17 00:00:00 2001 From: Nattfarinn Date: Wed, 29 Nov 2023 08:45:48 +0100 Subject: [PATCH 4/8] WIP: Part IV (circular reference) --- .../Resources/settings/storage_engines/legacy/content_type.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/src/lib/Resources/settings/storage_engines/legacy/content_type.yml b/src/lib/Resources/settings/storage_engines/legacy/content_type.yml index 06b1059ae8..a4c2d40a77 100644 --- a/src/lib/Resources/settings/storage_engines/legacy/content_type.yml +++ b/src/lib/Resources/settings/storage_engines/legacy/content_type.yml @@ -39,7 +39,6 @@ services: class: Ibexa\Core\Persistence\Legacy\Content\Type\Update\Handler\DoctrineDatabase arguments: - '@ibexa.persistence.legacy.content_type.gateway' - - '@Ibexa\Core\Persistence\Legacy\Content\Type\ContentUpdater' ibexa.persistence.legacy.content_type.update_handler: alias: Ibexa\Core\Persistence\Legacy\Content\Type\Update\Handler\DoctrineDatabase From e2585ae58c7ec82099aaf169f52ca0efe7070df5 Mon Sep 17 00:00:00 2001 From: Nattfarinn Date: Wed, 6 Dec 2023 22:29:21 +0100 Subject: [PATCH 5/8] WIP: Part V --- src/lib/Persistence/Legacy/Content/Mapper.php | 47 +++++++++---------- 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/src/lib/Persistence/Legacy/Content/Mapper.php b/src/lib/Persistence/Legacy/Content/Mapper.php index c5e107fc97..e12451f4aa 100644 --- a/src/lib/Persistence/Legacy/Content/Mapper.php +++ b/src/lib/Persistence/Legacy/Content/Mapper.php @@ -190,10 +190,13 @@ public function convertToStorageValue(Field $field) public function extractContentFromRows(array $rows, array $nameRows, $prefix = 'ezcontentobject_') { $versionedNameData = []; + $languageCodes = []; + foreach ($nameRows as $row) { - $contentId = (int)$row['ezcontentobject_name_contentobject_id']; - $versionNo = (int)$row['ezcontentobject_name_content_version']; - $versionedNameData[$contentId][$versionNo][$row['ezcontentobject_name_content_translation']] = $row['ezcontentobject_name_name']; + $contentId = (int)$row["{$prefix}name_contentobject_id"]; + $versionNo = (int)$row["{$prefix}name_content_version"]; + $versionedNameData[$contentId][$versionNo][$row["{$prefix}name_content_translation"]] = $row["{$prefix}name_name"]; + $languageCodes[] = $row["{$prefix}name_content_translation"]; } $contentInfos = []; @@ -210,23 +213,27 @@ public function extractContentFromRows(array $rows, array $nameRows, $prefix = ' if (!isset($versionInfos[$contentId])) { $versionInfos[$contentId] = []; } + if (!isset($fieldDefinitions[$contentId])) { $contentType = $this->contentTypeHandler->load($contentTypeId); foreach ($contentType->fieldDefinitions as $fieldDefinition) { - $fieldDefinitions[$contentId][$fieldDefinition->id] = $fieldDefinition; + foreach ($languageCodes as $languageCode) { + $fieldDefinitions[$contentId][$languageCode][$fieldDefinition->id] = $fieldDefinition; + } } } - $versionId = (int)$row['ezcontentobject_version_id']; + $versionId = (int)$row["{$prefix}version_id"]; if (!isset($versionInfos[$contentId][$versionId])) { $versionInfos[$contentId][$versionId] = $this->extractVersionInfoFromRow($row); } - $fieldId = (int)$row['ezcontentobject_attribute_id']; - $fieldDefinitionId = (int)$row["ezcontentobject_attribute_contentclassattribute_id"]; - if (!isset($fields[$contentId][$versionId][$fieldId]) && isset($fieldDefinitions[$contentId][$fieldDefinitionId])) { + $fieldId = (int)$row["{$prefix}attribute_id"]; + $fieldDefinitionId = (int)$row["{$prefix}attribute_contentclassattribute_id"]; + $languageCode = $row["{$prefix}attribute_language_code"]; + if (!isset($fields[$contentId][$versionId][$fieldId]) && isset($fieldDefinitions[$contentId][$languageCode][$fieldDefinitionId])) { $fields[$contentId][$versionId][$fieldId] = $this->extractFieldFromRow($row); - unset($fieldDefinitions[$contentId][$fieldDefinitionId]); + unset($fieldDefinitions[$contentId][$languageCode][$fieldDefinitionId]); } } @@ -246,12 +253,13 @@ public function extractContentFromRows(array $rows, array $nameRows, $prefix = ' $content->versionInfo->contentInfo = $contentInfo; $content->fields = array_values($fields[$contentId][$versionId]); - foreach ($fieldDefinitions[$contentId] as $fieldDefinition) { - $languageCode = $this->determineEmptyFieldLanguageCode($content); - $content->fields[] = $this->createEmptyField( - $fieldDefinition, - $languageCode - ); + foreach ($fieldDefinitions[$contentId] as $languageCode => $fieldDefinitions) { + foreach ($fieldDefinitions as $fieldDefinition) { + $content->fields[] = $this->createEmptyField( + $fieldDefinition, + $languageCode + ); + } } $results[] = $content; @@ -616,15 +624,6 @@ private function createEmptyField(FieldDefinition $fieldDefinition, string $lang return $field; } - - private function determineEmptyFieldLanguageCode(Content $content): string - { - foreach ($content->fields as $field) { - return $field->languageCode; - } - - return $content->versionInfo->initialLanguageCode;; - } } class_alias(Mapper::class, 'eZ\Publish\Core\Persistence\Legacy\Content\Mapper'); From e4032bf73d8cfd06aa825c1bc45f4f2de53ceb12 Mon Sep 17 00:00:00 2001 From: Nattfarinn Date: Tue, 12 Dec 2023 09:34:56 +0100 Subject: [PATCH 6/8] WIP: Part VI (Unit tests) --- src/lib/Persistence/Legacy/Content/Mapper.php | 14 ++--- .../Persistence/Legacy/Content/MapperTest.php | 49 +++++++++++++--- .../Content/Type/ContentTypeHandlerTest.php | 9 +-- .../Update/Handler/DoctrineDatabaseTest.php | 22 ++------ .../extract_content_from_rows_result.php | 56 +++++++++++++++++++ 5 files changed, 111 insertions(+), 39 deletions(-) diff --git a/src/lib/Persistence/Legacy/Content/Mapper.php b/src/lib/Persistence/Legacy/Content/Mapper.php index e12451f4aa..9ddbce1b92 100644 --- a/src/lib/Persistence/Legacy/Content/Mapper.php +++ b/src/lib/Persistence/Legacy/Content/Mapper.php @@ -206,6 +206,7 @@ public function extractContentFromRows(array $rows, array $nameRows, $prefix = ' foreach ($rows as $row) { $contentId = (int)$row["{$prefix}id"]; + $versionId = (int)$row["{$prefix}version_id"]; $contentTypeId = (int)$row["{$prefix}contentclass_id"]; if (!isset($contentInfos[$contentId])) { $contentInfos[$contentId] = $this->extractContentInfoFromRow($row, $prefix); @@ -214,16 +215,15 @@ public function extractContentFromRows(array $rows, array $nameRows, $prefix = ' $versionInfos[$contentId] = []; } - if (!isset($fieldDefinitions[$contentId])) { + if (!isset($fieldDefinitions[$contentId][$versionId])) { $contentType = $this->contentTypeHandler->load($contentTypeId); foreach ($contentType->fieldDefinitions as $fieldDefinition) { foreach ($languageCodes as $languageCode) { - $fieldDefinitions[$contentId][$languageCode][$fieldDefinition->id] = $fieldDefinition; + $fieldDefinitions[$contentId][$versionId][$languageCode][$fieldDefinition->id] = $fieldDefinition; } } } - $versionId = (int)$row["{$prefix}version_id"]; if (!isset($versionInfos[$contentId][$versionId])) { $versionInfos[$contentId][$versionId] = $this->extractVersionInfoFromRow($row); } @@ -231,9 +231,9 @@ public function extractContentFromRows(array $rows, array $nameRows, $prefix = ' $fieldId = (int)$row["{$prefix}attribute_id"]; $fieldDefinitionId = (int)$row["{$prefix}attribute_contentclassattribute_id"]; $languageCode = $row["{$prefix}attribute_language_code"]; - if (!isset($fields[$contentId][$versionId][$fieldId]) && isset($fieldDefinitions[$contentId][$languageCode][$fieldDefinitionId])) { + if (!isset($fields[$contentId][$versionId][$fieldId]) && isset($fieldDefinitions[$contentId][$versionId][$languageCode][$fieldDefinitionId])) { $fields[$contentId][$versionId][$fieldId] = $this->extractFieldFromRow($row); - unset($fieldDefinitions[$contentId][$languageCode][$fieldDefinitionId]); + unset($fieldDefinitions[$contentId][$versionId][$languageCode][$fieldDefinitionId]); } } @@ -253,8 +253,8 @@ public function extractContentFromRows(array $rows, array $nameRows, $prefix = ' $content->versionInfo->contentInfo = $contentInfo; $content->fields = array_values($fields[$contentId][$versionId]); - foreach ($fieldDefinitions[$contentId] as $languageCode => $fieldDefinitions) { - foreach ($fieldDefinitions as $fieldDefinition) { + foreach ($fieldDefinitions[$contentId][$versionId] as $languageCode => $versionFieldDefinitions) { + foreach ($versionFieldDefinitions as $fieldDefinition) { $content->fields[] = $this->createEmptyField( $fieldDefinition, $languageCode diff --git a/tests/lib/Persistence/Legacy/Content/MapperTest.php b/tests/lib/Persistence/Legacy/Content/MapperTest.php index 7f8dbd3ebd..a089fc5acb 100644 --- a/tests/lib/Persistence/Legacy/Content/MapperTest.php +++ b/tests/lib/Persistence/Legacy/Content/MapperTest.php @@ -6,6 +6,8 @@ */ namespace Ibexa\Tests\Core\Persistence\Legacy\Content; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\MockObject\MockType; use function count; use Ibexa\Contracts\Core\Persistence\Content; use Ibexa\Contracts\Core\Persistence\Content\ContentInfo; @@ -154,6 +156,12 @@ public function testExtractContentFromRows() $rowsFixture = $this->getContentExtractFixture(); $nameRowsFixture = $this->getNamesExtractFixture(); + $contentType = $this->getContentTypeFromRows($rowsFixture); + + /** @var MockObject $contentTypeHandlerMock */ + $contentTypeHandlerMock = $this->getContentTypeHandler(); + $contentTypeHandlerMock->method('load')->willReturn($contentType); + $convMock = $this->createMock(Converter::class); $convMock->expects($this->exactly(count($rowsFixture))) ->method('toFieldValue') @@ -178,7 +186,7 @@ public function testExtractContentFromRows() ] ); - $mapper = new Mapper($reg, $this->getLanguageHandler(), $this->getContentTypeHandler()); + $mapper = new Mapper($reg, $this->getLanguageHandler(), $contentTypeHandlerMock); $result = $mapper->extractContentFromRows($rowsFixture, $nameRowsFixture); $this->assertEquals( @@ -206,7 +214,13 @@ public function testExtractContentFromRowsMultipleVersions() $rowsFixture = $this->getMultipleVersionsExtractFixture(); $nameRowsFixture = $this->getMultipleVersionsNamesExtractFixture(); - $mapper = new Mapper($reg, $this->getLanguageHandler(), $this->getContentTypeHandler()); + $contentType = $this->getContentTypeFromRows($rowsFixture); + + /** @var MockObject $contentTypeHandlerMock */ + $contentTypeHandlerMock = $this->getContentTypeHandler(); + $contentTypeHandlerMock->method('load')->willReturn($contentType); + + $mapper = new Mapper($reg, $this->getLanguageHandler(), $contentTypeHandlerMock); $result = $mapper->extractContentFromRows($rowsFixture, $nameRowsFixture); $this->assertCount( @@ -608,14 +622,31 @@ static function ($languageCode) use ($languages) { protected function getContentTypeHandler(): Content\Type\Handler { - $mock = $this->createMock(Content\Type\Handler::class); - $mock - ->method('load') - ->willReturn( - $this->createMock(Content\Type::class) - ); + return $this->createMock(Content\Type\Handler::class); + } + + protected function getContentTypeFromRows(array $rows): Content\Type + { + $contentType = new Content\Type(); + $fieldDefinitions = []; + + foreach ($rows as $row) { + $fieldDefinitionId = $row['ezcontentobject_attribute_contentclassattribute_id']; + $fieldType = $row['ezcontentobject_attribute_data_type_string']; + + if (isset($fieldDefinitions[$fieldDefinitionId])) { + continue; + } + + $fieldDefinitions[$fieldDefinitionId] = new Content\Type\FieldDefinition([ + 'id' => $fieldDefinitionId, + 'fieldType' => $fieldType, + ]); + } + + $contentType->fieldDefinitions = array_values($fieldDefinitions); - return $mock; + return $contentType; } } diff --git a/tests/lib/Persistence/Legacy/Content/Type/ContentTypeHandlerTest.php b/tests/lib/Persistence/Legacy/Content/Type/ContentTypeHandlerTest.php index 2226bc1508..23bf963870 100644 --- a/tests/lib/Persistence/Legacy/Content/Type/ContentTypeHandlerTest.php +++ b/tests/lib/Persistence/Legacy/Content/Type/ContentTypeHandlerTest.php @@ -1005,12 +1005,9 @@ public function testPublish() $this->returnValue(new Type()) ); - $updateHandlerMock->expects($this->once()) - ->method('updateContentObjects') - ->with( - $this->isInstanceOf(Type::class), - $this->isInstanceOf(Type::class) - ); + $updateHandlerMock->expects($this->never()) + ->method('updateContentObjects'); + $updateHandlerMock->expects($this->once()) ->method('deleteOldType') ->with( diff --git a/tests/lib/Persistence/Legacy/Content/Type/Update/Handler/DoctrineDatabaseTest.php b/tests/lib/Persistence/Legacy/Content/Type/Update/Handler/DoctrineDatabaseTest.php index b051d3f509..9aaa10edee 100644 --- a/tests/lib/Persistence/Legacy/Content/Type/Update/Handler/DoctrineDatabaseTest.php +++ b/tests/lib/Persistence/Legacy/Content/Type/Update/Handler/DoctrineDatabaseTest.php @@ -37,23 +37,11 @@ public function testUpdateContentObjects() $updaterMock = $this->getContentUpdaterMock(); - $updaterMock->expects($this->once()) - ->method('determineActions') - ->with( - $this->isInstanceOf( - Type::class - ), - $this->isInstanceOf( - Type::class - ) - )->will($this->returnValue([])); - - $updaterMock->expects($this->once()) - ->method('applyUpdates') - ->with( - $this->equalTo(23), - $this->equalTo([]) - ); + $updaterMock->expects($this->never()) + ->method('determineActions'); + + $updaterMock->expects($this->never()) + ->method('applyUpdates'); $types = $this->getTypeFixtures(); diff --git a/tests/lib/Persistence/Legacy/Content/_fixtures/extract_content_from_rows_result.php b/tests/lib/Persistence/Legacy/Content/_fixtures/extract_content_from_rows_result.php index 5873f3f57a..ba0c381bf7 100644 --- a/tests/lib/Persistence/Legacy/Content/_fixtures/extract_content_from_rows_result.php +++ b/tests/lib/Persistence/Legacy/Content/_fixtures/extract_content_from_rows_result.php @@ -133,4 +133,60 @@ $content->fields[] = $field; +$field = new Field(); +$field->fieldDefinitionId = 183; +$field->type = 'ezstring'; +$field->value = new FieldValue(); +$field->languageCode = 'eng-GB'; + +$content->fields[] = $field; + +$field = new Field(); +$field->fieldDefinitionId = 184; +$field->type = 'ezstring'; +$field->value = new FieldValue(); +$field->languageCode = 'eng-GB'; + +$content->fields[] = $field; + +$field = new Field(); +$field->fieldDefinitionId = 185; +$field->type = 'ezauthor'; +$field->value = new FieldValue(); +$field->languageCode = 'eng-GB'; + +$content->fields[] = $field; + +$field = new Field(); +$field->fieldDefinitionId = 188; +$field->type = 'ezboolean'; +$field->value = new FieldValue(); +$field->languageCode = 'eng-GB'; + +$content->fields[] = $field; + +$field = new Field(); +$field->fieldDefinitionId = 189; +$field->type = 'ezimage'; +$field->value = new FieldValue(); +$field->languageCode = 'eng-GB'; + +$content->fields[] = $field; + +$field = new Field(); +$field->fieldDefinitionId = 191; +$field->type = 'ezdatetime'; +$field->value = new FieldValue(); +$field->languageCode = 'eng-GB'; + +$content->fields[] = $field; + +$field = new Field(); +$field->fieldDefinitionId = 192; +$field->type = 'ezdatetime'; +$field->value = new FieldValue(); +$field->languageCode = 'eng-GB'; + +$content->fields[] = $field; + return $content; From 9a3f2f47a9379defd00bb571435c9fd61714e56c Mon Sep 17 00:00:00 2001 From: Nattfarinn Date: Tue, 12 Dec 2023 15:21:24 +0100 Subject: [PATCH 7/8] WIP: Part VII (Tests) --- src/lib/Persistence/Legacy/Content/Mapper.php | 1 + .../Legacy/Content/StorageHandler.php | 2 +- .../Type/Update/Handler/DoctrineDatabase.php | 1 - .../DatabasePlatform/SqliteGateway.php | 30 +--- .../Repository/ContentTypeServiceTest.php | 60 ------- .../Core/Repository/ProofOfConceptTest.php | 82 --------- .../Persistence/Legacy/Content/MapperTest.php | 158 ++++++++++++++---- .../Legacy/Content/StorageHandlerTest.php | 1 + .../Type/Gateway/DoctrineDatabaseTest.php | 1 - .../Update/Handler/DoctrineDatabaseTest.php | 5 +- .../SharedGateway/GatewayFactoryTest.php | 2 +- tests/lib/Persistence/Legacy/TestCase.php | 2 +- 12 files changed, 133 insertions(+), 212 deletions(-) delete mode 100644 tests/integration/Core/Repository/ProofOfConceptTest.php diff --git a/src/lib/Persistence/Legacy/Content/Mapper.php b/src/lib/Persistence/Legacy/Content/Mapper.php index 9ddbce1b92..70454b1860 100644 --- a/src/lib/Persistence/Legacy/Content/Mapper.php +++ b/src/lib/Persistence/Legacy/Content/Mapper.php @@ -253,6 +253,7 @@ public function extractContentFromRows(array $rows, array $nameRows, $prefix = ' $content->versionInfo->contentInfo = $contentInfo; $content->fields = array_values($fields[$contentId][$versionId]); + /** @var string $languageCode */ foreach ($fieldDefinitions[$contentId][$versionId] as $languageCode => $versionFieldDefinitions) { foreach ($versionFieldDefinitions as $fieldDefinition) { $content->fields[] = $this->createEmptyField( diff --git a/src/lib/Persistence/Legacy/Content/StorageHandler.php b/src/lib/Persistence/Legacy/Content/StorageHandler.php index 475f6a1e98..621f033ad2 100644 --- a/src/lib/Persistence/Legacy/Content/StorageHandler.php +++ b/src/lib/Persistence/Legacy/Content/StorageHandler.php @@ -79,7 +79,7 @@ public function copyFieldData(VersionInfo $versionInfo, Field $field, Field $ori public function getFieldData(VersionInfo $versionInfo, Field $field) { $storage = $this->storageRegistry->getStorage($field->type); - if ($storage->hasFieldData()) { + if ($storage->hasFieldData() && $field->id !== null) { $storage->getFieldData($versionInfo, $field, $this->context); } } diff --git a/src/lib/Persistence/Legacy/Content/Type/Update/Handler/DoctrineDatabase.php b/src/lib/Persistence/Legacy/Content/Type/Update/Handler/DoctrineDatabase.php index 0f5fd63171..d27416712d 100644 --- a/src/lib/Persistence/Legacy/Content/Type/Update/Handler/DoctrineDatabase.php +++ b/src/lib/Persistence/Legacy/Content/Type/Update/Handler/DoctrineDatabase.php @@ -9,7 +9,6 @@ namespace Ibexa\Core\Persistence\Legacy\Content\Type\Update\Handler; use Ibexa\Contracts\Core\Persistence\Content\Type; -use Ibexa\Core\Persistence\Legacy\Content\Type\ContentUpdater; use Ibexa\Core\Persistence\Legacy\Content\Type\Gateway; use Ibexa\Core\Persistence\Legacy\Content\Type\Update\Handler; diff --git a/src/lib/Persistence/Legacy/SharedGateway/DatabasePlatform/SqliteGateway.php b/src/lib/Persistence/Legacy/SharedGateway/DatabasePlatform/SqliteGateway.php index 7b87d22156..410f92eb58 100644 --- a/src/lib/Persistence/Legacy/SharedGateway/DatabasePlatform/SqliteGateway.php +++ b/src/lib/Persistence/Legacy/SharedGateway/DatabasePlatform/SqliteGateway.php @@ -8,8 +8,6 @@ namespace Ibexa\Core\Persistence\Legacy\SharedGateway\DatabasePlatform; -use Doctrine\DBAL\Connection; -use Doctrine\DBAL\FetchMode; use Ibexa\Core\Base\Exceptions\DatabaseException; use Ibexa\Core\Persistence\Legacy\SharedGateway\Gateway; @@ -20,39 +18,19 @@ final class SqliteGateway implements Gateway */ private const FATAL_ERROR_CODE = 7; - /** @var \Doctrine\DBAL\Connection */ - private $connection; - - /** @var \Doctrine\DBAL\Platforms\AbstractPlatform */ - private $databasePlatform; - /** @var int[] */ private $lastInsertedIds = []; - /** - * @throws \Doctrine\DBAL\DBALException - */ - public function __construct(Connection $connection) - { - $this->connection = $connection; - $this->databasePlatform = $connection->getDatabasePlatform(); - } - public function getColumnNextIntegerValue( string $tableName, string $columnName, string $sequenceName ): ?int { - $query = $this->connection->createQueryBuilder(); - $query - ->select($this->databasePlatform->getMaxExpression($columnName)) - ->from($tableName); - - $lastId = (int)$query->execute()->fetch(FetchMode::COLUMN); + $lastId = $this->lastInsertedIds[$sequenceName] ?? 0; + $nextId = (int)hrtime(true); - $this->lastInsertedIds[$sequenceName] = $lastId + 1; - - return $this->lastInsertedIds[$sequenceName]; + // $lastId === $nextId shouldn't happen using high-resolution time, but better safe than sorry + return $this->lastInsertedIds[$sequenceName] = $lastId === $nextId ? $nextId + 1 : $nextId; } /** diff --git a/tests/integration/Core/Repository/ContentTypeServiceTest.php b/tests/integration/Core/Repository/ContentTypeServiceTest.php index 476cfdaf4c..12ce05fc4b 100644 --- a/tests/integration/Core/Repository/ContentTypeServiceTest.php +++ b/tests/integration/Core/Repository/ContentTypeServiceTest.php @@ -2085,66 +2085,6 @@ public function testRemoveFieldDefinitionRemovesFieldFromContentRemoved($data) ); } - /** - * @covers \Ibexa\Contracts\Core\Repository\ContentTypeService::removeFieldDefinition() - */ - public function testRemoveFieldDefinitionRemovesOrphanedRelations(): void - { - $repository = $this->getRepository(); - - $contentTypeService = $repository->getContentTypeService(); - $contentService = $repository->getContentService(); - - // Create ContentType - $contentTypeDraft = $this->createContentTypeDraft([$this->getRelationFieldDefinition()]); - $contentTypeService->publishContentTypeDraft($contentTypeDraft); - $publishedType = $contentTypeService->loadContentType($contentTypeDraft->id); - - // Create Content with Relation - $contentDraft = $this->createContentDraft(); - $publishedVersion = $contentService->publishVersion($contentDraft->versionInfo); - - $newDraft = $contentService->createContentDraft($publishedVersion->contentInfo); - $updateStruct = $contentService->newContentUpdateStruct(); - $updateStruct->setField('relation', 14, 'eng-US'); - $contentDraft = $contentService->updateContent($newDraft->versionInfo, $updateStruct); - $publishedContent = $contentService->publishVersion($contentDraft->versionInfo); - - // Remove field definition from ContentType - $contentTypeDraft = $contentTypeService->createContentTypeDraft($publishedType); - $relationField = $contentTypeDraft->getFieldDefinition('relation'); - $contentTypeService->removeFieldDefinition($contentTypeDraft, $relationField); - $contentTypeService->publishContentTypeDraft($contentTypeDraft); - - // Load Content - $content = $contentService->loadContent($publishedContent->contentInfo->id); - - $this->assertCount(0, $contentService->loadRelations($content->versionInfo)); - } - - private function getRelationFieldDefinition(): FieldDefinitionCreateStruct - { - $repository = $this->getRepository(); - - $contentTypeService = $repository->getContentTypeService(); - - $relationFieldCreate = $contentTypeService->newFieldDefinitionCreateStruct( - 'relation', - 'ezobjectrelation' - ); - $relationFieldCreate->names = ['eng-US' => 'Relation']; - $relationFieldCreate->descriptions = ['eng-US' => 'Relation to any Content']; - $relationFieldCreate->fieldGroup = 'blog-content'; - $relationFieldCreate->position = 3; - $relationFieldCreate->isTranslatable = false; - $relationFieldCreate->isRequired = false; - $relationFieldCreate->isInfoCollector = false; - $relationFieldCreate->validatorConfiguration = []; - $relationFieldCreate->isSearchable = false; - - return $relationFieldCreate; - } - /** * Test for the addFieldDefinition() method. * diff --git a/tests/integration/Core/Repository/ProofOfConceptTest.php b/tests/integration/Core/Repository/ProofOfConceptTest.php deleted file mode 100644 index bc9de328e2..0000000000 --- a/tests/integration/Core/Repository/ProofOfConceptTest.php +++ /dev/null @@ -1,82 +0,0 @@ -contentService = $this->getRepository()->getContentService(); - $this->contentTypeService = $this->getRepository()->getContentTypeService(); - $this->languageService = $this->getRepository()->getContentLanguageService(); - } - - public function testProofOfConcept() - { - $contentType = $this->contentTypeService->loadContentTypeByIdentifier('folder'); - - // Create content - $contentCreateStruct = $this->contentService->newContentCreateStruct($contentType, self::ENG_US); - $contentCreateStruct->setField('name', 'PoC', self::ENG_US); - $contentCreateStruct->setField('short_name', 'PoC', self::ENG_US); - $contentDraft = $this->contentService->createContent($contentCreateStruct); - $content = $this->contentService->publishVersion($contentDraft->getVersionInfo()); - - // Update content type definition - $contentTypeDraft = $this->contentTypeService->createContentTypeDraft($contentType); - $fieldDefCreateStruct = $this->contentTypeService->newFieldDefinitionCreateStruct( - 'poc_field', - 'ezstring' - ); - $fieldDefCreateStruct->names = [self::ENG_US => 'PoC Field']; - $fieldDefCreateStruct->descriptions = [self::ENG_US => 'PoC Field']; - $fieldDefCreateStruct->fieldGroup = 'content'; - $fieldDefCreateStruct->position = 2; - $fieldDefCreateStruct->isTranslatable = true; - $fieldDefCreateStruct->isRequired = true; - $fieldDefCreateStruct->isInfoCollector = false; - $fieldDefCreateStruct->validatorConfiguration = [ - 'StringLengthValidator' => [ - 'minStringLength' => 0, - 'maxStringLength' => 0, - ], - ]; - $fieldDefCreateStruct->fieldSettings = []; - $fieldDefCreateStruct->isSearchable = true; - $fieldDefCreateStruct->defaultValue = 'Default PoC Value'; - - $this->contentTypeService->addFieldDefinition($contentTypeDraft, $fieldDefCreateStruct); - $this->contentTypeService->publishContentTypeDraft($contentTypeDraft); - $contentType = $this->contentTypeService->loadContentType($contentTypeDraft->id); - - // Translate content - $contentDraft = $this->contentService->createContentDraft($content->contentInfo); - $contentUpdateStruct = $this->contentService->newContentUpdateStruct(); - $contentUpdateStruct->initialLanguageCode = self::ENG_GB; - $contentUpdateStruct->fields = $contentDraft->getFields(); - $contentUpdateStruct->setField('name', 'PoC GB', self::ENG_GB); - $this->contentService->updateContent($contentDraft->versionInfo, $contentUpdateStruct); - $content = $this->contentService->publishVersion($contentDraft->versionInfo); - } -} diff --git a/tests/lib/Persistence/Legacy/Content/MapperTest.php b/tests/lib/Persistence/Legacy/Content/MapperTest.php index a089fc5acb..c4989999b4 100644 --- a/tests/lib/Persistence/Legacy/Content/MapperTest.php +++ b/tests/lib/Persistence/Legacy/Content/MapperTest.php @@ -6,8 +6,6 @@ */ namespace Ibexa\Tests\Core\Persistence\Legacy\Content; -use PHPUnit\Framework\MockObject\MockObject; -use PHPUnit\Framework\MockObject\MockType; use function count; use Ibexa\Contracts\Core\Persistence\Content; use Ibexa\Contracts\Core\Persistence\Content\ContentInfo; @@ -158,65 +156,125 @@ public function testExtractContentFromRows() $contentType = $this->getContentTypeFromRows($rowsFixture); - /** @var MockObject $contentTypeHandlerMock */ $contentTypeHandlerMock = $this->getContentTypeHandler(); $contentTypeHandlerMock->method('load')->willReturn($contentType); - $convMock = $this->createMock(Converter::class); - $convMock->expects($this->exactly(count($rowsFixture))) - ->method('toFieldValue') - ->with( - $this->isInstanceOf( - StorageFieldValue::class - ) - )->will( - $this->returnValue( - new FieldValue() - ) - ); + $reg = $this->getFieldRegistry([ + 'ezauthor', + 'ezstring', + 'ezboolean', + 'ezimage', + 'ezdatetime', + 'ezkeyword', + ], count($rowsFixture)); - $reg = new Registry( + $mapper = new Mapper($reg, $this->getLanguageHandler(), $contentTypeHandlerMock); + $result = $mapper->extractContentFromRows($rowsFixture, $nameRowsFixture); + + $this->assertEquals( [ - 'ezauthor' => $convMock, - 'ezstring' => $convMock, - 'ezboolean' => $convMock, - 'ezimage' => $convMock, - 'ezdatetime' => $convMock, - 'ezkeyword' => $convMock, - ] + $this->getContentExtractReference(), + ], + $result ); + } + + public function testExtractContentFromRowsWithNewFieldDefinitions(): void + { + $rowsFixture = $this->getContentExtractFixture(); + $nameRowsFixture = $this->getNamesExtractFixture(); + + $contentType = $this->getContentTypeFromRows($rowsFixture); + $contentType->fieldDefinitions[] = new Content\Type\FieldDefinition([ + 'fieldType' => 'eznumber', + ]); + + $contentTypeHandlerMock = $this->getContentTypeHandler(); + $contentTypeHandlerMock->method('load')->willReturn($contentType); + + $reg = $this->getFieldRegistry([ + 'ezauthor', + 'ezstring', + 'ezboolean', + 'ezimage', + 'ezdatetime', + 'ezkeyword', + 'eznumber', + ], count($rowsFixture)); $mapper = new Mapper($reg, $this->getLanguageHandler(), $contentTypeHandlerMock); $result = $mapper->extractContentFromRows($rowsFixture, $nameRowsFixture); + $expectedContent = $this->getContentExtractReference(); + $expectedContent->fields[] = new Field([ + 'type' => 'eznumber', + 'languageCode' => 'eng-GB', + 'value' => new FieldValue(), + ]); + $expectedContent->fields[] = new Field([ + 'type' => 'eznumber', + 'languageCode' => 'eng-US', + 'value' => new FieldValue(), + ]); + $this->assertEquals( [ - $this->getContentExtractReference(), + $expectedContent, ], $result ); } - public function testExtractContentFromRowsMultipleVersions() + public function testExtractContentFromRowsWithRemovedFieldDefinitions(): void { - $convMock = $this->createMock(Converter::class); - $convMock->expects($this->any()) - ->method('toFieldValue') - ->will($this->returnValue(new FieldValue())); + $rowsFixture = $this->getContentExtractFixture(); + $nameRowsFixture = $this->getNamesExtractFixture(); + + $contentType = $this->getContentTypeFromRows($rowsFixture); + $contentType->fieldDefinitions = array_filter($contentType->fieldDefinitions, static function (Content\Type\FieldDefinition $fieldDefinition) { + // ref. fixtures, ezauthor + return $fieldDefinition->id !== 185; + }); - $reg = new Registry( + $contentTypeHandlerMock = $this->getContentTypeHandler(); + $contentTypeHandlerMock->method('load')->willReturn($contentType); + + $reg = $this->getFieldRegistry([ + 'ezstring', + 'ezboolean', + 'ezimage', + 'ezdatetime', + 'ezkeyword', + ], count($rowsFixture) - 1); + + $mapper = new Mapper($reg, $this->getLanguageHandler(), $contentTypeHandlerMock); + $result = $mapper->extractContentFromRows($rowsFixture, $nameRowsFixture); + + $expectedContent = $this->getContentExtractReference(); + $expectedContent->fields = array_values(array_filter($expectedContent->fields, static function (Field $field) { + return $field->fieldDefinitionId !== 185; + })); + + $this->assertEquals( [ - 'ezstring' => $convMock, - 'ezdatetime' => $convMock, - ] + $expectedContent, + ], + $result ); + } + + public function testExtractContentFromRowsMultipleVersions() + { + $reg = $this->getFieldRegistry([ + 'ezstring', + 'ezdatetime', + ]); $rowsFixture = $this->getMultipleVersionsExtractFixture(); $nameRowsFixture = $this->getMultipleVersionsNamesExtractFixture(); $contentType = $this->getContentTypeFromRows($rowsFixture); - /** @var MockObject $contentTypeHandlerMock */ $contentTypeHandlerMock = $this->getContentTypeHandler(); $contentTypeHandlerMock->method('load')->willReturn($contentType); @@ -247,6 +305,30 @@ public function testExtractContentFromRowsMultipleVersions() ); } + /** + * @param string[] $fields + */ + private function getFieldRegistry( + array $fields = [], + int $expectedConverterCalls = null + ): Registry { + $convMock = $this->createMock(Converter::class); + $convMock->expects( + $expectedConverterCalls === null + ? $this->any() + : $this->exactly($expectedConverterCalls) + ) + ->method('toFieldValue') + ->will($this->returnValue(new FieldValue())); + + $converters = []; + foreach ($fields as $field) { + $converters[$field] = $convMock; + } + + return new Registry($converters); + } + public function testCreateCreateStructFromContent() { $time = time(); @@ -620,11 +702,17 @@ static function ($languageCode) use ($languages) { return $this->languageHandler; } - protected function getContentTypeHandler(): Content\Type\Handler + /** + * @return Content\Type\Handler|\PHPUnit\Framework\MockObject\MockObject + */ + protected function getContentTypeHandler() { return $this->createMock(Content\Type\Handler::class); } + /** + * @param array> $rows + */ protected function getContentTypeFromRows(array $rows): Content\Type { $contentType = new Content\Type(); diff --git a/tests/lib/Persistence/Legacy/Content/StorageHandlerTest.php b/tests/lib/Persistence/Legacy/Content/StorageHandlerTest.php index 3ea01062bc..e856faf104 100644 --- a/tests/lib/Persistence/Legacy/Content/StorageHandlerTest.php +++ b/tests/lib/Persistence/Legacy/Content/StorageHandlerTest.php @@ -95,6 +95,7 @@ public function testGetFieldDataAvailable() ->will($this->returnValue($storageMock)); $field = new Field(); + $field->id = 123; $field->type = 'foobar'; $field->value = new FieldValue(); diff --git a/tests/lib/Persistence/Legacy/Content/Type/Gateway/DoctrineDatabaseTest.php b/tests/lib/Persistence/Legacy/Content/Type/Gateway/DoctrineDatabaseTest.php index f6b066ea9a..f06999a73e 100644 --- a/tests/lib/Persistence/Legacy/Content/Type/Gateway/DoctrineDatabaseTest.php +++ b/tests/lib/Persistence/Legacy/Content/Type/Gateway/DoctrineDatabaseTest.php @@ -462,7 +462,6 @@ public function testInsertType($column, $expectation) public static function getTypeCreationContentClassNameExpectations() { return [ - ['contentclass_id', [1, 1]], ['contentclass_version', [0, 0]], ['language_id', [3, 4]], ['language_locale', ['eng-US', 'eng-GB']], diff --git a/tests/lib/Persistence/Legacy/Content/Type/Update/Handler/DoctrineDatabaseTest.php b/tests/lib/Persistence/Legacy/Content/Type/Update/Handler/DoctrineDatabaseTest.php index 9aaa10edee..dd2a5dd2f6 100644 --- a/tests/lib/Persistence/Legacy/Content/Type/Update/Handler/DoctrineDatabaseTest.php +++ b/tests/lib/Persistence/Legacy/Content/Type/Update/Handler/DoctrineDatabaseTest.php @@ -109,10 +109,7 @@ protected function getTypeFixtures() */ protected function getUpdateHandler() { - return new DoctrineDatabase( - $this->getGatewayMock(), - $this->getContentUpdaterMock() - ); + return new DoctrineDatabase($this->getGatewayMock()); } /** diff --git a/tests/lib/Persistence/Legacy/SharedGateway/GatewayFactoryTest.php b/tests/lib/Persistence/Legacy/SharedGateway/GatewayFactoryTest.php index a75aab39c8..090c366bf9 100644 --- a/tests/lib/Persistence/Legacy/SharedGateway/GatewayFactoryTest.php +++ b/tests/lib/Persistence/Legacy/SharedGateway/GatewayFactoryTest.php @@ -30,7 +30,7 @@ final class GatewayFactoryTest extends TestCase public function setUp(): void { $gateways = [ - 'sqlite' => new SqliteGateway($this->createMock(Connection::class)), + 'sqlite' => new SqliteGateway(), ]; $this->factory = new GatewayFactory( diff --git a/tests/lib/Persistence/Legacy/TestCase.php b/tests/lib/Persistence/Legacy/TestCase.php index 72b9593222..887861cfe7 100644 --- a/tests/lib/Persistence/Legacy/TestCase.php +++ b/tests/lib/Persistence/Legacy/TestCase.php @@ -114,7 +114,7 @@ final public function getSharedGateway(): SharedGateway\Gateway $factory = new SharedGateway\GatewayFactory( new SharedGateway\DatabasePlatform\FallbackGateway($connection), [ - 'sqlite' => new SharedGateway\DatabasePlatform\SqliteGateway($connection), + 'sqlite' => new SharedGateway\DatabasePlatform\SqliteGateway(), ] ); From 29c30b002e0fc01433a0c82dc169619c4d81d38d Mon Sep 17 00:00:00 2001 From: Nattfarinn Date: Tue, 12 Dec 2023 15:24:19 +0100 Subject: [PATCH 8/8] WIP: Part VIII (Phpstan) --- phpstan-baseline.neon | 22 +--------------------- 1 file changed, 1 insertion(+), 21 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index ac2649e3e0..27ada4c81c 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -8860,16 +8860,6 @@ parameters: count: 1 path: src/lib/FieldType/Author/Value.php - - - message: "#^Cannot access offset 'fileSize' on array\\|void\\.$#" - count: 1 - path: src/lib/FieldType/BinaryBase/BinaryBaseStorage.php - - - - message: "#^Cannot access offset 'id' on array\\|void\\.$#" - count: 4 - path: src/lib/FieldType/BinaryBase/BinaryBaseStorage.php - - message: "#^Class Ibexa\\\\Core\\\\FieldType\\\\BinaryBase\\\\BinaryBaseStorage extends generic class Ibexa\\\\Contracts\\\\Core\\\\FieldType\\\\GatewayBasedStorage but does not specify its types\\: T$#" count: 1 @@ -15585,11 +15575,6 @@ parameters: count: 1 path: src/lib/Persistence/Legacy/Content/FieldValue/Converter/ImageConverter.php - - - message: "#^Cannot call method addAttribute\\(\\) on SimpleXMLElement\\|null\\.$#" - count: 1 - path: src/lib/Persistence/Legacy/Content/FieldValue/Converter/ImageConverter.php - - message: "#^Cannot call method getAttribute\\(\\) on DOMElement\\|null\\.$#" count: 6 @@ -18900,11 +18885,6 @@ parameters: count: 1 path: src/lib/Persistence/Legacy/Setting/Gateway/ExceptionConversion.php - - - message: "#^Cannot call method fetch\\(\\) on Doctrine\\\\DBAL\\\\ForwardCompatibility\\\\Result\\|int\\|string\\.$#" - count: 1 - path: src/lib/Persistence/Legacy/SharedGateway/DatabasePlatform/SqliteGateway.php - - message: "#^Argument of an invalid type array\\\\|iterable supplied for foreach, only iterables are supported\\.$#" count: 1 @@ -29377,7 +29357,7 @@ parameters: - message: "#^Parameter \\#2 \\$fieldDefinition of method Ibexa\\\\Contracts\\\\Core\\\\Repository\\\\ContentTypeService\\:\\:removeFieldDefinition\\(\\) expects Ibexa\\\\Contracts\\\\Core\\\\Repository\\\\Values\\\\ContentType\\\\FieldDefinition, Ibexa\\\\Contracts\\\\Core\\\\Repository\\\\Values\\\\ContentType\\\\FieldDefinition\\|null given\\.$#" - count: 7 + count: 6 path: tests/integration/Core/Repository/ContentTypeServiceTest.php -