Coupon : Condition module refactor

Less crappy unmaintainable javascript
More logic in extendable php
This commit is contained in:
gmorel
2014-01-05 00:00:15 +01:00
parent 49782765b4
commit e606a6f8ce
31 changed files with 1086 additions and 612 deletions

View File

@@ -156,7 +156,7 @@ class Coupon extends BaseAction implements EventSubscriberInterface
/** @var ConditionFactory $conditionFactory */
$conditionFactory = $this->container->get('thelia.condition.factory');
$couponRuleCollection = new ConditionCollection();
$couponRuleCollection->add($noConditionRule);
$couponRuleCollection[] = $noConditionRule;
$defaultSerializedRule = $conditionFactory->serializeConditionCollection(
$couponRuleCollection
);

View File

@@ -23,6 +23,9 @@
namespace Thelia\Condition;
use ArrayAccess;
use Countable;
use Iterator;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Thelia\Condition\Implementation\ConditionInterface;
@@ -33,43 +36,153 @@ use Thelia\Condition\Implementation\ConditionInterface;
* @author Guillaume MOREL <gmorel@openstudio.fr>
*
*/
class ConditionCollection
class ConditionCollection implements Iterator, Countable, ArrayAccess
{
/** @var array Array of ConditionInterface */
protected $conditions = array();
/**
* Get Conditions
* (PHP 5 &gt;= 5.0.0)
* Return the current element
* @link http://php.net/manual/en/iterator.current.php
*
* @return array Array of ConditionInterface
* @return mixed Can return any type.
*/
public function getConditions()
public function current()
{
return $this->conditions;
$var = current($this->conditions);
return $var;
}
/**
* Add a ConditionInterface to the Collection
* (PHP 5 &gt;= 5.0.0)
* Move forward to next element
* @link http://php.net/manual/en/iterator.next.php
*
* @param ConditionInterface $condition Condition
*
* @return $this
* @return void Any returned value is ignored.
*/
public function add(ConditionInterface $condition)
public function next()
{
$this->conditions[] = $condition;
return $this;
next($this->conditions);
}
/**
* Check if there is at least one condition in the collection
* (PHP 5 &gt;= 5.0.0)
* Return the key of the current element
* @link http://php.net/manual/en/iterator.key.php
*
* @return bool
* @return mixed scalar on success, or null on failure.
*/
public function isEmpty()
public function key()
{
return (empty($this->conditions));
$var = key($this->conditions);
return $var;
}
/**
* (PHP 5 &gt;= 5.0.0)
* Checks if current position is valid
* @link http://php.net/manual/en/iterator.valid.php
*
* @return boolean The return value will be casted to boolean and then evaluated.
* Returns true on success or false on failure.
*/
public function valid()
{
$key = key($this->conditions);
$var = ($key !== null && $key !== false);
return $var;
}
/**
* (PHP 5 &gt;= 5.0.0)
* Rewind the Iterator to the first element
* @link http://php.net/manual/en/iterator.rewind.php
*
* @return void Any returned value is ignored.
*/
public function rewind()
{
reset($this->conditions);
}
/**
* (PHP 5 &gt;= 5.1.0)
* Count elements of an object
* @link http://php.net/manual/en/countable.count.php
*
* @return int The custom count as an integer.
* The return value is cast to an integer.
*/
public function count()
{
return count($this->conditions);
}
/**
* (PHP 5 >= 5.0.0)
* Whether a offset exists
* @link http://php.net/manual/en/arrayaccess.offsetexists.php
* @param mixed $offset
* An offset to check for.
*
* @return boolean true on success or false on failure.
* The return value will be casted to boolean if non-boolean was returned.
*/
public function offsetExists($offset)
{
return isset($this->conditions[$offset]);
}
/**
* (PHP 5 >= 5.0.0)
* Offset to retrieve
* @link http://php.net/manual/en/arrayaccess.offsetget.php
* @param mixed $offset
* The offset to retrieve.
*
* @return mixed Can return all value types.
*/
public function offsetGet($offset)
{
return isset($this->conditions[$offset]) ? $this->conditions[$offset] : null;
}
/**
* (PHP 5 >= 5.0.0)
* Offset to set
* @link http://php.net/manual/en/arrayaccess.offsetset.php
* @param mixed $offset
* The offset to assign the value to.
* @param mixed $value
* The value to set.
*
* @return void
*/
public function offsetSet($offset, $value)
{
if (is_null($offset)) {
$this->conditions[] = $value;
} else {
$this->conditions[$offset] = $value;
}
}
/**
* (PHP 5 >= 5.0.0)
* Offset to unset
* @link http://php.net/manual/en/arrayaccess.offsetunset.php
* @param mixed $offset
* The offset to unset.
*
* @return void
*/
public function offsetUnset($offset)
{
unset($this->conditions[$offset]);
}
/**
@@ -81,12 +194,11 @@ class ConditionCollection
{
$arrayToSerialize = array();
/** @var ConditionInterface $condition */
foreach ($this->getConditions() as $condition) {
foreach ($this as $condition) {
$arrayToSerialize[] = $condition->getSerializableCondition();
}
return json_encode($arrayToSerialize);
}
}

View File

@@ -49,7 +49,7 @@ class ConditionEvaluator
{
$isMatching = true;
/** @var ConditionInterface $condition */
foreach ($conditions->getConditions() as $condition) {
foreach ($conditions as $condition) {
if (!$condition->isMatching()) {
$isMatching = false;
}

View File

@@ -67,20 +67,17 @@ class ConditionFactory
*/
public function serializeConditionCollection(ConditionCollection $collection)
{
if ($collection->isEmpty()) {
if ($collection->count() == 0) {
/** @var ConditionInterface $conditionNone */
$conditionNone = $this->container->get(
'thelia.condition.match_for_everyone'
);
$collection->add($conditionNone);
$collection[] = $conditionNone;
}
$serializableConditions = array();
$conditions = $collection->getConditions();
if ($conditions !== null) {
/** @var $condition ConditionInterface */
foreach ($conditions as $condition) {
$serializableConditions[] = $condition->getSerializableCondition();
}
/** @var $condition ConditionInterface */
foreach ($collection as $condition) {
$serializableConditions[] = $condition->getSerializableCondition();
}
return base64_encode(json_encode($serializableConditions));
@@ -109,7 +106,7 @@ class ConditionFactory
(array) $condition->operators,
(array) $condition->values
);
$collection->add(clone $conditionManager);
$collection[] = clone $conditionManager;
}
}
}
@@ -138,7 +135,7 @@ class ConditionFactory
$condition = $this->container->get($conditionServiceId);
$condition->setValidatorsFromForm($operators, $values);
return $condition;
return clone $condition;
}
/**
@@ -148,7 +145,7 @@ class ConditionFactory
*
* @return array Ready to be drawn condition inputs
*/
public function getInputs($conditionServiceId)
public function getInputsFromServiceId($conditionServiceId)
{
if (!$this->container->has($conditionServiceId)) {
return false;
@@ -157,6 +154,19 @@ class ConditionFactory
/** @var ConditionInterface $condition */
$condition = $this->container->get($conditionServiceId);
return $this->getInputsFromConditionInterface($condition);
}
/**
* Get Condition inputs from serviceId
*
* @param ConditionInterface $condition ConditionManager
*
* @return array Ready to be drawn condition inputs
*/
public function getInputsFromConditionInterface(ConditionInterface $condition)
{
return $condition->getValidators();
}
}

View File

@@ -219,4 +219,101 @@ abstract class ConditionAbstract implements ConditionInterface
return true;
}
/**
* Draw the operator input displayed in the BackOffice
* allowing Admin to set its Coupon Conditions
*
* @param string $inputKey Input key (ex: self::INPUT1)
*
* @return string HTML string
*/
protected function drawBackOfficeInputOperators($inputKey)
{
$selectHtml = '';
$optionHtml = '';
$inputs = $this->getValidators();
if(isset($inputs['inputs'][$inputKey])) {
$operators = $inputs['inputs'][$inputKey]['availableOperators'];
foreach ($operators as $key => $operator) {
$selected = '';
if (isset($this->operators) && isset($this->operators[$inputKey]) && $this->operators[$inputKey] == $key) {
$selected = ' selected="selected"';
}
$optionHtml .= '<option value="' . $key . '" '. $selected . '>' . $operator . '</option>';
}
$selectHtml .= '
<select class="form-control" id="' . $inputKey . '-operator" name="' . $inputKey . '[operator]">
' . $optionHtml . '
</select>
';
}
return $selectHtml;
}
/**
* Draw the base input displayed in the BackOffice
* allowing Admin to set its Coupon Conditions
*
* @param string $label I18n input label
* @param string $inputKey Input key (ex: self::INPUT1)
*
* @return string HTML string
*/
protected function drawBackOfficeBaseInputsText($label, $inputKey)
{
$operatorSelectHtml = $this->drawBackOfficeInputOperators($inputKey);
$currentValue = '';
if (isset($this->values) && isset($this->values[$inputKey])) {
$currentValue = $this->values[$inputKey];
}
$html = '
<div id="condition-add-operators-values" class="form-group col-md-6">
<label for="operator">' . $label . '</label>
<div class="row">
<div class="col-lg-6">
' . $operatorSelectHtml . '
</div>
<div class="input-group col-lg-6">
<input type="text" class="form-control" id="' . $inputKey . '-value" name="' . $inputKey . '[value]" value="' . $currentValue . '">
</div>
</div>
</div>
';
return $html;
}
/**
* Draw the quantity input displayed in the BackOffice
* allowing Admin to set its Coupon Conditions
*
* @param string $inputKey Input key (ex: self::INPUT1)
* @param int $max Maximum selectable
* @param int $min Minimum selectable
*
* @return string HTML string
*/
protected function drawBackOfficeInputQuantityValues($inputKey, $max = 10, $min = 0)
{
$selectHtml = '';
$optionHtml = '';
for ($i = $min; $i <= $max; $i++) {
$selected = '';
if (isset($this->values) && isset($this->values[$inputKey]) && $this->values[$inputKey] == $i) {
$selected = ' selected="selected"';
}
$optionHtml .= '<option value="' . $i . '" ' . $selected . '>' . $i . '</option>';
}
$selectHtml .= '
<select class="form-control" id="' . $inputKey . '-value" name="' . $inputKey . '[value]">
' . $optionHtml . '
</select>
';
return $selectHtml;
}
}

View File

@@ -85,11 +85,20 @@ interface ConditionInterface
/**
* Get I18n tooltip
* Explain in detail what the Condition checks
*
* @return string
*/
public function getToolTip();
/**
* Get I18n summary
* Explain briefly the condition with given values
*
* @return string
*/
public function getSummary();
/**
* Return all validators
*
@@ -104,4 +113,12 @@ interface ConditionInterface
*/
public function getSerializableCondition();
/**
* Draw the input displayed in the BackOffice
* allowing Admin to set its Coupon Conditions
*
* @return string HTML string
*/
public function drawBackOfficeInputs();
}

View File

@@ -97,6 +97,7 @@ class MatchForEveryone extends ConditionAbstract
/**
* Get I18n tooltip
* Explain in detail what the Condition checks
*
* @return string
*/
@@ -111,6 +112,23 @@ class MatchForEveryone extends ConditionAbstract
return $toolTip;
}
/**
* Get I18n summary
* Explain briefly the condition with given values
*
* @return string
*/
public function getSummary()
{
$toolTip = $this->translator->trans(
'Will return always true',
array(),
'condition'
);
return $toolTip;
}
/**
* Generate inputs ready to be drawn
*
@@ -121,4 +139,17 @@ class MatchForEveryone extends ConditionAbstract
return array();
}
/**
* Draw the input displayed in the BackOffice
* allowing Admin to set its Coupon Conditions
*
* @return string HTML string
*/
public function drawBackOfficeInputs()
{
// No input
return '';
}
}

View File

@@ -167,7 +167,7 @@ class MatchForTotalAmount extends ConditionAbstract
public function getName()
{
return $this->translator->trans(
'Cart total amount',
'By cart total amount',
array(),
'condition'
);
@@ -175,10 +175,28 @@ class MatchForTotalAmount extends ConditionAbstract
/**
* Get I18n tooltip
* Explain in detail what the Condition checks
*
* @return string
*/
public function getToolTip()
{
$toolTip = $this->translator->trans(
'Check the total Cart amount in the given currency',
array(),
'condition'
);
return $toolTip;
}
/**
* Get I18n summary
* Explain briefly the condition with given values
*
* @return string
*/
public function getSummary()
{
$i18nOperator = Operators::getI18n(
$this->translator, $this->operators[self::INPUT1]
@@ -227,8 +245,6 @@ class MatchForTotalAmount extends ConditionAbstract
'title' => $name1,
'availableOperators' => $this->availableOperators[self::INPUT1],
'availableValues' => '',
'type' => 'text',
'class' => 'form-control',
'value' => '',
'selectedOperator' => ''
),
@@ -236,12 +252,100 @@ class MatchForTotalAmount extends ConditionAbstract
'title' => $name2,
'availableOperators' => $this->availableOperators[self::INPUT2],
'availableValues' => $cleanedCurrencies,
'type' => 'select',
'class' => 'form-control',
'value' => '',
'selectedOperator' => Operators::EQUAL
)
);
}
/**
* Draw the input displayed in the BackOffice
* allowing Admin to set its Coupon Conditions
*
* @return string HTML string
*/
public function drawBackOfficeInputs()
{
$labelPrice = $this->facade
->getTranslator()
->trans('Price', array(), 'condition');
$html = $this->drawBackOfficeBaseInputsText($labelPrice, self::INPUT1);
return $html;
}
/**
* Draw the base input displayed in the BackOffice
* allowing Admin to set its Coupon Conditions
*
* @param string $label I18n input label
* @param string $inputKey Input key (ex: self::INPUT1)
*
* @return string HTML string
*/
protected function drawBackOfficeBaseInputsText($label, $inputKey)
{
$operatorSelectHtml = $this->drawBackOfficeInputOperators(self::INPUT1);
$currencySelectHtml = $this->drawBackOfficeCurrencyInput(self::INPUT2);
$selectedAmount = '';
if (isset($this->values) && isset($this->values[$inputKey])) {
$selectedAmount = $this->values[$inputKey];
}
$html = '
<label for="operator">' . $label . '</label>
<div class="row">
<div class="col-lg-6">
' . $operatorSelectHtml . '
</div>
<div class="input-group col-lg-3">
<input type="text" class="form-control" id="' . self::INPUT1 . '-value" name="' . self::INPUT1 . '[value]" value="' . $selectedAmount . '">
</div>
<div class="input-group col-lg-3">
<input type="hidden" id="' . self::INPUT2 . '-operator" name="' . self::INPUT2 . '[operator]" value="==" />
' . $currencySelectHtml . '
</div>
</div>
';
return $html;
}
/**
* Draw the currency input displayed in the BackOffice
* allowing Admin to set its Coupon Conditions
*
* @param string $inputKey Input key (ex: self::INPUT1)
*
* @return string HTML string
*/
protected function drawBackOfficeCurrencyInput($inputKey)
{
$optionHtml = '';
$currencies = CurrencyQuery::create()->find();
$cleanedCurrencies = array();
/** @var Currency $currency */
foreach ($currencies as $currency) {
$cleanedCurrencies[$currency->getCode()] = $currency->getSymbol();
}
foreach ($cleanedCurrencies as $key => $cleanedCurrency) {
$selected = '';
if (isset($this->values) && isset($this->values[$inputKey]) && $this->values[$inputKey] == $key) {
$selected = ' selected="selected"';
}
$optionHtml .= '<option value="' . $key . '" ' . $selected . '>' . $cleanedCurrency . '</option>';
}
$selectHtml = '
<select class="form-control" id="' . $inputKey . '-value" name="' . $inputKey . '[value]">
' . $optionHtml . '
</select>
';
return $selectHtml;
}
}

View File

@@ -140,7 +140,7 @@ class MatchForXArticles extends ConditionAbstract
public function getName()
{
return $this->translator->trans(
'Number of articles in cart',
'By number of articles in cart',
array(),
'condition'
);
@@ -148,10 +148,28 @@ class MatchForXArticles extends ConditionAbstract
/**
* Get I18n tooltip
* Explain in detail what the Condition checks
*
* @return string
*/
public function getToolTip()
{
$toolTip = $this->translator->trans(
'Check the amount of product in the Cart',
array(),
'condition'
);
return $toolTip;
}
/**
* Get I18n summary
* Explain briefly the condition with given values
*
* @return string
*/
public function getSummary()
{
$i18nOperator = Operators::getI18n(
$this->translator, $this->operators[self::INPUT1]
@@ -186,11 +204,57 @@ class MatchForXArticles extends ConditionAbstract
self::INPUT1 => array(
'title' => $name1,
'availableOperators' => $this->availableOperators[self::INPUT1],
'type' => 'text',
'class' => 'form-control',
'value' => '',
'selectedOperator' => ''
)
);
}
/**
* Draw the input displayed in the BackOffice
* allowing Admin to set its Coupon Conditions
*
* @return string HTML string
*/
public function drawBackOfficeInputs()
{
$labelQuantity = $this->facade
->getTranslator()
->trans('Quantity', array(), 'condition');
$html = $this->drawBackOfficeBaseInputsText($labelQuantity, self::INPUT1);
return $html;
}
/**
* Draw the base input displayed in the BackOffice
* allowing Admin to set its Coupon Conditions
*
* @param string $label I18n input label
* @param string $inputKey Input key (ex: self::INPUT1)
*
* @return string HTML string
*/
protected function drawBackOfficeBaseInputsText($label, $inputKey)
{
$operatorSelectHtml = $this->drawBackOfficeInputOperators($inputKey);
$quantitySelectHtml = $this->drawBackOfficeInputQuantityValues($inputKey, 20, 1);
$html = '
<div id="condition-add-operators-values" class="form-group col-md-6">
<label for="operator">' . $label . '</label>
<div class="row">
<div class="col-lg-6">
' . $operatorSelectHtml . '
</div>
<div class="input-group col-lg-6">
' . $quantitySelectHtml . '
</div>
</div>
</div>
';
return $html;
}
}

View File

@@ -499,17 +499,31 @@
<default key="_controller">Thelia\Controller\Admin\CouponController::readAction</default>
<requirement key="couponId">\d+</requirement>
</route>
<route id="admin.coupon.draw.inputs" path="/admin/coupon/draw/inputs/{couponServiceId}">
<default key="_controller">Thelia\Controller\Admin\CouponController::getBackOfficeInputsAction</default>
<route id="admin.coupon.draw.inputs.ajax" path="/admin/coupon/draw/inputs/{couponServiceId}">
<default key="_controller">Thelia\Controller\Admin\CouponController::getBackOfficeInputsAjaxAction</default>
<requirement key="couponServiceId">.*</requirement>
</route>
<route id="admin.coupon.condition.input" path="/admin/coupon/condition/{conditionId}">
<default key="_controller">Thelia\Controller\Admin\CouponController::getConditionInputAction</default>
<route id="admin.coupon.draw.condition.summaries.ajax" path="/admin/coupon/draw/conditionsSummaries/{couponId}">
<default key="_controller">Thelia\Controller\Admin\CouponController::getBackOfficeConditionSummariesAjaxAction</default>
<requirement key="couponId">\d+</requirement>
</route>
<route id="admin.coupon.draw.condition.read.inputs.ajax" path="/admin/coupon/draw/read/conditionInputs/{conditionId}">
<default key="_controller">Thelia\Controller\Admin\CouponController::getConditionEmptyInputAjaxAction</default>
<requirement key="conditionId">.*</requirement>
</route>
<route id="admin.coupon.condition.update" path="/admin/coupon/{couponId}/condition/update">
<default key="_controller">Thelia\Controller\Admin\CouponController::updateConditionsAction</default>
<route id="admin.coupon.draw.condition.update.inputs.ajax" path="/admin/coupon/draw/update/conditionInputs/{couponId}/{conditionIndex}">
<default key="_controller">Thelia\Controller\Admin\CouponController::getConditionToUpdateInputAjaxAction</default>
<requirement key="couponId">\d+</requirement>
<requirement key="conditionIndex">\d+</requirement>
</route>
<route id="admin.coupon.condition.save" path="/admin/coupon/{couponId}/condition/save" methods="post">
<default key="_controller">Thelia\Controller\Admin\CouponController::saveConditionsAction</default>
<requirement key="couponId">\d+</requirement>
</route>
<route id="admin.coupon.condition.delete" path="/admin/coupon/{couponId}/condition/delete/{conditionIndex}">
<default key="_controller">Thelia\Controller\Admin\CouponController::deleteConditionsAction</default>
<requirement key="couponId">\d+</requirement>
<requirement key="conditionIndex">\d+</requirement>
</route>
<route id="admin.coupon.consume" path="/admin/coupon/consume/{couponCode}">
<default key="_controller">Thelia\Controller\Admin\CouponController::consumeAction</default>

View File

@@ -25,6 +25,7 @@ namespace Thelia\Controller\Admin;
use Symfony\Component\Form\Form;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Router;
use Thelia\Condition\ConditionFactory;
use Thelia\Condition\Implementation\ConditionInterface;
@@ -235,18 +236,6 @@ class CouponController extends BaseAdminController
'locale' => $coupon->getLocale(),
);
$args['conditionsObject'] = array();
/** @var ConditionInterface $condition */
foreach ($conditions->getConditions() as $condition) {
$args['conditionsObject'][] = array(
'serviceId' => $condition->getServiceId(),
'name' => $condition->getName(),
'tooltip' => $condition->getToolTip(),
'validators' => $condition->getValidators()
);
}
$args['conditions'] = $this->cleanConditionForTemplate($conditions);
// Setup the object form
@@ -259,19 +248,40 @@ class CouponController extends BaseAdminController
$args['availableCoupons'] = $this->getAvailableCoupons();
$args['couponInputsHtml'] = $couponManager->drawBackOfficeInputs();
$args['urlAjaxAdminCouponDrawInputs'] = $this->getRoute(
'admin.coupon.draw.inputs',
'admin.coupon.draw.inputs.ajax',
array('couponServiceId' => 'couponServiceId'),
Router::ABSOLUTE_URL
);
$args['availableConditions'] = $this->getAvailableConditions();
$args['urlAjaxGetConditionInput'] = $this->getRoute(
'admin.coupon.condition.input',
$args['urlAjaxGetConditionInputFromServiceId'] = $this->getRoute(
'admin.coupon.draw.condition.read.inputs.ajax',
array('conditionId' => 'conditionId'),
Router::ABSOLUTE_URL
);
$args['urlAjaxGetConditionInputFromConditionInterface'] = $this->getRoute(
'admin.coupon.draw.condition.update.inputs.ajax',
array(
'couponId' => $couponId,
'conditionIndex' => 8888888
),
Router::ABSOLUTE_URL
);
$args['urlAjaxUpdateConditions'] = $this->getRoute(
'admin.coupon.condition.update',
$args['urlAjaxSaveConditions'] = $this->getRoute(
'admin.coupon.condition.save',
array('couponId' => $couponId),
Router::ABSOLUTE_URL
);
$args['urlAjaxDeleteConditions'] = $this->getRoute(
'admin.coupon.condition.delete',
array(
'couponId' => $couponId,
'conditionIndex' => 8888888
),
Router::ABSOLUTE_URL
);
$args['urlAjaxGetConditionSummaries'] = $this->getRoute(
'admin.coupon.draw.condition.summaries.ajax',
array('couponId' => $couponId),
Router::ABSOLUTE_URL
);
@@ -288,7 +298,7 @@ class CouponController extends BaseAdminController
*
* @return \Thelia\Core\HttpFoundation\Response
*/
public function getConditionInputAction($conditionId)
public function getConditionEmptyInputAjaxAction($conditionId)
{
$this->checkAuth(AdminResources::COUPON, array(), AccessManager::VIEW);
@@ -296,7 +306,14 @@ class CouponController extends BaseAdminController
/** @var ConditionFactory $conditionFactory */
$conditionFactory = $this->container->get('thelia.condition.factory');
$inputs = $conditionFactory->getInputs($conditionId);
$inputs = $conditionFactory->getInputsFromServiceId($conditionId);
if (!$this->container->has($conditionId)) {
return false;
}
/** @var ConditionInterface $condition */
$condition = $this->container->get($conditionId);
if ($inputs === null) {
return $this->pageNotFound();
@@ -305,8 +322,64 @@ class CouponController extends BaseAdminController
return $this->render(
'coupon/condition-input-ajax',
array(
'conditionId' => $conditionId,
'inputs' => $inputs
'inputsDrawn' => $condition->drawBackOfficeInputs(),
'conditionServiceId' => $condition->getServiceId(),
'conditionIndex' => -1,
)
);
}
/**
* Manage Coupons read display
*
* @param int $couponId Coupon id being updated
* @param int $conditionIndex Coupon Condition position in the collection
*
* @return \Thelia\Core\HttpFoundation\Response
*/
public function getConditionToUpdateInputAjaxAction($couponId, $conditionIndex)
{
$this->checkAuth(AdminResources::COUPON, array(), AccessManager::VIEW);
$this->checkXmlHttpRequest();
$search = CouponQuery::create();
/** @var Coupon $coupon */
$coupon = $search->findOneById($couponId);
if (!$coupon) {
return $this->pageNotFound();
}
/** @var CouponFactory $couponFactory */
$couponFactory = $this->container->get('thelia.coupon.factory');
$couponManager = $couponFactory->buildCouponFromModel($coupon);
if (!$couponManager instanceof CouponInterface) {
return $this->pageNotFound();
}
$conditions = $couponManager->getConditions();
if (!isset($conditions[$conditionIndex])) {
return $this->pageNotFound();
}
/** @var ConditionInterface $condition */
$condition = $conditions[$conditionIndex];
/** @var ConditionFactory $conditionFactory */
$conditionFactory = $this->container->get('thelia.condition.factory');
$inputs = $conditionFactory->getInputsFromConditionInterface($condition);
if ($inputs === null) {
return $this->pageNotFound();
}
return $this->render(
'coupon/condition-input-ajax',
array(
'inputsDrawn' => $condition->drawBackOfficeInputs(),
'conditionServiceId' => $condition->getServiceId(),
'conditionIndex' => $conditionIndex,
)
);
}
@@ -318,7 +391,7 @@ class CouponController extends BaseAdminController
*
* @return \Thelia\Core\HttpFoundation\Response
*/
public function updateConditionsAction($couponId)
public function saveConditionsAction($couponId)
{
$this->checkAuth(AdminResources::COUPON, array(), AccessManager::VIEW);
@@ -327,70 +400,72 @@ class CouponController extends BaseAdminController
$search = CouponQuery::create();
/** @var Coupon $coupon */
$coupon = $search->findOneById($couponId);
if (!$coupon) {
return $this->pageNotFound();
}
$conditions = new ConditionCollection();
$conditionToSave = $this->buildConditionFromRequest();
/** @var ConditionFactory $conditionFactory */
$conditionFactory = $this->container->get('thelia.condition.factory');
$conditionsReceived = json_decode($this->getRequest()->get('conditions'));
foreach ($conditionsReceived as $conditionReceived) {
$condition = $conditionFactory->build(
$conditionReceived->serviceId,
(array) $conditionReceived->operators,
(array) $conditionReceived->values
);
$conditions->add(clone $condition);
/** @var CouponFactory $couponFactory */
$couponFactory = $this->container->get('thelia.coupon.factory');
$couponManager = $couponFactory->buildCouponFromModel($coupon);
if (!$couponManager instanceof CouponInterface) {
return $this->pageNotFound();
}
$couponEvent = new CouponCreateOrUpdateEvent(
$coupon->getCode(),
$coupon->getType(),
$coupon->getTitle(),
$coupon->getEffects(),
$coupon->getShortDescription(),
$coupon->getDescription(),
$coupon->getIsEnabled(),
$coupon->getExpirationDate(),
$coupon->getIsAvailableOnSpecialOffers(),
$coupon->getIsCumulative(),
$coupon->getIsRemovingPostage(),
$coupon->getMaxUsage(),
$coupon->getLocale()
);
$couponEvent->setCouponModel($coupon);
$couponEvent->setConditions($conditions);
$conditions = $couponManager->getConditions();
$conditionIndex = $this->getRequest()->request->get('conditionIndex');
if ($conditionIndex >= 0) {
// Update mode
$conditions[$conditionIndex] = $conditionToSave;
} else {
// Insert mode
$conditions[] = $conditionToSave;
}
$couponManager->setConditions($conditions);
$eventToDispatch = TheliaEvents::COUPON_CONDITION_UPDATE;
// Dispatch Event to the Action
$this->dispatch(
$eventToDispatch,
$couponEvent
);
$this->manageConditionUpdate($coupon, $conditions);
$this->adminLogAppend(
AdminResources::COUPON, AccessManager::UPDATE,
sprintf(
'Coupon %s (ID %s) conditions updated',
$couponEvent->getCouponModel()->getTitle(),
$couponEvent->getCouponModel()->getType()
)
);
return new Response();
}
$cleanedConditions = $this->cleanConditionForTemplate($conditions);
/**
* Manage Coupons condition deleteion
*
* @param int $couponId Coupon id
* @param int $conditionIndex Coupon condition index in the collection
*
* @return \Thelia\Core\HttpFoundation\Response
*/
public function deleteConditionsAction($couponId, $conditionIndex)
{
$this->checkAuth(AdminResources::COUPON, array(), AccessManager::VIEW);
return $this->render(
'coupon/conditions',
array(
'couponId' => $couponId,
'conditions' => $cleanedConditions,
'urlEdit' => $couponId,
'urlDelete' => $couponId
)
);
$this->checkXmlHttpRequest();
$search = CouponQuery::create();
/** @var Coupon $coupon */
$coupon = $search->findOneById($couponId);
if (!$coupon) {
return $this->pageNotFound();
}
/** @var CouponFactory $couponFactory */
$couponFactory = $this->container->get('thelia.coupon.factory');
$couponManager = $couponFactory->buildCouponFromModel($coupon);
if (!$couponManager instanceof CouponInterface) {
return $this->pageNotFound();
}
$conditions = $couponManager->getConditions();
unset($conditions[$conditionIndex]);
$couponManager->setConditions($conditions);
$this->manageConditionUpdate($coupon, $conditions);
return new Response();
}
/**
@@ -577,8 +652,16 @@ class CouponController extends BaseAdminController
{
$cleanedConditions = array();
/** @var $condition ConditionInterface */
foreach ($conditions->getConditions() as $condition) {
$cleanedConditions[] = $condition->getToolTip();
foreach ($conditions as $index => $condition) {
$temp = array(
'serviceId' => $condition->getServiceId(),
'index' => $index,
'name' => $condition->getName(),
'toolTip' => $condition->getToolTip(),
'summary' => $condition->getSummary(),
'validators' => $condition->getValidators()
);
$cleanedConditions[] = $temp;
}
return $cleanedConditions;
@@ -592,20 +675,57 @@ class CouponController extends BaseAdminController
*
* @return ResponseRest
*/
public function getBackOfficeInputsAction($couponServiceId)
public function getBackOfficeInputsAjaxAction($couponServiceId)
{
/** @var CouponInterface $coupon */
$coupon = $this->container->get($couponServiceId);
$this->checkAuth(AdminResources::COUPON, array(), AccessManager::VIEW);
$this->checkXmlHttpRequest();
if (!$coupon instanceof CouponInterface) {
/** @var CouponInterface $coupon */
$couponManager = $this->container->get($couponServiceId);
if (!$couponManager instanceof CouponInterface) {
$this->pageNotFound();
}
$response = new ResponseRest($coupon->drawBackOfficeInputs());
$response = new ResponseRest($couponManager->drawBackOfficeInputs());
return $response;
}
/**
* Draw the input displayed in the BackOffice
* allowing Admin to set its Coupon effect
*
* @param int $couponId Coupon id
*
* @return ResponseRest
*/
public function getBackOfficeConditionSummariesAjaxAction($couponId)
{
$this->checkAuth(AdminResources::COUPON, array(), AccessManager::VIEW);
$this->checkXmlHttpRequest();
/** @var Coupon $coupon */
$coupon = CouponQuery::create()->findPk($couponId);
if (null === $coupon) {
return $this->pageNotFound();
}
/** @var CouponFactory $couponFactory */
$couponFactory = $this->container->get('thelia.coupon.factory');
$couponManager = $couponFactory->buildCouponFromModel($coupon);
if (!$couponManager instanceof CouponInterface) {
return $this->pageNotFound();
}
$args = array();
$args['conditions'] = $this->cleanConditionForTemplate($couponManager->getConditions());
return $this->render('coupon/conditions', $args);
}
/**
* Add percentage logic if found in the Coupon post data
*
@@ -677,4 +797,73 @@ class CouponController extends BaseAdminController
return $couponEvent;
}
/**
* Build ConditionInterface from request
*
* @return ConditionInterface
*/
protected function buildConditionFromRequest()
{
$request = $this->getRequest();
$post = $request->request->getIterator();
$serviceId = $request->request->get('categoryCondition');
$operators = array();
$values = array();
foreach ($post as $key => $input) {
if (isset($input['operator']) && isset($input['value'])) {
$operators[$key] = $input['operator'];
$values[$key] = $input['value'];
}
}
/** @var ConditionFactory $conditionFactory */
$conditionFactory = $this->container->get('thelia.condition.factory');
$conditionToSave = $conditionFactory->build($serviceId, $operators, $values);
return $conditionToSave;
}
/**
* Manage how a Condition is updated
*
* @param Coupon $coupon Coupon Model
* @param ConditionCollection $conditions Condition collection
*/
protected function manageConditionUpdate(Coupon $coupon, ConditionCollection $conditions)
{
$couponEvent = new CouponCreateOrUpdateEvent(
$coupon->getCode(),
$coupon->getType(),
$coupon->getTitle(),
$coupon->getEffects(),
$coupon->getShortDescription(),
$coupon->getDescription(),
$coupon->getIsEnabled(),
$coupon->getExpirationDate(),
$coupon->getIsAvailableOnSpecialOffers(),
$coupon->getIsCumulative(),
$coupon->getIsRemovingPostage(),
$coupon->getMaxUsage(),
$coupon->getLocale()
);
$couponEvent->setCouponModel($coupon);
$couponEvent->setConditions($conditions);
$eventToDispatch = TheliaEvents::COUPON_CONDITION_UPDATE;
// Dispatch Event to the Action
$this->dispatch(
$eventToDispatch,
$couponEvent
);
$this->adminLogAppend(
AdminResources::COUPON, AccessManager::UPDATE,
sprintf(
'Coupon %s (ID %s) conditions updated',
$couponEvent->getCouponModel()->getTitle(),
$couponEvent->getCouponModel()->getType()
)
);
}
}

View File

@@ -122,8 +122,12 @@ class Coupon extends BaseI18nLoop implements PropelSearchLoopInterface
$cleanedConditions = array();
/** @var ConditionInterface $condition */
foreach ($conditions->getConditions() as $condition) {
$cleanedConditions[] = $condition->getToolTip();
foreach ($conditions as $condition) {
$temp = array(
'toolTip' => $condition->getToolTip(),
'summary' => $condition->getSummary()
);
$cleanedConditions[] = $temp;
}
$loopResultRow->set("ID", $coupon->getId())
->set("IS_TRANSLATED", $coupon->getVirtualColumn('IS_TRANSLATED'))

View File

@@ -79,7 +79,7 @@ class CouponFactory
/** @var CouponInterface $couponInterface */
$couponInterface = $this->buildCouponFromModel($couponModel);
if ($couponInterface && $couponInterface->getConditions()->isEmpty()) {
if ($couponInterface && $couponInterface->getConditions()->count() == 0) {
throw new InvalidConditionException(
get_class($couponInterface)
);
@@ -129,7 +129,7 @@ class CouponFactory
$couponManager->setConditions($conditions);
return $couponManager;
return clone $couponManager;
}

View File

@@ -23,7 +23,6 @@
namespace Thelia\Coupon\Type;
use Thelia\Coupon\FacadeInterface;
use Thelia\Coupon\Type\CouponAbstract;
/**

View File

@@ -105,8 +105,7 @@ class ConditionCollectionTest extends \PHPUnit_Framework_TestCase
}
/**
* @covers Thelia\Condition\ConditionCollection::getConditions
* @covers Thelia\Condition\ConditionCollection::add
*
*/
public function testGetConditions()
{
@@ -123,23 +122,23 @@ class ConditionCollectionTest extends \PHPUnit_Framework_TestCase
$condition1->setValidatorsFromForm($operators, $values);
$collection = new ConditionCollection();
$collection->add($condition1);
$collection[] = $condition1;
$expected = $condition1;
$actual = $collection->getConditions()[0];
$actual = $collection[0];
$this->assertEquals($expected, $actual);
$this->assertFalse($collection->isEmpty());
$this->assertFalse($collection->count() == 0);
}
/**
* @covers Thelia\Condition\ConditionCollection::isEmpty
* @covers Thelia\Condition\ConditionCollection::count
*/
public function testIsEmpty()
{
$collection = new ConditionCollection();
$this->assertTrue($collection->isEmpty());
$this->assertTrue($collection->count() == 0);
}
/**
@@ -170,8 +169,8 @@ class ConditionCollectionTest extends \PHPUnit_Framework_TestCase
$condition2->setValidatorsFromForm($operators2, $values2);
$collection = new ConditionCollection();
$collection->add($condition1);
$collection->add($condition2);
$collection[] = $condition1;
$collection[] = $condition2;
$expected = '[{"conditionServiceId":"thelia.condition.match_for_total_amount","operators":{"price":">","currency":"=="},"values":{"price":400,"currency":"EUR"}},{"conditionServiceId":"thelia.condition.match_for_total_amount","operators":{"price":"<","currency":"=="},"values":{"price":600,"currency":"EUR"}}]';
$actual = $collection->__toString();;

View File

@@ -157,8 +157,8 @@ class ConditionEvaluatorTest extends \PHPUnit_Framework_TestCase
->will($this->returnValue(true));
$collection = new ConditionCollection();
$collection->add($stubConditionTrue1);
$collection->add($stubConditionTrue2);
$collection[] = $stubConditionTrue1;
$collection[] = $stubConditionTrue2;
$conditionEvaluator = new ConditionEvaluator();
$actual = $conditionEvaluator->isMatching($collection);
@@ -188,8 +188,8 @@ class ConditionEvaluatorTest extends \PHPUnit_Framework_TestCase
->will($this->returnValue(false));
$collection = new ConditionCollection();
$collection->add($stubConditionTrue);
$collection->add($stubConditionFalse);
$collection[] = $stubConditionTrue;
$collection[] = $stubConditionFalse;
$conditionEvaluator = new ConditionEvaluator();
$actual = $conditionEvaluator->isMatching($collection);

View File

@@ -239,8 +239,8 @@ class ConditionFactoryTest extends \PHPUnit_Framework_TestCase
$condition2->setValidatorsFromForm($operators, $values);
$conditions = new ConditionCollection();
$conditions->add($condition1);
$conditions->add($condition2);
$conditions[] = $condition1;
$conditions[] = $condition2;
$conditionFactory = new ConditionFactory($stubContainer);
@@ -307,12 +307,12 @@ class ConditionFactoryTest extends \PHPUnit_Framework_TestCase
$condition1->setValidatorsFromForm($operators, $values);
$conditions = new ConditionCollection();
$conditions->add($condition1);
$conditions[] = $condition1;
$conditionFactory = new ConditionFactory($stubContainer);
$expected = $condition1->getValidators();
$actual = $conditionFactory->getInputs('thelia.condition.match_for_x_articles');
$actual = $conditionFactory->getInputsFromServiceId('thelia.condition.match_for_x_articles');
$this->assertEquals($expected, $actual);
@@ -372,12 +372,12 @@ class ConditionFactoryTest extends \PHPUnit_Framework_TestCase
$condition1->setValidatorsFromForm($operators, $values);
$conditions = new ConditionCollection();
$conditions->add($condition1);
$conditions[] = $condition1;
$conditionFactory = new ConditionFactory($stubContainer);
$expected = false;
$actual = $conditionFactory->getInputs('thelia.condition.unknown');
$actual = $conditionFactory->getInputsFromServiceId('thelia.condition.unknown');
$this->assertEquals($expected, $actual);
@@ -435,7 +435,7 @@ class ConditionFactoryTest extends \PHPUnit_Framework_TestCase
$conditionNone = new MatchForEveryone($stubFacade);
$expectedCollection = new ConditionCollection();
$expectedCollection->add($conditionNone);
$expectedCollection[] = $conditionNone;
$expected = $conditionFactory->serializeConditionCollection($expectedCollection);
$actual = $conditionFactory->serializeConditionCollection($conditions);

View File

@@ -659,7 +659,7 @@ class MatchForTotalAmountTest extends \PHPUnit_Framework_TestCase
$conditionFactory = new ConditionFactory($stubContainer);
$collection = new ConditionCollection();
$collection->add($condition1);
$collection[] = $condition1;
$serialized = $conditionFactory->serializeConditionCollection($collection);
$conditionFactory->unserializeConditionCollection($serialized);
@@ -726,7 +726,7 @@ class MatchForTotalAmountTest extends \PHPUnit_Framework_TestCase
$conditionFactory = new ConditionFactory($stubContainer);
$collection = new ConditionCollection();
$collection->add($condition1);
$collection[] = $condition1;
$serialized = $conditionFactory->serializeConditionCollection($collection);
$conditionFactory->unserializeConditionCollection($serialized);
@@ -793,7 +793,7 @@ class MatchForTotalAmountTest extends \PHPUnit_Framework_TestCase
$conditionFactory = new ConditionFactory($stubContainer);
$collection = new ConditionCollection();
$collection->add($condition1);
$collection[] = $condition1;
$serialized = $conditionFactory->serializeConditionCollection($collection);
$conditionFactory->unserializeConditionCollection($serialized);
@@ -927,8 +927,6 @@ class MatchForTotalAmountTest extends \PHPUnit_Framework_TestCase
'>' => 'Price'
),
'availableValues' => '',
'type' => 'text',
'class' => 'form-control',
'value' => '',
'selectedOperator' => ''
),
@@ -940,8 +938,6 @@ class MatchForTotalAmountTest extends \PHPUnit_Framework_TestCase
'USD' => '$',
'GBP' => '£',
),
'type' => 'select',
'class' => 'form-control',
'value' => '',
'selectedOperator' => Operators::EQUAL
)

View File

@@ -743,8 +743,6 @@ class MatchForXArticlesTest extends \PHPUnit_Framework_TestCase
'>=' => 'Price',
'>' => 'Price'
),
'type' => 'text',
'class' => 'form-control',
'value' => '',
'selectedOperator' => ''
)

View File

@@ -146,8 +146,8 @@ Sed facilisis pellentesque nisl, eu tincidunt erat scelerisque a. Nullam malesua
$condition2->setValidatorsFromForm($operators, $values);
$conditions = new ConditionCollection();
$conditions->add($condition1);
$conditions->add($condition2);
$conditions[] = $condition1;
$conditions[] = $condition2;
$serializedConditions = $conditionFactory->serializeConditionCollection($conditions);
$coupon1->setSerializedConditions($serializedConditions);
@@ -210,8 +210,8 @@ Sed facilisis pellentesque nisl, eu tincidunt erat scelerisque a. Nullam malesua
$condition2->setValidatorsFromForm($operators, $values);
$conditions = new ConditionCollection();
$conditions->add($condition1);
$conditions->add($condition2);
$conditions[] = $condition1;
$conditions[] = $condition2;
$stubConditionFactory = $this->getMockBuilder('\Thelia\Condition\ConditionFactory')
->disableOriginalConstructor()
->getMock();
@@ -312,8 +312,8 @@ Sed facilisis pellentesque nisl, eu tincidunt erat scelerisque a. Nullam malesua
$condition2->setValidatorsFromForm($operators, $values);
$conditions = new ConditionCollection();
$conditions->add($condition1);
$conditions->add($condition2);
$conditions[] = $condition1;
$conditions[] = $condition2;
$stubConditionFactory = $this->getMockBuilder('\Thelia\Condition\ConditionFactory')
->disableOriginalConstructor()
->getMock();
@@ -439,8 +439,8 @@ Sed facilisis pellentesque nisl, eu tincidunt erat scelerisque a. Nullam malesua
$condition2->setValidatorsFromForm($operators, $values);
$conditions = new ConditionCollection();
$conditions->add($condition1);
$conditions->add($condition2);
$conditions[] = $condition1;
$conditions[] = $condition2;
$stubConditionFactory = $this->getMockBuilder('\Thelia\Condition\ConditionFactory')
->disableOriginalConstructor()
->getMock();

View File

@@ -108,8 +108,8 @@ Sed facilisis pellentesque nisl, eu tincidunt erat scelerisque a. Nullam malesua
$condition2->setValidatorsFromForm($operators, $values);
$conditions = new ConditionCollection();
$conditions->add($condition1);
$conditions->add($condition2);
$conditions[] = $condition1;
$conditions[] = $condition2;
$serializedConditions = $conditionFactory->serializeConditionCollection($conditions);
$coupon1->setSerializedConditions($serializedConditions);
@@ -372,8 +372,8 @@ Sed facilisis pellentesque nisl, eu tincidunt erat scelerisque a. Nullam malesua
$condition2->setValidatorsFromForm($operators, $values);
$conditions = new ConditionCollection();
$conditions->add($condition1);
$conditions->add($condition2);
$conditions[] = $condition1;
$conditions[] = $condition2;
$stubFacade->expects($this->any())
->method('getCurrentCoupons')
@@ -428,8 +428,8 @@ Sed facilisis pellentesque nisl, eu tincidunt erat scelerisque a. Nullam malesua
$condition2->setValidatorsFromForm($operators, $values);
$conditions = new ConditionCollection();
$conditions->add($condition1);
$conditions->add($condition2);
$conditions[] = $condition1;
$conditions[] = $condition2;
$coupon->setConditions($conditions);
$stubFacade->expects($this->any())
@@ -495,8 +495,8 @@ Sed facilisis pellentesque nisl, eu tincidunt erat scelerisque a. Nullam malesua
$condition2->setValidatorsFromForm($operators, $values);
$conditions = new ConditionCollection();
$conditions->add($condition1);
$conditions->add($condition2);
$conditions[] = $condition1;
$conditions[] = $condition2;
$coupon->setConditions($conditions);
$stubFacade->expects($this->any())

View File

@@ -150,8 +150,8 @@ class RemoveXAmountTest extends \PHPUnit_Framework_TestCase
$condition2->setValidatorsFromForm($operators, $values);
$conditions = new ConditionCollection();
$conditions->add($condition1);
$conditions->add($condition2);
$conditions[] = $condition1;
$conditions[] = $condition2;
$coupon->setConditions($conditions);
$this->assertEquals('XMAS', $coupon->getCode());

View File

@@ -140,8 +140,8 @@ class RemoveXPercentTest extends \PHPUnit_Framework_TestCase
$condition2->setValidatorsFromForm($operators, $values);
$conditions = new ConditionCollection();
$conditions->add($condition1);
$conditions->add($condition2);
$conditions[] = $condition1;
$conditions[] = $condition2;
$coupon->setConditions($conditions);
$this->assertEquals('XMAS', $coupon->getCode());