- Add Coupon, Rules, CouponManager, Adapter as Services
- Refactor Coupon to use these services
This commit is contained in:
gmorel
2013-09-05 20:07:17 +02:00
parent a9b0f53334
commit eea29cba06
20 changed files with 723 additions and 169 deletions

View File

@@ -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)
);
}
}

View File

@@ -198,6 +198,33 @@
<service id="service_container" synthetic="true" />
<service id="kernel" synthetic="true" />
<!-- Coupon module -->
<service id="thelia.adapter" class="Thelia\Coupon\CouponBaseAdapter">
<argument type="service" id="service_container" />
</service>
<service id="thelia.coupon.manager" class="Thelia\Coupon\CouponManager">
<argument type="service" id="thelia.adapter" />
</service>
<service id="thelia.constraint.rule.available_for_x_articles" class="Thelia\Constraint\Rule\AvailableForXArticles">
<argument type="service" id="thelia.translator" />
<tag name="thelia.coupon.addRule"/>
</service>
<service id="thelia.constraint.rule.available_for_total_amount" class="Thelia\Constraint\Rule\AvailableForTotalAmount">
<argument type="service" id="thelia.translator" />
<tag name="thelia.coupon.addRule"/>
</service>
<service id="thelia.coupon.type.remove_x_amount" class="Thelia\Coupon\Type\RemoveXAmount">
<argument type="service" id="thelia.translator" />
<tag name="thelia.coupon.addCoupon"/>
</service>
<service id="thelia.coupon.type.remove_x_percent" class="Thelia\Coupon\Type\RemoveXPercent">
<argument type="service" id="thelia.translator" />
<tag name="thelia.coupon.addCoupon"/>
</service>
</services>
</config>

View File

@@ -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 <strong>%operator%</strong> %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;
}
}

View File

@@ -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 <strong>%operator%</strong> %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;
}
}

View File

@@ -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();
}

View File

@@ -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;

View File

@@ -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 <gmorel@openstudio.fr>
*
*/
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();
}

View File

@@ -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;
// }
// }
}

View File

@@ -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())
;
}

View File

@@ -0,0 +1,69 @@
<?php
/**********************************************************************************/
/* */
/* Thelia */
/* */
/* Copyright (c) OpenStudio */
/* email : info@thelia.net */
/* web : http://www.thelia.net */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 3 of the License */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* */
/**********************************************************************************/
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 <gmorel@openstudio.fr>
*
*/
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)
)
);
}
}
}

View File

@@ -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 <gmorel@openstudio.fr>
*
*/
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)
)
);
}
}
}

View File

@@ -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 ---------------------------------------------

View File

@@ -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
*

View File

@@ -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');
}

View File

@@ -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;
// }
// }
}

View File

@@ -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;
}
}

View File

@@ -176,4 +176,5 @@ interface CouponInterface
* @return string
*/
public function getToolTip();
}

View File

@@ -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);

View File

@@ -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"

View File

@@ -18,17 +18,17 @@
<div class="control-group">
<div class="col-md-4">
<div class="form-group">
<label for="code">Code :</label>
<label for="code">{intl l='Code :'}</label>
{form_field form=$form field='code'}
<input id="code" class="form-control" type="text" name="{$name}" value="{$value}" placeholder="code">
<input id="code" class="form-control" type="text" name="{$name}" value="{$value}" placeholder="{intl l='code'}">
{if $error}{$message}{/if}
{/form_field}
</div>
<div class="form-group">
<label for="title">Title :</label>
<label for="title">{intl l='Title :'}</label>
{form_field form=$form field='title'}
<input id="title" class="form-control" type="text" name="{$name}" value="{$value}" placeholder="title">
<input id="title" class="form-control" type="text" name="{$name}" value="{$value}" placeholder="{intl l='title'}">
{if $error}{$message}{/if}
{/form_field}
</div>
@@ -39,7 +39,7 @@
<input id="enabled" type="checkbox" name="{$name}" {if $value}value="1" checked{else}value="0"{/if} >
{if $error}{$message}{/if}
{/form_field}
Is enabled ?
{intl l='Is enabled ?'}
</label>
</div>
@@ -49,7 +49,7 @@
<input id="available-on-special-offers" type="checkbox" name="{$name}" {if $value}value="1" checked{else}value="0"{/if} >
{if $error}{$message}{/if}
{/form_field}
Is available on special offers ?
{intl l='Is available on special offers ?'}
</label>
</div>
@@ -59,7 +59,7 @@
<input id="cumulative" type="checkbox" name="{$name}" {if $value}value="1" checked{else}value="0"{/if} >
{if $error}{$message}{/if}
{/form_field}
Is cumulative ?
{intl l='Is cumulative ?'}
</label>
</div>
@@ -69,12 +69,12 @@
<input id="renoving-postage" type="checkbox" name="{$name}" {if $value}value="1" checked{else}value="0"{/if} >
{if $error}{$message}{/if}
{/form_field}
Is removing postage ?
{intl l='Is removing postage ?'}
</label>
</div>
<div class="form-group">
<label for="expiration-date">Expiration date :</label>
<label for="expiration-date">{intl l='Expiration date :'}</label>
<div class="input-append date" data-date="12/02/2012" data-date-format="dd/mm/yyyy">
{form_field form=$form field='expirationDate'}
<input type="text" id="expiration-date" name="{$name}" value="{if $defaultDate}{$defaultDate}{else}{$value}{/if}">
@@ -85,13 +85,13 @@
</div>
<div class="form-group">
<label for="max-usage">Max usage :</label>
<label for="max-usage">{intl l='Max usage :'}</label>
<label for="is-unlimited" class="checkbox">
<input id="is-unlimited" type="checkbox" name="is-unlimited" checked >
Is unlimited ?
{intl l='Is unlimited ?'}
</label>
{form_field form=$form field='maxUsage'}
<input id="max-usage" type="text" class="form-control" name="{$name}" value="{$value}" placeholder="max usage">
<input id="max-usage" type="text" class="form-control" name="{$name}" value="{$value}" placeholder="{intl l='max usage'}">
{if $error}{$message}{/if}
{/form_field}
</div>
@@ -101,7 +101,7 @@
<div class="well clearfix">
<div class="col-md-6">
<div class="form-group">
<label for="effect">Effect :</label>
<label for="effect">{intl l='Effect :'}</label>
{form_field form=$form field='effect'}
<select name="{$name}" value="{$value}" id="effect" class="col-md-12 form-control">
<option value="1" data-description="More description n°1 about item">Remove x percents for category Y</option>
@@ -116,9 +116,9 @@
<div class="col-md-6">
<div class="form-group">
<label for="amount">Amount :</label>
<label for="amount">{intl l='Amount :'}</label>
{form_field form=$form field='amount'}
<input id="amount" type="text" class="form-control" name="{$name}" value="{$value}" placeholder="amount">
<input id="amount" type="text" class="form-control" name="{$name}" value="{$value}" placeholder="{intl l='14.50'}">
{if $error}{$message}{/if}
{/form_field}
</div>
@@ -137,9 +137,9 @@
</div>
<div class="form-group">
<label for="short-description">Short description :</label>
<label for="short-description">{intl l='Short description :'}</label>
{form_field form=$form field='shortDescription'}
<textarea id="short-description" name="{$name}" placeholder="short description" class="span12" rows="5">{$value nofilter}</textarea>
<textarea id="short-description" name="{$name}" placeholder="{intl l='short description'}" class="span12" rows="5">{$value nofilter}</textarea>
{if $error}{$message}{/if}
{/form_field}
</div>
@@ -149,14 +149,14 @@
<div class="col-md-12">
<div class="form-group">
<label for="description">Long description :</label>
<label for="description">{intl l='Long description :'}</label>
{form_field form=$form field='description'}
<textarea id="description" name="{$name}" placeholder="long description" class="form-control wysiwyg" rows="10">{$value nofilter}</textarea>
<textarea id="description" name="{$name}" placeholder="{intl l='long description'}" class="form-control wysiwyg" rows="10">{$value nofilter}</textarea>
{if $error}{$message}{/if}
{/form_field}
</div>
<button type="submit" class="btn btn-default btn-primary">Save</button>
<button type="submit" class="btn btn-default btn-primary">{intl l='Save'}</button>
</div>
</div>
@@ -166,47 +166,27 @@
<div class="col-md-12 general-block-decorator">
<table class="table table-striped">
<caption class="clearfix">
Rules
<a class="btn btn-default btn-primary pull-right" title="Add a new rule">
{intl l='Rules'}
<a class="btn btn-default btn-primary pull-right" title="{intl l='Add a new rule'}">
<span class="glyphicon glyphicon-plus-sign"></span>
</a>
</caption>
<thead>
<tr>
<th>Conditions</th>
<th>Operator</th>
<th>Value</th>
<th>Actions</th>
<th>{intl l='Conditions'}</th>
<th>{intl l='Actions'}</th>
</tr>
</thead>
<tbody>
<tr>
<td>Total Amount</td>
<td><span class="label">is superior or equals to</span></td>
<td>300 &euro;</td>
<td>
<a href="#url" class="btn btn-default btn-primary btn-medium"><span class="glyphicon glyphicon-edit"></span> Edit</a>
<a href="#url" class="btn btn-default btn-danger btn-medium" data-toggle="confirm" data-target="#delete"><span class="glyphicon glyphicon-remove"></span> Delete</a>
</td>
</tr>
<tr>
<td><span class="label">AND</span> NbArticleFromCategory</td>
<td><span class="label">is equals to</span></td>
<td>12 - <a href="#" target="_blank">Chaussettes rouges</a></td>
<td>
<a href="#url" class="btn btn-default btn-primary btn-medium"><span class="glyphicon glyphicon-edit"></span> Edit</a>
<a href="#url" class="btn btn-default btn-danger btn-medium" data-toggle="confirm" data-target="#delete"><span class="glyphicon glyphicon-remove"></span> Delete</a>
</td>
</tr>
<tr>
<td><span class="label label-info">OR</span> Date</td>
<td><span class="label">is inferior or equals to</span></td>
<td>12/02/2014</td>
<td>
<a href="#url" class="btn btn-default btn-primary btn-medium"><span class="glyphicon glyphicon-edit"></span> Edit</a>
<a href="#url" class="btn btn-default btn-danger btn-medium" data-toggle="confirm" data-target="#delete"><span class="glyphicon glyphicon-remove"></span> Delete</a>
</td>
</tr>
{foreach from=$rulesObject item=rule}
<tr>
<td>{$rule.tooltip}</td>
<td>
<a href="#url" class="btn btn-default btn-primary btn-medium"><span class="glyphicon glyphicon-edit"></span> {intl l='Edit'}</a>
<a href="#url" class="btn btn-default btn-danger btn-medium" data-toggle="confirm" data-target="#delete"><span class="glyphicon glyphicon-remove"></span> {intl l='Delete'}</a>
</td>
</tr>
{/foreach}
</tbody>
</table>
</div>
@@ -216,17 +196,17 @@
<div class="col-md-12 general-block-decorator clearfix">
<div class="form-group col-md-2">
<label for="type">Condition type :</label>
<label for="type">{intl l='Condition type :'}</label>
<label class="radio">
<input type="radio" name="type" id="type" value="1" checked> And
<input type="radio" name="type" id="type" value="1" checked> {intl l='And'}
</label>
<label class="radio">
<input type="radio" name="type" value="2"> Or
<input type="radio" name="type" value="2"> {intl l='Or'}
</label>
</div>
<div class="form-group col-md-4">
<label for="category-rule">Rule's category :</label>
<label for="category-rule">{intl l='Rule\'s category :'}</label>
<select name="categoryRule" id="category-rule" class="form-control">
<option value="1" selected>Total amount</option>
<option value="2">Date</option>
@@ -249,7 +229,7 @@
</div>
<div class="form-group col-md-6">
<label for="operator">Operator :</label>
<label for="operator">{intl l='Operator :'}</label>
<div class="row">
<div class="col-lg-6">
<select name="operator" id="operator" class="form-control">