Skip to content

Commit

Permalink
Merge pull request #511 from BitBagCommerce/feature/OP-440
Browse files Browse the repository at this point in the history
OP-440: Conditional block rendering
  • Loading branch information
senghe authored Jul 24, 2024
2 parents 6d34b8d + 7f948bd commit 12664cf
Show file tree
Hide file tree
Showing 34 changed files with 520 additions and 44 deletions.
66 changes: 49 additions & 17 deletions spec/Twig/Runtime/RenderBlockRuntimeSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,16 @@
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
{
public function let(
BlockResourceResolverInterface $blockResourceResolver,
Environment $templatingEngine,
ContentElementRendererStrategyInterface $contentElementRendererStrategy,
ContentElementRendererStrategyInterface $contentElementRendererStrategy
): void {
$this->beConstructedWith($blockResourceResolver, $templatingEngine, $contentElementRendererStrategy);
}
Expand All @@ -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');
}
}
9 changes: 9 additions & 0 deletions src/Entity/Block.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
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
Expand All @@ -23,13 +26,19 @@ class Block implements BlockInterface
use ChannelsAwareTrait;
use ContentConfigurationAwareTrait;
use LocaleAwareTrait;
use ProductsAwareTrait;
use TaxonAwareTrait;
use ProductsInTaxonsAwareTrait;

public function __construct()
{
$this->initializeCollectionsCollection();
$this->initializeChannelsCollection();
$this->initializeContentElementsCollection();
$this->initializeLocalesCollection();
$this->initializeProductsCollection();
$this->initializeTaxonCollection();
$this->initializeProductsInTaxonsCollection();
}

protected ?int $id;
Expand Down
7 changes: 6 additions & 1 deletion src/Entity/BlockInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,12 @@ interface BlockInterface extends
CollectibleInterface,
ChannelsAwareInterface,
ContentConfigurationAwareInterface,
LocaleAwareInterface
LocaleAwareInterface,
ProductsAwareInterface,
TaxonAwareInterface,
ProductsInTaxonsAwareInterface,
BlockTaxonAwareInterface,
BlockProductAwareInterface
{
public function getCode(): ?string;

Expand Down
20 changes: 20 additions & 0 deletions src/Entity/BlockProductAwareInterface.php
Original file line number Diff line number Diff line change
@@ -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;
}
18 changes: 18 additions & 0 deletions src/Entity/BlockTaxonAwareInterface.php
Original file line number Diff line number Diff line change
@@ -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;
}
30 changes: 30 additions & 0 deletions src/Entity/ProductsInTaxonsAwareInterface.php
Original file line number Diff line number Diff line change
@@ -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;
}
7 changes: 6 additions & 1 deletion src/Entity/Trait/ProductsAwareTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
trait ProductsAwareTrait
{
/** @var Collection|ProductInterface[] */
protected $products;
protected Collection $products;

public function initializeProductsCollection(): void
{
Expand Down Expand Up @@ -47,4 +47,9 @@ public function removeProduct(ProductInterface $product): void
$this->products->removeElement($product);
}
}

public function canBeDisplayedForProduct(ProductInterface $product): bool
{
return $this->hasProduct($product);
}
}
61 changes: 61 additions & 0 deletions src/Entity/Trait/ProductsInTaxonsAwareTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?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\ProductInterface;
use Sylius\Component\Core\Model\TaxonInterface;

trait ProductsInTaxonsAwareTrait
{
/** @var Collection|TaxonInterface[] */
protected 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);
}
}

public function canBeDisplayedForProductInTaxon(ProductInterface $product): bool
{
$taxon = $product->getMainTaxon();
if (null === $taxon) {
return false;
}

return $this->hasProductsInTaxon($taxon);
}
}
17 changes: 11 additions & 6 deletions src/Entity/Trait/TaxonAwareTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,34 +17,39 @@
trait TaxonAwareTrait
{
/** @var Collection|TaxonInterface[] */
protected $taxonomies;
protected 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);
}
}

public function canBeDisplayedForTaxon(TaxonInterface $taxon): bool
{
return $this->hasTaxon($taxon);
}
}
17 changes: 17 additions & 0 deletions src/Form/Type/BlockType.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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',
])
;
}

Expand Down
Loading

0 comments on commit 12664cf

Please sign in to comment.