From cf98c55a0eaea83871b9537950645b59013e7001 Mon Sep 17 00:00:00 2001 From: Alexander Schranz Date: Thu, 14 Oct 2021 09:58:17 +0200 Subject: [PATCH] Add Webspace select to Settings Tab --- .../DataMapper/WebspaceDataMapper.php | 46 +++++++++ Content/Domain/Model/WebspaceInterface.php | 25 +++++ Content/Domain/Model/WebspaceTrait.php | 53 ++++++++++ .../Doctrine/MetadataLoader.php | 6 ++ .../Sulu/Page/Select/WebspaceSelect.php | 42 ++++++++ Resources/config/data-mapper.xml | 4 + .../config/forms/content_settings_author.xml | 3 +- .../forms/content_settings_webspace.xml | 47 +++++++++ Resources/config/services.xml | 7 ++ Resources/translations/admin.de.json | 6 +- Resources/translations/admin.en.json | 6 +- .../Entity/ExampleDimensionContent.php | 5 +- .../Integration/ExampleControllerTest.php | 9 +- .../Integration/responses/example_get.json | 4 +- .../Integration/responses/example_post.json | 4 +- .../responses/example_post_publish.json | 4 +- .../example_post_trigger_unpublish.json | 4 +- .../Integration/responses/example_put.json | 6 +- .../DataMapper/WebspaceDataMapperTest.php | 96 +++++++++++++++++++ .../Domain/Model/WebspaceTraitTest.php | 44 +++++++++ .../Doctrine/MetadataLoaderTest.php | 14 +++ 21 files changed, 422 insertions(+), 13 deletions(-) create mode 100644 Content/Application/ContentDataMapper/DataMapper/WebspaceDataMapper.php create mode 100644 Content/Domain/Model/WebspaceInterface.php create mode 100644 Content/Domain/Model/WebspaceTrait.php create mode 100644 Content/Infrastructure/Sulu/Page/Select/WebspaceSelect.php create mode 100644 Resources/config/forms/content_settings_webspace.xml create mode 100644 Tests/Unit/Content/Application/ContentDataMapper/DataMapper/WebspaceDataMapperTest.php create mode 100644 Tests/Unit/Content/Domain/Model/WebspaceTraitTest.php diff --git a/Content/Application/ContentDataMapper/DataMapper/WebspaceDataMapper.php b/Content/Application/ContentDataMapper/DataMapper/WebspaceDataMapper.php new file mode 100644 index 00000000..efa22b10 --- /dev/null +++ b/Content/Application/ContentDataMapper/DataMapper/WebspaceDataMapper.php @@ -0,0 +1,46 @@ +setWebspaceData($localizedDimensionContent, $data); + } + + /** + * @param mixed[] $data + */ + private function setWebspaceData(WebspaceInterface $dimensionContent, array $data): void + { + if (\array_key_exists('mainWebspace', $data)) { + $dimensionContent->setMainWebspace($data['mainWebspace']); + } + + if (\array_key_exists('additionalWebspaces', $data)) { + $dimensionContent->setAdditionalWebspaces($data['additionalWebspaces'] ?: []); + } + } +} diff --git a/Content/Domain/Model/WebspaceInterface.php b/Content/Domain/Model/WebspaceInterface.php new file mode 100644 index 00000000..3c4bbcb5 --- /dev/null +++ b/Content/Domain/Model/WebspaceInterface.php @@ -0,0 +1,25 @@ +mainWebspace; + } + + public function setMainWebspace(?string $mainWebspace): void + { + $this->mainWebspace = $mainWebspace; + } + + /** + * @return string[] + */ + public function getAdditionalWebspaces(): array + { + return $this->additionalWebspaces ?: []; + } + + /** + * @param string[] + */ + public function setAdditionalWebspaces(array $additionalWebspaces): void + { + $this->additionalWebspaces = $additionalWebspaces; + } +} diff --git a/Content/Infrastructure/Doctrine/MetadataLoader.php b/Content/Infrastructure/Doctrine/MetadataLoader.php index 54601194..92c893d8 100644 --- a/Content/Infrastructure/Doctrine/MetadataLoader.php +++ b/Content/Infrastructure/Doctrine/MetadataLoader.php @@ -25,6 +25,7 @@ use Sulu\Bundle\ContentBundle\Content\Domain\Model\ExcerptInterface; use Sulu\Bundle\ContentBundle\Content\Domain\Model\SeoInterface; use Sulu\Bundle\ContentBundle\Content\Domain\Model\TemplateInterface; +use Sulu\Bundle\ContentBundle\Content\Domain\Model\WebspaceInterface; use Sulu\Bundle\ContentBundle\Content\Domain\Model\WorkflowInterface; use Sulu\Bundle\MediaBundle\Entity\MediaInterface; use Sulu\Bundle\TagBundle\Tag\TagInterface; @@ -94,6 +95,11 @@ public function loadClassMetadata(LoadClassMetadataEventArgs $event): void $this->addManyToMany($event, $metadata, 'excerptCategories', CategoryInterface::class, 'category_id'); } + if ($reflection->implementsInterface(WebspaceInterface::class)) { + $this->addField($metadata, 'mainWebspace', 'string', ['nullable' => true]); + $this->addField($metadata, 'additionalWebspaces', 'json', ['nullable' => true]); + } + if ($reflection->implementsInterface(AuthorInterface::class)) { $this->addField($metadata, 'authored', 'datetime_immutable', ['nullable' => true]); $this->addManyToOne($event, $metadata, 'author', ContactInterface::class, true); diff --git a/Content/Infrastructure/Sulu/Page/Select/WebspaceSelect.php b/Content/Infrastructure/Sulu/Page/Select/WebspaceSelect.php new file mode 100644 index 00000000..57a4ad35 --- /dev/null +++ b/Content/Infrastructure/Sulu/Page/Select/WebspaceSelect.php @@ -0,0 +1,42 @@ +webspaceManager = $webspaceManager; + } + + public function getValues(): array + { + $values = []; + foreach ($this->webspaceManager->getWebspaceCollection() as $webspace) { + $values[] = [ + 'name' => $webspace->getKey(), + 'title' => $webspace->getName(), + ]; + } + + return $values; + } +} diff --git a/Resources/config/data-mapper.xml b/Resources/config/data-mapper.xml index d5362cdd..c8000462 100644 --- a/Resources/config/data-mapper.xml +++ b/Resources/config/data-mapper.xml @@ -23,6 +23,10 @@ + + + + diff --git a/Resources/config/forms/content_settings_author.xml b/Resources/config/forms/content_settings_author.xml index 920dc16c..f08a3260 100644 --- a/Resources/config/forms/content_settings_author.xml +++ b/Resources/config/forms/content_settings_author.xml @@ -5,7 +5,7 @@ > content_settings_author - +
@@ -18,6 +18,7 @@ sulu_content.authored_date + sulu_content.author diff --git a/Resources/config/forms/content_settings_webspace.xml b/Resources/config/forms/content_settings_webspace.xml new file mode 100644 index 00000000..608135a8 --- /dev/null +++ b/Resources/config/forms/content_settings_webspace.xml @@ -0,0 +1,47 @@ + +
+ content_settings_webspace + + + + +
+ + sulu_content.main_webspace + + + + + + sulu_content.main_webspace + + + + + + + + + + sulu_content.additional_webspaces + + + + + + + +
+
+ diff --git a/Resources/config/services.xml b/Resources/config/services.xml index 362934e1..2275591c 100644 --- a/Resources/config/services.xml +++ b/Resources/config/services.xml @@ -26,6 +26,13 @@ + + + diff --git a/Resources/translations/admin.de.json b/Resources/translations/admin.de.json index 0b5da4a9..f02a4868 100644 --- a/Resources/translations/admin.de.json +++ b/Resources/translations/admin.de.json @@ -3,6 +3,8 @@ "sulu_content.excerpt": "Auszug & Taxonomien", "sulu_content.content": "Inhalt", "sulu_content.published": "Veröffentlicht am", - "sulu_content.author": "Author", - "sulu_page.authored_date": "Authored Date" + "sulu_content.author": "Autor", + "sulu_content.authored_date": "Verfasst am", + "sulu_content.main_webspace": "Hauptwebspace", + "sulu_content.additional_webspaces": "Weitere Webspaces" } diff --git a/Resources/translations/admin.en.json b/Resources/translations/admin.en.json index c9f009de..ad2c529d 100644 --- a/Resources/translations/admin.en.json +++ b/Resources/translations/admin.en.json @@ -3,6 +3,8 @@ "sulu_content.excerpt": "Excerpt & Taxonomies", "sulu_content.content": "Content", "sulu_content.published": "Published on", - "sulu_content.author": "Autor", - "sulu_content.authored_date": "Verfasst am" + "sulu_content.author": "Author", + "sulu_content.authored_date": "Authored Date", + "sulu_content.main_webspace": "Main Webspace", + "sulu_content.additional_webspaces": "Weitere Webspaces" } diff --git a/Tests/Application/ExampleTestBundle/Entity/ExampleDimensionContent.php b/Tests/Application/ExampleTestBundle/Entity/ExampleDimensionContent.php index 36a6d439..f4894bb4 100644 --- a/Tests/Application/ExampleTestBundle/Entity/ExampleDimensionContent.php +++ b/Tests/Application/ExampleTestBundle/Entity/ExampleDimensionContent.php @@ -26,10 +26,12 @@ use Sulu\Bundle\ContentBundle\Content\Domain\Model\SeoTrait; use Sulu\Bundle\ContentBundle\Content\Domain\Model\TemplateInterface; use Sulu\Bundle\ContentBundle\Content\Domain\Model\TemplateTrait; +use Sulu\Bundle\ContentBundle\Content\Domain\Model\WebspaceInterface; +use Sulu\Bundle\ContentBundle\Content\Domain\Model\WebspaceTrait; use Sulu\Bundle\ContentBundle\Content\Domain\Model\WorkflowInterface; use Sulu\Bundle\ContentBundle\Content\Domain\Model\WorkflowTrait; -class ExampleDimensionContent implements DimensionContentInterface, ExcerptInterface, SeoInterface, TemplateInterface, RoutableInterface, WorkflowInterface, AuthorInterface +class ExampleDimensionContent implements DimensionContentInterface, ExcerptInterface, SeoInterface, TemplateInterface, RoutableInterface, WorkflowInterface, AuthorInterface, WebspaceInterface { use AuthorTrait; use DimensionContentTrait; @@ -39,6 +41,7 @@ class ExampleDimensionContent implements DimensionContentInterface, ExcerptInter use TemplateTrait { setTemplateData as parentSetTemplateData; } + use WebspaceTrait; use WorkflowTrait; /** diff --git a/Tests/Functional/Integration/ExampleControllerTest.php b/Tests/Functional/Integration/ExampleControllerTest.php index cfeac399..c869730a 100644 --- a/Tests/Functional/Integration/ExampleControllerTest.php +++ b/Tests/Functional/Integration/ExampleControllerTest.php @@ -66,6 +66,8 @@ public function testPostPublish(): int 'excerptMedia' => null, 'author' => null, 'authored' => '2020-05-08T00:00:00+00:00', + 'mainWebspace' => null, + 'additionalWebspaces' => [], ]) ?: null); $response = $this->client->getResponse(); @@ -114,7 +116,6 @@ public function testPost(): int self::purgeDatabase(); $this->client->request('POST', '/admin/api/examples?locale=en', [], [], [], \json_encode([ - 'authored' => '2020-05-08T00:00:00+00:00', 'template' => 'example-2', 'title' => 'Test Example', 'url' => '/my-example', @@ -133,6 +134,9 @@ public function testPost(): int 'excerptCategories' => [], 'excerptIcon' => null, 'excerptMedia' => null, + 'mainWebspace' => 'sulu-io', + 'additionalWebspaces' => [], + 'authored' => '2020-05-08T00:00:00+00:00', ]) ?: null); $response = $this->client->getResponse(); @@ -190,6 +194,9 @@ public function testPut(int $id): void 'excerptCategories' => [], 'excerptIcon' => null, 'excerptMedia' => null, + 'authored' => '2020-06-09T00:00:00+00:00', + 'mainWebspace' => 'sulu-io2', + 'additionalWebspaces' => ['sulu-io', 'sulu-io2'], ]) ?: null); $response = $this->client->getResponse(); diff --git a/Tests/Functional/Integration/responses/example_get.json b/Tests/Functional/Integration/responses/example_get.json index 4ea0b4a5..6b8aee98 100644 --- a/Tests/Functional/Integration/responses/example_get.json +++ b/Tests/Functional/Integration/responses/example_get.json @@ -27,5 +27,7 @@ "template": "example-2", "title": "Test Example", "url": "/my-example", - "workflowPlace": "unpublished" + "workflowPlace": "unpublished", + "mainWebspace": "sulu-io", + "additionalWebspaces": [] } diff --git a/Tests/Functional/Integration/responses/example_post.json b/Tests/Functional/Integration/responses/example_post.json index 4ea0b4a5..6b8aee98 100644 --- a/Tests/Functional/Integration/responses/example_post.json +++ b/Tests/Functional/Integration/responses/example_post.json @@ -27,5 +27,7 @@ "template": "example-2", "title": "Test Example", "url": "/my-example", - "workflowPlace": "unpublished" + "workflowPlace": "unpublished", + "mainWebspace": "sulu-io", + "additionalWebspaces": [] } diff --git a/Tests/Functional/Integration/responses/example_post_publish.json b/Tests/Functional/Integration/responses/example_post_publish.json index 3a862ceb..f02cd2ad 100644 --- a/Tests/Functional/Integration/responses/example_post_publish.json +++ b/Tests/Functional/Integration/responses/example_post_publish.json @@ -27,5 +27,7 @@ "template": "example-2", "title": "Test Example", "url": "/my-example", - "workflowPlace": "published" + "workflowPlace": "published", + "mainWebspace": "sulu-io", + "additionalWebspaces": [] } diff --git a/Tests/Functional/Integration/responses/example_post_trigger_unpublish.json b/Tests/Functional/Integration/responses/example_post_trigger_unpublish.json index 963a1022..21c4600d 100644 --- a/Tests/Functional/Integration/responses/example_post_trigger_unpublish.json +++ b/Tests/Functional/Integration/responses/example_post_trigger_unpublish.json @@ -27,5 +27,7 @@ "template": "example-2", "title": "Test Example", "url": "\/my-example", - "workflowPlace": "unpublished" + "workflowPlace": "unpublished", + "mainWebspace": "sulu-io", + "additionalWebspaces": [] } diff --git a/Tests/Functional/Integration/responses/example_put.json b/Tests/Functional/Integration/responses/example_put.json index 2e89dd25..b40102a4 100644 --- a/Tests/Functional/Integration/responses/example_put.json +++ b/Tests/Functional/Integration/responses/example_put.json @@ -1,6 +1,6 @@ { "author": null, - "authored": "2020-05-08T00:00:00+00:00", + "authored": "2020-06-09T00:00:00+00:00", "article": "

Test Article 2

", "blocks": null, "description": null, @@ -30,5 +30,7 @@ "template": "default", "title": "Test Example 2", "url": "/my-example-2", - "workflowPlace": "unpublished" + "workflowPlace": "unpublished", + "mainWebspace": "sulu-io2", + "additionalWebspaces": ["sulu-io", "sulu-io2"] } diff --git a/Tests/Unit/Content/Application/ContentDataMapper/DataMapper/WebspaceDataMapperTest.php b/Tests/Unit/Content/Application/ContentDataMapper/DataMapper/WebspaceDataMapperTest.php new file mode 100644 index 00000000..990f0810 --- /dev/null +++ b/Tests/Unit/Content/Application/ContentDataMapper/DataMapper/WebspaceDataMapperTest.php @@ -0,0 +1,96 @@ + 1, + 'authored' => '2020-05-08T00:00:00+00:00', + ]; + + $unlocalizedDimensionContent = $this->prophesize(DimensionContentInterface::class); + $localizedDimensionContent = $this->prophesize(DimensionContentInterface::class); + + $authorMapper = $this->createWebspaceDataMapperInstance(); + $authorMapper->map($unlocalizedDimensionContent->reveal(), $localizedDimensionContent->reveal(), $data); + $this->assertTrue(true); // Avoid risky test as this is an early return test + } + + public function testMapWebspaceNoData(): void + { + $data = []; + + $example = new Example(); + $unlocalizedDimensionContent = new ExampleDimensionContent($example); + $localizedDimensionContent = new ExampleDimensionContent($example); + + $authorMapper = $this->createWebspaceDataMapperInstance(); + $authorMapper->map($unlocalizedDimensionContent, $localizedDimensionContent, $data); + + $this->assertNull($localizedDimensionContent->getMainWebspace()); + $this->assertSame([], $localizedDimensionContent->getAdditionalWebspaces()); + } + + public function testMapData(): void + { + $data = [ + 'mainWebspace' => 'example', + 'additionalWebspaces' => ['example', 'example2'], + ]; + + $example = new Example(); + $unlocalizedDimensionContent = new ExampleDimensionContent($example); + $localizedDimensionContent = new ExampleDimensionContent($example); + + $authorMapper = $this->createWebspaceDataMapperInstance(); + $authorMapper->map($unlocalizedDimensionContent, $localizedDimensionContent, $data); + + $this->assertSame('example', $localizedDimensionContent->getMainWebspace()); + $this->assertSame(['example', 'example2'], $localizedDimensionContent->getAdditionalWebspaces()); + } + + public function testMapDataEmpty(): void + { + $data = [ + 'mainWebspace' => null, + 'additionalWebspaces' => null, + ]; + + $example = new Example(); + $unlocalizedDimensionContent = new ExampleDimensionContent($example); + $localizedDimensionContent = new ExampleDimensionContent($example); + $localizedDimensionContent->setMainWebspace('example'); + $localizedDimensionContent->setAdditionalWebspaces(['example', 'example2']); + + $authorMapper = $this->createWebspaceDataMapperInstance(); + $authorMapper->map($unlocalizedDimensionContent, $localizedDimensionContent, $data); + + $this->assertNull($localizedDimensionContent->getMainWebspace()); + $this->assertSame([], $localizedDimensionContent->getAdditionalWebspaces()); + } +} diff --git a/Tests/Unit/Content/Domain/Model/WebspaceTraitTest.php b/Tests/Unit/Content/Domain/Model/WebspaceTraitTest.php new file mode 100644 index 00000000..0e67bc69 --- /dev/null +++ b/Tests/Unit/Content/Domain/Model/WebspaceTraitTest.php @@ -0,0 +1,44 @@ +getWebspaceInstance(); + $this->assertNull($model->getMainWebspace()); + $model->setMainWebspace('example'); + $this->assertSame('example', $model->getMainWebspace()); + } + + public function testGetSetAdditionalWebspaces(): void + { + $model = $this->getWebspaceInstance(); + $this->assertSame([], $model->getAdditionalWebspaces()); + $model->setAdditionalWebspaces(['example', 'example2']); + $this->assertSame(['example', 'example2'], $model->getAdditionalWebspaces()); + } +} diff --git a/Tests/Unit/Content/Infrastructure/Doctrine/MetadataLoaderTest.php b/Tests/Unit/Content/Infrastructure/Doctrine/MetadataLoaderTest.php index 74dfe4a8..937b3ec3 100644 --- a/Tests/Unit/Content/Infrastructure/Doctrine/MetadataLoaderTest.php +++ b/Tests/Unit/Content/Infrastructure/Doctrine/MetadataLoaderTest.php @@ -27,6 +27,7 @@ use Sulu\Bundle\ContentBundle\Content\Domain\Model\ExcerptInterface; use Sulu\Bundle\ContentBundle\Content\Domain\Model\SeoInterface; use Sulu\Bundle\ContentBundle\Content\Domain\Model\TemplateInterface; +use Sulu\Bundle\ContentBundle\Content\Domain\Model\WebspaceInterface; use Sulu\Bundle\ContentBundle\Content\Domain\Model\WorkflowInterface; use Sulu\Bundle\ContentBundle\Content\Infrastructure\Doctrine\MetadataLoader; use Sulu\Bundle\ContentBundle\Tests\Application\ExampleTestBundle\Entity\ExampleDimensionContent; @@ -66,6 +67,7 @@ public function testInvalidMetadata(array $interfaces, array $fields, array $man $reflectionClass->implementsInterface(ExcerptInterface::class)->willReturn(\in_array(ExcerptInterface::class, $interfaces, true)); $reflectionClass->implementsInterface(TemplateInterface::class)->willReturn(\in_array(TemplateInterface::class, $interfaces, true)); $reflectionClass->implementsInterface(WorkflowInterface::class)->willReturn(\in_array(WorkflowInterface::class, $interfaces, true)); + $reflectionClass->implementsInterface(WebspaceInterface::class)->willReturn(\in_array(WebspaceInterface::class, $interfaces, true)); $reflectionClass->implementsInterface(AuthorInterface::class)->willReturn(\in_array(AuthorInterface::class, $interfaces, true)); foreach ($interfaces as $interface) { @@ -243,5 +245,17 @@ public function dataProvider(): \Generator 'author' => true, ], ]; + + yield [ + [ + WebspaceInterface::class, + ], + [ + 'mainWebspace' => true, + 'additionalWebspaces' => true, + ], + [], + [], + ]; } }