Skip to content

Commit

Permalink
Improve coupons validation
Browse files Browse the repository at this point in the history
  • Loading branch information
maximehuran committed Dec 18, 2023
1 parent 25b9c20 commit 7fdbc96
Show file tree
Hide file tree
Showing 11 changed files with 97 additions and 100 deletions.
2 changes: 1 addition & 1 deletion src/Entity/PromotionCouponsAwareInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

interface PromotionCouponsAwareInterface
{
/** @return Collection<array-key, PromotionCouponInterface> */
/** @return Collection<array-key, ?PromotionCouponInterface> */
public function getPromotionCoupons(): Collection;

public function hasPromotionCoupon(PromotionCouponInterface $promotionCoupon): bool;
Expand Down
2 changes: 1 addition & 1 deletion src/Entity/PromotionCouponsAwareTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ private function initializePromotionCoupons(): void
$this->promotionCoupons = new ArrayCollection();
}

/** @return Collection<array-key, PromotionCouponInterface> */
/** @return Collection<array-key, ?PromotionCouponInterface> */
public function getPromotionCoupons(): Collection
{
return $this->promotionCoupons;
Expand Down
22 changes: 21 additions & 1 deletion src/Form/Extension/CartTypeExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,15 @@

use Sylius\Bundle\OrderBundle\Form\Type\CartType;
use Sylius\Bundle\PromotionBundle\Form\Type\PromotionCouponToCodeType;
use Sylius\Component\Core\Model\PromotionCouponInterface;
use Symfony\Component\Form\AbstractTypeExtension;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\OptionsResolver\Options;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Context\ExecutionContextInterface;

final class CartTypeExtension extends AbstractTypeExtension
{
Expand All @@ -34,11 +37,16 @@ public function buildForm(FormBuilderInterface $builder, array $options): void
'attr' => [
'form' => 'sylius_cart',
],
'constraints' => [
new Assert\Callback(
[$this, 'validatePromotionEntry'],
['monsieurbiz_advanced_promotion_coupon']
),
],
],
'required' => false,
'allow_add' => true,
'allow_delete' => true,
'delete_empty' => true,
'button_add_label' => 'monsieurbiz_sylius_advanced_promotion.coupons.add_coupon',
'attr' => [
'class' => 'monsieurbiz-coupons',
Expand All @@ -47,6 +55,18 @@ public function buildForm(FormBuilderInterface $builder, array $options): void
;
}

public function validatePromotionEntry(?PromotionCouponInterface $entry, ExecutionContextInterface $context): void
{
if (null !== $entry) {
return;
}

$context
->buildViolation('sylius.promotion_coupon.is_invalid')
->addViolation()
;
}

/**
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
Expand Down
3 changes: 0 additions & 3 deletions src/Form/Type/PromotionCouponType.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,6 @@ public function buildForm(FormBuilderInterface $builder, array $options): void
'label' => 'sylius.form.cart.coupon',
'required' => false,
'by_reference' => false,
'attr' => [
'form' => 'sylius_cart',
],
])
;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public function isEligible(PromotionSubjectInterface $promotionSubject, Promotio
// Loop on order promotions with coupon to check if one is eligible
$promotionCoupons = $promotionSubject->getPromotionCoupons();
foreach ($promotionCoupons as $promotionCoupon) {
if ($promotion !== $promotionCoupon->getPromotion()) {
if (!$promotionCoupon || $promotion !== $promotionCoupon->getPromotion()) {
continue;
}

Expand Down
5 changes: 4 additions & 1 deletion src/Promotion/Modifier/OrderPromotionsUsageModifier.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ public function increment(OrderInterface $order): void
// Same as Sylius but with multiple coupons
// @see Sylius\Component\Core\Promotion\Modifier\OrderPromotionsUsageModifier
foreach ($order->getPromotionCoupons() as $promotionCoupon) {
if (!$promotionCoupon) {
continue;
}
$promotionCoupon->incrementUsed();
}
}
Expand All @@ -42,7 +45,7 @@ public function decrement(OrderInterface $order): void
// Same as Sylius but with multiple coupons
// @see Sylius\Component\Core\Promotion\Modifier\OrderPromotionsUsageModifier
foreach ($order->getPromotionCoupons() as $promotionCoupon) {
if (OrderInterface::STATE_CANCELLED === $order->getState() && !$promotionCoupon->isReusableFromCancelledOrders()) {
if (!$promotionCoupon || OrderInterface::STATE_CANCELLED === $order->getState() && !$promotionCoupon->isReusableFromCancelledOrders()) {
continue;
}

Expand Down
24 changes: 0 additions & 24 deletions src/Promotion/Validator/PromotionSubjectCoupons.php

This file was deleted.

58 changes: 0 additions & 58 deletions src/Promotion/Validator/PromotionSubjectCouponsValidator.php

This file was deleted.

8 changes: 0 additions & 8 deletions src/Resources/config/validation/Order.yaml

This file was deleted.

13 changes: 11 additions & 2 deletions src/Resources/views/Shop/Cart/Summary/_coupons.html.twig
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
{% form_theme form '@MonsieurBizSyliusAdvancedPromotionPlugin/Shop/Form/theme.html.twig' %}

{% if form.promotionCoupon.vars.value|default(null) %}
{% include '@SyliusShop/Cart/Summary/_coupon.html.twig' %}
{% else %}
<div id="sylius-coupon" {{ sylius_test_html_attribute('cart-promotion-coupon') }} style="display: flex; ">
<div class="ui coupon action input form">
{{ form_widget(form.promotionCoupons) }}
<br>
{{ form_errors(form.promotionCoupons) }}
</div>
<div>
<button type="submit" id="sylius-save" {{ sylius_test_html_attribute('apply-coupon-button') }} class="ui teal icon labeled button" form="{{ main_form }}">
Expand All @@ -15,6 +15,15 @@
</div>

<style>
.monsieurbiz-coupons [data-form-collection="list"] .ui.pointing {
margin-top: -3px !important;
margin-bottom: 10px !important;
}
.monsieurbiz-coupons [data-form-collection="list"] .ui.pointing::before {
display: none !important;
}
.monsieurbiz-coupons [data-form-collection="item"] {
display: flex;
flex-flow: nowrap;
Expand Down
58 changes: 58 additions & 0 deletions src/Resources/views/Shop/Form/theme.html.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
{% extends '@SyliusShop/Form/theme.html.twig' %}

{# No changes with Sylius form #}
{# We copied it to called our `collection_item` #}
{% block collection_widget -%}
{% from '@SyliusResource/Macros/notification.html.twig' import error %}
{% import _self as self %}
{% set attr = attr|merge({'class': attr.class|default ~ ' controls collection-widget'}) %}

{% apply spaceless %}
<div data-form-type="collection" {{ block('widget_container_attributes') }}
{% if prototype is defined and allow_add %}
data-prototype='{{ self.collection_item(prototype, allow_delete, button_delete_label, prototype.vars.name)|e }}'
data-prototype-name='{{ prototype.vars.name }}'
{%- endif -%}
>
{{ error(form.vars.errors) }}

{% if prototypes|default is iterable %}
{% for key, subPrototype in prototypes %}
<input type="hidden" data-form-prototype="{{ key }}"
value="{{ self.collection_item(subPrototype, allow_delete, button_delete_label, subPrototype.vars.name)|e }}"
data-subprototype-name="{{ subPrototype.vars.name }}"
/>
{% endfor %}
{% endif %}

<div data-form-collection="list">
{% for child in form %}
{{ self.collection_item(child, allow_delete, button_delete_label, loop.index0) }}
{% endfor %}
</div>

{% if prototype is defined and allow_add %}
<a href="#" class="ui labeled icon button" data-form-collection="add">
<i class="plus square outline icon"></i>
{{ button_add_label|trans }}
</a>
{% endif %}
</div>
{% endapply %}
{%- endblock collection_widget %}

{# Same as Sylius one but add `form_errors` #}
{% macro collection_item(form, allow_delete, button_delete_label, index) %}
{% apply spaceless %}
<div data-form-collection="item" data-form-collection-index="{{ index }}">
{{ form_widget(form) }}
{% if allow_delete %}
<a href="#" data-form-collection="delete" class="ui red labeled icon button" style="margin-bottom: 1em;">
<i class="trash icon"></i>
{{ button_delete_label|trans }}
</a>
{% endif %}
{{ form_errors(form) }} {# Add this line to show error #}
</div>
{% endapply %}
{% endmacro %}

0 comments on commit 7fdbc96

Please sign in to comment.