From 36a2274e4acbe3fcac12aa5d46bb851a98b27e08 Mon Sep 17 00:00:00 2001 From: Prokyonn Date: Thu, 29 Jul 2021 13:32:35 +0200 Subject: [PATCH 01/11] Add AuthorInterface and dynamic settings form --- .../DataMapper/AuthorDataMapper.php | 72 +++++++++++++ .../ContentMerger/Merger/AuthorMerger.php | 38 +++++++ .../Normalizer/AuthorNormalizer.php | 39 +++++++ .../Domain/Factory/UserFactoryInterface.php | 21 ++++ Content/Domain/Model/AuthorInterface.php | 27 +++++ Content/Domain/Model/AuthorTrait.php | 52 +++++++++ .../Doctrine/MetadataLoader.php | 12 ++- .../Infrastructure/Doctrine/UserFactory.php | 46 ++++++++ .../Sulu/Admin/ContentViewBuilderFactory.php | 100 +++++++++++------- .../Sulu/Form/SettingsFormMetadataVisitor.php | 62 +++++++++++ .../Compiler/SettingsFormPass.php | 63 +++++++++++ DependencyInjection/SuluContentExtension.php | 1 + Resources/config/data-mapper.xml | 6 ++ Resources/config/form-visitor.xml | 14 +++ Resources/config/forms/content_settings.xml | 10 ++ .../config/forms/content_settings_author.xml | 29 +++++ Resources/config/merger.xml | 4 + Resources/config/normalizer.xml | 4 + Resources/config/services.xml | 5 + SuluContentBundle.php | 8 ++ .../Entity/ExampleDimensionContent.php | 5 +- 21 files changed, 579 insertions(+), 39 deletions(-) create mode 100644 Content/Application/ContentDataMapper/DataMapper/AuthorDataMapper.php create mode 100644 Content/Application/ContentMerger/Merger/AuthorMerger.php create mode 100644 Content/Application/ContentNormalizer/Normalizer/AuthorNormalizer.php create mode 100644 Content/Domain/Factory/UserFactoryInterface.php create mode 100644 Content/Domain/Model/AuthorInterface.php create mode 100644 Content/Domain/Model/AuthorTrait.php create mode 100644 Content/Infrastructure/Doctrine/UserFactory.php create mode 100644 Content/Infrastructure/Sulu/Form/SettingsFormMetadataVisitor.php create mode 100644 DependencyInjection/Compiler/SettingsFormPass.php create mode 100644 Resources/config/form-visitor.xml create mode 100644 Resources/config/forms/content_settings.xml create mode 100644 Resources/config/forms/content_settings_author.xml diff --git a/Content/Application/ContentDataMapper/DataMapper/AuthorDataMapper.php b/Content/Application/ContentDataMapper/DataMapper/AuthorDataMapper.php new file mode 100644 index 00000000..ef256adb --- /dev/null +++ b/Content/Application/ContentDataMapper/DataMapper/AuthorDataMapper.php @@ -0,0 +1,72 @@ +userFactory = $userFactory; + } + + public function map( + array $data, + DimensionContentCollectionInterface $dimensionContentCollection + ): void { + $dimensionAttributes = $dimensionContentCollection->getDimensionAttributes(); + $unlocalizedDimensionAttributes = array_merge($dimensionAttributes, ['locale' => null]); + $unlocalizedObject = $dimensionContentCollection->getDimensionContent($unlocalizedDimensionAttributes); + + if (!$unlocalizedObject instanceof AuthorInterface) { + return; + } + + $localizedObject = $dimensionContentCollection->getDimensionContent($dimensionAttributes); + + if ($localizedObject) { + if (!$localizedObject instanceof AuthorInterface) { + throw new \RuntimeException(sprintf('Expected "$localizedObject" from type "%s" but "%s" given.', AuthorInterface::class, \get_class($localizedObject))); + } + + $this->setAuthorData($localizedObject, $data); + + return; + } + + $this->setAuthorData($unlocalizedObject, $data); + } + + /** + * @param mixed[] $data + */ + private function setAuthorData(AuthorInterface $dimensionContent, array $data): void + { + if (isset($data['author'])) { + $dimensionContent->setAuthor($this->userFactory->create($data['author'])); + } + + if (isset($data['authored'])) { + $dimensionContent->setAuthored(new \DateTimeImmutable($data['authored'])); + } + } +} diff --git a/Content/Application/ContentMerger/Merger/AuthorMerger.php b/Content/Application/ContentMerger/Merger/AuthorMerger.php new file mode 100644 index 00000000..d357ee33 --- /dev/null +++ b/Content/Application/ContentMerger/Merger/AuthorMerger.php @@ -0,0 +1,38 @@ +getAuthor()) { + $targetObject->setAuthor($author); + } + + if ($authored = $sourceObject->getAuthored()) { + $targetObject->setAuthored($authored); + } + } +} diff --git a/Content/Application/ContentNormalizer/Normalizer/AuthorNormalizer.php b/Content/Application/ContentNormalizer/Normalizer/AuthorNormalizer.php new file mode 100644 index 00000000..9cf7d024 --- /dev/null +++ b/Content/Application/ContentNormalizer/Normalizer/AuthorNormalizer.php @@ -0,0 +1,39 @@ +getAuthor() ? $object->getAuthor()->getId() : null; + + return $normalizedData; + } + + public function getIgnoredAttributes(object $object): array + { + if (!$object instanceof AuthorInterface) { + return []; + } + + return ['author']; + } +} diff --git a/Content/Domain/Factory/UserFactoryInterface.php b/Content/Domain/Factory/UserFactoryInterface.php new file mode 100644 index 00000000..b14e094c --- /dev/null +++ b/Content/Domain/Factory/UserFactoryInterface.php @@ -0,0 +1,21 @@ +author; + } + + public function setAuthor(?UserInterface $author): void + { + $this->author = $author; + } + + public function getAuthored(): ?\DateTimeImmutable + { + return $this->authored; + } + + public function setAuthored(?\DateTimeImmutable $authored): void + { + $this->authored = $authored; + } +} diff --git a/Content/Infrastructure/Doctrine/MetadataLoader.php b/Content/Infrastructure/Doctrine/MetadataLoader.php index d7703cde..9da0a484 100644 --- a/Content/Infrastructure/Doctrine/MetadataLoader.php +++ b/Content/Infrastructure/Doctrine/MetadataLoader.php @@ -19,6 +19,7 @@ use Doctrine\ORM\Events; use Doctrine\ORM\Mapping\ClassMetadataInfo; use Sulu\Bundle\CategoryBundle\Entity\CategoryInterface; +use Sulu\Bundle\ContentBundle\Content\Domain\Model\AuthorInterface; use Sulu\Bundle\ContentBundle\Content\Domain\Model\DimensionContentInterface; use Sulu\Bundle\ContentBundle\Content\Domain\Model\ExcerptInterface; use Sulu\Bundle\ContentBundle\Content\Domain\Model\SeoInterface; @@ -26,6 +27,7 @@ use Sulu\Bundle\ContentBundle\Content\Domain\Model\WorkflowInterface; use Sulu\Bundle\MediaBundle\Entity\MediaInterface; use Sulu\Bundle\TagBundle\Tag\TagInterface; +use Sulu\Component\Security\Authentication\UserInterface; class MetadataLoader implements EventSubscriber { @@ -95,6 +97,11 @@ public function loadClassMetadata(LoadClassMetadataEventArgs $event): void $this->addManyToMany($event, $metadata, 'excerptCategories', CategoryInterface::class, 'category_id'); } + if ($reflection->implementsInterface(AuthorInterface::class)) { + $this->addField($metadata, 'authored', 'datetime_immutable', ['nullable' => true]); + $this->addManyToOne($event, $metadata, 'author', UserInterface::class, true); + } + if ($reflection->implementsInterface(WorkflowInterface::class)) { $this->addField($metadata, 'workflowPlace', 'string', ['length' => 32, 'nullable' => true]); $this->addField($metadata, 'workflowPublished', 'datetime_immutable', ['nullable' => true]); @@ -110,7 +117,8 @@ private function addManyToOne( LoadClassMetadataEventArgs $event, ClassMetadataInfo $metadata, string $name, - string $class + string $class, + bool $nullable = false ): void { if ($metadata->hasAssociation($name)) { return; @@ -126,7 +134,7 @@ private function addManyToOne( [ 'name' => $namingStrategy->joinKeyColumnName($name), 'referencedColumnName' => $referencedColumnName, - 'nullable' => false, + 'nullable' => $nullable, 'onDelete' => 'CASCADE', 'onUpdate' => 'CASCADE', ], diff --git a/Content/Infrastructure/Doctrine/UserFactory.php b/Content/Infrastructure/Doctrine/UserFactory.php new file mode 100644 index 00000000..5842395b --- /dev/null +++ b/Content/Infrastructure/Doctrine/UserFactory.php @@ -0,0 +1,46 @@ +entityManager = $entityManager; + } + + public function create(?int $userId): ?UserInterface + { + if (!$userId) { + return null; + } + + /** @var UserInterface|null $user */ + $user = $this->entityManager->getPartialReference( + UserInterface::class, + $userId + ); + + return $user; + } +} diff --git a/Content/Infrastructure/Sulu/Admin/ContentViewBuilderFactory.php b/Content/Infrastructure/Sulu/Admin/ContentViewBuilderFactory.php index 9fa5cd7c..1f4b5dd5 100644 --- a/Content/Infrastructure/Sulu/Admin/ContentViewBuilderFactory.php +++ b/Content/Infrastructure/Sulu/Admin/ContentViewBuilderFactory.php @@ -71,16 +71,16 @@ public function getDefaultToolbarActions( if (is_subclass_of($dimensionContentClass, WorkflowInterface::class)) { $toolbarActions['save'] = new ToolbarAction( - 'sulu_admin.save_with_publishing', - [ - 'publish_visible_condition' => '(!_permissions || _permissions.live)', - 'save_visible_condition' => '(!_permissions || _permissions.edit)', - ] - ); + 'sulu_admin.save_with_publishing', + [ + 'publish_visible_condition' => '(!_permissions || _permissions.live)', + 'save_visible_condition' => '(!_permissions || _permissions.edit)', + ] + ); } else { $toolbarActions['save'] = new ToolbarAction( - 'sulu_admin.save' - ); + 'sulu_admin.save' + ); } if (is_subclass_of($dimensionContentClass, TemplateInterface::class)) { @@ -93,31 +93,31 @@ public function getDefaultToolbarActions( } $toolbarActions['delete'] = new ToolbarAction( - 'sulu_admin.delete', - [ - 'visible_condition' => '(!_permissions || _permissions.delete) && url != "/"', - ] - ); + 'sulu_admin.delete', + [ + 'visible_condition' => '(!_permissions || _permissions.delete) && url != "/"', + ] + ); if (is_subclass_of($dimensionContentClass, WorkflowInterface::class)) { $toolbarActions['edit'] = new DropdownToolbarAction( - 'sulu_admin.edit', - 'su-pen', - [ - new ToolbarAction( - 'sulu_admin.delete_draft', - [ - 'visible_condition' => '(!_permissions || _permissions.live)', - ] - ), - new ToolbarAction( - 'sulu_admin.set_unpublished', - [ - 'visible_condition' => '(!_permissions || _permissions.live)', - ] - ), - ] - ); + 'sulu_admin.edit', + 'su-pen', + [ + new ToolbarAction( + 'sulu_admin.delete_draft', + [ + 'visible_condition' => '(!_permissions || _permissions.live)', + ] + ), + new ToolbarAction( + 'sulu_admin.set_unpublished', + [ + 'visible_condition' => '(!_permissions || _permissions.live)', + ] + ), + ] + ); } return $toolbarActions; @@ -138,24 +138,23 @@ public function createViews( $toolbarActions = $toolbarActions ?: $this->getDefaultToolbarActions($contentRichEntityClass); $addToolbarActions = $toolbarActions; + $settingsToolbarActions = []; $seoAndExcerptToolbarActions = []; if (isset($toolbarActions['save'])) { $seoAndExcerptToolbarActions = ['save' => $toolbarActions['save']]; + $settingsToolbarActions = ['save' => $toolbarActions['save']]; } if (!$this->hasPermission($securityContext, PermissionTypes::EDIT)) { - unset($toolbarActions['save']); - unset($seoAndExcerptToolbarActions['save']); + unset($toolbarActions['save'], $seoAndExcerptToolbarActions['save'], $settingsToolbarActions['save']); } if (!$this->hasPermission($securityContext, PermissionTypes::LIVE)) { - unset($toolbarActions['edit']); - unset($addToolbarActions['edit']); + unset($toolbarActions['edit'], $addToolbarActions['edit']); } if (!$this->hasPermission($securityContext, PermissionTypes::DELETE)) { - unset($toolbarActions['delete']); - unset($addToolbarActions['delete']); + unset($toolbarActions['delete'], $addToolbarActions['delete']); } $views = []; @@ -207,6 +206,14 @@ public function createViews( $seoAndExcerptToolbarActions ); } + + $views[] = $this->createSettingsFormView( + $editParentView, + $previewEnabled, + $resourceKey, + $settingsToolbarActions, + $dimensionContentClass + ); } return $views; @@ -269,6 +276,27 @@ private function createExcerptFormView( ->setParent($parentView); } + /** + * @param array $toolbarActions + */ + private function createSettingsFormView( + string $parentView, + bool $previewEnabled, + string $resourceKey, + array $toolbarActions, + string $dimensionContentClass + ): ViewBuilderInterface { + return $this->createFormViewBuilder($parentView . '.settings', '/settings', $previewEnabled) + ->addMetadataRequestParameters(['class' => $dimensionContentClass]) + ->setResourceKey($resourceKey) + ->setFormKey('content_settings') + ->setTabTitle('sulu_page.settings') + ->setTitleVisible(true) + ->addToolbarActions(array_values($toolbarActions)) + ->setTabOrder(50) + ->setParent($parentView); + } + /** * @return PreviewFormViewBuilderInterface|FormViewBuilderInterface */ diff --git a/Content/Infrastructure/Sulu/Form/SettingsFormMetadataVisitor.php b/Content/Infrastructure/Sulu/Form/SettingsFormMetadataVisitor.php new file mode 100644 index 00000000..60af6a2e --- /dev/null +++ b/Content/Infrastructure/Sulu/Form/SettingsFormMetadataVisitor.php @@ -0,0 +1,62 @@ + + */ + private $formMappingTags; + + /** + * @param array $formMappingTags + */ + public function __construct(FormXmlLoader $formXmlLoader, array $formMappingTags) + { + $this->formXmlLoader = $formXmlLoader; + $this->formMappingTags = $formMappingTags; + } + + public function visitFormMetadata(FormMetadata $formMetadata, string $locale, array $metadataOptions = []): void + { + if ('content_settings' === $formMetadata->getKey()) { + usort($this->formMappingTags, static function ($a, $b) { + return $b['priority'] <=> $a['priority']; + }); + + foreach ($this->formMappingTags as $tag) { + $class = $metadataOptions['class']; + if (is_subclass_of($class, $tag['instanceOf'])) { + /** @var LocalizedFormMetadataCollection $formMetadataCollection */ + $formMetadataCollection = $this->formXmlLoader->load($tag['path']); + $settingsMetadata = $formMetadataCollection->getItems()[$locale]; + + $formMetadata->setItems(array_merge($formMetadata->getItems(), $settingsMetadata->getItems())); + $formMetadata->setSchema($formMetadata->getSchema()->merge($settingsMetadata->getSchema())); + } + } + } + } +} diff --git a/DependencyInjection/Compiler/SettingsFormPass.php b/DependencyInjection/Compiler/SettingsFormPass.php new file mode 100644 index 00000000..ed6ed980 --- /dev/null +++ b/DependencyInjection/Compiler/SettingsFormPass.php @@ -0,0 +1,63 @@ +getParameter('sulu_admin.forms.directories'); + $formMappingTags = []; + + $finder = new Finder(); + $finder->files()->in($formDirectories); + foreach ($finder as $file) { + $document = new \DOMDocument(); + + if (!$xmlContent = file_get_contents($file->getPathname())) { + continue; + } + + $document->loadXML($xmlContent); + $path = new \DOMXPath($document); + $path->registerNamespace('x', FormXmlLoader::SCHEMA_NAMESPACE_URI); + $tagNodes = $path->query('/x:form/x:tag'); + + if (!$tagNodes) { + continue; + } + + /** @var \DOMElement $tagNode */ + foreach ($tagNodes as $tagNode) { + $tag = [ + 'name' => $tagNode->getAttribute('name'), + 'instanceOf' => $tagNode->getAttribute('instanceOf'), + 'priority' => $tagNode->getAttribute('priority'), + 'path' => $file->getPathname(), + ]; + + if (!empty($tag['instanceOf'])) { + $formMappingTags[] = $tag; + } + } + } + + $container->setParameter('sulu_content.settings_mapping_tags', $formMappingTags); + } +} diff --git a/DependencyInjection/SuluContentExtension.php b/DependencyInjection/SuluContentExtension.php index cb453174..96eb45bf 100644 --- a/DependencyInjection/SuluContentExtension.php +++ b/DependencyInjection/SuluContentExtension.php @@ -50,6 +50,7 @@ public function load(array $configs, ContainerBuilder $container): void $loader->load('merger.xml'); $loader->load('normalizer.xml'); $loader->load('services.xml'); + $loader->load('form-visitor.xml'); if ($container->hasParameter('kernel.bundles')) { // TODO FIXME add test here diff --git a/Resources/config/data-mapper.xml b/Resources/config/data-mapper.xml index 7b26e65f..6d1aa3dc 100644 --- a/Resources/config/data-mapper.xml +++ b/Resources/config/data-mapper.xml @@ -26,6 +26,12 @@ + + + + + + diff --git a/Resources/config/form-visitor.xml b/Resources/config/form-visitor.xml new file mode 100644 index 00000000..d6fa1f08 --- /dev/null +++ b/Resources/config/form-visitor.xml @@ -0,0 +1,14 @@ + + + + + + + %sulu_content.settings_mapping_tags% + + + + + diff --git a/Resources/config/forms/content_settings.xml b/Resources/config/forms/content_settings.xml new file mode 100644 index 00000000..90239eb9 --- /dev/null +++ b/Resources/config/forms/content_settings.xml @@ -0,0 +1,10 @@ + +
+ content_settings + + + +
diff --git a/Resources/config/forms/content_settings_author.xml b/Resources/config/forms/content_settings_author.xml new file mode 100644 index 00000000..3b3fe5bd --- /dev/null +++ b/Resources/config/forms/content_settings_author.xml @@ -0,0 +1,29 @@ + +
+ content_settings_author + + + + +
+ + sulu_page.editing_information + + + + + sulu_page.authored_date + + + + + sulu_page.author + + + +
+
+ diff --git a/Resources/config/merger.xml b/Resources/config/merger.xml index f7960c92..4b33debc 100644 --- a/Resources/config/merger.xml +++ b/Resources/config/merger.xml @@ -19,5 +19,9 @@ + + + + diff --git a/Resources/config/normalizer.xml b/Resources/config/normalizer.xml index e256eeb6..28a5c5a6 100644 --- a/Resources/config/normalizer.xml +++ b/Resources/config/normalizer.xml @@ -23,5 +23,9 @@ + + + + diff --git a/Resources/config/services.xml b/Resources/config/services.xml index fd41fa84..ec91a2ac 100644 --- a/Resources/config/services.xml +++ b/Resources/config/services.xml @@ -38,6 +38,11 @@
+ + + + + diff --git a/SuluContentBundle.php b/SuluContentBundle.php index b1df0cc5..3c8c95b9 100644 --- a/SuluContentBundle.php +++ b/SuluContentBundle.php @@ -13,8 +13,16 @@ namespace Sulu\Bundle\ContentBundle; +use Sulu\Bundle\ContentBundle\DependencyInjection\Compiler\SettingsFormPass; +use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\HttpKernel\Bundle\Bundle; class SuluContentBundle extends Bundle { + public function build(ContainerBuilder $container): void + { + parent::build($container); + + $container->addCompilerPass(new SettingsFormPass()); + } } diff --git a/Tests/Application/ExampleTestBundle/Entity/ExampleDimensionContent.php b/Tests/Application/ExampleTestBundle/Entity/ExampleDimensionContent.php index 8e588fab..46891199 100644 --- a/Tests/Application/ExampleTestBundle/Entity/ExampleDimensionContent.php +++ b/Tests/Application/ExampleTestBundle/Entity/ExampleDimensionContent.php @@ -13,6 +13,8 @@ namespace Sulu\Bundle\ContentBundle\Tests\Application\ExampleTestBundle\Entity; +use Sulu\Bundle\ContentBundle\Content\Domain\Model\AuthorInterface; +use Sulu\Bundle\ContentBundle\Content\Domain\Model\AuthorTrait; use Sulu\Bundle\ContentBundle\Content\Domain\Model\ContentRichEntityInterface; use Sulu\Bundle\ContentBundle\Content\Domain\Model\DimensionContentInterface; use Sulu\Bundle\ContentBundle\Content\Domain\Model\DimensionContentTrait; @@ -27,8 +29,9 @@ 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 +class ExampleDimensionContent implements DimensionContentInterface, ExcerptInterface, SeoInterface, TemplateInterface, RoutableInterface, WorkflowInterface, AuthorInterface { + use AuthorTrait; use DimensionContentTrait; use ExcerptTrait; use RoutableTrait; From 49c360464d04423ccef52d1c77e9fe407fd83e28 Mon Sep 17 00:00:00 2001 From: Prokyonn Date: Thu, 29 Jul 2021 16:01:24 +0200 Subject: [PATCH 02/11] Add review suggestions --- .../DataMapper/AuthorDataMapper.php | 12 +++--- ...erface.php => ContactFactoryInterface.php} | 6 +-- Content/Domain/Model/AuthorInterface.php | 6 +-- Content/Domain/Model/AuthorTrait.php | 8 ++-- .../{UserFactory.php => ContactFactory.php} | 20 ++++----- .../Sulu/Admin/ContentViewBuilderFactory.php | 21 +++++++++- .../Sulu/Form/SettingsFormMetadataVisitor.php | 42 +++++++------------ .../Compiler/SettingsFormPass.php | 25 ++++++----- Resources/config/data-mapper.xml | 2 +- Resources/config/form-visitor.xml | 3 +- .../config/forms/content_settings_author.xml | 8 ++-- Resources/config/services.xml | 5 ++- Resources/translations/admin.de.json | 4 +- Resources/translations/admin.en.json | 4 +- .../Admin/ContentViewBuilderFactoryTest.php | 3 +- 15 files changed, 91 insertions(+), 78 deletions(-) rename Content/Domain/Factory/{UserFactoryInterface.php => ContactFactoryInterface.php} (64%) rename Content/Infrastructure/Doctrine/{UserFactory.php => ContactFactory.php} (55%) diff --git a/Content/Application/ContentDataMapper/DataMapper/AuthorDataMapper.php b/Content/Application/ContentDataMapper/DataMapper/AuthorDataMapper.php index ef256adb..9c661313 100644 --- a/Content/Application/ContentDataMapper/DataMapper/AuthorDataMapper.php +++ b/Content/Application/ContentDataMapper/DataMapper/AuthorDataMapper.php @@ -13,20 +13,20 @@ namespace Sulu\Bundle\ContentBundle\Content\Application\ContentDataMapper\DataMapper; -use Sulu\Bundle\ContentBundle\Content\Domain\Factory\UserFactoryInterface; +use Sulu\Bundle\ContentBundle\Content\Domain\Factory\ContactFactoryInterface; use Sulu\Bundle\ContentBundle\Content\Domain\Model\AuthorInterface; use Sulu\Bundle\ContentBundle\Content\Domain\Model\DimensionContentCollectionInterface; class AuthorDataMapper implements DataMapperInterface { /** - * @var UserFactoryInterface + * @var ContactFactoryInterface */ - private $userFactory; + private $contactFactory; - public function __construct(UserFactoryInterface $userFactory) + public function __construct(ContactFactoryInterface $contactFactory) { - $this->userFactory = $userFactory; + $this->contactFactory = $contactFactory; } public function map( @@ -62,7 +62,7 @@ public function map( private function setAuthorData(AuthorInterface $dimensionContent, array $data): void { if (isset($data['author'])) { - $dimensionContent->setAuthor($this->userFactory->create($data['author'])); + $dimensionContent->setAuthor($this->contactFactory->create($data['author'])); } if (isset($data['authored'])) { diff --git a/Content/Domain/Factory/UserFactoryInterface.php b/Content/Domain/Factory/ContactFactoryInterface.php similarity index 64% rename from Content/Domain/Factory/UserFactoryInterface.php rename to Content/Domain/Factory/ContactFactoryInterface.php index b14e094c..aef9825e 100644 --- a/Content/Domain/Factory/UserFactoryInterface.php +++ b/Content/Domain/Factory/ContactFactoryInterface.php @@ -13,9 +13,9 @@ namespace Sulu\Bundle\ContentBundle\Content\Domain\Factory; -use Sulu\Component\Security\Authentication\UserInterface; +use Sulu\Bundle\ContactBundle\Entity\ContactInterface; -interface UserFactoryInterface +interface ContactFactoryInterface { - public function create(?int $userId): ?UserInterface; + public function create(?int $contactId): ?ContactInterface; } diff --git a/Content/Domain/Model/AuthorInterface.php b/Content/Domain/Model/AuthorInterface.php index 2680227e..68e5d72d 100644 --- a/Content/Domain/Model/AuthorInterface.php +++ b/Content/Domain/Model/AuthorInterface.php @@ -13,13 +13,13 @@ namespace Sulu\Bundle\ContentBundle\Content\Domain\Model; -use Sulu\Component\Security\Authentication\UserInterface; +use Sulu\Bundle\ContactBundle\Entity\ContactInterface; interface AuthorInterface { - public function getAuthor(): ?UserInterface; + public function getAuthor(): ?ContactInterface; - public function setAuthor(?UserInterface $author): void; + public function setAuthor(?ContactInterface $author): void; public function getAuthored(): ?\DateTimeImmutable; diff --git a/Content/Domain/Model/AuthorTrait.php b/Content/Domain/Model/AuthorTrait.php index c07f810d..799396f7 100644 --- a/Content/Domain/Model/AuthorTrait.php +++ b/Content/Domain/Model/AuthorTrait.php @@ -13,7 +13,7 @@ namespace Sulu\Bundle\ContentBundle\Content\Domain\Model; -use Sulu\Component\Security\Authentication\UserInterface; +use Sulu\Bundle\ContactBundle\Entity\ContactInterface; /** * Basic implementation of the AuthorTrait. @@ -21,7 +21,7 @@ trait AuthorTrait { /** - * @var UserInterface|null + * @var ContactInterface|null */ private $author; @@ -30,12 +30,12 @@ trait AuthorTrait */ private $authored; - public function getAuthor(): ?UserInterface + public function getAuthor(): ?ContactInterface { return $this->author; } - public function setAuthor(?UserInterface $author): void + public function setAuthor(?ContactInterface $author): void { $this->author = $author; } diff --git a/Content/Infrastructure/Doctrine/UserFactory.php b/Content/Infrastructure/Doctrine/ContactFactory.php similarity index 55% rename from Content/Infrastructure/Doctrine/UserFactory.php rename to Content/Infrastructure/Doctrine/ContactFactory.php index 5842395b..467d33c8 100644 --- a/Content/Infrastructure/Doctrine/UserFactory.php +++ b/Content/Infrastructure/Doctrine/ContactFactory.php @@ -14,10 +14,10 @@ namespace Sulu\Bundle\ContentBundle\Content\Infrastructure\Doctrine; use Doctrine\ORM\EntityManagerInterface; -use Sulu\Bundle\ContentBundle\Content\Domain\Factory\UserFactoryInterface; -use Sulu\Component\Security\Authentication\UserInterface; +use Sulu\Bundle\ContactBundle\Entity\ContactInterface; +use Sulu\Bundle\ContentBundle\Content\Domain\Factory\ContactFactoryInterface; -class UserFactory implements UserFactoryInterface +class ContactFactory implements ContactFactoryInterface { /** * @var EntityManagerInterface @@ -29,18 +29,18 @@ public function __construct(EntityManagerInterface $entityManager) $this->entityManager = $entityManager; } - public function create(?int $userId): ?UserInterface + public function create(?int $contactId): ?ContactInterface { - if (!$userId) { + if (!$contactId) { return null; } - /** @var UserInterface|null $user */ - $user = $this->entityManager->getPartialReference( - UserInterface::class, - $userId + /** @var ContactInterface|null $contact */ + $contact = $this->entityManager->getPartialReference( + ContactInterface::class, + $contactId ); - return $user; + return $contact; } } diff --git a/Content/Infrastructure/Sulu/Admin/ContentViewBuilderFactory.php b/Content/Infrastructure/Sulu/Admin/ContentViewBuilderFactory.php index 1f4b5dd5..821af766 100644 --- a/Content/Infrastructure/Sulu/Admin/ContentViewBuilderFactory.php +++ b/Content/Infrastructure/Sulu/Admin/ContentViewBuilderFactory.php @@ -50,16 +50,26 @@ class ContentViewBuilderFactory implements ContentViewBuilderFactoryInterface */ private $securityChecker; + /** + * @var array + */ + private $settingsForms; + + /** + * @param array $settingsForms + */ public function __construct( ViewBuilderFactoryInterface $viewBuilderFactory, PreviewObjectProviderRegistryInterface $objectProviderRegistry, ContentMetadataInspectorInterface $contentMetadataInspector, - SecurityCheckerInterface $securityChecker + SecurityCheckerInterface $securityChecker, + array $settingsForms ) { $this->viewBuilderFactory = $viewBuilderFactory; $this->objectProviderRegistry = $objectProviderRegistry; $this->contentMetadataInspector = $contentMetadataInspector; $this->securityChecker = $securityChecker; + $this->settingsForms = $settingsForms; } public function getDefaultToolbarActions( @@ -286,8 +296,15 @@ private function createSettingsFormView( array $toolbarActions, string $dimensionContentClass ): ViewBuilderInterface { + $forms = []; + foreach ($this->settingsForms as $key => $tag) { + if (is_subclass_of($dimensionContentClass, $tag['instanceOf'])) { + $forms[] = $key; + } + } + return $this->createFormViewBuilder($parentView . '.settings', '/settings', $previewEnabled) - ->addMetadataRequestParameters(['class' => $dimensionContentClass]) + ->addMetadataRequestParameters(['forms' => $forms]) ->setResourceKey($resourceKey) ->setFormKey('content_settings') ->setTabTitle('sulu_page.settings') diff --git a/Content/Infrastructure/Sulu/Form/SettingsFormMetadataVisitor.php b/Content/Infrastructure/Sulu/Form/SettingsFormMetadataVisitor.php index 60af6a2e..23bb6f8a 100644 --- a/Content/Infrastructure/Sulu/Form/SettingsFormMetadataVisitor.php +++ b/Content/Infrastructure/Sulu/Form/SettingsFormMetadataVisitor.php @@ -13,49 +13,35 @@ namespace Sulu\Bundle\ContentBundle\Content\Infrastructure\Sulu\Form; -use Sulu\Bundle\AdminBundle\FormMetadata\FormXmlLoader; use Sulu\Bundle\AdminBundle\Metadata\FormMetadata\FormMetadata; use Sulu\Bundle\AdminBundle\Metadata\FormMetadata\FormMetadataVisitorInterface; -use Sulu\Bundle\AdminBundle\Metadata\FormMetadata\LocalizedFormMetadataCollection; +use Sulu\Bundle\AdminBundle\Metadata\FormMetadata\XmlFormMetadataLoader; class SettingsFormMetadataVisitor implements FormMetadataVisitorInterface { /** - * @var FormXmlLoader + * @var XmlFormMetadataLoader */ - private $formXmlLoader; + private $xmlFormMetadataLoader; - /** - * @var array - */ - private $formMappingTags; - - /** - * @param array $formMappingTags - */ - public function __construct(FormXmlLoader $formXmlLoader, array $formMappingTags) + public function __construct(XmlFormMetadataLoader $xmlFormMetadataLoader) { - $this->formXmlLoader = $formXmlLoader; - $this->formMappingTags = $formMappingTags; + $this->xmlFormMetadataLoader = $xmlFormMetadataLoader; } public function visitFormMetadata(FormMetadata $formMetadata, string $locale, array $metadataOptions = []): void { if ('content_settings' === $formMetadata->getKey()) { - usort($this->formMappingTags, static function ($a, $b) { - return $b['priority'] <=> $a['priority']; - }); - - foreach ($this->formMappingTags as $tag) { - $class = $metadataOptions['class']; - if (is_subclass_of($class, $tag['instanceOf'])) { - /** @var LocalizedFormMetadataCollection $formMetadataCollection */ - $formMetadataCollection = $this->formXmlLoader->load($tag['path']); - $settingsMetadata = $formMetadataCollection->getItems()[$locale]; - - $formMetadata->setItems(array_merge($formMetadata->getItems(), $settingsMetadata->getItems())); - $formMetadata->setSchema($formMetadata->getSchema()->merge($settingsMetadata->getSchema())); + foreach ($metadataOptions['forms'] ?? [] as $form) { + /** @var FormMetadata|null $subFormMetadata */ + $subFormMetadata = $this->xmlFormMetadataLoader->getMetadata($form, $locale, $metadataOptions); + + if (!$subFormMetadata || !($subFormMetadata instanceof FormMetadata)) { + continue; } + + $formMetadata->setItems(array_merge($formMetadata->getItems(), $subFormMetadata->getItems())); + $formMetadata->setSchema($formMetadata->getSchema()->merge($subFormMetadata->getSchema())); } } } diff --git a/DependencyInjection/Compiler/SettingsFormPass.php b/DependencyInjection/Compiler/SettingsFormPass.php index ed6ed980..3c2ec689 100644 --- a/DependencyInjection/Compiler/SettingsFormPass.php +++ b/DependencyInjection/Compiler/SettingsFormPass.php @@ -23,10 +23,10 @@ class SettingsFormPass implements CompilerPassInterface public function process(ContainerBuilder $container): void { $formDirectories = $container->getParameter('sulu_admin.forms.directories'); - $formMappingTags = []; $finder = new Finder(); $finder->files()->in($formDirectories); + $settingsForms = []; foreach ($finder as $file) { $document = new \DOMDocument(); @@ -45,19 +45,24 @@ public function process(ContainerBuilder $container): void /** @var \DOMElement $tagNode */ foreach ($tagNodes as $tagNode) { - $tag = [ - 'name' => $tagNode->getAttribute('name'), - 'instanceOf' => $tagNode->getAttribute('instanceOf'), - 'priority' => $tagNode->getAttribute('priority'), - 'path' => $file->getPathname(), - ]; + $instanceOf = $tagNode->getAttribute('instanceOf'); + $priority = $tagNode->getAttribute('priority'); - if (!empty($tag['instanceOf'])) { - $formMappingTags[] = $tag; + if (empty($instanceOf)) { + continue; } + + $settingsForms[$tagNode->getAttribute('name')] = [ + 'instanceOf' => $instanceOf, + 'priority' => $priority, + ]; } } - $container->setParameter('sulu_content.settings_mapping_tags', $formMappingTags); + uasort($settingsForms, static function ($a, $b) { + return $b['priority'] <=> $a['priority']; + }); + + $container->setParameter('sulu_content.settings_forms', $settingsForms); } } diff --git a/Resources/config/data-mapper.xml b/Resources/config/data-mapper.xml index 6d1aa3dc..87ba3465 100644 --- a/Resources/config/data-mapper.xml +++ b/Resources/config/data-mapper.xml @@ -27,7 +27,7 @@ - + diff --git a/Resources/config/form-visitor.xml b/Resources/config/form-visitor.xml index d6fa1f08..19183e5c 100644 --- a/Resources/config/form-visitor.xml +++ b/Resources/config/form-visitor.xml @@ -5,8 +5,7 @@ - - %sulu_content.settings_mapping_tags% + diff --git a/Resources/config/forms/content_settings_author.xml b/Resources/config/forms/content_settings_author.xml index 3b3fe5bd..c205090d 100644 --- a/Resources/config/forms/content_settings_author.xml +++ b/Resources/config/forms/content_settings_author.xml @@ -5,22 +5,22 @@ > content_settings_author - +
- sulu_page.editing_information + sulu_content.author - sulu_page.authored_date + sulu_content.authored_date - sulu_page.author + sulu_content.author diff --git a/Resources/config/services.xml b/Resources/config/services.xml index ec91a2ac..598b7e99 100644 --- a/Resources/config/services.xml +++ b/Resources/config/services.xml @@ -13,6 +13,7 @@ + %sulu_content.settings_forms% @@ -38,8 +39,8 @@ - - + + diff --git a/Resources/translations/admin.de.json b/Resources/translations/admin.de.json index 2ba4ef47..0b5da4a9 100644 --- a/Resources/translations/admin.de.json +++ b/Resources/translations/admin.de.json @@ -2,5 +2,7 @@ "sulu_content.seo": "SEO", "sulu_content.excerpt": "Auszug & Taxonomien", "sulu_content.content": "Inhalt", - "sulu_content.published": "Veröffentlicht am" + "sulu_content.published": "Veröffentlicht am", + "sulu_content.author": "Author", + "sulu_page.authored_date": "Authored Date" } diff --git a/Resources/translations/admin.en.json b/Resources/translations/admin.en.json index 25e241f7..c9f009de 100644 --- a/Resources/translations/admin.en.json +++ b/Resources/translations/admin.en.json @@ -2,5 +2,7 @@ "sulu_content.seo": "SEO", "sulu_content.excerpt": "Excerpt & Taxonomies", "sulu_content.content": "Content", - "sulu_content.published": "Published on" + "sulu_content.published": "Published on", + "sulu_content.author": "Autor", + "sulu_content.authored_date": "Verfasst am" } diff --git a/Tests/Unit/Content/Infrastructure/Sulu/Admin/ContentViewBuilderFactoryTest.php b/Tests/Unit/Content/Infrastructure/Sulu/Admin/ContentViewBuilderFactoryTest.php index 60ae106a..eea713b1 100644 --- a/Tests/Unit/Content/Infrastructure/Sulu/Admin/ContentViewBuilderFactoryTest.php +++ b/Tests/Unit/Content/Infrastructure/Sulu/Admin/ContentViewBuilderFactoryTest.php @@ -58,7 +58,8 @@ protected function createContentViewBuilder( new ViewBuilderFactory(), $previewObjectProviderRegistry, $contentMetadataInspector, - $securityChecker + $securityChecker, + [] ); } From 01da991702127da0710b40f4d6fccd1f31893076 Mon Sep 17 00:00:00 2001 From: Prokyonn Date: Thu, 29 Jul 2021 17:08:33 +0200 Subject: [PATCH 03/11] Fix old tests --- .gitignore | 3 +-- .../Infrastructure/Doctrine/MetadataLoader.php | 4 ++-- .../Integration/ExampleControllerTest.php | 2 ++ .../Integration/responses/example_get.json | 2 ++ .../Integration/responses/example_post.json | 2 ++ .../responses/example_post_publish.json | 2 ++ .../example_post_trigger_unpublish.json | 2 ++ .../Integration/responses/example_put.json | 2 ++ .../Doctrine/MetadataLoaderTest.php | 16 ++++++++++++++++ .../Sulu/Admin/ContentViewBuilderFactoryTest.php | 15 +++++++++++---- Tests/Unit/SuluContentBundleTest.php | 2 +- 11 files changed, 43 insertions(+), 9 deletions(-) diff --git a/.gitignore b/.gitignore index 72fd675f..d81f1a44 100644 --- a/.gitignore +++ b/.gitignore @@ -27,8 +27,7 @@ package-lock.json # tests Tests/Application/var Tests/Application/public/build -Tests/Application/.env.local -Tests/Application/.env.test.local +Tests/Application/.env*.local Tests/reports/ # IDEs diff --git a/Content/Infrastructure/Doctrine/MetadataLoader.php b/Content/Infrastructure/Doctrine/MetadataLoader.php index 9da0a484..ff396d9d 100644 --- a/Content/Infrastructure/Doctrine/MetadataLoader.php +++ b/Content/Infrastructure/Doctrine/MetadataLoader.php @@ -19,6 +19,7 @@ use Doctrine\ORM\Events; use Doctrine\ORM\Mapping\ClassMetadataInfo; use Sulu\Bundle\CategoryBundle\Entity\CategoryInterface; +use Sulu\Bundle\ContactBundle\Entity\ContactInterface; use Sulu\Bundle\ContentBundle\Content\Domain\Model\AuthorInterface; use Sulu\Bundle\ContentBundle\Content\Domain\Model\DimensionContentInterface; use Sulu\Bundle\ContentBundle\Content\Domain\Model\ExcerptInterface; @@ -27,7 +28,6 @@ use Sulu\Bundle\ContentBundle\Content\Domain\Model\WorkflowInterface; use Sulu\Bundle\MediaBundle\Entity\MediaInterface; use Sulu\Bundle\TagBundle\Tag\TagInterface; -use Sulu\Component\Security\Authentication\UserInterface; class MetadataLoader implements EventSubscriber { @@ -99,7 +99,7 @@ public function loadClassMetadata(LoadClassMetadataEventArgs $event): void if ($reflection->implementsInterface(AuthorInterface::class)) { $this->addField($metadata, 'authored', 'datetime_immutable', ['nullable' => true]); - $this->addManyToOne($event, $metadata, 'author', UserInterface::class, true); + $this->addManyToOne($event, $metadata, 'author', ContactInterface::class, true); } if ($reflection->implementsInterface(WorkflowInterface::class)) { diff --git a/Tests/Functional/Integration/ExampleControllerTest.php b/Tests/Functional/Integration/ExampleControllerTest.php index 9f997dc0..df13eb59 100644 --- a/Tests/Functional/Integration/ExampleControllerTest.php +++ b/Tests/Functional/Integration/ExampleControllerTest.php @@ -64,6 +64,8 @@ public function testPostPublish(): int 'excerptCategories' => [], 'excerptIcon' => null, 'excerptMedia' => null, + 'author' => null, + 'authored' => null, ]) ?: null); $response = $this->client->getResponse(); diff --git a/Tests/Functional/Integration/responses/example_get.json b/Tests/Functional/Integration/responses/example_get.json index d5ad03bd..e78930a9 100644 --- a/Tests/Functional/Integration/responses/example_get.json +++ b/Tests/Functional/Integration/responses/example_get.json @@ -1,4 +1,6 @@ { + "author": null, + "authored": null, "excerptCategories": [], "excerptDescription": "Excerpt Description", "excerptIcon": null, diff --git a/Tests/Functional/Integration/responses/example_post.json b/Tests/Functional/Integration/responses/example_post.json index d5ad03bd..e78930a9 100644 --- a/Tests/Functional/Integration/responses/example_post.json +++ b/Tests/Functional/Integration/responses/example_post.json @@ -1,4 +1,6 @@ { + "author": null, + "authored": null, "excerptCategories": [], "excerptDescription": "Excerpt Description", "excerptIcon": null, diff --git a/Tests/Functional/Integration/responses/example_post_publish.json b/Tests/Functional/Integration/responses/example_post_publish.json index 34fed4ba..07863a01 100644 --- a/Tests/Functional/Integration/responses/example_post_publish.json +++ b/Tests/Functional/Integration/responses/example_post_publish.json @@ -1,4 +1,6 @@ { + "author": null, + "authored": null, "excerptCategories": [], "excerptDescription": "Excerpt Description", "excerptIcon": null, diff --git a/Tests/Functional/Integration/responses/example_post_trigger_unpublish.json b/Tests/Functional/Integration/responses/example_post_trigger_unpublish.json index 4d50c4a6..c3a11680 100644 --- a/Tests/Functional/Integration/responses/example_post_trigger_unpublish.json +++ b/Tests/Functional/Integration/responses/example_post_trigger_unpublish.json @@ -1,4 +1,6 @@ { + "author": null, + "authored": null, "excerptCategories": [], "excerptDescription": "Excerpt Description", "excerptIcon": null, diff --git a/Tests/Functional/Integration/responses/example_put.json b/Tests/Functional/Integration/responses/example_put.json index bef71882..589a6f6f 100644 --- a/Tests/Functional/Integration/responses/example_put.json +++ b/Tests/Functional/Integration/responses/example_put.json @@ -1,4 +1,6 @@ { + "author": null, + "authored": null, "article": "

Test Article 2

", "blocks": null, "description": null, diff --git a/Tests/Unit/Content/Infrastructure/Doctrine/MetadataLoaderTest.php b/Tests/Unit/Content/Infrastructure/Doctrine/MetadataLoaderTest.php index c4c6f476..322f0f56 100644 --- a/Tests/Unit/Content/Infrastructure/Doctrine/MetadataLoaderTest.php +++ b/Tests/Unit/Content/Infrastructure/Doctrine/MetadataLoaderTest.php @@ -22,6 +22,7 @@ use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Sulu\Bundle\CategoryBundle\Entity\CategoryInterface; +use Sulu\Bundle\ContentBundle\Content\Domain\Model\AuthorInterface; use Sulu\Bundle\ContentBundle\Content\Domain\Model\DimensionContentInterface; use Sulu\Bundle\ContentBundle\Content\Domain\Model\ExcerptInterface; use Sulu\Bundle\ContentBundle\Content\Domain\Model\SeoInterface; @@ -65,6 +66,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(AuthorInterface::class)->willReturn(\in_array(AuthorInterface::class, $interfaces, true)); foreach ($interfaces as $interface) { $reflectionClass->implementsInterface($interface)->willReturn(true); @@ -227,5 +229,19 @@ public function dataProvider(): \Generator ], [], ]; + + yield [ + [ + AuthorInterface::class, + ], + [ + 'author' => true, + 'authored' => true, + ], + [], + [ + 'author' => true, + ], + ]; } } diff --git a/Tests/Unit/Content/Infrastructure/Sulu/Admin/ContentViewBuilderFactoryTest.php b/Tests/Unit/Content/Infrastructure/Sulu/Admin/ContentViewBuilderFactoryTest.php index eea713b1..7edad29c 100644 --- a/Tests/Unit/Content/Infrastructure/Sulu/Admin/ContentViewBuilderFactoryTest.php +++ b/Tests/Unit/Content/Infrastructure/Sulu/Admin/ContentViewBuilderFactoryTest.php @@ -100,7 +100,7 @@ public function testCreateViews(): void $views = $contentViewBuilder->createViews(Example::class, 'edit_parent_key'); - $this->assertCount(3, $views); + $this->assertCount(4, $views); $this->assertInstanceOf(FormViewBuilderInterface::class, $views[0]); $this->assertSame('edit_parent_key.content', $views[0]->getName()); @@ -116,7 +116,7 @@ public function testCreateViews(): void $views = $contentViewBuilder->createViews(Example::class, 'edit_parent_key', 'add_parent_key'); - $this->assertCount(4, $views); + $this->assertCount(5, $views); $this->assertInstanceOf(FormViewBuilderInterface::class, $views[0]); $this->assertSame('add_parent_key.content', $views[0]->getName()); @@ -164,7 +164,7 @@ public function testCreateViewsWithPreview(): void $views = $contentViewBuilder->createViews(Example::class, 'edit_parent_key'); - $this->assertCount(3, $views); + $this->assertCount(4, $views); $this->assertInstanceOf(PreviewFormViewBuilderInterface::class, $views[0]); $this->assertInstanceOf(PreviewFormViewBuilderInterface::class, $views[1]); $this->assertInstanceOf(PreviewFormViewBuilderInterface::class, $views[2]); @@ -188,6 +188,7 @@ public function getSecurityContextData(): array ['sulu_admin.save_with_publishing', 'sulu_admin.type', 'sulu_admin.delete', 'sulu_admin.dropdown'], ['sulu_admin.save_with_publishing'], ['sulu_admin.save_with_publishing'], + ['sulu_admin.save_with_publishing'], ], ], [ @@ -201,6 +202,7 @@ public function getSecurityContextData(): array ['sulu_admin.save_with_publishing', 'sulu_admin.type', 'sulu_admin.delete', 'sulu_admin.dropdown'], ['sulu_admin.save_with_publishing'], ['sulu_admin.save_with_publishing'], + ['sulu_admin.save_with_publishing'], ], ], [ @@ -214,6 +216,7 @@ public function getSecurityContextData(): array ['sulu_admin.save_with_publishing', 'sulu_admin.type'], ['sulu_admin.save_with_publishing'], ['sulu_admin.save_with_publishing'], + ['sulu_admin.save_with_publishing'], ], ], [ @@ -239,6 +242,7 @@ public function getSecurityContextData(): array ['sulu_admin.save_with_publishing', 'sulu_admin.type', 'sulu_admin.delete'], ['sulu_admin.save_with_publishing'], ['sulu_admin.save_with_publishing'], + ['sulu_admin.save_with_publishing'], ], ], [ @@ -253,6 +257,7 @@ public function getSecurityContextData(): array ['sulu_admin.save_with_publishing', 'sulu_admin.type', 'sulu_admin.dropdown'], ['sulu_admin.save_with_publishing'], ['sulu_admin.save_with_publishing'], + ['sulu_admin.save_with_publishing'], ], ], ]; @@ -268,7 +273,6 @@ public function testCreateViewsWithSecurityContext(array $permissions, array $ex { $securityChecker = $this->prophesize(SecurityCheckerInterface::class); - $entityManager = $this->prophesize(EntityManagerInterface::class); $contentMetadataInspector = $this->prophesize(ContentMetadataInspectorInterface::class); $contentMetadataInspector->getDimensionContentClass(Example::class) ->willReturn(ExampleDimensionContent::class); @@ -323,6 +327,7 @@ public function getResource(): ContentRichEntityInterface [ ['sulu_admin.save'], ['sulu_admin.save'], + ['sulu_admin.save'], ], ], [ @@ -352,6 +357,7 @@ public static function getResourceKey(): string ['sulu_admin.save', 'sulu_admin.type', 'sulu_admin.delete'], ['sulu_admin.save'], ['sulu_admin.save'], + ['sulu_admin.save'], ], ], [ @@ -382,6 +388,7 @@ public static function getResourceKey(): string ['sulu_admin.save_with_publishing', 'sulu_admin.type', 'sulu_admin.delete', 'sulu_admin.dropdown'], ['sulu_admin.save_with_publishing'], ['sulu_admin.save_with_publishing'], + ['sulu_admin.save_with_publishing'], ], ], ]; diff --git a/Tests/Unit/SuluContentBundleTest.php b/Tests/Unit/SuluContentBundleTest.php index aba5ea1a..6c8f17d6 100644 --- a/Tests/Unit/SuluContentBundleTest.php +++ b/Tests/Unit/SuluContentBundleTest.php @@ -36,7 +36,7 @@ public function testPersistenceCompilerPass(): void $passConfig = $containerBuilder->getCompiler()->getPassConfig(); $this->assertSame( - 0, + 1, \count($passConfig->getPasses()) - $beforeCount ); } From 29bf9d00c5526c8dad96b49321ba7b5dce4bf935 Mon Sep 17 00:00:00 2001 From: Prokyonn Date: Fri, 30 Jul 2021 00:41:48 +0200 Subject: [PATCH 04/11] Add tests --- .../Doctrine/ContactFactoryTest.php | 59 ++++++ .../DataMapper/AuthorDataMapperTest.php | 160 ++++++++++++++++ .../ContentMerger/Merger/AuthorMergerTest.php | 93 ++++++++++ .../Normalizer/AuthorNormalizerTest.php | 93 ++++++++++ .../Content/Domain/Model/AuthorTraitTest.php | 47 +++++ .../Form/SettingsFormMetadataVisitorTest.php | 172 ++++++++++++++++++ 6 files changed, 624 insertions(+) create mode 100644 Tests/Functional/Content/Infrastructure/Doctrine/ContactFactoryTest.php create mode 100644 Tests/Unit/Content/Application/ContentDataMapper/DataMapper/AuthorDataMapperTest.php create mode 100644 Tests/Unit/Content/Application/ContentMerger/Merger/AuthorMergerTest.php create mode 100644 Tests/Unit/Content/Application/ContentNormalizer/Normalizer/AuthorNormalizerTest.php create mode 100644 Tests/Unit/Content/Domain/Model/AuthorTraitTest.php create mode 100644 Tests/Unit/Content/Infrastructure/Sulu/Form/SettingsFormMetadataVisitorTest.php diff --git a/Tests/Functional/Content/Infrastructure/Doctrine/ContactFactoryTest.php b/Tests/Functional/Content/Infrastructure/Doctrine/ContactFactoryTest.php new file mode 100644 index 00000000..2c7f18f1 --- /dev/null +++ b/Tests/Functional/Content/Infrastructure/Doctrine/ContactFactoryTest.php @@ -0,0 +1,59 @@ +get('sulu_content.contact_factory'); + } + + /** + * @dataProvider dataProvider + */ + public function testCreate(?int $contactId): void + { + $contactFactory = $this->createContactFactory(); + + $result = $contactFactory->create($contactId); + $this->assertSame( + $contactId, + $result ? $result->getId() : $result + ); + } + + /** + * @return \Generator + */ + public function dataProvider(): \Generator + { + yield [ + null, + ]; + + yield [ + 1, + ]; + } +} diff --git a/Tests/Unit/Content/Application/ContentDataMapper/DataMapper/AuthorDataMapperTest.php b/Tests/Unit/Content/Application/ContentDataMapper/DataMapper/AuthorDataMapperTest.php new file mode 100644 index 00000000..a1a71d6a --- /dev/null +++ b/Tests/Unit/Content/Application/ContentDataMapper/DataMapper/AuthorDataMapperTest.php @@ -0,0 +1,160 @@ + 1, + 'authored' => '2020-05-08T00:00:00+00:00', + ]; + + $unlocalizedDimensionContent = $this->prophesize(DimensionContentInterface::class); + + $dimensionContentCollection = $this->prophesize(DimensionContentCollectionInterface::class); + $dimensionContentCollection->getDimensionAttributes() + ->shouldBeCalled() + ->willReturn(['stage' => 'draft', 'locale' => 'de']); + $dimensionContentCollection->getDimensionContent(['stage' => 'draft', 'locale' => null]) + ->shouldBeCalled() + ->willReturn($unlocalizedDimensionContent); + + $contactFactory = $this->prophesize(ContactFactoryInterface::class); + + $authorMapper = $this->createAuthorDataMapperInstance($contactFactory->reveal()); + $authorMapper->map($data, $dimensionContentCollection->reveal()); + } + + public function testMapLocalizedNoAuthor(): void + { + $data = [ + 'author' => 1, + 'authored' => '2020-05-08T00:00:00+00:00', + ]; + + $unlocalizedDimensionContent = $this->prophesize(DimensionContentInterface::class); + $unlocalizedDimensionContent->willImplement(AuthorInterface::class); + + $localizedDimensionContent = $this->prophesize(DimensionContentInterface::class); + + $dimensionContentCollection = $this->prophesize(DimensionContentCollectionInterface::class); + $dimensionContentCollection->getDimensionAttributes() + ->shouldBeCalled() + ->willReturn(['stage' => 'draft', 'locale' => 'de']); + $dimensionContentCollection->getDimensionContent(['stage' => 'draft', 'locale' => null]) + ->willReturn($unlocalizedDimensionContent); + $dimensionContentCollection->getDimensionContent(['stage' => 'draft', 'locale' => 'de']) + ->willReturn($localizedDimensionContent->reveal()); + + $contactFactory = $this->prophesize(ContactFactoryInterface::class); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('Expected "$localizedObject" from type "Sulu\Bundle\ContentBundle\Content\Domain\Model\AuthorInterface" but "Double\DimensionContentInterface\P3" given.'); + + $authorMapper = $this->createAuthorDataMapperInstance($contactFactory->reveal()); + $authorMapper->map($data, $dimensionContentCollection->reveal()); + } + + public function testMapUnlocalizedAuthor(): void + { + $data = [ + 'author' => 1, + 'authored' => '2020-05-08T00:00:00+00:00', + ]; + $contact = $this->prophesize(ContactInterface::class); + $contactFactory = $this->prophesize(ContactFactoryInterface::class); + $contactFactory->create(1) + ->shouldBeCalled() + ->willReturn($contact->reveal()); + + $unlocalizedDimensionContent = $this->prophesize(DimensionContentInterface::class); + $unlocalizedDimensionContent->willImplement(AuthorInterface::class); + + $unlocalizedDimensionContent->setAuthor($contact->reveal()) + ->shouldBeCalled(); + $unlocalizedDimensionContent->setAuthored(Argument::that( + function (DateTimeImmutable $date) { + return $date->getTimestamp() === (new \DateTimeImmutable('2020-05-08T00:00:00+00:00'))->getTimestamp(); + }) + )->shouldBeCalled(); + + $dimensionContentCollection = $this->prophesize(DimensionContentCollectionInterface::class); + $dimensionContentCollection->getDimensionAttributes() + ->shouldBeCalled() + ->willReturn(['stage' => 'draft', 'locale' => 'de']); + $dimensionContentCollection->getDimensionContent(['stage' => 'draft', 'locale' => null]) + ->willReturn($unlocalizedDimensionContent->reveal()); + $dimensionContentCollection->getDimensionContent(['stage' => 'draft', 'locale' => 'de']) + ->willReturn(null); + + $authorMapper = $this->createAuthorDataMapperInstance($contactFactory->reveal()); + $authorMapper->map($data, $dimensionContentCollection->reveal()); + } + + public function testMapLocalizedAuthor(): void + { + $data = [ + 'author' => 1, + 'authored' => '2020-05-08T00:00:00+00:00', + ]; + $contact = $this->prophesize(ContactInterface::class); + $contactFactory = $this->prophesize(ContactFactoryInterface::class); + $contactFactory->create(1) + ->shouldBeCalled() + ->willReturn($contact->reveal()); + + $unlocalizedDimensionContent = $this->prophesize(DimensionContentInterface::class); + $unlocalizedDimensionContent->willImplement(AuthorInterface::class); + + $localizedDimensionContent = $this->prophesize(DimensionContentInterface::class); + $localizedDimensionContent->willImplement(AuthorInterface::class); + + $localizedDimensionContent->setAuthor($contact->reveal()) + ->shouldBeCalled(); + $localizedDimensionContent->setAuthored(Argument::that( + function (DateTimeImmutable $date) { + return $date->getTimestamp() === (new \DateTimeImmutable('2020-05-08T00:00:00+00:00'))->getTimestamp(); + }) + )->shouldBeCalled(); + + $dimensionContentCollection = $this->prophesize(DimensionContentCollectionInterface::class); + $dimensionContentCollection->getDimensionAttributes() + ->shouldBeCalled() + ->willReturn(['stage' => 'draft', 'locale' => 'de']); + $dimensionContentCollection->getDimensionContent(['stage' => 'draft', 'locale' => null]) + ->willReturn($unlocalizedDimensionContent->reveal()); + $dimensionContentCollection->getDimensionContent(['stage' => 'draft', 'locale' => 'de']) + ->willReturn($localizedDimensionContent->reveal()); + + $authorMapper = $this->createAuthorDataMapperInstance($contactFactory->reveal()); + $authorMapper->map($data, $dimensionContentCollection->reveal()); + } +} diff --git a/Tests/Unit/Content/Application/ContentMerger/Merger/AuthorMergerTest.php b/Tests/Unit/Content/Application/ContentMerger/Merger/AuthorMergerTest.php new file mode 100644 index 00000000..693dcee1 --- /dev/null +++ b/Tests/Unit/Content/Application/ContentMerger/Merger/AuthorMergerTest.php @@ -0,0 +1,93 @@ +getAuthorMergerInstance(); + + $source = $this->prophesize(DimensionContentInterface::class); + + $target = $this->prophesize(DimensionContentInterface::class); + $target->willImplement(AuthorInterface::class); + $target->setAuthor(Argument::any())->shouldNotBeCalled(); + + $merger->merge($target->reveal(), $source->reveal()); + } + + public function testMergeTargetNotImplementAuthorInterface(): void + { + $merger = $this->getAuthorMergerInstance(); + + $source = $this->prophesize(DimensionContentInterface::class); + $source->willImplement(AuthorInterface::class); + $source->getAuthor(Argument::any())->shouldNotBeCalled(); + + $target = $this->prophesize(DimensionContentInterface::class); + + $merger->merge($target->reveal(), $source->reveal()); + } + + public function testMergeSet(): void + { + $merger = $this->getAuthorMergerInstance(); + + $contact = $this->prophesize(ContactInterface::class); + $authoredDate = new \DateTimeImmutable('2020-05-08T00:00:00+00:00'); + + $source = $this->prophesize(DimensionContentInterface::class); + $source->willImplement(AuthorInterface::class); + $source->getAuthor()->willReturn($contact->reveal())->shouldBeCalled(); + $source->getAuthored()->willReturn($authoredDate)->shouldBeCalled(); + + $target = $this->prophesize(DimensionContentInterface::class); + $target->willImplement(AuthorInterface::class); + $target->setAuthor($contact->reveal())->shouldBeCalled(); + $target->setAuthored($authoredDate)->shouldBeCalled(); + + $merger->merge($target->reveal(), $source->reveal()); + } + + public function testMergeNotSet(): void + { + $merger = $this->getAuthorMergerInstance(); + + $source = $this->prophesize(DimensionContentInterface::class); + $source->willImplement(AuthorInterface::class); + $source->getAuthor()->willReturn(null)->shouldBeCalled(); + $source->getAuthored()->willReturn(null)->shouldBeCalled(); + + $target = $this->prophesize(DimensionContentInterface::class); + $target->willImplement(AuthorInterface::class); + $target->setAuthor(Argument::any())->shouldNotBeCalled(); + $target->setAuthored(Argument::any())->shouldNotBeCalled(); + + $merger->merge($target->reveal(), $source->reveal()); + } +} diff --git a/Tests/Unit/Content/Application/ContentNormalizer/Normalizer/AuthorNormalizerTest.php b/Tests/Unit/Content/Application/ContentNormalizer/Normalizer/AuthorNormalizerTest.php new file mode 100644 index 00000000..1e79951f --- /dev/null +++ b/Tests/Unit/Content/Application/ContentNormalizer/Normalizer/AuthorNormalizerTest.php @@ -0,0 +1,93 @@ +createAuthorNormalizerInstance(); + $object = $this->prophesize(\stdClass::class); + + $this->assertSame( + [], + $normalizer->getIgnoredAttributes($object->reveal()) + ); + } + + public function testIgnoredAttributes(): void + { + $normalizer = $this->createAuthorNormalizerInstance(); + $object = $this->prophesize(AuthorInterface::class); + + $this->assertSame( + [ + 'author', + ], + $normalizer->getIgnoredAttributes($object->reveal()) + ); + } + + public function testEnhanceNotImplementAuthorInterface(): void + { + $normalizer = $this->createAuthorNormalizerInstance(); + $object = $this->prophesize(\stdClass::class); + + $data = [ + 'author' => 1, + 'authored' => new \DateTimeImmutable('2020-05-08T00:00:00+00:00'), + ]; + + $this->assertSame( + $data, + $normalizer->enhance($object->reveal(), $data) + ); + } + + public function testEnhance(): void + { + $normalizer = $this->createAuthorNormalizerInstance(); + $object = $this->prophesize(AuthorInterface::class); + + $contact = $this->prophesize(ContactInterface::class); + $contact->getId()->shouldBeCalled()->willReturn(1); + $object->getAuthor()->willReturn($contact->reveal()); + $authored = new \DateTimeImmutable('2020-05-08T00:00:00+00:00'); + + $data = [ + 'author' => $contact->reveal(), + 'authored' => $authored, + ]; + + $expectedResult = [ + 'author' => 1, + 'authored' => $authored, + ]; + + $this->assertSame( + $expectedResult, + $normalizer->enhance($object->reveal(), $data) + ); + } +} diff --git a/Tests/Unit/Content/Domain/Model/AuthorTraitTest.php b/Tests/Unit/Content/Domain/Model/AuthorTraitTest.php new file mode 100644 index 00000000..99488ea7 --- /dev/null +++ b/Tests/Unit/Content/Domain/Model/AuthorTraitTest.php @@ -0,0 +1,47 @@ +getAuthorInstance(); + $author = $this->prophesize(ContactInterface::class); + $this->assertNull($model->getAuthor()); + $model->setAuthor($author->reveal()); + $this->assertSame($author->reveal(), $model->getAuthor()); + } + + public function testGetSetAuthored(): void + { + $model = $this->getAuthorInstance(); + $authored = new \DateTimeImmutable('2020-05-08T00:00:00+00:00'); + $this->assertNull($model->getAuthored()); + $model->setAuthored($authored); + $this->assertSame($authored, $model->getAuthored()); + } +} diff --git a/Tests/Unit/Content/Infrastructure/Sulu/Form/SettingsFormMetadataVisitorTest.php b/Tests/Unit/Content/Infrastructure/Sulu/Form/SettingsFormMetadataVisitorTest.php new file mode 100644 index 00000000..e2b71c30 --- /dev/null +++ b/Tests/Unit/Content/Infrastructure/Sulu/Form/SettingsFormMetadataVisitorTest.php @@ -0,0 +1,172 @@ +xmlFormMetadataLoader = $this->prophesize(XmlFormMetadataLoader::class); + $this->settingsFormMetadataVisitor = new SettingsFormMetadataVisitor($this->xmlFormMetadataLoader->reveal()); + } + + public function testVisitFormMetadataInvalidKey(): void + { + $formMetadata = $this->prophesize(FormMetadata::class); + $formMetadata->getKey() + ->shouldBeCalled() + ->willReturn('invalid_key'); + + $this->xmlFormMetadataLoader->getMetadata(Argument::any(), Argument::any(), Argument::any()) + ->shouldNotBeCalled(); + + $this->settingsFormMetadataVisitor->visitFormMetadata($formMetadata->reveal(), 'de', []); + } + + public function testVisitFormMetadataWithoutForms(): void + { + $formMetadata = $this->prophesize(FormMetadata::class); + $formMetadata->getKey() + ->shouldBeCalled() + ->willReturn('content_settings'); + + $this->xmlFormMetadataLoader->getMetadata(Argument::any(), Argument::any(), Argument::any()) + ->shouldNotBeCalled(); + + $this->settingsFormMetadataVisitor->visitFormMetadata($formMetadata->reveal(), 'de', []); + } + + public function testVisitFormMetadataInvalidSubFormMetadata(): void + { + $formMetadata = $this->prophesize(FormMetadata::class); + $formMetadata->getKey() + ->shouldBeCalled() + ->willReturn('content_settings'); + + $formMetadata->setItems(Argument::any()) + ->shouldNotBeCalled(); + $formMetadata->setSchema(Argument::any()) + ->shouldNotBeCalled(); + + $subFormMetadata = $this->prophesize(MetadataInterface::class); + + $metadataOptions = [ + 'forms' => ['content_settings_author'], + ]; + + $this->xmlFormMetadataLoader->getMetadata('content_settings_author', 'de', $metadataOptions) + ->shouldBeCalled() + ->willReturn($subFormMetadata->reveal()); + + $this->settingsFormMetadataVisitor->visitFormMetadata($formMetadata->reveal(), 'de', $metadataOptions); + } + + public function testVisitFormMetadataSubFormMetadataIsNull(): void + { + $formMetadata = $this->prophesize(FormMetadata::class); + $formMetadata->getKey() + ->shouldBeCalled() + ->willReturn('content_settings'); + + $formMetadata->setItems(Argument::any()) + ->shouldNotBeCalled(); + $formMetadata->setSchema(Argument::any()) + ->shouldNotBeCalled(); + + $metadataOptions = [ + 'forms' => ['content_settings_author'], + ]; + + $this->xmlFormMetadataLoader->getMetadata('content_settings_author', 'de', $metadataOptions) + ->shouldBeCalled() + ->willReturn(null); + + $this->settingsFormMetadataVisitor->visitFormMetadata($formMetadata->reveal(), 'de', $metadataOptions); + } + + public function testVisitFormMetadata(): void + { + $oldItemMetadata1 = $this->prophesize(ItemMetadata::class); + $oldItemMetadata2 = $this->prophesize(ItemMetadata::class); + + $formMetadata = $this->prophesize(FormMetadata::class); + $formMetadata->getKey() + ->shouldBeCalled() + ->willReturn('content_settings'); + $formMetadata->getItems() + ->shouldBeCalled() + ->willReturn([$oldItemMetadata1, $oldItemMetadata2]); + $oldSchemaMetadata = $this->prophesize(SchemaMetadata::class); + $formMetadata->getSchema() + ->shouldBeCalled() + ->willReturn($oldSchemaMetadata); + + $metadataOptions = [ + 'forms' => ['content_settings_author'], + ]; + + $newItemMetadata1 = $this->prophesize(ItemMetadata::class); + $newItemMetadata2 = $this->prophesize(ItemMetadata::class); + $subFormMetadata = $this->prophesize(FormMetadata::class); + $subFormMetadata->getItems() + ->shouldBeCalled() + ->willReturn([$newItemMetadata1, $newItemMetadata2]); + $newSchemaMetadata = $this->prophesize(SchemaMetadata::class); + $subFormMetadata->getSchema() + ->shouldBeCalled() + ->willReturn($newSchemaMetadata); + + $formMetadata->setItems([ + $oldItemMetadata1, + $oldItemMetadata2, + $newItemMetadata1, + $newItemMetadata2, + ])->shouldBeCalled(); + + $mergedSchemaMetadata = $this->prophesize(SchemaMetadata::class); + $oldSchemaMetadata->merge($newSchemaMetadata) + ->shouldBeCalled() + ->willReturn($mergedSchemaMetadata); + $formMetadata->setSchema($mergedSchemaMetadata) + ->shouldBeCalled(); + + $this->xmlFormMetadataLoader->getMetadata('content_settings_author', 'de', $metadataOptions) + ->shouldBeCalled() + ->willReturn($subFormMetadata->reveal()); + + $this->settingsFormMetadataVisitor->visitFormMetadata($formMetadata->reveal(), 'de', $metadataOptions); + } +} From 57639c0f4d96939b19b1a6cee5e84c0d6e67bfcc Mon Sep 17 00:00:00 2001 From: Prokyonn Date: Fri, 30 Jul 2021 09:45:02 +0200 Subject: [PATCH 05/11] Add missing tests --- .../Compiler/SettingsFormPass.php | 9 +--- .../Admin/ContentViewBuilderFactoryTest.php | 17 +++++-- .../Compiler/SettingsFormPassTest.php | 49 +++++++++++++++++++ .../content_settings_author.xml | 29 +++++++++++ .../content_settings_no_interface.xml | 12 +++++ .../content_settings_no_tag.xml | 10 ++++ .../SettingsFormXml/content_settings_seo.xml | 12 +++++ 7 files changed, 128 insertions(+), 10 deletions(-) create mode 100644 Tests/Unit/DependencyInjection/Compiler/SettingsFormPassTest.php create mode 100644 Tests/Unit/DependencyInjection/Compiler/SettingsFormXml/content_settings_author.xml create mode 100644 Tests/Unit/DependencyInjection/Compiler/SettingsFormXml/content_settings_no_interface.xml create mode 100644 Tests/Unit/DependencyInjection/Compiler/SettingsFormXml/content_settings_no_tag.xml create mode 100644 Tests/Unit/DependencyInjection/Compiler/SettingsFormXml/content_settings_seo.xml diff --git a/DependencyInjection/Compiler/SettingsFormPass.php b/DependencyInjection/Compiler/SettingsFormPass.php index 3c2ec689..6312c2d3 100644 --- a/DependencyInjection/Compiler/SettingsFormPass.php +++ b/DependencyInjection/Compiler/SettingsFormPass.php @@ -29,12 +29,7 @@ public function process(ContainerBuilder $container): void $settingsForms = []; foreach ($finder as $file) { $document = new \DOMDocument(); - - if (!$xmlContent = file_get_contents($file->getPathname())) { - continue; - } - - $document->loadXML($xmlContent); + $document->load($file->getPathname()); $path = new \DOMXPath($document); $path->registerNamespace('x', FormXmlLoader::SCHEMA_NAMESPACE_URI); $tagNodes = $path->query('/x:form/x:tag'); @@ -60,7 +55,7 @@ public function process(ContainerBuilder $container): void } uasort($settingsForms, static function ($a, $b) { - return $b['priority'] <=> $a['priority']; + return $b['priority'] ?? 0 <=> $a['priority'] ?? 0; }); $container->setParameter('sulu_content.settings_forms', $settingsForms); diff --git a/Tests/Unit/Content/Infrastructure/Sulu/Admin/ContentViewBuilderFactoryTest.php b/Tests/Unit/Content/Infrastructure/Sulu/Admin/ContentViewBuilderFactoryTest.php index 7edad29c..f1197fb7 100644 --- a/Tests/Unit/Content/Infrastructure/Sulu/Admin/ContentViewBuilderFactoryTest.php +++ b/Tests/Unit/Content/Infrastructure/Sulu/Admin/ContentViewBuilderFactoryTest.php @@ -21,6 +21,7 @@ use Sulu\Bundle\ContentBundle\Content\Application\ContentDataMapper\ContentDataMapperInterface; use Sulu\Bundle\ContentBundle\Content\Application\ContentMetadataInspector\ContentMetadataInspectorInterface; use Sulu\Bundle\ContentBundle\Content\Application\ContentResolver\ContentResolverInterface; +use Sulu\Bundle\ContentBundle\Content\Domain\Model\AuthorInterface; use Sulu\Bundle\ContentBundle\Content\Domain\Model\ContentRichEntityInterface; use Sulu\Bundle\ContentBundle\Content\Domain\Model\DimensionContentInterface; use Sulu\Bundle\ContentBundle\Content\Domain\Model\DimensionContentTrait; @@ -45,10 +46,14 @@ class ContentViewBuilderFactoryTest extends TestCase { + /** + * @param mixed[] $settingsForms + */ protected function createContentViewBuilder( ContentMetadataInspectorInterface $contentMetadataInspector, SecurityCheckerInterface $securityChecker, - PreviewObjectProviderRegistryInterface $previewObjectProviderRegistry = null + PreviewObjectProviderRegistryInterface $previewObjectProviderRegistry = null, + array $settingsForms = [] ): ContentViewBuilderFactoryInterface { if (null === $previewObjectProviderRegistry) { $previewObjectProviderRegistry = $this->createPreviewObjectProviderRegistry([]); @@ -59,7 +64,7 @@ protected function createContentViewBuilder( $previewObjectProviderRegistry, $contentMetadataInspector, $securityChecker, - [] + $settingsForms ); } @@ -96,7 +101,13 @@ public function testCreateViews(): void $contentMetadataInspector->getDimensionContentClass(Example::class) ->willReturn(ExampleDimensionContent::class); - $contentViewBuilder = $this->createContentViewBuilder($contentMetadataInspector->reveal(), $securityChecker->reveal()); + $settingsForms = [ + 'content_settings_author' => [ + 'instanceOf' => AuthorInterface::class, + 'priority' => 128, + ], + ]; + $contentViewBuilder = $this->createContentViewBuilder($contentMetadataInspector->reveal(), $securityChecker->reveal(), null, $settingsForms); $views = $contentViewBuilder->createViews(Example::class, 'edit_parent_key'); diff --git a/Tests/Unit/DependencyInjection/Compiler/SettingsFormPassTest.php b/Tests/Unit/DependencyInjection/Compiler/SettingsFormPassTest.php new file mode 100644 index 00000000..0dd86875 --- /dev/null +++ b/Tests/Unit/DependencyInjection/Compiler/SettingsFormPassTest.php @@ -0,0 +1,49 @@ +prophesize(ContainerBuilder::class); + $container->getParameter('sulu_admin.forms.directories') + ->shouldBeCalled() + ->willReturn($directories); + + $container->setParameter('sulu_content.settings_forms', [ + 'content_settings_seo' => [ + 'instanceOf' => SeoInterface::class, + 'priority' => 256, + ], + 'content_settings_author' => [ + 'instanceOf' => AuthorInterface::class, + 'priority' => 128, + ], + ])->shouldBeCalled(); + + $settingsFormPass = new SettingsFormPass(); + $settingsFormPass->process($container->reveal()); + } +} diff --git a/Tests/Unit/DependencyInjection/Compiler/SettingsFormXml/content_settings_author.xml b/Tests/Unit/DependencyInjection/Compiler/SettingsFormXml/content_settings_author.xml new file mode 100644 index 00000000..c205090d --- /dev/null +++ b/Tests/Unit/DependencyInjection/Compiler/SettingsFormXml/content_settings_author.xml @@ -0,0 +1,29 @@ + +
+ content_settings_author + + + + +
+ + sulu_content.author + + + + + sulu_content.authored_date + + + + + sulu_content.author + + + +
+
+ diff --git a/Tests/Unit/DependencyInjection/Compiler/SettingsFormXml/content_settings_no_interface.xml b/Tests/Unit/DependencyInjection/Compiler/SettingsFormXml/content_settings_no_interface.xml new file mode 100644 index 00000000..cb5c1f02 --- /dev/null +++ b/Tests/Unit/DependencyInjection/Compiler/SettingsFormXml/content_settings_no_interface.xml @@ -0,0 +1,12 @@ + +
+ content_settings_no_interface + + + + + + diff --git a/Tests/Unit/DependencyInjection/Compiler/SettingsFormXml/content_settings_no_tag.xml b/Tests/Unit/DependencyInjection/Compiler/SettingsFormXml/content_settings_no_tag.xml new file mode 100644 index 00000000..864fce8a --- /dev/null +++ b/Tests/Unit/DependencyInjection/Compiler/SettingsFormXml/content_settings_no_tag.xml @@ -0,0 +1,10 @@ + +
+ content_settings_no_tag + + + +
diff --git a/Tests/Unit/DependencyInjection/Compiler/SettingsFormXml/content_settings_seo.xml b/Tests/Unit/DependencyInjection/Compiler/SettingsFormXml/content_settings_seo.xml new file mode 100644 index 00000000..722127fb --- /dev/null +++ b/Tests/Unit/DependencyInjection/Compiler/SettingsFormXml/content_settings_seo.xml @@ -0,0 +1,12 @@ + +
+ content_settings_seo + + + + + + From 8f4e0c7e333372e584221a57eb3f3a66e089fe52 Mon Sep 17 00:00:00 2001 From: Prokyonn Date: Fri, 30 Jul 2021 09:54:02 +0200 Subject: [PATCH 06/11] Fix compiler pass test --- DependencyInjection/Compiler/SettingsFormPass.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DependencyInjection/Compiler/SettingsFormPass.php b/DependencyInjection/Compiler/SettingsFormPass.php index 6312c2d3..a36beb91 100644 --- a/DependencyInjection/Compiler/SettingsFormPass.php +++ b/DependencyInjection/Compiler/SettingsFormPass.php @@ -34,7 +34,7 @@ public function process(ContainerBuilder $container): void $path->registerNamespace('x', FormXmlLoader::SCHEMA_NAMESPACE_URI); $tagNodes = $path->query('/x:form/x:tag'); - if (!$tagNodes) { + if (!$tagNodes || 0 === $tagNodes->count()) { continue; } From 5c36019ab563b3b75cb8441fab6ca9356314bf74 Mon Sep 17 00:00:00 2001 From: Prokyonn Date: Fri, 30 Jul 2021 10:34:46 +0200 Subject: [PATCH 07/11] Increase sulu requirement to > 2.3 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index afda39d5..b7844ad9 100644 --- a/composer.json +++ b/composer.json @@ -20,7 +20,7 @@ "friendsofsymfony/rest-bundle": "^2.6 || ^3.0", "massive/search-bundle": "^2.4", "ramsey/uuid": "^3.8 || ^4.0", - "sulu/sulu": "^2.1 || ^2.3@dev", + "sulu/sulu": "^2.3@dev", "symfony/config": "^4.4 || ^5.0", "symfony/dependency-injection": "^4.4 || ^5.0", "symfony/event-dispatcher": "^4.4 || ^5.0", From b10440b87ea134913b38767260b95adea13bd198 Mon Sep 17 00:00:00 2001 From: Prokyonn Date: Fri, 30 Jul 2021 11:15:12 +0200 Subject: [PATCH 08/11] Apply suggestions from code review Co-authored-by: Alexander Schranz --- Content/Domain/Model/AuthorTrait.php | 2 +- .../Infrastructure/Sulu/Form/SettingsFormMetadataVisitor.php | 3 +++ DependencyInjection/Compiler/SettingsFormPass.php | 2 +- Resources/config/forms/content_settings_author.xml | 2 +- composer.json | 2 +- 5 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Content/Domain/Model/AuthorTrait.php b/Content/Domain/Model/AuthorTrait.php index 799396f7..088a49e7 100644 --- a/Content/Domain/Model/AuthorTrait.php +++ b/Content/Domain/Model/AuthorTrait.php @@ -16,7 +16,7 @@ use Sulu\Bundle\ContactBundle\Entity\ContactInterface; /** - * Basic implementation of the AuthorTrait. + * Basic implementation of the AuthorInterface. */ trait AuthorTrait { diff --git a/Content/Infrastructure/Sulu/Form/SettingsFormMetadataVisitor.php b/Content/Infrastructure/Sulu/Form/SettingsFormMetadataVisitor.php index 23bb6f8a..2962c6ca 100644 --- a/Content/Infrastructure/Sulu/Form/SettingsFormMetadataVisitor.php +++ b/Content/Infrastructure/Sulu/Form/SettingsFormMetadataVisitor.php @@ -17,6 +17,9 @@ use Sulu\Bundle\AdminBundle\Metadata\FormMetadata\FormMetadataVisitorInterface; use Sulu\Bundle\AdminBundle\Metadata\FormMetadata\XmlFormMetadataLoader; +/** + * @internal + */ class SettingsFormMetadataVisitor implements FormMetadataVisitorInterface { /** diff --git a/DependencyInjection/Compiler/SettingsFormPass.php b/DependencyInjection/Compiler/SettingsFormPass.php index a36beb91..ceeb1751 100644 --- a/DependencyInjection/Compiler/SettingsFormPass.php +++ b/DependencyInjection/Compiler/SettingsFormPass.php @@ -58,6 +58,6 @@ public function process(ContainerBuilder $container): void return $b['priority'] ?? 0 <=> $a['priority'] ?? 0; }); - $container->setParameter('sulu_content.settings_forms', $settingsForms); + $container->setParameter('sulu_content.content_settings_forms', $settingsForms); } } diff --git a/Resources/config/forms/content_settings_author.xml b/Resources/config/forms/content_settings_author.xml index c205090d..01fb7967 100644 --- a/Resources/config/forms/content_settings_author.xml +++ b/Resources/config/forms/content_settings_author.xml @@ -5,7 +5,7 @@ > content_settings_author - +
diff --git a/composer.json b/composer.json index b7844ad9..c244f135 100644 --- a/composer.json +++ b/composer.json @@ -20,7 +20,7 @@ "friendsofsymfony/rest-bundle": "^2.6 || ^3.0", "massive/search-bundle": "^2.4", "ramsey/uuid": "^3.8 || ^4.0", - "sulu/sulu": "^2.3@dev", + "sulu/sulu": "^2.3 || ^2.3@dev", "symfony/config": "^4.4 || ^5.0", "symfony/dependency-injection": "^4.4 || ^5.0", "symfony/event-dispatcher": "^4.4 || ^5.0", From b9b0b953bdd598cdbb4e183012bc42ebb5f95154 Mon Sep 17 00:00:00 2001 From: Prokyonn Date: Fri, 30 Jul 2021 12:29:48 +0200 Subject: [PATCH 09/11] Add review suggestions --- .../Compiler/SettingsFormPass.php | 29 +++++++++--- .../config/forms/content_settings_author.xml | 2 +- Resources/config/services.xml | 2 +- .../Integration/ExampleControllerTest.php | 3 +- .../Integration/responses/example_get.json | 2 +- .../Integration/responses/example_post.json | 2 +- .../responses/example_post_publish.json | 2 +- .../example_post_trigger_unpublish.json | 2 +- .../Integration/responses/example_put.json | 2 +- .../content_settings_no_interface.xml | 2 +- .../NoKey/content_settings_no_key.xml | 11 +++++ .../Compiler/SettingsFormPassTest.php | 44 +++++++++++++++++-- .../content_settings_author.xml | 2 +- .../content_settings_no_tag.xml | 0 .../content_settings_seo.xml | 2 +- 15 files changed, 87 insertions(+), 20 deletions(-) rename Tests/Unit/DependencyInjection/Compiler/{SettingsFormXml => InvalidSettingsForms/NoInterface}/content_settings_no_interface.xml (83%) create mode 100644 Tests/Unit/DependencyInjection/Compiler/InvalidSettingsForms/NoKey/content_settings_no_key.xml rename Tests/Unit/DependencyInjection/Compiler/{SettingsFormXml => SettingsForms}/content_settings_author.xml (87%) rename Tests/Unit/DependencyInjection/Compiler/{SettingsFormXml => SettingsForms}/content_settings_no_tag.xml (100%) rename Tests/Unit/DependencyInjection/Compiler/{SettingsFormXml => SettingsForms}/content_settings_seo.xml (70%) diff --git a/DependencyInjection/Compiler/SettingsFormPass.php b/DependencyInjection/Compiler/SettingsFormPass.php index ceeb1751..5cf83852 100644 --- a/DependencyInjection/Compiler/SettingsFormPass.php +++ b/DependencyInjection/Compiler/SettingsFormPass.php @@ -30,24 +30,43 @@ public function process(ContainerBuilder $container): void foreach ($finder as $file) { $document = new \DOMDocument(); $document->load($file->getPathname()); - $path = new \DOMXPath($document); - $path->registerNamespace('x', FormXmlLoader::SCHEMA_NAMESPACE_URI); - $tagNodes = $path->query('/x:form/x:tag'); + $xPath = new \DOMXPath($document); + $xPath->registerNamespace('x', FormXmlLoader::SCHEMA_NAMESPACE_URI); + $tagNodes = $xPath->query('/x:form/x:tag'); + $keyNodes = $xPath->query('/x:form/x:key'); if (!$tagNodes || 0 === $tagNodes->count()) { continue; } + $key = null; + if ($keyNodes && $keyNodes->count() > 0) { + $item = $keyNodes->item(0); + $key = $item->nodeValue ?? null; + } + + if (!$keyNodes || !$key) { + throw new \RuntimeException( + 'Forms must have a valid "key" element!' + ); + } + /** @var \DOMElement $tagNode */ foreach ($tagNodes as $tagNode) { $instanceOf = $tagNode->getAttribute('instanceOf'); $priority = $tagNode->getAttribute('priority'); - if (empty($instanceOf)) { + if ('sulu_content.content_settings_form' !== $tagNode->getAttribute('name')) { continue; } - $settingsForms[$tagNode->getAttribute('name')] = [ + if (empty($instanceOf)) { + throw new \RuntimeException( + 'Tags with the name "sulu_content.content_settings_form" must have a valid "instanceOf" attribute! ' + ); + } + + $settingsForms[$key] = [ 'instanceOf' => $instanceOf, 'priority' => $priority, ]; diff --git a/Resources/config/forms/content_settings_author.xml b/Resources/config/forms/content_settings_author.xml index 01fb7967..920dc16c 100644 --- a/Resources/config/forms/content_settings_author.xml +++ b/Resources/config/forms/content_settings_author.xml @@ -5,7 +5,7 @@ > content_settings_author - +
diff --git a/Resources/config/services.xml b/Resources/config/services.xml index 598b7e99..f85a6170 100644 --- a/Resources/config/services.xml +++ b/Resources/config/services.xml @@ -13,7 +13,7 @@ - %sulu_content.settings_forms% + %sulu_content.content_settings_forms% diff --git a/Tests/Functional/Integration/ExampleControllerTest.php b/Tests/Functional/Integration/ExampleControllerTest.php index df13eb59..3b024edd 100644 --- a/Tests/Functional/Integration/ExampleControllerTest.php +++ b/Tests/Functional/Integration/ExampleControllerTest.php @@ -65,7 +65,7 @@ public function testPostPublish(): int 'excerptIcon' => null, 'excerptMedia' => null, 'author' => null, - 'authored' => null, + 'authored' => '2020-05-08T00:00:00+00:00', ]) ?: null); $response = $this->client->getResponse(); @@ -114,6 +114,7 @@ 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', diff --git a/Tests/Functional/Integration/responses/example_get.json b/Tests/Functional/Integration/responses/example_get.json index e78930a9..4ea0b4a5 100644 --- a/Tests/Functional/Integration/responses/example_get.json +++ b/Tests/Functional/Integration/responses/example_get.json @@ -1,6 +1,6 @@ { "author": null, - "authored": null, + "authored": "2020-05-08T00:00:00+00:00", "excerptCategories": [], "excerptDescription": "Excerpt Description", "excerptIcon": null, diff --git a/Tests/Functional/Integration/responses/example_post.json b/Tests/Functional/Integration/responses/example_post.json index e78930a9..4ea0b4a5 100644 --- a/Tests/Functional/Integration/responses/example_post.json +++ b/Tests/Functional/Integration/responses/example_post.json @@ -1,6 +1,6 @@ { "author": null, - "authored": null, + "authored": "2020-05-08T00:00:00+00:00", "excerptCategories": [], "excerptDescription": "Excerpt Description", "excerptIcon": null, diff --git a/Tests/Functional/Integration/responses/example_post_publish.json b/Tests/Functional/Integration/responses/example_post_publish.json index 07863a01..3a862ceb 100644 --- a/Tests/Functional/Integration/responses/example_post_publish.json +++ b/Tests/Functional/Integration/responses/example_post_publish.json @@ -1,6 +1,6 @@ { "author": null, - "authored": null, + "authored": "2020-05-08T00:00:00+00:00", "excerptCategories": [], "excerptDescription": "Excerpt Description", "excerptIcon": null, diff --git a/Tests/Functional/Integration/responses/example_post_trigger_unpublish.json b/Tests/Functional/Integration/responses/example_post_trigger_unpublish.json index c3a11680..963a1022 100644 --- a/Tests/Functional/Integration/responses/example_post_trigger_unpublish.json +++ b/Tests/Functional/Integration/responses/example_post_trigger_unpublish.json @@ -1,6 +1,6 @@ { "author": null, - "authored": null, + "authored": "2020-05-08T00:00:00+00:00", "excerptCategories": [], "excerptDescription": "Excerpt Description", "excerptIcon": null, diff --git a/Tests/Functional/Integration/responses/example_put.json b/Tests/Functional/Integration/responses/example_put.json index 589a6f6f..2e89dd25 100644 --- a/Tests/Functional/Integration/responses/example_put.json +++ b/Tests/Functional/Integration/responses/example_put.json @@ -1,6 +1,6 @@ { "author": null, - "authored": null, + "authored": "2020-05-08T00:00:00+00:00", "article": "

Test Article 2

", "blocks": null, "description": null, diff --git a/Tests/Unit/DependencyInjection/Compiler/SettingsFormXml/content_settings_no_interface.xml b/Tests/Unit/DependencyInjection/Compiler/InvalidSettingsForms/NoInterface/content_settings_no_interface.xml similarity index 83% rename from Tests/Unit/DependencyInjection/Compiler/SettingsFormXml/content_settings_no_interface.xml rename to Tests/Unit/DependencyInjection/Compiler/InvalidSettingsForms/NoInterface/content_settings_no_interface.xml index cb5c1f02..99bfcf64 100644 --- a/Tests/Unit/DependencyInjection/Compiler/SettingsFormXml/content_settings_no_interface.xml +++ b/Tests/Unit/DependencyInjection/Compiler/InvalidSettingsForms/NoInterface/content_settings_no_interface.xml @@ -5,7 +5,7 @@ > content_settings_no_interface - + diff --git a/Tests/Unit/DependencyInjection/Compiler/InvalidSettingsForms/NoKey/content_settings_no_key.xml b/Tests/Unit/DependencyInjection/Compiler/InvalidSettingsForms/NoKey/content_settings_no_key.xml new file mode 100644 index 00000000..ed6665bd --- /dev/null +++ b/Tests/Unit/DependencyInjection/Compiler/InvalidSettingsForms/NoKey/content_settings_no_key.xml @@ -0,0 +1,11 @@ + +
+ + + + + + diff --git a/Tests/Unit/DependencyInjection/Compiler/SettingsFormPassTest.php b/Tests/Unit/DependencyInjection/Compiler/SettingsFormPassTest.php index 0dd86875..13d7773a 100644 --- a/Tests/Unit/DependencyInjection/Compiler/SettingsFormPassTest.php +++ b/Tests/Unit/DependencyInjection/Compiler/SettingsFormPassTest.php @@ -24,7 +24,7 @@ class SettingsFormPassTest extends TestCase public function testProcess(): void { $directories = [ - __DIR__ . \DIRECTORY_SEPARATOR . 'SettingsFormXml', + __DIR__ . \DIRECTORY_SEPARATOR . 'SettingsForms', ]; $container = $this->prophesize(ContainerBuilder::class); @@ -32,18 +32,54 @@ public function testProcess(): void ->shouldBeCalled() ->willReturn($directories); - $container->setParameter('sulu_content.settings_forms', [ + $container->setParameter('sulu_content.content_settings_forms', [ 'content_settings_seo' => [ 'instanceOf' => SeoInterface::class, - 'priority' => 256, + 'priority' => 70, ], 'content_settings_author' => [ 'instanceOf' => AuthorInterface::class, - 'priority' => 128, + 'priority' => 50, ], ])->shouldBeCalled(); $settingsFormPass = new SettingsFormPass(); $settingsFormPass->process($container->reveal()); } + + public function testProcessNoInstanceOf(): void + { + $directories = [ + __DIR__ . \DIRECTORY_SEPARATOR . 'InvalidSettingsForms' . \DIRECTORY_SEPARATOR . 'NoInterface', + ]; + + $container = $this->prophesize(ContainerBuilder::class); + $container->getParameter('sulu_admin.forms.directories') + ->shouldBeCalled() + ->willReturn($directories); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('Tags with the name "sulu_content.content_settings_form" must have a valid "instanceOf" attribute!'); + + $settingsFormPass = new SettingsFormPass(); + $settingsFormPass->process($container->reveal()); + } + + public function testProcessNoKey(): void + { + $directories = [ + __DIR__ . \DIRECTORY_SEPARATOR . 'InvalidSettingsForms' . \DIRECTORY_SEPARATOR . 'NoKey', + ]; + + $container = $this->prophesize(ContainerBuilder::class); + $container->getParameter('sulu_admin.forms.directories') + ->shouldBeCalled() + ->willReturn($directories); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('Forms must have a valid "key" element!'); + + $settingsFormPass = new SettingsFormPass(); + $settingsFormPass->process($container->reveal()); + } } diff --git a/Tests/Unit/DependencyInjection/Compiler/SettingsFormXml/content_settings_author.xml b/Tests/Unit/DependencyInjection/Compiler/SettingsForms/content_settings_author.xml similarity index 87% rename from Tests/Unit/DependencyInjection/Compiler/SettingsFormXml/content_settings_author.xml rename to Tests/Unit/DependencyInjection/Compiler/SettingsForms/content_settings_author.xml index c205090d..467a33a1 100644 --- a/Tests/Unit/DependencyInjection/Compiler/SettingsFormXml/content_settings_author.xml +++ b/Tests/Unit/DependencyInjection/Compiler/SettingsForms/content_settings_author.xml @@ -5,7 +5,7 @@ > content_settings_author - +
diff --git a/Tests/Unit/DependencyInjection/Compiler/SettingsFormXml/content_settings_no_tag.xml b/Tests/Unit/DependencyInjection/Compiler/SettingsForms/content_settings_no_tag.xml similarity index 100% rename from Tests/Unit/DependencyInjection/Compiler/SettingsFormXml/content_settings_no_tag.xml rename to Tests/Unit/DependencyInjection/Compiler/SettingsForms/content_settings_no_tag.xml diff --git a/Tests/Unit/DependencyInjection/Compiler/SettingsFormXml/content_settings_seo.xml b/Tests/Unit/DependencyInjection/Compiler/SettingsForms/content_settings_seo.xml similarity index 70% rename from Tests/Unit/DependencyInjection/Compiler/SettingsFormXml/content_settings_seo.xml rename to Tests/Unit/DependencyInjection/Compiler/SettingsForms/content_settings_seo.xml index 722127fb..41717311 100644 --- a/Tests/Unit/DependencyInjection/Compiler/SettingsFormXml/content_settings_seo.xml +++ b/Tests/Unit/DependencyInjection/Compiler/SettingsForms/content_settings_seo.xml @@ -5,7 +5,7 @@ > content_settings_seo - + From 4c7c1d83a00a1c1f471305dbffc7d7d4fb5900ab Mon Sep 17 00:00:00 2001 From: Prokyonn Date: Fri, 30 Jul 2021 12:35:14 +0200 Subject: [PATCH 10/11] Add pass test for coverage --- .../InvalidTag/content_settings_author.xml | 29 +++++++++++++++++++ .../Compiler/SettingsFormPassTest.php | 18 ++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 Tests/Unit/DependencyInjection/Compiler/InvalidSettingsForms/InvalidTag/content_settings_author.xml diff --git a/Tests/Unit/DependencyInjection/Compiler/InvalidSettingsForms/InvalidTag/content_settings_author.xml b/Tests/Unit/DependencyInjection/Compiler/InvalidSettingsForms/InvalidTag/content_settings_author.xml new file mode 100644 index 00000000..1d0e665a --- /dev/null +++ b/Tests/Unit/DependencyInjection/Compiler/InvalidSettingsForms/InvalidTag/content_settings_author.xml @@ -0,0 +1,29 @@ + +
+ content_settings_author + + + + +
+ + sulu_content.author + + + + + sulu_content.authored_date + + + + + sulu_content.author + + + +
+
+ diff --git a/Tests/Unit/DependencyInjection/Compiler/SettingsFormPassTest.php b/Tests/Unit/DependencyInjection/Compiler/SettingsFormPassTest.php index 13d7773a..c6cd1d71 100644 --- a/Tests/Unit/DependencyInjection/Compiler/SettingsFormPassTest.php +++ b/Tests/Unit/DependencyInjection/Compiler/SettingsFormPassTest.php @@ -82,4 +82,22 @@ public function testProcessNoKey(): void $settingsFormPass = new SettingsFormPass(); $settingsFormPass->process($container->reveal()); } + + public function testProcessInvalidTag(): void + { + $directories = [ + __DIR__ . \DIRECTORY_SEPARATOR . 'InvalidSettingsForms' . \DIRECTORY_SEPARATOR . 'InvalidTag', + ]; + + $container = $this->prophesize(ContainerBuilder::class); + $container->getParameter('sulu_admin.forms.directories') + ->shouldBeCalled() + ->willReturn($directories); + + $container->setParameter('sulu_content.content_settings_forms', []) + ->shouldBeCalled(); + + $settingsFormPass = new SettingsFormPass(); + $settingsFormPass->process($container->reveal()); + } } From 7a1cd932ed5a23c60a02e0d76f42f949e1467dbf Mon Sep 17 00:00:00 2001 From: Alexander Schranz Date: Fri, 30 Jul 2021 14:02:14 +0200 Subject: [PATCH 11/11] Update DependencyInjection/Compiler/SettingsFormPass.php --- DependencyInjection/Compiler/SettingsFormPass.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DependencyInjection/Compiler/SettingsFormPass.php b/DependencyInjection/Compiler/SettingsFormPass.php index 5cf83852..7a224c51 100644 --- a/DependencyInjection/Compiler/SettingsFormPass.php +++ b/DependencyInjection/Compiler/SettingsFormPass.php @@ -25,7 +25,7 @@ public function process(ContainerBuilder $container): void $formDirectories = $container->getParameter('sulu_admin.forms.directories'); $finder = new Finder(); - $finder->files()->in($formDirectories); + $finder->files()->in($formDirectories)->name('*.xml'); $settingsForms = []; foreach ($finder as $file) { $document = new \DOMDocument();