From 1b2144013cbf81e6a2ee6cad5e7cefc816f79baf Mon Sep 17 00:00:00 2001 From: jkindly Date: Fri, 13 Sep 2024 10:57:31 +0200 Subject: [PATCH 1/4] OP-543: Content elements translatable --- .../ContentElementRendererStrategySpec.php | 95 +++++++++---------- src/Entity/ContentConfiguration.php | 12 +++ src/Entity/ContentConfigurationInterface.php | 4 + src/Form/Type/BlockType.php | 35 +++++++ src/Form/Type/ContentConfigurationType.php | 2 + src/Form/Type/PageType.php | 55 +++++++++++ src/Migrations/Version20240912094638.php | 31 ++++++ .../ContentElementRendererStrategy.php | 6 ++ .../admin/js/cms/cms-content-configuration.js | 32 +++++++ .../assets/admin/js/cms/cms-template.js | 31 +++++- .../doctrine/ContentConfiguration.orm.xml | 2 + src/Resources/config/services/form.xml | 2 + src/Resources/config/services/renderer.xml | 1 + .../views/Block/Crud/_form.html.twig | 1 + src/Resources/views/Locale/form.html.twig | 8 ++ src/Resources/views/Page/Crud/_form.html.twig | 1 + 16 files changed, 265 insertions(+), 53 deletions(-) create mode 100644 src/Migrations/Version20240912094638.php create mode 100644 src/Resources/views/Locale/form.html.twig diff --git a/spec/Renderer/ContentElementRendererStrategySpec.php b/spec/Renderer/ContentElementRendererStrategySpec.php index 568ca110..7cd6b2c7 100644 --- a/spec/Renderer/ContentElementRendererStrategySpec.php +++ b/spec/Renderer/ContentElementRendererStrategySpec.php @@ -10,23 +10,18 @@ use Sylius\CmsPlugin\Entity\ContentConfigurationInterface; use Sylius\CmsPlugin\Entity\PageInterface; use Sylius\CmsPlugin\Renderer\ContentElement\ContentElementRendererInterface; -use Sylius\CmsPlugin\Renderer\ContentElementRendererStrategy; use Sylius\CmsPlugin\Renderer\ContentElementRendererStrategyInterface; use Sylius\CmsPlugin\Twig\Parser\ContentParserInterface; +use Sylius\Component\Locale\Context\LocaleContextInterface; final class ContentElementRendererStrategySpec extends ObjectBehavior { public function let( ContentParserInterface $contentParser, - ContentElementRendererInterface $renderer1, - ContentElementRendererInterface $renderer2, + LocaleContextInterface $localeContext, + ContentElementRendererInterface $renderer ): void { - $this->beConstructedWith($contentParser, [$renderer1, $renderer2]); - } - - public function it_is_initializable(): void - { - $this->shouldHaveType(ContentElementRendererStrategy::class); + $this->beConstructedWith($contentParser, $localeContext, [$renderer]); } public function it_implements_content_element_renderer_strategy_interface(): void @@ -34,55 +29,59 @@ public function it_implements_content_element_renderer_strategy_interface(): voi $this->shouldImplement(ContentElementRendererStrategyInterface::class); } - public function it_renders_content_elements_using_registered_renderers( - ContentParserInterface $contentParser, - ContentElementRendererInterface $renderer1, - ContentElementRendererInterface $renderer2, - BlockInterface $block, - ContentConfigurationInterface $contentElement1, - ContentConfigurationInterface $contentElement2, + public function it_renders_a_page_content_element_correctly( + PageInterface $page, + ContentConfigurationInterface $contentElement, + LocaleContextInterface $localeContext, + ContentElementRendererInterface $renderer, + ContentParserInterface $contentParser ): void { - $block->getContentElements()->willReturn( - new ArrayCollection([$contentElement1->getWrappedObject(), $contentElement2->getWrappedObject()]), - ); + $page->getContentElements()->willReturn(new ArrayCollection([$contentElement->getWrappedObject()])); + $localeContext->getLocaleCode()->willReturn('en_US'); + $contentElement->getLocale()->willReturn('en_US'); - $renderer1->supports($contentElement1)->willReturn(true); - $renderer1->supports($contentElement2)->willReturn(false); - $renderer1->render($contentElement1)->willReturn('Rendered content 1'); - $renderer2->supports($contentElement2)->willReturn(true); - $renderer2->supports($contentElement1)->willReturn(false); - $renderer2->render($contentElement2)->willReturn('Rendered content 2'); + $renderer->supports($contentElement)->willReturn(true); + $renderer->render($contentElement)->willReturn('<p>Hello World</p>'); - $expectedParsedContent = 'Parsed content after rendering'; + $contentParser->parse('

Hello World

')->willReturn('

Hello World

'); - $contentParser->parse('Rendered content 1Rendered content 2')->willReturn($expectedParsedContent); - - $this->render($block)->shouldReturn($expectedParsedContent); + $this->render($page)->shouldReturn('

Hello World

'); } - public function it_renders_content_elements_using_registered_renderers_for_page( - ContentParserInterface $contentParser, - ContentElementRendererInterface $renderer1, - ContentElementRendererInterface $renderer2, - PageInterface $page, - ContentConfigurationInterface $contentElement1, - ContentConfigurationInterface $contentElement2, + public function it_skips_content_element_with_non_matching_locale( + BlockInterface $block, + ContentConfigurationInterface $contentElement, + LocaleContextInterface $localeContext, + ContentParserInterface $contentParser ): void { - $page->getContentElements()->willReturn( - new ArrayCollection([$contentElement1->getWrappedObject(), $contentElement2->getWrappedObject()]), - ); + $block->getContentElements()->willReturn(new ArrayCollection([$contentElement])); + $localeContext->getLocaleCode()->willReturn('en_US'); + $contentElement->getLocale()->willReturn('fr_FR'); - $renderer1->supports($contentElement1)->willReturn(true); - $renderer1->supports($contentElement2)->willReturn(false); - $renderer1->render($contentElement1)->willReturn('Rendered content 1'); - $renderer2->supports($contentElement2)->willReturn(true); - $renderer2->supports($contentElement1)->willReturn(false); - $renderer2->render($contentElement2)->willReturn('Rendered content 2'); + $contentParser->parse('')->willReturn(''); + + $this->render($block)->shouldReturn(''); + } + + public function it_renders_only_supported_content_elements( + BlockInterface $block, + ContentConfigurationInterface $supportedElement, + ContentConfigurationInterface $unsupportedElement, + LocaleContextInterface $localeContext, + ContentElementRendererInterface $renderer, + ContentParserInterface $contentParser + ): void { + $block->getContentElements()->willReturn(new ArrayCollection([$supportedElement->getWrappedObject(), $unsupportedElement->getWrappedObject()])); + $localeContext->getLocaleCode()->willReturn('en_US'); + $supportedElement->getLocale()->willReturn('en_US'); + $unsupportedElement->getLocale()->willReturn('en_US'); - $expectedParsedContent = 'Parsed content after rendering'; + $renderer->supports($supportedElement)->willReturn(true); + $renderer->render($supportedElement)->willReturn('<p>Supported</p>'); + $renderer->supports($unsupportedElement)->willReturn(false); - $contentParser->parse('Rendered content 1Rendered content 2')->willReturn($expectedParsedContent); + $contentParser->parse('

Supported

')->willReturn('

Supported

'); - $this->render($page)->shouldReturn($expectedParsedContent); + $this->render($block)->shouldReturn('

Supported

'); } } diff --git a/src/Entity/ContentConfiguration.php b/src/Entity/ContentConfiguration.php index 54ec60ed..1b08cb74 100644 --- a/src/Entity/ContentConfiguration.php +++ b/src/Entity/ContentConfiguration.php @@ -12,6 +12,8 @@ class ContentConfiguration implements ContentConfigurationInterface protected array $configuration = []; + protected ?string $locale = null; + protected ?BlockInterface $block = null; protected ?PageInterface $page = null; @@ -41,6 +43,16 @@ public function setConfiguration(array $configuration): void $this->configuration = $configuration; } + public function getLocale(): ?string + { + return $this->locale; + } + + public function setLocale(?string $locale): void + { + $this->locale = $locale; + } + public function getBlock(): ?BlockInterface { return $this->block; diff --git a/src/Entity/ContentConfigurationInterface.php b/src/Entity/ContentConfigurationInterface.php index d814b223..b593a3c2 100644 --- a/src/Entity/ContentConfigurationInterface.php +++ b/src/Entity/ContentConfigurationInterface.php @@ -16,6 +16,10 @@ public function getConfiguration(): array; public function setConfiguration(array $configuration): void; + public function getLocale(): ?string; + + public function setLocale(?string $locale): void; + public function getBlock(): ?BlockInterface; public function setBlock(?BlockInterface $block): void; diff --git a/src/Form/Type/BlockType.php b/src/Form/Type/BlockType.php index b32acf3b..955ffad7 100755 --- a/src/Form/Type/BlockType.php +++ b/src/Form/Type/BlockType.php @@ -9,13 +9,32 @@ use Sylius\Bundle\ResourceBundle\Form\Type\AbstractResourceType; use Sylius\Bundle\TaxonomyBundle\Form\Type\TaxonAutocompleteChoiceType; use Sylius\CmsPlugin\Entity\BlockInterface; +use Sylius\Component\Locale\Model\LocaleInterface; +use Sylius\Component\Resource\Repository\RepositoryInterface; use Symfony\Component\Form\Extension\Core\Type\CheckboxType; +use Symfony\Component\Form\Extension\Core\Type\ChoiceType; use Symfony\Component\Form\Extension\Core\Type\CollectionType; use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\FormBuilderInterface; final class BlockType extends AbstractResourceType { + private array $locales = []; + + public function __construct( + private RepositoryInterface $localeRepository, + string $dataClass, + array $validationGroups = [], + ) { + parent::__construct($dataClass, $validationGroups); + + /** @var LocaleInterface[] $locales */ + $locales = $this->localeRepository->findAll(); + foreach ($locales as $locale) { + $this->locales[$locale->getName()] = $locale->getCode(); + } + } + public function buildForm(FormBuilderInterface $builder, array $options): void { /** @var BlockInterface $block */ @@ -50,6 +69,12 @@ public function buildForm(FormBuilderInterface $builder, array $options): void 'allow_delete' => true, 'by_reference' => false, 'required' => false, + 'entry_options' => [ + 'label' => false, + ], + 'attr' => [ + 'class' => 'content-elements-container', + ], ]) ->add('products', ProductAutocompleteChoiceType::class, [ 'label' => 'sylius_cms.ui.display_for_products.label', @@ -70,7 +95,17 @@ public function buildForm(FormBuilderInterface $builder, array $options): void 'label' => false, 'mapped' => false, ]) + ->add('locale', ChoiceType::class, [ + 'choices' => $this->locales, + 'mapped' => false, + 'label' => 'sylius.ui.locale', + 'attr' => [ + 'class' => 'locale-selector', + ] + ]) ; + + PageType::addContentElementLocaleListener($builder); } public function getBlockPrefix(): string diff --git a/src/Form/Type/ContentConfigurationType.php b/src/Form/Type/ContentConfigurationType.php index ece65504..f6572e43 100644 --- a/src/Form/Type/ContentConfigurationType.php +++ b/src/Form/Type/ContentConfigurationType.php @@ -7,6 +7,7 @@ use Sylius\Bundle\ResourceBundle\Form\Type\AbstractResourceType; use Sylius\CmsPlugin\Entity\ContentConfigurationInterface; use Symfony\Component\Form\Extension\Core\Type\ChoiceType; +use Symfony\Component\Form\Extension\Core\Type\HiddenType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\FormEvents; @@ -38,6 +39,7 @@ public function buildForm(FormBuilderInterface $builder, array $options): void $defaultActionConfigurationType = $this->actionConfigurationTypes[$defaultActionType]; $builder + ->add('locale', HiddenType::class) ->add('type', ChoiceType::class, [ 'label' => 'sylius.ui.type', 'choices' => $this->actionTypes, diff --git a/src/Form/Type/PageType.php b/src/Form/Type/PageType.php index 528a78cb..c168697f 100755 --- a/src/Form/Type/PageType.php +++ b/src/Form/Type/PageType.php @@ -8,14 +8,35 @@ use Sylius\Bundle\ResourceBundle\Form\Type\AbstractResourceType; use Sylius\Bundle\ResourceBundle\Form\Type\ResourceTranslationsType; use Sylius\CmsPlugin\Form\Type\Translation\PageTranslationType; +use Sylius\Component\Locale\Model\LocaleInterface; +use Sylius\Component\Resource\Repository\RepositoryInterface; use Symfony\Component\Form\Extension\Core\Type\CheckboxType; +use Symfony\Component\Form\Extension\Core\Type\ChoiceType; use Symfony\Component\Form\Extension\Core\Type\CollectionType; use Symfony\Component\Form\Extension\Core\Type\DateTimeType; use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\FormBuilderInterface; +use Symfony\Component\Form\FormEvent; +use Symfony\Component\Form\FormEvents; final class PageType extends AbstractResourceType { + private array $locales = []; + + public function __construct( + private RepositoryInterface $localeRepository, + string $dataClass, + array $validationGroups = [], + ) { + parent::__construct($dataClass, $validationGroups); + + /** @var LocaleInterface[] $locales */ + $locales = $this->localeRepository->findAll(); + foreach ($locales as $locale) { + $this->locales[$locale->getName()] = $locale->getCode(); + } + } + public function buildForm(FormBuilderInterface $builder, array $options): void { $builder @@ -57,12 +78,46 @@ public function buildForm(FormBuilderInterface $builder, array $options): void 'allow_delete' => true, 'by_reference' => false, 'required' => false, + 'entry_options' => [ + 'label' => false, + ], + 'attr' => [ + 'class' => 'content-elements-container', + ], ]) ->add('template', TemplatePageAutocompleteChoiceType::class, [ 'label' => false, 'mapped' => false, ]) + ->add('locale', ChoiceType::class, [ + 'choices' => $this->locales, + 'mapped' => false, + 'label' => 'sylius.ui.locale', + 'attr' => [ + 'class' => 'locale-selector', + ] + ]) ; + + self::addContentElementLocaleListener($builder); + } + + public static function addContentElementLocaleListener(FormBuilderInterface $builder): void + { + $builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) { + $data = $event->getData(); + $selectedLocale = $data['locale'] ?? null; + + if (isset($data['contentElements'])) { + foreach ($data['contentElements'] as &$contentElement) { + if (empty($contentElement['locale'])) { + $contentElement['locale'] = $selectedLocale; + } + } + } + + $event->setData($data); + }); } public function getBlockPrefix(): string diff --git a/src/Migrations/Version20240912094638.php b/src/Migrations/Version20240912094638.php new file mode 100644 index 00000000..80e6e51a --- /dev/null +++ b/src/Migrations/Version20240912094638.php @@ -0,0 +1,31 @@ +addSql('ALTER TABLE sylius_cms_content_configuration ADD locale VARCHAR(255) NOT NULL'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE sylius_cms_content_configuration DROP locale'); + } +} diff --git a/src/Renderer/ContentElementRendererStrategy.php b/src/Renderer/ContentElementRendererStrategy.php index 2e45094e..2f4fc6bc 100644 --- a/src/Renderer/ContentElementRendererStrategy.php +++ b/src/Renderer/ContentElementRendererStrategy.php @@ -8,6 +8,7 @@ use Sylius\CmsPlugin\Entity\PageInterface; use Sylius\CmsPlugin\Renderer\ContentElement\ContentElementRendererInterface; use Sylius\CmsPlugin\Twig\Parser\ContentParserInterface; +use Sylius\Component\Locale\Context\LocaleContextInterface; final class ContentElementRendererStrategy implements ContentElementRendererStrategyInterface { @@ -16,6 +17,7 @@ final class ContentElementRendererStrategy implements ContentElementRendererStra */ public function __construct( private ContentParserInterface $contentParser, + private LocaleContextInterface $localeContext, private iterable $renderers, ) { } @@ -25,6 +27,10 @@ public function render(BlockInterface|PageInterface $item): string $content = ''; foreach ($item->getContentElements() as $contentElement) { + if ($contentElement->getLocale() !== $this->localeContext->getLocaleCode()) { + continue; + } + foreach ($this->renderers as $renderer) { if ($renderer->supports($contentElement)) { $content .= html_entity_decode($renderer->render($contentElement), \ENT_QUOTES); diff --git a/src/Resources/assets/admin/js/cms/cms-content-configuration.js b/src/Resources/assets/admin/js/cms/cms-content-configuration.js index 2544ba60..1320437a 100644 --- a/src/Resources/assets/admin/js/cms/cms-content-configuration.js +++ b/src/Resources/assets/admin/js/cms/cms-content-configuration.js @@ -1,4 +1,32 @@ $(document).ready(function() { + const localeSelector = $('.locale-selector'); + const contentElementsContainer = $('.content-elements-container'); + + function updateContentElementsVisibility() { + const selectedLocale = localeSelector.val(); + + contentElementsContainer.find('.bb-collection-item').each(function() { + const $element = $(this); + const elementLocale = $element.find('input[name$="[locale]"]').val(); + + if (elementLocale === selectedLocale) { + $element.show(); + } else { + $element.hide(); + } + }); + } + + localeSelector.on('change', function() { + updateContentElementsVisibility(); + }); + + contentElementsContainer.on('contentElementAdded', function() { + updateContentElementsVisibility(); + }); + + updateContentElementsVisibility(); + $('.cms-media-autocomplete, .sylius-autocomplete').each((index, element) => { $(element).autoComplete(); }); @@ -32,15 +60,19 @@ $(document).ready(function() { if (!$(collectionHolder).length) { return; } + $(document).on('collection-form-add', () => { $('.cms-media-autocomplete, .sylius-autocomplete').each((index, element) => { if ($._data($(element).get(0), 'events') === undefined) { $(element).autoComplete(); } }); + $(`${collectionHolder} [data-form-collection="item"]`).each((index, element) => { $(document).loadContentConfiguration(element); }); + + $('.bb-collection-item:last-child').find('input[name$="[locale]"]').val(localeSelector.val()); }); $.fn.extend({ loadContentConfiguration(target) { diff --git a/src/Resources/assets/admin/js/cms/cms-template.js b/src/Resources/assets/admin/js/cms/cms-template.js index bee12f2a..87d631dc 100644 --- a/src/Resources/assets/admin/js/cms/cms-template.js +++ b/src/Resources/assets/admin/js/cms/cms-template.js @@ -5,6 +5,11 @@ export class HandleTemplate { const cmsPageTemplate = $('#sylius_cms_page_template'); const cmsBlockTemplate = $('#sylius_cms_block_template'); + let locales = []; + $('.locale-selector option').each(function() { + locales.push($(this).val()); + }); + cmsPageTemplate.on('change', function() { if ($(this).val()) { $('#load-template-confirmation-modal').modal('show'); @@ -38,15 +43,31 @@ export class HandleTemplate { .html(''); $.each(data.content, function () { - $('[data-form-collection="add"]').trigger('click'); + locales.forEach(function (locale) { + $('[data-form-collection="add"]').trigger('click'); + }); }); const elements = $('.bb-collection-item'); + let idx = 0; $.each(data.content, function (index, element) { - setTimeout(() => { - elements.eq(index).find('select:first').val(element.type); - elements.eq(index).find('select:first').change(); - }, 300); + locales.forEach(function (locale) { + elements.eq(idx).find('select:first').val(element.type); + elements.eq(idx).find('select:first').change(); + elements.eq(idx).find('input[name$="[locale]"]').val(locale); + idx++; + }); + }); + + $('.content-elements-container').find('.bb-collection-item').each(function() { + const $element = $(this); + const elementLocale = $element.find('input[name$="[locale]"]').val(); + + if (elementLocale === $('.locale-selector').val()) { + $element.show(); + } else { + $element.hide(); + } }); } else { console.error(data.message); diff --git a/src/Resources/config/doctrine/ContentConfiguration.orm.xml b/src/Resources/config/doctrine/ContentConfiguration.orm.xml index a1822195..b46c9f87 100644 --- a/src/Resources/config/doctrine/ContentConfiguration.orm.xml +++ b/src/Resources/config/doctrine/ContentConfiguration.orm.xml @@ -18,6 +18,8 @@ + + diff --git a/src/Resources/config/services/form.xml b/src/Resources/config/services/form.xml index 473585fc..1d517afc 100644 --- a/src/Resources/config/services/form.xml +++ b/src/Resources/config/services/form.xml @@ -13,6 +13,7 @@ + %sylius_cms.model.block.class% %sylius_cms.form.type.block.validation_groups% @@ -27,6 +28,7 @@ + %sylius_cms.model.page.class% %sylius_cms.form.type.page.validation_groups% diff --git a/src/Resources/config/services/renderer.xml b/src/Resources/config/services/renderer.xml index 106b8fba..7c17f5e6 100644 --- a/src/Resources/config/services/renderer.xml +++ b/src/Resources/config/services/renderer.xml @@ -6,6 +6,7 @@ + diff --git a/src/Resources/views/Block/Crud/_form.html.twig b/src/Resources/views/Block/Crud/_form.html.twig index 31310485..d7fdf6de 100755 --- a/src/Resources/views/Block/Crud/_form.html.twig +++ b/src/Resources/views/Block/Crud/_form.html.twig @@ -35,6 +35,7 @@

{{ 'sylius_cms.ui.content_elements.title'|trans }}

{% include '@SyliusCmsPlugin/Template/form.html.twig' with {ajax_url: path('sylius_cms_admin_ajax_template_content_by_id', {'id': 'REPLACE_ID'}) } %} + {% include '@SyliusCmsPlugin/Locale/form.html.twig' %}
{{ form_row(form.contentElements) }} diff --git a/src/Resources/views/Locale/form.html.twig b/src/Resources/views/Locale/form.html.twig new file mode 100644 index 00000000..a18cb691 --- /dev/null +++ b/src/Resources/views/Locale/form.html.twig @@ -0,0 +1,8 @@ +
+
{{ form_label(form.locale) }}
+
+
+ {{ form_widget(form.locale) }} +
+
+
diff --git a/src/Resources/views/Page/Crud/_form.html.twig b/src/Resources/views/Page/Crud/_form.html.twig index d46eb10f..fb9384da 100755 --- a/src/Resources/views/Page/Crud/_form.html.twig +++ b/src/Resources/views/Page/Crud/_form.html.twig @@ -43,6 +43,7 @@

{{ 'sylius_cms.ui.content_elements.title'|trans }}

{% include '@SyliusCmsPlugin/Template/form.html.twig' with {ajax_url: path('sylius_cms_admin_ajax_template_content_by_id', {'id': 'REPLACE_ID'}) } %} + {% include '@SyliusCmsPlugin/Locale/form.html.twig' %}
{{ form_row(form.contentElements) }} From 0475fdcbab792e02e2488be01ec8465911a0990c Mon Sep 17 00:00:00 2001 From: jkindly Date: Fri, 13 Sep 2024 12:09:49 +0200 Subject: [PATCH 2/4] OP-543: Fixtures fix and ECS --- ...esCollectionContentElementRendererSpec.php | 1 - .../ContentElementRendererStrategySpec.php | 8 +- .../TranslationFormReduceRuntimeSpec.php | 10 +- src/Fixture/BlockFixture.php | 5 +- src/Fixture/Factory/BlockFixtureFactory.php | 21 +- src/Fixture/Factory/PageFixtureFactory.php | 23 +- src/Fixture/PageFixture.php | 4 +- src/Form/Type/BlockType.php | 2 +- src/Form/Type/PageType.php | 2 +- .../config/packages/sylius_cms_plugin.yaml | 606 +++++++++--------- 10 files changed, 352 insertions(+), 330 deletions(-) diff --git a/spec/Renderer/ContentElement/PagesCollectionContentElementRendererSpec.php b/spec/Renderer/ContentElement/PagesCollectionContentElementRendererSpec.php index 97a5966c..a44bea05 100644 --- a/spec/Renderer/ContentElement/PagesCollectionContentElementRendererSpec.php +++ b/spec/Renderer/ContentElement/PagesCollectionContentElementRendererSpec.php @@ -10,7 +10,6 @@ use Sylius\CmsPlugin\Entity\ContentConfigurationInterface; use Sylius\CmsPlugin\Form\Type\ContentElements\PagesCollectionContentElementType; use Sylius\CmsPlugin\Renderer\ContentElement\AbstractContentElement; -use Sylius\CmsPlugin\Renderer\ContentElement\ContentElementRendererInterface; use Sylius\CmsPlugin\Renderer\ContentElement\PagesCollectionContentElementRenderer; use Sylius\CmsPlugin\Repository\CollectionRepositoryInterface; use Twig\Environment; diff --git a/spec/Renderer/ContentElementRendererStrategySpec.php b/spec/Renderer/ContentElementRendererStrategySpec.php index 7cd6b2c7..96147132 100644 --- a/spec/Renderer/ContentElementRendererStrategySpec.php +++ b/spec/Renderer/ContentElementRendererStrategySpec.php @@ -19,7 +19,7 @@ final class ContentElementRendererStrategySpec extends ObjectBehavior public function let( ContentParserInterface $contentParser, LocaleContextInterface $localeContext, - ContentElementRendererInterface $renderer + ContentElementRendererInterface $renderer, ): void { $this->beConstructedWith($contentParser, $localeContext, [$renderer]); } @@ -34,7 +34,7 @@ public function it_renders_a_page_content_element_correctly( ContentConfigurationInterface $contentElement, LocaleContextInterface $localeContext, ContentElementRendererInterface $renderer, - ContentParserInterface $contentParser + ContentParserInterface $contentParser, ): void { $page->getContentElements()->willReturn(new ArrayCollection([$contentElement->getWrappedObject()])); $localeContext->getLocaleCode()->willReturn('en_US'); @@ -52,7 +52,7 @@ public function it_skips_content_element_with_non_matching_locale( BlockInterface $block, ContentConfigurationInterface $contentElement, LocaleContextInterface $localeContext, - ContentParserInterface $contentParser + ContentParserInterface $contentParser, ): void { $block->getContentElements()->willReturn(new ArrayCollection([$contentElement])); $localeContext->getLocaleCode()->willReturn('en_US'); @@ -69,7 +69,7 @@ public function it_renders_only_supported_content_elements( ContentConfigurationInterface $unsupportedElement, LocaleContextInterface $localeContext, ContentElementRendererInterface $renderer, - ContentParserInterface $contentParser + ContentParserInterface $contentParser, ): void { $block->getContentElements()->willReturn(new ArrayCollection([$supportedElement->getWrappedObject(), $unsupportedElement->getWrappedObject()])); $localeContext->getLocaleCode()->willReturn('en_US'); diff --git a/spec/Twig/Runtime/TranslationFormReduceRuntimeSpec.php b/spec/Twig/Runtime/TranslationFormReduceRuntimeSpec.php index 0e8e718f..80822f69 100644 --- a/spec/Twig/Runtime/TranslationFormReduceRuntimeSpec.php +++ b/spec/Twig/Runtime/TranslationFormReduceRuntimeSpec.php @@ -19,10 +19,10 @@ public function it_reduces_form_to_specified_fields( FormView $form, FormView $localeForm, FormView $slugForm, - FormView $titleForm + FormView $titleForm, ): void { $form->children = [ - 'en_US' => $localeForm + 'en_US' => $localeForm, ]; $localeForm->children = [ @@ -56,7 +56,7 @@ public function it_handles_multiple_locales( FormView $enLocale, FormView $deLocale, FormView $slugForm, - FormView $titleForm + FormView $titleForm, ): void { $form->children = [ 'en_US' => $enLocale, @@ -85,7 +85,7 @@ public function it_throws_exception_if_field_is_not_present_in_multiple_locales( FormView $form, FormView $enLocale, FormView $deLocale, - FormView $slugForm + FormView $slugForm, ): void { $form->children = [ 'en_US' => $enLocale, @@ -108,7 +108,7 @@ public function it_handles_empty_field_array( FormView $form, FormView $localeForm, FormView $slugForm, - FormView $titleForm + FormView $titleForm, ): void { $form->children = [ 'en_US' => $localeForm, diff --git a/src/Fixture/BlockFixture.php b/src/Fixture/BlockFixture.php index 6208f020..f2063335 100755 --- a/src/Fixture/BlockFixture.php +++ b/src/Fixture/BlockFixture.php @@ -41,7 +41,9 @@ protected function configureOptionsNode(ArrayNodeDefinition $optionsNode): void ->arrayNode('taxons')->scalarPrototype()->end()->end() ->arrayNode('products_in_taxons')->scalarPrototype()->end()->end() ->arrayNode('content_elements') - ->useAttributeAsKey('key') + ->useAttributeAsKey('locale') + ->arrayPrototype() + ->useAttributeAsKey('key') ->arrayPrototype() ->children() ->scalarNode('type')->end() @@ -54,7 +56,6 @@ protected function configureOptionsNode(ArrayNodeDefinition $optionsNode): void ->scalarNode('products_carousel_by_taxon')->end() ->scalarNode('products_grid_by_taxon')->end() ->scalarNode('pages_collection')->end() - ->scalarNode('pages_collection')->end() ->scalarNode('spacer')->end() ->arrayNode('multiple_media')->scalarPrototype()->end()->end() ->arrayNode('products_grid') diff --git a/src/Fixture/Factory/BlockFixtureFactory.php b/src/Fixture/Factory/BlockFixtureFactory.php index e3118601..3faee5e6 100755 --- a/src/Fixture/Factory/BlockFixtureFactory.php +++ b/src/Fixture/Factory/BlockFixtureFactory.php @@ -61,16 +61,19 @@ private function createBlock(string $code, array $blockData): void $this->taxonsAssigner->assign($block, $blockData['taxons']); $this->productsInTaxonsAssigner->assign($block, $blockData['products_in_taxons']); - foreach ($blockData['content_elements'] as $data) { - $data['data'] = array_filter($data['data'], static function ($value) { - return !empty($value); - }); + foreach ($blockData['content_elements'] as $locale => $data) { + foreach ($data as $contentElementData) { + $contentElementData['data'] = array_filter($contentElementData['data'], static function ($value) { + return !empty($value); + }); - $contentConfiguration = new ContentConfiguration(); - $contentConfiguration->setType($data['type']); - $contentConfiguration->setConfiguration($data['data']); - $contentConfiguration->setBlock($block); - $block->addContentElement($contentConfiguration); + $contentConfiguration = new ContentConfiguration(); + $contentConfiguration->setType($contentElementData['type']); + $contentConfiguration->setConfiguration($contentElementData['data']); + $contentConfiguration->setLocale($locale); + $contentConfiguration->setBlock($block); + $block->addContentElement($contentConfiguration); + } } $this->blockRepository->add($block); diff --git a/src/Fixture/Factory/PageFixtureFactory.php b/src/Fixture/Factory/PageFixtureFactory.php index ac96822b..946a4b63 100755 --- a/src/Fixture/Factory/PageFixtureFactory.php +++ b/src/Fixture/Factory/PageFixtureFactory.php @@ -78,16 +78,19 @@ private function createPage( $page->addTranslation($pageTranslation); } - foreach ($pageData['content_elements'] as $data) { - $data['data'] = array_filter($data['data'], static function ($value) { - return !empty($value); - }); - - $contentConfiguration = new ContentConfiguration(); - $contentConfiguration->setType($data['type']); - $contentConfiguration->setConfiguration($data['data']); - $contentConfiguration->setPage($page); - $page->addContentElement($contentConfiguration); + foreach ($pageData['content_elements'] as $locale => $data) { + foreach ($data as $contentElementData) { + $contentElementData['data'] = array_filter($contentElementData['data'], static function ($value) { + return !empty($value); + }); + + $contentConfiguration = new ContentConfiguration(); + $contentConfiguration->setType($contentElementData['type']); + $contentConfiguration->setConfiguration($contentElementData['data']); + $contentConfiguration->setLocale($locale); + $contentConfiguration->setPage($page); + $page->addContentElement($contentConfiguration); + } } $this->pageRepository->add($page); diff --git a/src/Fixture/PageFixture.php b/src/Fixture/PageFixture.php index c015ec89..9d331b02 100755 --- a/src/Fixture/PageFixture.php +++ b/src/Fixture/PageFixture.php @@ -50,7 +50,9 @@ protected function configureOptionsNode(ArrayNodeDefinition $optionsNode): void ->end() ->end() ->arrayNode('content_elements') - ->useAttributeAsKey('key') + ->useAttributeAsKey('locale') + ->arrayPrototype() + ->useAttributeAsKey('key') ->arrayPrototype() ->children() ->scalarNode('type')->end() diff --git a/src/Form/Type/BlockType.php b/src/Form/Type/BlockType.php index 955ffad7..a3a436c5 100755 --- a/src/Form/Type/BlockType.php +++ b/src/Form/Type/BlockType.php @@ -101,7 +101,7 @@ public function buildForm(FormBuilderInterface $builder, array $options): void 'label' => 'sylius.ui.locale', 'attr' => [ 'class' => 'locale-selector', - ] + ], ]) ; diff --git a/src/Form/Type/PageType.php b/src/Form/Type/PageType.php index c168697f..6b02ddb7 100755 --- a/src/Form/Type/PageType.php +++ b/src/Form/Type/PageType.php @@ -95,7 +95,7 @@ public function buildForm(FormBuilderInterface $builder, array $options): void 'label' => 'sylius.ui.locale', 'attr' => [ 'class' => 'locale-selector', - ] + ], ]) ; diff --git a/tests/Application/config/packages/sylius_cms_plugin.yaml b/tests/Application/config/packages/sylius_cms_plugin.yaml index 0e94ebca..ccd13a04 100644 --- a/tests/Application/config/packages/sylius_cms_plugin.yaml +++ b/tests/Application/config/packages/sylius_cms_plugin.yaml @@ -41,19 +41,20 @@ sylius_fixtures: locales: - "en_US" content_elements: - heading: - type: "heading" - data: - heading_type: "h1" - heading: "Textarea" - textarea: - type: "textarea" - data: - textarea: | -

Lorem ipsum dolor sit amet, consectetur adipiscing elit. In metus metus, pellentesque feugiat dictum vitae, viverra et purus. Etiam ornare arcu eget bibendum ornare. Donec at dictum odio, venenatis imperdiet tortor. Aenean aliquam mauris id massa commodo condimentum. Praesent sit amet feugiat justo, quis dictum nulla.

-

Fusce gravida orci eu lorem pharetra viverra. Ut non posuere arcu, pellentesque tristique massa. Donec sit amet efficitur risus, a mattis sem. Pellentesque id fringilla lorem, non finibus velit. -

Lorem ipsum dolor sit amet, consectetur adipiscing elit. In metus metus, pellentesque feugiat dictum vitae, viverra et purus. Etiam ornare arcu eget bibendum ornare. Donec at dictum odio, venenatis imperdiet tortor. Aenean aliquam mauris id massa commodo condimentum. Praesent sit amet feugiat justo, quis dictum nulla.

-

Fusce gravida orci eu lorem pharetra viverra. Ut non posuere arcu, pellentesque tristique massa. Donec sit amet efficitur risus, a mattis sem. Pellentesque id fringilla lorem, non finibus velit.

+ en_US: + heading: + type: "heading" + data: + heading_type: "h1" + heading: "Textarea" + textarea: + type: "textarea" + data: + textarea: | +

Lorem ipsum dolor sit amet, consectetur adipiscing elit. In metus metus, pellentesque feugiat dictum vitae, viverra et purus. Etiam ornare arcu eget bibendum ornare. Donec at dictum odio, venenatis imperdiet tortor. Aenean aliquam mauris id massa commodo condimentum. Praesent sit amet feugiat justo, quis dictum nulla.

+

Fusce gravida orci eu lorem pharetra viverra. Ut non posuere arcu, pellentesque tristique massa. Donec sit amet efficitur risus, a mattis sem. Pellentesque id fringilla lorem, non finibus velit. +

Lorem ipsum dolor sit amet, consectetur adipiscing elit. In metus metus, pellentesque feugiat dictum vitae, viverra et purus. Etiam ornare arcu eget bibendum ornare. Donec at dictum odio, venenatis imperdiet tortor. Aenean aliquam mauris id massa commodo condimentum. Praesent sit amet feugiat justo, quis dictum nulla.

+

Fusce gravida orci eu lorem pharetra viverra. Ut non posuere arcu, pellentesque tristique massa. Donec sit amet efficitur risus, a mattis sem. Pellentesque id fringilla lorem, non finibus velit.

homepage_products_carousel: name: "Homepage products carousel" channels: @@ -61,20 +62,21 @@ sylius_fixtures: locales: - "en_US" content_elements: - heading: - type: "heading" - data: - heading_type: "h2" - heading: "Products carousel" - products_carousel: - type: "products_carousel" - data: - products_carousel: - products: - - "Everyday_white_basic_T_Shirt" - - "Loose_white_designer_T_Shirt" - - "Ribbed_copper_slim_fit_Tee" - - "Sport_basic_white_T_Shirt" + en_US: + heading: + type: "heading" + data: + heading_type: "h2" + heading: "Products carousel" + products_carousel: + type: "products_carousel" + data: + products_carousel: + products: + - "Everyday_white_basic_T_Shirt" + - "Loose_white_designer_T_Shirt" + - "Ribbed_copper_slim_fit_Tee" + - "Sport_basic_white_T_Shirt" homepage_products_carousel_by_taxon: name: "Homepage products carousel by Taxon" channels: @@ -82,67 +84,71 @@ sylius_fixtures: locales: - "en_US" content_elements: - heading: - type: "heading" - data: - heading_type: "h2" - heading: "Products carousel by Taxon" - products_carousel_by_taxon: - type: "products_carousel_by_taxon" - data: - products_carousel_by_taxon: "t_shirts" + en_US: + heading: + type: "heading" + data: + heading_type: "h2" + heading: "Products carousel by Taxon" + products_carousel_by_taxon: + type: "products_carousel_by_taxon" + data: + products_carousel_by_taxon: "t_shirts" homepage_products_grid: name: "Homepage products grid" channels: - "FASHION_WEB" content_elements: - heading: - type: "heading" - data: - heading_type: "h2" - heading: "Products grid" - products_grid: - type: "products_grid" - data: - products_grid: - products: - - "Raglan_grey_&_black_Tee" - - "Loose_white_designer_T_Shirt" - - "Sport_basic_white_T_Shirt" - - "Ribbed_copper_slim_fit_Tee" + en_US: + heading: + type: "heading" + data: + heading_type: "h2" + heading: "Products grid" + products_grid: + type: "products_grid" + data: + products_grid: + products: + - "Raglan_grey_&_black_Tee" + - "Loose_white_designer_T_Shirt" + - "Sport_basic_white_T_Shirt" + - "Ribbed_copper_slim_fit_Tee" homepage_products_grid_by_taxon: name: "Homepage products grid by Taxon" channels: - "FASHION_WEB" content_elements: - heading: - type: "heading" - data: - heading_type: "h2" - heading: "Products grid by Taxon" - products_grid_by_taxon: - type: "products_grid_by_taxon" - data: - products_grid_by_taxon: "caps" + en_US: + heading: + type: "heading" + data: + heading_type: "h2" + heading: "Products grid by Taxon" + products_grid_by_taxon: + type: "products_grid_by_taxon" + data: + products_grid_by_taxon: "caps" homepage_taxons_list: name: "Homepage taxons list" channels: - "FASHION_WEB" content_elements: - heading: - type: "heading" - data: - heading_type: "h2" - heading: "Taxons list" - taxons_list: - type: "taxons_list" - data: - taxons_list: - taxons: - - "t_shirts" - - "caps" - - "dresses" - - "jeans" + en_US: + heading: + type: "heading" + data: + heading_type: "h2" + heading: "Taxons list" + taxons_list: + type: "taxons_list" + data: + taxons_list: + taxons: + - "t_shirts" + - "caps" + - "dresses" + - "jeans" taxon_t_shirts_banner: name: "T-Shirts banner" channels: @@ -150,15 +156,16 @@ sylius_fixtures: taxons: - "t_shirts" content_elements: - heading: - type: "heading" - data: - heading_type: "h2" - heading: "Image block for specified category (T-Shirts)" - single_media: - type: "single_media" - data: - single_media: "t_shirts_banner" + en_US: + heading: + type: "heading" + data: + heading_type: "h2" + heading: "Image block for specified category (T-Shirts)" + single_media: + type: "single_media" + data: + single_media: "t_shirts_banner" specified_products_banner: name: "Specified products banner" channels: @@ -168,15 +175,16 @@ sylius_fixtures: - "Loose_white_designer_T_Shirt" - "Ribbed_copper_slim_fit_Tee" content_elements: - heading: - type: "heading" - data: - heading_type: "h2" - heading: "Image block for specified products" - single_media: - type: "single_media" - data: - single_media: "specified_products_banner" + en_US: + heading: + type: "heading" + data: + heading_type: "h2" + heading: "Image block for specified products" + single_media: + type: "single_media" + data: + single_media: "specified_products_banner" specified_products_in_taxons: name: "Specified products in taxons" channels: @@ -184,19 +192,20 @@ sylius_fixtures: products_in_taxons: - "womens_t_shirts" content_elements: - heading: - type: "heading" - data: - heading_type: "h2" - heading: "Block for products in specified taxons" - products_carousel_by_taxon: - type: "products_carousel_by_taxon" - data: - products_carousel_by_taxon: "t_shirts" - products_grid_by_taxon: - type: "products_grid_by_taxon" - data: - products_grid_by_taxon: "caps" + en_US: + heading: + type: "heading" + data: + heading_type: "h2" + heading: "Block for products in specified taxons" + products_carousel_by_taxon: + type: "products_carousel_by_taxon" + data: + products_carousel_by_taxon: "t_shirts" + products_grid_by_taxon: + type: "products_grid_by_taxon" + data: + products_grid_by_taxon: "caps" media: options: custom: @@ -302,51 +311,52 @@ sylius_fixtures: meta_title: "FAQ" meta_keywords: "faq" content_elements: - question1: - type: "heading" - data: - heading_type: "h3" - heading: "Lorem ipsum dolor sit amet, consectetur adipiscing elit?" - answer1: - type: "textarea" - data: - textarea: "

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" - question2: - type: "heading" - data: - heading_type: "h3" - heading: "Lorem ipsum dolor sit amet, consectetur adipiscing elit?" - answer2: - type: "textarea" - data: - textarea: "

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" - question3: - type: "heading" - data: - heading_type: "h3" - heading: "Lorem ipsum dolor sit amet, consectetur adipiscing elit?" - answer3: - type: "textarea" - data: - textarea: "

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" - question4: - type: "heading" - data: - heading_type: "h3" - heading: "Lorem ipsum dolor sit amet, consectetur adipiscing elit?" - answer4: - type: "textarea" - data: - textarea: "

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" - question5: - type: "heading" - data: - heading_type: "h3" - heading: "Lorem ipsum dolor sit amet, consectetur adipiscing elit?" - answer5: - type: "textarea" - data: - textarea: "

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" + en_US: + question1: + type: "heading" + data: + heading_type: "h3" + heading: "Lorem ipsum dolor sit amet, consectetur adipiscing elit?" + answer1: + type: "textarea" + data: + textarea: "

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" + question2: + type: "heading" + data: + heading_type: "h3" + heading: "Lorem ipsum dolor sit amet, consectetur adipiscing elit?" + answer2: + type: "textarea" + data: + textarea: "

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" + question3: + type: "heading" + data: + heading_type: "h3" + heading: "Lorem ipsum dolor sit amet, consectetur adipiscing elit?" + answer3: + type: "textarea" + data: + textarea: "

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" + question4: + type: "heading" + data: + heading_type: "h3" + heading: "Lorem ipsum dolor sit amet, consectetur adipiscing elit?" + answer4: + type: "textarea" + data: + textarea: "

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" + question5: + type: "heading" + data: + heading_type: "h3" + heading: "Lorem ipsum dolor sit amet, consectetur adipiscing elit?" + answer5: + type: "textarea" + data: + textarea: "

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" blog: name: "Blog" channels: @@ -356,18 +366,19 @@ sylius_fixtures: slug: "blog" meta_title: "Blog" content_elements: - single_media: - type: "single_media" - data: - single_media: "blog_banner" - textarea: - type: "textarea" - data: - textarea: "

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean molestie nulla ac tempus volutpat.

" - pages_collection: - type: "pages_collection" - data: - pages_collection: "blog" + en_US: + single_media: + type: "single_media" + data: + single_media: "blog_banner" + textarea: + type: "textarea" + data: + textarea: "

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean molestie nulla ac tempus volutpat.

" + pages_collection: + type: "pages_collection" + data: + pages_collection: "blog" blog_post_1: name: "Blog post 1" channels: @@ -382,51 +393,52 @@ sylius_fixtures: teaser_content: "
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean molestie nulla ac tempus volutpat. Aenean aliquet viverra sem a feugiat. Pellentesque a sollicitudin lacus. Mauris vel dolor quis justo vestibulum posuere. Sed sagittis, ipsum a cursus porttitor, justo felis tincidunt neque, eget scelerisque lacus sapien tempor felis.
" teaser_image: "sale" content_elements: - single_media: - type: "single_media" - data: - single_media: "blog_post_1_header_banner" - spacer1: - type: "spacer" - data: - spacer: 30 - heading1: - type: "heading" - data: - heading_type: "h2" - heading: "Lorem ipsum dolor sit amet, consectetur adipiscing elit" - text1: - type: "textarea" - data: - textarea: | -

Lorem ipsum dolor sit amet, consectetur adipiscing elit. In metus metus, pellentesque feugiat dictum vitae, viverra et purus. Etiam ornare arcu eget bibendum ornare. Donec at dictum odio, venenatis imperdiet tortor. Aenean aliquam mauris id massa commodo condimentum. Praesent sit amet feugiat justo, quis dictum nulla.

-

Fusce gravida orci eu lorem pharetra viverra. Ut non posuere arcu, pellentesque tristique massa. Donec sit amet efficitur risus, a mattis sem. Pellentesque id fringilla lorem, non finibus velit.

- spacer2: - type: "spacer" - data: - spacer: 30 - products_grid: - type: "products_grid" - data: - products_grid: - products: - - "Raglan_grey_&_black_Tee" - - "Loose_white_designer_T_Shirt" - - "Sport_basic_white_T_Shirt" - - "Ribbed_copper_slim_fit_Tee" - heading2: - type: "heading" - data: - heading_type: "h2" - heading: "Lorem ipsum dolor sit amet, consectetur adipiscing elit" - text2: - type: "textarea" - data: - textarea: | -

Lorem ipsum dolor sit amet, consectetur adipiscing elit. In metus metus, pellentesque feugiat dictum vitae, viverra et purus. Etiam ornare arcu eget bibendum ornare. Donec at dictum odio, venenatis imperdiet tortor. Aenean aliquam mauris id massa commodo condimentum. Praesent sit amet feugiat justo, quis dictum nulla.

-

Fusce gravida orci eu lorem pharetra viverra. Ut non posuere arcu, pellentesque tristique massa. Donec sit amet efficitur risus, a mattis sem. Pellentesque id fringilla lorem, non finibus velit. -

Lorem ipsum dolor sit amet, consectetur adipiscing elit. In metus metus, pellentesque feugiat dictum vitae, viverra et purus. Etiam ornare arcu eget bibendum ornare. Donec at dictum odio, venenatis imperdiet tortor. Aenean aliquam mauris id massa commodo condimentum. Praesent sit amet feugiat justo, quis dictum nulla.

-

Fusce gravida orci eu lorem pharetra viverra. Ut non posuere arcu, pellentesque tristique massa. Donec sit amet efficitur risus, a mattis sem. Pellentesque id fringilla lorem, non finibus velit.

+ en_US: + single_media: + type: "single_media" + data: + single_media: "blog_post_1_header_banner" + spacer1: + type: "spacer" + data: + spacer: 30 + heading1: + type: "heading" + data: + heading_type: "h2" + heading: "Lorem ipsum dolor sit amet, consectetur adipiscing elit" + text1: + type: "textarea" + data: + textarea: | +

Lorem ipsum dolor sit amet, consectetur adipiscing elit. In metus metus, pellentesque feugiat dictum vitae, viverra et purus. Etiam ornare arcu eget bibendum ornare. Donec at dictum odio, venenatis imperdiet tortor. Aenean aliquam mauris id massa commodo condimentum. Praesent sit amet feugiat justo, quis dictum nulla.

+

Fusce gravida orci eu lorem pharetra viverra. Ut non posuere arcu, pellentesque tristique massa. Donec sit amet efficitur risus, a mattis sem. Pellentesque id fringilla lorem, non finibus velit.

+ spacer2: + type: "spacer" + data: + spacer: 30 + products_grid: + type: "products_grid" + data: + products_grid: + products: + - "Raglan_grey_&_black_Tee" + - "Loose_white_designer_T_Shirt" + - "Sport_basic_white_T_Shirt" + - "Ribbed_copper_slim_fit_Tee" + heading2: + type: "heading" + data: + heading_type: "h2" + heading: "Lorem ipsum dolor sit amet, consectetur adipiscing elit" + text2: + type: "textarea" + data: + textarea: | +

Lorem ipsum dolor sit amet, consectetur adipiscing elit. In metus metus, pellentesque feugiat dictum vitae, viverra et purus. Etiam ornare arcu eget bibendum ornare. Donec at dictum odio, venenatis imperdiet tortor. Aenean aliquam mauris id massa commodo condimentum. Praesent sit amet feugiat justo, quis dictum nulla.

+

Fusce gravida orci eu lorem pharetra viverra. Ut non posuere arcu, pellentesque tristique massa. Donec sit amet efficitur risus, a mattis sem. Pellentesque id fringilla lorem, non finibus velit. +

Lorem ipsum dolor sit amet, consectetur adipiscing elit. In metus metus, pellentesque feugiat dictum vitae, viverra et purus. Etiam ornare arcu eget bibendum ornare. Donec at dictum odio, venenatis imperdiet tortor. Aenean aliquam mauris id massa commodo condimentum. Praesent sit amet feugiat justo, quis dictum nulla.

+

Fusce gravida orci eu lorem pharetra viverra. Ut non posuere arcu, pellentesque tristique massa. Donec sit amet efficitur risus, a mattis sem. Pellentesque id fringilla lorem, non finibus velit.

blog_post_2: name: "Blog post 2" channels: @@ -441,51 +453,52 @@ sylius_fixtures: teaser_content: "
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean molestie nulla ac tempus volutpat. Aenean aliquet viverra sem a feugiat. Pellentesque a sollicitudin lacus. Mauris vel dolor quis justo vestibulum posuere. Sed sagittis, ipsum a cursus porttitor, justo felis tincidunt neque, eget scelerisque lacus sapien tempor felis.
" teaser_image: "sale" content_elements: - single_media: - type: "single_media" - data: - single_media: "blog_post_1_header_banner" - spacer1: - type: "spacer" - data: - spacer: 30 - heading1: - type: "heading" - data: - heading_type: "h2" - heading: "Lorem ipsum dolor sit amet, consectetur adipiscing elit" - text1: - type: "textarea" - data: - textarea: | -

Lorem ipsum dolor sit amet, consectetur adipiscing elit. In metus metus, pellentesque feugiat dictum vitae, viverra et purus. Etiam ornare arcu eget bibendum ornare. Donec at dictum odio, venenatis imperdiet tortor. Aenean aliquam mauris id massa commodo condimentum. Praesent sit amet feugiat justo, quis dictum nulla.

-

Fusce gravida orci eu lorem pharetra viverra. Ut non posuere arcu, pellentesque tristique massa. Donec sit amet efficitur risus, a mattis sem. Pellentesque id fringilla lorem, non finibus velit.

- spacer2: - type: "spacer" - data: - spacer: 30 - products_grid: - type: "products_grid" - data: - products_grid: - products: - - "Raglan_grey_&_black_Tee" - - "Loose_white_designer_T_Shirt" - - "Sport_basic_white_T_Shirt" - - "Ribbed_copper_slim_fit_Tee" - heading2: - type: "heading" - data: - heading_type: "h2" - heading: "Lorem ipsum dolor sit amet, consectetur adipiscing elit" - text2: - type: "textarea" - data: - textarea: | -

Lorem ipsum dolor sit amet, consectetur adipiscing elit. In metus metus, pellentesque feugiat dictum vitae, viverra et purus. Etiam ornare arcu eget bibendum ornare. Donec at dictum odio, venenatis imperdiet tortor. Aenean aliquam mauris id massa commodo condimentum. Praesent sit amet feugiat justo, quis dictum nulla.

-

Fusce gravida orci eu lorem pharetra viverra. Ut non posuere arcu, pellentesque tristique massa. Donec sit amet efficitur risus, a mattis sem. Pellentesque id fringilla lorem, non finibus velit. -

Lorem ipsum dolor sit amet, consectetur adipiscing elit. In metus metus, pellentesque feugiat dictum vitae, viverra et purus. Etiam ornare arcu eget bibendum ornare. Donec at dictum odio, venenatis imperdiet tortor. Aenean aliquam mauris id massa commodo condimentum. Praesent sit amet feugiat justo, quis dictum nulla.

-

Fusce gravida orci eu lorem pharetra viverra. Ut non posuere arcu, pellentesque tristique massa. Donec sit amet efficitur risus, a mattis sem. Pellentesque id fringilla lorem, non finibus velit.

+ en_US: + single_media: + type: "single_media" + data: + single_media: "blog_post_1_header_banner" + spacer1: + type: "spacer" + data: + spacer: 30 + heading1: + type: "heading" + data: + heading_type: "h2" + heading: "Lorem ipsum dolor sit amet, consectetur adipiscing elit" + text1: + type: "textarea" + data: + textarea: | +

Lorem ipsum dolor sit amet, consectetur adipiscing elit. In metus metus, pellentesque feugiat dictum vitae, viverra et purus. Etiam ornare arcu eget bibendum ornare. Donec at dictum odio, venenatis imperdiet tortor. Aenean aliquam mauris id massa commodo condimentum. Praesent sit amet feugiat justo, quis dictum nulla.

+

Fusce gravida orci eu lorem pharetra viverra. Ut non posuere arcu, pellentesque tristique massa. Donec sit amet efficitur risus, a mattis sem. Pellentesque id fringilla lorem, non finibus velit.

+ spacer2: + type: "spacer" + data: + spacer: 30 + products_grid: + type: "products_grid" + data: + products_grid: + products: + - "Raglan_grey_&_black_Tee" + - "Loose_white_designer_T_Shirt" + - "Sport_basic_white_T_Shirt" + - "Ribbed_copper_slim_fit_Tee" + heading2: + type: "heading" + data: + heading_type: "h2" + heading: "Lorem ipsum dolor sit amet, consectetur adipiscing elit" + text2: + type: "textarea" + data: + textarea: | +

Lorem ipsum dolor sit amet, consectetur adipiscing elit. In metus metus, pellentesque feugiat dictum vitae, viverra et purus. Etiam ornare arcu eget bibendum ornare. Donec at dictum odio, venenatis imperdiet tortor. Aenean aliquam mauris id massa commodo condimentum. Praesent sit amet feugiat justo, quis dictum nulla.

+

Fusce gravida orci eu lorem pharetra viverra. Ut non posuere arcu, pellentesque tristique massa. Donec sit amet efficitur risus, a mattis sem. Pellentesque id fringilla lorem, non finibus velit. +

Lorem ipsum dolor sit amet, consectetur adipiscing elit. In metus metus, pellentesque feugiat dictum vitae, viverra et purus. Etiam ornare arcu eget bibendum ornare. Donec at dictum odio, venenatis imperdiet tortor. Aenean aliquam mauris id massa commodo condimentum. Praesent sit amet feugiat justo, quis dictum nulla.

+

Fusce gravida orci eu lorem pharetra viverra. Ut non posuere arcu, pellentesque tristique massa. Donec sit amet efficitur risus, a mattis sem. Pellentesque id fringilla lorem, non finibus velit.

blog_post_3: name: "Blog post 3" channels: @@ -500,51 +513,52 @@ sylius_fixtures: teaser_content: "
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean molestie nulla ac tempus volutpat. Aenean aliquet viverra sem a feugiat. Pellentesque a sollicitudin lacus. Mauris vel dolor quis justo vestibulum posuere. Sed sagittis, ipsum a cursus porttitor, justo felis tincidunt neque, eget scelerisque lacus sapien tempor felis.
" teaser_image: "sale" content_elements: - single_media: - type: "single_media" - data: - single_media: "blog_post_1_header_banner" - spacer1: - type: "spacer" - data: - spacer: 30 - heading1: - type: "heading" - data: - heading_type: "h2" - heading: "Lorem ipsum dolor sit amet, consectetur adipiscing elit" - text1: - type: "textarea" - data: - textarea: | -

Lorem ipsum dolor sit amet, consectetur adipiscing elit. In metus metus, pellentesque feugiat dictum vitae, viverra et purus. Etiam ornare arcu eget bibendum ornare. Donec at dictum odio, venenatis imperdiet tortor. Aenean aliquam mauris id massa commodo condimentum. Praesent sit amet feugiat justo, quis dictum nulla.

-

Fusce gravida orci eu lorem pharetra viverra. Ut non posuere arcu, pellentesque tristique massa. Donec sit amet efficitur risus, a mattis sem. Pellentesque id fringilla lorem, non finibus velit.

- spacer2: - type: "spacer" - data: - spacer: 30 - products_grid: - type: "products_grid" - data: - products_grid: - products: - - "Raglan_grey_&_black_Tee" - - "Loose_white_designer_T_Shirt" - - "Sport_basic_white_T_Shirt" - - "Ribbed_copper_slim_fit_Tee" - heading2: - type: "heading" - data: - heading_type: "h2" - heading: "Lorem ipsum dolor sit amet, consectetur adipiscing elit" - text2: - type: "textarea" - data: - textarea: | -

Lorem ipsum dolor sit amet, consectetur adipiscing elit. In metus metus, pellentesque feugiat dictum vitae, viverra et purus. Etiam ornare arcu eget bibendum ornare. Donec at dictum odio, venenatis imperdiet tortor. Aenean aliquam mauris id massa commodo condimentum. Praesent sit amet feugiat justo, quis dictum nulla.

-

Fusce gravida orci eu lorem pharetra viverra. Ut non posuere arcu, pellentesque tristique massa. Donec sit amet efficitur risus, a mattis sem. Pellentesque id fringilla lorem, non finibus velit. -

Lorem ipsum dolor sit amet, consectetur adipiscing elit. In metus metus, pellentesque feugiat dictum vitae, viverra et purus. Etiam ornare arcu eget bibendum ornare. Donec at dictum odio, venenatis imperdiet tortor. Aenean aliquam mauris id massa commodo condimentum. Praesent sit amet feugiat justo, quis dictum nulla.

-

Fusce gravida orci eu lorem pharetra viverra. Ut non posuere arcu, pellentesque tristique massa. Donec sit amet efficitur risus, a mattis sem. Pellentesque id fringilla lorem, non finibus velit.

+ en_US: + single_media: + type: "single_media" + data: + single_media: "blog_post_1_header_banner" + spacer1: + type: "spacer" + data: + spacer: 30 + heading1: + type: "heading" + data: + heading_type: "h2" + heading: "Lorem ipsum dolor sit amet, consectetur adipiscing elit" + text1: + type: "textarea" + data: + textarea: | +

Lorem ipsum dolor sit amet, consectetur adipiscing elit. In metus metus, pellentesque feugiat dictum vitae, viverra et purus. Etiam ornare arcu eget bibendum ornare. Donec at dictum odio, venenatis imperdiet tortor. Aenean aliquam mauris id massa commodo condimentum. Praesent sit amet feugiat justo, quis dictum nulla.

+

Fusce gravida orci eu lorem pharetra viverra. Ut non posuere arcu, pellentesque tristique massa. Donec sit amet efficitur risus, a mattis sem. Pellentesque id fringilla lorem, non finibus velit.

+ spacer2: + type: "spacer" + data: + spacer: 30 + products_grid: + type: "products_grid" + data: + products_grid: + products: + - "Raglan_grey_&_black_Tee" + - "Loose_white_designer_T_Shirt" + - "Sport_basic_white_T_Shirt" + - "Ribbed_copper_slim_fit_Tee" + heading2: + type: "heading" + data: + heading_type: "h2" + heading: "Lorem ipsum dolor sit amet, consectetur adipiscing elit" + text2: + type: "textarea" + data: + textarea: | +

Lorem ipsum dolor sit amet, consectetur adipiscing elit. In metus metus, pellentesque feugiat dictum vitae, viverra et purus. Etiam ornare arcu eget bibendum ornare. Donec at dictum odio, venenatis imperdiet tortor. Aenean aliquam mauris id massa commodo condimentum. Praesent sit amet feugiat justo, quis dictum nulla.

+

Fusce gravida orci eu lorem pharetra viverra. Ut non posuere arcu, pellentesque tristique massa. Donec sit amet efficitur risus, a mattis sem. Pellentesque id fringilla lorem, non finibus velit. +

Lorem ipsum dolor sit amet, consectetur adipiscing elit. In metus metus, pellentesque feugiat dictum vitae, viverra et purus. Etiam ornare arcu eget bibendum ornare. Donec at dictum odio, venenatis imperdiet tortor. Aenean aliquam mauris id massa commodo condimentum. Praesent sit amet feugiat justo, quis dictum nulla.

+

Fusce gravida orci eu lorem pharetra viverra. Ut non posuere arcu, pellentesque tristique massa. Donec sit amet efficitur risus, a mattis sem. Pellentesque id fringilla lorem, non finibus velit.

about: name: "About us page" channels: From d2f4438225f0c5bf7a9c7339a51f95066316b4d2 Mon Sep 17 00:00:00 2001 From: jkindly Date: Fri, 13 Sep 2024 12:45:22 +0200 Subject: [PATCH 3/4] OP-543: Behat fixes --- tests/Behat/Context/Setup/BlockContext.php | 1 + tests/Behat/Context/Setup/PageContext.php | 1 + tests/Behat/Page/Admin/Page/CreatePage.php | 17 +++++++++++++++-- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/tests/Behat/Context/Setup/BlockContext.php b/tests/Behat/Context/Setup/BlockContext.php index 0dec287d..c0532f8e 100755 --- a/tests/Behat/Context/Setup/BlockContext.php +++ b/tests/Behat/Context/Setup/BlockContext.php @@ -94,6 +94,7 @@ private function createBlockWithContentElement(string $code, string $contentElem /** @var ContentConfigurationInterface $contentConfiguration */ $contentConfiguration = new ContentConfiguration(); $contentConfiguration->setType(mb_strtolower($contentElement)); + $contentConfiguration->setLocale('en_US'); $contentConfiguration->setConfiguration(ContentElementHelper::getExampleConfigurationByContentElement($contentElement)); $contentConfiguration->setBlock($block); diff --git a/tests/Behat/Context/Setup/PageContext.php b/tests/Behat/Context/Setup/PageContext.php index 43352ebc..d4a4aca4 100755 --- a/tests/Behat/Context/Setup/PageContext.php +++ b/tests/Behat/Context/Setup/PageContext.php @@ -205,6 +205,7 @@ private function createPageWithContentElement(string $contentElement): PageInter /** @var ContentConfigurationInterface $contentConfiguration */ $contentConfiguration = new ContentConfiguration(); $contentConfiguration->setType(mb_strtolower($contentElement)); + $contentConfiguration->setLocale('en_US'); $contentConfiguration->setConfiguration(ContentElementHelper::getExampleConfigurationByContentElement($contentElement)); $contentConfiguration->setPage($page); diff --git a/tests/Behat/Page/Admin/Page/CreatePage.php b/tests/Behat/Page/Admin/Page/CreatePage.php index 7476451a..e3646280 100755 --- a/tests/Behat/Page/Admin/Page/CreatePage.php +++ b/tests/Behat/Page/Admin/Page/CreatePage.php @@ -111,8 +111,21 @@ public function addTextareaContentElementWithContent(string $content): void { Assert::isInstanceOf($this->getDriver(), ChromeDriver::class); - $textarea = $this->getElement('content_elements_textarea'); - $textarea->setValue($content); + $iframe = $this->getDocument()->find('css', '.cke_wysiwyg_frame'); + if (null === $iframe) { + throw new \Exception('CKEditor iframe not found'); + } + + $this->getDriver()->switchToIFrame($iframe->getAttribute('name')); + + $body = $this->getDocument()->find('css', 'body'); + if (null === $body) { + throw new \Exception('CKEditor body not found'); + } + + $body->setValue($content); + + $this->getDriver()->switchToIFrame(null); } public function addSingleMediaContentElementWithName(string $name): void From c31c6c5a86a173c0b5e6ea96f03d68b348e27f82 Mon Sep 17 00:00:00 2001 From: jkindly Date: Fri, 13 Sep 2024 13:24:56 +0200 Subject: [PATCH 4/4] OP-543: Behat fixes --- tests/Behat/Page/Admin/Block/CreatePage.php | 20 ++++++++++++++++++-- tests/Behat/Page/Admin/Page/CreatePage.php | 7 +++++-- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/tests/Behat/Page/Admin/Block/CreatePage.php b/tests/Behat/Page/Admin/Block/CreatePage.php index 15531ab3..5098fdcf 100755 --- a/tests/Behat/Page/Admin/Block/CreatePage.php +++ b/tests/Behat/Page/Admin/Block/CreatePage.php @@ -102,8 +102,24 @@ public function addTextareaContentElementWithContent(string $content): void { Assert::isInstanceOf($this->getDriver(), ChromeDriver::class); - $textarea = $this->getElement('content_elements_textarea'); - $textarea->setValue($content); + $iframe = $this->getDocument()->find('css', '.cke_wysiwyg_frame'); + if (null === $iframe) { + $textarea = $this->getElement('content_elements_textarea'); + $textarea->setValue($content); + + return; + } + + $this->getDriver()->switchToIFrame($iframe->getAttribute('name')); + + $body = $this->getDocument()->find('css', 'body'); + if (null === $body) { + throw new \Exception('CKEditor body not found'); + } + + $body->setValue($content); + + $this->getDriver()->switchToIFrame(); } public function addSingleMediaContentElementWithName(string $name): void diff --git a/tests/Behat/Page/Admin/Page/CreatePage.php b/tests/Behat/Page/Admin/Page/CreatePage.php index e3646280..83f983cd 100755 --- a/tests/Behat/Page/Admin/Page/CreatePage.php +++ b/tests/Behat/Page/Admin/Page/CreatePage.php @@ -113,7 +113,10 @@ public function addTextareaContentElementWithContent(string $content): void $iframe = $this->getDocument()->find('css', '.cke_wysiwyg_frame'); if (null === $iframe) { - throw new \Exception('CKEditor iframe not found'); + $textarea = $this->getElement('content_elements_textarea'); + $textarea->setValue($content); + + return; } $this->getDriver()->switchToIFrame($iframe->getAttribute('name')); @@ -125,7 +128,7 @@ public function addTextareaContentElementWithContent(string $content): void $body->setValue($content); - $this->getDriver()->switchToIFrame(null); + $this->getDriver()->switchToIFrame(); } public function addSingleMediaContentElementWithName(string $name): void