From eea29cba06649e311f7c77a05a6cf25601b94f47 Mon Sep 17 00:00:00 2001 From: gmorel Date: Thu, 5 Sep 2013 20:07:17 +0200 Subject: [PATCH] WIP - Add Coupon, Rules, CouponManager, Adapter as Services - Refactor Coupon to use these services --- core/lib/Thelia/Action/Coupon.php | 52 +++++++ core/lib/Thelia/Config/Resources/config.xml | 27 ++++ .../Rule/AvailableForTotalAmount.php | 88 +++++++++--- .../Constraint/Rule/AvailableForXArticles.php | 87 +++++++++--- .../Constraint/Rule/CouponRuleInterface.php | 28 ++++ core/lib/Thelia/Constraint/Rule/Operators.php | 21 ++- .../Rule/SerializableRule.php} | 17 ++- .../Controller/Admin/CouponController.php | 131 ++++++++++++++++++ core/lib/Thelia/Core/Bundle/TheliaBundle.php | 4 + .../Compiler/RegisterCouponPass.php | 69 +++++++++ .../Compiler/RegisterRulePass.php} | 52 ++++--- core/lib/Thelia/Core/Event/TheliaEvents.php | 56 +++++++- .../Thelia/Coupon/CouponAdapterInterface.php | 9 ++ core/lib/Thelia/Coupon/CouponBaseAdapter.php | 20 ++- core/lib/Thelia/Coupon/CouponFactory.php | 24 ++++ core/lib/Thelia/Coupon/CouponManager.php | 42 +++++- .../Thelia/Coupon/Type/CouponInterface.php | 1 + install/faker.php | 54 ++++---- reset_install.sh | 14 +- templates/admin/default/coupon/form.html | 96 +++++-------- 20 files changed, 723 insertions(+), 169 deletions(-) rename core/lib/Thelia/{Coupon/Type/RemoveXAmountForCategoryY.php => Constraint/Rule/SerializableRule.php} (82%) create mode 100755 core/lib/Thelia/Core/DependencyInjection/Compiler/RegisterCouponPass.php rename core/lib/Thelia/{Tests/Coupon/Type/RemoveXAmountForCategoryYTest.php => Core/DependencyInjection/Compiler/RegisterRulePass.php} (61%) mode change 100644 => 100755 diff --git a/core/lib/Thelia/Action/Coupon.php b/core/lib/Thelia/Action/Coupon.php index 57e019888..cc32d2c68 100755 --- a/core/lib/Thelia/Action/Coupon.php +++ b/core/lib/Thelia/Action/Coupon.php @@ -68,6 +68,52 @@ class Coupon extends BaseAction implements EventSubscriberInterface $this->createOrUpdate($coupon, $event); } + /** + * Occurring when a Coupon rule is about to be created + * + * @param CouponCreateOrUpdateEvent $event Event creation or update Event + */ + public function createRule(CouponCreateOrUpdateEvent $event) + { + $coupon = $event->getCoupon(); + + $this->createOrUpdate($coupon, $event); + } + + /** + * Occurring when a Coupon rule is about to be updated + * + * @param CouponCreateOrUpdateEvent $event Event creation or update Event + */ + public function updateRule(CouponCreateOrUpdateEvent $event) + { + $coupon = $event->getCoupon(); + + $this->createOrUpdate($coupon, $event); + } + + /** + * Occurring when a Coupon rule is about to be deleted + * + * @param CouponCreateOrUpdateEvent $event Event creation or update Event + */ + public function deleteRule(CouponCreateOrUpdateEvent $event) + { + $coupon = $event->getCoupon(); + + $this->createOrUpdate($coupon, $event); + } + + /** + * Occurring when a Coupon rule is about to be consumed + * + * @param CouponCreateOrUpdateEvent $event Event creation or update Event + */ + public function consume(CouponCreateOrUpdateEvent $event) + { + // @todo implements + } + /** * Call the Model and delegate the create or delete action * Feed the Event with the updated model @@ -123,6 +169,12 @@ class Coupon extends BaseAction implements EventSubscriberInterface return array( TheliaEvents::COUPON_CREATE => array("create", 128), TheliaEvents::COUPON_UPDATE => array("update", 128), + TheliaEvents::COUPON_DISABLE => array("disable", 128), + TheliaEvents::COUPON_ENABLE => array("enable", 128), + TheliaEvents::COUPON_CONSUME => array("consume", 128), + TheliaEvents::COUPON_RULE_CREATE => array("createRule", 128), + TheliaEvents::COUPON_RULE_UPDATE => array("updateRule", 128), + TheliaEvents::COUPON_RULE_DELETE => array("deleteRule", 128) ); } } diff --git a/core/lib/Thelia/Config/Resources/config.xml b/core/lib/Thelia/Config/Resources/config.xml index ce78f5010..08575590f 100755 --- a/core/lib/Thelia/Config/Resources/config.xml +++ b/core/lib/Thelia/Config/Resources/config.xml @@ -198,6 +198,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/lib/Thelia/Constraint/Rule/AvailableForTotalAmount.php b/core/lib/Thelia/Constraint/Rule/AvailableForTotalAmount.php index a6e5d60ee..7b4629b0f 100644 --- a/core/lib/Thelia/Constraint/Rule/AvailableForTotalAmount.php +++ b/core/lib/Thelia/Constraint/Rule/AvailableForTotalAmount.php @@ -24,6 +24,7 @@ namespace Thelia\Constraint\Rule; use Symfony\Component\Intl\Exception\NotImplementedException; +use Symfony\Component\Translation\Translator; use Thelia\Coupon\CouponAdapterInterface; use Thelia\Constraint\Validator\PriceParam; use Thelia\Constraint\Validator\RuleValidator; @@ -48,6 +49,9 @@ class AvailableForTotalAmount extends CouponRuleAbstract /** Rule 1st parameter : price */ CONST PARAM1_PRICE = 'price'; + /** Rule 1st parameter : currency */ + CONST PARAM1_CURRENCY = 'currency'; + /** @var array Available Operators (Operators::CONST) */ protected $availableOperators = array( Operators::INFERIOR, @@ -55,7 +59,7 @@ class AvailableForTotalAmount extends CouponRuleAbstract Operators::SUPERIOR, ); - /** @var RuleValidator Price Validator */ + /** @var PriceParam Price Validator */ protected $priceValidator = null; /** @@ -185,9 +189,11 @@ class AvailableForTotalAmount extends CouponRuleAbstract */ public function getName() { - return $this->adapter - ->getTranslator() - ->trans('Cart total amount', null, 'constraint'); + return $this->adapter->get('thelia.translator')->trans( + 'Cart total amount', + array(), + 'constraint' + ); } /** @@ -197,23 +203,73 @@ class AvailableForTotalAmount extends CouponRuleAbstract */ public function getToolTip() { + /** @var Translator $translator */ + $translator = $this->get('thelia.translator'); $i18nOperator = Operators::getI18n( - $this->adapter, $this->priceValidator->getOperator() + $translator, $this->priceValidator->getOperator() ); - $toolTip = $this->adapter - ->getTranslator() - ->trans( - 'If cart total amount is %operator% %amount% %currency%', - array( - '%operator%' => $i18nOperator, - '%amount%' => $this->priceValidator->getParam()->getPrice(), - '%currency%' => $this->priceValidator->getParam()->getCurrency() - ), - 'constraint' - ); + $toolTip = $translator->trans( + 'If cart total amount is %operator% %amount% %currency%', + array( + '%operator%' => $i18nOperator, + '%amount%' => $this->priceValidator->getParam()->getPrice(), + '%currency%' => $this->priceValidator->getParam()->getCurrency() + ), + 'constraint' + ); return $toolTip; } + /** + * Populate a Rule from a form admin + * + * @param array $operators Rule Operator set by the Admin + * @param array $values Rule Values set by the Admin + * + * @throws InvalidArgumentException + * @return $this + */ + public function populateFromForm(array $operators, array $values) + { + if ($values[self::PARAM1_PRICE] === null + || $values[self::PARAM1_CURRENCY] === null + ) { + throw new InvalidArgumentException( + 'The Rule ' . get_class() . 'needs at least a quantity set (' . self::PARAM1_PRICE . ', ' . self::PARAM1_CURRENCY . ')' + ); + } + + $this->priceValidator = new PriceParam( + $this->adapter, + $values[self::PARAM1_PRICE], + $values[self::PARAM1_CURRENCY] + ); + + return $this; + } + + /** + * Return a serializable Rule + * + * @return SerializableRule + */ + public function getSerializableRule() + { + $serializableRule = new SerializableRule(); + $serializableRule->operators = array( + self::PARAM1_PRICE => $this->priceValidator->getOperator() + ); + + $serializableRule->values = array( + self::PARAM1_PRICE => $this->priceValidator->getPrice(), + self::PARAM1_CURRENCY => $this->priceValidator->getCurrency() + ); + + return $serializableRule; + } + + + } \ No newline at end of file diff --git a/core/lib/Thelia/Constraint/Rule/AvailableForXArticles.php b/core/lib/Thelia/Constraint/Rule/AvailableForXArticles.php index d103f4f23..c60404218 100644 --- a/core/lib/Thelia/Constraint/Rule/AvailableForXArticles.php +++ b/core/lib/Thelia/Constraint/Rule/AvailableForXArticles.php @@ -23,6 +23,8 @@ namespace Thelia\Constraint\Rule; +use InvalidArgumentException; +use Symfony\Component\Translation\Translator; use Thelia\Constraint\Validator\QuantityParam; use Thelia\Constraint\Validator\RuleValidator; use Thelia\Coupon\CouponAdapterInterface; @@ -51,7 +53,7 @@ class AvailableForXArticles extends CouponRuleAbstract Operators::SUPERIOR, ); - /** @var RuleValidator Quantity Validator */ + /** @var QuantityParam Quantity Validator */ protected $quantityValidator = null; /** @@ -64,7 +66,7 @@ class AvailableForXArticles extends CouponRuleAbstract * * @throws InvalidRuleException */ - public function __construct(CouponAdapterInterface $adapter, array $validators) + public function __construct(CouponAdapterInterface $adapter, array $validators = null) { parent::__construct($adapter, $validators); @@ -160,7 +162,7 @@ class AvailableForXArticles extends CouponRuleAbstract $quantityValidator = $this->quantityValidator; try { $quantityValidator->getParam()->compareTo($quantity); - } catch(\InvalidArgumentException $e) { + } catch(InvalidArgumentException $e) { throw new InvalidRuleValueException(get_class(), self::PARAM1_QUANTITY); } @@ -174,9 +176,14 @@ class AvailableForXArticles extends CouponRuleAbstract */ public function getName() { - return $this->adapter - ->getTranslator() - ->trans('Number of articles in cart', null, 'constraint'); + /** @var Translator $translator */ + $translator = $this->adapter->get('thelia.translator'); + + return $translator->trans( + 'Number of articles in cart', + array(), + 'constraint' + ); } /** @@ -186,22 +193,68 @@ class AvailableForXArticles extends CouponRuleAbstract */ public function getToolTip() { + /** @var Translator $translator */ + $translator = $this->adapter->get('thelia.translator'); + $i18nOperator = Operators::getI18n( - $this->adapter, $this->priceValidator->getOperator() + $translator, $this->priceValidator->getOperator() ); - $toolTip = $this->adapter - ->getTranslator() - ->trans( - 'If cart products quantity is %operator% %quantity%', - array( - '%operator%' => $i18nOperator, - '%quantity%' => $this->quantityValidator->getParam()->getInteger(), - ), - 'constraint' - ); + $toolTip = $translator->trans( + 'If cart products quantity is %operator% %quantity%', + array( + '%operator%' => $i18nOperator, + '%quantity%' => $this->quantityValidator->getParam()->getInteger(), + ), + 'constraint' + ); return $toolTip; } + /** + * Populate a Rule from a form admin + * + * @param array $operators Rule Operator set by the Admin + * @param array $values Rule Values set by the Admin + * + * @throws InvalidArgumentException + * @return $this + */ + public function populateFromForm(array $operators, array $values) + { + if ($values[self::PARAM1_QUANTITY] === null) { + throw new InvalidArgumentException( + 'The Rule ' . get_class() . 'needs at least a quantity set (' . self::PARAM1_QUANTITY. ')' + ); + } + + $this->quantityValidator = new QuantityParam( + $this->adapter, + $values[self::PARAM1_QUANTITY] + ); + + return $this; + } + + /** + * Return a serializable Rule + * + * @return SerializableRule + */ + public function getSerializableRule() + { + $serializableRule = new SerializableRule(); + $serializableRule->operators = array( + self::PARAM1_QUANTITY => $this->quantityValidator->getOperator() + ); + + $serializableRule->values = array( + self::PARAM1_QUANTITY => $this->quantityValidator->getInteger() + ); + + return $serializableRule; + } + + } \ No newline at end of file diff --git a/core/lib/Thelia/Constraint/Rule/CouponRuleInterface.php b/core/lib/Thelia/Constraint/Rule/CouponRuleInterface.php index ea0ba42d9..ce8e6c469 100644 --- a/core/lib/Thelia/Constraint/Rule/CouponRuleInterface.php +++ b/core/lib/Thelia/Constraint/Rule/CouponRuleInterface.php @@ -23,6 +23,7 @@ namespace Thelia\Constraint\Rule; +use Symfony\Component\Translation\Translator; use Thelia\Coupon\CouponAdapterInterface; /** @@ -81,4 +82,31 @@ interface CouponRuleInterface */ public function getToolTip(); + /** + * Get validators + * + * @return array + */ + public function getValidators(); + + /** + * Populate a Rule from a form admin + * + * @param array $operators Rule Operator set by the Admin + * @param array $values Rule Values set by the Admin + * + * @return bool + */ + public function populateFromForm(array$operators, array $values); + + + /** + * Return a serializable Rule + * + * @return SerializableRule + */ + public function getSerializableRule(); + + + } diff --git a/core/lib/Thelia/Constraint/Rule/Operators.php b/core/lib/Thelia/Constraint/Rule/Operators.php index 41ed7428c..61e8337c6 100644 --- a/core/lib/Thelia/Constraint/Rule/Operators.php +++ b/core/lib/Thelia/Constraint/Rule/Operators.php @@ -23,6 +23,7 @@ namespace Thelia\Constraint\Rule; +use Symfony\Component\Translation\Translator; use Thelia\Constraint\Validator\ComparableInterface; /** @@ -110,56 +111,54 @@ abstract class Operators /** * Get operator translation * - * @param CouponAdapterInterface $adapter Provide necessary value from Thelia - * @param string $operator Operator const + * @param Translator $translator Provide necessary value from Thelia + * @param string $operator Operator const * * @return string */ - public static function getI18n(CouponAdapterInterface $adapter, $operator) + public static function getI18n(Translator $translator, $operator) { - $translator = $adapter->getTranslator(); - $ret = $operator; switch ($operator) { case self::INFERIOR: $ret = $translator->trans( 'inferior to', - null, + array(), 'constraint' ); break; case self::INFERIOR_OR_EQUAL: $ret = $translator->trans( 'inferior or equals to', - null, + array(), 'constraint' ); break; case self::EQUAL: $ret = $translator->trans( 'equals to', - null, + array(), 'constraint' ); break; case self::SUPERIOR_OR_EQUAL: $ret = $translator->trans( 'superior or equals to', - null, + array(), 'constraint' ); break; case self::SUPERIOR: $ret = $translator->trans( 'superior to', - null, + array(), 'constraint' ); break; case self::DIFFERENT: $ret = $translator->trans( 'different from', - null, + array(), 'constraint' ); break; diff --git a/core/lib/Thelia/Coupon/Type/RemoveXAmountForCategoryY.php b/core/lib/Thelia/Constraint/Rule/SerializableRule.php similarity index 82% rename from core/lib/Thelia/Coupon/Type/RemoveXAmountForCategoryY.php rename to core/lib/Thelia/Constraint/Rule/SerializableRule.php index 4a75683bc..66caa793d 100644 --- a/core/lib/Thelia/Coupon/Type/RemoveXAmountForCategoryY.php +++ b/core/lib/Thelia/Constraint/Rule/SerializableRule.php @@ -21,18 +21,29 @@ /* */ /**********************************************************************************/ -namespace Thelia\Coupon\Type; +namespace Thelia\Constraint\Rule; /** * Created by JetBrains PhpStorm. * Date: 8/19/13 * Time: 3:24 PM * - * @package Coupon + * A rule set by an admin ready to be serialized and stored in DataBase + * + * @package Constraint * @author Guillaume MOREL * */ -class RemoveXAmountForCategoryY extends RemoveXAmount +class SerializableRule { + /** @var string Rule Service id */ + public $ruleClassName = null; + + /** @var array Operators set by Admin for this Rule */ + public $operators = array(); + + /** @var array Values set by Admin for this Rule */ + public $values = array(); + } \ No newline at end of file diff --git a/core/lib/Thelia/Controller/Admin/CouponController.php b/core/lib/Thelia/Controller/Admin/CouponController.php index 1e093f89f..758e0b616 100755 --- a/core/lib/Thelia/Controller/Admin/CouponController.php +++ b/core/lib/Thelia/Controller/Admin/CouponController.php @@ -24,6 +24,9 @@ namespace Thelia\Controller\Admin; use Symfony\Component\HttpFoundation\Request; +use Thelia\Constraint\Rule\AvailableForTotalAmount; +use Thelia\Constraint\Rule\CouponRuleInterface; +use Thelia\Constraint\Validator\PriceParam; use Thelia\Core\Event\Coupon\CouponCreateEvent; use Thelia\Core\Event\Coupon\CouponCreateOrUpdateEvent; use Thelia\Core\Event\Coupon\CouponEvent; @@ -31,6 +34,8 @@ use Thelia\Core\Event\TheliaEvents; use Thelia\Core\HttpFoundation\Session\Session; use Thelia\Core\Security\Exception\AuthenticationException; use Thelia\Core\Security\Exception\AuthorizationException; +use Thelia\Core\Translation\Translator; +use Thelia\Coupon\CouponAdapterInterface; use Thelia\Coupon\CouponRuleCollection; use Thelia\Form\CouponCreationForm; use Thelia\Form\Exception\FormValidationException; @@ -165,6 +170,21 @@ class CouponController extends BaseAdminController 'locale' => $coupon->getLocale(), ); + /** @var CouponAdapterInterface $adapter */ + $adapter = $this->container->get('thelia.adapter'); + /** @var Translator $translator */ + $translator = $this->container->get('thelia.translator'); + + $args['rulesObject'] = array(); + /** @var CouponRuleInterface $rule */ + foreach ($coupon->getRules()->getRules() as $rule) { + $args['rulesObject'][] = array( + 'name' => $rule->getName(), + 'tooltip' => $rule->getToolTip(), + 'validators' => $rule->getValidators() + ); + } + // Setup the object form $changeForm = new CouponCreationForm($this->getRequest(), 'form', $data); @@ -180,6 +200,95 @@ class CouponController extends BaseAdminController ); } + + /** + * Manage Coupons Rule creation display + * + * @param int $couponId Coupon id + * + * @return \Symfony\Component\HttpFoundation\Response + */ + public function createRuleAction($couponId) + { + // Check current user authorization + $response = $this->checkAuth('admin.coupon.update'); + if ($response !== null) { + return $response; + } + + /** @var Coupon $coupon */ + $coupon = CouponQuery::create()->findOneById($couponId); + if (!$coupon) { + $this->pageNotFound(); + } + + // Parameters given to the template + $args = array(); + + $i18n = new I18n(); + /** @var Lang $lang */ + $lang = $this->getSession()->get('lang'); + $eventToDispatch = TheliaEvents::COUPON_RULE_CREATE; + + if ($this->getRequest()->isMethod('POST')) { + $this->validateCreateOrUpdateForm( + $i18n, + $lang, + $eventToDispatch, + 'updated', + 'update' + ); + } else { + // Prepare the data that will hydrate the form + $data = array( + 'code' => $coupon->getCode(), + 'title' => $coupon->getTitle(), + 'amount' => $coupon->getAmount(), + 'effect' => $coupon->getType(), + 'shortDescription' => $coupon->getShortDescription(), + 'description' => $coupon->getDescription(), + 'isEnabled' => ($coupon->getIsEnabled() == 1), + 'expirationDate' => $coupon->getExpirationDate($lang->getDateFormat()), + 'isAvailableOnSpecialOffers' => ($coupon->getIsAvailableOnSpecialOffers() == 1), + 'isCumulative' => ($coupon->getIsCumulative() == 1), + 'isRemovingPostage' => ($coupon->getIsRemovingPostage() == 1), + 'maxUsage' => $coupon->getMaxUsage(), + 'rules' => new CouponRuleCollection(array()), + 'locale' => $coupon->getLocale(), + ); + + /** @var CouponAdapterInterface $adapter */ + $adapter = $this->container->get('thelia.adapter'); + /** @var Translator $translator */ + $translator = $this->container->get('thelia.translator'); + + $args['rulesObject'] = array(); + /** @var CouponRuleInterface $rule */ + foreach ($coupon->getRules()->getRules() as $rule) { + $args['rulesObject'][] = array( + 'name' => $rule->getName($translator), + 'tooltip' => $rule->getToolTip($translator), + 'validators' => $rule->getValidators() + ); + } + + // Setup the object form + $changeForm = new CouponCreationForm($this->getRequest(), 'form', $data); + + // Pass it to the parser + $this->getParserContext()->addForm($changeForm); + } + + $args['formAction'] = 'admin/coupon/update/' . $couponId; + + return $this->render( + 'coupon-update', + $args + ); + } + + + /** * Manage Coupons read display * @@ -345,4 +454,26 @@ class CouponController extends BaseAdminController return $this; } +// /** +// * Validation Rule creation +// * +// * @param string $type Rule class type +// * @param string $operator Rule operator (<, >, =, etc) +// * @param array $values Rules values +// * +// * @return bool +// */ +// protected function validateRulesCreation($type, $operator, $values) +// { +// /** @var CouponAdapterInterface $adapter */ +// $adapter = $this->container->get('thelia.adapter'); +// $validator = new PriceParam() +// try { +// $rule = new AvailableForTotalAmount($adapter, $validators); +// $rule = new $type($adapter, $validators); +// } catch (\Exception $e) { +// return false; +// } +// } + } diff --git a/core/lib/Thelia/Core/Bundle/TheliaBundle.php b/core/lib/Thelia/Core/Bundle/TheliaBundle.php index 9c8b8fedf..a9704b350 100755 --- a/core/lib/Thelia/Core/Bundle/TheliaBundle.php +++ b/core/lib/Thelia/Core/Bundle/TheliaBundle.php @@ -26,9 +26,11 @@ use Symfony\Component\HttpKernel\Bundle\Bundle; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Scope; +use Thelia\Core\DependencyInjection\Compiler\RegisterCouponPass; use Thelia\Core\DependencyInjection\Compiler\RegisterListenersPass; use Thelia\Core\DependencyInjection\Compiler\RegisterParserPluginPass; use Thelia\Core\DependencyInjection\Compiler\RegisterRouterPass; +use Thelia\Core\DependencyInjection\Compiler\RegisterRulePass; /** * First Bundle use in Thelia @@ -60,6 +62,8 @@ class TheliaBundle extends Bundle ->addCompilerPass(new RegisterListenersPass()) ->addCompilerPass(new RegisterParserPluginPass()) ->addCompilerPass(new RegisterRouterPass()) + ->addCompilerPass(new RegisterCouponPass()) + ->addCompilerPass(new RegisterRulePass()) ; } diff --git a/core/lib/Thelia/Core/DependencyInjection/Compiler/RegisterCouponPass.php b/core/lib/Thelia/Core/DependencyInjection/Compiler/RegisterCouponPass.php new file mode 100755 index 000000000..cf6f32842 --- /dev/null +++ b/core/lib/Thelia/Core/DependencyInjection/Compiler/RegisterCouponPass.php @@ -0,0 +1,69 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Core\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; + +/** + * Created by JetBrains PhpStorm. + * Date: 9/05/13 + * Time: 3:24 PM + * + * Class RegisterListenersPass + * Source code come from Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\RegisterKernelListenersPass class + * + * @package Thelia\Core\DependencyInjection\Compiler + * @author Guillaume MOREL + * + */ +class RegisterCouponPass implements CompilerPassInterface +{ + /** + * You can modify the container here before it is dumped to PHP code. + * + * @param ContainerBuilder $container Container + * + * @api + */ + public function process(ContainerBuilder $container) + { + if (!$container->hasDefinition('thelia.coupon.manager')) { + return; + } + + $couponManager = $container->getDefinition('thelia.coupon.manager'); + $services = $container->findTaggedServiceIds("thelia.coupon.addCoupon"); + + foreach ($services as $id => $rule) { + $couponManager->addMethodCall( + 'addAvailableCoupon', + array( + new Reference($id) + ) + ); + } + } +} diff --git a/core/lib/Thelia/Tests/Coupon/Type/RemoveXAmountForCategoryYTest.php b/core/lib/Thelia/Core/DependencyInjection/Compiler/RegisterRulePass.php old mode 100644 new mode 100755 similarity index 61% rename from core/lib/Thelia/Tests/Coupon/Type/RemoveXAmountForCategoryYTest.php rename to core/lib/Thelia/Core/DependencyInjection/Compiler/RegisterRulePass.php index 896cc5feb..6d66e4bf1 --- a/core/lib/Thelia/Tests/Coupon/Type/RemoveXAmountForCategoryYTest.php +++ b/core/lib/Thelia/Core/DependencyInjection/Compiler/RegisterRulePass.php @@ -21,43 +21,49 @@ /* */ /**********************************************************************************/ -namespace Thelia\Coupon; +namespace Thelia\Core\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; /** * Created by JetBrains PhpStorm. - * Date: 8/19/13 + * Date: 9/05/13 * Time: 3:24 PM * - * Unit Test RemoveXAmountForCategoryY Class + * Class RegisterListenersPass + * Source code come from Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\RegisterKernelListenersPass class * - * @package Coupon + * @package Thelia\Core\DependencyInjection\Compiler * @author Guillaume MOREL * */ -class RemoveXAmountForCategoryYTest extends \PHPUnit_Framework_TestCase +class RegisterRulePass implements CompilerPassInterface { - /** - * Sets up the fixture, for example, opens a network connection. - * This method is called before a test is executed. + * You can modify the container here before it is dumped to PHP code. + * + * @param ContainerBuilder $container Container + * + * @api */ - protected function setUp() + public function process(ContainerBuilder $container) { - } + if (!$container->hasDefinition('thelia.coupon.manager')) { + return; + } - public function incompleteTest() - { - $this->markTestIncomplete( - 'This test has not been implemented yet.' - ); - } + $couponManager = $container->getDefinition('thelia.coupon.manager'); + $services = $container->findTaggedServiceIds("thelia.coupon.addCoupon"); - /** - * Tears down the fixture, for example, closes a network connection. - * This method is called after a test is executed. - */ - protected function tearDown() - { + foreach ($services as $id => $rule) { + $couponManager->addMethodCall( + 'addAvailableCoupon', + array( + new Reference($id) + ) + ); + } } - } diff --git a/core/lib/Thelia/Core/Event/TheliaEvents.php b/core/lib/Thelia/Core/Event/TheliaEvents.php index ed9070c6b..18ca58be1 100755 --- a/core/lib/Thelia/Core/Event/TheliaEvents.php +++ b/core/lib/Thelia/Core/Event/TheliaEvents.php @@ -249,15 +249,67 @@ final class TheliaEvents */ const AFTER_ENABLE_COUPON = "action.after_enable_coupon"; + /** + * Sent when attempting to use a Coupon + */ + const COUPON_CONSUME = "action.consume_coupon"; + /** * Sent just before an attempt to use a Coupon */ - const BEFORE_USE_COUPON = "action.before_use_coupon"; + const BEFORE_CONSUME_COUPON = "action.before_consume_coupon"; /** * Sent just after an attempt to use a Coupon */ - const AFTER_USE_COUPON = "action.after_use_coupon"; + const AFTER_CONSUME_COUPON = "action.after_consume_coupon"; + + + /** + * Sent when attempting to create Coupon Rule + */ + const COUPON_RULE_CREATE = "action.create_coupon_rule"; + + /** + * Sent just before an attempt to create a Coupon Rule + */ + const BEFORE_COUPON_RULE_CREATE = "action.before_create_coupon_rule"; + + /** + * Sent just after an attempt to create a Coupon Rule + */ + const AFTER_COUPON_RULE_CREATE = "action.after_create_coupon_rule"; + + /** + * Sent when attempting to update Coupon Rule + */ + const COUPON_RULE_UPDATE = "action.update_coupon_rule"; + + /** + * Sent just before an attempt to update a Coupon Rule + */ + const BEFORE_COUPON_RULE_UPDATE = "action.before_update_coupon_rule"; + + /** + * Sent just after an attempt to update a Coupon Rule + */ + const AFTER_COUPON_RULE_UPDATE = "action.after_update_coupon_rule"; + + /** + * Sent when attempting to delete Coupon Rule + */ + const COUPON_RULE_DELETE = "action.delete_coupon_rule"; + + /** + * Sent just before an attempt to delete a Coupon Rule + */ + const BEFORE_COUPON_RULE_DELETE = "action.before_delete_coupon_rule"; + + /** + * Sent just after an attempt to delete a Coupon Rule + */ + const AFTER_COUPON_RULE_DELETE = "action.after_delete_coupon_rule"; + // -- Configuration management --------------------------------------------- diff --git a/core/lib/Thelia/Coupon/CouponAdapterInterface.php b/core/lib/Thelia/Coupon/CouponAdapterInterface.php index 4325da3ae..29cf059f4 100644 --- a/core/lib/Thelia/Coupon/CouponAdapterInterface.php +++ b/core/lib/Thelia/Coupon/CouponAdapterInterface.php @@ -24,6 +24,8 @@ namespace Thelia\Coupon; use Symfony\Component\DependencyInjection\Container; +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\Translation\Translator; use Symfony\Component\Translation\TranslatorInterface; use Thelia\Coupon\Type\CouponInterface; use Thelia\Model\Coupon; @@ -42,6 +44,13 @@ use Thelia\Model\Coupon; interface CouponAdapterInterface { + /** + * Constructor + * + * @param ContainerInterface $container Service container + */ + function __construct(ContainerInterface $container); + /** * Return a Cart a CouponManager can process * diff --git a/core/lib/Thelia/Coupon/CouponBaseAdapter.php b/core/lib/Thelia/Coupon/CouponBaseAdapter.php index 70c9ebf94..271c319d8 100644 --- a/core/lib/Thelia/Coupon/CouponBaseAdapter.php +++ b/core/lib/Thelia/Coupon/CouponBaseAdapter.php @@ -24,6 +24,8 @@ namespace Thelia\Coupon; use Symfony\Component\DependencyInjection\Container; +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\Translation\Translator; use Symfony\Component\Translation\TranslatorInterface; use Thelia\Coupon\Type\CouponInterface; use Thelia\Model\Coupon; @@ -41,6 +43,22 @@ use Thelia\Model\CouponQuery; */ class CouponBaseAdapter implements CouponAdapterInterface { + /** @var ContainerInterface Service Container */ + protected $container = null; + + /** @var Translator Service Translator */ + protected $translator = null; + + /** + * Constructor + * + * @param ContainerInterface $container Service container + */ + function __construct(ContainerInterface $container) + { + $this->container = $container; + } + /** * Return a Cart a CouponManager can process * @@ -189,7 +207,7 @@ class CouponBaseAdapter implements CouponAdapterInterface */ public function getTranslator() { - return $this->getContainer()->get('thelia.translator'); + return $this->container->get('thelia.translator'); } diff --git a/core/lib/Thelia/Coupon/CouponFactory.php b/core/lib/Thelia/Coupon/CouponFactory.php index a77871ffd..23f082974 100644 --- a/core/lib/Thelia/Coupon/CouponFactory.php +++ b/core/lib/Thelia/Coupon/CouponFactory.php @@ -24,6 +24,7 @@ namespace Thelia\Coupon; use Symfony\Component\Translation\Exception\NotFoundResourceException; +use Thelia\Constraint\Rule\CouponRuleInterface; use Thelia\Coupon\Type\CouponInterface; use Thelia\Exception\CouponExpiredException; use Thelia\Exception\InvalidRuleException; @@ -125,4 +126,27 @@ class CouponFactory return $coupon; } + + +// /** +// * Build a Coupon Rule from form +// * +// * @param string $type Rule class name +// * @param string $operator Rule Operator (<, >, = ) +// * @param array $values Values setting this Rule +// * +// * @return CouponRuleInterface Ready to use Rule or false +// */ +// public function buildCouponRuleFromForm($ruleClassName, $operator, array $values) +// { +// /** @var CouponAdapterInterface $adapter */ +// $adapter = $this->container->get('thelia.adapter'); +// $validator = new PriceParam() +// try { +// $rule = new AvailableForTotalAmount($adapter, $validators); +// $rule = new $type($adapter, $validators); +// } catch (\Exception $e) { +// return false; +// } +// } } diff --git a/core/lib/Thelia/Coupon/CouponManager.php b/core/lib/Thelia/Coupon/CouponManager.php index 272cb7ed7..ad351081c 100644 --- a/core/lib/Thelia/Coupon/CouponManager.php +++ b/core/lib/Thelia/Coupon/CouponManager.php @@ -23,6 +23,8 @@ namespace Thelia\Coupon; +use Symfony\Component\DependencyInjection\ContainerInterface; +use Thelia\Constraint\Rule\CouponRuleInterface; use Thelia\Coupon\Type\CouponInterface; /** @@ -39,21 +41,23 @@ use Thelia\Coupon\Type\CouponInterface; class CouponManager { /** @var CouponAdapterInterface Provides necessary value from Thelia */ - protected $adapter; + protected $adapter = null; + + /** @var ContainerInterface Service Container */ + protected $container = null; /** @var array CouponInterface to process*/ protected $coupons = array(); /** * Constructor - * Gather Coupons from Adapter - * via $adapter->getCurrentCoupons(); * - * @param CouponAdapterInterface $adapter Provide necessary value from Thelia + * @param ContainerInterface $container Service container */ - function __construct(CouponAdapterInterface $adapter) + function __construct(ContainerInterface $container) { - $this->adapter = $adapter; + $this->container = $container; + $this->adapter = $container->get('thelia.adapter'); $this->coupons = $this->adapter->getCurrentCoupons(); } @@ -178,4 +182,30 @@ class CouponManager return $discount; } + + /** + * Build a CouponRuleInterface from data coming from a form + * + * @param string $ruleServiceId Rule service id you want to instantiate + * @param array $operators Rule Operator set by the Admin + * @param array $values Rule Values set by the Admin + * + * @return CouponRuleInterface + */ + public function buildRuleFromForm($ruleServiceId, array $operators, array $values) + { + $rule = false; + try { + + if ($this->container->has($ruleServiceId)) { + /** @var CouponRuleInterface $rule */ + $rule = $this->container->get($ruleServiceId); + $rule->populateFromForm($operators, $values); + } + } catch (\InvalidArgumentException $e) { + + } + + return $rule; + } } \ No newline at end of file diff --git a/core/lib/Thelia/Coupon/Type/CouponInterface.php b/core/lib/Thelia/Coupon/Type/CouponInterface.php index 116995496..aa7dc9a79 100644 --- a/core/lib/Thelia/Coupon/Type/CouponInterface.php +++ b/core/lib/Thelia/Coupon/Type/CouponInterface.php @@ -176,4 +176,5 @@ interface CouponInterface * @return string */ public function getToolTip(); + } diff --git a/install/faker.php b/install/faker.php index 9dcab3995..7ab987459 100755 --- a/install/faker.php +++ b/install/faker.php @@ -495,6 +495,8 @@ function setI18n($faker, &$object) */ function generateCouponFixtures() { + $adapter = new \Thelia\Coupon\CouponBaseAdapter(); + // Coupons $coupon1 = new Thelia\Model\Coupon(); $coupon1->setCode('XMAS'); @@ -516,31 +518,35 @@ Sed facilisis pellentesque nisl, eu tincidunt erat scelerisque a. Nullam malesua $date = new \DateTime(); $coupon1->setExpirationDate($date->setTimestamp(strtotime("today + 2 months"))); -// $rule1 = new Thelia\Constraint\Rule\AvailableForTotalAmount( -// array( -// Thelia\Constraint\Rule\AvailableForTotalAmount::PARAM1_PRICE => new Thelia\Constraint\Validator\RuleValidator( -// Thelia\Constraint\Rule\Operators::SUPERIOR, -// new Thelia\Constraint\Validator\PriceParam( -// 40.00, -// 'EUR' -// ) -// ) -// ) -// ); -// $rule2 = new Thelia\Constraint\Rule\AvailableForTotalAmount( -// array( -// Thelia\Constraint\Rule\AvailableForTotalAmount::PARAM1_PRICE => new Thelia\Coupon\Parameter\RuleValidator( -// Thelia\Constraint\Rule\Operators::INFERIOR, -// new Thelia\Constraint\Parameter\PriceParam( -// 400.00, -// 'EUR' -// ) -// ) -// ) -// ); -// $rules = new \Thelia\Coupon\CouponRuleCollection(array($rule1, $rule2)); + $rule1 = new Thelia\Constraint\Rule\AvailableForTotalAmount( + $adapter, + array( + Thelia\Constraint\Rule\AvailableForTotalAmount::PARAM1_PRICE => new Thelia\Constraint\Validator\RuleValidator( + Thelia\Constraint\Rule\Operators::SUPERIOR, + new Thelia\Constraint\Validator\PriceParam( + $adapter, + 40.00, + 'EUR' + ) + ) + ) + ); + $rule2 = new Thelia\Constraint\Rule\AvailableForTotalAmount( + $adapter, + array( + Thelia\Constraint\Rule\AvailableForTotalAmount::PARAM1_PRICE => new Thelia\Constraint\Validator\RuleValidator( + Thelia\Constraint\Rule\Operators::INFERIOR, + new Thelia\Constraint\Validator\PriceParam( + $adapter, + 400.00, + 'EUR' + ) + ) + ) + ); + $rules = new \Thelia\Coupon\CouponRuleCollection(array($rule1, $rule2)); -// $coupon1->setSerializedRules(base64_encode(serialize($rules))); + $coupon1->setSerializedRules(base64_encode(serialize($rules))); $coupon1->setIsCumulative(1); $coupon1->setIsRemovingPostage(0); diff --git a/reset_install.sh b/reset_install.sh index aaa7ae2d7..448390854 100755 --- a/reset_install.sh +++ b/reset_install.sh @@ -1,6 +1,6 @@ #!/bin/bash # @author Guillaume MOREL -# v0.1 +# v0.2 echo -e "\033[47m\033[1;31m\n[WARN] This script will reset this Thelia2 install\n\033[0m" @@ -15,11 +15,10 @@ echo -e "\n\e[01;34m[INFO] Building Models file\e[00m\n" echo -e "\n\e[01;34m[INFO] Building SQL CREATE file\e[00m\n" ../../bin/propel sql:build -v --output-dir=../../install/ - - echo -e "\n\e[01;34m[INFO] Reloaded Thelia2 database\e[00m\n" - cd ../.. - rm install/sqldb.map - php Thelia thelia:dev:reloadDB +echo -e "\n\e[01;34m[INFO] Reloaded Thelia2 database\e[00m\n" +cd ../.. +rm install/sqldb.map +php Thelia thelia:dev:reloadDB echo -e "\n\e[01;34m[INFO] Installing fixtures\e[00m\n" php install/faker.php @@ -27,5 +26,4 @@ php install/faker.php echo -e "\n\e[01;34m[INFO] Adding admin\e[00m\n" php Thelia thelia:create-admin --login_name thelia2 --password thelia2 --last_name thelia2 --first_name thelia2 - echo -e "\n\e[00;32m[SUCCESS] Reset done\e[00m\n" -fi +echo -e "\n\e[00;32m[SUCCESS] Reset done\e[00m\n" \ No newline at end of file diff --git a/templates/admin/default/coupon/form.html b/templates/admin/default/coupon/form.html index 452eff0a6..cf108da1a 100644 --- a/templates/admin/default/coupon/form.html +++ b/templates/admin/default/coupon/form.html @@ -18,17 +18,17 @@
- + {form_field form=$form field='code'} - + {if $error}{$message}{/if} {/form_field}
- + {form_field form=$form field='title'} - + {if $error}{$message}{/if} {/form_field}
@@ -39,7 +39,7 @@ {if $error}{$message}{/if} {/form_field} - Is enabled ? + {intl l='Is enabled ?'}
@@ -49,7 +49,7 @@ {if $error}{$message}{/if} {/form_field} - Is available on special offers ? + {intl l='Is available on special offers ?'}
@@ -59,7 +59,7 @@ {if $error}{$message}{/if} {/form_field} - Is cumulative ? + {intl l='Is cumulative ?'} @@ -69,12 +69,12 @@ {if $error}{$message}{/if} {/form_field} - Is removing postage ? + {intl l='Is removing postage ?'}
- +
{form_field form=$form field='expirationDate'} @@ -85,13 +85,13 @@
- + {form_field form=$form field='maxUsage'} - + {if $error}{$message}{/if} {/form_field}
@@ -101,7 +101,7 @@
- + {form_field form=$form field='effect'} + {if $error}{$message}{/if} {/form_field}
@@ -137,9 +137,9 @@
- + {form_field form=$form field='shortDescription'} - + {if $error}{$message}{/if} {/form_field}
@@ -149,14 +149,14 @@
- + {form_field form=$form field='description'} - + {if $error}{$message}{/if} {/form_field}
- +
@@ -166,47 +166,27 @@
- - - - + + - - - - - - - - - - - - - - - - - - + {foreach from=$rulesObject item=rule} + + + + + {/foreach}
- Rules - + {intl l='Rules'} +
ConditionsOperatorValueActions{intl l='Conditions'}{intl l='Actions'}
Total Amountis superior or equals to300 € - Edit - Delete -
AND NbArticleFromCategoryis equals to12 - Chaussettes rouges - Edit - Delete -
OR Dateis inferior or equals to12/02/2014 - Edit - Delete -
{$rule.tooltip} + {intl l='Edit'} + {intl l='Delete'} +
@@ -216,17 +196,17 @@
- +
- +