Skip to content

Commit

Permalink
Merge pull request #534 from BitBagCommerce/feature/OP-545
Browse files Browse the repository at this point in the history
OP-545: Twig templates for blocks and pages
  • Loading branch information
senghe authored Sep 25, 2024
2 parents 4b028d9 + b8e2cae commit a8f4500
Show file tree
Hide file tree
Showing 75 changed files with 672 additions and 158 deletions.
6 changes: 3 additions & 3 deletions features/admin/adding_block.feature
Original file line number Diff line number Diff line change
Expand Up @@ -181,12 +181,12 @@ Feature: Adding blocks
Then I should be notified that "Code, Name" fields are too long

@ui @javascript
Scenario: Adding block with template
Given there is an existing template named "Homepage" with "Block" type that contains "Textarea, Single media" content elements
Scenario: Adding block with content template
Given there is an existing content template named "Homepage" with "Block" type that contains "Textarea, Single media" content elements
When I go to the create block page
And I fill the code with "intro"
And I fill the name with "Intro"
And I select "Homepage" template
And I select "Homepage" content template
And I confirm that I want to use this template
And I add it
Then I should be notified that the block has been created
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@managing_templates
@managing_content_templates
Feature: Adding cms templates
In order to create templates
As an Administrator
Expand Down
21 changes: 18 additions & 3 deletions features/admin/adding_page.feature
Original file line number Diff line number Diff line change
Expand Up @@ -210,15 +210,30 @@ Feature: Adding new page
And I should see newly created "Multiple media" content element in Content elements section

@ui @javascript
Scenario: Adding page with template
Given there is an existing template named "Homepage" with "Page" type that contains "Textarea, Single media" content elements
Scenario: Adding page with content template
Given there is an existing content template named "Homepage" with "Page" type that contains "Textarea, Single media" content elements
When I go to the create page page
And I fill the code with "my_page"
And I fill the slug with "my_page"
And I fill the name with "My page"
And I select "Homepage" template
And I select "Homepage" content template
And I confirm that I want to use this template
And I add it
Then I should be notified that the page has been created
And I should see newly created "Textarea" content element in Content elements section
And I should see newly created "Single media" content element in Content elements section

@ui @javascript
Scenario: Adding page with with a custom template
Given there is an existing template with "@SyliusCmsPlugin/Shop/Page/custom.html.twig" value
When I go to the create page page
And I fill the code with "my_page"
And I fill the slug with "my-page"
And I fill the name with "My page"
And I select "United States" channel
And I select "@SyliusCmsPlugin/Shop/Page/custom.html.twig" template
And I add it
Then I should be notified that the page has been created
And I go to the "my-page" page
And The rendered page should contain custom layout code

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@managing_templates
@managing_content_templates
Feature: Managing cms templates
In order to manage existing templates
As an Administrator
Expand Down
2 changes: 1 addition & 1 deletion features/admin/managing_pages.feature
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Feature: Managing cms pages
@ui
Scenario: Deleting page
Given there is a page in the store
When I go to the pages page
When I go to the cms pages page
And I delete this page
Then I should be notified that the page has been deleted
And I should see empty list of pages
Expand Down
2 changes: 1 addition & 1 deletion spec/Menu/ContentManagementMenuBuilderSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public function it_build_menu(
->addChild('templates', ['route' => 'sylius_cms_admin_template_index'])
->willReturn($cmsRootMenuItem)
;
$cmsRootMenuItem->setLabel('sylius_cms.ui.templates')->willReturn($cmsRootMenuItem);
$cmsRootMenuItem->setLabel('sylius_cms.ui.content_templates')->willReturn($cmsRootMenuItem);
$cmsRootMenuItem->setLabelAttribute('icon', 'clone')->shouldBeCalled();

$cmsRootMenuItem
Expand Down
52 changes: 52 additions & 0 deletions spec/Provider/ResourceTemplateProviderSpec.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

declare(strict_types=1);

namespace spec\Sylius\CmsPlugin\Provider;

use PhpSpec\ObjectBehavior;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Sylius\CmsPlugin\Provider\ResourceTemplateProvider;
use Sylius\CmsPlugin\Provider\ResourceTemplateProviderInterface;

final class ResourceTemplateProviderSpec extends ObjectBehavior
{
public function let(ParameterBagInterface $parameterBag): void
{
$parameterBag->get('sylius_cms.templates.pages')->willReturn([
'@CustomTemplate/Page.html.twig' => '@CustomTemplate/Page.html.twig',
]);

$parameterBag->get('sylius_cms.templates.blocks')->willReturn([
'@CustomTemplate/Block.html.twig' => '@CustomTemplate/Block.html.twig',
]);

$this->beConstructedWith($parameterBag);
}

public function it_is_initializable(): void
{
$this->shouldHaveType(ResourceTemplateProvider::class);
}

public function it_implements_resource_template_provider_interface(): void
{
$this->shouldImplement(ResourceTemplateProviderInterface::class);
}

public function it_returns_default_and_custom_page_templates(): void
{
$this->getPageTemplates()->shouldReturn([
'sylius.ui.default' => '@SyliusCmsPlugin/Shop/Page/show.html.twig',
'@CustomTemplate/Page.html.twig' => '@CustomTemplate/Page.html.twig',
]);
}

public function it_returns_default_and_custom_block_templates(): void
{
$this->getBlockTemplates()->shouldReturn([
'sylius.ui.default' => '@SyliusCmsPlugin/Shop/Block/show.html.twig',
'@CustomTemplate/Block.html.twig' => '@CustomTemplate/Block.html.twig',
]);
}
}
10 changes: 7 additions & 3 deletions src/Controller/BlockController.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use FOS\RestBundle\View\View;
use Sylius\Bundle\ResourceBundle\Controller\ResourceController;
use Sylius\CmsPlugin\Entity\BlockInterface;
use Sylius\CmsPlugin\Renderer\ContentElementRendererStrategyInterface;
use Sylius\CmsPlugin\Resolver\BlockResourceResolverInterface;
use Sylius\Component\Resource\ResourceActions;
use Symfony\Component\HttpFoundation\Request;
Expand Down Expand Up @@ -40,9 +41,7 @@ public function renderBlockAction(Request $request): Response
return $this->viewHandler->handle($configuration, View::create($block));
}

$template = $request->get('template') ?? self::BLOCK_TEMPLATE;

return $this->render($template, [
return $this->render($block->getTemplate() ?? self::BLOCK_TEMPLATE, [
'configuration' => $configuration,
'metadata' => $this->metadata,
'resource' => $block,
Expand Down Expand Up @@ -70,8 +69,13 @@ public function previewAction(Request $request): Response
return $this->viewHandler->handle($configuration, View::create($block));
}

/** @var ContentElementRendererStrategyInterface $contentElementRendererStrategy */
$contentElementRendererStrategy = $this->get('sylius_cms.content_element_renderer_strategy');

return $this->render($configuration->getTemplate(ResourceActions::CREATE . '.html'), [
'resource' => $block,
'template' => $block->getTemplate(),
'content' => $contentElementRendererStrategy->render($block),
$this->metadata->getName() => $block,
]);
}
Expand Down
40 changes: 40 additions & 0 deletions src/Controller/PageController.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@
use FOS\RestBundle\View\View;
use Sylius\Bundle\ResourceBundle\Controller\ResourceController;
use Sylius\CmsPlugin\Entity\PageInterface;
use Sylius\CmsPlugin\Repository\PageRepositoryInterface;
use Sylius\CmsPlugin\Resolver\PageResourceResolverInterface;
use Sylius\Component\Channel\Context\ChannelContextInterface;
use Sylius\Component\Locale\Context\LocaleContextInterface;
use Sylius\Component\Resource\ResourceActions;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
Expand All @@ -22,6 +25,42 @@ final class PageController extends ResourceController

public const FILTER = 'sylius_admin_product_original';

public const DEFAULT_TEMPLATE = '@SyliusCmsPlugin/Shop/Page/show.html.twig';

public function showAction(Request $request): Response
{
$configuration = $this->getRequestConfiguration($request);

$this->isGrantedOr403($configuration, ResourceActions::SHOW);

$slug = $request->attributes->get('slug');

/** @var PageRepositoryInterface $pageRepository */
$pageRepository = $this->get('sylius_cms.repository.page');

/** @var LocaleContextInterface $localeContext */
$localeContext = $this->get('sylius.context.locale');

/** @var ChannelContextInterface $channelContext */
$channelContext = $this->get('sylius.context.channel');

Assert::notNull($channelContext->getChannel()->getCode());

$page = $pageRepository->findOneEnabledBySlugAndChannelCode(
$slug,
$localeContext->getLocaleCode(),
$channelContext->getChannel()->getCode(),
);

if (null === $page) {
throw $this->createNotFoundException('Page not found');
}

return $this->render($page->getTemplate() ?? self::DEFAULT_TEMPLATE, [
'page' => $page,
]);
}

public function renderLinkAction(Request $request): Response
{
$configuration = $this->getRequestConfiguration($request);
Expand Down Expand Up @@ -78,6 +117,7 @@ public function previewAction(Request $request): Response
return $this->render($configuration->getTemplate(ResourceActions::CREATE . '.html'), [
'resource' => $page,
'preview' => true,
'template' => $page->getTemplate() ?? self::DEFAULT_TEMPLATE,
$this->metadata->getName() => $page,
]);
}
Expand Down
20 changes: 20 additions & 0 deletions src/DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ public function getConfigTreeBuilder(): TreeBuilder
$rootNode = $treeBuilder->getRootNode();

$this->addResourcesSection($rootNode);
$this->addTemplatesSection($rootNode);

return $treeBuilder;
}
Expand Down Expand Up @@ -196,4 +197,23 @@ private function addResourcesSection(ArrayNodeDefinition $node): void
->end()
;
}

private function addTemplatesSection(ArrayNodeDefinition $node): void
{
$node
->children()
->arrayNode('templates')
->addDefaultsIfNotSet()
->children()
->arrayNode('pages')
->scalarPrototype()->end()
->end()
->arrayNode('blocks')
->scalarPrototype()->end()
->end()
->end()
->end()
->end()
;
}
}
5 changes: 5 additions & 0 deletions src/DependencyInjection/SyliusCmsExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ final class SyliusCmsExtension extends AbstractResourceExtension implements Prep

public function load(array $configs, ContainerBuilder $container): void
{
$configuration = new Configuration();
$config = $this->processConfiguration($configuration, $configs);

$container->setParameter('sylius_cms.templates.pages', $config['templates']['pages']);
$container->setParameter('sylius_cms.templates.blocks', $config['templates']['blocks']);
}

public function prepend(ContainerBuilder $container): void
Expand Down
12 changes: 12 additions & 0 deletions src/Entity/Block.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ public function __construct()

protected ?string $name;

protected ?string $template = null;

public function getId(): ?int
{
return $this->id;
Expand All @@ -62,4 +64,14 @@ public function setName(?string $name): void
{
$this->name = $name;
}

public function getTemplate(): ?string
{
return $this->template;
}

public function setTemplate(?string $template): void
{
$this->template = $template;
}
}
4 changes: 4 additions & 0 deletions src/Entity/BlockInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,8 @@ public function setCode(?string $code): void;
public function getName(): ?string;

public function setName(?string $name): void;

public function getTemplate(): ?string;

public function setTemplate(?string $template): void;
}
12 changes: 12 additions & 0 deletions src/Entity/Page.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ class Page implements PageInterface

protected ?string $name = null;

protected ?string $template = null;

protected ?\DateTimeImmutable $publishAt;

public function __construct()
Expand Down Expand Up @@ -161,6 +163,16 @@ public function setName(?string $name): void
$this->name = $name;
}

public function getTemplate(): ?string
{
return $this->template;
}

public function setTemplate(?string $template): void
{
$this->template = $template;
}

public function getTitle(): ?string
{
/** @var PageTranslationInterface $pageTranslationInterface */
Expand Down
4 changes: 4 additions & 0 deletions src/Entity/PageInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ public function getName(): ?string;

public function setName(?string $name): void;

public function getTemplate(): ?string;

public function setTemplate(?string $template): void;

public function getTitle(): ?string;

public function setTitle(?string $title): void;
Expand Down
10 changes: 9 additions & 1 deletion src/Form/Type/BlockType.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Sylius\Bundle\ResourceBundle\Form\Type\AbstractResourceType;
use Sylius\Bundle\TaxonomyBundle\Form\Type\TaxonAutocompleteChoiceType;
use Sylius\CmsPlugin\Entity\BlockInterface;
use Sylius\CmsPlugin\Provider\ResourceTemplateProviderInterface;
use Sylius\Component\Locale\Model\LocaleInterface;
use Sylius\Component\Resource\Repository\RepositoryInterface;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
Expand All @@ -23,6 +24,7 @@ final class BlockType extends AbstractResourceType

public function __construct(
private RepositoryInterface $localeRepository,
private ResourceTemplateProviderInterface $templateProvider,
string $dataClass,
array $validationGroups = [],
) {
Expand All @@ -48,6 +50,11 @@ public function buildForm(FormBuilderInterface $builder, array $options): void
->add('name', TextType::class, [
'label' => 'sylius_cms.ui.name',
])
->add('templates', ChoiceType::class, [
'label' => 'sylius_cms.ui.template',
'choices' => $this->templateProvider->getBlockTemplates(),
'mapped' => false,
])
->add('collections', CollectionAutocompleteChoiceType::class, [
'label' => 'sylius_cms.ui.collections',
'multiple' => true,
Expand Down Expand Up @@ -90,7 +97,7 @@ public function buildForm(FormBuilderInterface $builder, array $options): void
'multiple' => true,
'help' => 'sylius_cms.ui.display_for_taxons.help',
])
->add('template', TemplateBlockAutocompleteChoiceType::class, [
->add('contentTemplate', TemplateBlockAutocompleteChoiceType::class, [
'label' => false,
'mapped' => false,
])
Expand All @@ -105,6 +112,7 @@ public function buildForm(FormBuilderInterface $builder, array $options): void
;

PageType::addContentElementLocaleListener($builder);
PageType::addTemplateListener($builder);
}

public function getBlockPrefix(): string
Expand Down
Loading

0 comments on commit a8f4500

Please sign in to comment.