From 8b6cbb06214139500e4ce0492af094460eaf820f Mon Sep 17 00:00:00 2001 From: gmorel Date: Wed, 28 Aug 2013 14:37:29 +0200 Subject: [PATCH] WIP - Beginning BackOffice Coupon implementation --- core/lib/Thelia/Action/Coupon.php | 79 +++++++ .../Thelia/Config/Resources/routing/admin.xml | 5 + .../Constraint/Rule/AvailableForCustomer.php | 203 ++++++++++++++++++ .../Constraint/Rule/AvailableForXArticles.php | 2 +- .../Constraint/Validator/CustomerParam.php | 158 ++++++++++++++ .../Controller/Admin/CouponController.php | 100 +++++++++ templates/default/coupon.html | 5 + 7 files changed, 551 insertions(+), 1 deletion(-) create mode 100755 core/lib/Thelia/Action/Coupon.php create mode 100644 core/lib/Thelia/Constraint/Rule/AvailableForCustomer.php create mode 100644 core/lib/Thelia/Constraint/Validator/CustomerParam.php create mode 100755 core/lib/Thelia/Controller/Admin/CouponController.php create mode 100755 templates/default/coupon.html diff --git a/core/lib/Thelia/Action/Coupon.php b/core/lib/Thelia/Action/Coupon.php new file mode 100755 index 000000000..7b95d80fa --- /dev/null +++ b/core/lib/Thelia/Action/Coupon.php @@ -0,0 +1,79 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Action; + +use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Thelia\Core\Event\ActionEvent; +use Thelia\Core\Event\TheliaEvents; +use Thelia\Model\Category as CategoryModel; +use Thelia\Form\CategoryCreationForm; +use Thelia\Core\Event\CategoryEvent; +use Thelia\Tools\Redirect; +use Thelia\Model\CategoryQuery; +use Thelia\Model\AdminLog; +use Thelia\Form\CategoryDeletionForm; +use Thelia\Action\Exception\FormValidationException; + +use Propel\Runtime\ActiveQuery\Criteria; +use Propel\Runtime\Propel; +use Thelia\Model\Map\CategoryTableMap; +use Propel\Runtime\Exception\PropelException; + +class Coupon extends BaseAction implements EventSubscriberInterface +{ + + /** + * Returns an array of event names this subscriber listens to. + * + * The array keys are event names and the value can be: + * + * * The method name to call (priority defaults to 0) + * * An array composed of the method name to call and the priority + * * An array of arrays composed of the method names to call and respective + * priorities, or 0 if unset + * + * For instance: + * + * * array('eventName' => 'methodName') + * * array('eventName' => array('methodName', $priority)) + * * array('eventName' => array(array('methodName1', $priority), array('methodName2')) + * + * @return array The event names to listen to + * + * @api + */ + public static function getSubscribedEvents() + { + return array( +// "action.createCategory" => array("create", 128), +// "action.modifyCategory" => array("modify", 128), +// "action.deleteCategory" => array("delete", 128), +// +// "action.toggleCategoryVisibility" => array("toggleVisibility", 128), +// "action.changeCategoryPositionUp" => array("changePositionUp", 128), +// "action.changeCategoryPositionDown" => array("changePositionDown", 128), +// "action.changeCategoryPosition" => array("changePosition", 128), + ); + } +} diff --git a/core/lib/Thelia/Config/Resources/routing/admin.xml b/core/lib/Thelia/Config/Resources/routing/admin.xml index ece222c22..df1495953 100755 --- a/core/lib/Thelia/Config/Resources/routing/admin.xml +++ b/core/lib/Thelia/Config/Resources/routing/admin.xml @@ -35,6 +35,11 @@ Thelia\Controller\Admin\CategoryController::processAction + + + Thelia\Controller\Admin\CouponController::indexAction + + diff --git a/core/lib/Thelia/Constraint/Rule/AvailableForCustomer.php b/core/lib/Thelia/Constraint/Rule/AvailableForCustomer.php new file mode 100644 index 000000000..299736d89 --- /dev/null +++ b/core/lib/Thelia/Constraint/Rule/AvailableForCustomer.php @@ -0,0 +1,203 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Constraint\Rule; + +use Thelia\Constraint\Validator\CustomerParam; +use Thelia\Constraint\Validator\RuleValidator; +use Thelia\Coupon\CouponAdapterInterface; +use Thelia\Exception\InvalidRuleException; +use Thelia\Exception\InvalidRuleOperatorException; +use Thelia\Exception\InvalidRuleValueException; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * @package Constraint + * @author Guillaume MOREL + * + */ +class AvailableForCustomer extends CouponRuleAbstract +{ + + /** Rule 1st parameter : customer id */ + CONST PARAM1 = 'customerId'; + + /** @var array Available Operators (Operators::CONST) */ + protected $availableOperators = array( + Operators::EQUAL, + ); + + /** @var RuleValidator Customer Validator */ + protected $customerValidator = null; + + /** + * Constructor + * + * @param CouponAdapterInterface $adapter allowing to gather + * all necessary Thelia variables + * @param array $validators Array of RuleValidator + * validating $paramsToValidate against + * + * @throws InvalidRuleException + */ + public function __construct(CouponAdapterInterface $adapter, array $validators) + { + parent::__construct($adapter, $validators); + + if (isset($validators[self::PARAM1]) + && $validators[self::PARAM1] instanceof RuleValidator + ) { + $this->customerValidator = $validators[self::PARAM1]; + } else { + throw new InvalidRuleException(get_class()); + } + + $this->adapter = $adapter; + } + + /** + * Check if backoffice inputs are relevant or not + * + * @throws InvalidRuleOperatorException if Operator is not allowed + * @throws InvalidRuleValueException if Value is not allowed + * @return bool + */ + public function checkBackOfficeInput() + { + if (!isset($this->validators) + || empty($this->validators) + ||!isset($this->validators[self::PARAM1]) + ||!isset($this->validators[self::PARAM1]) + ) { + throw new InvalidRuleValueException(get_class(), self::PARAM1); + } + + /** @var RuleValidator $ruleValidator */ + $ruleValidator = $this->validators[self::PARAM1]; + /** @var CustomerParam $customer */ + $customer = $ruleValidator->getParam(); + + if (!$customer instanceof CustomerParam) { + throw new InvalidRuleValueException(get_class(), self::PARAM1); + } + + $this->checkBackOfficeInputsOperators(); + + return $this->isCustomerValid($customer->getInteger()); + } + + /** + * Generate current Rule param to be validated from adapter + * + * @return $this + */ + protected function setParametersToValidate() + { + $this->paramsToValidate = array( + self::PARAM1 => $this->adapter->getCustomer()->getId() + ); + + return $this; + } + + /** + * Check if Checkout inputs are relevant or not + * + * @throws \Thelia\Exception\InvalidRuleValueException + * @return bool + */ + public function checkCheckoutInput() + { + if (!isset($this->paramsToValidate) + || empty($this->paramsToValidate) + ||!isset($this->paramsToValidate[self::PARAM1]) + ) { + throw new InvalidRuleValueException(get_class(), self::PARAM1); + } + + $customerId = $this->paramsToValidate[self::PARAM1]; + + return $this->isCustomerValid($customerId); + } + + /** + * Check if a Customer is valid + * + * @param int $customerId Customer to check + * + * @throws InvalidRuleValueException if Value is not allowed + * @return bool + */ + protected function isCustomerValid($customerId) + { + $customerValidator = $this->customerValidator; + try { + $customerValidator->getParam()->compareTo($customerId); + } catch(\InvalidArgumentException $e) { + throw new InvalidRuleValueException(get_class(), self::PARAM1); + } + + return true; + } + + /** + * Get I18n name + * + * @return string + */ + public function getName() + { + return $this->adapter + ->getTranslator() + ->trans('Customer', null, 'constraint'); + } + + /** + * Get I18n tooltip + * + * @return string + */ + public function getToolTip() + { + /** @var CustomerParam $param */ + $param = $this->customerValidator->getParam(); + $toolTip = $this->adapter + ->getTranslator() + ->trans( + 'If customer is %fistname% %lastname% (%email%)', + array( + '%fistname%' => $param->getFirstName(), + '%lastname%' => $param->getLastName(), + '%email%' => $param->getEmail(), + ), + 'constraint' + ); + + return $toolTip; + } + + +} \ 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 9de10b2bb..d103f4f23 100644 --- a/core/lib/Thelia/Constraint/Rule/AvailableForXArticles.php +++ b/core/lib/Thelia/Constraint/Rule/AvailableForXArticles.php @@ -150,7 +150,7 @@ class AvailableForXArticles extends CouponRuleAbstract /** * Check if a quantity is valid * - * @param float $quantity Quantity to check + * @param int $quantity Quantity to check * * @throws InvalidRuleValueException if Value is not allowed * @return bool diff --git a/core/lib/Thelia/Constraint/Validator/CustomerParam.php b/core/lib/Thelia/Constraint/Validator/CustomerParam.php new file mode 100644 index 000000000..5b4390ddc --- /dev/null +++ b/core/lib/Thelia/Constraint/Validator/CustomerParam.php @@ -0,0 +1,158 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Constraint\Validator; + +use InvalidArgumentException; +use Propel\Runtime\ActiveQuery\ModelCriteria; +use Thelia\Coupon\CouponAdapterInterface; +use Thelia\Model\Customer; +use Thelia\Model\CustomerQuery; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Represent a Customer + * + * @package Constraint + * @author Guillaume MOREL + * + */ +class CustomerParam extends IntegerParam +{ + /** @var string Model Class name */ + protected $modelClass = '\Thelia\Model\Customer'; + + /** @var ModelCriteria */ + protected $queryBuilder = null; + + /** @var string Customer firstname */ + protected $firstName = null; + + /** @var string Customer lastname */ + protected $lastName = null; + + /** @var string Customer email */ + protected $email = null; + + /** + * Constructor + * + * @param CouponAdapterInterface $adapter Provide necessary value from Thelia + * @param int $integer Integer + * + * @throws InvalidArgumentException + */ + public function __construct(CouponAdapterInterface $adapter, $integer) + { + $this->integer = $integer; + $this->adapter = $adapter; + + $this->queryBuilder = CustomerQuery::create(); + /** @var Customer $customer */ + $customer = $this->queryBuilder->findById($integer); + if ($customer !== null) { + $this->firstName = $customer->getFirstname(); + $this->lastName = $customer->getLastname(); + $this->email = $customer->getEmail(); + } else { + throw new \InvalidArgumentException( + 'CustomerParam can compare only existing Customers' + ); + } + } + + /** + * Compare the current object to the passed $other. + * + * Returns 0 if they are semantically equal, 1 if the other object + * is less than the current one, or -1 if its more than the current one. + * + * This method should not check for identity using ===, only for semantically equality for example + * when two different DateTime instances point to the exact same Date + TZ. + * + * @param mixed $other Object + * + * @throws InvalidArgumentException + * @return int + */ + public function compareTo($other) + { + if (!is_integer($other) || $other < 0) { + throw new InvalidArgumentException( + 'IntegerParam can compare only positive int' + ); + } + + return parent::compareTo($other); + } + + /** + * Customer email + * + * @return string + */ + public function getEmail() + { + return $this->email; + } + + /** + * Customer first name + * + * @return string + */ + public function getFirstName() + { + return $this->firstName; + } + + /** + * Customer last name + * + * @return string + */ + public function getLastName() + { + return $this->lastName; + } + + /** + * Get I18n tooltip + * + * @return string + */ + public function getToolTip() + { + return $this->adapter + ->getTranslator() + ->trans( + 'A Customer', + null, + 'constraint' + ); + } + +} diff --git a/core/lib/Thelia/Controller/Admin/CouponController.php b/core/lib/Thelia/Controller/Admin/CouponController.php new file mode 100755 index 000000000..67d1e451e --- /dev/null +++ b/core/lib/Thelia/Controller/Admin/CouponController.php @@ -0,0 +1,100 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Controller\Admin; + +use Thelia\Core\Security\Exception\AuthenticationException; +use Thelia\Core\Security\Exception\AuthorizationException; + +class CouponController extends BaseAdminController +{ + + protected function browseCoupon($args) + { + $this->checkAuth("ADMIN", "admin.coupon.view"); + + return $this->render('coupons', $args); + } + + public function indexAction() + { + return $this->processAction(); + } + + public function processAction() + { + // Get the current action + $action = $this->getRequest()->get('action', 'browse'); + + // Get the category ID + $id = $this->getRequest()->get('id', 0); + + $args = array( + 'action' => $action, + 'current_coupon_id' => $id + ); + + try { + switch ($action) { + case 'browse' : // Browse coupon + + return $this->browseCoupons($args); + + case 'create' : // Create a new category + +// return $this->createNewCategory($args); + + case 'edit' : // Edit an existing category + +// return $this->editCategory($args); + + case 'delete' : // Delete an existing category + +// return $this->deleteCategory($args); + + case 'visibilityToggle' : // Toggle visibility + +// return $this->visibilityToggle($id); + + case 'changePosition' : // Change position + +// return $this->changePosition($args); + + case 'positionUp' : // Move up category + +// return $this->positionUp($args); + + case 'positionDown' : // Move down category + +// return $this->positionDown($args); + } + } catch (AuthorizationException $ex) { + return $this->errorPage($ex->getMessage()); + } catch (AuthenticationException $ex) { + return $this->errorPage($ex->getMessage()); + } + + // We did not recognized the action -> return a 404 page + return $this->pageNotFound(); + } +} diff --git a/templates/default/coupon.html b/templates/default/coupon.html new file mode 100755 index 000000000..3fd478575 --- /dev/null +++ b/templates/default/coupon.html @@ -0,0 +1,5 @@ +

Coupon page

+ +
+ +

COUPON