Skip to content

Commit

Permalink
Merge pull request #510 from BitBagCommerce/feature/OP-439
Browse files Browse the repository at this point in the history
OP-439: Products grid & Products grid by Taxon content elements
  • Loading branch information
senghe authored Jul 22, 2024
2 parents b829519 + 6ae04d5 commit 6d34b8d
Show file tree
Hide file tree
Showing 33 changed files with 570 additions and 6 deletions.
26 changes: 26 additions & 0 deletions features/admin/adding_block.feature
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,32 @@ Feature: Adding blocks
Then I should be notified that the block has been created
And I should see newly created "Products carousel by Taxon" content element in Content elements section

@ui @javascript
Scenario: Adding block with products grid content element
Given the store has "iPhone 8" and "iPhone X" products
When I go to the create block page
And I fill the code with "intro"
And I fill the name with "Intro"
And I click on Add button in Content elements section
And I select "Products grid" content element
And I add a products grid content element with "iPhone 8" and "iPhone X" products
And I add it
Then I should be notified that the block has been created
And I should see newly created "Products grid" content element in Content elements section

@ui @javascript
Scenario: Adding block with products grid by taxon content element
Given the store has "Smartphones" taxonomy
When I go to the create block page
And I fill the code with "intro"
And I fill the name with "Intro"
And I click on Add button in Content elements section
And I select "Products grid by Taxon" content element
And I add a products grid by taxon content element with "Smartphones" taxonomy
And I add it
Then I should be notified that the block has been created
And I should see newly created "Products grid by Taxon" content element in Content elements section

@ui @javascript
Scenario: Adding block with taxons list content element
Given the store classifies its products as "Smartphones" and "Laptops"
Expand Down
28 changes: 28 additions & 0 deletions features/admin/adding_page.feature
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,34 @@ Feature: Adding new page
Then I should be notified that the page has been created
And I should see newly created "Products carousel by Taxon" content element in Content elements section

@ui @javascript
Scenario: Adding page with products grid content element
Given the store has "iPhone 8" and "iPhone X" products
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 click on Add button in Content elements section
And I select "Products grid" content element
And I add a products grid content element with "iPhone 8" and "iPhone X" products
And I add it
Then I should be notified that the page has been created
And I should see newly created "Products grid" content element in Content elements section

@ui @javascript
Scenario: Adding page with products grid by taxon content element
Given the store has "Smartphones" taxonomy
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 click on Add button in Content elements section
And I select "Products grid by Taxon" content element
And I add a products grid by taxon content element with "Smartphones" taxonomy
And I add it
Then I should be notified that the page has been created
And I should see newly created "Products grid by Taxon" content element in Content elements section

@ui @javascript
Scenario: Adding page with taxons list content element
Given the store classifies its products as "Smartphones" and "Laptops"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<?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\ContentElement;

use BitBag\SyliusCmsPlugin\Entity\ContentConfigurationInterface;
use BitBag\SyliusCmsPlugin\Form\Type\ContentElements\ProductsGridByTaxonContentElementType;
use BitBag\SyliusCmsPlugin\Renderer\ContentElement\ContentElementRendererInterface;
use BitBag\SyliusCmsPlugin\Renderer\ContentElement\ProductsGridByTaxonContentElementRenderer;
use PhpSpec\ObjectBehavior;
use Sylius\Component\Core\Model\Product;
use Sylius\Component\Core\Model\TaxonInterface;
use Sylius\Component\Core\Repository\ProductRepositoryInterface;
use Sylius\Component\Taxonomy\Repository\TaxonRepositoryInterface;
use Twig\Environment;

final class ProductsGridByTaxonContentElementRendererSpec extends ObjectBehavior
{
public function let(Environment $twig, ProductRepositoryInterface $productRepository, TaxonRepositoryInterface $taxonRepository): void
{
$this->beConstructedWith($twig, $productRepository, $taxonRepository);
}

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

public function it_implements_content_element_renderer_interface(): void
{
$this->shouldImplement(ContentElementRendererInterface::class);
}

public function it_supports_products_grid_by_taxon_content_element_type(ContentConfigurationInterface $contentConfiguration): void
{
$contentConfiguration->getType()->willReturn(ProductsGridByTaxonContentElementType::TYPE);
$this->supports($contentConfiguration)->shouldReturn(true);
}

public function it_does_not_support_other_content_element_types(ContentConfigurationInterface $contentConfiguration): void
{
$contentConfiguration->getType()->willReturn('other_type');
$this->supports($contentConfiguration)->shouldReturn(false);
}

public function it_renders_products_grid_by_taxon_content_element(
Environment $twig,
ProductRepositoryInterface $productRepository,
TaxonRepositoryInterface $taxonRepository,
ContentConfigurationInterface $contentConfiguration,
TaxonInterface $taxon,
Product $product1,
Product $product2
): void
{
$contentConfiguration->getConfiguration()->willReturn([
'products_grid_by_taxon' => 'taxon_code'
]);

$taxonRepository->findOneBy(['code' => 'taxon_code'])->willReturn($taxon);
$productRepository->findByTaxon($taxon)->willReturn([$product1, $product2]);

$twig->render('@BitBagSyliusCmsPlugin/Shop/ContentElement/index.html.twig', [
'content_element' => '@BitBagSyliusCmsPlugin/Shop/ContentElement/_products_grid.html.twig',
'products' => [$product1, $product2],
])->willReturn('rendered template');

$this->render($contentConfiguration)->shouldReturn('rendered template');
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?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\ContentElement;

use BitBag\SyliusCmsPlugin\Entity\ContentConfigurationInterface;
use BitBag\SyliusCmsPlugin\Form\Type\ContentElements\ProductsGridContentElementType;
use BitBag\SyliusCmsPlugin\Renderer\ContentElement\ContentElementRendererInterface;
use BitBag\SyliusCmsPlugin\Renderer\ContentElement\ProductsGridContentElementRenderer;
use PhpSpec\ObjectBehavior;
use Sylius\Component\Core\Model\Product;
use Sylius\Component\Core\Repository\ProductRepositoryInterface;
use Twig\Environment;

final class ProductsGridContentElementRendererSpec extends ObjectBehavior
{
public function let(Environment $twig, ProductRepositoryInterface $productRepository): void
{
$this->beConstructedWith($twig, $productRepository);
}

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

public function it_implements_content_element_renderer_interface(): void
{
$this->shouldImplement(ContentElementRendererInterface::class);
}

public function it_supports_products_grid_content_element_type(ContentConfigurationInterface $contentConfiguration): void
{
$contentConfiguration->getType()->willReturn(ProductsGridContentElementType::TYPE);
$this->supports($contentConfiguration)->shouldReturn(true);
}

public function it_does_not_support_other_content_element_types(ContentConfigurationInterface $contentConfiguration): void
{
$contentConfiguration->getType()->willReturn('other_type');
$this->supports($contentConfiguration)->shouldReturn(false);
}

public function it_renders_products_grid_content_element(
Environment $twig,
ProductRepositoryInterface $productRepository,
ContentConfigurationInterface $contentConfiguration,
Product $product1,
Product $product2
): void
{
$contentConfiguration->getConfiguration()->willReturn([
'products_grid' => ['products' => ['code1', 'code2']]
]);

$productRepository->findBy(['code' => ['code1', 'code2']])->willReturn([$product1, $product2]);

$twig->render('@BitBagSyliusCmsPlugin/Shop/ContentElement/index.html.twig', [
'content_element' => '@BitBagSyliusCmsPlugin/Shop/ContentElement/_products_grid.html.twig',
'products' => [$product1, $product2],
])->willReturn('rendered template');

$this->render($contentConfiguration)->shouldReturn('rendered template');
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?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\Form\Type\ContentElements;

use Sylius\Bundle\ResourceBundle\Form\DataTransformer\ResourceToIdentifierTransformer;
use Sylius\Bundle\TaxonomyBundle\Form\Type\TaxonAutocompleteChoiceType;
use Sylius\Component\Resource\Repository\RepositoryInterface;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\ReversedTransformer;

final class ProductsGridByTaxonContentElementType extends AbstractType
{
public const TYPE = 'products_grid_by_taxon';

public function __construct(private RepositoryInterface $taxonRepository)
{
}

public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add(self::TYPE, TaxonAutocompleteChoiceType::class, [
'label' => 'bitbag_sylius_cms_plugin.ui.taxon',
'choice_value' => 'code',
'resource' => 'sylius.taxon',
])
;

$builder->get(self::TYPE)->addModelTransformer(
new ReversedTransformer(new ResourceToIdentifierTransformer($this->taxonRepository, 'code')),
);
}

public function getBlockPrefix(): string
{
return 'bitbag_sylius_cms_plugin_content_elements_' . self::TYPE;
}
}
34 changes: 34 additions & 0 deletions src/Form/Type/ContentElements/ProductsGridContentElementType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?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\Form\Type\ContentElements;

use Sylius\Bundle\CoreBundle\Form\Type\CatalogPromotionScope\ForProductsScopeConfigurationType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;

final class ProductsGridContentElementType extends AbstractType
{
public const TYPE = 'products_grid';

public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add(self::TYPE, ForProductsScopeConfigurationType::class, [
'label' => false,
])
;
}

public function getBlockPrefix(): string
{
return 'bitbag_sylius_cms_plugin_content_elements_' . self::TYPE;
}
}
13 changes: 7 additions & 6 deletions src/Migrations/Version20240715083336.php
Original file line number Diff line number Diff line change
@@ -1,25 +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\Migrations;

use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;

/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20240715083336 extends AbstractMigration
{
public function getDescription(): string
{
return '';
return 'This migration renames block_id to media_id in bitbag_cms_media_channels table.';
}

public function up(Schema $schema): void
{
// this up() migration is auto-generated, please modify it to your needs
$this->addSql('ALTER TABLE bitbag_cms_media_channels DROP FOREIGN KEY FK_D109622EE9ED820C');
$this->addSql('DROP INDEX IDX_D109622EE9ED820C ON bitbag_cms_media_channels');
$this->addSql('DROP INDEX `primary` ON bitbag_cms_media_channels');
Expand All @@ -31,7 +33,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_media_channels DROP FOREIGN KEY FK_D109622EEA9FDD75');
$this->addSql('DROP INDEX IDX_D109622EEA9FDD75 ON bitbag_cms_media_channels');
$this->addSql('DROP INDEX `PRIMARY` ON bitbag_cms_media_channels');
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?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\ContentElement;

use BitBag\SyliusCmsPlugin\Entity\ContentConfigurationInterface;
use BitBag\SyliusCmsPlugin\Form\Type\ContentElements\ProductsGridByTaxonContentElementType;
use Sylius\Component\Core\Model\TaxonInterface;
use Sylius\Component\Core\Repository\ProductRepositoryInterface;
use Sylius\Component\Taxonomy\Repository\TaxonRepositoryInterface;
use Twig\Environment;

final class ProductsGridByTaxonContentElementRenderer implements ContentElementRendererInterface
{
public function __construct(
private Environment $twig,
private ProductRepositoryInterface $productRepository,
private TaxonRepositoryInterface $taxonRepository,
) {
}

public function supports(ContentConfigurationInterface $contentConfiguration): bool
{
return ProductsGridByTaxonContentElementType::TYPE === $contentConfiguration->getType();
}

public function render(ContentConfigurationInterface $contentConfiguration): string
{
$taxonCode = $contentConfiguration->getConfiguration()['products_grid_by_taxon'];

/** @var TaxonInterface $taxon */
$taxon = $this->taxonRepository->findOneBy(['code' => $taxonCode]);
$products = $this->productRepository->findByTaxon($taxon);

return $this->twig->render('@BitBagSyliusCmsPlugin/Shop/ContentElement/index.html.twig', [
'content_element' => '@BitBagSyliusCmsPlugin/Shop/ContentElement/_products_grid.html.twig',
'products' => $products,
]);
}
}
Loading

0 comments on commit 6d34b8d

Please sign in to comment.