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 - 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..70454b1860 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; } /** @@ -182,18 +190,24 @@ 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 = []; $versionInfos = []; $fields = []; + $fieldDefinitions = []; 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); } @@ -201,14 +215,25 @@ public function extractContentFromRows(array $rows, array $nameRows, $prefix = ' $versionInfos[$contentId] = []; } - $versionId = (int)$row['ezcontentobject_version_id']; + if (!isset($fieldDefinitions[$contentId][$versionId])) { + $contentType = $this->contentTypeHandler->load($contentTypeId); + foreach ($contentType->fieldDefinitions as $fieldDefinition) { + foreach ($languageCodes as $languageCode) { + $fieldDefinitions[$contentId][$versionId][$languageCode][$fieldDefinition->id] = $fieldDefinition; + } + } + } + if (!isset($versionInfos[$contentId][$versionId])) { $versionInfos[$contentId][$versionId] = $this->extractVersionInfoFromRow($row); } - $fieldId = (int)$row['ezcontentobject_attribute_id']; - if (!isset($fields[$contentId][$versionId][$fieldId])) { + $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][$versionId][$languageCode][$fieldDefinitionId])) { $fields[$contentId][$versionId][$fieldId] = $this->extractFieldFromRow($row); + unset($fieldDefinitions[$contentId][$versionId][$languageCode][$fieldDefinitionId]); } } @@ -227,6 +252,17 @@ public function extractContentFromRows(array $rows, array $nameRows, $prefix = ' $content->versionInfo->names = $names; $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( + $fieldDefinition, + $languageCode + ); + } + } + $results[] = $content; } } @@ -578,6 +614,17 @@ 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; + } } class_alias(Mapper::class, 'eZ\Publish\Core\Persistence\Legacy\Content\Mapper'); 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/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/Persistence/Legacy/Content/Type/Update/Handler/DoctrineDatabase.php b/src/lib/Persistence/Legacy/Content/Type/Update/Handler/DoctrineDatabase.php index 15d3d38558..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; @@ -23,21 +22,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/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/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 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 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/lib/Persistence/Legacy/Content/MapperTest.php b/tests/lib/Persistence/Legacy/Content/MapperTest.php index 806767f9e4..c4989999b4 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( @@ -154,59 +154,131 @@ public function testExtractContentFromRows() $rowsFixture = $this->getContentExtractFixture(); $nameRowsFixture = $this->getNamesExtractFixture(); - $convMock = $this->createMock(Converter::class); - $convMock->expects($this->exactly(count($rowsFixture))) - ->method('toFieldValue') - ->with( - $this->isInstanceOf( - StorageFieldValue::class - ) - )->will( - $this->returnValue( - new FieldValue() - ) - ); + $contentType = $this->getContentTypeFromRows($rowsFixture); + + $contentTypeHandlerMock = $this->getContentTypeHandler(); + $contentTypeHandlerMock->method('load')->willReturn($contentType); + + $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(); - $mapper = new Mapper($reg, $this->getLanguageHandler()); + $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; + }); + + $contentTypeHandlerMock = $this->getContentTypeHandler(); + $contentTypeHandlerMock->method('load')->willReturn($contentType); + + $reg = $this->getFieldRegistry([ + 'ezstring', + 'ezboolean', + 'ezimage', + 'ezdatetime', + 'ezkeyword', + ], count($rowsFixture) - 1); - $reg = new Registry( + $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(); - $mapper = new Mapper($reg, $this->getLanguageHandler()); + $contentType = $this->getContentTypeFromRows($rowsFixture); + + $contentTypeHandlerMock = $this->getContentTypeHandler(); + $contentTypeHandlerMock->method('load')->willReturn($contentType); + + $mapper = new Mapper($reg, $this->getLanguageHandler(), $contentTypeHandlerMock); $result = $mapper->extractContentFromRows($rowsFixture, $nameRowsFixture); $this->assertCount( @@ -233,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(); @@ -351,7 +447,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 +605,8 @@ protected function getMapper($valueConverter = null) { return new Mapper( $this->getValueConverterRegistryMock(), - $this->getLanguageHandler() + $this->getLanguageHandler(), + $this->getContentTypeHandler() ); } @@ -603,6 +701,41 @@ static function ($languageCode) use ($languages) { return $this->languageHandler; } + + /** + * @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(); + $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 $contentType; + } } class_alias(MapperTest::class, 'eZ\Publish\Core\Persistence\Legacy\Tests\Content\MapperTest'); 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/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/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 b051d3f509..dd2a5dd2f6 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(); @@ -121,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/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; 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(), ] ); 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'])