From 58269d4aedba3b623c1b0aeb7c7a594b153a35b1 Mon Sep 17 00:00:00 2001 From: jkindly <kozupa.jakub@gmail.com> Date: Tue, 23 Jul 2024 11:56:19 +0200 Subject: [PATCH 01/15] OP-441: Twig function to render Collection --- src/Form/Type/CollectionType.php | 2 - .../Collection/CollectionBlocksRenderer.php | 45 ++++++++++++++++++ .../Collection/CollectionMediaRenderer.php | 46 +++++++++++++++++++ .../Collection/CollectionPagesRenderer.php | 45 ++++++++++++++++++ .../CollectionRendererInterface.php | 20 ++++++++ src/Renderer/CollectionRendererStrategy.php | 35 ++++++++++++++ .../CollectionRendererStrategyInterface.php | 18 ++++++++ src/Renderer/PageLinkRenderer.php | 41 +++++++++++++++++ src/Renderer/PageLinkRendererInterface.php | 18 ++++++++ src/Resolver/CollectionResourceResolver.php | 40 ++++++++++++++++ .../CollectionResourceResolverInterface.php | 18 ++++++++ .../js/bitbag/bitbag-content-configuration.js | 8 ++-- src/Resources/config/services/renderer.xml | 24 ++++++++++ src/Resources/config/services/resolver.xml | 5 ++ src/Resources/config/services/twig.xml | 12 +++++ .../views/Shop/Collection/show.html.twig | 3 ++ .../views/Shop/Media/Show/file.html.twig | 18 ++++---- .../views/Shop/Media/Show/image.html.twig | 14 +++--- src/Resources/views/Shop/Page/link.html.twig | 3 ++ src/Sorter/SorterById.php | 27 +++++++++++ .../Extension/RenderCollectionExtension.php | 33 +++++++++++++ src/Twig/Runtime/RenderCollectionRuntime.php | 42 +++++++++++++++++ .../RenderCollectionRuntimeInterface.php | 16 +++++++ .../SyliusShopBundle/Homepage/index.html.twig | 1 + 24 files changed, 514 insertions(+), 20 deletions(-) create mode 100644 src/Renderer/Collection/CollectionBlocksRenderer.php create mode 100644 src/Renderer/Collection/CollectionMediaRenderer.php create mode 100644 src/Renderer/Collection/CollectionPagesRenderer.php create mode 100644 src/Renderer/Collection/CollectionRendererInterface.php create mode 100644 src/Renderer/CollectionRendererStrategy.php create mode 100644 src/Renderer/CollectionRendererStrategyInterface.php create mode 100644 src/Renderer/PageLinkRenderer.php create mode 100644 src/Renderer/PageLinkRendererInterface.php create mode 100755 src/Resolver/CollectionResourceResolver.php create mode 100755 src/Resolver/CollectionResourceResolverInterface.php create mode 100644 src/Resources/views/Shop/Collection/show.html.twig create mode 100644 src/Resources/views/Shop/Page/link.html.twig create mode 100644 src/Sorter/SorterById.php create mode 100644 src/Twig/Extension/RenderCollectionExtension.php create mode 100644 src/Twig/Runtime/RenderCollectionRuntime.php create mode 100644 src/Twig/Runtime/RenderCollectionRuntimeInterface.php diff --git a/src/Form/Type/CollectionType.php b/src/Form/Type/CollectionType.php index 73f802d9e..6478f89da 100755 --- a/src/Form/Type/CollectionType.php +++ b/src/Form/Type/CollectionType.php @@ -10,7 +10,6 @@ namespace BitBag\SyliusCmsPlugin\Form\Type; -use BitBag\SyliusCmsPlugin\Entity\MediaInterface; use Sylius\Bundle\ResourceBundle\Form\Type\AbstractResourceType; use Symfony\Component\Form\Event\PreSubmitEvent; use Symfony\Component\Form\Extension\Core\Type\ChoiceType; @@ -55,7 +54,6 @@ public function buildForm(FormBuilderInterface $builder, array $options): void ->add('media', MediaAutocompleteChoiceType::class, [ 'label' => 'bitbag_sylius_cms_plugin.ui.media', 'multiple' => true, - 'media_type' => MediaInterface::IMAGE_TYPE, ]) ->addEventListener(FormEvents::PRE_SUBMIT, function (PreSubmitEvent $event): void { $formData = $event->getData(); diff --git a/src/Renderer/Collection/CollectionBlocksRenderer.php b/src/Renderer/Collection/CollectionBlocksRenderer.php new file mode 100644 index 000000000..584da2568 --- /dev/null +++ b/src/Renderer/Collection/CollectionBlocksRenderer.php @@ -0,0 +1,45 @@ +<?php + +/* + * This file was created by developers working at BitBag + * Do you need more information about us and what we do? Visit our https://bitbag.io website! + * We are hiring developers from all over the world. Join us and start your new, exciting adventure and become part of us: https://bitbag.io/career +*/ + +declare(strict_types=1); + +namespace BitBag\SyliusCmsPlugin\Renderer\Collection; + +use BitBag\SyliusCmsPlugin\Entity\BlockInterface; +use BitBag\SyliusCmsPlugin\Entity\CollectionInterface; +use BitBag\SyliusCmsPlugin\Renderer\ContentElementRendererStrategyInterface; +use BitBag\SyliusCmsPlugin\Sorter\SorterById; +use Webmozart\Assert\Assert; + +final class CollectionBlocksRenderer implements CollectionRendererInterface +{ + public function __construct(private ContentElementRendererStrategyInterface $contentElementRendererStrategy) + { + } + + public function render(CollectionInterface $collection, ?int $countToRender = null): string + { + $content = ''; + $iterator = 0; + Assert::notNull($collection->getBlocks()); + /** @var BlockInterface $block */ + foreach (SorterById::sort($collection->getBlocks()->toArray()) as $block) { + $content .= $this->contentElementRendererStrategy->render($block); + if (++$iterator === $countToRender) { + break; + } + } + + return $content; + } + + public function supports(CollectionInterface $collection): bool + { + return $collection->getBlocks()?->count() > 0; + } +} diff --git a/src/Renderer/Collection/CollectionMediaRenderer.php b/src/Renderer/Collection/CollectionMediaRenderer.php new file mode 100644 index 000000000..b5c7ee8a3 --- /dev/null +++ b/src/Renderer/Collection/CollectionMediaRenderer.php @@ -0,0 +1,46 @@ +<?php + +/* + * This file was created by developers working at BitBag + * Do you need more information about us and what we do? Visit our https://bitbag.io website! + * We are hiring developers from all over the world. Join us and start your new, exciting adventure and become part of us: https://bitbag.io/career +*/ + +declare(strict_types=1); + +namespace BitBag\SyliusCmsPlugin\Renderer\Collection; + +use BitBag\SyliusCmsPlugin\Entity\CollectionInterface; +use BitBag\SyliusCmsPlugin\Entity\MediaInterface; +use BitBag\SyliusCmsPlugin\Sorter\SorterById; +use BitBag\SyliusCmsPlugin\Twig\Runtime\RenderMediaRuntimeInterface; +use Webmozart\Assert\Assert; + +final class CollectionMediaRenderer implements CollectionRendererInterface +{ + public function __construct(private RenderMediaRuntimeInterface $renderMediaRuntime) + { + } + + public function render(CollectionInterface $collection, ?int $countToRender = null): string + { + $content = ''; + $iterator = 0; + Assert::notNull($collection->getMedia()); + /** @var MediaInterface $media */ + foreach (SorterById::sort($collection->getMedia()->toArray()) as $media) { + Assert::notNull($media->getCode()); + $content .= $this->renderMediaRuntime->renderMedia($media->getCode()); + if (++$iterator === $countToRender) { + break; + } + } + + return $content; + } + + public function supports(CollectionInterface $collection): bool + { + return $collection->getMedia()?->count() > 0; + } +} diff --git a/src/Renderer/Collection/CollectionPagesRenderer.php b/src/Renderer/Collection/CollectionPagesRenderer.php new file mode 100644 index 000000000..587434e17 --- /dev/null +++ b/src/Renderer/Collection/CollectionPagesRenderer.php @@ -0,0 +1,45 @@ +<?php + +/* + * This file was created by developers working at BitBag + * Do you need more information about us and what we do? Visit our https://bitbag.io website! + * We are hiring developers from all over the world. Join us and start your new, exciting adventure and become part of us: https://bitbag.io/career +*/ + +declare(strict_types=1); + +namespace BitBag\SyliusCmsPlugin\Renderer\Collection; + +use BitBag\SyliusCmsPlugin\Entity\CollectionInterface; +use BitBag\SyliusCmsPlugin\Entity\PageInterface; +use BitBag\SyliusCmsPlugin\Renderer\PageLinkRendererInterface; +use BitBag\SyliusCmsPlugin\Sorter\SorterById; +use Webmozart\Assert\Assert; + +final class CollectionPagesRenderer implements CollectionRendererInterface +{ + public function __construct(private PageLinkRendererInterface $pageLinkRenderer) + { + } + + public function render(CollectionInterface $collection, ?int $countToRender = null): string + { + $content = ''; + $iterator = 0; + Assert::notNull($collection->getPages()); + /** @var PageInterface $page */ + foreach (SorterById::sort($collection->getPages()->toArray(), 'desc') as $page) { + $content .= $this->pageLinkRenderer->render($page); + if (++$iterator === $countToRender) { + break; + } + } + + return $content; + } + + public function supports(CollectionInterface $collection): bool + { + return $collection->getPages()?->count() > 0; + } +} diff --git a/src/Renderer/Collection/CollectionRendererInterface.php b/src/Renderer/Collection/CollectionRendererInterface.php new file mode 100644 index 000000000..4de98d3dc --- /dev/null +++ b/src/Renderer/Collection/CollectionRendererInterface.php @@ -0,0 +1,20 @@ +<?php + +/* + * This file was created by developers working at BitBag + * Do you need more information about us and what we do? Visit our https://bitbag.io website! + * We are hiring developers from all over the world. Join us and start your new, exciting adventure and become part of us: https://bitbag.io/career +*/ + +declare(strict_types=1); + +namespace BitBag\SyliusCmsPlugin\Renderer\Collection; + +use BitBag\SyliusCmsPlugin\Entity\CollectionInterface; + +interface CollectionRendererInterface +{ + public function render(CollectionInterface $collection, ?int $countToRender = null): string; + + public function supports(CollectionInterface $collection): bool; +} diff --git a/src/Renderer/CollectionRendererStrategy.php b/src/Renderer/CollectionRendererStrategy.php new file mode 100644 index 000000000..5ec435386 --- /dev/null +++ b/src/Renderer/CollectionRendererStrategy.php @@ -0,0 +1,35 @@ +<?php + +/* + * This file was created by developers working at BitBag + * Do you need more information about us and what we do? Visit our https://bitbag.io website! + * We are hiring developers from all over the world. Join us and start your new, exciting adventure and become part of us: https://bitbag.io/career +*/ + +declare(strict_types=1); + +namespace BitBag\SyliusCmsPlugin\Renderer; + +use BitBag\SyliusCmsPlugin\Entity\CollectionInterface; +use BitBag\SyliusCmsPlugin\Renderer\Collection\CollectionRendererInterface; + +final class CollectionRendererStrategy implements CollectionRendererStrategyInterface +{ + /** + * @param CollectionRendererInterface[] $renderers + */ + public function __construct(private iterable $renderers) + { + } + + public function render(CollectionInterface $collection, ?int $countToRender = null): string + { + foreach ($this->renderers as $renderer) { + if ($renderer->supports($collection)) { + return $renderer->render($collection, $countToRender); + } + } + + return ''; + } +} diff --git a/src/Renderer/CollectionRendererStrategyInterface.php b/src/Renderer/CollectionRendererStrategyInterface.php new file mode 100644 index 000000000..d8c0c606f --- /dev/null +++ b/src/Renderer/CollectionRendererStrategyInterface.php @@ -0,0 +1,18 @@ +<?php + +/* + * This file was created by developers working at BitBag + * Do you need more information about us and what we do? Visit our https://bitbag.io website! + * We are hiring developers from all over the world. Join us and start your new, exciting adventure and become part of us: https://bitbag.io/career +*/ + +declare(strict_types=1); + +namespace BitBag\SyliusCmsPlugin\Renderer; + +use BitBag\SyliusCmsPlugin\Entity\CollectionInterface; + +interface CollectionRendererStrategyInterface +{ + public function render(CollectionInterface $collection, ?int $countToRender = null): string; +} diff --git a/src/Renderer/PageLinkRenderer.php b/src/Renderer/PageLinkRenderer.php new file mode 100644 index 000000000..c218462e6 --- /dev/null +++ b/src/Renderer/PageLinkRenderer.php @@ -0,0 +1,41 @@ +<?php + +/* + * This file was created by developers working at BitBag + * Do you need more information about us and what we do? Visit our https://bitbag.io website! + * We are hiring developers from all over the world. Join us and start your new, exciting adventure and become part of us: https://bitbag.io/career +*/ + +declare(strict_types=1); + +namespace BitBag\SyliusCmsPlugin\Renderer; + +use BitBag\SyliusCmsPlugin\Entity\PageInterface; +use Symfony\Component\Routing\Generator\UrlGeneratorInterface; +use Twig\Environment; + +final class PageLinkRenderer implements PageLinkRendererInterface +{ + private const DEFAULT_TEMPLATE = '@BitBagSyliusCmsPlugin/Shop/Page/link.html.twig'; + + public function __construct( + private UrlGeneratorInterface $urlGenerator, + private Environment $twig, + ) { + } + + public function render(PageInterface $page, ?string $template = null): string + { + return $this->twig->render( + $template ?? self::DEFAULT_TEMPLATE, + [ + 'link' => $this->urlGenerator->generate( + 'bitbag_sylius_cms_plugin_shop_page_show', + ['slug' => $page->getSlug()], + UrlGeneratorInterface::ABSOLUTE_URL, + ), + 'name' => $page->getName(), + ], + ); + } +} diff --git a/src/Renderer/PageLinkRendererInterface.php b/src/Renderer/PageLinkRendererInterface.php new file mode 100644 index 000000000..a7a80001b --- /dev/null +++ b/src/Renderer/PageLinkRendererInterface.php @@ -0,0 +1,18 @@ +<?php + +/* + * This file was created by developers working at BitBag + * Do you need more information about us and what we do? Visit our https://bitbag.io website! + * We are hiring developers from all over the world. Join us and start your new, exciting adventure and become part of us: https://bitbag.io/career +*/ + +declare(strict_types=1); + +namespace BitBag\SyliusCmsPlugin\Renderer; + +use BitBag\SyliusCmsPlugin\Entity\PageInterface; + +interface PageLinkRendererInterface +{ + public function render(PageInterface $page, ?string $template = null): string; +} diff --git a/src/Resolver/CollectionResourceResolver.php b/src/Resolver/CollectionResourceResolver.php new file mode 100755 index 000000000..dd2a59b24 --- /dev/null +++ b/src/Resolver/CollectionResourceResolver.php @@ -0,0 +1,40 @@ +<?php + +/* + * This file was created by developers working at BitBag + * Do you need more information about us and what we do? Visit our https://bitbag.io website! + * We are hiring developers from all over the world. Join us and start your new, exciting adventure and become part of us: https://bitbag.io/career +*/ + +declare(strict_types=1); + +namespace BitBag\SyliusCmsPlugin\Resolver; + +use BitBag\SyliusCmsPlugin\Entity\CollectionInterface; +use BitBag\SyliusCmsPlugin\Repository\CollectionRepositoryInterface; +use Psr\Log\LoggerInterface; + +final class CollectionResourceResolver implements CollectionResourceResolverInterface +{ + public function __construct( + private CollectionRepositoryInterface $collectionRepository, + private LoggerInterface $logger, + ) { + } + + public function findOrLog(string $code): ?CollectionInterface + { + $collection = $this->collectionRepository->findOneByCode($code); + + if (false === $collection instanceof CollectionInterface) { + $this->logger->warning(sprintf( + 'Collection with "%s" code was not found in the database.', + $code, + )); + + return null; + } + + return $collection; + } +} diff --git a/src/Resolver/CollectionResourceResolverInterface.php b/src/Resolver/CollectionResourceResolverInterface.php new file mode 100755 index 000000000..4ea8827e0 --- /dev/null +++ b/src/Resolver/CollectionResourceResolverInterface.php @@ -0,0 +1,18 @@ +<?php + +/* + * This file was created by developers working at BitBag + * Do you need more information about us and what we do? Visit our https://bitbag.io website! + * We are hiring developers from all over the world. Join us and start your new, exciting adventure and become part of us: https://bitbag.io/career +*/ + +declare(strict_types=1); + +namespace BitBag\SyliusCmsPlugin\Resolver; + +use BitBag\SyliusCmsPlugin\Entity\CollectionInterface; + +interface CollectionResourceResolverInterface +{ + public function findOrLog(string $code): ?CollectionInterface; +} diff --git a/src/Resources/assets/admin/js/bitbag/bitbag-content-configuration.js b/src/Resources/assets/admin/js/bitbag/bitbag-content-configuration.js index ee45066fa..b221f2ca4 100644 --- a/src/Resources/assets/admin/js/bitbag/bitbag-content-configuration.js +++ b/src/Resources/assets/admin/js/bitbag/bitbag-content-configuration.js @@ -5,6 +5,10 @@ */ $(document).ready(function() { + $('.bitbag-media-autocomplete, .sylius-autocomplete').each((index, element) => { + $(element).autoComplete(); + }); + let pageElements = '#bitbag_sylius_cms_plugin_page_contentElements'; let blockElements = '#bitbag_sylius_cms_plugin_block_contentElements'; @@ -69,10 +73,6 @@ $(document).ready(function() { } }); - $('.bitbag-media-autocomplete, .sylius-autocomplete').each((index, element) => { - $(element).autoComplete(); - }); - $(`${collectionHolder} [data-form-collection="item"]`).each((index, element) => { $(document).loadContentConfiguration(element); }); diff --git a/src/Resources/config/services/renderer.xml b/src/Resources/config/services/renderer.xml index 2f2fba36b..a0943d659 100644 --- a/src/Resources/config/services/renderer.xml +++ b/src/Resources/config/services/renderer.xml @@ -64,5 +64,29 @@ <argument type="service" id="sylius.repository.taxon" /> <tag name="bitbag_sylius_cms_plugin.renderer.content_element" /> </service> + + <service id="bitbag_sylius_cms_plugin.collection_renderer_strategy" class="BitBag\SyliusCmsPlugin\Renderer\CollectionRendererStrategy"> + <argument type="tagged_iterator" tag="bitbag_sylius_cms_plugin.renderer.collection" /> + </service> + + <service id="bitbag_sylius_cms_plugin.renderer.collection.blocks" class="BitBag\SyliusCmsPlugin\Renderer\Collection\CollectionBlocksRenderer"> + <argument type="service" id="bitbag_sylius_cms_plugin.content_element_renderer_strategy" /> + <tag name="bitbag_sylius_cms_plugin.renderer.collection" /> + </service> + + <service id="bitbag_sylius_cms_plugin.renderer.collection.media" class="BitBag\SyliusCmsPlugin\Renderer\Collection\CollectionMediaRenderer"> + <argument type="service" id="bitbag_sylius_cms_plugin.twig.runtime.media" /> + <tag name="bitbag_sylius_cms_plugin.renderer.collection" /> + </service> + + <service id="bitbag_sylius_cms_plugin.renderer.collection.pages" class="BitBag\SyliusCmsPlugin\Renderer\Collection\CollectionPagesRenderer"> + <argument type="service" id="bitbag_sylius_cms_plugin.page_link_renderer" /> + <tag name="bitbag_sylius_cms_plugin.renderer.collection" /> + </service> + + <service id="bitbag_sylius_cms_plugin.page_link_renderer" class="BitBag\SyliusCmsPlugin\Renderer\PageLinkRenderer"> + <argument type="service" id="router.default" /> + <argument type="service" id="twig" /> + </service> </services> </container> diff --git a/src/Resources/config/services/resolver.xml b/src/Resources/config/services/resolver.xml index 2bfd80270..9d51b70b1 100644 --- a/src/Resources/config/services/resolver.xml +++ b/src/Resources/config/services/resolver.xml @@ -34,6 +34,11 @@ <argument type="service" id="sylius.context.channel" /> </service> + <service id="bitbag_sylius_cms_plugin.resolver.collection_resource" class="BitBag\SyliusCmsPlugin\Resolver\CollectionResourceResolver" public="true"> + <argument type="service" id="bitbag_sylius_cms_plugin.repository.collection" /> + <argument type="service" id="logger" /> + </service> + <service id="bitbag_sylius_cms_plugin.resolver.page_resource" class="BitBag\SyliusCmsPlugin\Resolver\PageResourceResolver" public="true"> <argument type="service" id="bitbag_sylius_cms_plugin.repository.page" /> <argument type="service" id="logger" /> diff --git a/src/Resources/config/services/twig.xml b/src/Resources/config/services/twig.xml index 39d108966..d831b84ca 100644 --- a/src/Resources/config/services/twig.xml +++ b/src/Resources/config/services/twig.xml @@ -24,6 +24,18 @@ <tag name="twig.runtime" /> </service> + <service id="bitbag_sylius_cms_plugin.twig.extension.collection" class="BitBag\SyliusCmsPlugin\Twig\Extension\RenderCollectionExtension"> + <argument type="service" id="bitbag_sylius_cms_plugin.twig.runtime.collection" /> + <tag name="twig.extension" /> + </service> + + <service id="bitbag_sylius_cms_plugin.twig.runtime.collection" class="BitBag\SyliusCmsPlugin\Twig\Runtime\RenderCollectionRuntime"> + <argument type="service" id="twig" /> + <argument type="service" id="bitbag_sylius_cms_plugin.resolver.collection_resource" /> + <argument type="service" id="bitbag_sylius_cms_plugin.collection_renderer_strategy" /> + <tag name="twig.runtime" /> + </service> + <service id="bitbag_sylius_cms_plugin.twig.extension.media" class="BitBag\SyliusCmsPlugin\Twig\Extension\RenderMediaExtension"> <argument type="service" id="bitbag_sylius_cms_plugin.twig.runtime.media" /> <tag name="twig.extension" /> diff --git a/src/Resources/views/Shop/Collection/show.html.twig b/src/Resources/views/Shop/Collection/show.html.twig new file mode 100644 index 000000000..c1e138d62 --- /dev/null +++ b/src/Resources/views/Shop/Collection/show.html.twig @@ -0,0 +1,3 @@ +<div class="bitbag-collection"> + {{ content|raw }} +</div> diff --git a/src/Resources/views/Shop/Media/Show/file.html.twig b/src/Resources/views/Shop/Media/Show/file.html.twig index 62a370885..2a03c5d81 100755 --- a/src/Resources/views/Shop/Media/Show/file.html.twig +++ b/src/Resources/views/Shop/Media/Show/file.html.twig @@ -1,10 +1,12 @@ -{% if null != media.name %} - <h2>{{ media.name|raw }}</h2> -{% endif %} +<div> + {% if null != media.name %} + <h2>{{ media.name|raw }}</h2> + {% endif %} -<p>{{ bitbag_cms_render_content(media) }}</p> + <p>{{ bitbag_cms_render_content(media) }}</p> -<a class="ui icon labeled primary button" href="{{ path('bitbag_sylius_cms_plugin_shop_media_download', {'code': media.code}) }}"> - <i class="download icon"></i> - {{ 'bitbag_sylius_cms_plugin.ui.download'|trans }} -</a> + <a class="ui icon labeled primary button" href="{{ path('bitbag_sylius_cms_plugin_shop_media_download', {'code': media.code}) }}"> + <i class="download icon"></i> + {{ 'bitbag_sylius_cms_plugin.ui.download'|trans }} + </a> +</div> diff --git a/src/Resources/views/Shop/Media/Show/image.html.twig b/src/Resources/views/Shop/Media/Show/image.html.twig index edf7565dc..0b13ea9f0 100755 --- a/src/Resources/views/Shop/Media/Show/image.html.twig +++ b/src/Resources/views/Shop/Media/Show/image.html.twig @@ -1,8 +1,10 @@ -<h2>{{ media.name|raw }}</h2> +<div> + <h2>{{ media.name|raw }}</h2> -<img class="ui fluid image" src="{{ media.path }}" alt="{{ media.alt }}" - {% if media.width is not null %} width="{{ media.width }}" {% endif %} - {% if media.height is not null %} height="{{ media.height }}" {% endif %} -/> + <img class="ui fluid image" src="{{ media.path }}" alt="{{ media.alt }}" + {% if media.width is not null %} width="{{ media.width }}" {% endif %} + {% if media.height is not null %} height="{{ media.height }}" {% endif %} + /> -<p>{{ bitbag_cms_render_content(media) }}</p> + <p>{{ bitbag_cms_render_content(media) }}</p> +</div> diff --git a/src/Resources/views/Shop/Page/link.html.twig b/src/Resources/views/Shop/Page/link.html.twig new file mode 100644 index 000000000..c55da6b38 --- /dev/null +++ b/src/Resources/views/Shop/Page/link.html.twig @@ -0,0 +1,3 @@ +<div> + <a href="{{ link }}">{{ name }}</a> +</div> diff --git a/src/Sorter/SorterById.php b/src/Sorter/SorterById.php new file mode 100644 index 000000000..16757f288 --- /dev/null +++ b/src/Sorter/SorterById.php @@ -0,0 +1,27 @@ +<?php + +/* + * This file was created by developers working at BitBag + * Do you need more information about us and what we do? Visit our https://bitbag.io website! + * We are hiring developers from all over the world. Join us and start your new, exciting adventure and become part of us: https://bitbag.io/career +*/ + +declare(strict_types=1); + +namespace BitBag\SyliusCmsPlugin\Sorter; + +final class SorterById +{ + public static function sort(array $elements, string $direction = 'asc'): array + { + usort($elements, static function ($element1, $element2) use ($direction) { + if ($direction === 'asc') { + return $element1->getId() <=> $element2->getId(); + } + + return $element2->getId() <=> $element1->getId(); + }); + + return $elements; + } +} diff --git a/src/Twig/Extension/RenderCollectionExtension.php b/src/Twig/Extension/RenderCollectionExtension.php new file mode 100644 index 000000000..246be6897 --- /dev/null +++ b/src/Twig/Extension/RenderCollectionExtension.php @@ -0,0 +1,33 @@ +<?php + +/* + * This file was created by developers working at BitBag + * Do you need more information about us and what we do? Visit our https://bitbag.io website! + * We are hiring developers from all over the world. Join us and start your new, exciting adventure and become part of us: https://bitbag.io/career +*/ + +declare(strict_types=1); + +namespace BitBag\SyliusCmsPlugin\Twig\Extension; + +use BitBag\SyliusCmsPlugin\Twig\Runtime\RenderCollectionRuntimeInterface; +use Twig\Extension\AbstractExtension; +use Twig\TwigFunction; + +final class RenderCollectionExtension extends AbstractExtension +{ + public function __construct(private RenderCollectionRuntimeInterface $collectionRuntime) + { + } + + public function getFunctions(): array + { + return [ + new TwigFunction( + 'bitbag_cms_render_collection', + [$this->collectionRuntime, 'renderCollection'], + ['is_safe' => ['html']], + ), + ]; + } +} diff --git a/src/Twig/Runtime/RenderCollectionRuntime.php b/src/Twig/Runtime/RenderCollectionRuntime.php new file mode 100644 index 000000000..45b9b5901 --- /dev/null +++ b/src/Twig/Runtime/RenderCollectionRuntime.php @@ -0,0 +1,42 @@ +<?php + +/* + * This file was created by developers working at BitBag + * Do you need more information about us and what we do? Visit our https://bitbag.io website! + * We are hiring developers from all over the world. Join us and start your new, exciting adventure and become part of us: https://bitbag.io/career +*/ + +declare(strict_types=1); + +namespace BitBag\SyliusCmsPlugin\Twig\Runtime; + +use BitBag\SyliusCmsPlugin\Renderer\CollectionRendererStrategyInterface; +use BitBag\SyliusCmsPlugin\Resolver\CollectionResourceResolverInterface; +use Twig\Environment; + +final class RenderCollectionRuntime implements RenderCollectionRuntimeInterface +{ + private const DEFAULT_TEMPLATE = '@BitBagSyliusCmsPlugin/Shop/Collection/show.html.twig'; + + public function __construct( + private Environment $twig, + private CollectionResourceResolverInterface $collectionResourceResolver, + private CollectionRendererStrategyInterface $collectionRenderer, + ) { + } + + public function renderCollection(string $code, ?int $countToRender = null, ?string $template = null): string + { + $collection = $this->collectionResourceResolver->findOrLog($code); + if (null === $collection) { + return ''; + } + + return $this->twig->render( + $template ?? self::DEFAULT_TEMPLATE, + [ + 'content' => $this->collectionRenderer->render($collection, $countToRender), + ], + ); + } +} diff --git a/src/Twig/Runtime/RenderCollectionRuntimeInterface.php b/src/Twig/Runtime/RenderCollectionRuntimeInterface.php new file mode 100644 index 000000000..ac6f52a17 --- /dev/null +++ b/src/Twig/Runtime/RenderCollectionRuntimeInterface.php @@ -0,0 +1,16 @@ +<?php + +/* + * This file was created by developers working at BitBag + * Do you need more information about us and what we do? Visit our https://bitbag.io website! + * We are hiring developers from all over the world. Join us and start your new, exciting adventure and become part of us: https://bitbag.io/career +*/ + +declare(strict_types=1); + +namespace BitBag\SyliusCmsPlugin\Twig\Runtime; + +interface RenderCollectionRuntimeInterface +{ + public function renderCollection(string $code, ?int $countToRender = null, ?string $template = null): string; +} diff --git a/tests/Application/templates/bundles/SyliusShopBundle/Homepage/index.html.twig b/tests/Application/templates/bundles/SyliusShopBundle/Homepage/index.html.twig index ab008b882..83f010ec7 100755 --- a/tests/Application/templates/bundles/SyliusShopBundle/Homepage/index.html.twig +++ b/tests/Application/templates/bundles/SyliusShopBundle/Homepage/index.html.twig @@ -1,6 +1,7 @@ {% extends '@SyliusShop/layout.html.twig' %} {% block content %} + {{ bitbag_cms_render_collection('blog') }} <div class="top one"> <div class="ui center aligned segment stackable grid cms-logo"> <a href="https://github.com/BitBagCommerce/SyliusCmsPlugin"> From eb876f402b6eba2183c9a5d6153067293c1076a4 Mon Sep 17 00:00:00 2001 From: jkindly <kozupa.jakub@gmail.com> Date: Tue, 23 Jul 2024 11:59:24 +0200 Subject: [PATCH 02/15] OP-441: ECS fixes --- src/Renderer/Collection/CollectionBlocksRenderer.php | 2 +- src/Renderer/Collection/CollectionMediaRenderer.php | 2 +- src/Renderer/Collection/CollectionPagesRenderer.php | 2 +- src/Sorter/SorterById.php | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Renderer/Collection/CollectionBlocksRenderer.php b/src/Renderer/Collection/CollectionBlocksRenderer.php index 584da2568..250cf5709 100644 --- a/src/Renderer/Collection/CollectionBlocksRenderer.php +++ b/src/Renderer/Collection/CollectionBlocksRenderer.php @@ -40,6 +40,6 @@ public function render(CollectionInterface $collection, ?int $countToRender = nu public function supports(CollectionInterface $collection): bool { - return $collection->getBlocks()?->count() > 0; + return 0 < $collection->getBlocks()?->count(); } } diff --git a/src/Renderer/Collection/CollectionMediaRenderer.php b/src/Renderer/Collection/CollectionMediaRenderer.php index b5c7ee8a3..ddb91be54 100644 --- a/src/Renderer/Collection/CollectionMediaRenderer.php +++ b/src/Renderer/Collection/CollectionMediaRenderer.php @@ -41,6 +41,6 @@ public function render(CollectionInterface $collection, ?int $countToRender = nu public function supports(CollectionInterface $collection): bool { - return $collection->getMedia()?->count() > 0; + return 0 < $collection->getMedia()?->count(); } } diff --git a/src/Renderer/Collection/CollectionPagesRenderer.php b/src/Renderer/Collection/CollectionPagesRenderer.php index 587434e17..2b5578cf6 100644 --- a/src/Renderer/Collection/CollectionPagesRenderer.php +++ b/src/Renderer/Collection/CollectionPagesRenderer.php @@ -40,6 +40,6 @@ public function render(CollectionInterface $collection, ?int $countToRender = nu public function supports(CollectionInterface $collection): bool { - return $collection->getPages()?->count() > 0; + return 0 < $collection->getPages()?->count(); } } diff --git a/src/Sorter/SorterById.php b/src/Sorter/SorterById.php index 16757f288..5ecdcd959 100644 --- a/src/Sorter/SorterById.php +++ b/src/Sorter/SorterById.php @@ -15,7 +15,7 @@ final class SorterById public static function sort(array $elements, string $direction = 'asc'): array { usort($elements, static function ($element1, $element2) use ($direction) { - if ($direction === 'asc') { + if ('asc' === $direction) { return $element1->getId() <=> $element2->getId(); } From 0b53af17cd4fb961dfbe51e57defd939a67e771c Mon Sep 17 00:00:00 2001 From: jkindly <kozupa.jakub@gmail.com> Date: Tue, 23 Jul 2024 14:12:36 +0200 Subject: [PATCH 03/15] OP-441: PHP Spec --- .../CollectionBlocksRendererSpec.php | 100 ++++++++++++++++++ .../CollectionMediaRendererSpec.php | 78 ++++++++++++++ .../CollectionPagesRendererSpec.php | 92 ++++++++++++++++ .../CollectionRendererStrategySpec.php | 73 +++++++++++++ spec/Renderer/PageLinkRendererSpec.php | 88 +++++++++++++++ 5 files changed, 431 insertions(+) create mode 100644 spec/Renderer/Collection/CollectionBlocksRendererSpec.php create mode 100644 spec/Renderer/Collection/CollectionMediaRendererSpec.php create mode 100644 spec/Renderer/Collection/CollectionPagesRendererSpec.php create mode 100644 spec/Renderer/CollectionRendererStrategySpec.php create mode 100644 spec/Renderer/PageLinkRendererSpec.php diff --git a/spec/Renderer/Collection/CollectionBlocksRendererSpec.php b/spec/Renderer/Collection/CollectionBlocksRendererSpec.php new file mode 100644 index 000000000..d131e1cbf --- /dev/null +++ b/spec/Renderer/Collection/CollectionBlocksRendererSpec.php @@ -0,0 +1,100 @@ +<?php + +/* + * This file was created by developers working at BitBag + * Do you need more information about us and what we do? Visit our https://bitbag.io website! + * We are hiring developers from all over the world. Join us and start your new, exciting adventure and become part of us: https://bitbag.io/career +*/ + +declare(strict_types=1); + +namespace spec\BitBag\SyliusCmsPlugin\Renderer\Collection; + +use BitBag\SyliusCmsPlugin\Entity\BlockInterface; +use BitBag\SyliusCmsPlugin\Entity\CollectionInterface; +use BitBag\SyliusCmsPlugin\Renderer\Collection\CollectionBlocksRenderer; +use BitBag\SyliusCmsPlugin\Renderer\Collection\CollectionRendererInterface; +use BitBag\SyliusCmsPlugin\Renderer\ContentElementRendererStrategyInterface; +use Doctrine\Common\Collections\ArrayCollection; +use PhpSpec\ObjectBehavior; + +final class CollectionBlocksRendererSpec extends ObjectBehavior +{ + public function let(ContentElementRendererStrategyInterface $contentElementRendererStrategy): void + { + $this->beConstructedWith($contentElementRendererStrategy); + } + + public function it_is_initializable(): void + { + $this->shouldHaveType(CollectionBlocksRenderer::class); + } + + public function it_implements_collection_renderer_interface(): void + { + $this->shouldImplement(CollectionRendererInterface::class); + } + + public function it_renders_blocks_from_collection( + ContentElementRendererStrategyInterface $contentElementRendererStrategy, + CollectionInterface $collection, + BlockInterface $block1, + BlockInterface $block2 + ): void + { + $blocks = new ArrayCollection([$block1->getWrappedObject(), $block2->getWrappedObject()]); + $collection->getBlocks()->willReturn($blocks); + + $contentElementRendererStrategy->render($block1)->willReturn('block1_content'); + $contentElementRendererStrategy->render($block2)->willReturn('block2_content'); + + $this->render($collection)->shouldReturn('block1_contentblock2_content'); + } + + public function it_limits_number_of_rendered_blocks( + ContentElementRendererStrategyInterface $contentElementRendererStrategy, + CollectionInterface $collection, + BlockInterface $block1, + BlockInterface $block2 + ): void + { + $blocks = new ArrayCollection([$block1->getWrappedObject(), $block2->getWrappedObject()]); + $collection->getBlocks()->willReturn($blocks); + + $contentElementRendererStrategy->render($block1)->willReturn('block1_content'); + $contentElementRendererStrategy->render($block2)->willReturn('block2_content'); + + $this->render($collection, 1)->shouldReturn('block1_content'); + } + + public function it_supports_collections_with_blocks( + CollectionInterface $collection, + BlockInterface $block + ): void + { + $blocks = new ArrayCollection([$block]); + $collection->getBlocks()->willReturn($blocks); + + $this->supports($collection)->shouldReturn(true); + } + + public function it_does_not_support_empty_collections( + CollectionInterface $collection + ): void + { + $collection->getBlocks()->willReturn(new ArrayCollection()); + + $this->supports($collection)->shouldReturn(false); + } + + public function it_throws_exception_when_blocks_are_null( + ContentElementRendererStrategyInterface $contentElementRendererStrategy, + CollectionInterface $collection + ): void + { + $collection->getBlocks()->willReturn(null); + + $this->shouldThrow(\InvalidArgumentException::class) + ->during('render', [$collection]); + } +} diff --git a/spec/Renderer/Collection/CollectionMediaRendererSpec.php b/spec/Renderer/Collection/CollectionMediaRendererSpec.php new file mode 100644 index 000000000..d04537038 --- /dev/null +++ b/spec/Renderer/Collection/CollectionMediaRendererSpec.php @@ -0,0 +1,78 @@ +<?php + +/* + * This file was created by developers working at BitBag + * Do you need more information about us and what we do? Visit our https://bitbag.io website! + * We are hiring developers from all over the world. Join us and start your new, exciting adventure and become part of us: https://bitbag.io/career +*/ + +declare(strict_types=1); + +namespace spec\BitBag\SyliusCmsPlugin\Renderer\Collection; + +use BitBag\SyliusCmsPlugin\Entity\CollectionInterface; +use BitBag\SyliusCmsPlugin\Entity\MediaInterface; +use BitBag\SyliusCmsPlugin\Renderer\Collection\CollectionMediaRenderer; +use BitBag\SyliusCmsPlugin\Renderer\Collection\CollectionRendererInterface; +use BitBag\SyliusCmsPlugin\Twig\Runtime\RenderMediaRuntimeInterface; +use Doctrine\Common\Collections\ArrayCollection; +use PhpSpec\ObjectBehavior; + +final class CollectionMediaRendererSpec extends ObjectBehavior +{ + function let(RenderMediaRuntimeInterface $renderMediaRuntime) + { + $this->beConstructedWith($renderMediaRuntime); + } + + function it_is_initializable() + { + $this->shouldHaveType(CollectionMediaRenderer::class); + $this->shouldImplement(CollectionRendererInterface::class); + } + + function it_renders_media_collection(RenderMediaRuntimeInterface $renderMediaRuntime, CollectionInterface $collection, MediaInterface $media1, MediaInterface $media2) + { + $media1->getId()->willReturn(1); + $media2->getId()->willReturn(2); + + $media1->getCode()->willReturn('media_code_1'); + $media2->getCode()->willReturn('media_code_2'); + + $collection->getMedia()->willReturn(new ArrayCollection([$media1->getWrappedObject(), $media2->getWrappedObject()])); + + $renderMediaRuntime->renderMedia('media_code_1')->willReturn('media1'); + $renderMediaRuntime->renderMedia('media_code_2')->willReturn('media2'); + + $this->render($collection)->shouldReturn('media1media2'); + } + + function it_renders_limited_number_of_media(RenderMediaRuntimeInterface $renderMediaRuntime, CollectionInterface $collection, MediaInterface $media1, MediaInterface $media2) + { + $media1->getId()->willReturn(1); + $media2->getId()->willReturn(2); + + $media1->getCode()->willReturn('media_code_1'); + $media2->getCode()->willReturn('media_code_2'); + + $collection->getMedia()->willReturn(new ArrayCollection([$media1->getWrappedObject(), $media2->getWrappedObject()])); + + $renderMediaRuntime->renderMedia('media_code_1')->willReturn('media1'); + + $this->render($collection, 1)->shouldReturn('media1'); + } + + function it_supports_collections_with_media(CollectionInterface $collection, MediaInterface $media1) + { + $collection->getMedia()->willReturn(new ArrayCollection([$media1])); + + $this->supports($collection)->shouldReturn(true); + } + + function it_does_not_support_collections_without_media(CollectionInterface $collection) + { + $collection->getMedia()->willReturn(new ArrayCollection()); + + $this->supports($collection)->shouldReturn(false); + } +} diff --git a/spec/Renderer/Collection/CollectionPagesRendererSpec.php b/spec/Renderer/Collection/CollectionPagesRendererSpec.php new file mode 100644 index 000000000..e5421f555 --- /dev/null +++ b/spec/Renderer/Collection/CollectionPagesRendererSpec.php @@ -0,0 +1,92 @@ +<?php + +/* + * This file was created by developers working at BitBag + * Do you need more information about us and what we do? Visit our https://bitbag.io website! + * We are hiring developers from all over the world. Join us and start your new, exciting adventure and become part of us: https://bitbag.io/career +*/ + +declare(strict_types=1); + +namespace spec\BitBag\SyliusCmsPlugin\Renderer\Collection; + +use BitBag\SyliusCmsPlugin\Entity\CollectionInterface; +use BitBag\SyliusCmsPlugin\Entity\PageInterface; +use BitBag\SyliusCmsPlugin\Renderer\Collection\CollectionPagesRenderer; +use BitBag\SyliusCmsPlugin\Renderer\Collection\CollectionRendererInterface; +use BitBag\SyliusCmsPlugin\Renderer\PageLinkRendererInterface; +use Doctrine\Common\Collections\ArrayCollection; +use PhpSpec\ObjectBehavior; + +final class CollectionPagesRendererSpec extends ObjectBehavior +{ + public function let(PageLinkRendererInterface $pageLinkRenderer): void + { + $this->beConstructedWith($pageLinkRenderer); + } + + public function it_is_initializable(): void + { + $this->shouldHaveType(CollectionPagesRenderer::class); + } + + public function it_implements_collection_renderer_interface(): void + { + $this->shouldImplement(CollectionRendererInterface::class); + } + + public function it_renders_pages_from_collection( + PageLinkRendererInterface $pageLinkRenderer, + CollectionInterface $collection, + PageInterface $page1, + PageInterface $page2 + ): void + { + $page1->getId()->willReturn(2); + $page2->getId()->willReturn(1); + + $collection->getPages()->willReturn(new ArrayCollection([$page1->getWrappedObject(), $page2->getWrappedObject()])); + + $pageLinkRenderer->render($page1)->willReturn('page1_content'); + $pageLinkRenderer->render($page2)->willReturn('page2_content'); + + $this->render($collection)->shouldReturn('page1_contentpage2_content'); + } + + public function it_limits_number_of_rendered_pages( + PageLinkRendererInterface $pageLinkRenderer, + CollectionInterface $collection, + PageInterface $page1, + PageInterface $page2 + ): void + { + $page1->getId()->willReturn(2); + $page2->getId()->willReturn(1); + + $collection->getPages()->willReturn(new ArrayCollection([$page1->getWrappedObject(), $page2->getWrappedObject()])); + + $pageLinkRenderer->render($page1)->willReturn('page1_content'); + $pageLinkRenderer->render($page2)->willReturn('page2_content'); + + $this->render($collection, 1)->shouldReturn('page1_content'); + } + + public function it_supports_collections_with_pages( + CollectionInterface $collection, + PageInterface $page + ): void + { + $collection->getPages()->willReturn(new ArrayCollection([$page])); + + $this->supports($collection)->shouldReturn(true); + } + + public function it_does_not_support_empty_collections( + CollectionInterface $collection + ): void + { + $collection->getPages()->willReturn(new ArrayCollection()); + + $this->supports($collection)->shouldReturn(false); + } +} diff --git a/spec/Renderer/CollectionRendererStrategySpec.php b/spec/Renderer/CollectionRendererStrategySpec.php new file mode 100644 index 000000000..67aebde51 --- /dev/null +++ b/spec/Renderer/CollectionRendererStrategySpec.php @@ -0,0 +1,73 @@ +<?php + +/* + * This file was created by developers working at BitBag + * Do you need more information about us and what we do? Visit our https://bitbag.io website! + * We are hiring developers from all over the world. Join us and start your new, exciting adventure and become part of us: https://bitbag.io/career +*/ + +declare(strict_types=1); + +namespace spec\BitBag\SyliusCmsPlugin\Renderer; + +use BitBag\SyliusCmsPlugin\Entity\CollectionInterface; +use BitBag\SyliusCmsPlugin\Renderer\Collection\CollectionRendererInterface; +use BitBag\SyliusCmsPlugin\Renderer\CollectionRendererStrategy; +use BitBag\SyliusCmsPlugin\Renderer\CollectionRendererStrategyInterface; +use PhpSpec\ObjectBehavior; + +final class CollectionRendererStrategySpec extends ObjectBehavior +{ + public function let(CollectionRendererInterface $renderer1, CollectionRendererInterface $renderer2): void + { + $this->beConstructedWith([$renderer1, $renderer2]); + } + + public function it_is_initializable(): void + { + $this->shouldHaveType(CollectionRendererStrategy::class); + } + + public function it_implements_collection_renderer_strategy_interface(): void + { + $this->shouldImplement(CollectionRendererStrategyInterface::class); + } + + public function it_renders_collection_using_supported_renderer( + CollectionRendererInterface $renderer1, + CollectionRendererInterface $renderer2, + CollectionInterface $collection + ): void + { + $renderer1->supports($collection)->willReturn(false); + $renderer2->supports($collection)->willReturn(true); + $renderer2->render($collection, null)->willReturn('rendered content'); + + $this->render($collection)->shouldReturn('rendered content'); + } + + public function it_renders_collection_with_count_to_render( + CollectionRendererInterface $renderer1, + CollectionRendererInterface $renderer2, + CollectionInterface $collection + ): void + { + $renderer1->supports($collection)->willReturn(false); + $renderer2->supports($collection)->willReturn(true); + $renderer2->render($collection, 5)->willReturn('rendered content with count'); + + $this->render($collection, 5)->shouldReturn('rendered content with count'); + } + + public function it_returns_empty_string_when_no_renderer_supports_collection( + CollectionRendererInterface $renderer1, + CollectionRendererInterface $renderer2, + CollectionInterface $collection + ): void + { + $renderer1->supports($collection)->willReturn(false); + $renderer2->supports($collection)->willReturn(false); + + $this->render($collection)->shouldReturn(''); + } +} diff --git a/spec/Renderer/PageLinkRendererSpec.php b/spec/Renderer/PageLinkRendererSpec.php new file mode 100644 index 000000000..45fb7b5f9 --- /dev/null +++ b/spec/Renderer/PageLinkRendererSpec.php @@ -0,0 +1,88 @@ +<?php + +/* + * This file was created by developers working at BitBag + * Do you need more information about us and what we do? Visit our https://bitbag.io website! + * We are hiring developers from all over the world. Join us and start your new, exciting adventure and become part of us: https://bitbag.io/career +*/ + +declare(strict_types=1); + +namespace spec\BitBag\SyliusCmsPlugin\Renderer; + +use BitBag\SyliusCmsPlugin\Entity\PageInterface; +use BitBag\SyliusCmsPlugin\Renderer\PageLinkRenderer; +use BitBag\SyliusCmsPlugin\Renderer\PageLinkRendererInterface; +use PhpSpec\ObjectBehavior; +use Symfony\Component\Routing\Generator\UrlGeneratorInterface; +use Twig\Environment; + +final class PageLinkRendererSpec extends ObjectBehavior +{ + public function let( + UrlGeneratorInterface $urlGenerator, + Environment $twig + ): void { + $this->beConstructedWith($urlGenerator, $twig); + } + + public function it_is_initializable(): void + { + $this->shouldHaveType(PageLinkRenderer::class); + } + + public function it_implements_page_link_renderer_interface(): void + { + $this->shouldImplement(PageLinkRendererInterface::class); + } + + public function it_renders_page_link_with_default_template( + UrlGeneratorInterface $urlGenerator, + Environment $twig, + PageInterface $page + ): void { + $page->getSlug()->willReturn('page-slug'); + $page->getName()->willReturn('Page Name'); + + $urlGenerator->generate( + 'bitbag_sylius_cms_plugin_shop_page_show', + ['slug' => 'page-slug'], + UrlGeneratorInterface::ABSOLUTE_URL + )->willReturn('http://example.com/page-slug'); + + $twig->render( + '@BitBagSyliusCmsPlugin/Shop/Page/link.html.twig', + [ + 'link' => 'http://example.com/page-slug', + 'name' => 'Page Name', + ] + )->willReturn('<a href="http://example.com/page-slug">Page Name</a>'); + + $this->render($page)->shouldReturn('<a href="http://example.com/page-slug">Page Name</a>'); + } + + public function it_renders_page_link_with_custom_template( + UrlGeneratorInterface $urlGenerator, + Environment $twig, + PageInterface $page + ): void { + $page->getSlug()->willReturn('page-slug'); + $page->getName()->willReturn('Page Name'); + + $urlGenerator->generate( + 'bitbag_sylius_cms_plugin_shop_page_show', + ['slug' => 'page-slug'], + UrlGeneratorInterface::ABSOLUTE_URL + )->willReturn('http://example.com/page-slug'); + + $twig->render( + 'custom_template.html.twig', + [ + 'link' => 'http://example.com/page-slug', + 'name' => 'Page Name', + ] + )->willReturn('<a href="http://example.com/page-slug">Page Name</a>'); + + $this->render($page, 'custom_template.html.twig')->shouldReturn('<a href="http://example.com/page-slug">Page Name</a>'); + } +} From 637020ec7bb49e74bd6eb44aba87f5acf1b0b416 Mon Sep 17 00:00:00 2001 From: jkindly <kozupa.jakub@gmail.com> Date: Fri, 19 Jul 2024 11:22:51 +0200 Subject: [PATCH 04/15] OP-440: Conditional block rendering --- src/Entity/Block.php | 13 +++++ src/Entity/BlockInterface.php | 7 ++- src/Entity/BlockProductAwareInterface.php | 20 ++++++++ src/Entity/BlockTaxonAwareInterface.php | 18 +++++++ src/Entity/ProductsInTaxonsAwareInterface.php | 30 +++++++++++ src/Entity/Trait/BlockProductAwareTrait.php | 31 ++++++++++++ src/Entity/Trait/BlockTaxonAwareTrait.php | 21 ++++++++ src/Entity/Trait/ProductsAwareTrait.php | 2 +- .../Trait/ProductsInTaxonsAwareTrait.php | 50 +++++++++++++++++++ src/Entity/Trait/TaxonAwareTrait.php | 12 ++--- src/Form/Type/BlockType.php | 17 +++++++ src/Resources/assets/admin/scss/_css.scss | 6 +++ src/Resources/config/doctrine/Block.orm.xml | 33 ++++++++++++ .../views/Block/Crud/_form.html.twig | 6 +++ src/Resources/views/Form/theme.html.twig | 22 ++++++++ src/Twig/Runtime/RenderBlockRuntime.php | 30 +++++++---- .../SyliusShopBundle/Product/show.html.twig | 2 +- .../Taxon/Header/_content.html.twig | 6 +++ 18 files changed, 307 insertions(+), 19 deletions(-) create mode 100644 src/Entity/BlockProductAwareInterface.php create mode 100644 src/Entity/BlockTaxonAwareInterface.php create mode 100755 src/Entity/ProductsInTaxonsAwareInterface.php create mode 100644 src/Entity/Trait/BlockProductAwareTrait.php create mode 100644 src/Entity/Trait/BlockTaxonAwareTrait.php create mode 100644 src/Entity/Trait/ProductsInTaxonsAwareTrait.php create mode 100644 tests/Application/templates/bundles/SyliusShopBundle/Taxon/Header/_content.html.twig diff --git a/src/Entity/Block.php b/src/Entity/Block.php index 4c8cb7341..3457c357c 100755 --- a/src/Entity/Block.php +++ b/src/Entity/Block.php @@ -10,10 +10,15 @@ namespace BitBag\SyliusCmsPlugin\Entity; +use BitBag\SyliusCmsPlugin\Entity\Trait\BlockProductAwareTrait; +use BitBag\SyliusCmsPlugin\Entity\Trait\BlockTaxonAwareTrait; use BitBag\SyliusCmsPlugin\Entity\Trait\ChannelsAwareTrait; use BitBag\SyliusCmsPlugin\Entity\Trait\CollectibleTrait; use BitBag\SyliusCmsPlugin\Entity\Trait\ContentConfigurationAwareTrait; use BitBag\SyliusCmsPlugin\Entity\Trait\LocaleAwareTrait; +use BitBag\SyliusCmsPlugin\Entity\Trait\ProductsAwareTrait; +use BitBag\SyliusCmsPlugin\Entity\Trait\ProductsInTaxonsAwareTrait; +use BitBag\SyliusCmsPlugin\Entity\Trait\TaxonAwareTrait; use Sylius\Component\Resource\Model\ToggleableTrait; class Block implements BlockInterface @@ -23,6 +28,11 @@ class Block implements BlockInterface use ChannelsAwareTrait; use ContentConfigurationAwareTrait; use LocaleAwareTrait; + use ProductsAwareTrait; + use TaxonAwareTrait; + use ProductsInTaxonsAwareTrait; + use BlockTaxonAwareTrait; + use BlockProductAwareTrait; public function __construct() { @@ -30,6 +40,9 @@ public function __construct() $this->initializeChannelsCollection(); $this->initializeContentElementsCollection(); $this->initializeLocalesCollection(); + $this->initializeProductsCollection(); + $this->initializeTaxonCollection(); + $this->initializeProductsInTaxonsCollection(); } protected ?int $id; diff --git a/src/Entity/BlockInterface.php b/src/Entity/BlockInterface.php index c60770207..e3c002ac0 100755 --- a/src/Entity/BlockInterface.php +++ b/src/Entity/BlockInterface.php @@ -20,7 +20,12 @@ interface BlockInterface extends CollectibleInterface, ChannelsAwareInterface, ContentConfigurationAwareInterface, - LocaleAwareInterface + LocaleAwareInterface, + ProductsAwareInterface, + TaxonAwareInterface, + ProductsInTaxonsAwareInterface, + BlockTaxonAwareInterface, + BlockProductAwareInterface { public function getCode(): ?string; diff --git a/src/Entity/BlockProductAwareInterface.php b/src/Entity/BlockProductAwareInterface.php new file mode 100644 index 000000000..fbbb94e9d --- /dev/null +++ b/src/Entity/BlockProductAwareInterface.php @@ -0,0 +1,20 @@ +<?php + +/* + * This file was created by developers working at BitBag + * Do you need more information about us and what we do? Visit our https://bitbag.io website! + * We are hiring developers from all over the world. Join us and start your new, exciting adventure and become part of us: https://bitbag.io/career +*/ + +declare(strict_types=1); + +namespace BitBag\SyliusCmsPlugin\Entity; + +use Sylius\Component\Core\Model\ProductInterface; + +interface BlockProductAwareInterface +{ + public function canBeDisplayedForProduct(ProductInterface $product): bool; + + public function canBeDisplayedForProductInTaxon(ProductInterface $product): bool; +} diff --git a/src/Entity/BlockTaxonAwareInterface.php b/src/Entity/BlockTaxonAwareInterface.php new file mode 100644 index 000000000..1c4b8a57c --- /dev/null +++ b/src/Entity/BlockTaxonAwareInterface.php @@ -0,0 +1,18 @@ +<?php + +/* + * This file was created by developers working at BitBag + * Do you need more information about us and what we do? Visit our https://bitbag.io website! + * We are hiring developers from all over the world. Join us and start your new, exciting adventure and become part of us: https://bitbag.io/career +*/ + +declare(strict_types=1); + +namespace BitBag\SyliusCmsPlugin\Entity; + +use Sylius\Component\Core\Model\TaxonInterface; + +interface BlockTaxonAwareInterface +{ + public function canBeDisplayedForTaxon(TaxonInterface $taxon): bool; +} diff --git a/src/Entity/ProductsInTaxonsAwareInterface.php b/src/Entity/ProductsInTaxonsAwareInterface.php new file mode 100755 index 000000000..4a03c9939 --- /dev/null +++ b/src/Entity/ProductsInTaxonsAwareInterface.php @@ -0,0 +1,30 @@ +<?php + +/* + * This file was created by developers working at BitBag + * Do you need more information about us and what we do? Visit our https://bitbag.io website! + * We are hiring developers from all over the world. Join us and start your new, exciting adventure and become part of us: https://bitbag.io/career +*/ + +declare(strict_types=1); + +namespace BitBag\SyliusCmsPlugin\Entity; + +use Doctrine\Common\Collections\Collection; +use Sylius\Component\Core\Model\TaxonInterface; + +interface ProductsInTaxonsAwareInterface +{ + public function initializeProductsInTaxonsCollection(): void; + + /** + * @return Collection|TaxonInterface[] + */ + public function getProductsInTaxons(): Collection; + + public function hasProductsInTaxon(TaxonInterface $taxon): bool; + + public function addProductsInTaxon(TaxonInterface $taxon): void; + + public function removeProductsInTaxon(TaxonInterface $taxon): void; +} diff --git a/src/Entity/Trait/BlockProductAwareTrait.php b/src/Entity/Trait/BlockProductAwareTrait.php new file mode 100644 index 000000000..27c13ab82 --- /dev/null +++ b/src/Entity/Trait/BlockProductAwareTrait.php @@ -0,0 +1,31 @@ +<?php + +/* + * This file was created by developers working at BitBag + * Do you need more information about us and what we do? Visit our https://bitbag.io website! + * We are hiring developers from all over the world. Join us and start your new, exciting adventure and become part of us: https://bitbag.io/career +*/ + +declare(strict_types=1); + +namespace BitBag\SyliusCmsPlugin\Entity\Trait; + +use Sylius\Component\Core\Model\ProductInterface; + +trait BlockProductAwareTrait +{ + public function canBeDisplayedForProduct(ProductInterface $product): bool + { + return $this->hasProduct($product); + } + + public function canBeDisplayedForProductInTaxon(ProductInterface $product): bool + { + $taxon = $product->getMainTaxon(); + if (null === $taxon) { + return false; + } + + return $this->hasProductsInTaxon($taxon); + } +} diff --git a/src/Entity/Trait/BlockTaxonAwareTrait.php b/src/Entity/Trait/BlockTaxonAwareTrait.php new file mode 100644 index 000000000..c84cd24cd --- /dev/null +++ b/src/Entity/Trait/BlockTaxonAwareTrait.php @@ -0,0 +1,21 @@ +<?php + +/* + * This file was created by developers working at BitBag + * Do you need more information about us and what we do? Visit our https://bitbag.io website! + * We are hiring developers from all over the world. Join us and start your new, exciting adventure and become part of us: https://bitbag.io/career +*/ + +declare(strict_types=1); + +namespace BitBag\SyliusCmsPlugin\Entity\Trait; + +use Sylius\Component\Core\Model\TaxonInterface; + +trait BlockTaxonAwareTrait +{ + public function canBeDisplayedForTaxon(TaxonInterface $taxon): bool + { + return $this->hasTaxon($taxon); + } +} diff --git a/src/Entity/Trait/ProductsAwareTrait.php b/src/Entity/Trait/ProductsAwareTrait.php index 16478bb2d..3710dea32 100755 --- a/src/Entity/Trait/ProductsAwareTrait.php +++ b/src/Entity/Trait/ProductsAwareTrait.php @@ -17,7 +17,7 @@ trait ProductsAwareTrait { /** @var Collection|ProductInterface[] */ - protected $products; + protected array|Collection $products; public function initializeProductsCollection(): void { diff --git a/src/Entity/Trait/ProductsInTaxonsAwareTrait.php b/src/Entity/Trait/ProductsInTaxonsAwareTrait.php new file mode 100644 index 000000000..6e331bdf8 --- /dev/null +++ b/src/Entity/Trait/ProductsInTaxonsAwareTrait.php @@ -0,0 +1,50 @@ +<?php + +/* + * This file was created by developers working at BitBag + * Do you need more information about us and what we do? Visit our https://bitbag.io website! + * We are hiring developers from all over the world. Join us and start your new, exciting adventure and become part of us: https://bitbag.io/career +*/ + +declare(strict_types=1); + +namespace BitBag\SyliusCmsPlugin\Entity\Trait; + +use Doctrine\Common\Collections\ArrayCollection; +use Doctrine\Common\Collections\Collection; +use Sylius\Component\Core\Model\TaxonInterface; + +trait ProductsInTaxonsAwareTrait +{ + /** @var Collection|TaxonInterface[] */ + protected array|Collection $productsInTaxons; + + public function initializeProductsInTaxonsCollection(): void + { + $this->productsInTaxons = new ArrayCollection(); + } + + public function getProductsInTaxons(): Collection + { + return $this->productsInTaxons; + } + + public function hasProductsInTaxon(TaxonInterface $taxon): bool + { + return $this->productsInTaxons->contains($taxon); + } + + public function addProductsInTaxon(TaxonInterface $taxon): void + { + if (false === $this->hasProductsInTaxon($taxon)) { + $this->productsInTaxons->add($taxon); + } + } + + public function removeProductsInTaxon(TaxonInterface $taxon): void + { + if (true === $this->hasProductsInTaxon($taxon)) { + $this->productsInTaxons->removeElement($taxon); + } + } +} diff --git a/src/Entity/Trait/TaxonAwareTrait.php b/src/Entity/Trait/TaxonAwareTrait.php index 1306731ed..8edc13cc7 100644 --- a/src/Entity/Trait/TaxonAwareTrait.php +++ b/src/Entity/Trait/TaxonAwareTrait.php @@ -17,34 +17,34 @@ trait TaxonAwareTrait { /** @var Collection|TaxonInterface[] */ - protected $taxonomies; + protected array|Collection $taxons; public function initializeTaxonCollection(): void { - $this->taxonomies = new ArrayCollection(); + $this->taxons = new ArrayCollection(); } public function getTaxons(): Collection { - return $this->taxonomies; + return $this->taxons; } public function hasTaxon(TaxonInterface $taxon): bool { - return $this->taxonomies->contains($taxon); + return $this->taxons->contains($taxon); } public function addTaxon(TaxonInterface $taxon): void { if (false === $this->hasTaxon($taxon)) { - $this->taxonomies->add($taxon); + $this->taxons->add($taxon); } } public function removeTaxon(TaxonInterface $taxon): void { if (true === $this->hasTaxon($taxon)) { - $this->taxonomies->removeElement($taxon); + $this->taxons->removeElement($taxon); } } } diff --git a/src/Form/Type/BlockType.php b/src/Form/Type/BlockType.php index c1425b237..73fb6c3de 100755 --- a/src/Form/Type/BlockType.php +++ b/src/Form/Type/BlockType.php @@ -12,7 +12,9 @@ use BitBag\SyliusCmsPlugin\Entity\BlockInterface; use Sylius\Bundle\ChannelBundle\Form\Type\ChannelChoiceType; +use Sylius\Bundle\ProductBundle\Form\Type\ProductAutocompleteChoiceType; use Sylius\Bundle\ResourceBundle\Form\Type\AbstractResourceType; +use Sylius\Bundle\TaxonomyBundle\Form\Type\TaxonAutocompleteChoiceType; use Symfony\Component\Form\Extension\Core\Type\CheckboxType; use Symfony\Component\Form\Extension\Core\Type\CollectionType; use Symfony\Component\Form\Extension\Core\Type\TextType; @@ -55,6 +57,21 @@ public function buildForm(FormBuilderInterface $builder, array $options): void 'by_reference' => false, 'required' => false, ]) + ->add('products', ProductAutocompleteChoiceType::class, [ + 'label' => 'bitbag_sylius_cms_plugin.ui.display_for_products.label', + 'multiple' => true, + 'help' => 'bitbag_sylius_cms_plugin.ui.display_for_products.help', + ]) + ->add('productsInTaxons', TaxonAutocompleteChoiceType::class, [ + 'label' => 'bitbag_sylius_cms_plugin.ui.display_for_products_in_taxons.label', + 'multiple' => true, + 'help' => 'bitbag_sylius_cms_plugin.ui.display_for_products_in_taxons.help' + ]) + ->add('taxons', TaxonAutocompleteChoiceType::class, [ + 'label' => 'bitbag_sylius_cms_plugin.ui.display_for_taxons.label', + 'multiple' => true, + 'help' => 'bitbag_sylius_cms_plugin.ui.display_for_taxons.help', + ]) ; } diff --git a/src/Resources/assets/admin/scss/_css.scss b/src/Resources/assets/admin/scss/_css.scss index 872507af4..d3c63c491 100644 --- a/src/Resources/assets/admin/scss/_css.scss +++ b/src/Resources/assets/admin/scss/_css.scss @@ -115,3 +115,9 @@ .cke_notifications_area { display: none; } + +.help-text { + font-size: 12px; + margin-top: -10px; + opacity: 0.5; +} diff --git a/src/Resources/config/doctrine/Block.orm.xml b/src/Resources/config/doctrine/Block.orm.xml index 78b52ac7b..eaf0eb4cf 100644 --- a/src/Resources/config/doctrine/Block.orm.xml +++ b/src/Resources/config/doctrine/Block.orm.xml @@ -58,5 +58,38 @@ </join-table> </many-to-many> + <many-to-many field="products" target-entity="Sylius\Component\Core\Model\ProductInterface"> + <join-table name="bitbag_cms_block_products"> + <join-columns> + <join-column name="block_id" referenced-column-name="id" nullable="false" on-delete="CASCADE"/> + </join-columns> + <inverse-join-columns> + <join-column name="product_id" referenced-column-name="id" nullable="false" on-delete="CASCADE"/> + </inverse-join-columns> + </join-table> + </many-to-many> + + <many-to-many field="taxons" target-entity="Sylius\Component\Core\Model\TaxonInterface"> + <join-table name="bitbag_cms_block_taxons"> + <join-columns> + <join-column name="block_id" referenced-column-name="id" nullable="false" on-delete="CASCADE"/> + </join-columns> + <inverse-join-columns> + <join-column name="taxon_id" referenced-column-name="id" nullable="false" on-delete="CASCADE"/> + </inverse-join-columns> + </join-table> + </many-to-many> + + <many-to-many field="productsInTaxons" target-entity="Sylius\Component\Core\Model\TaxonInterface"> + <join-table name="bitbag_cms_block_products_in_taxons"> + <join-columns> + <join-column name="block_id" referenced-column-name="id" nullable="false" on-delete="CASCADE"/> + </join-columns> + <inverse-join-columns> + <join-column name="taxon_id" referenced-column-name="id" nullable="false" on-delete="CASCADE"/> + </inverse-join-columns> + </join-table> + </many-to-many> + </mapped-superclass> </doctrine-mapping> diff --git a/src/Resources/views/Block/Crud/_form.html.twig b/src/Resources/views/Block/Crud/_form.html.twig index d6d326322..d53d42d74 100755 --- a/src/Resources/views/Block/Crud/_form.html.twig +++ b/src/Resources/views/Block/Crud/_form.html.twig @@ -12,6 +12,12 @@ {{ form_row(form.locales) }} {{ form_row(form.collections) }} </div> + <div class="ui segment"> + <h4 class="ui dividing header">{{ 'bitbag_sylius_cms_plugin.ui.manage_block_display'|trans }}</h4> + {{ form_row(form.products) }} + {{ form_row(form.productsInTaxons) }} + {{ form_row(form.taxons) }} + </div> </div> <div class="column"> <div class="ui segment"> diff --git a/src/Resources/views/Form/theme.html.twig b/src/Resources/views/Form/theme.html.twig index 841343b8f..66b88405f 100755 --- a/src/Resources/views/Form/theme.html.twig +++ b/src/Resources/views/Form/theme.html.twig @@ -104,3 +104,25 @@ </div> {% endapply %} {% endmacro %} + +{% block sylius_resource_autocomplete_choice_row %} + <div class="{% if required %}required {% endif %}{% if disabled %}disabled {% endif %}field{% if (not compound or force_error|default(false)) and not valid %} error{% endif %}"> + {{- form_label(form) -}} + {{- form_help(form) -}} + <div + class="sylius-autocomplete ui fluid search selection dropdown {% if multiple %}multiple{% endif %}" + data-url="{{ remote_url }}" + data-choice-name="{{ choice_name }}" + data-choice-value="{{ choice_value }}" + data-criteria-type="{{ remote_criteria_type }}" + data-criteria-name="{{ remote_criteria_name }}" + data-load-edit-url="{{ load_edit_url }}" + > + {{- form_widget(form, {'attr': {'class' : 'autocomplete'}}) -}} + <i class="dropdown icon"></i> + <div class="default text">{% if placeholder is defined %} {{ placeholder|trans }} {% endif %}</div> + <div class="menu"></div> + </div> + {{- form_errors(form) -}} + </div> +{% endblock %} diff --git a/src/Twig/Runtime/RenderBlockRuntime.php b/src/Twig/Runtime/RenderBlockRuntime.php index ddec96185..6b8798be2 100644 --- a/src/Twig/Runtime/RenderBlockRuntime.php +++ b/src/Twig/Runtime/RenderBlockRuntime.php @@ -12,6 +12,8 @@ use BitBag\SyliusCmsPlugin\Renderer\ContentElementRendererStrategyInterface; use BitBag\SyliusCmsPlugin\Resolver\BlockResourceResolverInterface; +use Sylius\Component\Core\Model\ProductInterface; +use Sylius\Component\Core\Model\TaxonInterface; use Twig\Environment; final class RenderBlockRuntime implements RenderBlockRuntimeInterface @@ -25,21 +27,29 @@ public function __construct( ) { } - public function renderBlock(string $code, ?string $template = null): string + public function renderBlock(string $code, ?string $template = null, ProductInterface|TaxonInterface $context = null): string { $block = $this->blockResourceResolver->findOrLog($code); + if (null === $block) { + return ''; + } - if (null !== $block) { - $template = $template ?? self::DEFAULT_TEMPLATE; + if ($context instanceof TaxonInterface && false === $block->canBeDisplayedForTaxon($context)) { + return ''; + } - return $this->templatingEngine->render( - $template, - [ - 'content' => $this->contentElementRendererStrategy->render($block), - ], - ); + if ($context instanceof ProductInterface && + false === $block->canBeDisplayedForProduct($context) && + false === $block->canBeDisplayedForProductInTaxon($context) + ) { + return ''; } - return ''; + return $this->templatingEngine->render( + $template ?? self::DEFAULT_TEMPLATE, + [ + 'content' => $this->contentElementRendererStrategy->render($block), + ], + ); } } diff --git a/tests/Application/templates/bundles/SyliusShopBundle/Product/show.html.twig b/tests/Application/templates/bundles/SyliusShopBundle/Product/show.html.twig index eb749f4b3..37da1040b 100755 --- a/tests/Application/templates/bundles/SyliusShopBundle/Product/show.html.twig +++ b/tests/Application/templates/bundles/SyliusShopBundle/Product/show.html.twig @@ -52,7 +52,7 @@ {{ render(path('bitbag_sylius_cms_plugin_shop_block_index_by_collection_code', {'collectionCode' : 'products', 'template' : '@BitBagSyliusCmsPlugin/Shop/Block/index.html.twig'})) }} - {{ bitbag_cms_render_block('lorem_ipsum') }} + {{ bitbag_cms_render_block('lorem_ipsum', null, product) }} {{ sonata_block_render_event('sylius.shop.product.show.before_tabs', {'product': product}) }} diff --git a/tests/Application/templates/bundles/SyliusShopBundle/Taxon/Header/_content.html.twig b/tests/Application/templates/bundles/SyliusShopBundle/Taxon/Header/_content.html.twig new file mode 100644 index 000000000..c55f25be1 --- /dev/null +++ b/tests/Application/templates/bundles/SyliusShopBundle/Taxon/Header/_content.html.twig @@ -0,0 +1,6 @@ +<h1 class="ui monster section dividing header"> + {{ taxon.name }} + <div class="sub header">{{ taxon.description }}</div> +</h1> + +{{ bitbag_cms_render_block('lorem_ipsum', null, taxon) }} From 7a8ac18b940073105931bccc2b6d905103379cc0 Mon Sep 17 00:00:00 2001 From: jkindly <kozupa.jakub@gmail.com> Date: Fri, 19 Jul 2024 12:34:57 +0200 Subject: [PATCH 05/15] OP-440: Translations --- src/Resources/translations/messages.cs.yml | 10 ++++++++++ src/Resources/translations/messages.cs_CZ.yml | 10 ++++++++++ src/Resources/translations/messages.de.yml | 10 ++++++++++ src/Resources/translations/messages.en.yml | 10 ++++++++++ src/Resources/translations/messages.es.yml | 10 ++++++++++ src/Resources/translations/messages.fr.yml | 10 ++++++++++ src/Resources/translations/messages.hr.yml | 10 ++++++++++ src/Resources/translations/messages.lt.yml | 10 ++++++++++ src/Resources/translations/messages.nl.yml | 10 ++++++++++ src/Resources/translations/messages.pl.yml | 10 ++++++++++ src/Resources/translations/messages.ru.yml | 10 ++++++++++ src/Resources/translations/messages.sk.yml | 10 ++++++++++ src/Resources/translations/messages.uk.yml | 10 ++++++++++ 13 files changed, 130 insertions(+) diff --git a/src/Resources/translations/messages.cs.yml b/src/Resources/translations/messages.cs.yml index 6ad54fb2f..1648a6c49 100755 --- a/src/Resources/translations/messages.cs.yml +++ b/src/Resources/translations/messages.cs.yml @@ -20,6 +20,16 @@ bitbag_sylius_cms_plugin: products_grid_by_taxon: Produkty v mřížce podle taxonu heading_type: Typ nadpisu taxon: Taxon + display_for_products: + label: Zobrazit pro produkty + help: Vyberte produkty, ve kterých se bude tento blok zobrazovat + display_for_products_in_taxons: + label: Zobrazit pro produkty v taxonech + help: Tento blok bude zobrazen pro produkty ve vybraných taxonech. Pouze "Hlavní taxon" je brán v úvahu. + display_for_taxons: + label: Zobrazit pro taxony + help: Vyberte taxony, ve kterých se bude tento blok zobrazovat + manage_block_display: Správa zobrazení bloku cms: content_management: Obsahový management cms: Obsahový management diff --git a/src/Resources/translations/messages.cs_CZ.yml b/src/Resources/translations/messages.cs_CZ.yml index 6ad54fb2f..1648a6c49 100755 --- a/src/Resources/translations/messages.cs_CZ.yml +++ b/src/Resources/translations/messages.cs_CZ.yml @@ -20,6 +20,16 @@ bitbag_sylius_cms_plugin: products_grid_by_taxon: Produkty v mřížce podle taxonu heading_type: Typ nadpisu taxon: Taxon + display_for_products: + label: Zobrazit pro produkty + help: Vyberte produkty, ve kterých se bude tento blok zobrazovat + display_for_products_in_taxons: + label: Zobrazit pro produkty v taxonech + help: Tento blok bude zobrazen pro produkty ve vybraných taxonech. Pouze "Hlavní taxon" je brán v úvahu. + display_for_taxons: + label: Zobrazit pro taxony + help: Vyberte taxony, ve kterých se bude tento blok zobrazovat + manage_block_display: Správa zobrazení bloku cms: content_management: Obsahový management cms: Obsahový management diff --git a/src/Resources/translations/messages.de.yml b/src/Resources/translations/messages.de.yml index 18cb3c28f..ff3180d51 100755 --- a/src/Resources/translations/messages.de.yml +++ b/src/Resources/translations/messages.de.yml @@ -70,3 +70,13 @@ bitbag_sylius_cms_plugin: products_grid_by_taxon: Produkte im Raster nach Taxon heading_type: Überschrift-Typ taxon: Taxon + display_for_products: + label: Display für Produkte + help: Wählen Sie Produkte aus, in denen dieser Block angezeigt wird + display_for_products_in_taxons: + label: Display für Produkte in Taxons + help: Dieser Block wird für Produkte in ausgewählten Taxonen angezeigt. Nur „Haupttaxon“ ist belegt. + display_for_taxons: + label: Display für Taxons + help: Wählen Sie Taxonen aus, in denen dieser Block angezeigt wird + manage_block_display: Blockanzeige verwalten diff --git a/src/Resources/translations/messages.en.yml b/src/Resources/translations/messages.en.yml index d8daf5cfa..2a6b073a3 100755 --- a/src/Resources/translations/messages.en.yml +++ b/src/Resources/translations/messages.en.yml @@ -75,3 +75,13 @@ bitbag_sylius_cms_plugin: heading_type: Heading type taxon: Taxon seo: SEO + display_for_products: + label: Display for products + help: Select products in which this block will be displayed + display_for_products_in_taxons: + label: Display for products in taxons + help: This block will be displayed for products in selected taxons. Only "Main Taxon" is taken. + display_for_taxons: + label: Display for taxons + help: Select taxons in which this block will be displayed + manage_block_display: Manage block display diff --git a/src/Resources/translations/messages.es.yml b/src/Resources/translations/messages.es.yml index b93bfcac0..6de50ed77 100755 --- a/src/Resources/translations/messages.es.yml +++ b/src/Resources/translations/messages.es.yml @@ -49,3 +49,13 @@ bitbag_sylius_cms_plugin: products_grid_by_taxon: Productos en cuadrícula por taxón heading_type: Tipo de encabezado taxon: Taxón + display_for_products: + label: Mostrar para productos + help: Seleccione productos en los que se mostrará este bloque + display_for_products_in_taxons: + label: Mostrar para productos en taxones + help: Este bloque se mostrará para productos en los taxones seleccionados. Solo se considera el "Taxón principal". + display_for_taxons: + label: Mostrar para taxones + help: Seleccione taxones en los que se mostrará este bloque + manage_block_display: Administrar visualización de bloques diff --git a/src/Resources/translations/messages.fr.yml b/src/Resources/translations/messages.fr.yml index 04ece97e9..1ec73eaa1 100755 --- a/src/Resources/translations/messages.fr.yml +++ b/src/Resources/translations/messages.fr.yml @@ -67,3 +67,13 @@ bitbag_sylius_cms_plugin: products_grid_by_taxon: Produits en grille par taxon heading_type: Type d'en-tête taxon: Taxon + display_for_products: + label: Afficher pour les produits + help: Ce bloc sera affiché pour les produits sélectionnés + display_for_products_in_taxons: + label: Afficher pour les produits dans les taxons + help: Ce bloc sera affiché pour les produits des taxons sélectionnés. Seul le « taxon principal » est pris en compte. + display_for_taxons: + label: Afficher pour les taxons + help: Ce bloc sera affiché pour les taxons sélectionnés + manage_block_display: Gérer l'affichage du bloc diff --git a/src/Resources/translations/messages.hr.yml b/src/Resources/translations/messages.hr.yml index 9296a3222..6f7c423fd 100755 --- a/src/Resources/translations/messages.hr.yml +++ b/src/Resources/translations/messages.hr.yml @@ -49,3 +49,13 @@ bitbag_sylius_cms_plugin: products_grid_by_taxon: Proizvodi u mreži po taksonu heading_type: Tip naslova taxon: Takson + display_for_products: + label: Prikaz za proizvode + help: Ovaj blok će biti prikazan za odabrane proizvode + display_for_products_in_taxons: + label: Prikaz za proizvode u taksonima + help: Ovaj će blok biti prikazan za proizvode u odabranim taksonima. Uzima se samo "Glavni takson". + display_for_taxons: + label: Prikaz za takson + help: Odaberite taksone u kojima će se ovaj blok prikazati + manage_block_display: Upravljanje prikazom bloka diff --git a/src/Resources/translations/messages.lt.yml b/src/Resources/translations/messages.lt.yml index 6799bf34f..6972d8d70 100644 --- a/src/Resources/translations/messages.lt.yml +++ b/src/Resources/translations/messages.lt.yml @@ -66,3 +66,13 @@ bitbag_sylius_cms_plugin: products_grid_by_taxon: Produktų tinklelis pagal taksoną heading_type: Antraštės tipas taxon: Taksonas + display_for_products: + label: Rodyti produktams + help: Pasirinkite produktus, kuriuose šis blokas bus rodomas + display_for_products_in_taxons: + label: Rodyti produktams + help: Šis blokas bus rodomas produktams pasirinktuose taksonuose. Paimamas tik „Pagrindinis taksonas“. + display_for_taxons: + label: Rodyti taksonams + help: Pasirinkite taksonus, kuriuose šis blokas bus rodomas + manage_block_display: Bloko rodymo valdymas diff --git a/src/Resources/translations/messages.nl.yml b/src/Resources/translations/messages.nl.yml index 4b23f947a..15e996263 100755 --- a/src/Resources/translations/messages.nl.yml +++ b/src/Resources/translations/messages.nl.yml @@ -48,3 +48,13 @@ bitbag_sylius_cms_plugin: products_grid_by_taxon: Producten grid per taxon heading_type: Kop type taxon: Taxon + display_for_products: + label: Display voor producten + help: Selecteer producten waarin dit blok wordt weergegeven + display_for_products_in_taxons: + label: Display voor producten in taxons + help: Dit blok wordt weergegeven voor producten in geselecteerde taxonen. Alleen "Hoofdtaxon" wordt gebruikt. + display_for_taxons: + label: Display voor taxons + help: Selecteer taxonen waarin dit blok wordt weergegeven + manage_block_display: Beheer blok weergave diff --git a/src/Resources/translations/messages.pl.yml b/src/Resources/translations/messages.pl.yml index 67a9d2ef3..641ad43cf 100755 --- a/src/Resources/translations/messages.pl.yml +++ b/src/Resources/translations/messages.pl.yml @@ -53,3 +53,13 @@ bitbag_sylius_cms_plugin: products_grid_by_taxon: Siatka produktów według taksonomii heading_type: Typ nagłówka taxon: Taksonomia + display_for_products: + label: Wyświetlaj dla produktów + help: Wybierz produkty, dla których ten blok będzie wyświetlany + display_for_products_in_taxons: + label: Wyświetlaj dla produktów w taksonomiach + help: Ten blok będzie wyświetlany dla produktów w wybranych taksonomiach. Tylko "Główna taksonomia" jest brana pod uwagę. + display_for_taxons: + label: Wyświetlaj dla taksonomii + help: Wybież taksonomie, dla których ten blok będzie wyświetlany + manage_block_display: Zarządzaj wyświetlaniem bloku diff --git a/src/Resources/translations/messages.ru.yml b/src/Resources/translations/messages.ru.yml index 6de939b42..321edc71c 100755 --- a/src/Resources/translations/messages.ru.yml +++ b/src/Resources/translations/messages.ru.yml @@ -66,3 +66,13 @@ bitbag_sylius_cms_plugin: products_grid_by_taxon: Продукты в сетке по таксону heading_type: Тип заголовка taxon: Таксон + display_for_products: + label: Отображать для товаров + help: Выберите товары, для которых этот блок будет отображаться + display_for_products_in_taxons: + label: Отображать для товаров в таксономиях + help: Этот блок будет отображаться для товаров в выбранных таксонах. Берется только «Основной таксон». + display_for_taxons: + label: Отображать для таксонов + help: Выберите таксоны, в которых будет отображаться этот блок + manage_block_display: Управление отображением блоков diff --git a/src/Resources/translations/messages.sk.yml b/src/Resources/translations/messages.sk.yml index 3e8fd8221..7091345c7 100644 --- a/src/Resources/translations/messages.sk.yml +++ b/src/Resources/translations/messages.sk.yml @@ -67,3 +67,13 @@ bitbag_sylius_cms_plugin: products_grid_by_taxon: Produkty v mriežke podľa taxónu heading_type: Typ nadpisu taxon: Taxón + display_for_products: + label: Zobraziť pre produkty + help: Tento blok bude zobrazený pre vybrané produkty + display_for_products_in_taxons: + label: Zobraziť pre produkty v taxónoch + help: Tento blok sa zobrazí pri produktoch vo vybraných taxónoch. Zaberie sa iba „hlavný taxón“. + display_for_taxons: + label: Zobrazenie pre taxóny + help: Vyberte taxóny, v ktorých sa tento blok zobrazí + manage_block_display: Spravovať zobrazenie bloku diff --git a/src/Resources/translations/messages.uk.yml b/src/Resources/translations/messages.uk.yml index dba77b1ec..6786a053e 100755 --- a/src/Resources/translations/messages.uk.yml +++ b/src/Resources/translations/messages.uk.yml @@ -66,3 +66,13 @@ bitbag_sylius_cms_plugin: products_grid_by_taxon: Продукти в сітці за таксоном heading_type: Тип заголовка taxon: Таксон + display_for_products: + label: Дисплей для продуктів + help: Цей блок буде відображатися для вибраних продуктів + display_for_products_in_taxons: + label: Дисплей для таксонів + help: Цей блок відображатиметься для продуктів у вибраних таксонах. Береться лише «Основний таксон». + display_for_taxons: + label: Дисплей для таксонів + help: Виберіть таксони, в яких буде відображатися цей блок + manage_block_display: Керування відображенням блоку From 46838715175b211c378bfdadd5a8bdd07e0e8e6f Mon Sep 17 00:00:00 2001 From: jkindly <kozupa.jakub@gmail.com> Date: Fri, 19 Jul 2024 12:35:03 +0200 Subject: [PATCH 06/15] OP-440: Migration --- src/Migrations/Version20240719070318.php | 47 ++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 src/Migrations/Version20240719070318.php diff --git a/src/Migrations/Version20240719070318.php b/src/Migrations/Version20240719070318.php new file mode 100644 index 000000000..09bd3a4e2 --- /dev/null +++ b/src/Migrations/Version20240719070318.php @@ -0,0 +1,47 @@ +<?php + +declare(strict_types=1); + +namespace BitBag\SyliusCmsPlugin\Migrations; + +use Doctrine\DBAL\Schema\Schema; +use Doctrine\Migrations\AbstractMigration; + +/** + * Auto-generated Migration: Please modify to your needs! + */ +final class Version20240719070318 extends AbstractMigration +{ + public function getDescription(): string + { + return ''; + } + + public function up(Schema $schema): void + { + // this up() migration is auto-generated, please modify it to your needs + $this->addSql('CREATE TABLE bitbag_cms_block_products (block_id INT NOT NULL, product_id INT NOT NULL, INDEX IDX_C4B9089FE9ED820C (block_id), INDEX IDX_C4B9089F4584665A (product_id), PRIMARY KEY(block_id, product_id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); + $this->addSql('CREATE TABLE bitbag_cms_block_taxons (block_id INT NOT NULL, taxon_id INT NOT NULL, INDEX IDX_E324C6CEE9ED820C (block_id), INDEX IDX_E324C6CEDE13F470 (taxon_id), PRIMARY KEY(block_id, taxon_id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); + $this->addSql('CREATE TABLE bitbag_cms_block_products_in_taxons (block_id INT NOT NULL, taxon_id INT NOT NULL, INDEX IDX_DAA9DD18E9ED820C (block_id), INDEX IDX_DAA9DD18DE13F470 (taxon_id), PRIMARY KEY(block_id, taxon_id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); + $this->addSql('ALTER TABLE bitbag_cms_block_products ADD CONSTRAINT FK_C4B9089FE9ED820C FOREIGN KEY (block_id) REFERENCES bitbag_cms_block (id) ON DELETE CASCADE'); + $this->addSql('ALTER TABLE bitbag_cms_block_products ADD CONSTRAINT FK_C4B9089F4584665A FOREIGN KEY (product_id) REFERENCES sylius_product (id) ON DELETE CASCADE'); + $this->addSql('ALTER TABLE bitbag_cms_block_taxons ADD CONSTRAINT FK_E324C6CEE9ED820C FOREIGN KEY (block_id) REFERENCES bitbag_cms_block (id) ON DELETE CASCADE'); + $this->addSql('ALTER TABLE bitbag_cms_block_taxons ADD CONSTRAINT FK_E324C6CEDE13F470 FOREIGN KEY (taxon_id) REFERENCES sylius_taxon (id) ON DELETE CASCADE'); + $this->addSql('ALTER TABLE bitbag_cms_block_products_in_taxons ADD CONSTRAINT FK_DAA9DD18E9ED820C FOREIGN KEY (block_id) REFERENCES bitbag_cms_block (id) ON DELETE CASCADE'); + $this->addSql('ALTER TABLE bitbag_cms_block_products_in_taxons ADD CONSTRAINT FK_DAA9DD18DE13F470 FOREIGN KEY (taxon_id) REFERENCES sylius_taxon (id) ON DELETE CASCADE'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE bitbag_cms_block_products DROP FOREIGN KEY FK_C4B9089FE9ED820C'); + $this->addSql('ALTER TABLE bitbag_cms_block_products DROP FOREIGN KEY FK_C4B9089F4584665A'); + $this->addSql('ALTER TABLE bitbag_cms_block_taxons DROP FOREIGN KEY FK_E324C6CEE9ED820C'); + $this->addSql('ALTER TABLE bitbag_cms_block_taxons DROP FOREIGN KEY FK_E324C6CEDE13F470'); + $this->addSql('ALTER TABLE bitbag_cms_block_products_in_taxons DROP FOREIGN KEY FK_DAA9DD18E9ED820C'); + $this->addSql('ALTER TABLE bitbag_cms_block_products_in_taxons DROP FOREIGN KEY FK_DAA9DD18DE13F470'); + $this->addSql('DROP TABLE bitbag_cms_block_products'); + $this->addSql('DROP TABLE bitbag_cms_block_taxons'); + $this->addSql('DROP TABLE bitbag_cms_block_products_in_taxons'); + } +} From e9f9c62759bbaadca18d95cfd7d7bf62ca1cb019 Mon Sep 17 00:00:00 2001 From: jkindly <kozupa.jakub@gmail.com> Date: Fri, 19 Jul 2024 12:47:43 +0200 Subject: [PATCH 07/15] OP-440: PHPStan & ECS fixes --- src/Entity/Trait/ProductsAwareTrait.php | 2 +- src/Entity/Trait/ProductsInTaxonsAwareTrait.php | 2 +- src/Entity/Trait/TaxonAwareTrait.php | 2 +- src/Form/Type/BlockType.php | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Entity/Trait/ProductsAwareTrait.php b/src/Entity/Trait/ProductsAwareTrait.php index 3710dea32..57c35f557 100755 --- a/src/Entity/Trait/ProductsAwareTrait.php +++ b/src/Entity/Trait/ProductsAwareTrait.php @@ -17,7 +17,7 @@ trait ProductsAwareTrait { /** @var Collection|ProductInterface[] */ - protected array|Collection $products; + protected Collection $products; public function initializeProductsCollection(): void { diff --git a/src/Entity/Trait/ProductsInTaxonsAwareTrait.php b/src/Entity/Trait/ProductsInTaxonsAwareTrait.php index 6e331bdf8..f95dea5a7 100644 --- a/src/Entity/Trait/ProductsInTaxonsAwareTrait.php +++ b/src/Entity/Trait/ProductsInTaxonsAwareTrait.php @@ -17,7 +17,7 @@ trait ProductsInTaxonsAwareTrait { /** @var Collection|TaxonInterface[] */ - protected array|Collection $productsInTaxons; + protected Collection $productsInTaxons; public function initializeProductsInTaxonsCollection(): void { diff --git a/src/Entity/Trait/TaxonAwareTrait.php b/src/Entity/Trait/TaxonAwareTrait.php index 8edc13cc7..6679e4931 100644 --- a/src/Entity/Trait/TaxonAwareTrait.php +++ b/src/Entity/Trait/TaxonAwareTrait.php @@ -17,7 +17,7 @@ trait TaxonAwareTrait { /** @var Collection|TaxonInterface[] */ - protected array|Collection $taxons; + protected Collection $taxons; public function initializeTaxonCollection(): void { diff --git a/src/Form/Type/BlockType.php b/src/Form/Type/BlockType.php index 73fb6c3de..d2472dc34 100755 --- a/src/Form/Type/BlockType.php +++ b/src/Form/Type/BlockType.php @@ -65,7 +65,7 @@ public function buildForm(FormBuilderInterface $builder, array $options): void ->add('productsInTaxons', TaxonAutocompleteChoiceType::class, [ 'label' => 'bitbag_sylius_cms_plugin.ui.display_for_products_in_taxons.label', 'multiple' => true, - 'help' => 'bitbag_sylius_cms_plugin.ui.display_for_products_in_taxons.help' + 'help' => 'bitbag_sylius_cms_plugin.ui.display_for_products_in_taxons.help', ]) ->add('taxons', TaxonAutocompleteChoiceType::class, [ 'label' => 'bitbag_sylius_cms_plugin.ui.display_for_taxons.label', From 156989a56e9c35f4d4f560af2d04d06806f31cd6 Mon Sep 17 00:00:00 2001 From: jkindly <kozupa.jakub@gmail.com> Date: Mon, 22 Jul 2024 08:37:41 +0200 Subject: [PATCH 08/15] OP-440: Spec --- spec/Twig/Runtime/RenderBlockRuntimeSpec.php | 66 ++++++++++++++----- .../SyliusShopBundle/Product/show.html.twig | 2 - 2 files changed, 49 insertions(+), 19 deletions(-) diff --git a/spec/Twig/Runtime/RenderBlockRuntimeSpec.php b/spec/Twig/Runtime/RenderBlockRuntimeSpec.php index 85c9a3df1..72fab0841 100644 --- a/spec/Twig/Runtime/RenderBlockRuntimeSpec.php +++ b/spec/Twig/Runtime/RenderBlockRuntimeSpec.php @@ -18,6 +18,8 @@ use BitBag\SyliusCmsPlugin\Twig\Runtime\RenderBlockRuntime; use BitBag\SyliusCmsPlugin\Twig\Runtime\RenderBlockRuntimeInterface; use PhpSpec\ObjectBehavior; +use Sylius\Component\Core\Model\ProductInterface; +use Sylius\Component\Core\Model\TaxonInterface; use Twig\Environment; final class RenderBlockRuntimeSpec extends ObjectBehavior @@ -25,7 +27,7 @@ final class RenderBlockRuntimeSpec extends ObjectBehavior public function let( BlockResourceResolverInterface $blockResourceResolver, Environment $templatingEngine, - ContentElementRendererStrategyInterface $contentElementRendererStrategy, + ContentElementRendererStrategyInterface $contentElementRendererStrategy ): void { $this->beConstructedWith($blockResourceResolver, $templatingEngine, $contentElementRendererStrategy); } @@ -37,38 +39,68 @@ public function it_is_initializable(): void public function it_implements_render_block_runtime_interface(): void { - $this->shouldHaveType(RenderBlockRuntimeInterface::class); + $this->shouldImplement(RenderBlockRuntimeInterface::class); + } + + public function it_returns_empty_string_when_block_not_found(BlockResourceResolverInterface $blockResourceResolver): void + { + $blockResourceResolver->findOrLog('code')->willReturn(null); + + $this->renderBlock('code')->shouldReturn(''); } - public function it_renders_block( + public function it_returns_empty_string_when_block_not_displayable_for_taxon( BlockResourceResolverInterface $blockResourceResolver, BlockInterface $block, + TaxonInterface $taxon + ): void { + $blockResourceResolver->findOrLog('code')->willReturn($block); + $block->canBeDisplayedForTaxon($taxon)->willReturn(false); + + $this->renderBlock('code', null, $taxon)->shouldReturn(''); + } + + public function it_returns_empty_string_when_block_not_displayable_for_product( + BlockResourceResolverInterface $blockResourceResolver, + BlockInterface $block, + ProductInterface $product + ): void { + $blockResourceResolver->findOrLog('code')->willReturn($block); + $block->canBeDisplayedForProduct($product)->willReturn(false); + $block->canBeDisplayedForProductInTaxon($product)->willReturn(false); + + $this->renderBlock('code', null, $product)->shouldReturn(''); + } + + public function it_renders_block_with_default_template( + BlockResourceResolverInterface $blockResourceResolver, Environment $templatingEngine, ContentElementRendererStrategyInterface $contentElementRendererStrategy, + BlockInterface $block ): void { - $blockResourceResolver->findOrLog('bitbag')->willReturn($block); + $blockResourceResolver->findOrLog('code')->willReturn($block); $contentElementRendererStrategy->render($block)->willReturn('rendered content'); - $templatingEngine->render( - '@BitBagSyliusCmsPlugin/Shop/Block/show.html.twig', - ['content' => 'rendered content'], - )->willReturn('<div>BitBag</div>'); - $this->renderBlock('bitbag'); + $templatingEngine->render('@BitBagSyliusCmsPlugin/Shop/Block/show.html.twig', [ + 'content' => 'rendered content', + ])->willReturn('rendered block'); + + $this->renderBlock('code')->shouldReturn('rendered block'); } - public function it_renders_block_with_template( + public function it_renders_block_with_custom_template( BlockResourceResolverInterface $blockResourceResolver, - BlockInterface $block, Environment $templatingEngine, ContentElementRendererStrategyInterface $contentElementRendererStrategy, + BlockInterface $block ): void { - $blockResourceResolver->findOrLog('bitbag')->willReturn($block); + $blockResourceResolver->findOrLog('code')->willReturn($block); $contentElementRendererStrategy->render($block)->willReturn('rendered content'); - $templatingEngine->render( - '@BitBagSyliusCmsPlugin/Shop/Block/otherTemplate.html.twig', - ['content' => 'rendered content'], - )->willReturn('<div>BitBag Other Template</div>'); - $this->renderBlock('bitbag', '@BitBagSyliusCmsPlugin/Shop/Block/otherTemplate.html.twig'); + $templatingEngine->render('custom_template.html.twig', [ + 'content' => 'rendered content', + ])->willReturn('rendered block'); + + $this->renderBlock('code', 'custom_template.html.twig')->shouldReturn('rendered block'); } } diff --git a/tests/Application/templates/bundles/SyliusShopBundle/Product/show.html.twig b/tests/Application/templates/bundles/SyliusShopBundle/Product/show.html.twig index 37da1040b..8955ade69 100755 --- a/tests/Application/templates/bundles/SyliusShopBundle/Product/show.html.twig +++ b/tests/Application/templates/bundles/SyliusShopBundle/Product/show.html.twig @@ -50,8 +50,6 @@ </div> </div> - {{ render(path('bitbag_sylius_cms_plugin_shop_block_index_by_collection_code', {'collectionCode' : 'products', 'template' : '@BitBagSyliusCmsPlugin/Shop/Block/index.html.twig'})) }} - {{ bitbag_cms_render_block('lorem_ipsum', null, product) }} {{ sonata_block_render_event('sylius.shop.product.show.before_tabs', {'product': product}) }} From f573e448b21275479da55645c4e02f11aa02ca53 Mon Sep 17 00:00:00 2001 From: jkindly <kozupa.jakub@gmail.com> Date: Mon, 22 Jul 2024 08:40:33 +0200 Subject: [PATCH 09/15] OP-440: Migration comments --- src/Migrations/Version20240719070318.php | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/Migrations/Version20240719070318.php b/src/Migrations/Version20240719070318.php index 09bd3a4e2..dbbccf8df 100644 --- a/src/Migrations/Version20240719070318.php +++ b/src/Migrations/Version20240719070318.php @@ -1,5 +1,11 @@ <?php +/* + * This file was created by developers working at BitBag + * Do you need more information about us and what we do? Visit our https://bitbag.io website! + * We are hiring developers from all over the world. Join us and start your new, exciting adventure and become part of us: https://bitbag.io/career +*/ + declare(strict_types=1); namespace BitBag\SyliusCmsPlugin\Migrations; @@ -7,19 +13,15 @@ use Doctrine\DBAL\Schema\Schema; use Doctrine\Migrations\AbstractMigration; -/** - * Auto-generated Migration: Please modify to your needs! - */ final class Version20240719070318 extends AbstractMigration { public function getDescription(): string { - return ''; + return 'This migration adds products, taxons, products in taxons to the block entity.'; } public function up(Schema $schema): void { - // this up() migration is auto-generated, please modify it to your needs $this->addSql('CREATE TABLE bitbag_cms_block_products (block_id INT NOT NULL, product_id INT NOT NULL, INDEX IDX_C4B9089FE9ED820C (block_id), INDEX IDX_C4B9089F4584665A (product_id), PRIMARY KEY(block_id, product_id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); $this->addSql('CREATE TABLE bitbag_cms_block_taxons (block_id INT NOT NULL, taxon_id INT NOT NULL, INDEX IDX_E324C6CEE9ED820C (block_id), INDEX IDX_E324C6CEDE13F470 (taxon_id), PRIMARY KEY(block_id, taxon_id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); $this->addSql('CREATE TABLE bitbag_cms_block_products_in_taxons (block_id INT NOT NULL, taxon_id INT NOT NULL, INDEX IDX_DAA9DD18E9ED820C (block_id), INDEX IDX_DAA9DD18DE13F470 (taxon_id), PRIMARY KEY(block_id, taxon_id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); @@ -33,7 +35,6 @@ public function up(Schema $schema): void public function down(Schema $schema): void { - // this down() migration is auto-generated, please modify it to your needs $this->addSql('ALTER TABLE bitbag_cms_block_products DROP FOREIGN KEY FK_C4B9089FE9ED820C'); $this->addSql('ALTER TABLE bitbag_cms_block_products DROP FOREIGN KEY FK_C4B9089F4584665A'); $this->addSql('ALTER TABLE bitbag_cms_block_taxons DROP FOREIGN KEY FK_E324C6CEE9ED820C'); From 8590a3aabe667af9b68e9bf75d62710d489eb2af Mon Sep 17 00:00:00 2001 From: jkindly <kozupa.jakub@gmail.com> Date: Mon, 22 Jul 2024 09:01:50 +0200 Subject: [PATCH 10/15] OP-440: PHPUnit fix --- src/Resources/config/serialization/Block.xml | 7 +++++-- .../Api/BlockTest/test_it_get_block_by_id.json | 5 ++++- .../Api/BlockTest/test_it_get_blocks.json | 15 ++++++++++++--- 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/src/Resources/config/serialization/Block.xml b/src/Resources/config/serialization/Block.xml index 7549db77b..6bcab96ea 100644 --- a/src/Resources/config/serialization/Block.xml +++ b/src/Resources/config/serialization/Block.xml @@ -16,15 +16,18 @@ <attribute name="collections"> <group>shop:cms:read</group> </attribute> - <attribute name="products"> + <attribute name="channels"> <group>shop:cms:read</group> </attribute> - <attribute name="channels"> + <attribute name="products"> <group>shop:cms:read</group> </attribute> <attribute name="taxons"> <group>shop:cms:read</group> </attribute> + <attribute name="productsInTaxons"> + <group>shop:cms:read</group> + </attribute> <attribute name="contentElements"> <group>shop:cms:read</group> </attribute> diff --git a/tests/Functional/Responses/Expected/Api/BlockTest/test_it_get_block_by_id.json b/tests/Functional/Responses/Expected/Api/BlockTest/test_it_get_block_by_id.json index 857e57f70..dbc9c1802 100644 --- a/tests/Functional/Responses/Expected/Api/BlockTest/test_it_get_block_by_id.json +++ b/tests/Functional/Responses/Expected/Api/BlockTest/test_it_get_block_by_id.json @@ -16,5 +16,8 @@ "channels": [ "/api/v2/shop/channels/code" ], - "contentElements": [] + "contentElements": [], + "products": [], + "taxons": [], + "productsInTaxons": [] } diff --git a/tests/Functional/Responses/Expected/Api/BlockTest/test_it_get_blocks.json b/tests/Functional/Responses/Expected/Api/BlockTest/test_it_get_blocks.json index 7a770ed6f..c163c76eb 100644 --- a/tests/Functional/Responses/Expected/Api/BlockTest/test_it_get_blocks.json +++ b/tests/Functional/Responses/Expected/Api/BlockTest/test_it_get_blocks.json @@ -20,7 +20,10 @@ "channels": [ "/api/v2/shop/channels/code" ], - "contentElements": [] + "contentElements": [], + "products": [], + "taxons": [], + "productsInTaxons": [] }, { "@id": "/api/v2/shop/cms-plugin/blocks/@integer@", @@ -39,7 +42,10 @@ "channels": [ "/api/v2/shop/channels/code" ], - "contentElements": [] + "contentElements": [], + "products": [], + "taxons": [], + "productsInTaxons": [] }, { "@id": "/api/v2/shop/cms-plugin/blocks/@integer@", @@ -58,7 +64,10 @@ "channels": [ "/api/v2/shop/channels/code" ], - "contentElements": [] + "contentElements": [], + "products": [], + "taxons": [], + "productsInTaxons": [] } ], "hydra:totalItems": 3 From cf8fb16b3ea834081b7b404efb8bd85ed57cc567 Mon Sep 17 00:00:00 2001 From: jkindly <kozupa.jakub@gmail.com> Date: Tue, 23 Jul 2024 11:56:19 +0200 Subject: [PATCH 11/15] OP-441: Twig function to render Collection --- src/Form/Type/CollectionType.php | 2 - .../Collection/CollectionBlocksRenderer.php | 45 ++++++++++++++++++ .../Collection/CollectionMediaRenderer.php | 46 +++++++++++++++++++ .../Collection/CollectionPagesRenderer.php | 45 ++++++++++++++++++ .../CollectionRendererInterface.php | 20 ++++++++ src/Renderer/CollectionRendererStrategy.php | 35 ++++++++++++++ .../CollectionRendererStrategyInterface.php | 18 ++++++++ src/Renderer/PageLinkRenderer.php | 41 +++++++++++++++++ src/Renderer/PageLinkRendererInterface.php | 18 ++++++++ src/Resolver/CollectionResourceResolver.php | 40 ++++++++++++++++ .../CollectionResourceResolverInterface.php | 18 ++++++++ .../js/bitbag/bitbag-content-configuration.js | 8 ++-- src/Resources/config/services/renderer.xml | 24 ++++++++++ src/Resources/config/services/resolver.xml | 5 ++ src/Resources/config/services/twig.xml | 12 +++++ .../views/Shop/Collection/show.html.twig | 3 ++ .../views/Shop/Media/Show/file.html.twig | 18 ++++---- .../views/Shop/Media/Show/image.html.twig | 14 +++--- src/Resources/views/Shop/Page/link.html.twig | 3 ++ src/Sorter/SorterById.php | 27 +++++++++++ .../Extension/RenderCollectionExtension.php | 33 +++++++++++++ src/Twig/Runtime/RenderCollectionRuntime.php | 42 +++++++++++++++++ .../RenderCollectionRuntimeInterface.php | 16 +++++++ .../SyliusShopBundle/Homepage/index.html.twig | 1 + 24 files changed, 514 insertions(+), 20 deletions(-) create mode 100644 src/Renderer/Collection/CollectionBlocksRenderer.php create mode 100644 src/Renderer/Collection/CollectionMediaRenderer.php create mode 100644 src/Renderer/Collection/CollectionPagesRenderer.php create mode 100644 src/Renderer/Collection/CollectionRendererInterface.php create mode 100644 src/Renderer/CollectionRendererStrategy.php create mode 100644 src/Renderer/CollectionRendererStrategyInterface.php create mode 100644 src/Renderer/PageLinkRenderer.php create mode 100644 src/Renderer/PageLinkRendererInterface.php create mode 100755 src/Resolver/CollectionResourceResolver.php create mode 100755 src/Resolver/CollectionResourceResolverInterface.php create mode 100644 src/Resources/views/Shop/Collection/show.html.twig create mode 100644 src/Resources/views/Shop/Page/link.html.twig create mode 100644 src/Sorter/SorterById.php create mode 100644 src/Twig/Extension/RenderCollectionExtension.php create mode 100644 src/Twig/Runtime/RenderCollectionRuntime.php create mode 100644 src/Twig/Runtime/RenderCollectionRuntimeInterface.php diff --git a/src/Form/Type/CollectionType.php b/src/Form/Type/CollectionType.php index 73f802d9e..6478f89da 100755 --- a/src/Form/Type/CollectionType.php +++ b/src/Form/Type/CollectionType.php @@ -10,7 +10,6 @@ namespace BitBag\SyliusCmsPlugin\Form\Type; -use BitBag\SyliusCmsPlugin\Entity\MediaInterface; use Sylius\Bundle\ResourceBundle\Form\Type\AbstractResourceType; use Symfony\Component\Form\Event\PreSubmitEvent; use Symfony\Component\Form\Extension\Core\Type\ChoiceType; @@ -55,7 +54,6 @@ public function buildForm(FormBuilderInterface $builder, array $options): void ->add('media', MediaAutocompleteChoiceType::class, [ 'label' => 'bitbag_sylius_cms_plugin.ui.media', 'multiple' => true, - 'media_type' => MediaInterface::IMAGE_TYPE, ]) ->addEventListener(FormEvents::PRE_SUBMIT, function (PreSubmitEvent $event): void { $formData = $event->getData(); diff --git a/src/Renderer/Collection/CollectionBlocksRenderer.php b/src/Renderer/Collection/CollectionBlocksRenderer.php new file mode 100644 index 000000000..584da2568 --- /dev/null +++ b/src/Renderer/Collection/CollectionBlocksRenderer.php @@ -0,0 +1,45 @@ +<?php + +/* + * This file was created by developers working at BitBag + * Do you need more information about us and what we do? Visit our https://bitbag.io website! + * We are hiring developers from all over the world. Join us and start your new, exciting adventure and become part of us: https://bitbag.io/career +*/ + +declare(strict_types=1); + +namespace BitBag\SyliusCmsPlugin\Renderer\Collection; + +use BitBag\SyliusCmsPlugin\Entity\BlockInterface; +use BitBag\SyliusCmsPlugin\Entity\CollectionInterface; +use BitBag\SyliusCmsPlugin\Renderer\ContentElementRendererStrategyInterface; +use BitBag\SyliusCmsPlugin\Sorter\SorterById; +use Webmozart\Assert\Assert; + +final class CollectionBlocksRenderer implements CollectionRendererInterface +{ + public function __construct(private ContentElementRendererStrategyInterface $contentElementRendererStrategy) + { + } + + public function render(CollectionInterface $collection, ?int $countToRender = null): string + { + $content = ''; + $iterator = 0; + Assert::notNull($collection->getBlocks()); + /** @var BlockInterface $block */ + foreach (SorterById::sort($collection->getBlocks()->toArray()) as $block) { + $content .= $this->contentElementRendererStrategy->render($block); + if (++$iterator === $countToRender) { + break; + } + } + + return $content; + } + + public function supports(CollectionInterface $collection): bool + { + return $collection->getBlocks()?->count() > 0; + } +} diff --git a/src/Renderer/Collection/CollectionMediaRenderer.php b/src/Renderer/Collection/CollectionMediaRenderer.php new file mode 100644 index 000000000..b5c7ee8a3 --- /dev/null +++ b/src/Renderer/Collection/CollectionMediaRenderer.php @@ -0,0 +1,46 @@ +<?php + +/* + * This file was created by developers working at BitBag + * Do you need more information about us and what we do? Visit our https://bitbag.io website! + * We are hiring developers from all over the world. Join us and start your new, exciting adventure and become part of us: https://bitbag.io/career +*/ + +declare(strict_types=1); + +namespace BitBag\SyliusCmsPlugin\Renderer\Collection; + +use BitBag\SyliusCmsPlugin\Entity\CollectionInterface; +use BitBag\SyliusCmsPlugin\Entity\MediaInterface; +use BitBag\SyliusCmsPlugin\Sorter\SorterById; +use BitBag\SyliusCmsPlugin\Twig\Runtime\RenderMediaRuntimeInterface; +use Webmozart\Assert\Assert; + +final class CollectionMediaRenderer implements CollectionRendererInterface +{ + public function __construct(private RenderMediaRuntimeInterface $renderMediaRuntime) + { + } + + public function render(CollectionInterface $collection, ?int $countToRender = null): string + { + $content = ''; + $iterator = 0; + Assert::notNull($collection->getMedia()); + /** @var MediaInterface $media */ + foreach (SorterById::sort($collection->getMedia()->toArray()) as $media) { + Assert::notNull($media->getCode()); + $content .= $this->renderMediaRuntime->renderMedia($media->getCode()); + if (++$iterator === $countToRender) { + break; + } + } + + return $content; + } + + public function supports(CollectionInterface $collection): bool + { + return $collection->getMedia()?->count() > 0; + } +} diff --git a/src/Renderer/Collection/CollectionPagesRenderer.php b/src/Renderer/Collection/CollectionPagesRenderer.php new file mode 100644 index 000000000..587434e17 --- /dev/null +++ b/src/Renderer/Collection/CollectionPagesRenderer.php @@ -0,0 +1,45 @@ +<?php + +/* + * This file was created by developers working at BitBag + * Do you need more information about us and what we do? Visit our https://bitbag.io website! + * We are hiring developers from all over the world. Join us and start your new, exciting adventure and become part of us: https://bitbag.io/career +*/ + +declare(strict_types=1); + +namespace BitBag\SyliusCmsPlugin\Renderer\Collection; + +use BitBag\SyliusCmsPlugin\Entity\CollectionInterface; +use BitBag\SyliusCmsPlugin\Entity\PageInterface; +use BitBag\SyliusCmsPlugin\Renderer\PageLinkRendererInterface; +use BitBag\SyliusCmsPlugin\Sorter\SorterById; +use Webmozart\Assert\Assert; + +final class CollectionPagesRenderer implements CollectionRendererInterface +{ + public function __construct(private PageLinkRendererInterface $pageLinkRenderer) + { + } + + public function render(CollectionInterface $collection, ?int $countToRender = null): string + { + $content = ''; + $iterator = 0; + Assert::notNull($collection->getPages()); + /** @var PageInterface $page */ + foreach (SorterById::sort($collection->getPages()->toArray(), 'desc') as $page) { + $content .= $this->pageLinkRenderer->render($page); + if (++$iterator === $countToRender) { + break; + } + } + + return $content; + } + + public function supports(CollectionInterface $collection): bool + { + return $collection->getPages()?->count() > 0; + } +} diff --git a/src/Renderer/Collection/CollectionRendererInterface.php b/src/Renderer/Collection/CollectionRendererInterface.php new file mode 100644 index 000000000..4de98d3dc --- /dev/null +++ b/src/Renderer/Collection/CollectionRendererInterface.php @@ -0,0 +1,20 @@ +<?php + +/* + * This file was created by developers working at BitBag + * Do you need more information about us and what we do? Visit our https://bitbag.io website! + * We are hiring developers from all over the world. Join us and start your new, exciting adventure and become part of us: https://bitbag.io/career +*/ + +declare(strict_types=1); + +namespace BitBag\SyliusCmsPlugin\Renderer\Collection; + +use BitBag\SyliusCmsPlugin\Entity\CollectionInterface; + +interface CollectionRendererInterface +{ + public function render(CollectionInterface $collection, ?int $countToRender = null): string; + + public function supports(CollectionInterface $collection): bool; +} diff --git a/src/Renderer/CollectionRendererStrategy.php b/src/Renderer/CollectionRendererStrategy.php new file mode 100644 index 000000000..5ec435386 --- /dev/null +++ b/src/Renderer/CollectionRendererStrategy.php @@ -0,0 +1,35 @@ +<?php + +/* + * This file was created by developers working at BitBag + * Do you need more information about us and what we do? Visit our https://bitbag.io website! + * We are hiring developers from all over the world. Join us and start your new, exciting adventure and become part of us: https://bitbag.io/career +*/ + +declare(strict_types=1); + +namespace BitBag\SyliusCmsPlugin\Renderer; + +use BitBag\SyliusCmsPlugin\Entity\CollectionInterface; +use BitBag\SyliusCmsPlugin\Renderer\Collection\CollectionRendererInterface; + +final class CollectionRendererStrategy implements CollectionRendererStrategyInterface +{ + /** + * @param CollectionRendererInterface[] $renderers + */ + public function __construct(private iterable $renderers) + { + } + + public function render(CollectionInterface $collection, ?int $countToRender = null): string + { + foreach ($this->renderers as $renderer) { + if ($renderer->supports($collection)) { + return $renderer->render($collection, $countToRender); + } + } + + return ''; + } +} diff --git a/src/Renderer/CollectionRendererStrategyInterface.php b/src/Renderer/CollectionRendererStrategyInterface.php new file mode 100644 index 000000000..d8c0c606f --- /dev/null +++ b/src/Renderer/CollectionRendererStrategyInterface.php @@ -0,0 +1,18 @@ +<?php + +/* + * This file was created by developers working at BitBag + * Do you need more information about us and what we do? Visit our https://bitbag.io website! + * We are hiring developers from all over the world. Join us and start your new, exciting adventure and become part of us: https://bitbag.io/career +*/ + +declare(strict_types=1); + +namespace BitBag\SyliusCmsPlugin\Renderer; + +use BitBag\SyliusCmsPlugin\Entity\CollectionInterface; + +interface CollectionRendererStrategyInterface +{ + public function render(CollectionInterface $collection, ?int $countToRender = null): string; +} diff --git a/src/Renderer/PageLinkRenderer.php b/src/Renderer/PageLinkRenderer.php new file mode 100644 index 000000000..c218462e6 --- /dev/null +++ b/src/Renderer/PageLinkRenderer.php @@ -0,0 +1,41 @@ +<?php + +/* + * This file was created by developers working at BitBag + * Do you need more information about us and what we do? Visit our https://bitbag.io website! + * We are hiring developers from all over the world. Join us and start your new, exciting adventure and become part of us: https://bitbag.io/career +*/ + +declare(strict_types=1); + +namespace BitBag\SyliusCmsPlugin\Renderer; + +use BitBag\SyliusCmsPlugin\Entity\PageInterface; +use Symfony\Component\Routing\Generator\UrlGeneratorInterface; +use Twig\Environment; + +final class PageLinkRenderer implements PageLinkRendererInterface +{ + private const DEFAULT_TEMPLATE = '@BitBagSyliusCmsPlugin/Shop/Page/link.html.twig'; + + public function __construct( + private UrlGeneratorInterface $urlGenerator, + private Environment $twig, + ) { + } + + public function render(PageInterface $page, ?string $template = null): string + { + return $this->twig->render( + $template ?? self::DEFAULT_TEMPLATE, + [ + 'link' => $this->urlGenerator->generate( + 'bitbag_sylius_cms_plugin_shop_page_show', + ['slug' => $page->getSlug()], + UrlGeneratorInterface::ABSOLUTE_URL, + ), + 'name' => $page->getName(), + ], + ); + } +} diff --git a/src/Renderer/PageLinkRendererInterface.php b/src/Renderer/PageLinkRendererInterface.php new file mode 100644 index 000000000..a7a80001b --- /dev/null +++ b/src/Renderer/PageLinkRendererInterface.php @@ -0,0 +1,18 @@ +<?php + +/* + * This file was created by developers working at BitBag + * Do you need more information about us and what we do? Visit our https://bitbag.io website! + * We are hiring developers from all over the world. Join us and start your new, exciting adventure and become part of us: https://bitbag.io/career +*/ + +declare(strict_types=1); + +namespace BitBag\SyliusCmsPlugin\Renderer; + +use BitBag\SyliusCmsPlugin\Entity\PageInterface; + +interface PageLinkRendererInterface +{ + public function render(PageInterface $page, ?string $template = null): string; +} diff --git a/src/Resolver/CollectionResourceResolver.php b/src/Resolver/CollectionResourceResolver.php new file mode 100755 index 000000000..dd2a59b24 --- /dev/null +++ b/src/Resolver/CollectionResourceResolver.php @@ -0,0 +1,40 @@ +<?php + +/* + * This file was created by developers working at BitBag + * Do you need more information about us and what we do? Visit our https://bitbag.io website! + * We are hiring developers from all over the world. Join us and start your new, exciting adventure and become part of us: https://bitbag.io/career +*/ + +declare(strict_types=1); + +namespace BitBag\SyliusCmsPlugin\Resolver; + +use BitBag\SyliusCmsPlugin\Entity\CollectionInterface; +use BitBag\SyliusCmsPlugin\Repository\CollectionRepositoryInterface; +use Psr\Log\LoggerInterface; + +final class CollectionResourceResolver implements CollectionResourceResolverInterface +{ + public function __construct( + private CollectionRepositoryInterface $collectionRepository, + private LoggerInterface $logger, + ) { + } + + public function findOrLog(string $code): ?CollectionInterface + { + $collection = $this->collectionRepository->findOneByCode($code); + + if (false === $collection instanceof CollectionInterface) { + $this->logger->warning(sprintf( + 'Collection with "%s" code was not found in the database.', + $code, + )); + + return null; + } + + return $collection; + } +} diff --git a/src/Resolver/CollectionResourceResolverInterface.php b/src/Resolver/CollectionResourceResolverInterface.php new file mode 100755 index 000000000..4ea8827e0 --- /dev/null +++ b/src/Resolver/CollectionResourceResolverInterface.php @@ -0,0 +1,18 @@ +<?php + +/* + * This file was created by developers working at BitBag + * Do you need more information about us and what we do? Visit our https://bitbag.io website! + * We are hiring developers from all over the world. Join us and start your new, exciting adventure and become part of us: https://bitbag.io/career +*/ + +declare(strict_types=1); + +namespace BitBag\SyliusCmsPlugin\Resolver; + +use BitBag\SyliusCmsPlugin\Entity\CollectionInterface; + +interface CollectionResourceResolverInterface +{ + public function findOrLog(string $code): ?CollectionInterface; +} diff --git a/src/Resources/assets/admin/js/bitbag/bitbag-content-configuration.js b/src/Resources/assets/admin/js/bitbag/bitbag-content-configuration.js index ee45066fa..b221f2ca4 100644 --- a/src/Resources/assets/admin/js/bitbag/bitbag-content-configuration.js +++ b/src/Resources/assets/admin/js/bitbag/bitbag-content-configuration.js @@ -5,6 +5,10 @@ */ $(document).ready(function() { + $('.bitbag-media-autocomplete, .sylius-autocomplete').each((index, element) => { + $(element).autoComplete(); + }); + let pageElements = '#bitbag_sylius_cms_plugin_page_contentElements'; let blockElements = '#bitbag_sylius_cms_plugin_block_contentElements'; @@ -69,10 +73,6 @@ $(document).ready(function() { } }); - $('.bitbag-media-autocomplete, .sylius-autocomplete').each((index, element) => { - $(element).autoComplete(); - }); - $(`${collectionHolder} [data-form-collection="item"]`).each((index, element) => { $(document).loadContentConfiguration(element); }); diff --git a/src/Resources/config/services/renderer.xml b/src/Resources/config/services/renderer.xml index 2f2fba36b..a0943d659 100644 --- a/src/Resources/config/services/renderer.xml +++ b/src/Resources/config/services/renderer.xml @@ -64,5 +64,29 @@ <argument type="service" id="sylius.repository.taxon" /> <tag name="bitbag_sylius_cms_plugin.renderer.content_element" /> </service> + + <service id="bitbag_sylius_cms_plugin.collection_renderer_strategy" class="BitBag\SyliusCmsPlugin\Renderer\CollectionRendererStrategy"> + <argument type="tagged_iterator" tag="bitbag_sylius_cms_plugin.renderer.collection" /> + </service> + + <service id="bitbag_sylius_cms_plugin.renderer.collection.blocks" class="BitBag\SyliusCmsPlugin\Renderer\Collection\CollectionBlocksRenderer"> + <argument type="service" id="bitbag_sylius_cms_plugin.content_element_renderer_strategy" /> + <tag name="bitbag_sylius_cms_plugin.renderer.collection" /> + </service> + + <service id="bitbag_sylius_cms_plugin.renderer.collection.media" class="BitBag\SyliusCmsPlugin\Renderer\Collection\CollectionMediaRenderer"> + <argument type="service" id="bitbag_sylius_cms_plugin.twig.runtime.media" /> + <tag name="bitbag_sylius_cms_plugin.renderer.collection" /> + </service> + + <service id="bitbag_sylius_cms_plugin.renderer.collection.pages" class="BitBag\SyliusCmsPlugin\Renderer\Collection\CollectionPagesRenderer"> + <argument type="service" id="bitbag_sylius_cms_plugin.page_link_renderer" /> + <tag name="bitbag_sylius_cms_plugin.renderer.collection" /> + </service> + + <service id="bitbag_sylius_cms_plugin.page_link_renderer" class="BitBag\SyliusCmsPlugin\Renderer\PageLinkRenderer"> + <argument type="service" id="router.default" /> + <argument type="service" id="twig" /> + </service> </services> </container> diff --git a/src/Resources/config/services/resolver.xml b/src/Resources/config/services/resolver.xml index 2bfd80270..9d51b70b1 100644 --- a/src/Resources/config/services/resolver.xml +++ b/src/Resources/config/services/resolver.xml @@ -34,6 +34,11 @@ <argument type="service" id="sylius.context.channel" /> </service> + <service id="bitbag_sylius_cms_plugin.resolver.collection_resource" class="BitBag\SyliusCmsPlugin\Resolver\CollectionResourceResolver" public="true"> + <argument type="service" id="bitbag_sylius_cms_plugin.repository.collection" /> + <argument type="service" id="logger" /> + </service> + <service id="bitbag_sylius_cms_plugin.resolver.page_resource" class="BitBag\SyliusCmsPlugin\Resolver\PageResourceResolver" public="true"> <argument type="service" id="bitbag_sylius_cms_plugin.repository.page" /> <argument type="service" id="logger" /> diff --git a/src/Resources/config/services/twig.xml b/src/Resources/config/services/twig.xml index 39d108966..d831b84ca 100644 --- a/src/Resources/config/services/twig.xml +++ b/src/Resources/config/services/twig.xml @@ -24,6 +24,18 @@ <tag name="twig.runtime" /> </service> + <service id="bitbag_sylius_cms_plugin.twig.extension.collection" class="BitBag\SyliusCmsPlugin\Twig\Extension\RenderCollectionExtension"> + <argument type="service" id="bitbag_sylius_cms_plugin.twig.runtime.collection" /> + <tag name="twig.extension" /> + </service> + + <service id="bitbag_sylius_cms_plugin.twig.runtime.collection" class="BitBag\SyliusCmsPlugin\Twig\Runtime\RenderCollectionRuntime"> + <argument type="service" id="twig" /> + <argument type="service" id="bitbag_sylius_cms_plugin.resolver.collection_resource" /> + <argument type="service" id="bitbag_sylius_cms_plugin.collection_renderer_strategy" /> + <tag name="twig.runtime" /> + </service> + <service id="bitbag_sylius_cms_plugin.twig.extension.media" class="BitBag\SyliusCmsPlugin\Twig\Extension\RenderMediaExtension"> <argument type="service" id="bitbag_sylius_cms_plugin.twig.runtime.media" /> <tag name="twig.extension" /> diff --git a/src/Resources/views/Shop/Collection/show.html.twig b/src/Resources/views/Shop/Collection/show.html.twig new file mode 100644 index 000000000..c1e138d62 --- /dev/null +++ b/src/Resources/views/Shop/Collection/show.html.twig @@ -0,0 +1,3 @@ +<div class="bitbag-collection"> + {{ content|raw }} +</div> diff --git a/src/Resources/views/Shop/Media/Show/file.html.twig b/src/Resources/views/Shop/Media/Show/file.html.twig index 62a370885..2a03c5d81 100755 --- a/src/Resources/views/Shop/Media/Show/file.html.twig +++ b/src/Resources/views/Shop/Media/Show/file.html.twig @@ -1,10 +1,12 @@ -{% if null != media.name %} - <h2>{{ media.name|raw }}</h2> -{% endif %} +<div> + {% if null != media.name %} + <h2>{{ media.name|raw }}</h2> + {% endif %} -<p>{{ bitbag_cms_render_content(media) }}</p> + <p>{{ bitbag_cms_render_content(media) }}</p> -<a class="ui icon labeled primary button" href="{{ path('bitbag_sylius_cms_plugin_shop_media_download', {'code': media.code}) }}"> - <i class="download icon"></i> - {{ 'bitbag_sylius_cms_plugin.ui.download'|trans }} -</a> + <a class="ui icon labeled primary button" href="{{ path('bitbag_sylius_cms_plugin_shop_media_download', {'code': media.code}) }}"> + <i class="download icon"></i> + {{ 'bitbag_sylius_cms_plugin.ui.download'|trans }} + </a> +</div> diff --git a/src/Resources/views/Shop/Media/Show/image.html.twig b/src/Resources/views/Shop/Media/Show/image.html.twig index edf7565dc..0b13ea9f0 100755 --- a/src/Resources/views/Shop/Media/Show/image.html.twig +++ b/src/Resources/views/Shop/Media/Show/image.html.twig @@ -1,8 +1,10 @@ -<h2>{{ media.name|raw }}</h2> +<div> + <h2>{{ media.name|raw }}</h2> -<img class="ui fluid image" src="{{ media.path }}" alt="{{ media.alt }}" - {% if media.width is not null %} width="{{ media.width }}" {% endif %} - {% if media.height is not null %} height="{{ media.height }}" {% endif %} -/> + <img class="ui fluid image" src="{{ media.path }}" alt="{{ media.alt }}" + {% if media.width is not null %} width="{{ media.width }}" {% endif %} + {% if media.height is not null %} height="{{ media.height }}" {% endif %} + /> -<p>{{ bitbag_cms_render_content(media) }}</p> + <p>{{ bitbag_cms_render_content(media) }}</p> +</div> diff --git a/src/Resources/views/Shop/Page/link.html.twig b/src/Resources/views/Shop/Page/link.html.twig new file mode 100644 index 000000000..c55da6b38 --- /dev/null +++ b/src/Resources/views/Shop/Page/link.html.twig @@ -0,0 +1,3 @@ +<div> + <a href="{{ link }}">{{ name }}</a> +</div> diff --git a/src/Sorter/SorterById.php b/src/Sorter/SorterById.php new file mode 100644 index 000000000..16757f288 --- /dev/null +++ b/src/Sorter/SorterById.php @@ -0,0 +1,27 @@ +<?php + +/* + * This file was created by developers working at BitBag + * Do you need more information about us and what we do? Visit our https://bitbag.io website! + * We are hiring developers from all over the world. Join us and start your new, exciting adventure and become part of us: https://bitbag.io/career +*/ + +declare(strict_types=1); + +namespace BitBag\SyliusCmsPlugin\Sorter; + +final class SorterById +{ + public static function sort(array $elements, string $direction = 'asc'): array + { + usort($elements, static function ($element1, $element2) use ($direction) { + if ($direction === 'asc') { + return $element1->getId() <=> $element2->getId(); + } + + return $element2->getId() <=> $element1->getId(); + }); + + return $elements; + } +} diff --git a/src/Twig/Extension/RenderCollectionExtension.php b/src/Twig/Extension/RenderCollectionExtension.php new file mode 100644 index 000000000..246be6897 --- /dev/null +++ b/src/Twig/Extension/RenderCollectionExtension.php @@ -0,0 +1,33 @@ +<?php + +/* + * This file was created by developers working at BitBag + * Do you need more information about us and what we do? Visit our https://bitbag.io website! + * We are hiring developers from all over the world. Join us and start your new, exciting adventure and become part of us: https://bitbag.io/career +*/ + +declare(strict_types=1); + +namespace BitBag\SyliusCmsPlugin\Twig\Extension; + +use BitBag\SyliusCmsPlugin\Twig\Runtime\RenderCollectionRuntimeInterface; +use Twig\Extension\AbstractExtension; +use Twig\TwigFunction; + +final class RenderCollectionExtension extends AbstractExtension +{ + public function __construct(private RenderCollectionRuntimeInterface $collectionRuntime) + { + } + + public function getFunctions(): array + { + return [ + new TwigFunction( + 'bitbag_cms_render_collection', + [$this->collectionRuntime, 'renderCollection'], + ['is_safe' => ['html']], + ), + ]; + } +} diff --git a/src/Twig/Runtime/RenderCollectionRuntime.php b/src/Twig/Runtime/RenderCollectionRuntime.php new file mode 100644 index 000000000..45b9b5901 --- /dev/null +++ b/src/Twig/Runtime/RenderCollectionRuntime.php @@ -0,0 +1,42 @@ +<?php + +/* + * This file was created by developers working at BitBag + * Do you need more information about us and what we do? Visit our https://bitbag.io website! + * We are hiring developers from all over the world. Join us and start your new, exciting adventure and become part of us: https://bitbag.io/career +*/ + +declare(strict_types=1); + +namespace BitBag\SyliusCmsPlugin\Twig\Runtime; + +use BitBag\SyliusCmsPlugin\Renderer\CollectionRendererStrategyInterface; +use BitBag\SyliusCmsPlugin\Resolver\CollectionResourceResolverInterface; +use Twig\Environment; + +final class RenderCollectionRuntime implements RenderCollectionRuntimeInterface +{ + private const DEFAULT_TEMPLATE = '@BitBagSyliusCmsPlugin/Shop/Collection/show.html.twig'; + + public function __construct( + private Environment $twig, + private CollectionResourceResolverInterface $collectionResourceResolver, + private CollectionRendererStrategyInterface $collectionRenderer, + ) { + } + + public function renderCollection(string $code, ?int $countToRender = null, ?string $template = null): string + { + $collection = $this->collectionResourceResolver->findOrLog($code); + if (null === $collection) { + return ''; + } + + return $this->twig->render( + $template ?? self::DEFAULT_TEMPLATE, + [ + 'content' => $this->collectionRenderer->render($collection, $countToRender), + ], + ); + } +} diff --git a/src/Twig/Runtime/RenderCollectionRuntimeInterface.php b/src/Twig/Runtime/RenderCollectionRuntimeInterface.php new file mode 100644 index 000000000..ac6f52a17 --- /dev/null +++ b/src/Twig/Runtime/RenderCollectionRuntimeInterface.php @@ -0,0 +1,16 @@ +<?php + +/* + * This file was created by developers working at BitBag + * Do you need more information about us and what we do? Visit our https://bitbag.io website! + * We are hiring developers from all over the world. Join us and start your new, exciting adventure and become part of us: https://bitbag.io/career +*/ + +declare(strict_types=1); + +namespace BitBag\SyliusCmsPlugin\Twig\Runtime; + +interface RenderCollectionRuntimeInterface +{ + public function renderCollection(string $code, ?int $countToRender = null, ?string $template = null): string; +} diff --git a/tests/Application/templates/bundles/SyliusShopBundle/Homepage/index.html.twig b/tests/Application/templates/bundles/SyliusShopBundle/Homepage/index.html.twig index ab008b882..83f010ec7 100755 --- a/tests/Application/templates/bundles/SyliusShopBundle/Homepage/index.html.twig +++ b/tests/Application/templates/bundles/SyliusShopBundle/Homepage/index.html.twig @@ -1,6 +1,7 @@ {% extends '@SyliusShop/layout.html.twig' %} {% block content %} + {{ bitbag_cms_render_collection('blog') }} <div class="top one"> <div class="ui center aligned segment stackable grid cms-logo"> <a href="https://github.com/BitBagCommerce/SyliusCmsPlugin"> From 9a239a327e5c8eaacf46d936aada61d67604a459 Mon Sep 17 00:00:00 2001 From: jkindly <kozupa.jakub@gmail.com> Date: Tue, 23 Jul 2024 11:59:24 +0200 Subject: [PATCH 12/15] OP-441: ECS fixes --- src/Renderer/Collection/CollectionBlocksRenderer.php | 2 +- src/Renderer/Collection/CollectionMediaRenderer.php | 2 +- src/Renderer/Collection/CollectionPagesRenderer.php | 2 +- src/Sorter/SorterById.php | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Renderer/Collection/CollectionBlocksRenderer.php b/src/Renderer/Collection/CollectionBlocksRenderer.php index 584da2568..250cf5709 100644 --- a/src/Renderer/Collection/CollectionBlocksRenderer.php +++ b/src/Renderer/Collection/CollectionBlocksRenderer.php @@ -40,6 +40,6 @@ public function render(CollectionInterface $collection, ?int $countToRender = nu public function supports(CollectionInterface $collection): bool { - return $collection->getBlocks()?->count() > 0; + return 0 < $collection->getBlocks()?->count(); } } diff --git a/src/Renderer/Collection/CollectionMediaRenderer.php b/src/Renderer/Collection/CollectionMediaRenderer.php index b5c7ee8a3..ddb91be54 100644 --- a/src/Renderer/Collection/CollectionMediaRenderer.php +++ b/src/Renderer/Collection/CollectionMediaRenderer.php @@ -41,6 +41,6 @@ public function render(CollectionInterface $collection, ?int $countToRender = nu public function supports(CollectionInterface $collection): bool { - return $collection->getMedia()?->count() > 0; + return 0 < $collection->getMedia()?->count(); } } diff --git a/src/Renderer/Collection/CollectionPagesRenderer.php b/src/Renderer/Collection/CollectionPagesRenderer.php index 587434e17..2b5578cf6 100644 --- a/src/Renderer/Collection/CollectionPagesRenderer.php +++ b/src/Renderer/Collection/CollectionPagesRenderer.php @@ -40,6 +40,6 @@ public function render(CollectionInterface $collection, ?int $countToRender = nu public function supports(CollectionInterface $collection): bool { - return $collection->getPages()?->count() > 0; + return 0 < $collection->getPages()?->count(); } } diff --git a/src/Sorter/SorterById.php b/src/Sorter/SorterById.php index 16757f288..5ecdcd959 100644 --- a/src/Sorter/SorterById.php +++ b/src/Sorter/SorterById.php @@ -15,7 +15,7 @@ final class SorterById public static function sort(array $elements, string $direction = 'asc'): array { usort($elements, static function ($element1, $element2) use ($direction) { - if ($direction === 'asc') { + if ('asc' === $direction) { return $element1->getId() <=> $element2->getId(); } From a2a21acece320f0afacb0af0af3c247017783748 Mon Sep 17 00:00:00 2001 From: jkindly <kozupa.jakub@gmail.com> Date: Tue, 23 Jul 2024 14:12:36 +0200 Subject: [PATCH 13/15] OP-441: PHP Spec --- .../CollectionBlocksRendererSpec.php | 100 ++++++++++++++++++ .../CollectionMediaRendererSpec.php | 78 ++++++++++++++ .../CollectionPagesRendererSpec.php | 92 ++++++++++++++++ .../CollectionRendererStrategySpec.php | 73 +++++++++++++ spec/Renderer/PageLinkRendererSpec.php | 88 +++++++++++++++ 5 files changed, 431 insertions(+) create mode 100644 spec/Renderer/Collection/CollectionBlocksRendererSpec.php create mode 100644 spec/Renderer/Collection/CollectionMediaRendererSpec.php create mode 100644 spec/Renderer/Collection/CollectionPagesRendererSpec.php create mode 100644 spec/Renderer/CollectionRendererStrategySpec.php create mode 100644 spec/Renderer/PageLinkRendererSpec.php diff --git a/spec/Renderer/Collection/CollectionBlocksRendererSpec.php b/spec/Renderer/Collection/CollectionBlocksRendererSpec.php new file mode 100644 index 000000000..d131e1cbf --- /dev/null +++ b/spec/Renderer/Collection/CollectionBlocksRendererSpec.php @@ -0,0 +1,100 @@ +<?php + +/* + * This file was created by developers working at BitBag + * Do you need more information about us and what we do? Visit our https://bitbag.io website! + * We are hiring developers from all over the world. Join us and start your new, exciting adventure and become part of us: https://bitbag.io/career +*/ + +declare(strict_types=1); + +namespace spec\BitBag\SyliusCmsPlugin\Renderer\Collection; + +use BitBag\SyliusCmsPlugin\Entity\BlockInterface; +use BitBag\SyliusCmsPlugin\Entity\CollectionInterface; +use BitBag\SyliusCmsPlugin\Renderer\Collection\CollectionBlocksRenderer; +use BitBag\SyliusCmsPlugin\Renderer\Collection\CollectionRendererInterface; +use BitBag\SyliusCmsPlugin\Renderer\ContentElementRendererStrategyInterface; +use Doctrine\Common\Collections\ArrayCollection; +use PhpSpec\ObjectBehavior; + +final class CollectionBlocksRendererSpec extends ObjectBehavior +{ + public function let(ContentElementRendererStrategyInterface $contentElementRendererStrategy): void + { + $this->beConstructedWith($contentElementRendererStrategy); + } + + public function it_is_initializable(): void + { + $this->shouldHaveType(CollectionBlocksRenderer::class); + } + + public function it_implements_collection_renderer_interface(): void + { + $this->shouldImplement(CollectionRendererInterface::class); + } + + public function it_renders_blocks_from_collection( + ContentElementRendererStrategyInterface $contentElementRendererStrategy, + CollectionInterface $collection, + BlockInterface $block1, + BlockInterface $block2 + ): void + { + $blocks = new ArrayCollection([$block1->getWrappedObject(), $block2->getWrappedObject()]); + $collection->getBlocks()->willReturn($blocks); + + $contentElementRendererStrategy->render($block1)->willReturn('block1_content'); + $contentElementRendererStrategy->render($block2)->willReturn('block2_content'); + + $this->render($collection)->shouldReturn('block1_contentblock2_content'); + } + + public function it_limits_number_of_rendered_blocks( + ContentElementRendererStrategyInterface $contentElementRendererStrategy, + CollectionInterface $collection, + BlockInterface $block1, + BlockInterface $block2 + ): void + { + $blocks = new ArrayCollection([$block1->getWrappedObject(), $block2->getWrappedObject()]); + $collection->getBlocks()->willReturn($blocks); + + $contentElementRendererStrategy->render($block1)->willReturn('block1_content'); + $contentElementRendererStrategy->render($block2)->willReturn('block2_content'); + + $this->render($collection, 1)->shouldReturn('block1_content'); + } + + public function it_supports_collections_with_blocks( + CollectionInterface $collection, + BlockInterface $block + ): void + { + $blocks = new ArrayCollection([$block]); + $collection->getBlocks()->willReturn($blocks); + + $this->supports($collection)->shouldReturn(true); + } + + public function it_does_not_support_empty_collections( + CollectionInterface $collection + ): void + { + $collection->getBlocks()->willReturn(new ArrayCollection()); + + $this->supports($collection)->shouldReturn(false); + } + + public function it_throws_exception_when_blocks_are_null( + ContentElementRendererStrategyInterface $contentElementRendererStrategy, + CollectionInterface $collection + ): void + { + $collection->getBlocks()->willReturn(null); + + $this->shouldThrow(\InvalidArgumentException::class) + ->during('render', [$collection]); + } +} diff --git a/spec/Renderer/Collection/CollectionMediaRendererSpec.php b/spec/Renderer/Collection/CollectionMediaRendererSpec.php new file mode 100644 index 000000000..d04537038 --- /dev/null +++ b/spec/Renderer/Collection/CollectionMediaRendererSpec.php @@ -0,0 +1,78 @@ +<?php + +/* + * This file was created by developers working at BitBag + * Do you need more information about us and what we do? Visit our https://bitbag.io website! + * We are hiring developers from all over the world. Join us and start your new, exciting adventure and become part of us: https://bitbag.io/career +*/ + +declare(strict_types=1); + +namespace spec\BitBag\SyliusCmsPlugin\Renderer\Collection; + +use BitBag\SyliusCmsPlugin\Entity\CollectionInterface; +use BitBag\SyliusCmsPlugin\Entity\MediaInterface; +use BitBag\SyliusCmsPlugin\Renderer\Collection\CollectionMediaRenderer; +use BitBag\SyliusCmsPlugin\Renderer\Collection\CollectionRendererInterface; +use BitBag\SyliusCmsPlugin\Twig\Runtime\RenderMediaRuntimeInterface; +use Doctrine\Common\Collections\ArrayCollection; +use PhpSpec\ObjectBehavior; + +final class CollectionMediaRendererSpec extends ObjectBehavior +{ + function let(RenderMediaRuntimeInterface $renderMediaRuntime) + { + $this->beConstructedWith($renderMediaRuntime); + } + + function it_is_initializable() + { + $this->shouldHaveType(CollectionMediaRenderer::class); + $this->shouldImplement(CollectionRendererInterface::class); + } + + function it_renders_media_collection(RenderMediaRuntimeInterface $renderMediaRuntime, CollectionInterface $collection, MediaInterface $media1, MediaInterface $media2) + { + $media1->getId()->willReturn(1); + $media2->getId()->willReturn(2); + + $media1->getCode()->willReturn('media_code_1'); + $media2->getCode()->willReturn('media_code_2'); + + $collection->getMedia()->willReturn(new ArrayCollection([$media1->getWrappedObject(), $media2->getWrappedObject()])); + + $renderMediaRuntime->renderMedia('media_code_1')->willReturn('media1'); + $renderMediaRuntime->renderMedia('media_code_2')->willReturn('media2'); + + $this->render($collection)->shouldReturn('media1media2'); + } + + function it_renders_limited_number_of_media(RenderMediaRuntimeInterface $renderMediaRuntime, CollectionInterface $collection, MediaInterface $media1, MediaInterface $media2) + { + $media1->getId()->willReturn(1); + $media2->getId()->willReturn(2); + + $media1->getCode()->willReturn('media_code_1'); + $media2->getCode()->willReturn('media_code_2'); + + $collection->getMedia()->willReturn(new ArrayCollection([$media1->getWrappedObject(), $media2->getWrappedObject()])); + + $renderMediaRuntime->renderMedia('media_code_1')->willReturn('media1'); + + $this->render($collection, 1)->shouldReturn('media1'); + } + + function it_supports_collections_with_media(CollectionInterface $collection, MediaInterface $media1) + { + $collection->getMedia()->willReturn(new ArrayCollection([$media1])); + + $this->supports($collection)->shouldReturn(true); + } + + function it_does_not_support_collections_without_media(CollectionInterface $collection) + { + $collection->getMedia()->willReturn(new ArrayCollection()); + + $this->supports($collection)->shouldReturn(false); + } +} diff --git a/spec/Renderer/Collection/CollectionPagesRendererSpec.php b/spec/Renderer/Collection/CollectionPagesRendererSpec.php new file mode 100644 index 000000000..e5421f555 --- /dev/null +++ b/spec/Renderer/Collection/CollectionPagesRendererSpec.php @@ -0,0 +1,92 @@ +<?php + +/* + * This file was created by developers working at BitBag + * Do you need more information about us and what we do? Visit our https://bitbag.io website! + * We are hiring developers from all over the world. Join us and start your new, exciting adventure and become part of us: https://bitbag.io/career +*/ + +declare(strict_types=1); + +namespace spec\BitBag\SyliusCmsPlugin\Renderer\Collection; + +use BitBag\SyliusCmsPlugin\Entity\CollectionInterface; +use BitBag\SyliusCmsPlugin\Entity\PageInterface; +use BitBag\SyliusCmsPlugin\Renderer\Collection\CollectionPagesRenderer; +use BitBag\SyliusCmsPlugin\Renderer\Collection\CollectionRendererInterface; +use BitBag\SyliusCmsPlugin\Renderer\PageLinkRendererInterface; +use Doctrine\Common\Collections\ArrayCollection; +use PhpSpec\ObjectBehavior; + +final class CollectionPagesRendererSpec extends ObjectBehavior +{ + public function let(PageLinkRendererInterface $pageLinkRenderer): void + { + $this->beConstructedWith($pageLinkRenderer); + } + + public function it_is_initializable(): void + { + $this->shouldHaveType(CollectionPagesRenderer::class); + } + + public function it_implements_collection_renderer_interface(): void + { + $this->shouldImplement(CollectionRendererInterface::class); + } + + public function it_renders_pages_from_collection( + PageLinkRendererInterface $pageLinkRenderer, + CollectionInterface $collection, + PageInterface $page1, + PageInterface $page2 + ): void + { + $page1->getId()->willReturn(2); + $page2->getId()->willReturn(1); + + $collection->getPages()->willReturn(new ArrayCollection([$page1->getWrappedObject(), $page2->getWrappedObject()])); + + $pageLinkRenderer->render($page1)->willReturn('page1_content'); + $pageLinkRenderer->render($page2)->willReturn('page2_content'); + + $this->render($collection)->shouldReturn('page1_contentpage2_content'); + } + + public function it_limits_number_of_rendered_pages( + PageLinkRendererInterface $pageLinkRenderer, + CollectionInterface $collection, + PageInterface $page1, + PageInterface $page2 + ): void + { + $page1->getId()->willReturn(2); + $page2->getId()->willReturn(1); + + $collection->getPages()->willReturn(new ArrayCollection([$page1->getWrappedObject(), $page2->getWrappedObject()])); + + $pageLinkRenderer->render($page1)->willReturn('page1_content'); + $pageLinkRenderer->render($page2)->willReturn('page2_content'); + + $this->render($collection, 1)->shouldReturn('page1_content'); + } + + public function it_supports_collections_with_pages( + CollectionInterface $collection, + PageInterface $page + ): void + { + $collection->getPages()->willReturn(new ArrayCollection([$page])); + + $this->supports($collection)->shouldReturn(true); + } + + public function it_does_not_support_empty_collections( + CollectionInterface $collection + ): void + { + $collection->getPages()->willReturn(new ArrayCollection()); + + $this->supports($collection)->shouldReturn(false); + } +} diff --git a/spec/Renderer/CollectionRendererStrategySpec.php b/spec/Renderer/CollectionRendererStrategySpec.php new file mode 100644 index 000000000..67aebde51 --- /dev/null +++ b/spec/Renderer/CollectionRendererStrategySpec.php @@ -0,0 +1,73 @@ +<?php + +/* + * This file was created by developers working at BitBag + * Do you need more information about us and what we do? Visit our https://bitbag.io website! + * We are hiring developers from all over the world. Join us and start your new, exciting adventure and become part of us: https://bitbag.io/career +*/ + +declare(strict_types=1); + +namespace spec\BitBag\SyliusCmsPlugin\Renderer; + +use BitBag\SyliusCmsPlugin\Entity\CollectionInterface; +use BitBag\SyliusCmsPlugin\Renderer\Collection\CollectionRendererInterface; +use BitBag\SyliusCmsPlugin\Renderer\CollectionRendererStrategy; +use BitBag\SyliusCmsPlugin\Renderer\CollectionRendererStrategyInterface; +use PhpSpec\ObjectBehavior; + +final class CollectionRendererStrategySpec extends ObjectBehavior +{ + public function let(CollectionRendererInterface $renderer1, CollectionRendererInterface $renderer2): void + { + $this->beConstructedWith([$renderer1, $renderer2]); + } + + public function it_is_initializable(): void + { + $this->shouldHaveType(CollectionRendererStrategy::class); + } + + public function it_implements_collection_renderer_strategy_interface(): void + { + $this->shouldImplement(CollectionRendererStrategyInterface::class); + } + + public function it_renders_collection_using_supported_renderer( + CollectionRendererInterface $renderer1, + CollectionRendererInterface $renderer2, + CollectionInterface $collection + ): void + { + $renderer1->supports($collection)->willReturn(false); + $renderer2->supports($collection)->willReturn(true); + $renderer2->render($collection, null)->willReturn('rendered content'); + + $this->render($collection)->shouldReturn('rendered content'); + } + + public function it_renders_collection_with_count_to_render( + CollectionRendererInterface $renderer1, + CollectionRendererInterface $renderer2, + CollectionInterface $collection + ): void + { + $renderer1->supports($collection)->willReturn(false); + $renderer2->supports($collection)->willReturn(true); + $renderer2->render($collection, 5)->willReturn('rendered content with count'); + + $this->render($collection, 5)->shouldReturn('rendered content with count'); + } + + public function it_returns_empty_string_when_no_renderer_supports_collection( + CollectionRendererInterface $renderer1, + CollectionRendererInterface $renderer2, + CollectionInterface $collection + ): void + { + $renderer1->supports($collection)->willReturn(false); + $renderer2->supports($collection)->willReturn(false); + + $this->render($collection)->shouldReturn(''); + } +} diff --git a/spec/Renderer/PageLinkRendererSpec.php b/spec/Renderer/PageLinkRendererSpec.php new file mode 100644 index 000000000..45fb7b5f9 --- /dev/null +++ b/spec/Renderer/PageLinkRendererSpec.php @@ -0,0 +1,88 @@ +<?php + +/* + * This file was created by developers working at BitBag + * Do you need more information about us and what we do? Visit our https://bitbag.io website! + * We are hiring developers from all over the world. Join us and start your new, exciting adventure and become part of us: https://bitbag.io/career +*/ + +declare(strict_types=1); + +namespace spec\BitBag\SyliusCmsPlugin\Renderer; + +use BitBag\SyliusCmsPlugin\Entity\PageInterface; +use BitBag\SyliusCmsPlugin\Renderer\PageLinkRenderer; +use BitBag\SyliusCmsPlugin\Renderer\PageLinkRendererInterface; +use PhpSpec\ObjectBehavior; +use Symfony\Component\Routing\Generator\UrlGeneratorInterface; +use Twig\Environment; + +final class PageLinkRendererSpec extends ObjectBehavior +{ + public function let( + UrlGeneratorInterface $urlGenerator, + Environment $twig + ): void { + $this->beConstructedWith($urlGenerator, $twig); + } + + public function it_is_initializable(): void + { + $this->shouldHaveType(PageLinkRenderer::class); + } + + public function it_implements_page_link_renderer_interface(): void + { + $this->shouldImplement(PageLinkRendererInterface::class); + } + + public function it_renders_page_link_with_default_template( + UrlGeneratorInterface $urlGenerator, + Environment $twig, + PageInterface $page + ): void { + $page->getSlug()->willReturn('page-slug'); + $page->getName()->willReturn('Page Name'); + + $urlGenerator->generate( + 'bitbag_sylius_cms_plugin_shop_page_show', + ['slug' => 'page-slug'], + UrlGeneratorInterface::ABSOLUTE_URL + )->willReturn('http://example.com/page-slug'); + + $twig->render( + '@BitBagSyliusCmsPlugin/Shop/Page/link.html.twig', + [ + 'link' => 'http://example.com/page-slug', + 'name' => 'Page Name', + ] + )->willReturn('<a href="http://example.com/page-slug">Page Name</a>'); + + $this->render($page)->shouldReturn('<a href="http://example.com/page-slug">Page Name</a>'); + } + + public function it_renders_page_link_with_custom_template( + UrlGeneratorInterface $urlGenerator, + Environment $twig, + PageInterface $page + ): void { + $page->getSlug()->willReturn('page-slug'); + $page->getName()->willReturn('Page Name'); + + $urlGenerator->generate( + 'bitbag_sylius_cms_plugin_shop_page_show', + ['slug' => 'page-slug'], + UrlGeneratorInterface::ABSOLUTE_URL + )->willReturn('http://example.com/page-slug'); + + $twig->render( + 'custom_template.html.twig', + [ + 'link' => 'http://example.com/page-slug', + 'name' => 'Page Name', + ] + )->willReturn('<a href="http://example.com/page-slug">Page Name</a>'); + + $this->render($page, 'custom_template.html.twig')->shouldReturn('<a href="http://example.com/page-slug">Page Name</a>'); + } +} From 20e54cf1f5d59176f1d6a4f6fa8d508ba1efc71a Mon Sep 17 00:00:00 2001 From: jkindly <kozupa.jakub@gmail.com> Date: Wed, 24 Jul 2024 08:56:03 +0200 Subject: [PATCH 14/15] OP-441: Remove useless specs --- .../Extension/RenderBlockExtensionSpec.php | 47 ------------------- .../RenderContentElementsExtensionSpec.php | 40 ---------------- .../Extension/RenderContentExtensionSpec.php | 40 ---------------- .../Extension/RenderMediaExtensionSpec.php | 47 ------------------- .../Extension/RenderPageLinkExtensionSpec.php | 42 ----------------- 5 files changed, 216 deletions(-) delete mode 100755 spec/Twig/Extension/RenderBlockExtensionSpec.php delete mode 100644 spec/Twig/Extension/RenderContentElementsExtensionSpec.php delete mode 100644 spec/Twig/Extension/RenderContentExtensionSpec.php delete mode 100755 spec/Twig/Extension/RenderMediaExtensionSpec.php delete mode 100644 spec/Twig/Extension/RenderPageLinkExtensionSpec.php diff --git a/spec/Twig/Extension/RenderBlockExtensionSpec.php b/spec/Twig/Extension/RenderBlockExtensionSpec.php deleted file mode 100755 index a2d6c2985..000000000 --- a/spec/Twig/Extension/RenderBlockExtensionSpec.php +++ /dev/null @@ -1,47 +0,0 @@ -<?php - -/* - * This file was created by developers working at BitBag - * Do you need more information about us and what we do? Visit our https://bitbag.io website! - * We are hiring developers from all over the world. Join us and start your new, exciting adventure and become part of us: https://bitbag.io/career -*/ - -declare(strict_types=1); - -namespace spec\BitBag\SyliusCmsPlugin\Twig\Extension; - -use BitBag\SyliusCmsPlugin\Twig\Extension\RenderBlockExtension; -use BitBag\SyliusCmsPlugin\Twig\Runtime\RenderBlockRuntimeInterface; -use PhpSpec\ObjectBehavior; -use Twig\Extension\AbstractExtension; -use Twig\TwigFunction; - -final class RenderBlockExtensionSpec extends ObjectBehavior -{ - public function let( - RenderBlockRuntimeInterface $blockRuntime - ): void { - $this->beConstructedWith($blockRuntime); - } - - public function it_is_initializable(): void - { - $this->shouldHaveType(RenderBlockExtension::class); - } - - public function it_extends_abstract_extension(): void - { - $this->shouldHaveType(AbstractExtension::class); - } - - public function it_returns_functions(): void - { - $functions = $this->getFunctions(); - - $functions->shouldHaveCount(1); - - foreach ($functions as $function) { - $function->shouldHaveType(TwigFunction::class); - } - } -} diff --git a/spec/Twig/Extension/RenderContentElementsExtensionSpec.php b/spec/Twig/Extension/RenderContentElementsExtensionSpec.php deleted file mode 100644 index b7309efd0..000000000 --- a/spec/Twig/Extension/RenderContentElementsExtensionSpec.php +++ /dev/null @@ -1,40 +0,0 @@ -<?php - -/* - * This file was created by developers working at BitBag - * Do you need more information about us and what we do? Visit our https://bitbag.io website! - * We are hiring developers from all over the world. Join us and start your new, exciting adventure and become part of us: https://bitbag.io/career -*/ - -declare(strict_types=1); - -namespace spec\BitBag\SyliusCmsPlugin\Twig\Extension; - -use BitBag\SyliusCmsPlugin\Twig\Extension\RenderContentElementsExtension; -use PhpSpec\ObjectBehavior; -use Twig\Extension\AbstractExtension; -use Twig\TwigFunction; - -final class RenderContentElementsExtensionSpec extends ObjectBehavior -{ - public function it_is_initializable(): void - { - $this->shouldHaveType(RenderContentElementsExtension::class); - } - - public function it_extends_abstract_extension(): void - { - $this->shouldHaveType(AbstractExtension::class); - } - - public function it_returns_functions(): void - { - $functions = $this->getFunctions(); - - $functions->shouldHaveCount(1); - - foreach ($functions as $function) { - $function->shouldHaveType(TwigFunction::class); - } - } -} diff --git a/spec/Twig/Extension/RenderContentExtensionSpec.php b/spec/Twig/Extension/RenderContentExtensionSpec.php deleted file mode 100644 index 52e8c7f2c..000000000 --- a/spec/Twig/Extension/RenderContentExtensionSpec.php +++ /dev/null @@ -1,40 +0,0 @@ -<?php - -/* - * This file was created by developers working at BitBag - * Do you need more information about us and what we do? Visit our https://bitbag.io website! - * We are hiring developers from all over the world. Join us and start your new, exciting adventure and become part of us: https://bitbag.io/career -*/ - -declare(strict_types=1); - -namespace spec\BitBag\SyliusCmsPlugin\Twig\Extension; - -use BitBag\SyliusCmsPlugin\Twig\Extension\RenderContentExtension; -use PhpSpec\ObjectBehavior; -use Twig\Extension\AbstractExtension; -use Twig\TwigFunction; - -final class RenderContentExtensionSpec extends ObjectBehavior -{ - public function it_is_initializable(): void - { - $this->shouldHaveType(RenderContentExtension::class); - } - - public function it_extends_abstract_extension(): void - { - $this->shouldHaveType(AbstractExtension::class); - } - - public function it_returns_functions(): void - { - $functions = $this->getFunctions(); - - $functions->shouldHaveCount(1); - - foreach ($functions as $function) { - $function->shouldHaveType(TwigFunction::class); - } - } -} diff --git a/spec/Twig/Extension/RenderMediaExtensionSpec.php b/spec/Twig/Extension/RenderMediaExtensionSpec.php deleted file mode 100755 index 7fd5959cd..000000000 --- a/spec/Twig/Extension/RenderMediaExtensionSpec.php +++ /dev/null @@ -1,47 +0,0 @@ -<?php - -/* - * This file was created by developers working at BitBag - * Do you need more information about us and what we do? Visit our https://bitbag.io website! - * We are hiring developers from all over the world. Join us and start your new, exciting adventure and become part of us: https://bitbag.io/career -*/ - -declare(strict_types=1); - -namespace spec\BitBag\SyliusCmsPlugin\Twig\Extension; - -use BitBag\SyliusCmsPlugin\Twig\Extension\RenderMediaExtension; -use BitBag\SyliusCmsPlugin\Twig\Runtime\RenderMediaRuntimeInterface; -use PhpSpec\ObjectBehavior; -use Twig\Extension\AbstractExtension; -use Twig\TwigFunction; - -final class RenderMediaExtensionSpec extends ObjectBehavior -{ - public function let( - RenderMediaRuntimeInterface $mediaRuntime - ) { - $this->beConstructedWith($mediaRuntime); - } - - public function it_is_initializable(): void - { - $this->shouldHaveType(RenderMediaExtension::class); - } - - public function it_extends_abstract_extension(): void - { - $this->shouldHaveType(AbstractExtension::class); - } - - public function it_returns_functions(): void - { - $functions = $this->getFunctions(); - - $functions->shouldHaveCount(1); - - foreach ($functions as $function) { - $function->shouldHaveType(TwigFunction::class); - } - } -} diff --git a/spec/Twig/Extension/RenderPageLinkExtensionSpec.php b/spec/Twig/Extension/RenderPageLinkExtensionSpec.php deleted file mode 100644 index 3ef518c6a..000000000 --- a/spec/Twig/Extension/RenderPageLinkExtensionSpec.php +++ /dev/null @@ -1,42 +0,0 @@ -<?php - -/* - * This file has been created by developers from BitBag. - * Feel free to contact us once you face any issues or want to start - * another great project. - * You can find more information about us on https://bitbag.io and write us - * an email on mikolaj.krol@bitbag.pl. - */ - -declare(strict_types=1); - -namespace spec\BitBag\SyliusCmsPlugin\Twig\Extension; - -use BitBag\SyliusCmsPlugin\Twig\Extension\RenderPageLinkExtension; -use PhpSpec\ObjectBehavior; -use Twig\Extension\AbstractExtension; -use Twig\TwigFunction; - -final class RenderPageLinkExtensionSpec extends ObjectBehavior -{ - public function it_is_initializable(): void - { - $this->shouldHaveType(RenderPageLinkExtension::class); - } - - public function it_extends_abstract_extension(): void - { - $this->shouldHaveType(AbstractExtension::class); - } - - public function it_returns_functions(): void - { - $functions = $this->getFunctions(); - - $functions->shouldHaveCount(2); - - foreach ($functions as $function) { - $function->shouldHaveType(TwigFunction::class); - } - } -} From 56ccb600a99f0bff22d7debd198505ccbe5d15b8 Mon Sep 17 00:00:00 2001 From: jkindly <kozupa.jakub@gmail.com> Date: Wed, 24 Jul 2024 09:00:29 +0200 Subject: [PATCH 15/15] OP-441: Remove forgotten function --- .../templates/bundles/SyliusShopBundle/Homepage/index.html.twig | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/Application/templates/bundles/SyliusShopBundle/Homepage/index.html.twig b/tests/Application/templates/bundles/SyliusShopBundle/Homepage/index.html.twig index 83f010ec7..ab008b882 100755 --- a/tests/Application/templates/bundles/SyliusShopBundle/Homepage/index.html.twig +++ b/tests/Application/templates/bundles/SyliusShopBundle/Homepage/index.html.twig @@ -1,7 +1,6 @@ {% extends '@SyliusShop/layout.html.twig' %} {% block content %} - {{ bitbag_cms_render_collection('blog') }} <div class="top one"> <div class="ui center aligned segment stackable grid cms-logo"> <a href="https://github.com/BitBagCommerce/SyliusCmsPlugin">