Skip to content

Commit

Permalink
Validate samples when the order is updated through the cart
Browse files Browse the repository at this point in the history
  • Loading branch information
mbabker committed Jul 14, 2022
1 parent 1177db6 commit 40fad85
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 4 deletions.
11 changes: 8 additions & 3 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -76,19 +76,24 @@ parameters:
path: src/Form/Extension/AddToCartTypeExtension.php

-
message: "#^Cannot call method getSampleOf\\(\\) on Sylius\\\\Component\\\\Core\\\\Model\\\\ProductVariantInterface\\|null\\.$#"
message: "#^Parameter \\#1 \\$variant of method Sylius\\\\Component\\\\Core\\\\Model\\\\OrderItemInterface\\:\\:setVariant\\(\\) expects Sylius\\\\Component\\\\Core\\\\Model\\\\ProductVariantInterface\\|null, Sylius\\\\Component\\\\Product\\\\Model\\\\ProductVariantInterface\\|null given\\.$#"
count: 1
path: src/Form/Extension/AddToCartTypeExtension.php

-
message: "#^Parameter \\#1 \\$variant of method Sylius\\\\Component\\\\Core\\\\Model\\\\OrderItemInterface\\:\\:setVariant\\(\\) expects Sylius\\\\Component\\\\Core\\\\Model\\\\ProductVariantInterface\\|null, Sylius\\\\Component\\\\Product\\\\Model\\\\ProductVariantInterface\\|null given\\.$#"
message: "#^Strict comparison using \\=\\=\\= between 0 and int\\<1, max\\> will always evaluate to false\\.$#"
count: 1
path: src/Form/Extension/AddToCartTypeExtension.php

-
message: "#^Call to static method Webmozart\\\\Assert\\\\Assert\\:\\:isInstanceOf\\(\\) with BabDev\\\\SyliusProductSamplesPlugin\\\\Model\\\\ChannelInterface and 'BabDev\\\\\\\\SyliusProductSamplesPlugin\\\\\\\\Model\\\\\\\\ChannelInterface' will always evaluate to true\\.$#"
count: 1
path: src/Form/Extension/CartTypeExtension.php

-
message: "#^Strict comparison using \\=\\=\\= between 0 and int\\<1, max\\> will always evaluate to false\\.$#"
count: 1
path: src/Form/Extension/AddToCartTypeExtension.php
path: src/Form/Extension/CartTypeExtension.php

-
message: "#^Call to an undefined method Sylius\\\\Component\\\\Product\\\\Model\\\\ProductVariantInterface\\:\\:setSampleOf\\(\\)\\.$#"
Expand Down
11 changes: 11 additions & 0 deletions psalm-baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,17 @@
<code>getVariantSelectionMethod</code>
</MixedMethodCall>
</file>
<file src="src/Form/Extension/CartTypeExtension.php">
<PossiblyNullReference occurrences="1">
<code>getSampleOf</code>
</PossiblyNullReference>
<TypeDoesNotContainType occurrences="1">
<code>0 === $channel-&gt;getMaxSamplesPerOrder()</code>
</TypeDoesNotContainType>
<UndefinedInterfaceMethod occurrences="1">
<code>getSampleOf</code>
</UndefinedInterfaceMethod>
</file>
<file src="src/Form/Extension/ProductVariantTypeExtension.php">
<PossiblyNullArgument occurrences="1">
<code>$variant-&gt;getProduct()</code>
Expand Down
2 changes: 1 addition & 1 deletion src/Form/Extension/AddToCartTypeExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ public function buildForm(FormBuilderInterface $builder, array $options): void

/** @var OrderItemInterface $item */
foreach ($addToCartCommand->getCart()->getItems() as $item) {
Assert::isInstanceOf($cartItem->getVariant(), ProductVariantInterface::class);
Assert::isInstanceOf($item->getVariant(), ProductVariantInterface::class);

if (null === $item->getVariant()->getSampleOf()) {
continue;
Expand Down
73 changes: 73 additions & 0 deletions src/Form/Extension/CartTypeExtension.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<?php

declare(strict_types=1);

namespace BabDev\SyliusProductSamplesPlugin\Form\Extension;

use BabDev\SyliusProductSamplesPlugin\Model\ChannelInterface;
use BabDev\SyliusProductSamplesPlugin\Model\ProductVariantInterface;
use Sylius\Bundle\OrderBundle\Form\Type\CartType;
use Sylius\Component\Channel\Context\ChannelContextInterface;
use Sylius\Component\Core\Model\OrderItemInterface;
use Sylius\Component\Order\Model\OrderInterface;
use Symfony\Component\Form\AbstractTypeExtension;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormError;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Contracts\Translation\TranslatorInterface;
use Webmozart\Assert\Assert;

final class CartTypeExtension extends AbstractTypeExtension
{
public function __construct(
private ChannelContextInterface $channelContext,
private TranslatorInterface $translator,
) {
}

public function buildForm(FormBuilderInterface $builder, array $options): void
{
// This listener must run after the validation listener
$builder->addEventListener(FormEvents::POST_SUBMIT, function (FormEvent $event): void {
/** @var OrderInterface $order */
$order = $event->getData();

/** @var ChannelInterface $channel */
$channel = $this->channelContext->getChannel();

Assert::isInstanceOf($channel, ChannelInterface::class);

if (null === $channel->getMaxSamplesPerOrder() || 0 === $channel->getMaxSamplesPerOrder()) {
return;
}

$samples = 0;

/** @var OrderItemInterface $item */
foreach ($order->getItems() as $item) {
Assert::isInstanceOf($item->getVariant(), ProductVariantInterface::class);

if (null === $item->getVariant()->getSampleOf()) {
continue;
}

$samples += $item->getQuantity();
}

if ($samples > $channel->getMaxSamplesPerOrder()) {
$event->getForm()->addError(new FormError(
$this->translator->trans('babdev_sylius_product_samples.order.allowed_samples.plural_max_per_order', ['%count%' => $channel->getMaxSamplesPerOrder()], 'validators'),
null,
['{{ limit }}' => $channel->getMaxSamplesPerOrder()],
$channel->getMaxSamplesPerOrder(),
));
}
}, -10);
}

public static function getExtendedTypes(): iterable
{
return [CartType::class];
}
}
10 changes: 10 additions & 0 deletions src/Resources/config/services.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use BabDev\SyliusProductSamplesPlugin\EventListener\SampleVariantGeneratorListener;
use BabDev\SyliusProductSamplesPlugin\Form\Extension\AddToCartTypeExtension;
use BabDev\SyliusProductSamplesPlugin\Form\Extension\CartItemTypeExtension;
use BabDev\SyliusProductSamplesPlugin\Form\Extension\CartTypeExtension;
use BabDev\SyliusProductSamplesPlugin\Form\Extension\ChannelTypeExtension;
use BabDev\SyliusProductSamplesPlugin\Form\Extension\ProductTypeExtension;
use BabDev\SyliusProductSamplesPlugin\Form\Extension\ProductVariantTypeExtension;
Expand All @@ -24,6 +25,7 @@
use Sylius\Bundle\ChannelBundle\Form\Type\ChannelType;
use Sylius\Bundle\CoreBundle\Form\Type\Order\AddToCartType;
use Sylius\Bundle\OrderBundle\Form\Type\CartItemType;
use Sylius\Bundle\OrderBundle\Form\Type\CartType;
use Sylius\Bundle\ProductBundle\Form\Type\ProductType;
use Sylius\Bundle\ProductBundle\Form\Type\ProductVariantType;

Expand All @@ -48,6 +50,14 @@
->tag('form.type_extension', ['extended-type' => AddToCartType::class])
;

$services->set('babdev_sylius_product_samples.form.extension.cart', CartTypeExtension::class)
->args([
service('sylius.context.channel'),
service('translator'),
])
->tag('form.type_extension', ['extended-type' => CartType::class])
;

$services->set('babdev_sylius_product_samples.form.extension.cart_item_type', CartItemTypeExtension::class)
->tag('form.type_extension', ['extended-type' => CartItemType::class, 'priority' => -10]) // Needs to run after the extension in SyliusCoreBundle
;
Expand Down
1 change: 1 addition & 0 deletions src/Resources/translations/validators.en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ babdev_sylius_product_samples:
order:
allowed_samples:
max_per_order: 'Only 1 sample may be requested per order.|Only {{ limit }} samples may be requested per order.'
plural_max_per_order: '{1}Only 1 sample may be requested per order.|]1,Inf[Only %count% samples may be requested per order.'

0 comments on commit 40fad85

Please sign in to comment.