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 @@
+
+
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,
+ ],
+ [],
+ [],
+ ];
}
}