Merge branch '1.13' into 2.0

* 1.13:
  [PromotionBundle] Add prefix to validation groups for promotion action/rule
  [PromotionBundle][PromotionRule] Add available type to validation message
  [PromotionBundle][PromotionAction] Add available type to validation message
  Update upgrade file
  [PromotionBundle] Split PromotionRuleValidator to PromotionRuleGroupValidator and PromotionRuleTypeValidator
  [PromotionBundle] Split PromotionActionValidator to PromotionActionGroupValidator and PromotionActionTypeValidator
  Add prefix sylius_ to validation groups
  Update upgrade file
  [PromotionBundle] Remove constraints from FormType to avoid double constraints
  [PromotionBundle] Move logic from PromotionRuleGroupValidator to PromotionRuleValidator
  [PromotionBundle] Move logic from PromotionActionGroupValidator to PromotionActionValidator
  [PromotionBundle] Add parameters validation groups for promotion action and promotion rule
This commit is contained in:
Grzegorz Sadowski 2023-12-15 14:10:11 +01:00
commit fe77e9782d
No known key found for this signature in database
GPG key ID: EF87FF4E6E3BD364
34 changed files with 330 additions and 191 deletions

View file

@ -22,6 +22,51 @@ sylius_payum:
- 'sylius'
- 'stripe_checkout'
sylius_promotion:
promotion_action:
validation_groups:
order_percentage_discount:
- 'sylius'
- 'sylius_promotion_action_order_percentage_discount'
shipping_percentage_discount:
- 'sylius'
- 'sylius_promotion_action_shipping_percentage_discount'
order_fixed_discount:
- 'sylius'
- 'sylius_promotion_action_order_fixed_discount'
unit_fixed_discount:
- 'sylius'
- 'sylius_promotion_action_unit_fixed_discount'
unit_percentage_discount:
- 'sylius'
- 'sylius_promotion_action_unit_percentage_discount'
promotion_rule:
validation_groups:
cart_quantity:
- 'sylius'
- 'sylius_promotion_rule_cart_quantity'
customer_group:
- 'sylius'
- 'sylius_promotion_rule_customer_group'
nth_order:
- 'sylius'
- 'sylius_promotion_rule_nth_order'
shipping_country:
- 'sylius'
- 'sylius_promotion_rule_shipping_country'
has_taxon:
- 'sylius'
- 'sylius_promotion_rule_has_taxon'
total_of_items_from_taxon:
- 'sylius'
- 'sylius_promotion_rule_total_of_items_from_taxon'
contains_product:
- 'sylius'
- 'sylius_promotion_rule_contains_product'
item_total:
- 'sylius'
- 'sylius_promotion_rule_item_total'
sylius_shop:
product_grid:
include_all_descendants: true

View file

@ -188,13 +188,5 @@
<argument type="service" id="Sylius\Bundle\ApiBundle\Validator\CatalogPromotion\ForVariantsScopeValidator.inner" />
<argument type="service" id="Sylius\Bundle\CoreBundle\SectionResolver\SectionProviderInterface" />
</service>
<service id="Sylius\Bundle\ApiBundle\Validator\Constraints\PromotionActionGroupValidator">
<tag name="validator.constraint_validator" alias="sylius_promotion_action_group" />
</service>
<service id="Sylius\Bundle\ApiBundle\Validator\Constraints\PromotionRuleGroupValidator">
<tag name="validator.constraint_validator" alias="sylius_promotion_rule_group" />
</service>
</services>
</container>

View file

@ -33,10 +33,6 @@ final class ContainsProductConfigurationType extends AbstractType
$builder
->add('product_code', ProductAutocompleteChoiceType::class, [
'label' => 'sylius.form.promotion_action.add_product_configuration.product',
'constraints' => [
new NotBlank(['groups' => ['sylius']]),
new Type(['type' => 'string', 'groups' => ['sylius']]),
],
])
;

View file

@ -26,10 +26,6 @@ final class NthOrderConfigurationType extends AbstractType
$builder
->add('nth', IntegerType::class, [
'label' => 'sylius.form.promotion_rule.nth_order_configuration.nth',
'constraints' => [
new NotBlank(['groups' => ['sylius']]),
new Type(['type' => 'numeric', 'groups' => ['sylius']]),
],
])
;
}

View file

@ -13,56 +13,55 @@
<constraint-mapping xmlns="http://symfony.com/schema/dic/constraint-mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/constraint-mapping http://symfony.com/schema/dic/services/constraint-mapping-1.0.xsd">
<class name="Sylius\Component\Promotion\Model\PromotionAction">
<constraint name="Sylius\Bundle\ApiBundle\Validator\Constraints\PromotionActionGroup">
<option name="groups">sylius_api</option>
</constraint>
<property name="configuration">
<constraint name="Collection">
<option name="allowExtraFields">true</option>
<option name="groups">
<value>order_percentage_discount</value>
<value>shipping_percentage_discount</value>
<value>sylius_promotion_action_order_percentage_discount</value>
<value>sylius_promotion_action_shipping_percentage_discount</value>
</option>
<option name="fields">
<value key="percentage">
<constraint name="NotBlank">
<option name="groups">
<value>order_percentage_discount</value>
<value>shipping_percentage_discount</value>
<value>sylius_promotion_action_order_percentage_discount</value>
<value>sylius_promotion_action_shipping_percentage_discount</value>
</option>
</constraint>
<constraint name="Type">
<option name="groups">
<value>order_percentage_discount</value>
<value>shipping_percentage_discount</value>
</option>
<option name="type">numeric</option>
<option name="groups">
<value>sylius_promotion_action_order_percentage_discount</value>
<value>sylius_promotion_action_shipping_percentage_discount</value>
</option>
</constraint>
<constraint name="Range">
<option name="groups">
<value>order_percentage_discount</value>
<value>shipping_percentage_discount</value>
</option>
<option name="min">0</option>
<option name="max">1</option>
<option name="notInRangeMessage">sylius.promotion_action.percentage_discount_configuration.not_in_range</option>
<option name="groups">
<value>sylius_promotion_action_order_percentage_discount</value>
<value>sylius_promotion_action_shipping_percentage_discount</value>
</option>
</constraint>
</value>
</option>
</constraint>
<constraint name="Sylius\Bundle\CoreBundle\Validator\Constraints\ChannelCodeCollection">
<option name="groups">order_fixed_discount</option>
<option name="allowExtraFields">true</option>
<option name="groups">sylius_promotion_action_order_fixed_discount</option>
<option name="constraints">
<constraint name="Collection">
<option name="allowExtraFields">true</option>
<option name="fields">
<value key="amount">
<constraint name="NotBlank">
<option name="groups">order_fixed_discount</option>
<option name="groups">sylius_promotion_action_order_fixed_discount</option>
</constraint>
<constraint name="Type">
<option name="groups">order_fixed_discount</option>
<option name="type">numeric</option>
<option name="groups">sylius_promotion_action_order_fixed_discount</option>
</constraint>
</value>
</option>
@ -71,17 +70,19 @@
</constraint>
<constraint name="Sylius\Bundle\CoreBundle\Validator\Constraints\ChannelCodeCollection">
<option name="groups">unit_fixed_discount</option>
<option name="allowExtraFields">true</option>
<option name="groups">sylius_promotion_action_unit_fixed_discount</option>
<option name="constraints">
<constraint name="Collection">
<option name="allowExtraFields">true</option>
<option name="fields">
<value key="amount">
<constraint name="NotBlank">
<option name="groups">unit_fixed_discount</option>
<option name="groups">sylius_promotion_action_unit_fixed_discount</option>
</constraint>
<constraint name="Type">
<option name="groups">unit_fixed_discount</option>
<option name="type">numeric</option>
<option name="groups">sylius_promotion_action_unit_fixed_discount</option>
</constraint>
</value>
<value key="filters">
@ -95,16 +96,16 @@
<value key="min">
<constraint name="Optional">
<constraint name="Type">
<option name="groups">unit_fixed_discount</option>
<option name="type">numeric</option>
<option name="groups">sylius_promotion_action_unit_fixed_discount</option>
</constraint>
</constraint>
</value>
<value key="max">
<constraint name="Optional">
<constraint name="Type">
<option name="groups">unit_fixed_discount</option>
<option name="type">numeric</option>
<option name="groups">sylius_promotion_action_unit_fixed_discount</option>
</constraint>
</constraint>
</value>
@ -119,13 +120,13 @@
<value key="taxons">
<constraint name="Optional">
<constraint name="All">
<option name="groups">unit_fixed_discount</option>
<option name="groups">sylius_promotion_action_unit_fixed_discount</option>
<option name="constraints">
<constraint name="NotBlank">
<option name="groups">unit_fixed_discount</option>
<option name="groups">sylius_promotion_action_unit_fixed_discount</option>
</constraint>
<constraint name="Sylius\Bundle\CoreBundle\Validator\Constraints\TaxonCodeExists">
<option name="groups">unit_fixed_discount</option>
<option name="groups">sylius_promotion_action_unit_fixed_discount</option>
</constraint>
</option>
</constraint>
@ -142,13 +143,13 @@
<value key="products">
<constraint name="Optional">
<constraint name="All">
<option name="groups">unit_fixed_discount</option>
<option name="groups">sylius_promotion_action_unit_fixed_discount</option>
<option name="constraints">
<constraint name="NotBlank">
<option name="groups">unit_fixed_discount</option>
<option name="groups">sylius_promotion_action_unit_fixed_discount</option>
</constraint>
<constraint name="Sylius\Bundle\CoreBundle\Validator\Constraints\ProductCodeExists">
<option name="groups">unit_fixed_discount</option>
<option name="groups">sylius_promotion_action_unit_fixed_discount</option>
</constraint>
</option>
</constraint>
@ -168,23 +169,25 @@
</constraint>
<constraint name="Sylius\Bundle\CoreBundle\Validator\Constraints\ChannelCodeCollection">
<option name="groups">unit_percentage_discount</option>
<option name="allowExtraFields">true</option>
<option name="groups">sylius_promotion_action_unit_percentage_discount</option>
<option name="constraints">
<constraint name="Collection">
<option name="allowExtraFields">true</option>
<option name="fields">
<value key="percentage">
<constraint name="NotBlank">
<option name="groups">unit_percentage_discount</option>
<option name="groups">sylius_promotion_action_unit_percentage_discount</option>
</constraint>
<constraint name="Type">
<option name="groups">unit_percentage_discount</option>
<option name="type">numeric</option>
<option name="groups">sylius_promotion_action_unit_percentage_discount</option>
</constraint>
<constraint name="Range">
<option name="groups">unit_percentage_discount</option>
<option name="min">0</option>
<option name="max">1</option>
<option name="notInRangeMessage">sylius.promotion_action.percentage_discount_configuration.not_in_range</option>
<option name="groups">sylius_promotion_action_unit_percentage_discount</option>
</constraint>
</value>
<value key="filters">
@ -198,16 +201,16 @@
<value key="min">
<constraint name="Optional">
<constraint name="Type">
<option name="groups">unit_percentage_discount</option>
<option name="type">numeric</option>
<option name="groups">sylius_promotion_action_unit_percentage_discount</option>
</constraint>
</constraint>
</value>
<value key="max">
<constraint name="Optional">
<constraint name="Type">
<option name="groups">unit_percentage_discount</option>
<option name="type">numeric</option>
<option name="groups">sylius_promotion_action_unit_percentage_discount</option>
</constraint>
</constraint>
</value>
@ -222,13 +225,13 @@
<value key="taxons">
<constraint name="Optional">
<constraint name="All">
<option name="groups">unit_percentage_discount</option>
<option name="groups">sylius_promotion_action_unit_percentage_discount</option>
<option name="constraints">
<constraint name="NotBlank">
<option name="groups">unit_percentage_discount</option>
<option name="groups">sylius_promotion_action_unit_percentage_discount</option>
</constraint>
<constraint name="Sylius\Bundle\CoreBundle\Validator\Constraints\TaxonCodeExists">
<option name="groups">unit_percentage_discount</option>
<option name="groups">sylius_promotion_action_unit_percentage_discount</option>
</constraint>
</option>
</constraint>
@ -245,13 +248,13 @@
<value key="products">
<constraint name="Optional">
<constraint name="All">
<option name="groups">unit_percentage_discount</option>
<option name="groups">sylius_promotion_action_unit_percentage_discount</option>
<option name="constraints">
<constraint name="NotBlank">
<option name="groups">unit_percentage_discount</option>
<option name="groups">sylius_promotion_action_unit_percentage_discount</option>
</constraint>
<constraint name="Sylius\Bundle\CoreBundle\Validator\Constraints\ProductCodeExists">
<option name="groups">unit_percentage_discount</option>
<option name="groups">sylius_promotion_action_unit_percentage_discount</option>
</constraint>
</option>
</constraint>

View file

@ -13,89 +13,90 @@
<constraint-mapping xmlns="http://symfony.com/schema/dic/constraint-mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/constraint-mapping http://symfony.com/schema/dic/services/constraint-mapping-1.0.xsd">
<class name="Sylius\Component\Promotion\Model\PromotionRule">
<constraint name="Sylius\Bundle\ApiBundle\Validator\Constraints\PromotionRuleGroup">
<option name="groups">sylius_api</option>
</constraint>
<property name="configuration">
<constraint name="Collection">
<option name="groups">cart_quantity</option>
<option name="allowExtraFields">true</option>
<option name="groups">sylius_promotion_rule_cart_quantity</option>
<option name="fields">
<value key="count">
<constraint name="NotBlank">
<option name="groups">cart_quantity</option>
<option name="groups">sylius_promotion_rule_cart_quantity</option>
</constraint>
<constraint name="Type">
<option name="groups">cart_quantity</option>
<option name="type">numeric</option>
<option name="groups">sylius_promotion_rule_cart_quantity</option>
</constraint>
</value>
</option>
</constraint>
<constraint name="Collection">
<option name="groups">customer_group</option>
<option name="allowExtraFields">true</option>
<option name="groups">sylius_promotion_rule_customer_group</option>
<option name="fields">
<value key="group_code">
<constraint name="NotBlank">
<option name="groups">customer_group</option>
<option name="groups">sylius_promotion_rule_customer_group</option>
</constraint>
<constraint name="Type">
<option name="groups">customer_group</option>
<option name="type">string</option>
<option name="groups">sylius_promotion_rule_customer_group</option>
</constraint>
<constraint name="Sylius\Bundle\CoreBundle\Validator\Constraints\CustomerGroupCodeExists">
<option name="groups">customer_group</option>
<option name="groups">sylius_promotion_rule_customer_group</option>
</constraint>
</value>
</option>
</constraint>
<constraint name="Collection">
<option name="groups">nth_order</option>
<option name="allowExtraFields">true</option>
<option name="groups">sylius_promotion_rule_nth_order</option>
<option name="fields">
<value key="nth">
<constraint name="NotBlank">
<option name="groups">nth_order</option>
<option name="groups">sylius_promotion_rule_nth_order</option>
</constraint>
<constraint name="Type">
<option name="groups">nth_order</option>
<option name="type">numeric</option>
<option name="groups">sylius_promotion_rule_nth_order</option>
</constraint>
</value>
</option>
</constraint>
<constraint name="Collection">
<option name="groups">shipping_country</option>
<option name="allowExtraFields">true</option>
<option name="groups">sylius_promotion_rule_shipping_country</option>
<option name="fields">
<value key="country">
<constraint name="NotBlank">
<option name="groups">shipping_country</option>
<option name="groups">sylius_promotion_rule_shipping_country</option>
</constraint>
<constraint name="Type">
<option name="groups">shipping_country</option>
<option name="type">string</option>
<option name="groups">sylius_promotion_rule_shipping_country</option>
</constraint>
<constraint name="Sylius\Bundle\CoreBundle\Validator\Constraints\CountryCodeExists">
<option name="groups">shipping_country</option>
<option name="groups">sylius_promotion_rule_shipping_country</option>
</constraint>
</value>
</option>
</constraint>
<constraint name="Collection">
<option name="groups">has_taxon</option>
<option name="allowExtraFields">true</option>
<option name="groups">sylius_promotion_rule_has_taxon</option>
<option name="fields">
<value key="taxons">
<constraint name="All">
<option name="groups">has_taxon</option>
<option name="groups">sylius_promotion_rule_has_taxon</option>
<option name="constraints">
<constraint name="NotBlank">
<option name="groups">has_taxon</option>
<option name="groups">sylius_promotion_rule_has_taxon</option>
</constraint>
<constraint name="Sylius\Bundle\CoreBundle\Validator\Constraints\TaxonCodeExists">
<option name="groups">has_taxon</option>
<option name="groups">sylius_promotion_rule_has_taxon</option>
</constraint>
</option>
</constraint>
@ -104,25 +105,27 @@
</constraint>
<constraint name="Sylius\Bundle\CoreBundle\Validator\Constraints\ChannelCodeCollection">
<option name="groups">total_of_items_from_taxon</option>
<option name="allowExtraFields">true</option>
<option name="groups">sylius_promotion_rule_total_of_items_from_taxon</option>
<option name="constraints">
<constraint name="Collection">
<option name="allowExtraFields">true</option>
<option name="fields">
<value key="amount">
<constraint name="Required">
<constraint name="NotBlank">
<option name="groups">total_of_items_from_taxon</option>
<option name="groups">sylius_promotion_rule_total_of_items_from_taxon</option>
</constraint>
<constraint name="Type">
<option name="groups">total_of_items_from_taxon</option>
<option name="type">numeric</option>
<option name="groups">sylius_promotion_rule_total_of_items_from_taxon</option>
</constraint>
</constraint>
</value>
<value key="taxon">
<constraint name="Optional">
<constraint name="Sylius\Bundle\CoreBundle\Validator\Constraints\TaxonCodeExists">
<option name="groups">total_of_items_from_taxon</option>
<option name="groups">sylius_promotion_rule_total_of_items_from_taxon</option>
</constraint>
</constraint>
</value>
@ -132,35 +135,38 @@
</constraint>
<constraint name="Collection">
<option name="groups">contains_product</option>
<option name="allowExtraFields">true</option>
<option name="groups">sylius_promotion_rule_contains_product</option>
<option name="fields">
<value key="product_code">
<constraint name="NotBlank">
<option name="groups">contains_product</option>
<option name="groups">sylius_promotion_rule_contains_product</option>
</constraint>
<constraint name="Type">
<option name="groups">contains_product</option>
<option name="type">string</option>
<option name="groups">sylius_promotion_rule_contains_product</option>
</constraint>
<constraint name="Sylius\Bundle\CoreBundle\Validator\Constraints\ProductCodeExists">
<option name="groups">contains_product</option>
<option name="groups">sylius_promotion_rule_contains_product</option>
</constraint>
</value>
</option>
</constraint>
<constraint name="Sylius\Bundle\CoreBundle\Validator\Constraints\ChannelCodeCollection">
<option name="groups">item_total</option>
<option name="allowExtraFields">true</option>
<option name="groups">sylius_promotion_rule_item_total</option>
<option name="constraints">
<constraint name="Collection">
<option name="allowExtraFields">true</option>
<option name="fields">
<value key="amount">
<constraint name="NotBlank">
<option name="groups">item_total</option>
<option name="groups">sylius_promotion_rule_item_total</option>
</constraint>
<constraint name="Type">
<option name="groups">item_total</option>
<option name="type">numeric</option>
<option name="groups">sylius_promotion_rule_item_total</option>
</constraint>
</value>
</option>

View file

@ -58,6 +58,24 @@ final class Configuration implements ConfigurationInterface
$rootNode
->addDefaultsIfNotSet()
->children()
->arrayNode('promotion_action')
->addDefaultsIfNotSet()
->children()
->arrayNode('validation_groups')
->useAttributeAsKey('name')
->variablePrototype()->end()
->end()
->end()
->end()
->arrayNode('promotion_rule')
->addDefaultsIfNotSet()
->children()
->arrayNode('validation_groups')
->useAttributeAsKey('name')
->variablePrototype()->end()
->end()
->end()
->end()
->scalarNode('driver')->defaultValue(SyliusResourceBundle::DRIVER_DOCTRINE_ORM)->end()
->end()
;

View file

@ -33,6 +33,9 @@ final class SyliusPromotionExtension extends AbstractResourceExtension
$loader->load('services.xml');
$loader->load(sprintf('services/integrations/%s.xml', $config['driver']));
$container->setParameter('sylius.promotion.promotion_action.validation_groups', $config['promotion_action']['validation_groups']);
$container->setParameter('sylius.promotion.promotion_rule.validation_groups', $config['promotion_rule']['validation_groups']);
$this->registerResources('sylius', $config['driver'], $config['resources'], $container);
$this->registerAutoconfiguration($container);
}

View file

@ -27,10 +27,6 @@ final class FixedDiscountConfigurationType extends AbstractType
$builder
->add('amount', MoneyType::class, [
'label' => 'sylius.form.promotion_action.fixed_discount_configuration.amount',
'constraints' => [
new NotBlank(['groups' => ['sylius']]),
new Type(['type' => 'numeric', 'groups' => ['sylius']]),
],
'currency' => $options['currency'],
])
;

View file

@ -29,16 +29,6 @@ final class PercentageDiscountConfigurationType extends AbstractType
'label' => 'sylius.form.promotion_action.percentage_discount_configuration.percentage',
'html5' => true,
'scale' => 2,
'constraints' => [
new NotBlank(['groups' => ['sylius']]),
new Type(['type' => 'numeric', 'groups' => ['sylius']]),
new Range([
'min' => 0,
'max' => 1,
'notInRangeMessage' => 'sylius.promotion_action.percentage_discount_configuration.not_in_range',
'groups' => ['sylius'],
]),
],
])
;
}

View file

@ -28,10 +28,6 @@ final class UnitFixedDiscountConfigurationType extends AbstractType
$builder
->add('amount', MoneyType::class, [
'label' => 'sylius.form.promotion_action.fixed_discount_configuration.amount',
'constraints' => [
new NotBlank(['groups' => ['sylius']]),
new Type(['type' => 'numeric', 'groups' => ['sylius']]),
],
'currency' => $options['currency'],
])
->add('filters', PromotionFilterCollectionType::class, [

View file

@ -31,16 +31,6 @@ final class UnitPercentageDiscountConfigurationType extends AbstractType
'label' => 'sylius.form.promotion_action.percentage_discount_configuration.percentage',
'html5' => true,
'scale' => 2,
'constraints' => [
new NotBlank(['groups' => ['sylius']]),
new Type(['type' => 'numeric', 'groups' => ['sylius']]),
new Range([
'min' => 0,
'max' => 1,
'notInRangeMessage' => 'sylius.promotion_action.percentage_discount_configuration.not_in_range',
'groups' => ['sylius'],
]),
],
])
->add('filters', PromotionFilterCollectionType::class, [
'label' => 'sylius.form.promotion_action.filters',

View file

@ -26,10 +26,6 @@ final class CartQuantityConfigurationType extends AbstractType
$builder
->add('count', IntegerType::class, [
'label' => 'sylius.form.promotion_rule.cart_quantity_configuration.count',
'constraints' => [
new NotBlank(['groups' => ['sylius']]),
new Type(['type' => 'numeric', 'groups' => ['sylius']]),
],
])
;
}

View file

@ -27,10 +27,6 @@ final class ItemTotalConfigurationType extends AbstractType
$builder
->add('amount', MoneyType::class, [
'label' => 'sylius.form.promotion_rule.item_total_configuration.amount',
'constraints' => [
new NotBlank(['groups' => ['sylius']]),
new Type(['type' => 'numeric', 'groups' => ['sylius']]),
],
'currency' => $options['currency'],
])
;

View file

@ -41,14 +41,24 @@
<tag name="validator.constraint_validator" alias="sylius_catalog_promotion_scope" />
</service>
<service id="Sylius\Bundle\PromotionBundle\Validator\PromotionActionValidator">
<argument>%sylius.promotion_actions%</argument>
<tag name="validator.constraint_validator" alias="sylius_promotion_action" />
<service id="Sylius\Bundle\PromotionBundle\Validator\PromotionActionGroupValidator">
<argument>%sylius.promotion.promotion_action.validation_groups%</argument>
<tag name="validator.constraint_validator" alias="sylius_promotion_action_group" />
</service>
<service id="Sylius\Bundle\PromotionBundle\Validator\PromotionRuleValidator">
<service id="Sylius\Bundle\PromotionBundle\Validator\PromotionActionTypeValidator">
<argument>%sylius.promotion_actions%</argument>
<tag name="validator.constraint_validator" alias="sylius_promotion_action_type" />
</service>
<service id="Sylius\Bundle\PromotionBundle\Validator\PromotionRuleGroupValidator">
<argument>%sylius.promotion.promotion_rule.validation_groups%</argument>
<tag name="validator.constraint_validator" alias="sylius_promotion_rule_group" />
</service>
<service id="Sylius\Bundle\PromotionBundle\Validator\PromotionRuleTypeValidator">
<argument>%sylius.promotion_rules%</argument>
<tag name="validator.constraint_validator" alias="sylius_promotion_rule" />
<tag name="validator.constraint_validator" alias="sylius_promotion_rule_type" />
</service>
<service id="Sylius\Bundle\PromotionBundle\Validator\PromotionNotCouponBasedValidator">

View file

@ -13,7 +13,10 @@
<constraint-mapping xmlns="http://symfony.com/schema/dic/constraint-mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/constraint-mapping http://symfony.com/schema/dic/services/constraint-mapping-1.0.xsd">
<class name="Sylius\Component\Promotion\Model\PromotionAction">
<constraint name="Sylius\Bundle\PromotionBundle\Validator\Constraints\PromotionAction">
<constraint name="Sylius\Bundle\PromotionBundle\Validator\Constraints\PromotionActionGroup">
<option name="groups">sylius</option>
</constraint>
<constraint name="Sylius\Bundle\PromotionBundle\Validator\Constraints\PromotionActionType">
<option name="groups">sylius</option>
</constraint>
</class>

View file

@ -13,7 +13,10 @@
<constraint-mapping xmlns="http://symfony.com/schema/dic/constraint-mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/constraint-mapping http://symfony.com/schema/dic/services/constraint-mapping-1.0.xsd">
<class name="Sylius\Component\Promotion\Model\PromotionRule">
<constraint name="Sylius\Bundle\PromotionBundle\Validator\Constraints\PromotionRule">
<constraint name="Sylius\Bundle\PromotionBundle\Validator\Constraints\PromotionRuleType">
<option name="groups">sylius</option>
</constraint>
<constraint name="Sylius\Bundle\PromotionBundle\Validator\Constraints\PromotionRuleGroup">
<option name="groups">sylius</option>
</constraint>
</class>

View file

@ -37,8 +37,11 @@ sylius:
min_length: Promotion name must be at least 1 character long.|Promotion name must be at least {{ limit }} characters long.
not_blank: Please enter promotion name.
promotion_action:
invalid_type: Promotion action type is invalid. Available action types are {{ available_action_types }}.
percentage_discount_configuration:
not_in_range: The percentage discount must be between 0% and 100%.
promotion_rule:
invalid_type: Promotion rule type is invalid. Available rule types are {{ available_rule_types }}.
promotion_coupon:
code:
max_length: Coupon code must not be longer than 1 character.|Coupon code must not be longer than {{ limit }} characters.

View file

@ -117,6 +117,42 @@ final class SyliusPromotionExtensionTest extends AbstractExtensionTestCase
);
}
/** @test */
public function it_loads_promotion_action_validation_groups_parameter_value_properly(): void
{
$this->load([
'promotion_action' => [
'validation_groups' => [
'order_percentage_discount' => ['sylius', 'order_percentage_discount'],
'order_fixed_discount' => ['sylius', 'order_fixed_discount']
]
]
]);
$this->assertContainerBuilderHasParameter(
'sylius.promotion.promotion_action.validation_groups',
['order_percentage_discount' => ['sylius', 'order_percentage_discount'], 'order_fixed_discount' => ['sylius', 'order_fixed_discount']]
);
}
/** @test */
public function it_loads_promotion_rule_validation_groups_parameter_value_properly(): void
{
$this->load([
'promotion_rule' => [
'validation_groups' => [
'cart_quantity' => ['sylius', 'cart_quantity'],
'nth_order' => ['sylius', 'nth_order']
]
]
]);
$this->assertContainerBuilderHasParameter(
'sylius.promotion.promotion_rule.validation_groups',
['cart_quantity' => ['sylius', 'cart_quantity'], 'nth_order' => ['sylius', 'nth_order']]
);
}
protected function getContainerExtensions(): array
{
return [new SyliusPromotionExtension()];

View file

@ -11,11 +11,10 @@
declare(strict_types=1);
namespace Sylius\Bundle\ApiBundle\Validator\Constraints;
namespace Sylius\Bundle\PromotionBundle\Validator\Constraints;
use Symfony\Component\Validator\Constraint;
/** @experimental */
final class PromotionActionGroup extends Constraint
{
public function validatedBy(): string

View file

@ -15,13 +15,13 @@ namespace Sylius\Bundle\PromotionBundle\Validator\Constraints;
use Symfony\Component\Validator\Constraint;
final class PromotionAction extends Constraint
final class PromotionActionType extends Constraint
{
public string $invalidType = 'sylius.promotion_action.invalid_type';
public function validatedBy(): string
{
return 'sylius_promotion_action';
return 'sylius_promotion_action_type';
}
public function getTargets(): string

View file

@ -11,11 +11,10 @@
declare(strict_types=1);
namespace Sylius\Bundle\ApiBundle\Validator\Constraints;
namespace Sylius\Bundle\PromotionBundle\Validator\Constraints;
use Symfony\Component\Validator\Constraint;
/** @experimental */
final class PromotionRuleGroup extends Constraint
{
public function validatedBy(): string

View file

@ -15,13 +15,13 @@ namespace Sylius\Bundle\PromotionBundle\Validator\Constraints;
use Symfony\Component\Validator\Constraint;
final class PromotionRule extends Constraint
final class PromotionRuleType extends Constraint
{
public string $invalidType = 'sylius.promotion_rule.invalid_type';
public function validatedBy(): string
{
return 'sylius_promotion_rule';
return 'sylius_promotion_rule_type';
}
public function getTargets(): string

View file

@ -11,17 +11,22 @@
declare(strict_types=1);
namespace Sylius\Bundle\ApiBundle\Validator\Constraints;
namespace Sylius\Bundle\PromotionBundle\Validator;
use Sylius\Bundle\PromotionBundle\Validator\Constraints\PromotionActionGroup;
use Sylius\Component\Promotion\Model\PromotionActionInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
use Symfony\Component\Validator\Exception\UnexpectedValueException;
/** @experimental */
final class PromotionActionGroupValidator extends ConstraintValidator
{
/** @param array<string, array<string, string>> $validationGroups */
public function __construct(private array $validationGroups)
{
}
public function validate(mixed $value, Constraint $constraint): void
{
if (!$constraint instanceof PromotionActionGroup) {
@ -33,7 +38,7 @@ final class PromotionActionGroupValidator extends ConstraintValidator
}
/** @var string[] $groups */
$groups = array_merge($constraint->groups, [$value->getType()]);
$groups = $this->validationGroups[$value->getType()] ?? $constraint->groups;
$validator = $this->context->getValidator()->inContext($this->context);
$validator->validate(value: $value, groups: $groups);
}

View file

@ -13,14 +13,14 @@ declare(strict_types=1);
namespace Sylius\Bundle\PromotionBundle\Validator;
use Sylius\Bundle\PromotionBundle\Validator\Constraints\PromotionAction;
use Sylius\Bundle\PromotionBundle\Validator\Constraints\PromotionActionType;
use Sylius\Component\Promotion\Model\PromotionActionInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
use Symfony\Component\Validator\Exception\UnexpectedValueException;
final class PromotionActionValidator extends ConstraintValidator
final class PromotionActionTypeValidator extends ConstraintValidator
{
/** @param array<string, string> $actionTypes */
public function __construct(private array $actionTypes)
@ -29,17 +29,19 @@ final class PromotionActionValidator extends ConstraintValidator
public function validate(mixed $value, Constraint $constraint): void
{
if (!$constraint instanceof PromotionAction) {
throw new UnexpectedTypeException($constraint, PromotionAction::class);
if (!$constraint instanceof PromotionActionType) {
throw new UnexpectedTypeException($constraint, PromotionActionType::class);
}
if (!$value instanceof PromotionActionInterface) {
throw new UnexpectedValueException($value, PromotionActionInterface::class);
}
$type = $value->getType();
if (!array_key_exists($type, $this->actionTypes)) {
$this->context->buildViolation($constraint->invalidType)->atPath('type')->addViolation();
if (!array_key_exists($value->getType(), $this->actionTypes)) {
$this->context->buildViolation($constraint->invalidType)
->setParameter('{{ available_action_types }}', implode(', ', array_keys($this->actionTypes)))
->atPath('type')
->addViolation();
}
}
}

View file

@ -11,17 +11,22 @@
declare(strict_types=1);
namespace Sylius\Bundle\ApiBundle\Validator\Constraints;
namespace Sylius\Bundle\PromotionBundle\Validator;
use Sylius\Bundle\PromotionBundle\Validator\Constraints\PromotionRuleGroup;
use Sylius\Component\Promotion\Model\PromotionRuleInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
use Symfony\Component\Validator\Exception\UnexpectedValueException;
/** @experimental */
final class PromotionRuleGroupValidator extends ConstraintValidator
{
/** @param array<string, array<string, string>> $validationGroups */
public function __construct(private array $validationGroups)
{
}
public function validate(mixed $value, Constraint $constraint): void
{
if (!$constraint instanceof PromotionRuleGroup) {
@ -33,7 +38,7 @@ final class PromotionRuleGroupValidator extends ConstraintValidator
}
/** @var string[] $groups */
$groups = array_merge($constraint->groups, [$value->getType()]);
$groups = $this->validationGroups[$value->getType()] ?? $constraint->groups;
$validator = $this->context->getValidator()->inContext($this->context);
$validator->validate(value: $value, groups: $groups);
}

View file

@ -13,14 +13,14 @@ declare(strict_types=1);
namespace Sylius\Bundle\PromotionBundle\Validator;
use Sylius\Bundle\PromotionBundle\Validator\Constraints\PromotionRule;
use Sylius\Bundle\PromotionBundle\Validator\Constraints\PromotionRuleType;
use Sylius\Component\Promotion\Model\PromotionRuleInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
use Symfony\Component\Validator\Exception\UnexpectedValueException;
final class PromotionRuleValidator extends ConstraintValidator
final class PromotionRuleTypeValidator extends ConstraintValidator
{
/** @param array<string, string> $ruleTypes */
public function __construct(private array $ruleTypes)
@ -29,17 +29,19 @@ final class PromotionRuleValidator extends ConstraintValidator
public function validate(mixed $value, Constraint $constraint): void
{
if (!$constraint instanceof PromotionRule) {
throw new UnexpectedTypeException($constraint, PromotionRule::class);
if (!$constraint instanceof PromotionRuleType) {
throw new UnexpectedTypeException($constraint, PromotionRuleType::class);
}
if (!$value instanceof PromotionRuleInterface) {
throw new UnexpectedValueException($value, PromotionRuleInterface::class);
}
$type = $value->getType();
if (!array_key_exists($type, $this->ruleTypes)) {
$this->context->buildViolation($constraint->invalidType)->atPath('type')->addViolation();
if (!array_key_exists($value->getType(), $this->ruleTypes)) {
$this->context->buildViolation($constraint->invalidType)
->setParameter('{{ available_rule_types }}', implode(', ', array_keys($this->ruleTypes)))
->atPath('type')
->addViolation();
}
}
}

View file

@ -11,11 +11,10 @@
declare(strict_types=1);
namespace spec\Sylius\Bundle\ApiBundle\Validator\Constraints;
namespace spec\Sylius\Bundle\PromotionBundle\Validator;
use PhpSpec\ObjectBehavior;
use Sylius\Bundle\ApiBundle\Validator\Constraints\PromotionActionGroup;
use Sylius\Component\Core\Model\PromotionInterface;
use Sylius\Bundle\PromotionBundle\Validator\Constraints\PromotionActionGroup;
use Sylius\Component\Promotion\Model\PromotionActionInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
@ -28,6 +27,8 @@ final class PromotionActionGroupValidatorSpec extends ObjectBehavior
{
function let(ExecutionContextInterface $context): void
{
$this->beConstructedWith(['action_two' => ['Default', 'action_two']]);
$this->initialize($context);
}
@ -41,12 +42,11 @@ final class PromotionActionGroupValidatorSpec extends ObjectBehavior
;
}
function it_throws_an_exception_if_value_is_not_an_instance_of_promotion_action(
PromotionInterface $promotion,
): void {
function it_throws_an_exception_if_value_is_not_an_instance_of_promotion_action(): void
{
$this
->shouldThrow(UnexpectedValueException::class)
->during('validate', [$promotion, new PromotionActionGroup()])
->during('validate', [new \stdClass(), new PromotionActionGroup()])
;
}
@ -61,7 +61,23 @@ final class PromotionActionGroupValidatorSpec extends ObjectBehavior
$context->getValidator()->willReturn($validator);
$validator->inContext($context)->willReturn($contextualValidator);
$contextualValidator->validate($promotionAction, null, ['Default', 'test_group', 'action_two'])->willReturn($contextualValidator)->shouldBeCalled();
$contextualValidator->validate($promotionAction, null, ['Default', 'action_two'])->willReturn($contextualValidator)->shouldBeCalled();
$this->validate($promotionAction, new PromotionActionGroup(['groups' => ['Default', 'test_group']]));
}
function it_calls_validator_with_default_groups_if_none_provided_for_promotion_action_type(
ExecutionContextInterface $context,
PromotionActionInterface $promotionAction,
ValidatorInterface $validator,
ContextualValidatorInterface $contextualValidator,
): void {
$promotionAction->getType()->willReturn('action_one');
$context->getValidator()->willReturn($validator);
$validator->inContext($context)->willReturn($contextualValidator);
$contextualValidator->validate($promotionAction, null, ['Default', 'test_group'])->willReturn($contextualValidator)->shouldBeCalled();
$this->validate($promotionAction, new PromotionActionGroup(['groups' => ['Default', 'test_group']]));
}

View file

@ -14,7 +14,7 @@ declare(strict_types=1);
namespace spec\Sylius\Bundle\PromotionBundle\Validator;
use PhpSpec\ObjectBehavior;
use Sylius\Bundle\PromotionBundle\Validator\Constraints\PromotionAction;
use Sylius\Bundle\PromotionBundle\Validator\Constraints\PromotionActionType;
use Sylius\Component\Promotion\Model\PromotionActionInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
@ -22,7 +22,7 @@ use Symfony\Component\Validator\Exception\UnexpectedTypeException;
use Symfony\Component\Validator\Exception\UnexpectedValueException;
use Symfony\Component\Validator\Violation\ConstraintViolationBuilderInterface;
final class PromotionActionValidatorSpec extends ObjectBehavior
final class PromotionActionTypeValidatorSpec extends ObjectBehavior
{
function let(ExecutionContextInterface $context): void
{
@ -31,7 +31,7 @@ final class PromotionActionValidatorSpec extends ObjectBehavior
$this->initialize($context);
}
function it_throws_an_exception_if_constraint_is_not_an_instance_of_promotion_action(
function it_throws_an_exception_if_constraint_is_not_an_instance_of_promotion_action_type(
Constraint $constraint,
PromotionActionInterface $promotionAction,
): void {
@ -45,7 +45,7 @@ final class PromotionActionValidatorSpec extends ObjectBehavior
{
$this
->shouldThrow(UnexpectedValueException::class)
->during('validate', [new \stdClass(), new PromotionAction()])
->during('validate', [new \stdClass(), new PromotionActionType()])
;
}
@ -57,9 +57,10 @@ final class PromotionActionValidatorSpec extends ObjectBehavior
$promotionAction->getType()->willReturn('wrong_type');
$context->buildViolation('sylius.promotion_action.invalid_type')->willReturn($constraintViolationBuilder);
$constraintViolationBuilder->setParameter('{{ available_action_types }}', 'action_one, action_two')->willReturn($constraintViolationBuilder);
$constraintViolationBuilder->atPath('type')->willReturn($constraintViolationBuilder);
$constraintViolationBuilder->addViolation()->shouldBeCalled();
$this->validate($promotionAction, new PromotionAction());
$this->validate($promotionAction, new PromotionActionType());
}
}

View file

@ -11,11 +11,10 @@
declare(strict_types=1);
namespace spec\Sylius\Bundle\ApiBundle\Validator\Constraints;
namespace spec\Sylius\Bundle\PromotionBundle\Validator;
use PhpSpec\ObjectBehavior;
use Sylius\Bundle\ApiBundle\Validator\Constraints\PromotionRuleGroup;
use Sylius\Component\Core\Model\PromotionInterface;
use Sylius\Bundle\PromotionBundle\Validator\Constraints\PromotionRuleGroup;
use Sylius\Component\Promotion\Model\PromotionRuleInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
@ -28,6 +27,8 @@ final class PromotionRuleGroupValidatorSpec extends ObjectBehavior
{
function let(ExecutionContextInterface $context): void
{
$this->beConstructedWith(['rule_two' => ['Default', 'rule_two']]);
$this->initialize($context);
}
@ -41,12 +42,11 @@ final class PromotionRuleGroupValidatorSpec extends ObjectBehavior
;
}
function it_throws_an_exception_if_value_is_not_an_instance_of_promotion_rule(
PromotionInterface $promotion,
): void {
function it_throws_an_exception_if_value_is_not_an_instance_of_array(): void
{
$this
->shouldThrow(UnexpectedValueException::class)
->during('validate', [$promotion, new PromotionRuleGroup()])
->during('validate', [new \stdClass(), new PromotionRuleGroup()])
;
}
@ -61,7 +61,23 @@ final class PromotionRuleGroupValidatorSpec extends ObjectBehavior
$context->getValidator()->willReturn($validator);
$validator->inContext($context)->willReturn($contextualValidator);
$contextualValidator->validate($promotionRule, null, ['Default', 'test_group', 'rule_two'])->willReturn($contextualValidator)->shouldBeCalled();
$contextualValidator->validate($promotionRule, null, ['Default', 'rule_two'])->willReturn($contextualValidator)->shouldBeCalled();
$this->validate($promotionRule, new PromotionRuleGroup(['groups' => ['Default', 'test_group']]));
}
function it_calls_validator_with_default_groups_if_none_provided_for_promotion_action_type(
ExecutionContextInterface $context,
PromotionRuleInterface $promotionRule,
ValidatorInterface $validator,
ContextualValidatorInterface $contextualValidator,
): void {
$promotionRule->getType()->willReturn('rule_one');
$context->getValidator()->willReturn($validator);
$validator->inContext($context)->willReturn($contextualValidator);
$contextualValidator->validate($promotionRule, null, ['Default', 'test_group'])->willReturn($contextualValidator)->shouldBeCalled();
$this->validate($promotionRule, new PromotionRuleGroup(['groups' => ['Default', 'test_group']]));
}

View file

@ -14,7 +14,7 @@ declare(strict_types=1);
namespace spec\Sylius\Bundle\PromotionBundle\Validator;
use PhpSpec\ObjectBehavior;
use Sylius\Bundle\PromotionBundle\Validator\Constraints\PromotionRule;
use Sylius\Bundle\PromotionBundle\Validator\Constraints\PromotionRuleType;
use Sylius\Component\Promotion\Model\PromotionRuleInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
@ -22,7 +22,7 @@ use Symfony\Component\Validator\Exception\UnexpectedTypeException;
use Symfony\Component\Validator\Exception\UnexpectedValueException;
use Symfony\Component\Validator\Violation\ConstraintViolationBuilderInterface;
final class PromotionRuleValidatorSpec extends ObjectBehavior
final class PromotionRuleTypeValidatorSpec extends ObjectBehavior
{
function let(ExecutionContextInterface $context): void
{
@ -31,7 +31,7 @@ final class PromotionRuleValidatorSpec extends ObjectBehavior
$this->initialize($context);
}
function it_throws_an_exception_if_constraint_is_not_an_instance_of_promotion_rule(
function it_throws_an_exception_if_constraint_is_not_an_instance_of_promotion_rule_type(
Constraint $constraint,
PromotionRuleInterface $promotionRule,
): void {
@ -45,7 +45,7 @@ final class PromotionRuleValidatorSpec extends ObjectBehavior
{
$this
->shouldThrow(UnexpectedValueException::class)
->during('validate', [new \stdClass(), new PromotionRule()])
->during('validate', [new \stdClass(), new PromotionRuleType()])
;
}
@ -57,9 +57,10 @@ final class PromotionRuleValidatorSpec extends ObjectBehavior
$promotionRule->getType()->willReturn('wrong_type');
$context->buildViolation('sylius.promotion_rule.invalid_type')->willReturn($constraintViolationBuilder);
$constraintViolationBuilder->setParameter('{{ available_rule_types }}', 'rule_one, rule_two')->willReturn($constraintViolationBuilder);
$constraintViolationBuilder->atPath('type')->willReturn($constraintViolationBuilder);
$constraintViolationBuilder->addViolation()->shouldBeCalled();
$this->validate($promotionRule, new PromotionRule());
$this->validate($promotionRule, new PromotionRuleType());
}
}

View file

@ -387,6 +387,11 @@ final class PromotionsTest extends JsonApiTestCase
],
],
],
[
'type' => 'wrong_type',
'configuration' => [
],
],
],
], \JSON_THROW_ON_ERROR),
);
@ -447,6 +452,11 @@ final class PromotionsTest extends JsonApiTestCase
'configuration' => [
],
],
[
'type' => 'wrong_type',
'configuration' => [
],
],
],
], \JSON_THROW_ON_ERROR),
);

View file

@ -33,6 +33,11 @@
"propertyPath": "actions[4].configuration[percentage]",
"message": "This field is missing.",
"code": @string@
},
{
"propertyPath": "actions[5].type",
"message": "Promotion action type is invalid. Available action types are order_fixed_discount, unit_fixed_discount, order_percentage_discount, unit_percentage_discount, shipping_percentage_discount.",
"code": null
}
]
}

View file

@ -50,9 +50,9 @@
"code": @string@
},
{
"propertyPath": "rules[7].configuration[MOBILE]",
"message": "This field was not expected.",
"code": @string@
"propertyPath": "rules[8].type",
"message": "Promotion rule type is invalid. Available rule types are cart_quantity, customer_group, nth_order, shipping_country, has_taxon, total_of_items_from_taxon, contains_product, item_total.",
"code": null
}
]
}