From b1957452f1aaa6ddab3f8994fe679b98ccb2aa8b Mon Sep 17 00:00:00 2001 From: Nattfarinn Date: Fri, 19 Jul 2024 10:26:29 +0200 Subject: [PATCH 1/7] IBX-8492: Fixed replacing only field of Content Type with virtual field --- eZ/Publish/Core/Persistence/Legacy/Content/Mapper.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/eZ/Publish/Core/Persistence/Legacy/Content/Mapper.php b/eZ/Publish/Core/Persistence/Legacy/Content/Mapper.php index dafce22757..1f30da460c 100644 --- a/eZ/Publish/Core/Persistence/Legacy/Content/Mapper.php +++ b/eZ/Publish/Core/Persistence/Legacy/Content/Mapper.php @@ -313,9 +313,10 @@ private function buildContentObjects( $content->versionInfo = $versionInfo; $content->versionInfo->names = $names; $content->versionInfo->contentInfo = $contentInfo; - $content->fields = array_values($fields[$contentId][$versionId]); + $content->fields = array_values($fields[$contentId][$versionId] ?? []); + + $missingVersionFieldDefinitions = $missingFieldDefinitions[$contentId][$versionId] ?? []; - $missingVersionFieldDefinitions = $missingFieldDefinitions[$contentId][$versionId]; foreach ($missingVersionFieldDefinitions as $languageCode => $versionFieldDefinitions) { foreach ($versionFieldDefinitions as $fieldDefinition) { $event = $this->eventDispatcher->dispatch( From 18b7369cff355b4b6788bcc72a145934a40d916f Mon Sep 17 00:00:00 2001 From: Nattfarinn Date: Wed, 24 Jul 2024 08:45:59 +0200 Subject: [PATCH 2/7] IBX-8562: Fixed flooding content attributes table with duplicates --- .../Core/Persistence/Legacy/Content/Handler.php | 8 ++++++-- .../Core/Persistence/Legacy/Content/Mapper.php | 13 +++++++++---- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/eZ/Publish/Core/Persistence/Legacy/Content/Handler.php b/eZ/Publish/Core/Persistence/Legacy/Content/Handler.php index 0fb6e39a2b..f045281f00 100644 --- a/eZ/Publish/Core/Persistence/Legacy/Content/Handler.php +++ b/eZ/Publish/Core/Persistence/Legacy/Content/Handler.php @@ -320,7 +320,9 @@ public function load($id, $version = null, array $translations = null) $this->contentGateway->loadVersionedNameData([[ 'id' => $id, 'version' => $rows[0]['ezcontentobject_version_version'], - ]]) + ]]), + 'ezcontentobject_', + $translations ); $content = $contentObjects[0]; unset($rows, $contentObjects); @@ -371,7 +373,9 @@ public function loadContentList(array $contentIds, array $translations = null): try { $contentList = $this->mapper->extractContentFromRows( $contentItemsRow, - $contentItemNameData[$contentId] + $contentItemNameData[$contentId], + 'ezcontentobject_', + $translations ); $contentItems[$contentId] = $contentList[0]; } catch (Exception $e) { diff --git a/eZ/Publish/Core/Persistence/Legacy/Content/Mapper.php b/eZ/Publish/Core/Persistence/Legacy/Content/Mapper.php index 1f30da460c..6a357afe69 100644 --- a/eZ/Publish/Core/Persistence/Legacy/Content/Mapper.php +++ b/eZ/Publish/Core/Persistence/Legacy/Content/Mapper.php @@ -220,6 +220,7 @@ public function convertToStorageValue(Field $field) * @param array> $rows * @param array> $nameRows * @param string $prefix + * @param array|null $translations * * @return \eZ\Publish\SPI\Persistence\Content[] * @@ -228,7 +229,8 @@ public function convertToStorageValue(Field $field) public function extractContentFromRows( array $rows, array $nameRows, - string $prefix = 'ezcontentobject_' + string $prefix = 'ezcontentobject_', + ?array $translations = null ): array { $versionedNameData = []; @@ -245,7 +247,8 @@ public function extractContentFromRows( $fieldDefinitions = $this->loadCachedVersionFieldDefinitionsPerLanguage( $rows, - $prefix + $prefix, + $translations ); foreach ($rows as $row) { @@ -348,7 +351,8 @@ private function buildContentObjects( */ private function loadCachedVersionFieldDefinitionsPerLanguage( array $rows, - string $prefix + string $prefix, + ?array $translations = null ): array { $fieldDefinitions = []; $contentTypes = []; @@ -364,7 +368,8 @@ private function loadCachedVersionFieldDefinitionsPerLanguage( continue; } - $languageCodes = $this->extractLanguageCodesFromMask($languageMask, $allLanguages); + $allLanguagesCodes = $this->extractLanguageCodesFromMask($languageMask, $allLanguages); + $languageCodes = empty($translations) ? $allLanguagesCodes : array_intersect($translations, $allLanguagesCodes); $contentTypes[$contentTypeId] = $contentTypes[$contentTypeId] ?? $this->contentTypeHandler->load($contentTypeId); $contentType = $contentTypes[$contentTypeId]; foreach ($contentType->fieldDefinitions as $fieldDefinition) { From 36b051b78b0af99b6bf1f13658d4759032ffb689 Mon Sep 17 00:00:00 2001 From: Nattfarinn Date: Wed, 31 Jul 2024 08:40:08 +0200 Subject: [PATCH 3/7] fix: Makes single field contents editable after field switch --- .../Legacy/Content/FieldHandler.php | 12 ++++++-- .../Persistence/Legacy/Content/Handler.php | 13 +++++++++ .../Persistence/Legacy/Content/Mapper.php | 5 +++- .../Tests/Content/ContentHandlerTest.php | 28 ++++++++++++++++++- .../Legacy/Tests/Content/FieldHandlerTest.php | 22 ++++++--------- .../storage_engines/legacy/content.yml | 1 + 6 files changed, 63 insertions(+), 18 deletions(-) diff --git a/eZ/Publish/Core/Persistence/Legacy/Content/FieldHandler.php b/eZ/Publish/Core/Persistence/Legacy/Content/FieldHandler.php index dba486b78e..0be175d5f4 100644 --- a/eZ/Publish/Core/Persistence/Legacy/Content/FieldHandler.php +++ b/eZ/Publish/Core/Persistence/Legacy/Content/FieldHandler.php @@ -332,7 +332,7 @@ public function updateFields(Content $content, UpdateStruct $updateStruct, Type if (isset($updateFieldMap[$fieldDefinition->id][$languageCode])) { $field = clone $updateFieldMap[$fieldDefinition->id][$languageCode]; $field->versionNo = $content->versionInfo->versionNo; - if (isset($field->id) && array_key_exists($field->languageCode, $existingLanguageCodes)) { + if (null !== $field->id && array_key_exists($field->languageCode, $existingLanguageCodes)) { $this->updateField($field, $content); $updatedFields[$fieldDefinition->id][$languageCode] = $field; } else { @@ -358,6 +358,14 @@ public function updateFields(Content $content, UpdateStruct $updateStruct, Type // also update copied field data // Register for processing after all given fields are updated $nonTranslatableCopiesUpdateSet[$fieldDefinition->id][] = $languageCode; + } elseif (isset($contentFieldMap[$fieldDefinition->id][$languageCode])) { + $field = clone $contentFieldMap[$fieldDefinition->id][$languageCode]; + $field->versionNo = $content->versionInfo->versionNo; + // Persist virtual field + if (null === $field->id) { + $this->updateField($field, $content); + $updatedFields[$fieldDefinition->id][$languageCode] = $field; + } } // If no above conditions were met - do nothing @@ -417,7 +425,7 @@ protected function updateCopiedField(Field $field, Field $updateField, Field $or * @param \eZ\Publish\SPI\Persistence\Content\Field[] $fields * @param array $languageCodes * - * @return \eZ\Publish\SPI\Persistence\Content\Field[][] + * @return array> */ protected function getFieldMap(array $fields, &$languageCodes = null) { diff --git a/eZ/Publish/Core/Persistence/Legacy/Content/Handler.php b/eZ/Publish/Core/Persistence/Legacy/Content/Handler.php index f045281f00..677f75af20 100644 --- a/eZ/Publish/Core/Persistence/Legacy/Content/Handler.php +++ b/eZ/Publish/Core/Persistence/Legacy/Content/Handler.php @@ -15,6 +15,7 @@ use eZ\Publish\SPI\Persistence\Content\CreateStruct; use eZ\Publish\SPI\Persistence\Content\Field; use eZ\Publish\SPI\Persistence\Content\Handler as BaseContentHandler; +use eZ\Publish\SPI\Persistence\Content\Language\Handler as LanguageHandler; use eZ\Publish\SPI\Persistence\Content\MetadataUpdateStruct; use eZ\Publish\SPI\Persistence\Content\Relation\CreateStruct as RelationCreateStruct; use eZ\Publish\SPI\Persistence\Content\Type\Handler as ContentTypeHandler; @@ -84,6 +85,8 @@ class Handler implements BaseContentHandler */ protected $treeHandler; + protected LanguageHandler $languageHandler; + /** @var \Psr\Log\LoggerInterface */ private $logger; @@ -109,6 +112,7 @@ public function __construct( UrlAliasGateway $urlAliasGateway, ContentTypeHandler $contentTypeHandler, TreeHandler $treeHandler, + LanguageHandler $languageHandler, LoggerInterface $logger = null ) { $this->contentGateway = $contentGateway; @@ -119,6 +123,7 @@ public function __construct( $this->urlAliasGateway = $urlAliasGateway; $this->contentTypeHandler = $contentTypeHandler; $this->treeHandler = $treeHandler; + $this->languageHandler = $languageHandler; $this->logger = null !== $logger ? $logger : new NullLogger(); } @@ -275,6 +280,14 @@ public function createDraftFromVersion($contentId, $srcVersion, $userId, ?string // Clone fields from previous version and append them to the new one $this->fieldHandler->createExistingFieldsInNewVersion($content); + // Persist virtual fields + $contentType = $this->contentTypeHandler->load($content->versionInfo->contentInfo->contentTypeId); + $this->fieldHandler->updateFields($content, new UpdateStruct([ + 'initialLanguageId' => $this->languageHandler->loadByLanguageCode( + $content->versionInfo->initialLanguageCode + )->id, + ]), $contentType); + // Create relations for new version $relations = $this->contentGateway->loadRelations($contentId, $srcVersion); foreach ($relations as $relation) { diff --git a/eZ/Publish/Core/Persistence/Legacy/Content/Mapper.php b/eZ/Publish/Core/Persistence/Legacy/Content/Mapper.php index 6a357afe69..ed9e8a8dbc 100644 --- a/eZ/Publish/Core/Persistence/Legacy/Content/Mapper.php +++ b/eZ/Publish/Core/Persistence/Legacy/Content/Mapper.php @@ -345,6 +345,8 @@ private function buildContentObjects( } /** + * @param string[]|null $translations + * * @phpstan-return TVersionedLanguageFieldDefinitionsMap * * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException @@ -374,7 +376,8 @@ private function loadCachedVersionFieldDefinitionsPerLanguage( $contentType = $contentTypes[$contentTypeId]; foreach ($contentType->fieldDefinitions as $fieldDefinition) { foreach ($languageCodes as $languageCode) { - $id = $fieldDefinition->id; + $id = (int)$fieldDefinition->id; + $languageCode = (string)$languageCode; $fieldDefinitions[$contentId][$versionId][$languageCode][$id] = $fieldDefinition; } } diff --git a/eZ/Publish/Core/Persistence/Legacy/Tests/Content/ContentHandlerTest.php b/eZ/Publish/Core/Persistence/Legacy/Tests/Content/ContentHandlerTest.php index ce2720aab0..69548ce248 100644 --- a/eZ/Publish/Core/Persistence/Legacy/Tests/Content/ContentHandlerTest.php +++ b/eZ/Publish/Core/Persistence/Legacy/Tests/Content/ContentHandlerTest.php @@ -11,6 +11,7 @@ use eZ\Publish\Core\Persistence\Legacy\Content\FieldHandler; use eZ\Publish\Core\Persistence\Legacy\Content\Gateway as ContentGateway; use eZ\Publish\Core\Persistence\Legacy\Content\Handler; +use eZ\Publish\Core\Persistence\Legacy\Content\Language\Handler as LanguageHandler; use eZ\Publish\Core\Persistence\Legacy\Content\Location\Gateway as LocationGateway; use eZ\Publish\Core\Persistence\Legacy\Content\Mapper; use eZ\Publish\Core\Persistence\Legacy\Content\TreeHandler; @@ -108,6 +109,8 @@ class ContentHandlerTest extends TestCase */ protected $contentTypeHandlerMock; + protected LanguageHandler $languageHandlerMock; + /** * @covers \eZ\Publish\Core\Persistence\Legacy\Content\Handler::create * @@ -384,6 +387,8 @@ public function testCreateDraftFromVersion() $mapperMock = $this->getMapperMock(); $gatewayMock = $this->getGatewayMock(); $fieldHandlerMock = $this->getFieldHandlerMock(); + $languageHandlerMock = $this->getLanguageHandlerMock(); + $contentTypeHandlerMock = $this->getContentTypeHandlerMock(); $handler->expects($this->once()) ->method('load') @@ -402,11 +407,18 @@ public function testCreateDraftFromVersion() [ 'names' => [], 'versionNo' => 3, + 'contentInfo' => new ContentInfo(), ] ) ) ); + $languageHandlerMock->method('loadByLanguageCode') + ->willReturn(new Content\Language()); + + $contentTypeHandlerMock->method('load') + ->willReturn(new Type()); + $gatewayMock->expects($this->once()) ->method('insertVersion') ->with( @@ -1538,7 +1550,8 @@ protected function getContentHandler() $this->getSlugConverterMock(), $this->getUrlAliasGatewayMock(), $this->getContentTypeHandlerMock(), - $this->getTreeHandlerMock() + $this->getTreeHandlerMock(), + $this->getLanguageHandlerMock(), ); } @@ -1566,6 +1579,7 @@ protected function getPartlyMockedHandler(array $methods) $this->getUrlAliasGatewayMock(), $this->getContentTypeHandlerMock(), $this->getTreeHandlerMock(), + $this->getLanguageHandlerMock(), ] ) ->getMock(); @@ -1599,6 +1613,18 @@ protected function getContentTypeHandlerMock() return $this->contentTypeHandlerMock; } + /** + * @return \PHPUnit\Framework\MockObject\MockObject|\eZ\Publish\Core\Persistence\Legacy\Content\Language\Handler + */ + protected function getLanguageHandlerMock(): LanguageHandler + { + if (!isset($this->languageHandlerMock)) { + $this->languageHandlerMock = $this->createMock(LanguageHandler::class); + } + + return $this->languageHandlerMock; + } + /** * Returns a FieldHandler mock. * diff --git a/eZ/Publish/Core/Persistence/Legacy/Tests/Content/FieldHandlerTest.php b/eZ/Publish/Core/Persistence/Legacy/Tests/Content/FieldHandlerTest.php index d784832cad..93b010529c 100644 --- a/eZ/Publish/Core/Persistence/Legacy/Tests/Content/FieldHandlerTest.php +++ b/eZ/Publish/Core/Persistence/Legacy/Tests/Content/FieldHandlerTest.php @@ -633,7 +633,7 @@ public function assertUpdateFieldsForInitialLanguage($storageHandlerUpdatesField $callNo = 0; $fieldValue = new FieldValue(); $fieldsToCopy = []; - foreach ([1, 2, 3] as $fieldDefinitionId) { + foreach ([1, 2, 3] as $id => $fieldDefinitionId) { $field = new Field( [ 'fieldDefinitionId' => $fieldDefinitionId, @@ -646,6 +646,7 @@ public function assertUpdateFieldsForInitialLanguage($storageHandlerUpdatesField // These fields are copied from main language if ($fieldDefinitionId == 2 || $fieldDefinitionId == 3) { $originalField = clone $field; + $originalField->id = $fieldDefinitionId; $originalField->languageCode = 'eng-GB'; $fieldsToCopy[] = [ 'copy' => clone $field, @@ -845,20 +846,13 @@ protected function getContentSingleLanguageFixture() $field->value = new FieldValue(); $field->languageCode = 'eng-GB'; - $firstField = clone $field; - $firstField->fieldDefinitionId = 1; - - $secondField = clone $field; - $secondField->fieldDefinitionId = 2; - - $thirdField = clone $field; - $thirdField->fieldDefinitionId = 3; + foreach ([1, 2, 3] as $id) { + $contentField = clone $field; + $contentField->id = $id; + $contentField->fieldDefinitionId = $id; - $content->fields = [ - $firstField, - $secondField, - $thirdField, - ]; + $content->fields[] = $contentField; + } return $content; } diff --git a/eZ/Publish/Core/settings/storage_engines/legacy/content.yml b/eZ/Publish/Core/settings/storage_engines/legacy/content.yml index 58c0de94b0..2a956461b7 100644 --- a/eZ/Publish/Core/settings/storage_engines/legacy/content.yml +++ b/eZ/Publish/Core/settings/storage_engines/legacy/content.yml @@ -68,5 +68,6 @@ services: - "@ezpublish.persistence.legacy.url_alias.gateway" - "@ezpublish.spi.persistence.legacy.content_type.handler" - "@ezpublish.persistence.legacy.tree_handler" + - "@ezpublish.spi.persistence.legacy.language.handler" - "@logger" lazy: true From df28a0df23c1dd77a135d93e311424fea6736cfe Mon Sep 17 00:00:00 2001 From: Nattfarinn Date: Wed, 31 Jul 2024 09:19:46 +0200 Subject: [PATCH 4/7] fix: Downgrade to PHP 7.3 --- eZ/Publish/Core/Persistence/Legacy/Content/Handler.php | 5 ++++- .../Persistence/Legacy/Tests/Content/ContentHandlerTest.php | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/eZ/Publish/Core/Persistence/Legacy/Content/Handler.php b/eZ/Publish/Core/Persistence/Legacy/Content/Handler.php index 677f75af20..66b81eeeef 100644 --- a/eZ/Publish/Core/Persistence/Legacy/Content/Handler.php +++ b/eZ/Publish/Core/Persistence/Legacy/Content/Handler.php @@ -85,7 +85,10 @@ class Handler implements BaseContentHandler */ protected $treeHandler; - protected LanguageHandler $languageHandler; + /** + * @var \eZ\Publish\SPI\Persistence\Content\Language\Handler + */ + protected $languageHandler; /** @var \Psr\Log\LoggerInterface */ private $logger; diff --git a/eZ/Publish/Core/Persistence/Legacy/Tests/Content/ContentHandlerTest.php b/eZ/Publish/Core/Persistence/Legacy/Tests/Content/ContentHandlerTest.php index 69548ce248..d815e4c2ee 100644 --- a/eZ/Publish/Core/Persistence/Legacy/Tests/Content/ContentHandlerTest.php +++ b/eZ/Publish/Core/Persistence/Legacy/Tests/Content/ContentHandlerTest.php @@ -109,7 +109,10 @@ class ContentHandlerTest extends TestCase */ protected $contentTypeHandlerMock; - protected LanguageHandler $languageHandlerMock; + /** + * @var \eZ\Publish\Core\Persistence\Legacy\Content\Language\Handler + */ + protected $languageHandlerMock; /** * @covers \eZ\Publish\Core\Persistence\Legacy\Content\Handler::create From b0ca85faeecaaac434600671a6e562417017f4d0 Mon Sep 17 00:00:00 2001 From: Nattfarinn Date: Fri, 2 Aug 2024 08:27:04 +0200 Subject: [PATCH 5/7] fix: Create new field instead of updating it --- eZ/Publish/Core/Persistence/Legacy/Content/FieldHandler.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/eZ/Publish/Core/Persistence/Legacy/Content/FieldHandler.php b/eZ/Publish/Core/Persistence/Legacy/Content/FieldHandler.php index 0be175d5f4..3c16602c2b 100644 --- a/eZ/Publish/Core/Persistence/Legacy/Content/FieldHandler.php +++ b/eZ/Publish/Core/Persistence/Legacy/Content/FieldHandler.php @@ -363,8 +363,7 @@ public function updateFields(Content $content, UpdateStruct $updateStruct, Type $field->versionNo = $content->versionInfo->versionNo; // Persist virtual field if (null === $field->id) { - $this->updateField($field, $content); - $updatedFields[$fieldDefinition->id][$languageCode] = $field; + $this->createNewField($field, $content); } } From 1f45c9e84f29f351fcb84f7b73f433a4d62419b3 Mon Sep 17 00:00:00 2001 From: Nattfarinn Date: Wed, 7 Aug 2024 09:45:04 +0200 Subject: [PATCH 6/7] fix: Code review --- eZ/Publish/Core/Persistence/Legacy/Content/Handler.php | 2 ++ .../Persistence/Legacy/Tests/Content/ContentHandlerTest.php | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/eZ/Publish/Core/Persistence/Legacy/Content/Handler.php b/eZ/Publish/Core/Persistence/Legacy/Content/Handler.php index 66b81eeeef..430f3b7b8a 100644 --- a/eZ/Publish/Core/Persistence/Legacy/Content/Handler.php +++ b/eZ/Publish/Core/Persistence/Legacy/Content/Handler.php @@ -263,6 +263,8 @@ public function publish($contentId, $versionNo, MetadataUpdateStruct $metaDataUp * @param string|null $languageCode * * @return \eZ\Publish\SPI\Persistence\Content + * + * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException */ public function createDraftFromVersion($contentId, $srcVersion, $userId, ?string $languageCode = null) { diff --git a/eZ/Publish/Core/Persistence/Legacy/Tests/Content/ContentHandlerTest.php b/eZ/Publish/Core/Persistence/Legacy/Tests/Content/ContentHandlerTest.php index d815e4c2ee..133e8904f5 100644 --- a/eZ/Publish/Core/Persistence/Legacy/Tests/Content/ContentHandlerTest.php +++ b/eZ/Publish/Core/Persistence/Legacy/Tests/Content/ContentHandlerTest.php @@ -110,9 +110,9 @@ class ContentHandlerTest extends TestCase protected $contentTypeHandlerMock; /** - * @var \eZ\Publish\Core\Persistence\Legacy\Content\Language\Handler + * @var \PHPUnit\Framework\MockObject\MockObject&\eZ\Publish\Core\Persistence\Legacy\Content\Language\Handler */ - protected $languageHandlerMock; + private $languageHandlerMock; /** * @covers \eZ\Publish\Core\Persistence\Legacy\Content\Handler::create @@ -1617,7 +1617,7 @@ protected function getContentTypeHandlerMock() } /** - * @return \PHPUnit\Framework\MockObject\MockObject|\eZ\Publish\Core\Persistence\Legacy\Content\Language\Handler + * @return \PHPUnit\Framework\MockObject\MockObject&\eZ\Publish\Core\Persistence\Legacy\Content\Language\Handler */ protected function getLanguageHandlerMock(): LanguageHandler { From e72fd7549f761058fed8ba9340572d54fab844d6 Mon Sep 17 00:00:00 2001 From: Nattfarinn Date: Wed, 7 Aug 2024 09:59:40 +0200 Subject: [PATCH 7/7] fix: Replace null comparison with isset --- eZ/Publish/Core/Persistence/Legacy/Content/FieldHandler.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eZ/Publish/Core/Persistence/Legacy/Content/FieldHandler.php b/eZ/Publish/Core/Persistence/Legacy/Content/FieldHandler.php index 3c16602c2b..5bb2dc0460 100644 --- a/eZ/Publish/Core/Persistence/Legacy/Content/FieldHandler.php +++ b/eZ/Publish/Core/Persistence/Legacy/Content/FieldHandler.php @@ -332,7 +332,7 @@ public function updateFields(Content $content, UpdateStruct $updateStruct, Type if (isset($updateFieldMap[$fieldDefinition->id][$languageCode])) { $field = clone $updateFieldMap[$fieldDefinition->id][$languageCode]; $field->versionNo = $content->versionInfo->versionNo; - if (null !== $field->id && array_key_exists($field->languageCode, $existingLanguageCodes)) { + if (isset($field->id) && array_key_exists($field->languageCode, $existingLanguageCodes)) { $this->updateField($field, $content); $updatedFields[$fieldDefinition->id][$languageCode] = $field; } else {