[Promotion] Add product filter

This commit is contained in:
Łukasz 2016-10-25 09:12:49 +02:00
parent fe8cfa2827
commit a8bb6cf9f5
6 changed files with 289 additions and 0 deletions

View file

@ -0,0 +1,77 @@
<?php
/*
* This file is part of the Sylius package.
*
* (c) Paweł Jędrzejewski
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sylius\Bundle\CoreBundle\Form\DataTransformer;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Sylius\Component\Core\Model\ProductInterface;
use Sylius\Component\Resource\Exception\UnexpectedTypeException;
use Sylius\Component\Core\Repository\ProductRepositoryInterface;
use Symfony\Component\Form\DataTransformerInterface;
/**
* @author Łukasz Chruściel <lukasz.chrusciel@lakion.com>
*/
final class ProductsToCodesTransformer implements DataTransformerInterface
{
/**
* @var ProductRepositoryInterface
*/
private $productRepository;
/**
* @param ProductRepositoryInterface $productRepository
*/
public function __construct(ProductRepositoryInterface $productRepository)
{
$this->productRepository = $productRepository;
}
/**
* {@inheritdoc}
*/
public function transform($value)
{
if (!is_array($value) && !is_null($value)) {
throw new UnexpectedTypeException($value, 'array');
}
if (empty($value)) {
return new ArrayCollection();
}
return new ArrayCollection($this->productRepository->findBy(['code' => $value]));
}
/**
* {@inheritdoc}
*/
public function reverseTransform($products)
{
if (!$products instanceof Collection) {
throw new UnexpectedTypeException($products, Collection::class);
}
if (null === $products) {
return [];
}
$productCodes = [];
/** @var ProductInterface $product */
foreach ($products as $product) {
$productCodes[] = $product->getCode();
}
return $productCodes;
}
}

View file

@ -0,0 +1,71 @@
<?php
/*
* This file is part of the Sylius package.
*
* (c) Paweł Jędrzejewski
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sylius\Bundle\CoreBundle\Form\Type\Promotion\Filter;
use Sylius\Component\Core\Repository\ProductRepositoryInterface;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Validator\Constraints\Type;
/**
* @author Łukasz Chruściel <lukasz.chrusciel@lakion.com>
*/
class ProductFilterConfigurationType extends AbstractType
{
/**
* @var ProductRepositoryInterface
*/
protected $productRepository;
/**
* @var DataTransformerInterface
*/
private $productsToCodesTransformer;
/**
* @param ProductRepositoryInterface $productRepository
* @param DataTransformerInterface $productsToCodesTransformer
*/
public function __construct(
ProductRepositoryInterface $productRepository,
DataTransformerInterface $productsToCodesTransformer
) {
$this->productRepository = $productRepository;
$this->productsToCodesTransformer = $productsToCodesTransformer;
}
/**
* {@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('products', 'sylius_product_choice', [
'label' => 'sylius.form.promotion_rule.product.products',
'multiple' => true,
'required' => false,
])
;
$builder->get('products')->addModelTransformer($this->productsToCodesTransformer);
}
/**
* {@inheritdoc}
*/
public function getName()
{
return 'sylius_promotion_action_filter_product_configuration';
}
}

View file

@ -27,5 +27,6 @@ class PromotionFiltersType extends BasePromotionFiltersType
parent::buildForm($builder, $options); parent::buildForm($builder, $options);
$builder->add('taxons_filter', 'sylius_promotion_action_filter_taxon_configuration', ['required' => false]); $builder->add('taxons_filter', 'sylius_promotion_action_filter_taxon_configuration', ['required' => false]);
$builder->add('products_filter', 'sylius_promotion_action_filter_product_configuration', ['required' => false]);
} }
} }

View file

@ -113,6 +113,11 @@
<argument type="service" id="sylius.form.type.data_transformer.taxons_to_codes" /> <argument type="service" id="sylius.form.type.data_transformer.taxons_to_codes" />
<tag name="form.type" alias="sylius_promotion_action_filter_taxon_configuration" /> <tag name="form.type" alias="sylius_promotion_action_filter_taxon_configuration" />
</service> </service>
<service id="sylius.form.type.promotion_action.filter.product" class="Sylius\Bundle\CoreBundle\Form\Type\Promotion\Filter\ProductFilterConfigurationType">
<argument type="service" id="sylius.repository.product" />
<argument type="service" id="sylius.form.type.data_transformer.products_to_codes" />
<tag name="form.type" alias="sylius_promotion_action_filter_product_configuration" />
</service>
<service id="sylius.form.type.price_calculator.channel_based" class="Sylius\Bundle\CoreBundle\Form\Type\Pricing\ChannelBasedConfigurationType"> <service id="sylius.form.type.price_calculator.channel_based" class="Sylius\Bundle\CoreBundle\Form\Type\Pricing\ChannelBasedConfigurationType">
<argument type="service" id="sylius.repository.channel" /> <argument type="service" id="sylius.repository.channel" />
@ -130,6 +135,9 @@
<service id="sylius.form.type.data_transformer.taxons_to_codes" class="Sylius\Bundle\CoreBundle\Form\DataTransformer\TaxonsToCodesTransformer"> <service id="sylius.form.type.data_transformer.taxons_to_codes" class="Sylius\Bundle\CoreBundle\Form\DataTransformer\TaxonsToCodesTransformer">
<argument type="service" id="sylius.repository.taxon" /> <argument type="service" id="sylius.repository.taxon" />
</service> </service>
<service id="sylius.form.type.data_transformer.products_to_codes" class="Sylius\Bundle\CoreBundle\Form\DataTransformer\ProductsToCodesTransformer">
<argument type="service" id="sylius.repository.product" />
</service>
<service id="sylius.form.type.customer_guest" class="Sylius\Bundle\CoreBundle\Form\Type\Customer\CustomerGuestType"> <service id="sylius.form.type.customer_guest" class="Sylius\Bundle\CoreBundle\Form\Type\Customer\CustomerGuestType">
<argument>%sylius.model.customer.class%</argument> <argument>%sylius.model.customer.class%</argument>

View file

@ -125,6 +125,8 @@ sylius:
count: Count count: Count
taxon: taxon:
taxons: Taxons taxons: Taxons
product:
products: Products
total_of_items_from_taxon: total_of_items_from_taxon:
taxon: Taxon taxon: Taxon
amount: Amount amount: Amount

View file

@ -0,0 +1,130 @@
<?php
/*
* This file is part of the Sylius package.
*
* (c) Paweł Jędrzejewski
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace spec\Sylius\Bundle\CoreBundle\Form\DataTransformer;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use PhpSpec\ObjectBehavior;
use Sylius\Bundle\CoreBundle\Form\DataTransformer\ProductsToCodesTransformer;
use Sylius\Component\Core\Model\ProductInterface;
use Sylius\Component\Resource\Exception\UnexpectedTypeException;
use Sylius\Component\Core\Repository\ProductRepositoryInterface;
use Symfony\Component\Form\DataTransformerInterface;
/**
* @author Łukasz Chruściel <lukasz.chrusciel@lakion.com>
*/
final class ProductsToCodesTransformerSpec extends ObjectBehavior
{
function let(ProductRepositoryInterface $productRepository)
{
$this->beConstructedWith($productRepository);
}
function it_is_initializable()
{
$this->shouldHaveType(ProductsToCodesTransformer::class);
}
function it_implements_data_transformer_interface()
{
$this->shouldImplement(DataTransformerInterface::class);
}
function it_transforms_array_of_products_codes_to_products_collection(
ProductRepositoryInterface $productRepository,
ProductInterface $bow,
ProductInterface $sword
) {
$productRepository->findBy(['code' => ['bow', 'sword']])->willReturn([$bow, $sword]);
$products = new ArrayCollection([$bow->getWrappedObject(), $sword->getWrappedObject()]);
$this->transform(['bow', 'sword'])->shouldBeCollection($products);
}
function it_transforms_only_existing_products(
ProductRepositoryInterface $productRepository,
ProductInterface $bow
) {
$productRepository->findBy(['code' => ['bow', 'sword']])->willReturn([$bow]);
$products = new ArrayCollection([$bow->getWrappedObject()]);
$this->transform(['bow', 'sword'])->shouldBeCollection($products);
}
function it_transforms_empty_array_into_empty_collection()
{
$this->transform([])->shouldBeCollection(new ArrayCollection([]));
}
function it_throws_exception_if_value_to_transform_is_not_array()
{
$this
->shouldThrow(new UnexpectedTypeException('badObject', 'array'))
->during('transform', ['badObject'])
;
}
function it_reverse_transforms_into_array_of_products_codes(
ProductInterface $axes,
ProductInterface $shields
) {
$axes->getCode()->willReturn('axes');
$shields->getCode()->willReturn('shields');
$this
->reverseTransform(new ArrayCollection([$axes->getWrappedObject(), $shields->getWrappedObject()]))
->shouldReturn(['axes', 'shields'])
;
}
function it_throws_exception_if_reverse_transformed_object_is_not_collection()
{
$this
->shouldThrow(new UnexpectedTypeException('badObject', Collection::class))
->during('reverseTransform', ['badObject'])
;
}
function it_returns_empty_array_if_passed_collection_is_empty()
{
$this->reverseTransform(new ArrayCollection())->shouldReturn([]);
}
/**
* {@inheritdoc}
*/
public function getMatchers()
{
return [
'beCollection' => function ($subject, $key) {
if (!$subject instanceof Collection || !$key instanceof Collection) {
return false;
}
if ($subject->count() !== $key->count()) {
return false;
}
foreach ($subject as $subjectElement) {
if (!$key->contains($subjectElement)) {
return false;
}
}
return true;
},
];
}
}