diff --git a/.gitignore b/.gitignore index f208419b9..2af71adba 100755 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,5 @@ web/.htaccess phpdoc*.log php-cs xhprof/ +phpunit.phar +.DS_Store \ No newline at end of file diff --git a/composer.json b/composer.json index 09aa606b5..9d179a987 100755 --- a/composer.json +++ b/composer.json @@ -9,7 +9,6 @@ }, "require":{ "php": ">=5.4", - "ezyang/htmlpurifier": "dev-master", "ircmaxell/password-compat": "dev-master", "propel/propel": "dev-master", "psr/log" : "1.0", @@ -37,11 +36,13 @@ "simplepie/simplepie": "dev-master", "imagine/imagine": "dev-master", + "symfony/serializer": "dev-master", "symfony/icu": "1.0" }, "require-dev" : { "phpunit/phpunit": "3.7.*", - "fzaninotto/faker": "dev-master" + "fzaninotto/faker": "dev-master", + "maximebf/debugbar": "1.*" }, "minimum-stability": "stable", "config" : { diff --git a/composer.lock b/composer.lock index a54fe3024..0215c3d0f 100755 --- a/composer.lock +++ b/composer.lock @@ -3,52 +3,9 @@ "This file locks the dependencies of your project to a known state", "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file" ], - "hash": "db69990b239a4056558bfd694115d01b", + "hash": "ba2f3e0943f00c7c3bf0c086bc611b0f", + "packages": [ - { - "name": "ezyang/htmlpurifier", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/ezyang/htmlpurifier.git", - "reference": "fac747bdbdba6aeaba4bed91ef49b2378c1798e4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/fac747bdbdba6aeaba4bed91ef49b2378c1798e4", - "reference": "fac747bdbdba6aeaba4bed91ef49b2378c1798e4", - "shasum": "" - }, - "require": { - "php": ">=5.2" - }, - "type": "library", - "autoload": { - "psr-0": { - "HTMLPurifier": "library/" - }, - "files": [ - "library/HTMLPurifier.composer.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "LGPL" - ], - "authors": [ - { - "name": "Edward Z. Yang", - "email": "admin@htmlpurifier.org", - "homepage": "http://ezyang.com" - } - ], - "description": "Standards compliant HTML filter written in PHP", - "homepage": "http://htmlpurifier.org/", - "keywords": [ - "html" - ], - "time": "2013-08-18 02:27:26" - }, { "name": "imagine/imagine", "version": "dev-master", @@ -1662,6 +1619,55 @@ ], "time": "2013-08-29 19:11:59" }, + { + "name": "maximebf/debugbar", + "version": "1.5.1", + "source": { + "type": "git", + "url": "https://github.com/maximebf/php-debugbar.git", + "reference": "37dccc40da52bf9f85571c30cf302da696db0d05" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/maximebf/php-debugbar/zipball/37dccc40da52bf9f85571c30cf302da696db0d05", + "reference": "37dccc40da52bf9f85571c30cf302da696db0d05", + "shasum": "" + }, + "require": { + "php": ">=5.3.0", + "psr/log": "~1.0" + }, + "require-dev": { + "php": ">=5.3.0" + }, + "suggest": { + "kriswallsmith/assetic": "The best way to manage assets", + "monolog/monolog": "Log using Monolog" + }, + "type": "library", + "autoload": { + "psr-0": { + "DebugBar": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Maxime Bouroumeau-Fuseau", + "email": "maxime.bouroumeau@gmail.com", + "homepage": "http://maximebf.com" + } + ], + "description": "Debug bar in the browser for php application", + "homepage": "https://github.com/maximebf/php-debugbar", + "keywords": [ + "debug" + ], + "time": "2013-08-17 02:02:49" + }, { "name": "phpunit/php-code-coverage", "version": "1.2.12", @@ -2035,7 +2041,6 @@ ], "minimum-stability": "stable", "stability-flags": { - "ezyang/htmlpurifier": 20, "ircmaxell/password-compat": 20, "propel/propel": 20, "kriswallsmith/assetic": 20, diff --git a/core/lib/Thelia/Action/Category.php b/core/lib/Thelia/Action/Category.php index 1b0568cbe..7b7608dc9 100755 --- a/core/lib/Thelia/Action/Category.php +++ b/core/lib/Thelia/Action/Category.php @@ -51,6 +51,8 @@ class Category extends BaseAction implements EventSubscriberInterface $event->getParent(), $event->getLocale() ); + + $event->setCategory($category); } public function update(CategoryChangeEvent $event) diff --git a/core/lib/Thelia/Action/Coupon.php b/core/lib/Thelia/Action/Coupon.php new file mode 100755 index 000000000..cc32d2c68 --- /dev/null +++ b/core/lib/Thelia/Action/Coupon.php @@ -0,0 +1,180 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Action; + +use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Thelia\Core\Event\Coupon\CouponCreateOrUpdateEvent; +use Thelia\Core\Event\TheliaEvents; +use Thelia\Model\Coupon as CouponModel; +use Propel\Runtime\ActiveQuery\Criteria; +use Propel\Runtime\Propel; +use Thelia\Model\Map\CategoryTableMap; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Process Coupon Events + * + * @package Coupon + * @author Guillaume MOREL + * + */ +class Coupon extends BaseAction implements EventSubscriberInterface +{ + /** + * Occurring when a Coupon is about to be created + * + * @param CouponCreateOrUpdateEvent $event Event creation or update Event + */ + public function create(CouponCreateOrUpdateEvent $event) + { + $coupon = new CouponModel(); + + $this->createOrUpdate($coupon, $event); + } + + /** + * Occurring when a Coupon is about to be updated + * + * @param CouponCreateOrUpdateEvent $event Event creation or update Event + */ + public function update(CouponCreateOrUpdateEvent $event) + { + $coupon = $event->getCoupon(); + + $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 + * + * @param CouponModel $coupon Model to save + * @param CouponCreateOrUpdateEvent $event Event containing data + */ + protected function createOrUpdate(CouponModel $coupon, CouponCreateOrUpdateEvent $event) + { + $coupon->setDispatcher($this->getDispatcher()); + + $coupon->createOrUpdate( + $event->getCode(), + $event->getTitle(), + $event->getAmount(), + $event->getEffect(), + $event->getShortDescription(), + $event->getDescription(), + $event->isEnabled(), + $event->getExpirationDate(), + $event->isAvailableOnSpecialOffers(), + $event->isCumulative(), + $event->getMaxUsage(), + $event->getRules(), + $event->getLocale() + ); + + $event->setCoupon($coupon); + } + + /** + * 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( + TheliaEvents::COUPON_CREATE => array("create", 128), + TheliaEvents::COUPON_UPDATE => array("update", 128), + TheliaEvents::COUPON_DISABLE => array("disable", 128), + TheliaEvents::COUPON_ENABLE => array("enable", 128), + TheliaEvents::COUPON_CONSUME => array("consume", 128), + TheliaEvents::COUPON_RULE_CREATE => array("createRule", 128), + TheliaEvents::COUPON_RULE_UPDATE => array("updateRule", 128), + TheliaEvents::COUPON_RULE_DELETE => array("deleteRule", 128) + ); + } +} diff --git a/core/lib/Thelia/Command/CreateAdminUser.php b/core/lib/Thelia/Command/CreateAdminUser.php index dc7118399..868ca1496 100644 --- a/core/lib/Thelia/Command/CreateAdminUser.php +++ b/core/lib/Thelia/Command/CreateAdminUser.php @@ -41,6 +41,34 @@ class CreateAdminUser extends ContainerAwareCommand ->setName("thelia:create-admin") ->setDescription("Create a new adminsitration user") ->setHelp("The thelia:create-admin command create a new administration user.") + ->addOption( + 'login_name', + null, + InputOption::VALUE_OPTIONAL, + 'Admin login name', + null + ) + ->addOption( + 'first_name', + null, + InputOption::VALUE_OPTIONAL, + 'User first name', + null + ) + ->addOption( + "last_name", + null, + InputOption::VALUE_OPTIONAL, + 'User last name', + null + ) + ->addOption( + 'password', + null, + InputOption::VALUE_OPTIONAL, + 'Password', + null + ) ; } @@ -54,25 +82,25 @@ class CreateAdminUser extends ContainerAwareCommand $admin->save(); $output->writeln(array( - "", - "User ".$admin->getLogin()." successfully created.", - "" - )); + "", + "User ".$admin->getLogin()." successfully created.", + "" + )); } protected function enterData($dialog, $output, $label, $error_message) { return $dialog->askAndValidate( - $output, - $this->decorateInfo($label), - function ($answer) { - $answer = trim($answer); - if (empty($answer)) { - throw new \RuntimeException("This information is mandatory."); - } - - return $answer; + $output, + $this->decorateInfo($label), + function ($answer) { + $answer = trim($answer); + if (empty($answer)) { + throw new \RuntimeException("This information is mandatory."); } + + return $answer; + } ); } @@ -89,13 +117,13 @@ class CreateAdminUser extends ContainerAwareCommand $admin = new Admin(); - $admin->setLogin($this->enterData($dialog, $output, "Admin login name : ", "Please enter a login name.")); - $admin->setFirstname($this->enterData($dialog, $output, "User first name : ", "Please enter user first name.")); - $admin->setLastname($this->enterData($dialog, $output, "User last name : ", "Please enter user last name.")); + $admin->setLogin($input->getOption("login_name") ?: $this->enterData($dialog, $output, "Admin login name : ", "Please enter a login name.")); + $admin->setFirstname($input->getOption("first_name") ?: $this->enterData($dialog, $output, "User first name : ", "Please enter user first name.")); + $admin->setLastname($input->getOption("last_name") ?: $this->enterData($dialog, $output, "User last name : ", "Please enter user last name.")); do { - $password = $this->enterData($dialog, $output, "Password : ", "Please enter a password."); - $password_again = $this->enterData($dialog, $output, "Password (again): ", "Please enter the password again."); + $password = $input->getOption("password") ?: $this->enterData($dialog, $output, "Password : ", "Please enter a password."); + $password_again = $input->getOption("password") ?: $this->enterData($dialog, $output, "Password (again): ", "Please enter the password again."); if (! empty($password) && $password == $password_again) { @@ -109,11 +137,11 @@ class CreateAdminUser extends ContainerAwareCommand while (true); return $admin; - } + } protected function decorateInfo($text) { return sprintf("%s", $text); } -} +} \ No newline at end of file diff --git a/core/lib/Thelia/Command/Skeleton/Module/Class.php b/core/lib/Thelia/Command/Skeleton/Module/Class.php index c9c7109ac..c4c90aa60 100755 --- a/core/lib/Thelia/Command/Skeleton/Module/Class.php +++ b/core/lib/Thelia/Command/Skeleton/Module/Class.php @@ -25,7 +25,7 @@ namespace %%NAMESPACE%%; use Thelia\Module\BaseModule; -class Class extends BaseModule +class %%CLASSNAME%% extends BaseModule { /** * YOU HAVE TO IMPLEMENT HERE ABSTRACT METHODD FROM BaseModule Class diff --git a/core/lib/Thelia/Config/Resources/action.xml b/core/lib/Thelia/Config/Resources/action.xml index 5bf4cbab8..dd43bbb91 100755 --- a/core/lib/Thelia/Config/Resources/action.xml +++ b/core/lib/Thelia/Config/Resources/action.xml @@ -47,6 +47,11 @@ + + + + + diff --git a/core/lib/Thelia/Config/Resources/config.xml b/core/lib/Thelia/Config/Resources/config.xml index 974de091c..74e1f4629 100755 --- a/core/lib/Thelia/Config/Resources/config.xml +++ b/core/lib/Thelia/Config/Resources/config.xml @@ -33,7 +33,9 @@ + + @@ -47,7 +49,10 @@
- + + + + @@ -59,6 +64,8 @@ + + @@ -79,7 +86,6 @@ - %kernel.environment% @@ -98,7 +104,7 @@ - + @@ -143,11 +149,7 @@ - - - - - + %thelia.parser.loops% @@ -207,6 +209,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/lib/Thelia/Config/Resources/routing/admin.xml b/core/lib/Thelia/Config/Resources/routing/admin.xml index 588434765..3235171df 100755 --- a/core/lib/Thelia/Config/Resources/routing/admin.xml +++ b/core/lib/Thelia/Config/Resources/routing/admin.xml @@ -25,16 +25,82 @@ - + - Thelia\Controller\Admin\CategoryController::indexAction + Thelia\Controller\Admin\CategoryController::defaultAction - - Thelia\Controller\Admin\CategoryController::processAction + + + + Thelia\Controller\Admin\CustomerController::indexAction + + + + + + Thelia\Controller\Admin\CategoryController::defaultAction + + + + Thelia\Controller\Admin\CategoryController::createAction + + + + Thelia\Controller\Admin\CategoryController::changeAction + + + + Thelia\Controller\Admin\CategoryController::saveChangeAction + + + + Thelia\Controller\Admin\CategoryController::toggleOnlineAction + + + + Thelia\Controller\Admin\CategoryController::deleteAction + + + + Thelia\Controller\Admin\CategoryController::updatePositionAction + + + Thelia\Controller\Admin\CategoryController::getByParentIdAction + xml|json + + + + + + + + + + + Thelia\Controller\Admin\CouponController::browseAction + + + Thelia\Controller\Admin\CouponController::createAction + + + Thelia\Controller\Admin\CouponController::updateAction + + + Thelia\Controller\Admin\CouponController::readAction + + + Thelia\Controller\Admin\CouponController::getRuleInputAction + + + + + + + @@ -105,6 +171,10 @@ Thelia\Controller\Admin\CurrencyController::setDefaultAction + + Thelia\Controller\Admin\CurrencyController::updatePositionAction + + Thelia\Controller\Admin\CurrencyController::updateRatesAction @@ -118,8 +188,7 @@ - - + Thelia\Controller\Admin\AttributeController::defaultAction @@ -128,7 +197,6 @@ Thelia\Controller\Admin\AttributeController::updateAction - diff --git a/core/lib/Thelia/Config/Resources/routing/front.xml b/core/lib/Thelia/Config/Resources/routing/front.xml index f8b156946..d06585f73 100755 --- a/core/lib/Thelia/Config/Resources/routing/front.xml +++ b/core/lib/Thelia/Config/Resources/routing/front.xml @@ -15,17 +15,29 @@ connexion + + Thelia\Controller\Front\DefaultController::noAction + register + + Thelia\Controller\Front\CustomerController::updateAction Thelia\Controller\Front\CustomerController::loginAction + login + + + + Thelia\Controller\Front\DefaultController::noAction + login Thelia\Controller\Front\CustomerController::logoutAction + @@ -60,4 +72,11 @@ cart + + + Thelia\Controller\Front\DeliveryController::select + \d+ + + + diff --git a/core/lib/Thelia/Constraint/ConstraintFactory.php b/core/lib/Thelia/Constraint/ConstraintFactory.php new file mode 100644 index 000000000..e96509172 --- /dev/null +++ b/core/lib/Thelia/Constraint/ConstraintFactory.php @@ -0,0 +1,162 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Constraint; + +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\Serializer\Encoder\JsonEncoder; +use Thelia\Constraint\Rule\AvailableForTotalAmountManager; +use Thelia\Constraint\Rule\CouponRuleInterface; +use Thelia\Constraint\Rule\SerializableRule; +use Thelia\Coupon\CouponAdapterInterface; +use Thelia\Coupon\CouponRuleCollection; + + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Manage how Constraint could interact + * + * @package Constraint + * @author Guillaume MOREL + * + */ +class ConstraintFactory +{ + /** @var ContainerInterface Service Container */ + protected $container = null; + + /** @var CouponAdapterInterface Provide necessary value from Thelia*/ + protected $adapter; + + /** @var array CouponRuleCollection to process*/ + protected $rules = null; + + /** + * Constructor + * + * @param ContainerInterface $container Service container + */ + function __construct(ContainerInterface $container) + { + $this->container = $container; + $this->adapter = $container->get('thelia.adapter'); + } + + /** + * Serialize a collection of rules + * + * @param CouponRuleCollection $collection A collection of rules + * + * @return string A ready to be stored Rule collection + */ + public function serializeCouponRuleCollection(CouponRuleCollection $collection) + { + $serializableRules = array(); + $rules = $collection->getRules(); + if ($rules !== null) { + /** @var $rule CouponRuleInterface */ + foreach ($rules as $rule) { + $serializableRules[] = $rule->getSerializableRule(); + } + } + + return base64_encode(json_encode($serializableRules)); + } + + /** + * Unserialize a collection of rules + * + * @param string $serializedRules Serialized Rules + * + * @return CouponRuleCollection Rules ready to be processed + */ + public function unserializeCouponRuleCollection($serializedRules) + { + $unserializedRules = json_decode(base64_decode($serializedRules)); + + $collection = new CouponRuleCollection(); + + if (!empty($serializedRules) && !empty($unserializedRules)) { + /** @var SerializableRule $rule */ + foreach ($unserializedRules as $rule) { + if ($this->container->has($rule->ruleServiceId)) { + /** @var CouponRuleInterface $couponRule */ + $couponRule = $this->build( + $rule->ruleServiceId, + (array) $rule->operators, + (array) $rule->values + ); + $collection->add(clone $couponRule); + } + } + } + + return $collection; + } + + + /** + * Build a Coupon Rule from form + * + * @param string $ruleServiceId Rule class name + * @param array $operators Rule Operator (<, >, = ) + * @param array $values Values setting this Rule + * + * @throws \InvalidArgumentException + * @return CouponRuleInterface Ready to use Rule or false + */ + public function build($ruleServiceId, array $operators, array $values) + { + if (!$this->container->has($ruleServiceId)) { + return false; + } + + /** @var CouponRuleInterface $rule */ + $rule = $this->container->get($ruleServiceId); + $rule->setValidatorsFromForm($operators, $values); + + return $rule; + } + + /** + * Get Coupon Rule inputs from serviceId + * + * @param string $ruleServiceId Rule class name + * + * @return array Ready to be drawn rule inputs + */ + public function getInputs($ruleServiceId) + { + if (!$this->container->has($ruleServiceId)) { + return false; + } + + /** @var CouponRuleInterface $rule */ + $rule = $this->container->get($ruleServiceId); + + return $rule->getValidators(); + } +} \ No newline at end of file diff --git a/core/lib/Thelia/Constraint/ConstraintValidator.php b/core/lib/Thelia/Constraint/ConstraintValidator.php new file mode 100644 index 000000000..edacee317 --- /dev/null +++ b/core/lib/Thelia/Constraint/ConstraintValidator.php @@ -0,0 +1,133 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Constraint; + +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\Serializer\Encoder\JsonEncoder; +use Thelia\Constraint\Rule\AvailableForTotalAmountManager; +use Thelia\Constraint\Rule\CouponRuleInterface; +use Thelia\Constraint\Rule\Operators; +use Thelia\Coupon\CouponRuleCollection; + + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Validate Constraints + * + * @package Constraint + * @author Guillaume MOREL + * + */ +class ConstraintValidator +{ + + /** + * Check if a Customer meets SerializableRule + * + * @param CouponRuleCollection $rules Rules to check against the Customer + * + * @return bool + */ + public function test(CouponRuleCollection $rules) + { + $isMatching = true; + /** @var CouponRuleInterface $rule */ + foreach ($rules->getRules() as $rule) { + if (!$rule->isMatching()) { + $isMatching = false; + } + } + + return $isMatching; + + } + + /** + * Do variable comparison + * + * @param mixed $v1 Variable 1 + * @param string $o Operator + * + * @param mixed $v2 Variable 2 + * @throws \Exception + * @return bool + */ + public function variableOpComparison($v1, $o, $v2) { + if ($o == Operators::DIFFERENT) { + return ($v1 != $v2); + } // could put this elsewhere... +// $operators = str_split($o); +// foreach($o as $operator) { + switch ($o) { // return will exit switch, foreach loop, function + case Operators::SUPERIOR : // > + if ($v1 > $v2) { + return true; + } else { + continue; + } break; + case Operators::SUPERIOR_OR_EQUAL : // >= + if ($v1 >= $v2) { + return true; + } else { + continue; + } break; + case Operators::INFERIOR : // < + if ($v1 < $v2) { + return true; + } else { + continue; + } break; + case Operators::INFERIOR_OR_EQUAL : // <= + if ($v1 <= $v2) { + return true; + } else { + continue; + } break; + case Operators::EQUAL : // == + if ($v1 == $v2) { + return true; + } else { + continue; + } break; + case Operators::IN: + if (in_array($v1, $v2)) { // in + return true; + } else { + continue; + } break; + case Operators::OUT: + if (!in_array($v1, $v2)) { // not in + return true; + } else { + continue; + } break; + default: throw new \Exception('Unrecognized operator ' . $o); + } +// } + return false; + } +} \ No newline at end of file diff --git a/core/lib/Thelia/Constraint/Rule/AvailableForCustomer.php b/core/lib/Thelia/Constraint/Rule/AvailableForCustomer.php new file mode 100644 index 000000000..ad722eb5c --- /dev/null +++ b/core/lib/Thelia/Constraint/Rule/AvailableForCustomer.php @@ -0,0 +1,178 @@ +. */ +/* */ +/**********************************************************************************/ + +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; + + /** + * 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/AvailableForDate.php b/core/lib/Thelia/Constraint/Rule/AvailableForDate.php new file mode 100644 index 000000000..1ddfd0350 --- /dev/null +++ b/core/lib/Thelia/Constraint/Rule/AvailableForDate.php @@ -0,0 +1,59 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Constraint\Rule; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * @package Constraint + * @author Guillaume MOREL + * + */ +class AvailableForDate extends AvailableForPeriod +{ + + /** + * Check if backoffice inputs are relevant or not + * + * @return bool + */ + public function checkBackOfficeInput() + { + // TODO: Implement checkBackOfficeInput() method. + } + + /** + * Check if Checkout inputs are relevant or not + * + * @return bool + */ + public function checkCheckoutInput() + { + // TODO: Implement checkCheckoutInput() method. + } + + +} \ No newline at end of file diff --git a/core/lib/Thelia/Constraint/Rule/AvailableForEveryoneManager.php b/core/lib/Thelia/Constraint/Rule/AvailableForEveryoneManager.php new file mode 100644 index 000000000..15e0e3ab7 --- /dev/null +++ b/core/lib/Thelia/Constraint/Rule/AvailableForEveryoneManager.php @@ -0,0 +1,135 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Constraint\Rule; + +use InvalidArgumentException; +use Symfony\Component\Translation\Translator; +use Thelia\Constraint\ConstraintValidator; +use Thelia\Constraint\Validator\QuantityParam; +use Thelia\Constraint\Validator\RuleValidator; +use Thelia\Coupon\CouponAdapterInterface; +use Thelia\Exception\InvalidRuleException; +use Thelia\Exception\InvalidRuleValueException; +use Thelia\Type\FloatType; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Allow every one, perform no check + * + * @package Constraint + * @author Guillaume MOREL + * + */ +class AvailableForEveryoneManager extends CouponRuleAbstract +{ + /** @var string Service Id from Resources/config.xml */ + protected $serviceId = 'thelia.constraint.rule.available_for_everyone'; + + /** @var array Available Operators (Operators::CONST) */ + protected $availableOperators = array(); + + /** + * Check validators relevancy and store them + * + * @param array $operators Operators the Admin set in BackOffice + * @param array $values Values the Admin set in BackOffice + * + * @throws \InvalidArgumentException + * @return $this + */ + public function setValidatorsFromForm(array $operators, array $values) + { + $this->setValidators(); + + return $this; + } + + /** + * Check validators relevancy and store them + * + * @throws \InvalidArgumentException + * @return $this + */ + protected function setValidators() + { + $this->operators = array(); + $this->values = array(); + + return $this; + } + + /** + * Test if Customer meets conditions + * + * @return bool + */ + public function isMatching() + { + return true; + } + + /** + * Get I18n name + * + * @return string + */ + public function getName() + { + return $this->translator->trans( + 'Everybody can use it (no condition)', + array(), + 'constraint' + ); + } + + /** + * Get I18n tooltip + * + * @return string + */ + public function getToolTip() + { + $toolTip = $this->translator->trans( + 'Will return always true', + array(), + 'constraint' + ); + + return $toolTip; + } + + /** + * Generate inputs ready to be drawn + * + * @return array + */ + protected function generateInputs() + { + return array(); + } + +} \ No newline at end of file diff --git a/core/lib/Thelia/Constraint/Rule/AvailableForLocationX.php b/core/lib/Thelia/Constraint/Rule/AvailableForLocationX.php new file mode 100644 index 000000000..5c3ec494c --- /dev/null +++ b/core/lib/Thelia/Constraint/Rule/AvailableForLocationX.php @@ -0,0 +1,59 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Constraint\Rule; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * @package Constraint + * @author Guillaume MOREL + * + */ +class AvailableForLocationX extends CouponRuleAbstract +{ + + /** + * Check if backoffice inputs are relevant or not + * + * @return bool + */ + public function checkBackOfficeInput() + { + // TODO: Implement checkBackOfficeInput() method. + } + + /** + * Check if Checkout inputs are relevant or not + * + * @return bool + */ + public function checkCheckoutInput() + { + // TODO: Implement checkCheckoutInput() method. + } + + +} \ No newline at end of file diff --git a/core/lib/Thelia/Constraint/Rule/AvailableForPeriod.php b/core/lib/Thelia/Constraint/Rule/AvailableForPeriod.php new file mode 100644 index 000000000..30679a973 --- /dev/null +++ b/core/lib/Thelia/Constraint/Rule/AvailableForPeriod.php @@ -0,0 +1,57 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Constraint\Rule; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * @package Constraint + * @author Guillaume MOREL + * + */ +class AvailableForPeriod extends CouponRuleAbstract +{ + + /** + * Check if backoffice inputs are relevant or not + * + * @return bool + */ + public function checkBackOfficeInput() + { + // TODO: Implement checkBackOfficeInput() method. + } + + /** + * Check if Checkout inputs are relevant or not + * + * @return bool + */ + public function checkCheckoutInput() + { + // TODO: Implement checkCheckoutInput() method. + } +} \ No newline at end of file diff --git a/core/lib/Thelia/Constraint/Rule/AvailableForRepeatedDate.php b/core/lib/Thelia/Constraint/Rule/AvailableForRepeatedDate.php new file mode 100644 index 000000000..3449a7f5b --- /dev/null +++ b/core/lib/Thelia/Constraint/Rule/AvailableForRepeatedDate.php @@ -0,0 +1,57 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Constraint\Rule; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * @package Constraint + * @author Guillaume MOREL + * + */ +class AvailableForRepeatedDate extends AvailableForDate +{ + + /** + * Check if backoffice inputs are relevant or not + * + * @return bool + */ + public function checkBackOfficeInput() + { + // TODO: Implement checkBackOfficeInput() method. + } + + /** + * Check if Checkout inputs are relevant or not + * + * @return bool + */ + public function checkCheckoutInput() + { + // TODO: Implement checkCheckoutInput() method. + } +} \ No newline at end of file diff --git a/core/lib/Thelia/Constraint/Rule/AvailableForRepeatedPeriod.php b/core/lib/Thelia/Constraint/Rule/AvailableForRepeatedPeriod.php new file mode 100644 index 000000000..f5bf9bafc --- /dev/null +++ b/core/lib/Thelia/Constraint/Rule/AvailableForRepeatedPeriod.php @@ -0,0 +1,73 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Constraint\Rule; + +use Thelia\Coupon\CouponAdapterInterface; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * @package Constraint + * @author Guillaume MOREL + * + */ +class AvailableForRepeatedPeriod extends AvailableForPeriod +{ + + /** + * Generate current Rule param to be validated from adapter + * + * @param CouponAdapterInterface $adapter allowing to gather + * all necessary Thelia variables + * + * @throws \Symfony\Component\Intl\Exception\NotImplementedException + * @return $this + */ + public function setParametersToValidate(CouponAdapterInterface $adapter) + { + // @todo implement + } + + /** + * Check if backoffice inputs are relevant or not + * + * @return bool + */ + public function checkBackOfficeInput() + { + // TODO: Implement checkBackOfficeInput() method. + } + + /** + * Check if Checkout inputs are relevant or not + * + * @return bool + */ + public function checkCheckoutInput() + { + // TODO: Implement checkCheckoutInput() method. + } +} \ No newline at end of file diff --git a/core/lib/Thelia/Constraint/Rule/AvailableForTotalAmountForCategoryY.php b/core/lib/Thelia/Constraint/Rule/AvailableForTotalAmountForCategoryY.php new file mode 100644 index 000000000..0f9f7f10b --- /dev/null +++ b/core/lib/Thelia/Constraint/Rule/AvailableForTotalAmountForCategoryY.php @@ -0,0 +1,38 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Constraint\Rule; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * @package Constraint + * @author Guillaume MOREL + * + */ +class AvailableForTotalAmountForCategoryY extends AvailableForTotalAmount +{ + +} \ No newline at end of file diff --git a/core/lib/Thelia/Constraint/Rule/AvailableForTotalAmountManager.php b/core/lib/Thelia/Constraint/Rule/AvailableForTotalAmountManager.php new file mode 100644 index 000000000..6ab746e6c --- /dev/null +++ b/core/lib/Thelia/Constraint/Rule/AvailableForTotalAmountManager.php @@ -0,0 +1,417 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Constraint\Rule; + +use Symfony\Component\Intl\Exception\NotImplementedException; +use Symfony\Component\Translation\Translator; +use Thelia\Constraint\ConstraintValidator; +use Thelia\Coupon\CouponAdapterInterface; +use Thelia\Constraint\Validator\PriceParam; +use Thelia\Constraint\Validator\RuleValidator; +use Thelia\Exception\InvalidRuleException; +use Thelia\Exception\InvalidRuleOperatorException; +use Thelia\Exception\InvalidRuleValueException; +use Thelia\Model\Currency; +use Thelia\Model\CurrencyQuery; +use Thelia\Type\FloatType; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Rule AvailableForTotalAmount + * Check if a Checkout total amount match criteria + * + * @package Constraint + * @author Guillaume MOREL + * + */ +class AvailableForTotalAmountManager extends CouponRuleAbstract +{ + /** Rule 1st parameter : price */ + CONST INPUT1 = 'price'; + + /** Rule 1st parameter : currency */ + CONST INPUT2 = 'currency'; + + /** @var string Service Id from Resources/config.xml */ + protected $serviceId = 'thelia.constraint.rule.available_for_total_amount'; + + /** @var array Available Operators (Operators::CONST) */ + protected $availableOperators = array( + self::INPUT1 => array( + Operators::INFERIOR, + Operators::INFERIOR_OR_EQUAL, + Operators::EQUAL, + Operators::SUPERIOR_OR_EQUAL, + Operators::SUPERIOR + ), + self::INPUT2 => array( + Operators::EQUAL, + ) + ); + +// /** @var RuleValidator Price Validator */ +// protected $priceValidator = null; + +// /** +// * 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_PRICE]) +// ||!isset($this->validators[self::PARAM1_PRICE]) +// ) { +// throw new InvalidRuleValueException(get_class(), self::PARAM1_PRICE); +// } +// +// /** @var RuleValidator $ruleValidator */ +// $ruleValidator = $this->validators[self::PARAM1_PRICE]; +// /** @var PriceParam $price */ +// $price = $ruleValidator->getParam(); +// +// if (!$price instanceof PriceParam) { +// throw new InvalidRuleValueException(get_class(), self::PARAM1_PRICE); +// } +// +// $this->checkBackOfficeInputsOperators(); +// +// return $this->isPriceValid($price->getPrice(), $price->getCurrency()); +// } + +// /** +// * Check if Checkout inputs are relevant or not +// * +// * @throws InvalidRuleValueException if Value is not allowed +// * @return bool +// */ +// public function checkCheckoutInput() +// { +// $currency = $this->adapter->getCheckoutCurrency(); +// if (empty($currency)) { +// throw new InvalidRuleValueException( +// get_class(), self::PARAM1_CURRENCY +// ); +// } +// +// $price = $this->adapter->getCartTotalPrice(); +// if (empty($price)) { +// throw new InvalidRuleValueException( +// get_class(), self::PARAM1_PRICE +// ); +// } +// +// $this->paramsToValidate = array( +// self::PARAM1_PRICE => $this->adapter->getCartTotalPrice(), +// self::PARAM1_CURRENCY => $this->adapter->getCheckoutCurrency() +// ); +// +// return $this->isPriceValid($price, $currency); +// } + + /** + * Check validators relevancy and store them + * + * @param array $operators Operators the Admin set in BackOffice + * @param array $values Values the Admin set in BackOffice + * + * @throws \InvalidArgumentException + * @return $this + */ + public function setValidatorsFromForm(array $operators, array $values) + { + $this->setValidators( + $operators[self::INPUT1], + $values[self::INPUT1], + $operators[self::INPUT2], + $values[self::INPUT2] + ); + + return $this; + } + + /** + * Check validators relevancy and store them + * + * @param string $priceOperator Price Operator ex < + * @param float $priceValue Price set to meet condition + * @param string $currencyOperator Currency Operator ex = + * @param string $currencyValue Currency set to meet condition + * + * @throws \InvalidArgumentException + * @return $this + */ + protected function setValidators($priceOperator, $priceValue, $currencyOperator, $currencyValue) + { + $isOperator1Legit = $this->isOperatorLegit( + $priceOperator, + $this->availableOperators[self::INPUT1] + ); + if (!$isOperator1Legit) { + throw new \InvalidArgumentException( + 'Operator for price field is not legit' + ); + } + + $isOperator1Legit = $this->isOperatorLegit( + $currencyOperator, + $this->availableOperators[self::INPUT2] + ); + if (!$isOperator1Legit) { + throw new \InvalidArgumentException( + 'Operator for currency field is not legit' + ); + } + + $floatType = new FloatType(); + if (!$floatType->isValid($priceValue) || $priceValue <= 0) { + throw new \InvalidArgumentException( + 'Value for price field is not legit' + ); + } + + // @todo check currency is legit or not + + $this->operators = array( + self::INPUT1 => $priceOperator, + self::INPUT2 => $currencyOperator, + ); + $this->values = array( + self::INPUT1 => $priceValue, + self::INPUT2 => $currencyValue, + ); + + return $this; + } + + /** + * Test if Customer meets conditions + * + * @return bool + */ + public function isMatching() + { + $isOperator1Legit = $this->isOperatorLegit( + $this->operators[self::INPUT1], + $this->availableOperators[self::INPUT1] + ); + $isOperator2Legit = $this->isOperatorLegit( + $this->operators[self::INPUT2], + $this->availableOperators[self::INPUT2] + ); + + if (!$isOperator1Legit || !$isOperator2Legit) { + return false; + } + + $constrainValidator = new ConstraintValidator(); + $constraint1 =$constrainValidator->variableOpComparison( + $this->adapter->getCartTotalPrice(), + $this->operators[self::INPUT1], + $this->values[self::INPUT1] + ); + $constraint2 =$constrainValidator->variableOpComparison( + $this->adapter->getCheckoutCurrency(), + $this->operators[self::INPUT2], + $this->values[self::INPUT2] + ); + if ($constraint1 && $constraint2) { + return true; + } + return false; + } + +// /** +// * Check if a price is valid +// * +// * @param float $price Price to check +// * @param string $currency Price currency +// * +// * @throws InvalidRuleValueException if Value is not allowed +// * @return bool +// */ +// protected function isPriceValid($price, $currency) +// { +// $priceValidator = $this->priceValidator; +// +// /** @var PriceParam $param */ +// $param = $priceValidator->getParam(); +// if ($currency == $param->getCurrency()) { +// try { +// $priceValidator->getParam()->compareTo($price); +// } catch(\InvalidArgumentException $e) { +// throw new InvalidRuleValueException(get_class(), self::PARAM1_PRICE); +// } +// } else { +// throw new InvalidRuleValueException(get_class(), self::PARAM1_CURRENCY); +// } +// +// return true; +// } + +// /** +// * Generate current Rule param to be validated from adapter +// * +// * @return $this +// */ +// protected function setParametersToValidate() +// { +// $this->paramsToValidate = array( +// self::PARAM1_PRICE => $this->adapter->getCartTotalPrice(), +// self::PARAM1_CURRENCY => $this->adapter->getCheckoutCurrency() +// ); +// +// return $this; +// } + + /** + * Get I18n name + * + * @return string + */ + public function getName() + { + return $this->translator->trans( + 'Cart total amount', + array(), + 'constraint' + ); + } + + /** + * Get I18n tooltip + * + * @return string + */ + public function getToolTip() + { + $i18nOperator = Operators::getI18n( + $this->translator, $this->operators[self::INPUT1] + ); + + $toolTip = $this->translator->trans( + 'If cart total amount is %operator% %amount% %currency%', + array( + '%operator%' => $i18nOperator, + '%amount%' => $this->values[self::INPUT1], + '%currency%' => $this->values[self::INPUT2] + ), + 'constraint' + ); + + return $toolTip; + } + + /** + * Generate inputs ready to be drawn + * + * @return array + */ + protected function generateInputs() + { + $currencies = CurrencyQuery::create()->find(); + $cleanedCurrencies = array(); + /** @var Currency $currency */ + foreach ($currencies as $currency) { + $cleanedCurrencies[$currency->getCode()] = $currency->getSymbol(); + } + + $name1 = $this->translator->trans( + 'Price', + array(), + 'constraint' + ); + $name2 = $this->translator->trans( + 'Currency', + array(), + 'constraint' + ); + + return array( + self::INPUT1 => array( + 'title' => $name1, + 'availableOperators' => $this->availableOperators[self::INPUT1], + 'availableValues' => '', + 'type' => 'text', + 'class' => 'form-control', + 'value' => '', + 'selectedOperator' => '' + ), + self::INPUT2 => array( + 'title' => $name2, + 'availableOperators' => $this->availableOperators[self::INPUT2], + 'availableValues' => $cleanedCurrencies, + 'type' => 'select', + 'class' => 'form-control', + 'value' => '', + 'selectedOperator' => Operators::EQUAL + ) + ); + } + +// /** +// * 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 RuleValidator( +// $operators[self::PARAM1_PRICE], +// new PriceParam( +// $this->translator, +// $values[self::PARAM1_PRICE], +// $values[self::PARAM1_CURRENCY] +// ) +// ); +// +// $this->validators = array(self::PARAM1_PRICE => $this->priceValidator); +// +// return $this; +// } + + + + + +} \ No newline at end of file diff --git a/core/lib/Thelia/Constraint/Rule/AvailableForXArticlesManager.php b/core/lib/Thelia/Constraint/Rule/AvailableForXArticlesManager.php new file mode 100644 index 000000000..20d7eddca --- /dev/null +++ b/core/lib/Thelia/Constraint/Rule/AvailableForXArticlesManager.php @@ -0,0 +1,325 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Constraint\Rule; + +use InvalidArgumentException; +use Symfony\Component\Translation\Translator; +use Thelia\Constraint\ConstraintValidator; +use Thelia\Constraint\Validator\QuantityParam; +use Thelia\Constraint\Validator\RuleValidator; +use Thelia\Coupon\CouponAdapterInterface; +use Thelia\Exception\InvalidRuleException; +use Thelia\Exception\InvalidRuleValueException; +use Thelia\Type\FloatType; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Check a Checkout against its Product number + * + * @package Constraint + * @author Guillaume MOREL + * + */ +class AvailableForXArticlesManager extends CouponRuleAbstract +{ + /** Rule 1st parameter : quantity */ + CONST INPUT1 = 'quantity'; + + /** @var string Service Id from Resources/config.xml */ + protected $serviceId = 'thelia.constraint.rule.available_for_x_articles'; + + /** @var array Available Operators (Operators::CONST) */ + protected $availableOperators = array( + self::INPUT1 => array( + Operators::INFERIOR, + Operators::INFERIOR_OR_EQUAL, + Operators::EQUAL, + Operators::SUPERIOR_OR_EQUAL, + Operators::SUPERIOR + ) + ); + +// /** @var QuantityParam Quantity Validator */ +// protected $quantityValidator = null; + +// /** +// * 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_QUANTITY]) +// ||!isset($this->validators[self::PARAM1_QUANTITY]) +// ) { +// throw new InvalidRuleValueException(get_class(), self::PARAM1_QUANTITY); +// } +// +// /** @var RuleValidator $ruleValidator */ +// $ruleValidator = $this->validators[self::PARAM1_QUANTITY]; +// /** @var QuantityParam $quantity */ +// $quantity = $ruleValidator->getParam(); +// +// if (!$quantity instanceof QuantityParam) { +// throw new InvalidRuleValueException(get_class(), self::PARAM1_QUANTITY); +// } +// +// $this->checkBackOfficeInputsOperators(); +// +// return $this->isQuantityValid($quantity->getInteger()); +// } + +// /** +// * Generate current Rule param to be validated from adapter +// * +// * @param CouponAdapterInterface $adapter allowing to gather +// * all necessary Thelia variables +// * +// * @return $this +// */ +// protected function setParametersToValidate() +// { +// $this->paramsToValidate = array( +// self::PARAM1_QUANTITY => $this->adapter->getNbArticlesInCart() +// ); +// +// 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_QUANTITY]) +// ) { +// throw new InvalidRuleValueException(get_class(), self::PARAM1_QUANTITY); +// } +// +// $price = $this->paramsToValidate[self::PARAM1_QUANTITY]; +// +// return $this->isQuantityValid($price); +// } + + /** + * Check validators relevancy and store them + * + * @param array $operators Operators the Admin set in BackOffice + * @param array $values Values the Admin set in BackOffice + * + * @throws \InvalidArgumentException + * @return $this + */ + public function setValidatorsFromForm(array $operators, array $values) + { + $this->setValidators( + $operators[self::INPUT1], + $values[self::INPUT1] + ); + + return $this; + } + + /** + * Check validators relevancy and store them + * + * @param string $quantityOperator Quantity Operator ex < + * @param int $quantityValue Quantity set to meet condition + * + * @throws \InvalidArgumentException + * @return $this + */ + protected function setValidators($quantityOperator, $quantityValue) + { + $isOperator1Legit = $this->isOperatorLegit( + $quantityOperator, + $this->availableOperators[self::INPUT1] + ); + if (!$isOperator1Legit) { + throw new \InvalidArgumentException( + 'Operator for quantity field is not legit' + ); + } + + if (!is_int($quantityValue) || $quantityValue <= 0) { + throw new \InvalidArgumentException( + 'Value for quantity field is not legit' + ); + } + + $this->operators = array( + self::INPUT1 => $quantityOperator, + ); + $this->values = array( + self::INPUT1 => $quantityValue, + ); + + return $this; + } + + /** + * Test if Customer meets conditions + * + * @return bool + */ + public function isMatching() + { + $constrainValidator = new ConstraintValidator(); + $constraint1 =$constrainValidator->variableOpComparison( + $this->adapter->getNbArticlesInCart(), + $this->operators[self::INPUT1], + $this->values[self::INPUT1] + ); + + if ($constraint1) { + return true; + } + return false; + } + +// /** +// * Check if a quantity is valid +// * +// * @param int $quantity Quantity to check +// * +// * @throws InvalidRuleValueException if Value is not allowed +// * @return bool +// */ +// protected function isQuantityValid($quantity) +// { +// $quantityValidator = $this->quantityValidator; +// try { +// $quantityValidator->getParam()->compareTo($quantity); +// } catch(InvalidArgumentException $e) { +// throw new InvalidRuleValueException(get_class(), self::PARAM1_QUANTITY); +// } +// +// return true; +// } + + /** + * Get I18n name + * + * @return string + */ + public function getName() + { + return $this->translator->trans( + 'Number of articles in cart', + array(), + 'constraint' + ); + } + + /** + * Get I18n tooltip + * + * @return string + */ + public function getToolTip() + { + $i18nOperator = Operators::getI18n( + $this->translator, $this->operators[self::INPUT1] + ); + + $toolTip = $this->translator->trans( + 'If cart products quantity is %operator% %quantity%', + array( + '%operator%' => $i18nOperator, + '%quantity%' => $this->values[self::INPUT1] + ), + '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 RuleValidator( +// $operators[self::PARAM1_QUANTITY], +// new QuantityParam( +// $this->adapter, +// $values[self::PARAM1_QUANTITY] +// ) +// ); +// +// $this->validators = array(self::PARAM1_QUANTITY => $this->quantityValidator); +// +// return $this; +// } + + /** + * Generate inputs ready to be drawn + * + * @return array + */ + protected function generateInputs() + { + $name1 = $this->translator->trans( + 'Quantity', + array(), + 'constraint' + ); + + return array( + self::INPUT1 => array( + 'title' => $name1, + 'availableOperators' => $this->availableOperators[self::INPUT1], + 'type' => 'text', + 'class' => 'form-control', + 'value' => '', + 'selectedOperator' => '' + ) + ); + } + +} \ No newline at end of file diff --git a/core/lib/Thelia/Constraint/Rule/CouponRuleAbstract.php b/core/lib/Thelia/Constraint/Rule/CouponRuleAbstract.php new file mode 100644 index 000000000..868db4dd7 --- /dev/null +++ b/core/lib/Thelia/Constraint/Rule/CouponRuleAbstract.php @@ -0,0 +1,262 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Constraint\Rule; + +use Symfony\Component\Intl\Exception\NotImplementedException; +use Thelia\Core\Translation\Translator; +use Thelia\Coupon\CouponAdapterInterface; +use Thelia\Constraint\Validator\ComparableInterface; +use Thelia\Constraint\Validator\RuleValidator; +use Thelia\Exception\InvalidRuleException; +use Thelia\Exception\InvalidRuleOperatorException; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Assist in writing a condition of whether the Rule is applied or not + * + * @package Constraint + * @author Guillaume MOREL + * + */ +abstract class CouponRuleAbstract implements CouponRuleInterface +{ +// /** Operator key in $validators */ +// CONST OPERATOR = 'operator'; +// /** Value key in $validators */ +// CONST VALUE = 'value'; + + /** @var string Service Id from Resources/config.xml */ + protected $serviceId = null; + + /** @var array Available Operators (Operators::CONST) */ + protected $availableOperators = array(); + + /** @var array Parameters validating parameters against */ + protected $validators = array(); + +// /** @var array Parameters to be validated */ +// protected $paramsToValidate = array(); + + /** @var CouponAdapterInterface Provide necessary value from Thelia */ + protected $adapter = null; + + /** @var Translator Service Translator */ + protected $translator = null; + + /** @var array Operators set by Admin in BackOffice */ + protected $operators = array(); + + /** @var array Values set by Admin in BackOffice */ + protected $values = array(); + + /** + * Constructor + * + * @param CouponAdapterInterface $adapter Service adapter + */ + function __construct(CouponAdapterInterface $adapter) + { + $this->adapter = $adapter; + $this->translator = $adapter->getTranslator(); + } + +// /** +// * Check validator relevancy and store them +// * +// * @param array $validators Array of RuleValidator +// * validating $paramsToValidate against +// * +// * @return $this +// * @throws InvalidRuleException +// */ +// protected function setValidators(array $validators) +// { +// foreach ($validators as $validator) { +// if (!$validator instanceof RuleValidator) { +// throw new InvalidRuleException(get_class()); +// } +// if (!in_array($validator->getOperator(), $this->availableOperators)) { +// throw new InvalidRuleOperatorException( +// get_class(), +// $validator->getOperator() +// ); +// } +// } +// $this->validators = $validators; +// +// return $this; +// } + + + +// /** +// * Check if the current Checkout matches this condition +// * +// * @return bool +// */ +// public function isMatching() +// { +// $this->checkBackOfficeInput(); +// $this->checkCheckoutInput(); +// +// $isMatching = true; +// /** @var $validator RuleValidator*/ +// foreach ($this->validators as $param => $validator) { +// $a = $this->paramsToValidate[$param]; +// $operator = $validator->getOperator(); +// /** @var ComparableInterface, RuleParameterAbstract $b */ +// $b = $validator->getParam(); +// +// if (!Operators::isValid($a, $operator, $b)) { +// $isMatching = false; +// } +// } +// +// return $isMatching; +// +// } + + /** + * Return all available Operators for this Rule + * + * @return array Operators::CONST + */ + public function getAvailableOperators() + { + return $this->availableOperators; + } + +// /** +// * Check if Operators set for this Rule in the BackOffice are legit +// * +// * @throws InvalidRuleOperatorException if Operator is not allowed +// * @return bool +// */ +// protected function checkBackOfficeInputsOperators() +// { +// /** @var RuleValidator $param */ +// foreach ($this->validators as $key => $param) { +// $operator = $param->getOperator(); +// if (!isset($operator) +// ||!in_array($operator, $this->availableOperators) +// ) { +// throw new InvalidRuleOperatorException(get_class(), $key); +// } +// } +// return true; +// } + +// /** +// * Generate current Rule param to be validated from adapter +// * +// * @throws \Thelia\Exception\NotImplementedException +// * @return $this +// */ +// protected function setParametersToValidate() +// { +// throw new \Thelia\Exception\NotImplementedException(); +// } + + /** + * Return all validators + * + * @return array + */ + public function getValidators() + { + $this->validators = $this->generateInputs(); + + $translatedInputs = array(); + foreach ($this->validators as $key => $validator) { + $translatedOperators = array(); + foreach ($validator['availableOperators'] as $availableOperators) { + $translatedOperators[$availableOperators] = Operators::getI18n( + $this->translator, + $availableOperators + ); + } + + $validator['availableOperators'] = $translatedOperators; + $translatedInputs[$key] = $validator; + } + + return $translatedInputs; + } + + /** + * Generate inputs ready to be drawn + * + * @throws \Thelia\Exception\NotImplementedException + * @return array + */ + protected function generateInputs() + { + throw new \Thelia\Exception\NotImplementedException( + 'The generateInputs method must be implemented in ' . get_class() + ); + } + + /** + * Get Rule Service id + * + * @return string + */ + public function getServiceId() + { + return $this->serviceId; + } + + /** + * Validate if Operator given is available for this Coupon + * + * @param string $operator Operator to validate ex < + * @param array $availableOperators Available operators + * + * @return bool + */ + protected function isOperatorLegit($operator, array $availableOperators) + { + return in_array($operator, $availableOperators); + } + + /** + * Return a serializable Rule + * + * @return SerializableRule + */ + public function getSerializableRule() + { + $serializableRule = new SerializableRule(); + $serializableRule->ruleServiceId = $this->serviceId; + $serializableRule->operators = $this->operators; + + $serializableRule->values = $this->values; + + return $serializableRule; + } + +} \ No newline at end of file diff --git a/core/lib/Thelia/Constraint/Rule/CouponRuleInterface.php b/core/lib/Thelia/Constraint/Rule/CouponRuleInterface.php new file mode 100644 index 000000000..ac9579094 --- /dev/null +++ b/core/lib/Thelia/Constraint/Rule/CouponRuleInterface.php @@ -0,0 +1,146 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Constraint\Rule; + +use Thelia\Core\Translation\Translator; +use Thelia\Coupon\CouponAdapterInterface; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Represents a condition of whether the Rule is applied or not + * + * @package Constraint + * @author Guillaume MOREL + * + */ +interface CouponRuleInterface +{ + /** + * Constructor + * + * @param CouponAdapterInterface $adapter Service adapter + */ + function __construct(CouponAdapterInterface $adapter); + + /** + * Get Rule Service id + * + * @return string + */ + public function getServiceId(); + +// /** +// * Check if backoffice inputs are relevant or not +// * +// * @return bool +// */ +// public function checkBackOfficeInput(); + +// /** +// * Check if Checkout inputs are relevant or not +// * +// * @return bool +// */ +// public function checkCheckoutInput(); + + /** + * Check validators relevancy and store them + * + * @param array $operators Operators the Admin set in BackOffice + * @param array $values Values the Admin set in BackOffice + * + * @throws \InvalidArgumentException + * @return $this + */ + public function setValidatorsFromForm(array $operators, array $values); + +// /** +// * Check if the current Checkout matches this condition +// * +// * @return bool +// */ +// public function isMatching(); + + /** + * Test if Customer meets conditions + * + * @return bool + */ + public function isMatching(); + + /** + * Return all available Operators for this Rule + * + * @return array Operators::CONST + */ + public function getAvailableOperators(); + + + /** + * Get I18n name + * + * @return string + */ + public function getName(); + + /** + * Get I18n tooltip + * + * @return string + */ + public function getToolTip(); + + /** + * Return all validators + * + * @return array + */ + public function getValidators(); + +// /** +// * Populate a Rule from a form admin +// * +// * @param array $operators Rule Operator set by the Admin +// * @param array $values Rule Values set by the Admin +// * +// * @return bool +// */ +// public function populateFromForm(array$operators, array $values); + + + /** + * Return a serializable Rule + * + * @return SerializableRule + */ + public function getSerializableRule(); + + + + + +} diff --git a/core/lib/Thelia/Constraint/Rule/Operators.php b/core/lib/Thelia/Constraint/Rule/Operators.php new file mode 100644 index 000000000..41640810c --- /dev/null +++ b/core/lib/Thelia/Constraint/Rule/Operators.php @@ -0,0 +1,188 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Constraint\Rule; + +use Symfony\Component\Translation\Translator; +use Thelia\Constraint\Validator\ComparableInterface; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Represent available Operations in rule checking + * + * @package Constraint + * @author Guillaume MOREL + * + */ +abstract class Operators +{ + /** Param1 is inferior to Param2 */ + CONST INFERIOR = '<'; + /** Param1 is inferior to Param2 */ + CONST INFERIOR_OR_EQUAL = '<='; + /** Param1 is equal to Param2 */ + CONST EQUAL = '=='; + /** Param1 is superior to Param2 */ + CONST SUPERIOR_OR_EQUAL = '>='; + /** Param1 is superior to Param2 */ + CONST SUPERIOR = '>'; + /** Param1 is different to Param2 */ + CONST DIFFERENT = '!='; + /** Param1 is in Param2 */ + CONST IN = 'in'; + /** Param1 is not in Param2 */ + CONST OUT = 'out'; + +// /** +// * Check if a parameter is valid against a ComparableInterface from its operator +// * +// * @param mixed $a Parameter to validate +// * @param string $operator Operator to validate against +// * @param ComparableInterface $b Comparable to validate against +// * +// * @return bool +// */ +// public static function isValid($a, $operator, ComparableInterface $b) +// { +// $ret = false; +// +// try { +// $comparison = $b->compareTo($a); +// } catch (\Exception $e) { +// return false; +// } +// +// switch ($operator) { +// case self::INFERIOR: +// if ($comparison == 1) { +// return true; +// } +// break; +// case self::INFERIOR_OR_EQUAL: +// if ($comparison == 1 || $comparison == 0) { +// return true; +// } +// break; +// case self::EQUAL: +// if ($comparison == 0) { +// return true; +// } +// break; +// case self::SUPERIOR_OR_EQUAL: +// if ($comparison == -1 || $comparison == 0) { +// return true; +// } +// break; +// case self::SUPERIOR: +// if ($comparison == -1) { +// return true; +// } +// break; +// case self::DIFFERENT: +// if ($comparison != 0) { +// return true; +// } +// break; +// default: +// } +// +// return $ret; +// } + + /** + * Get operator translation + * + * @param Translator $translator Provide necessary value from Thelia + * @param string $operator Operator const + * + * @return string + */ + public static function getI18n(Translator $translator, $operator) + { + $ret = $operator; + switch ($operator) { + case self::INFERIOR: + $ret = $translator->trans( + 'inferior to', + array(), + 'constraint' + ); + break; + case self::INFERIOR_OR_EQUAL: + $ret = $translator->trans( + 'inferior or equals to', + array(), + 'constraint' + ); + break; + case self::EQUAL: + $ret = $translator->trans( + 'equals to', + array(), + 'constraint' + ); + break; + case self::SUPERIOR_OR_EQUAL: + $ret = $translator->trans( + 'superior or equals to', + array(), + 'constraint' + ); + break; + case self::SUPERIOR: + $ret = $translator->trans( + 'superior to', + array(), + 'constraint' + ); + break; + case self::DIFFERENT: + $ret = $translator->trans( + 'different from', + array(), + 'constraint' + ); + break; + case self::IN: + $ret = $translator->trans( + 'in', + array(), + 'constraint' + ); + break; + case self::OUT: + $ret = $translator->trans( + 'not in', + array(), + 'constraint' + ); + break; + default: + } + + return $ret; + } +} \ No newline at end of file diff --git a/core/lib/Thelia/Constraint/Rule/SerializableRule.php b/core/lib/Thelia/Constraint/Rule/SerializableRule.php new file mode 100644 index 000000000..011c3e261 --- /dev/null +++ b/core/lib/Thelia/Constraint/Rule/SerializableRule.php @@ -0,0 +1,81 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Constraint\Rule; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * A rule set by an admin ready to be serialized and stored in DataBase + * + * @package Constraint + * @author Guillaume MOREL + * + */ +class SerializableRule +{ + /** @var string Rule Service id */ + public $ruleServiceId = 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(); + + /** + * Get Operators set by Admin for this Rule + * + * @return array + */ + public function getOperators() + { + return $this->operators; + } + + /** + * Get Rule Service id + * + * @return string + */ + public function getRuleServiceId() + { + return $this->ruleServiceId; + } + + /** + * Get Values set by Admin for this Rule + * + * @return array + */ + public function getValues() + { + return $this->values; + } + + + + +} \ No newline at end of file diff --git a/core/lib/Thelia/Constraint/Validator/ComparableInterface.php b/core/lib/Thelia/Constraint/Validator/ComparableInterface.php new file mode 100644 index 000000000..d06187fb0 --- /dev/null +++ b/core/lib/Thelia/Constraint/Validator/ComparableInterface.php @@ -0,0 +1,49 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Constraint\Validator; + +/** + * Comparable interface + * Allows to compare two value objects to each other for similarity. + * + * @author Benjamin Eberlei + * @author Guilherme Blanco + */ +interface ComparableInterface +{ + /** + * 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 + * + * @return int + */ + public function compareTo($other); +} \ No newline at end of file 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/Constraint/Validator/DateParam.php b/core/lib/Thelia/Constraint/Validator/DateParam.php new file mode 100644 index 000000000..ae7eff858 --- /dev/null +++ b/core/lib/Thelia/Constraint/Validator/DateParam.php @@ -0,0 +1,120 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Constraint\Validator; + +use Thelia\Coupon\CouponAdapterInterface; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Represent a DateTime + * + * @package Constraint + * @author Guillaume MOREL + * + */ +class DateParam extends RuleParameterAbstract +{ + /** @var \DateTime Date */ + protected $dateTime = null; + + /** + * Constructor + * + * @param CouponAdapterInterface $adapter Provide necessary value from Thelia + * @param \DateTime $dateTime DateTime + */ + public function __construct(CouponAdapterInterface $adapter, \DateTime $dateTime) + { + $this->dateTime = $dateTime; + $this->adapter = $adapter; + } + + /** + * Get DateTime + * + * @return \DateTime + */ + public function getDateTime() + { + return clone $this->dateTime; + } + + /** + * 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 (!$other instanceof \DateTime) { + throw new \InvalidArgumentException('DateParam can compare only DateTime'); + } + + $ret = -1; + if ($this->dateTime == $other) { + $ret = 0; + } elseif ($this->dateTime > $other) { + $ret = 1; + } else { + $ret = -1; + } + + return $ret; + } + + /** + * Get Parameter value to test against + * + * @return \Datetime + */ + public function getValue() + { + return clone $this->dateTime; + } + + /** + * Get I18n tooltip + * + * @return string + */ + public function getToolTip() + { + return $this->adapter + ->getTranslator() + ->trans('A date (ex: YYYY-MM-DD HH:MM:SS)', null, 'constraint'); + } + +} diff --git a/core/lib/Thelia/Constraint/Validator/IntegerParam.php b/core/lib/Thelia/Constraint/Validator/IntegerParam.php new file mode 100644 index 000000000..c783655c8 --- /dev/null +++ b/core/lib/Thelia/Constraint/Validator/IntegerParam.php @@ -0,0 +1,121 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Constraint\Validator; + +use Thelia\Coupon\CouponAdapterInterface; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Represent an Integer + * + * @package Constraint + * @author Guillaume MOREL + * + */ +class IntegerParam extends RuleParameterAbstract +{ + /** @var int Integer to compare with */ + protected $integer = 0; + + /** + * Constructor + * + * @param CouponAdapterInterface $adapter Provide necessary value from Thelia + * @param int $integer Integer + */ + public function __construct(CouponAdapterInterface $adapter, $integer) + { + $this->integer = $integer; + $this->adapter = $adapter; + } + + /** + * Get integer + * + * @return int + */ + public function getInteger() + { + return $this->integer; + } + + + /** + * 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)) { + throw new \InvalidArgumentException('IntegerParam can compare only int'); + } + + $ret = -1; + if ($this->integer == $other) { + $ret = 0; + } elseif ($this->integer > $other) { + $ret = 1; + } else { + $ret = -1; + } + + return $ret; + } + + /** + * Get Parameter value to test against + * + * @return int + */ + public function getValue() + { + return $this->integer; + } + + /** + * Get I18n tooltip + * + * @return string + */ + public function getToolTip() + { + return $this->adapter + ->getTranslator() + ->trans('A number (ex: 42)', null, 'constraint'); + } + +} \ No newline at end of file diff --git a/core/lib/Thelia/Constraint/Validator/IntervalParam.php b/core/lib/Thelia/Constraint/Validator/IntervalParam.php new file mode 100644 index 000000000..a4554760a --- /dev/null +++ b/core/lib/Thelia/Constraint/Validator/IntervalParam.php @@ -0,0 +1,165 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Constraint\Validator; + +use Thelia\Coupon\CouponAdapterInterface; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Represent an DateTime period + * + * @package Constraint + * @author Guillaume MOREL + * + */ +class IntervalParam extends RuleParameterAbstract +{ + /** @var \DatePeriod Date period */ + protected $datePeriod = null; + + /** @var \DateTime Start date */ + protected $start = null; + + /** @var \DateInterval Interval date */ + protected $interval = null; + + /** + * Constructor + * + * @param CouponAdapterInterface $adapter Provide necessary value from Thelia + * @param \DateTime $start Start interval + * @param \DateInterval $interval Period + */ + public function __construct(CouponAdapterInterface $adapter, \DateTime $start, \DateInterval $interval) + { + $this->datePeriod = new \DatePeriod($start, $interval, 1); + $this->adapter = $adapter; + + $this->start = $start; + $this->interval = $interval; + } + + /** + * Get Interval + * + * @return \DateInterval + */ + public function getInterval() + { + return $this->interval; + } + + /** + * Get start date + * + * @return \DateTime + */ + public function getStart() + { + return $this->start; + } + + + + /** + * Get DatePeriod + * + * @return \DatePeriod + */ + public function getDatePeriod() + { + return clone $this->datePeriod; + } + + /** + * 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 (!$other instanceof \DateTime) { + throw new \InvalidArgumentException('IntervalParam can compare only DateTime'); + } + + /** @var \DateTime Start Date */ + $startDate = null; + /** @var \DateTime End Date */ + $endDate = null; + + foreach ($this->datePeriod as $key => $value) { + if ($key == 0) { + $startDate = $value; + } + if ($key == 1) { + $endDate = $value; + } + } + + $ret = -1; + if ($startDate <= $other && $other <= $endDate) { + $ret = 0; + } elseif ($startDate > $other) { + $ret = 1; + } else { + $ret = -1; + } + + return $ret; + } + + /** + * Get Parameter value to test against + * + * @return \DatePeriod + */ + public function getValue() + { + return clone $this->datePeriod; + } + + /** + * Get I18n tooltip + * + * @return string + */ + public function getToolTip() + { + return $this->adapter + ->getTranslator() + ->trans('An interval between two dates', null, 'constraint'); + } +} \ No newline at end of file diff --git a/core/lib/Thelia/Constraint/Validator/ModelParam.php b/core/lib/Thelia/Constraint/Validator/ModelParam.php new file mode 100644 index 000000000..7ff4567b8 --- /dev/null +++ b/core/lib/Thelia/Constraint/Validator/ModelParam.php @@ -0,0 +1,115 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Constraint\Validator; + +use InvalidArgumentException; +use Thelia\Coupon\CouponAdapterInterface; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Represent a Model + * + * @package Constraint + * @author Guillaume MOREL + * + */ +class ModelParam extends IntegerParam +{ + /** @var string Model Class name */ + protected $modelClass = null; + + /** @var ModelCriteria */ + protected $queryBuilder = null; + + /** + * Constructor + * + * @param CouponAdapterInterface $adapter Provide necessary value from Thelia + * @param int $integer Integer + * @param string $modelClass Model class name + * + * @throws InvalidArgumentException + */ + public function __construct(CouponAdapterInterface $adapter, $integer, $modelClass) + { + if ($integer < 0) { + $integer = 0; + } + $this->integer = $integer; + $this->adapter = $adapter; + + $this->modelClass = $modelClass; + $queryClassName = $modelClass . 'Query'; + try { + $this->queryBuilder = $queryClassName::create(); + } catch (\Exception $e) { + throw new InvalidArgumentException('ModelParam can only compare Models'); + } + } + + /** + * 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); + } + + /** + * Get I18n tooltip + * + * @return string + */ + public function getToolTip() + { + return $this->adapter + ->getTranslator() + ->trans( + 'A Model', + null, + 'constraint' + ); + } + +} diff --git a/core/lib/Thelia/Constraint/Validator/PriceParam.php b/core/lib/Thelia/Constraint/Validator/PriceParam.php new file mode 100644 index 000000000..e965d6aba --- /dev/null +++ b/core/lib/Thelia/Constraint/Validator/PriceParam.php @@ -0,0 +1,145 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Constraint\Validator; + +use Thelia\Core\Translation\Translator; +use Thelia\Coupon\CouponAdapterInterface; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Represent a Price + * Positive value with currency + * + * @package Constraint + * @author Guillaume MOREL + * + */ +class PriceParam extends RuleParameterAbstract +{ + /** @var float Positive Float to compare with */ + protected $price = null; + + /** @var string Currency Code ISO 4217 EUR|USD|GBP */ + protected $currency = null; + + /** + * Constructor + * + * @param Translator $translator Service translator + * @param float $price Positive float + * @param string $currency Currency Code ISO 4217 EUR|USD|GBP + */ + public function __construct(Translator $translator, $price, $currency) + { + $this->price = $price; + $this->currency = $currency; + $this->translator = $translator; + } + + /** + * Get currency code + * + * @return string + */ + public function getCurrency() + { + return $this->currency; + } + + /** + * Get price + * + * @return float + */ + public function getPrice() + { + return $this->price; + } + + /** + * 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_float($other)) { + throw new \InvalidArgumentException( + 'PriceParam can compare only positive float' + ); + } + + $epsilon = 0.00001; + + $ret = -1; + if (abs($this->price - $other) < $epsilon) { + $ret = 0; + } elseif ($this->price > $other) { + $ret = 1; + } else { + $ret = -1; + } + + return $ret; + } + + /** + * Get Parameter value to test against + * + * @return float + */ + public function getValue() + { + return $this->price; + } + + /** + * Get I18n tooltip + * + * @return string + */ + public function getToolTip() + { + return $this->translator + ->trans( + 'A price in %currency% (ex: 14.50)', + array( + '%currency%' => $this->currency + ), + 'constraint' + ); + } +} \ No newline at end of file diff --git a/core/lib/Thelia/Constraint/Validator/QuantityParam.php b/core/lib/Thelia/Constraint/Validator/QuantityParam.php new file mode 100644 index 000000000..ac6fcf851 --- /dev/null +++ b/core/lib/Thelia/Constraint/Validator/QuantityParam.php @@ -0,0 +1,96 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Constraint\Validator; + +use Thelia\Coupon\CouponAdapterInterface; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Represent a Quantity + * + * @package Constraint + * @author Guillaume MOREL + * + */ +class QuantityParam extends IntegerParam +{ + + /** + * Constructor + * + * @param CouponAdapterInterface $adapter Provide necessary value from Thelia + * @param int $integer Integer + */ + public function __construct(CouponAdapterInterface $adapter, $integer) + { + $this->integer = $integer; + $this->adapter = $adapter; + } + + /** + * 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); + } + + + /** + * Get I18n tooltip + * + * @return string + */ + public function getToolTip() + { + return $this->adapter + ->getTranslator() + ->trans( + 'A positive quantity (ex: 42)', + null, + 'constraint' + ); + } + +} diff --git a/core/lib/Thelia/Constraint/Validator/RepeatedDateParam.php b/core/lib/Thelia/Constraint/Validator/RepeatedDateParam.php new file mode 100644 index 000000000..0e8a558cf --- /dev/null +++ b/core/lib/Thelia/Constraint/Validator/RepeatedDateParam.php @@ -0,0 +1,117 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Constraint\Validator; + +use Thelia\Coupon\CouponAdapterInterface; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Represent A repeated Date across the time + * Ex : + * A date repeated every 1 months 5 times + * ---------*---*---*---*---*---*---------------------------> time + * 1 2 3 4 5 6 + * 1 : $this->from Start date of the repetition + * *--- : $this->interval Duration of a whole cycle + * x5 : $this->recurrences How many repeated cycle, 1st excluded + * x6 : How many occurrence + * + * @package Constraint + * @author Guillaume MOREL + * + */ +class RepeatedDateParam extends RepeatedParam +{ + /** + * Constructor + * + * @param CouponAdapterInterface $adapter Provide necessary value from Thelia + */ + public function __construct(CouponAdapterInterface $adapter) + { + $this->defaultConstructor(); + $this->adapter = $adapter; + } + + /** + * 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 (!$other instanceof \DateTime) { + throw new \InvalidArgumentException('RepeatedDateParam can compare only DateTime'); + } + + $ret = -1; + $dates = array(); + /** @var $value \DateTime */ + foreach ($this->datePeriod as $value) { + $dates[$value->getTimestamp()] = $value; + } + + foreach ($dates as $date) { + if ($date == $other) { + return 0; + } + } + + return $ret; + } + + /** + * Get Parameter value to test against + * + * @return \DatePeriod + */ + public function getValue() + { + return clone $this->datePeriod; + } + + /** + * Get I18n tooltip + * + * @return string + */ + public function getToolTip() + { + return $this->adapter + ->getTranslator() + ->trans('A date (ex: YYYY-MM-DD HH:MM:SS)', null, 'constraint'); + } +} \ No newline at end of file diff --git a/core/lib/Thelia/Constraint/Validator/RepeatedIntervalParam.php b/core/lib/Thelia/Constraint/Validator/RepeatedIntervalParam.php new file mode 100644 index 000000000..e37cd3b45 --- /dev/null +++ b/core/lib/Thelia/Constraint/Validator/RepeatedIntervalParam.php @@ -0,0 +1,151 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Constraint\Validator; + +use Thelia\Coupon\CouponAdapterInterface; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Represent A repeated DateInterval across the time + * Ex : + * A duration of 1 month repeated every 2 months 5 times + * ---------****----****----****----****----****----****-----------------> time + * 1 2 3 4 5 6 + * 1 : $this->from Start date of the repetition + * ****---- : $this->interval Duration of a whole cycle + * x5 : $this->recurrences How many repeated cycle, 1st excluded + * x6 : How many occurrence + * **** : $this->durationInDays Duration of a period + * + * @package Constraint + * @author Guillaume MOREL + * + */ +class RepeatedIntervalParam extends RepeatedParam +{ + + /** @var int duration of the param */ + protected $durationInDays = 1; + + /** + * Get how many day a Param is lasting + * + * @return int + */ + public function getDurationInDays() + { + return $this->durationInDays; + } + + /** + * Set how many day a Param is lasting + * + * @param int $durationInDays How many day a Param is lasting + * + * @return $this + */ + public function setDurationInDays($durationInDays = 1) + { + $this->durationInDays = $durationInDays; + + return $this; + } + + /** + * Constructor + * + * @param CouponAdapterInterface $adapter Provide necessary value from Thelia + */ + public function __construct(CouponAdapterInterface $adapter) + { + $this->defaultConstructor(); + $this->adapter = $adapter; + } + + /** + * 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 (!$other instanceof \DateTime) { + throw new \InvalidArgumentException('RepeatedIntervalParam can compare only DateTime'); + } + + $ret = -1; + $dates = array(); + /** @var $value \DateTime */ + foreach ($this->datePeriod as $value) { + $dates[$value->getTimestamp()]['startDate'] = $value; + $endDate = new \DateTime(); + $dates[$value->getTimestamp()]['endDate'] = $endDate->setTimestamp( + $value->getTimestamp() + ($this->durationInDays * 60 *60 *24) + ); + } + + foreach ($dates as $date) { + if ($date['startDate'] <= $other && $other <= $date['endDate']) { + return 0; + } + } + + return $ret; + + } + + /** + * Get Parameter value to test against + * + * @return \DatePeriod + */ + public function getValue() + { + return clone $this->datePeriod; + } + + /** + * Get I18n tooltip + * + * @return string + */ + public function getToolTip() + { + return $this->adapter + ->getTranslator() + ->trans('A date (ex: YYYY-MM-DD HH:MM:SS)', null, 'constraint'); + } +} \ No newline at end of file diff --git a/core/lib/Thelia/Constraint/Validator/RepeatedParam.php b/core/lib/Thelia/Constraint/Validator/RepeatedParam.php new file mode 100644 index 000000000..1188e4fbb --- /dev/null +++ b/core/lib/Thelia/Constraint/Validator/RepeatedParam.php @@ -0,0 +1,297 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Constraint\Validator; + +use DateInterval; +use DatePeriod; +use DateTime; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Allow to set the way a parameter can be repeated across the time + * + * @package Constraint + * @author Guillaume MOREL + * + */ +abstract class RepeatedParam extends RuleParameterAbstract +{ + /** @var DateTime The start date of the period. */ + protected $from = null; + + /** @var DateInterval The interval between recurrences within the period. */ + protected $interval = null; + + /** @var int Nb time the object will be repeated (1st occurrence excluded). */ + protected $recurrences = null; + + /** @var DatePeriod dates recurring at regular intervals, over a given period */ + protected $datePeriod = null; + + /** @var int Frequency the object will be repeated */ + protected $frequency = null; + + /** @var int $nbRepetition Time the object will be repeated */ + protected $nbRepetition = null; + + /** + * Get frequency + * + * @return int + */ + public function getFrequency() + { + return $this->frequency; + } + + /** + * Get Interval + * + * @return \DateInterval + */ + public function getInterval() + { + return $this->interval; + } + + /** + * Get number of time it will be repeated + * + * @return int + */ + public function getNbRepetition() + { + return $this->nbRepetition; + } + + /** + * Get number of recurrences + * + * @return int + */ + public function getRecurrences() + { + return $this->recurrences; + } + + /** + * Generate default repetition + * Every 1 week 100 times from now + * + * @return $this + */ + protected function defaultConstructor() + { + $this->from = new \DateTime(); + $this->interval = new \DateInterval('P1W'); // 1 week + $this->recurrences = 100; + $this->generateDatePeriod(); + + return $this; + } + + /** + * Generate DatePeriod from class attributes + * Will repeat every DatePeriod + * + * @return $this + */ + protected function generateDatePeriod() + { + $this->datePeriod = new DatePeriod( + $this->from, + $this->interval, + $this->recurrences + ); + + return $this; + } + + /** + * Set the Object to be repeated every days + * Ex : $obj->repeatEveryDay() will occur once + * $obj->repeatEveryDay(10) will occur once + * $obj->repeatEveryDay(10, 0) will occur once + * $obj->repeatEveryDay(10, 4) will occur every 10 days 5 times + * + * @param int $frequency Frequency the object will be repeated + * @param int $nbRepetition Time the object will be repeated + * + * @return $this + */ + public function repeatEveryDay($frequency = 1, $nbRepetition = 0) + { + $this->_repeatEveryPeriod($period = 'D', $frequency, $nbRepetition); + + return $this; + } + + /** + * Set the Object to be repeated every week + * Ex : $obj->repeatEveryWeek() will occur once + * $obj->repeatEveryWeek(10) will occur once + * $obj->repeatEveryWeek(10, 0) will occur once + * $obj->repeatEveryWeek(10, 4) will occur every 10 weeks (70days) 5 times + * + * @param int $frequency Frequency the object will be repeated + * @param int $nbRepetition Time the object will be repeated + * + * @return $this + */ + public function repeatEveryWeek($frequency = 1, $nbRepetition = 0) + { + $this->_repeatEveryPeriod($period = 'W', $frequency, $nbRepetition); + + return $this; + } + + /** + * Set the Object to be repeated every month + * Ex : $obj->repeatEveryWeek() will occur once + * $obj->repeatEveryWeek(10) will occur once + * $obj->repeatEveryWeek(10, 0) will occur once + * $obj->repeatEveryWeek(10, 4) will occur every 10 month (70days) 5times + * + * @param int $frequency Frequency the object will be repeated + * @param int $nbRepetition Time the object will be repeated + * + * @return $this + */ + public function repeatEveryMonth($frequency = 1, $nbRepetition = 0) + { + $this->_repeatEveryPeriod($period = 'M', $frequency, $nbRepetition); + + return $this; + } + + /** + * Set the Object to be repeated every year + * Ex : $obj->repeatEveryWeek() will occur once + * $obj->repeatEveryWeek(10) will occur once + * $obj->repeatEveryWeek(10, 0) will occur once + * $obj->repeatEveryWeek(10, 4) will occur every 10 year 5 times + * + * @param int $frequency Frequency the object will be repeated + * @param int $nbRepetition Time the object will be repeated + * + * @return $this + */ + public function repeatEveryYear($frequency = 1, $nbRepetition = 0) + { + $this->_repeatEveryPeriod($period = 'Y', $frequency, $nbRepetition); + + return $this; + } + + /** + * Set the Object to be repeated every Period + * Ex : $obj->repeatEveryPeriod('D') will occur once + * $obj->repeatEveryPeriod('W', 10) will occur once + * $obj->repeatEveryPeriod('W', 10, 0) will occur once + * $obj->repeatEveryPeriod('M', 10, 4) will occur every 10 month 5 times + * + * @param string $period Period Y|M||D|W + * @param int $frequency Frequency the object will be repeated + * @param int $nbRepetition Time the object will be repeated + * + * @return $this + */ + private function _repeatEveryPeriod($period, $frequency = 1, $nbRepetition = 0) + { + if (is_numeric($frequency) && $frequency > 0) { + $this->interval = new \DateInterval('P' . $frequency . $period); + } + + if (is_numeric($nbRepetition) && $nbRepetition >= 0) { + $this->recurrences = $nbRepetition; + } + + $this->generateDatePeriod(); + + return $this; + } + + + + /** + * Set Start time + * + * @param \DateTime $from Start time + * + * @return $this + */ + public function setFrom($from) + { + $this->from = $from; + + return $this; + } + + /** + * Get Start time + * + * @return \DateTime + */ + public function getFrom() + { + return clone $this->from; + } + + /** + * Set DatePeriod + * + * @param DatePeriod $datePeriod DatePeriod + * + * @return $this + */ + public function setDatePeriod(DatePeriod $datePeriod) + { + $this->datePeriod = $datePeriod; + + return $this; + } + + /** + * Get date DatePeriod + * + * @return \DatePeriod + */ + public function getDatePeriod() + { + return clone $this->datePeriod; + } + + /** + * Get Parameter value to test against + * + * @return \DatePeriod + */ + public function getValue() + { + return clone $this->datePeriod; + } +} \ No newline at end of file diff --git a/core/lib/Thelia/Constraint/Validator/RuleParameterAbstract.php b/core/lib/Thelia/Constraint/Validator/RuleParameterAbstract.php new file mode 100644 index 000000000..2be4c581f --- /dev/null +++ b/core/lib/Thelia/Constraint/Validator/RuleParameterAbstract.php @@ -0,0 +1,67 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Constraint\Validator; + +use Thelia\Core\Translation\Translator; +use Thelia\Coupon\CouponAdapterInterface; +use Thelia\Exception\NotImplementedException; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Get a Param value + * + * @package Constraint + * @author Guillaume MOREL + * + */ +abstract class RuleParameterAbstract implements ComparableInterface +{ + /** @var Translator Service Translator */ + protected $translator = null; + + /** + * Get Parameter value to test against + * + * @return mixed + */ + public function getValue() + { + return new NotImplementedException(); + } + + /** + * Get I18n tooltip + * + * @return string + */ + public function getToolTip() + { + return new NotImplementedException(); + } + + +} \ No newline at end of file diff --git a/core/lib/Thelia/Constraint/Validator/RuleValidator.php b/core/lib/Thelia/Constraint/Validator/RuleValidator.php new file mode 100644 index 000000000..9b0093bc9 --- /dev/null +++ b/core/lib/Thelia/Constraint/Validator/RuleValidator.php @@ -0,0 +1,77 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Constraint\Validator; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Allow to validate parameters + * + * @package Constraint + * @author Guillaume MOREL + * + */ +class RuleValidator +{ + /** @var string Operator ex: Operators::INFERIOR */ + protected $operator = null; + + /** @var ComparableInterface Validator */ + protected $param = null; + + /** + * Constructor + * + * @param string $operator Operator ex: Operators::INFERIOR + * @param ComparableInterface $param Validator ex: PriceParam + */ + function __construct($operator, ComparableInterface $param) + { + $this->operator = $operator; + $this->param = $param; + } + + /** + * Get Validator Operator + * + * @return string + */ + public function getOperator() + { + return $this->operator; + } + + /** + * Get Validator Param + * + * @return ComparableInterface + */ + public function getParam() + { + return $this->param; + } + +} \ No newline at end of file diff --git a/core/lib/Thelia/Controller/Admin/BaseAdminController.php b/core/lib/Thelia/Controller/Admin/BaseAdminController.php index eab57394b..5461b8d3f 100755 --- a/core/lib/Thelia/Controller/Admin/BaseAdminController.php +++ b/core/lib/Thelia/Controller/Admin/BaseAdminController.php @@ -22,6 +22,9 @@ /*************************************************************************************/ namespace Thelia\Controller\Admin; +use Symfony\Component\Routing\Exception\InvalidParameterException; +use Symfony\Component\Routing\Exception\MissingMandatoryParametersException; +use Symfony\Component\Routing\Exception\RouteNotFoundException; use Thelia\Controller\BaseController; use Symfony\Component\HttpFoundation\Response; use Thelia\Core\Security\Exception\AuthorizationException; @@ -34,6 +37,9 @@ use Thelia\Core\Security\SecurityContext; use Thelia\Model\AdminLog; use Thelia\Model\Lang; use Thelia\Model\LangQuery; +use Thelia\Form\BaseForm; +use Thelia\Form\Exception\FormValidationException; +use Thelia\Log\Tlog; class BaseAdminController extends BaseController { @@ -66,7 +72,7 @@ class BaseAdminController extends BaseController } } catch (\Exception $ex) { - return new Response($this->errorPage($ex->getMessage())); + return $this->errorPage($ex->getMessage()); } return $this->pageNotFound(); @@ -92,7 +98,7 @@ class BaseAdminController extends BaseController protected function errorPage($message) { if ($message instanceof \Exception) { - $message = sprintf("Sorry, an error occured: %s", $message->getMessage()); + $message = sprintf($this->getTranslator()->trans("Sorry, an error occured: %msg"), array('msg' => $message->getMessage())); } return $this->render('general_error', array( @@ -123,7 +129,56 @@ class BaseAdminController extends BaseController // Generate the proper response $response = new Response(); - return $response->setContent($this->errorPage("Sorry, you're not allowed to perform this action")); + return $this->errorPage($this->getTranslator()->trans("Sorry, you're not allowed to perform this action")); + } + + /* + * Create the standard message displayed to the user when the form cannot be validated. + */ + protected function createStandardFormValidationErrorMessage(FormValidationException $exception) { + return $this->getTranslator()->trans( + "Please check your input: %error", + array( + '%error' => $exception->getMessage() + ) + ); + } + + /** + * Setup the error context when an error occurs in a action method. + * + * @param string $action the action that caused the error (category modification, variable creation, currency update, etc.) + * @param BaseForm $form the form where the error occured, or null if no form was involved + * @param string $error_message the error message + * @param Exception $exception the exception or null if no exception + */ + protected function setupFormErrorContext($action, $error_message, BaseForm $form = null, \Exception $exception = null) { + + if ($error_message !== false) { + + // Log the error message + Tlog::getInstance()->error( + $this->getTranslator()->trans( + "Error during %action process : %error. Exception was %exc", + array( + '%action' => $action, + '%error' => $error_message, + '%exc' => $exception != null ? $exception->getMessage() : 'no exception' + ) + ) + ); + + if ($form != null) { + // Mark the form as errored + $form->setErrorMessage($error_message); + + // Pass it to the parser context + $this->getParserContext()->addForm($form); + } + + // Pass the error message to the parser. + $this->getParserContext()->setGeneralError($error_message); + } } /** @@ -159,12 +214,26 @@ class BaseAdminController extends BaseController /** * Return the route path defined for the givent route ID * - * @param string $routeId a route ID, as defines in Config/Resources/routing/admin.xml + * @param string $routeId a route ID, as defines in Config/Resources/routing/admin.xml + * @param mixed $parameters An array of parameters + * @param Boolean|string $referenceType The type of reference to be generated (one of the constants) + * + * @throws RouteNotFoundException If the named route doesn't exist + * @throws MissingMandatoryParametersException When some parameters are missing that are mandatory for the route + * @throws InvalidParameterException When a parameter value for a placeholder is not correct because + * it does not match the requirement + * @throws \InvalidArgumentException When the router doesn't exist + * @return string The generated URL * * @see \Thelia\Controller\BaseController::getRouteFromRouter() */ - protected function getRoute($routeId) { - return $this->getRouteFromRouter('router.admin', $routeId); + protected function getRoute($routeId, $parameters = array(), $referenceType = Router::ABSOLUTE_PATH) { + return $this->getRouteFromRouter( + 'router.admin', + $routeId, + $parameters, + $referenceType + ); } /** @@ -261,7 +330,7 @@ class BaseAdminController extends BaseController } catch (AuthorizationException $ex) { // User is not allowed to perform the required action. Return the error page instead of the requested page. - return $this->errorPage("Sorry, you are not allowed to perform this action."); + return $this->errorPage($this->getTranslator()->trans("Sorry, you are not allowed to perform this action.")); } } } diff --git a/core/lib/Thelia/Controller/Admin/CategoryController.php b/core/lib/Thelia/Controller/Admin/CategoryController.php index 6cba34e39..5eca91cf9 100755 --- a/core/lib/Thelia/Controller/Admin/CategoryController.php +++ b/core/lib/Thelia/Controller/Admin/CategoryController.php @@ -34,226 +34,305 @@ use Thelia\Core\Event\CategoryToggleVisibilityEvent; use Thelia\Core\Event\CategoryChangePositionEvent; use Thelia\Form\CategoryDeletionForm; use Thelia\Model\Lang; +use Thelia\Core\Translation\Translator; +use Thelia\Core\Event\CategoryUpdatePositionEvent; +use Thelia\Model\CategoryQuery; +use Thelia\Form\CategoryModificationForm; class CategoryController extends BaseAdminController { - protected function createNewCategory($args) - { - try { - $categoryCreationForm = new CategoryCreationForm($this->getRequest()); - - $form = $this->validateForm($categoryCreationForm, "POST"); - - $data = $form->getData(); - - $categoryCreateEvent = new CategoryCreateEvent( - $data["title"], - $data["parent"], - $data["locale"] - ); - - $this->dispatch(TheliaEvents::CATEGORY_CREATE, $categoryCreateEvent); - - $category = $categoryCreateEvent->getCreatedCategory(); - - $this->adminLogAppend(sprintf("Category %s (ID %s) created", $category->getTitle(), $category->getId())); - - // Substitute _ID_ in the URL with the ID of the created category - $successUrl = str_replace('_ID_', $category->getId(), $categoryCreationForm->getSuccessUrl()); - - // Redirect to the success URL - $this->redirect($successUrl); - } - catch (FormValidationException $e) { - $categoryCreationForm->setErrorMessage($e->getMessage()); - $this->getParserContext()->addForm($categoryCreationForm); - } - catch (Exception $e) { - Tlog::getInstance()->error(sprintf("Failed to create category: %s", $e->getMessage())); - $this->getParserContext()->setGeneralError($e->getMessage()); - } - - // At this point, the form has error, and should be redisplayed. - return $this->render('categories', $args); + /** + * Render the categories list, ensuring the sort order is set. + * + * @return Symfony\Component\HttpFoundation\Response the response + */ + protected function renderList() { + return $this->render('categories', $this->getTemplateArgs()); } - protected function editCategory($args) - { - if (null !== $response = $this->checkAuth("admin.category.edit")) return $response; - - return $this->render('edit_category', $args); - } - - protected function deleteCategory($args) - { - try { - $categoryDeletionForm = new CategoryDeletionForm($this->getRequest()); - - $data = $this->validateForm($categoryDeletionForm, "POST")->getData(); - - $categoryDeleteEvent = new CategoryDeleteEvent($data['category_id']); - - $this->dispatch(TheliaEvents::CATEGORY_DELETE, $categoryDeleteEvent); - - $category = $categoryDeleteEvent->getDeletedCategory(); - - $this->adminLogAppend(sprintf("Category %s (ID %s) deleted", $category->getTitle(), $category->getId())); - - // Substitute _ID_ in the URL with the ID of the created category - $successUrl = str_replace('_ID_', $categoryDeleteEvent->getDeletedCategory()->getParent(), $categoryDeletionForm->getSuccessUrl()); - - // Redirect to the success URL - $this->redirect($successUrl); - } - catch (FormValidationException $e) { - $categoryDeletionForm->setErrorMessage($e->getMessage()); - $this->getParserContext()->addForm($categoryDeletionForm); - } - catch (Exception $e) { - Tlog::getInstance()->error(sprintf("Failed to delete category: %s", $e->getMessage())); - $this->getParserContext()->setGeneralError($e->getMessage()); - } - - // At this point, something was wrong, category was not deleted. Display parent category list - return $this->render('categories', $args); - } - - protected function browseCategory($args) - { - if (null !== $response = $this->checkAuth("admin.catalog.view")) return $response; - - return $this->render('categories', $args); - } - - protected function visibilityToggle($args) - { - $event = new CategoryToggleVisibilityEvent($this->getRequest()->get('category_id', 0)); - - $this->dispatch(TheliaEvents::CATEGORY_TOGGLE_VISIBILITY, $event); - - return $this->nullResponse(); - } - - protected function changePosition($args) - { - $request = $this->getRequest(); - - $event = new CategoryChangePositionEvent( - $request->get('category_id', 0), - CategoryChangePositionEvent::POSITION_ABSOLUTE, - $request->get('position', null) - ); - - $this->dispatch(TheliaEvents::CATEGORY_CHANGE_POSITION, $event); - - return $this->render('categories', $args); - } - - protected function positionDown($args) - { - $event = new CategoryChangePositionEvent( - $this->getRequest()->get('category_id', 0), - CategoryChangePositionEvent::POSITION_DOWN - ); - - $this->dispatch(TheliaEvents::CATEGORY_CHANGE_POSITION, $event); - - return $this->render('categories', $args); - } - - protected function positionUp($args) - { - $event = new CategoryChangePositionEvent( - $this->getRequest()->get('category_id', 0), - CategoryChangePositionEvent::POSITION_UP - ); - - $this->dispatch(TheliaEvents::CATEGORY_CHANGE_POSITION, $event); - - return $this->render('categories', $args); - } - - public function indexAction() - { - return $this->processAction(); - } - - public function processAction() - { - // Get the current action - $action = $this->getRequest()->get('action', 'browse'); + protected function getTemplateArgs() { // Get the category ID - $id = $this->getRequest()->get('id', 0); + $category_id = $this->getRequest()->get('category_id', 0); - // Find the current order + // Find the current category order $category_order = $this->getRequest()->get( 'order', $this->getSession()->get('admin.category_order', 'manual') ); - // Find the current edit language ID - $edition_language = $this->getRequest()->get( - 'edition_language', - $this->getSession()->get('admin.edition_language', Lang::getDefaultLanguage()->getId()) - ); - $args = array( - 'action' => $action, - 'current_category_id' => $id, + 'current_category_id' => $category_id, 'category_order' => $category_order, - 'edition_language' => $edition_language, ); // Store the current sort order in session $this->getSession()->set('admin.category_order', $category_order); - // Store the current edition language in session - $this->getSession()->set('admin.edition_language', $edition_language); + return $args; + } + + /** + * The default action is displaying the categories list. + * + * @return Symfony\Component\HttpFoundation\Response the response + */ + public function defaultAction() { + + if (null !== $response = $this->checkAuth("admin.categories.view")) return $response; + + return $this->renderList(); + } + + /** + * Create a new category object + * + * @return Symfony\Component\HttpFoundation\Response the response + */ + public function createAction() { + + // Check current user authorization + if (null !== $response = $this->checkAuth("admin.categories.create")) return $response; + + $error_msg = false; + + // Create the Creation Form + $creationForm = new CategoryCreationForm($this->getRequest()); try { - switch ($action) { - case 'browse' : // Browse categories - return $this->browseCategory($args); + // Validate the form, create the CategoryCreation event and dispatch it. + $form = $this->validateForm($creationForm, "POST"); - case 'create' : // Create a new category + $data = $form->getData(); - return $this->createNewCategory($args); + $createEvent = new CategoryCreateEvent( + $data["title"], + $data["parent"], + $data["locale"] + ); - case 'edit' : // Edit an existing category + $this->dispatch(TheliaEvents::CATEGORY_CREATE, $createEvent); - return $this->editCategory($args); + if (! $createEvent->hasCategory()) throw new \LogicException($this->getTranslator()->trans("No category was created.")); - case 'delete' : // Delete an existing category + $createdObject = $createEvent->getCategory(); - return $this->deleteCategory($args); + // Log category creation + $this->adminLogAppend(sprintf("Category %s (ID %s) created", $createdObject->getTitle(), $createdObject->getId())); - case 'visibilityToggle' : // Toggle visibility + // Substitute _ID_ in the URL with the ID of the created object + $successUrl = str_replace('_ID_', $createdObject->getId(), $creationForm->getSuccessUrl()); - 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); - } + // Redirect to the success URL + $this->redirect($successUrl); } - catch (AuthorizationException $ex) { - return $this->errorPage($ex->getMessage()); + catch (FormValidationException $ex) { + // Form cannot be validated + $error_msg = $this->createStandardFormValidationErrorMessage($ex); } - catch (AuthenticationException $ex) { - return $this->errorPage($ex->getMessage()); + catch (\Exception $ex) { + // Any other error + $error_msg = $ex->getMessage(); } - // We did not recognized the action -> return a 404 page - return $this->pageNotFound(); + $this->setupFormErrorContext("category creation", $error_msg, $creationForm, $ex); + + // At this point, the form has error, and should be redisplayed. + return $this->renderList(); } -} + + /** + * Load a category object for modification, and display the edit template. + * + * @return Symfony\Component\HttpFoundation\Response the response + */ + public function changeAction() { + + // Check current user authorization + if (null !== $response = $this->checkAuth("admin.categories.update")) return $response; + + // Load the category object + $category = CategoryQuery::create() + ->joinWithI18n($this->getCurrentEditionLocale()) + ->findOneById($this->getRequest()->get('category_id')); + + if ($category != null) { + + // Prepare the data that will hydrate the form + $data = array( + 'id' => $category->getId(), + 'locale' => $category->getLocale(), + 'title' => $category->getTitle(), + 'chapo' => $category->getChapo(), + 'description' => $category->getDescription(), + 'postscriptum' => $category->getPostscriptum(), + 'parent' => $category->getParent(), + 'visible' => $category->getVisible() ? true : false, + 'url' => $category->getUrl($this->getCurrentEditionLocale()) + // tbc !!! + ); + + // Setup the object form + $changeForm = new CategoryModificationForm($this->getRequest(), "form", $data); + + // Pass it to the parser + $this->getParserContext()->addForm($changeForm); + } + + // Render the edition template. + return $this->render('category-edit', $this->getTemplateArgs()); + } + + /** + * Save changes on a modified category object, and either go back to the category list, or stay on the edition page. + * + * @return Symfony\Component\HttpFoundation\Response the response + */ + public function saveChangeAction() { + + // Check current user authorization + if (null !== $response = $this->checkAuth("admin.categories.update")) return $response; + + $error_msg = false; + + // Create the form from the request + $changeForm = new CategoryModificationForm($this->getRequest()); + + // Get the category ID + $category_id = $this->getRequest()->get('category_id'); + + try { + + // Check the form against constraints violations + $form = $this->validateForm($changeForm, "POST"); + + // Get the form field values + $data = $form->getData(); + + $changeEvent = new CategoryUpdateEvent($data['id']); + + // Create and dispatch the change event + $changeEvent + ->setCategoryName($data['name']) + ->setLocale($data["locale"]) + ->setSymbol($data['symbol']) + ->setCode($data['code']) + ->setRate($data['rate']) + ; + + $this->dispatch(TheliaEvents::CATEGORY_UPDATE, $changeEvent); + + if (! $createEvent->hasCategory()) throw new \LogicException($this->getTranslator()->trans("No category was updated.")); + + // Log category modification + $changedObject = $changeEvent->getCategory(); + + $this->adminLogAppend(sprintf("Category %s (ID %s) modified", $changedObject->getTitle(), $changedObject->getId())); + + // If we have to stay on the same page, do not redirect to the succesUrl, + // just redirect to the edit page again. + if ($this->getRequest()->get('save_mode') == 'stay') { + $this->redirectToRoute( + "admin.categories.update", + array('category_id' => $category_id) + ); + } + + // Redirect to the success URL + $this->redirect($changeForm->getSuccessUrl()); + } + catch (FormValidationException $ex) { + // Form cannot be validated + $error_msg = $this->createStandardFormValidationErrorMessage($ex); + } + catch (\Exception $ex) { + // Any other error + $error_msg = $ex->getMessage(); + } + + $this->setupFormErrorContext("category modification", $error_msg, $changeForm, $ex); + + // At this point, the form has errors, and should be redisplayed. + return $this->render('category-edit', array('category_id' => $category_id)); + } + + /** + * Online status toggle category + */ + public function setToggleVisibilityAction() { + // Check current user authorization + if (null !== $response = $this->checkAuth("admin.categories.update")) return $response; + + $changeEvent = new CategoryUpdateEvent($this->getRequest()->get('category_id', 0)); + + // Create and dispatch the change event + $changeEvent->setIsDefault(true); + + try { + $this->dispatch(TheliaEvents::CATEGORY_SET_DEFAULT, $changeEvent); + } + catch (\Exception $ex) { + // Any error + return $this->errorPage($ex); + } + + $this->redirectToRoute('admin.categories.default'); + } + + /** + * Update categoryposition + */ + public function updatePositionAction() { + // Check current user authorization + if (null !== $response = $this->checkAuth("admin.categories.update")) return $response; + + try { + $mode = $this->getRequest()->get('mode', null); + + if ($mode == 'up') + $mode = CategoryUpdatePositionEvent::POSITION_UP; + else if ($mode == 'down') + $mode = CategoryUpdatePositionEvent::POSITION_DOWN; + else + $mode = CategoryUpdatePositionEvent::POSITION_ABSOLUTE; + + $position = $this->getRequest()->get('position', null); + + $event = new CategoryUpdatePositionEvent( + $this->getRequest()->get('category_id', null), + $mode, + $this->getRequest()->get('position', null) + ); + + $this->dispatch(TheliaEvents::CATEGORY_UPDATE_POSITION, $event); + } + catch (\Exception $ex) { + // Any error + return $this->errorPage($ex); + } + + $this->redirectToRoute('admin.categories.default'); + } + + /** + * Delete a category object + * + * @return Symfony\Component\HttpFoundation\Response the response + */ + public function deleteAction() { + + // Check current user authorization + if (null !== $response = $this->checkAuth("admin.categories.delete")) return $response; + + // Get the category id, and dispatch the deleted request + $event = new CategoryDeleteEvent($this->getRequest()->get('category_id')); + + $this->dispatch(TheliaEvents::CATEGORY_DELETE, $event); + + if ($event->hasCategory()) + $this->adminLogAppend(sprintf("Category %s (ID %s) deleted", $event->getCategory()->getTitle(), $event->getCategory()->getId())); + + $this->redirectToRoute('admin.categories.default'); + } +} \ No newline at end of file diff --git a/core/lib/Thelia/Controller/Admin/ConfigController.php b/core/lib/Thelia/Controller/Admin/ConfigController.php index b84368c2f..6d1a04b05 100644 --- a/core/lib/Thelia/Controller/Admin/ConfigController.php +++ b/core/lib/Thelia/Controller/Admin/ConfigController.php @@ -108,6 +108,8 @@ class ConfigController extends BaseAdminController $this->dispatch(TheliaEvents::CONFIG_CREATE, $createEvent); + if (! $createEvent->hasConfig()) throw new \LogicException($this->getTranslator()->trans("No variable was created.")); + $createdObject = $createEvent->getConfig(); // Log config creation @@ -121,26 +123,14 @@ class ConfigController extends BaseAdminController } catch (FormValidationException $ex) { // Form cannot be validated - $message = sprintf("Please check your input: %s", $ex->getMessage()); + $message = $this->createStandardFormValidationErrorMessage($ex); } catch (\Exception $ex) { // Any other error - $message = sprintf("Sorry, an error occured: %s", $ex->getMessage()); + $message = $ex->getMessage(); } - if ($message !== false) { - // An error has been detected: log it - Tlog::getInstance()->error(sprintf("Error during variable creation process : %s. Exception was %s", $message, $ex->getMessage())); - - // Mark the form as errored - $creationForm->setErrorMessage($message); - - // Pass it to the parser, along with the error message - $this->getParserContext() - ->addForm($creationForm) - ->setGeneralError($message) - ; - } + $this->setupFormErrorContext("variable creation", $message, $creationForm, $ex); // At this point, the form has error, and should be redisplayed. return $this->renderList(); @@ -231,6 +221,8 @@ class ConfigController extends BaseAdminController $this->dispatch(TheliaEvents::CONFIG_UPDATE, $changeEvent); + if (! $changeEvent->hasConfig()) throw new \LogicException($this->getTranslator()->trans("No variable was updated.")); + // Log config modification $changedObject = $changeEvent->getConfig(); @@ -250,27 +242,15 @@ class ConfigController extends BaseAdminController $this->redirect($changeForm->getSuccessUrl()); } catch (FormValidationException $ex) { - // Invalid data entered - $message = sprintf("Please check your input: %s", $ex->getMessage()); + // Form cannot be validated + $message = $this->createStandardFormValidationErrorMessage($ex); } catch (\Exception $ex) { // Any other error - $message = sprintf("Sorry, an error occured: %s", $ex->getMessage()); + $message = $ex->getMessage(); } - if ($message !== false) { - // Log error message - Tlog::getInstance()->error(sprintf("Error during variable modification process : %s. Exception was %s", $message, $ex->getMessage())); - - // Mark the form as errored - $changeForm->setErrorMessage($message); - - // Pas the form and the error to the parser - $this->getParserContext() - ->addForm($changeForm) - ->setGeneralError($message) - ; - } + $this->setupFormErrorContext("variable edition", $message, $changeForm, $ex); // At this point, the form has errors, and should be redisplayed. return $this->render('variable-edit', array('variable_id' => $variable_id)); @@ -314,6 +294,9 @@ class ConfigController extends BaseAdminController $this->dispatch(TheliaEvents::CONFIG_DELETE, $event); + if ($event->hasConfig()) + $this->adminLogAppend(sprintf("Variable %s (ID %s) modified", $event->getConfig()->getName(), $event->getConfig()->getId())); + $this->redirectToRoute('admin.configuration.variables.default'); } } \ No newline at end of file diff --git a/core/lib/Thelia/Controller/Admin/CouponController.php b/core/lib/Thelia/Controller/Admin/CouponController.php new file mode 100755 index 000000000..d2368a573 --- /dev/null +++ b/core/lib/Thelia/Controller/Admin/CouponController.php @@ -0,0 +1,581 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Controller\Admin; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\Routing\Router; +use Thelia\Constraint\ConstraintFactory; +use Thelia\Constraint\ConstraintFactoryTest; +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; +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\CouponManager; +use Thelia\Coupon\CouponRuleCollection; +use Thelia\Coupon\Type\CouponInterface; +use Thelia\Form\CouponCreationForm; +use Thelia\Form\Exception\FormValidationException; +use Thelia\Log\Tlog; +use Thelia\Model\Coupon; +use Thelia\Model\CouponQuery; +use Thelia\Model\Lang; +use Thelia\Tools\I18n; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Control View and Action (Model) via Events + * + * @package Coupon + * @author Guillaume MOREL + * + */ +class CouponController extends BaseAdminController +{ + /** + * Manage Coupons list display + * + * @return \Symfony\Component\HttpFoundation\Response + */ + public function browseAction() + { + $this->checkAuth('ADMIN', 'admin.coupon.view'); + + return $this->render('coupon-list'); + } + + /** + * Manage Coupons creation display + * + * @return \Symfony\Component\HttpFoundation\Response + */ + public function createAction() + { + // Check current user authorization + $response = $this->checkAuth('admin.coupon.create'); + if ($response !== null) { + return $response; + } + + // Parameters given to the template + $args = array(); + + $i18n = new I18n(); + /** @var Lang $lang */ + $lang = $this->getSession()->get('lang'); + $eventToDispatch = TheliaEvents::COUPON_CREATE; + + if ($this->getRequest()->isMethod('POST')) { + $this->validateCreateOrUpdateForm( + $i18n, + $lang, + $eventToDispatch, + 'created', + 'creation' + ); + } else { + // If no input for expirationDate, now + 2 months + $defaultDate = new \DateTime(); + $args['defaultDate'] = $defaultDate->modify('+2 month') + ->format($lang->getDateFormat()); + } + + $args['formAction'] = 'admin/coupon/create'; + + return $this->render( + 'coupon-create', + $args + ); + } + + /** + * Manage Coupons edition display + * + * @param int $couponId Coupon id + * + * @return \Symfony\Component\HttpFoundation\Response + */ + public function updateAction($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()->getLang(); + $eventToDispatch = TheliaEvents::COUPON_UPDATE; + + 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(), + ); + + $args['rulesObject'] = array(); + + /** @var ConstraintFactory $constraintFactory */ + $constraintFactory = $this->container->get('thelia.constraint.factory'); + $rules = $constraintFactory->unserializeCouponRuleCollection( + $coupon->getSerializedRules() + ); + + /** @var CouponRuleInterface $rule */ + foreach ($rules 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); + + // Pass it to the parser + $this->getParserContext()->addForm($changeForm); + } + + $args['availableCoupons'] = $this->getAvailableCoupons(); + $args['availableRules'] = $this->getAvailableRules(); + $args['urlAjaxGetRuleInput'] = $this->getRouteFromRouter( + 'router.admin', + 'admin.coupon.rule.input', + array('ruleId' => 'ruleId'), + Router::ABSOLUTE_URL + ); + + $args['formAction'] = 'admin/coupon/update/' . $couponId; + + return $this->render( + 'coupon-update', + $args + ); + } + + + /** + * 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 + * + * @param int $couponId Coupon Id + * + * @return \Symfony\Component\HttpFoundation\Response + */ + public function readAction($couponId) + { + $this->checkAuth('ADMIN', 'admin.coupon.read'); + + // Database request repeated in the loop but cached + $search = CouponQuery::create(); + $coupon = $search->findOneById($couponId); + + if ($coupon === null) { + return $this->pageNotFound(); + } + + return $this->render('coupon-read', array('couponId' => $couponId)); + } + + /** + * Manage Coupons read display + * + * @param string $ruleId Rule service id + * + * @return \Symfony\Component\HttpFoundation\Response + */ + public function getRuleInputAction($ruleId) + { + $this->checkAuth('ADMIN', 'admin.coupon.read'); + + if (!$this->getRequest()->isXmlHttpRequest()) { + $this->redirect( + $this->getRoute( + 'admin', + array(), + Router::ABSOLUTE_URL + ) + ); + } + + /** @var ConstraintFactory $constraintFactory */ + $constraintFactory = $this->container->get('thelia.constraint.factory'); + $inputs = $constraintFactory->getInputs($ruleId); + + if ($inputs === null) { + return $this->pageNotFound(); + } + + return $this->render( + 'coupon/rule-input-ajax', + array( + 'ruleId' => $ruleId, + 'inputs' => $inputs + ) + ); + } + + /** + * Build a Coupon from its form + * + * @param array $data Form data + * + * @return Coupon + */ + protected function buildCouponFromForm(array $data) + { + $couponBeingCreated = new Coupon(); + $couponBeingCreated->setCode($data['code']); + $couponBeingCreated->setType($data['type']); + $couponBeingCreated->setTitle($data['title']); + $couponBeingCreated->setShortDescription($data['shortDescription']); + $couponBeingCreated->setDescription($data['description']); + $couponBeingCreated->setAmount($data['amount']); + $couponBeingCreated->setIsEnabled($data['isEnabled']); + $couponBeingCreated->setExpirationDate($data['expirationDate']); + $couponBeingCreated->setSerializedRules( + new CouponRuleCollection( + array() + ) + ); + $couponBeingCreated->setIsCumulative($data['isCumulative']); + $couponBeingCreated->setIsRemovingPostage( + $data['isRemovingPostage'] + ); + $couponBeingCreated->setMaxUsage($data['maxUsage']); + $couponBeingCreated->setIsAvailableOnSpecialOffers( + $data['isAvailableOnSpecialOffers'] + ); + + return $couponBeingCreated; + } + + /** + * Log error message + * + * @param string $action Creation|Update|Delete + * @param string $message Message to log + * @param \Exception $e Exception to log + * + * @return $this + */ + protected function logError($action, $message, $e) + { + Tlog::getInstance()->error( + sprintf( + 'Error during Coupon ' . $action . ' process : %s. Exception was %s', + $message, + $e->getMessage() + ) + ); + + return $this; + } + + /** + * Validate the CreateOrUpdate form + * + * @param string $i18n Local code (fr_FR) + * @param Lang $lang Local variables container + * @param string $eventToDispatch Event which will activate actions + * @param string $log created|edited + * @param string $action creation|edition + * + * @return $this + */ + protected function validateCreateOrUpdateForm($i18n, $lang, $eventToDispatch, $log, $action) + { + // Create the form from the request + $creationForm = new CouponCreationForm($this->getRequest()); + + $message = false; + try { + // Check the form against constraints violations + $form = $this->validateForm($creationForm, 'POST'); + + // Get the form field values + $data = $form->getData(); + $couponEvent = new CouponCreateOrUpdateEvent( + $data['code'], + $data['title'], + $data['amount'], + $data['effect'], + $data['shortDescription'], + $data['description'], + $data['isEnabled'], + $i18n->getDateTimeFromForm($lang, $data['expirationDate']), + $data['isAvailableOnSpecialOffers'], + $data['isCumulative'], + $data['isRemovingPostage'], + $data['maxUsage'], + new CouponRuleCollection(array()), + $data['locale'] + ); + + // Dispatch Event to the Action + $this->dispatch( + $eventToDispatch, + $couponEvent + ); + + $this->adminLogAppend( + sprintf( + 'Coupon %s (ID ) ' . $log, + $couponEvent->getTitle(), + $couponEvent->getCoupon()->getId() + ) + ); + + $this->redirect( + str_replace( + '{id}', + $couponEvent->getCoupon()->getId(), + $creationForm->getSuccessUrl() + ) + ); + + } catch (FormValidationException $e) { + // Invalid data entered + $message = 'Please check your input:'; + $this->logError($action, $message, $e); + + } catch (\Exception $e) { + // Any other error + $message = 'Sorry, an error occurred:'; + $this->logError($action, $message, $e); + } + + if ($message !== false) { + // Mark the form as with error + $creationForm->setErrorMessage($message); + + // Send the form and the error to the parser + $this->getParserContext() + ->addForm($creationForm) + ->setGeneralError($message); + } + + return $this; + } + + /** + * Get all available rules + * + * @return array + */ + protected function getAvailableRules() + { + /** @var CouponManager $couponManager */ + $couponManager = $this->container->get('thelia.coupon.manager'); + $availableRules = $couponManager->getAvailableRules(); + $cleanedRules = array(); + /** @var CouponRuleInterface $availableRule */ + foreach ($availableRules as $availableRule) { + $rule = array(); + $rule['serviceId'] = $availableRule->getServiceId(); + $rule['name'] = $availableRule->getName(); + $rule['toolTip'] = $availableRule->getToolTip(); + $cleanedRules[] = $rule; + } + + return $cleanedRules; + } + + /** + * Get all available coupons + * + * @return array + */ + protected function getAvailableCoupons() + { + /** @var CouponManager $couponManager */ + $couponManager = $this->container->get('thelia.coupon.manager'); + $availableCoupons = $couponManager->getAvailableCoupons(); + $cleanedRules = array(); + /** @var CouponInterface $availableCoupon */ + foreach ($availableCoupons as $availableCoupon) { + $rule = array(); + $rule['serviceId'] = $availableCoupon->getServiceId(); + $rule['name'] = $availableCoupon->getName(); + $rule['toolTip'] = $availableCoupon->getToolTip(); + $cleanedRules[] = $rule; + } + + return $cleanedRules; + } + +// /** +// * Validation Rule creation +// * +// * @param string $type Rule class type +// * @param string $operator Rule operator (<, >, =, etc) +// * @param array $values Rules values +// * +// * @return bool +// */ +// protected function validateRulesCreation($type, $operator, $values) +// { +// /** @var CouponAdapterInterface $adapter */ +// $adapter = $this->container->get('thelia.adapter'); +// $validator = new PriceParam() +// try { +// $rule = new AvailableForTotalAmount($adapter, $validators); +// $rule = new $type($adapter, $validators); +// } catch (\Exception $e) { +// return false; +// } +// } + + + +} diff --git a/core/lib/Thelia/Controller/Admin/CurrencyController.php b/core/lib/Thelia/Controller/Admin/CurrencyController.php index 56acfb89d..c6f5afdc3 100644 --- a/core/lib/Thelia/Controller/Admin/CurrencyController.php +++ b/core/lib/Thelia/Controller/Admin/CurrencyController.php @@ -108,10 +108,12 @@ class CurrencyController extends BaseAdminController $this->dispatch(TheliaEvents::CURRENCY_CREATE, $createEvent); + if (! $createEvent->hasCurrency()) throw new \LogicException($this->getTranslator()->trans("No currency was created.")); + $createdObject = $createEvent->getCurrency(); // Log currency creation - $this->adminLogAppend(sprintf("Variable %s (ID %s) created", $createdObject->getName(), $createdObject->getId())); + $this->adminLogAppend(sprintf("Currency %s (ID %s) created", $createdObject->getName(), $createdObject->getId())); // Substitute _ID_ in the URL with the ID of the created object $successUrl = str_replace('_ID_', $createdObject->getId(), $creationForm->getSuccessUrl()); @@ -121,26 +123,14 @@ class CurrencyController extends BaseAdminController } catch (FormValidationException $ex) { // Form cannot be validated - $error_msg = sprintf("Please check your input: %s", $ex->getMessage()); + $error_msg = $this->createStandardFormValidationErrorMessage($ex); } catch (\Exception $ex) { // Any other error - $error_msg = $ex; + $error_msg = $ex->getMessage(); } - if ($error_msg !== false) { - // An error has been detected: log it - Tlog::getInstance()->error(sprintf("Error during currency creation process : %s. Exception was %s", $error_msg, $ex->getMessage())); - - // Mark the form as errored - $creationForm->setErrorMessage($error_msg); - - // Pass it to the parser, along with the error currency - $this->getParserContext() - ->addForm($creationForm) - ->setGeneralError($error_msg) - ; - } + $this->setupFormErrorContext("currency creation", $error_msg, $creationForm, $ex); // At this point, the form has error, and should be redisplayed. return $this->renderList(); @@ -223,10 +213,12 @@ class CurrencyController extends BaseAdminController $this->dispatch(TheliaEvents::CURRENCY_UPDATE, $changeEvent); + if (! $changeEvent->hasCurrency()) throw new \LogicException($this->getTranslator()->trans("No currency was updated.")); + // Log currency modification $changedObject = $changeEvent->getCurrency(); - $this->adminLogAppend(sprintf("Variable %s (ID %s) modified", $changedObject->getName(), $changedObject->getId())); + $this->adminLogAppend(sprintf("Currency %s (ID %s) modified", $changedObject->getName(), $changedObject->getId())); // If we have to stay on the same page, do not redirect to the succesUrl, // just redirect to the edit page again. @@ -241,27 +233,15 @@ class CurrencyController extends BaseAdminController $this->redirect($changeForm->getSuccessUrl()); } catch (FormValidationException $ex) { - // Invalid data entered - $error_msg = sprintf("Please check your input: %s", $ex->getMessage()); + // Form cannot be validated + $error_msg = $this->createStandardFormValidationErrorMessage($ex); } catch (\Exception $ex) { // Any other error - $error_msg = $ex; + $error_msg = $ex->getMessage(); } - if ($error_msg !== false) { - // Log error currency - Tlog::getInstance()->error(sprintf("Error during currency modification process : %s. Exception was %s", $error_msg, $ex->getMessage())); - - // Mark the form as errored - $changeForm->setErrorMessage($error_msg); - - // Pas the form and the error to the parser - $this->getParserContext() - ->addForm($changeForm) - ->setGeneralError($error_msg) - ; - } + $this->setupFormErrorContext("currency modification", $error_msg, $changeForm, $ex); // At this point, the form has errors, and should be redisplayed. return $this->render('currency-edit', array('currency_id' => $currency_id)); @@ -359,6 +339,9 @@ class CurrencyController extends BaseAdminController $this->dispatch(TheliaEvents::CURRENCY_DELETE, $event); + if ($event->hasCurrency()) + $this->adminLogAppend(sprintf("Currency %s (ID %s) modified", $event->getCurrency()->getName(), $event->getCurrency()->getId())); + $this->redirectToRoute('admin.configuration.currencies.default'); } } \ No newline at end of file diff --git a/core/lib/Thelia/Controller/Admin/CustomerController.php b/core/lib/Thelia/Controller/Admin/CustomerController.php new file mode 100644 index 000000000..04c8842cd --- /dev/null +++ b/core/lib/Thelia/Controller/Admin/CustomerController.php @@ -0,0 +1,40 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Controller\Admin; + + +/** + * Class CustomerController + * @package Thelia\Controller\Admin + * @author Manuel Raynaud + */ +class CustomerController extends BaseAdminController +{ + public function indexAction() + { + if (null !== $response = $this->checkAuth("admin.customers.view")) return $response; + + return $this->render("customers", array("display_customer" => 20)); + } +} \ No newline at end of file diff --git a/core/lib/Thelia/Controller/Admin/MessageController.php b/core/lib/Thelia/Controller/Admin/MessageController.php index c024a5d34..00fcb17bd 100644 --- a/core/lib/Thelia/Controller/Admin/MessageController.php +++ b/core/lib/Thelia/Controller/Admin/MessageController.php @@ -42,6 +42,15 @@ use Thelia\Form\MessageCreationForm; */ class MessageController extends BaseAdminController { + /** + * Render the messages list + * + * @return Symfony\Component\HttpFoundation\Response the response + */ + protected function renderList() { + return $this->render('messages'); + } + /** * The default action is displaying the messages list. * @@ -51,7 +60,7 @@ class MessageController extends BaseAdminController if (null !== $response = $this->checkAuth("admin.configuration.messages.view")) return $response; - return $this->render('messages'); + return $this->renderList(); } /** @@ -66,7 +75,7 @@ class MessageController extends BaseAdminController $message = false; - // Create the Creation Form + // Create the creation Form $creationForm = new MessageCreationForm($this->getRequest()); try { @@ -87,10 +96,11 @@ class MessageController extends BaseAdminController $this->dispatch(TheliaEvents::MESSAGE_CREATE, $createEvent); + if (! $createEvent->hasMessage()) throw new \LogicException($this->getTranslator()->trans("No message was created.")); + $createdObject = $createEvent->getMessage(); - // Log message creation - $this->adminLogAppend(sprintf("Variable %s (ID %s) created", $createdObject->getName(), $createdObject->getId())); + $this->adminLogAppend(sprintf("Message %s (ID %s) created", $createdObject->getName(), $createdObject->getId())); // Substitute _ID_ in the URL with the ID of the created object $successUrl = str_replace('_ID_', $createdObject->getId(), $creationForm->getSuccessUrl()); @@ -100,26 +110,14 @@ class MessageController extends BaseAdminController } catch (FormValidationException $ex) { // Form cannot be validated - $message = sprintf("Please check your input: %s", $ex->getMessage()); + $message = $this->createStandardFormValidationErrorMessage($ex); } catch (\Exception $ex) { // Any other error - $message = sprintf("Sorry, an error occured: %s", $ex->getMessage()); + $message = $ex->getMessage(); } - if ($message !== false) { - // An error has been detected: log it - Tlog::getInstance()->error(sprintf("Error during message creation process : %s. Exception was %s", $message, $ex->getMessage())); - - // Mark the form as errored - $creationForm->setErrorMessage($message); - - // Pass it to the parser, along with the error message - $this->getParserContext() - ->addForm($creationForm) - ->setGeneralError($message) - ; - } + $this->setupFormErrorContext("message modification", $message, $creationForm, $ex); // At this point, the form has error, and should be redisplayed. return $this->render('messages'); @@ -206,7 +204,8 @@ class MessageController extends BaseAdminController $this->dispatch(TheliaEvents::MESSAGE_UPDATE, $changeEvent); - // Log message modification + if (! $changeEvent->hasMessage()) throw new \LogicException($this->getTranslator()->trans("No message was updated.")); + $changedObject = $changeEvent->getMessage(); $this->adminLogAppend(sprintf("Variable %s (ID %s) modified", $changedObject->getName(), $changedObject->getId())); @@ -224,27 +223,15 @@ class MessageController extends BaseAdminController $this->redirect($changeForm->getSuccessUrl()); } catch (FormValidationException $ex) { - // Invalid data entered - $message = sprintf("Please check your input: %s", $ex->getMessage()); + // Form cannot be validated + $message = $this->createStandardFormValidationErrorMessage($ex); } catch (\Exception $ex) { // Any other error - $message = sprintf("Sorry, an error occured: %s", $ex->getMessage()); + $message = $ex->getMessage(); } - if ($message !== false) { - // Log error message - Tlog::getInstance()->error(sprintf("Error during message modification process : %s. Exception was %s", $message, $ex->getMessage())); - - // Mark the form as errored - $changeForm->setErrorMessage($message); - - // Pas the form and the error to the parser - $this->getParserContext() - ->addForm($changeForm) - ->setGeneralError($message) - ; - } + $this->setupFormErrorContext("message modification", $message, $changeForm, $ex); // At this point, the form has errors, and should be redisplayed. return $this->render('message-edit', array('message_id' => $message_id)); @@ -265,6 +252,9 @@ class MessageController extends BaseAdminController $this->dispatch(TheliaEvents::MESSAGE_DELETE, $event); - $this->redirect(URL::getInstance()->adminViewUrl('messages')); + if ($event->hasMessage()) + $this->adminLogAppend(sprintf("Message %s (ID %s) modified", $event->getMessage()->getName(), $event->getMessage()->getId())); + + $this->redirectToRoute('admin.configuration.messages.default'); } } \ No newline at end of file diff --git a/core/lib/Thelia/Controller/Admin/SessionController.php b/core/lib/Thelia/Controller/Admin/SessionController.php index a377df208..d7385ad1b 100755 --- a/core/lib/Thelia/Controller/Admin/SessionController.php +++ b/core/lib/Thelia/Controller/Admin/SessionController.php @@ -73,32 +73,34 @@ class SessionController extends BaseAdminController // Redirect to the success URL return Redirect::exec($adminLoginForm->getSuccessUrl()); - } catch (ValidatorException $ex) { + + } + catch (FormValidationException $ex) { // Validation problem - $message = "Missing or invalid information. Please check your input."; - } catch (AuthenticationException $ex) { + $message = $this->createStandardFormValidationErrorMessage($ex); + } + catch (AuthenticationException $ex) { // Log authentication failure AdminLog::append(sprintf("Authentication failure for username '%s'", $authenticator->getUsername()), $request); - $message = "Login failed. Please check your username and password."; - } catch (\Exception $ex) { + $message = $this->getTranslator()->trans("Login failed. Please check your username and password."); + } + catch (\Exception $ex) { // Log authentication failure AdminLog::append(sprintf("Undefined error: %s", $ex->getMessage()), $request); - $message = "Unable to process your request. Please try again.".$ex->getMessage(); + $message = $this->getTranslator()->trans( + "Unable to process your request. Please try again (%err).", + array("%err" => $ex->getMessage()) + ); } - // Store error information in the form - $adminLoginForm->setError(true); - $adminLoginForm->setErrorMessage($message); - - // Store the form name in session (see Form Smarty plugin to find usage of this parameter) - $this->getParserContext()->addForm($adminLoginForm); + $this->setupFormErrorContext("Login process", $message, $adminLoginForm, $ex); // Display the login form again return $this->render("login"); } -} +} \ No newline at end of file diff --git a/core/lib/Thelia/Controller/BaseController.php b/core/lib/Thelia/Controller/BaseController.php index e5b098f02..5e992b258 100755 --- a/core/lib/Thelia/Controller/BaseController.php +++ b/core/lib/Thelia/Controller/BaseController.php @@ -25,6 +25,10 @@ namespace Thelia\Controller; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\DependencyInjection\ContainerAware; +use Symfony\Component\Routing\Exception\InvalidParameterException; +use Symfony\Component\Routing\Exception\MissingMandatoryParametersException; +use Symfony\Component\Routing\Exception\RouteNotFoundException; +use Symfony\Component\Routing\Router; use Thelia\Core\Security\SecurityContext; use Thelia\Tools\URL; use Thelia\Tools\Redirect; @@ -175,7 +179,14 @@ class BaseController extends ContainerAware return $form; } else { - throw new FormValidationException(sprintf("Missing or invalid data: %s", $this->getErrorMessages($form))); + $errorMessage = null; + if ($form->get("error_message")->getData() != null) { + $errorMessage = $form->get("error_message")->getData(); + } else { + $errorMessage = sprintf("Missing or invalid data: %s", $this->getErrorMessages($form)); + } + + throw new FormValidationException($errorMessage); } } else { @@ -216,20 +227,27 @@ class BaseController extends ContainerAware /** * Get a route path from the route id. * - * @param $routerName - * @param $routeId + * @param string $routerName Router name + * @param string $routeId The name of the route + * @param mixed $parameters An array of parameters + * @param Boolean|string $referenceType The type of reference to be generated (one of the constants) * - * @return mixed - * @throws InvalidArgumentException + * @throws RouteNotFoundException If the named route doesn't exist + * @throws MissingMandatoryParametersException When some parameters are missing that are mandatory for the route + * @throws InvalidParameterException When a parameter value for a placeholder is not correct because + * it does not match the requirement + * @throws \InvalidArgumentException When the router doesn't exist + * @return string The generated URL */ - protected function getRouteFromRouter($routerName, $routeId) { - $route = $this->container->get($routerName)->getRouteCollection()->get($routeId); + protected function getRouteFromRouter($routerName, $routeId, $parameters = array(), $referenceType = Router::ABSOLUTE_PATH) { + /** @var Router $router */ + $router = $this->container->get($routerName); - if ($route == null) { - throw new \InvalidArgumentException(sprintf("Route ID '%s' does not exists.", $routeId)); + if ($router == null) { + throw new \InvalidArgumentException(sprintf("Router '%s' does not exists.", $routerName)); } - return $route->getPath(); + return $router->generate($routeId, $parameters, $referenceType); } /** diff --git a/core/lib/Thelia/Controller/Front/BaseFrontController.php b/core/lib/Thelia/Controller/Front/BaseFrontController.php index e92387a83..ed6774c8b 100755 --- a/core/lib/Thelia/Controller/Front/BaseFrontController.php +++ b/core/lib/Thelia/Controller/Front/BaseFrontController.php @@ -22,6 +22,7 @@ /*************************************************************************************/ namespace Thelia\Controller\Front; +use Symfony\Component\Routing\Router; use Thelia\Controller\BaseController; use Thelia\Tools\URL; @@ -34,8 +35,8 @@ class BaseFrontController extends BaseController * * @see \Thelia\Controller\BaseController::getRouteFromRouter() */ - protected function getRoute($routeId) { - return $this->getRouteFromRouter('router.front', $routeId); + protected function getRoute($routeId, $parameters = array(), $referenceType = Router::ABSOLUTE_PATH) { + return $this->getRouteFromRouter('router.front', $routeId, $parameters, $referenceType); } /** @@ -44,7 +45,7 @@ class BaseFrontController extends BaseController * @param unknown $routeId the route ID, as found in Config/Resources/routing/admin.xml * @param unknown $urlParameters the URL parametrs, as a var/value pair array */ - public function redirectToRoute($routeId, $urlParameters = array()) { - $this->redirect(URL::getInstance()->absoluteUrl($this->getRoute($routeId), $urlParameters)); + public function redirectToRoute($routeId, $urlParameters = array(), $referenceType = Router::ABSOLUTE_PATH) { + $this->redirect(URL::getInstance()->absoluteUrl($this->getRoute($routeId, array(), $referenceType), $urlParameters)); } } diff --git a/core/lib/Thelia/Controller/Front/CustomerController.php b/core/lib/Thelia/Controller/Front/CustomerController.php index d753510a6..58d578955 100755 --- a/core/lib/Thelia/Controller/Front/CustomerController.php +++ b/core/lib/Thelia/Controller/Front/CustomerController.php @@ -39,6 +39,7 @@ use Thelia\Core\Factory\ActionEventFactory; use Thelia\Tools\URL; use Thelia\Log\Tlog; use Thelia\Core\Security\Exception\WrongPasswordException; +use Symfony\Component\Routing\Router; /** * Class CustomerController @@ -167,16 +168,25 @@ class CustomerController extends BaseFrontController } catch (FormValidationException $e) { + + if ($request->request->has("account")) { + $account = $request->request->get("account"); + $form = $customerLoginForm->getForm(); + if($account == 0 && $form->get("email")->getData() !== null) { + $this->redirectToRoute("customer.create.view", array("email" => $form->get("email")->getData())); + } + } + $message = sprintf("Please check your input: %s", $e->getMessage()); } catch(UsernameNotFoundException $e) { - $message = "This customer email was not found."; + $message = "Wrong email or password. Please try again"; } catch (WrongPasswordException $e) { - $message = "Wrong password. Please try again."; + $message = "Wrong email or password. Please try again"; } catch(AuthenticationException $e) { - $message = "Sorry, we failed to authentify you. Please try again."; + $message = "Wrong email or password. Please try again"; } catch (\Exception $e) { $message = sprintf("Sorry, an error occured: %s", $e->getMessage()); diff --git a/core/lib/Thelia/Controller/Front/DeliveryController.php b/core/lib/Thelia/Controller/Front/DeliveryController.php new file mode 100644 index 000000000..ef84be6ab --- /dev/null +++ b/core/lib/Thelia/Controller/Front/DeliveryController.php @@ -0,0 +1,56 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Controller\Front; +use Thelia\Model\ModuleQuery; +use Thelia\Tools\URL; + + +/** + * Class DeliveryController + * @package Thelia\Controller\Front + * @author Manuel Raynaud + */ +class DeliveryController extends BaseFrontController +{ + public function select($delivery_id) + { + if ($this->getSecurityContext()->hasCustomerUser() === false) { + $this->redirect(URL::getInstance()->getIndexPage()); + } + + $request = $this->getRequest(); + + $deliveryModule = ModuleQuery::create() + ->filterById($delivery_id) + ->filterByActivate(1) + ->findOne() + ; + + if ($deliveryModule) { + $request->getSession()->setDelivery($delivery_id); + } else { + $this->pageNotFound(); + } + } +} \ No newline at end of file diff --git a/core/lib/Thelia/Core/Bundle/TheliaBundle.php b/core/lib/Thelia/Core/Bundle/TheliaBundle.php index 9c8b8fedf..a9704b350 100755 --- a/core/lib/Thelia/Core/Bundle/TheliaBundle.php +++ b/core/lib/Thelia/Core/Bundle/TheliaBundle.php @@ -26,9 +26,11 @@ use Symfony\Component\HttpKernel\Bundle\Bundle; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Scope; +use Thelia\Core\DependencyInjection\Compiler\RegisterCouponPass; use Thelia\Core\DependencyInjection\Compiler\RegisterListenersPass; use Thelia\Core\DependencyInjection\Compiler\RegisterParserPluginPass; use Thelia\Core\DependencyInjection\Compiler\RegisterRouterPass; +use Thelia\Core\DependencyInjection\Compiler\RegisterRulePass; /** * First Bundle use in Thelia @@ -60,6 +62,8 @@ class TheliaBundle extends Bundle ->addCompilerPass(new RegisterListenersPass()) ->addCompilerPass(new RegisterParserPluginPass()) ->addCompilerPass(new RegisterRouterPass()) + ->addCompilerPass(new RegisterCouponPass()) + ->addCompilerPass(new RegisterRulePass()) ; } diff --git a/core/lib/Thelia/Core/DependencyInjection/Compiler/RegisterCouponPass.php b/core/lib/Thelia/Core/DependencyInjection/Compiler/RegisterCouponPass.php new file mode 100755 index 000000000..cf6f32842 --- /dev/null +++ b/core/lib/Thelia/Core/DependencyInjection/Compiler/RegisterCouponPass.php @@ -0,0 +1,69 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Core\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; + +/** + * Created by JetBrains PhpStorm. + * Date: 9/05/13 + * Time: 3:24 PM + * + * Class RegisterListenersPass + * Source code come from Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\RegisterKernelListenersPass class + * + * @package Thelia\Core\DependencyInjection\Compiler + * @author Guillaume MOREL + * + */ +class RegisterCouponPass implements CompilerPassInterface +{ + /** + * You can modify the container here before it is dumped to PHP code. + * + * @param ContainerBuilder $container Container + * + * @api + */ + public function process(ContainerBuilder $container) + { + if (!$container->hasDefinition('thelia.coupon.manager')) { + return; + } + + $couponManager = $container->getDefinition('thelia.coupon.manager'); + $services = $container->findTaggedServiceIds("thelia.coupon.addCoupon"); + + foreach ($services as $id => $rule) { + $couponManager->addMethodCall( + 'addAvailableCoupon', + array( + new Reference($id) + ) + ); + } + } +} diff --git a/core/lib/Thelia/Core/DependencyInjection/Compiler/RegisterRulePass.php b/core/lib/Thelia/Core/DependencyInjection/Compiler/RegisterRulePass.php new file mode 100755 index 000000000..dcc54cf8e --- /dev/null +++ b/core/lib/Thelia/Core/DependencyInjection/Compiler/RegisterRulePass.php @@ -0,0 +1,69 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Core\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; + +/** + * Created by JetBrains PhpStorm. + * Date: 9/05/13 + * Time: 3:24 PM + * + * Class RegisterListenersPass + * Source code come from Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\RegisterKernelListenersPass class + * + * @package Thelia\Core\DependencyInjection\Compiler + * @author Guillaume MOREL + * + */ +class RegisterRulePass 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.addRule"); + + foreach ($services as $id => $rule) { + $couponManager->addMethodCall( + 'addAvailableRule', + array( + new Reference($id) + ) + ); + } + } +} diff --git a/core/lib/Thelia/Core/Event/BaseToggleVisibilityEvent.php b/core/lib/Thelia/Core/Event/BaseToggleVisibilityEvent.php new file mode 100644 index 000000000..2dbd54374 --- /dev/null +++ b/core/lib/Thelia/Core/Event/BaseToggleVisibilityEvent.php @@ -0,0 +1,48 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Core\Event; + + +class BaseToggleVisibilityEvent extends ActionEvent +{ + protected $object_id; + + protected $object; + + public function __construct($object_id) + { + $this->object_id = $object_id; + } + + public function getObjectId() + { + return $this->object_id; + } + + public function setObjectId($object_id) + { + $this->object_id = $object_id; + return $this; + } +} \ No newline at end of file diff --git a/core/lib/Thelia/Core/Event/CategoryCreateEvent.php b/core/lib/Thelia/Core/Event/CategoryCreateEvent.php index f4d5a45ee..0a6b79269 100644 --- a/core/lib/Thelia/Core/Event/CategoryCreateEvent.php +++ b/core/lib/Thelia/Core/Event/CategoryCreateEvent.php @@ -25,12 +25,11 @@ namespace Thelia\Core\Event; use Thelia\Model\Category; -class CategoryCreateEvent extends ActionEvent +class CategoryCreateEvent extends CategoryEvent { protected $title; protected $parent; protected $locale; - protected $created_category; public function __construct($title, $parent, $locale) { @@ -47,6 +46,7 @@ class CategoryCreateEvent extends ActionEvent public function setTitle($title) { $this->title = $title; + return $this; } public function getParent() @@ -57,6 +57,7 @@ class CategoryCreateEvent extends ActionEvent public function setParent($parent) { $this->parent = $parent; + return $this; } public function getLocale() @@ -67,15 +68,6 @@ class CategoryCreateEvent extends ActionEvent public function setLocale($locale) { $this->locale = $locale; + return $this; } - - public function getCreatedCategory() - { - return $this->created_category; - } - - public function setCreatedCategory(Category $created_category) - { - $this->created_category = $created_category; - } -} +} \ No newline at end of file diff --git a/core/lib/Thelia/Core/Event/CategoryDeleteEvent.php b/core/lib/Thelia/Core/Event/CategoryDeleteEvent.php index 3e863be8e..ad686563d 100644 --- a/core/lib/Thelia/Core/Event/CategoryDeleteEvent.php +++ b/core/lib/Thelia/Core/Event/CategoryDeleteEvent.php @@ -22,13 +22,11 @@ /*************************************************************************************/ namespace Thelia\Core\Event; + use Thelia\Model\Category; -class CategoryDeleteEvent extends ActionEvent +class CategoryDeleteEvent extends CategoryEvent { - protected $category_id; - protected $deleted_category; - public function __construct($category_id) { $this->category_id = $category_id; @@ -42,15 +40,6 @@ class CategoryDeleteEvent extends ActionEvent public function setCategoryId($category_id) { $this->category_id = $category_id; + return $this; } - - public function getDeletedCategory() - { - return $this->deleted_category; - } - - public function setDeletedCategory(Category $deleted_category) - { - $this->deleted_category = $deleted_category; - } -} +} \ No newline at end of file diff --git a/core/lib/Thelia/Core/Event/CategoryEvent.php b/core/lib/Thelia/Core/Event/CategoryEvent.php index c29d681d8..ac04f15c9 100644 --- a/core/lib/Thelia/Core/Event/CategoryEvent.php +++ b/core/lib/Thelia/Core/Event/CategoryEvent.php @@ -28,20 +28,26 @@ use Thelia\Core\Event\ActionEvent; class CategoryEvent extends ActionEvent { - public $category; + public $category = null; - public function __construct(Category $category) + public function __construct(Category $category = null) { $this->category = $category; } - /** - * @return \Thelia\Model\Category - */ + public function hasCategory() { + return ! is_null($this->category); + } + public function getCategory() { return $this->category; } + public function setCategory(Category $category) + { + $this->category = $category; + return $this; + } } diff --git a/core/lib/Thelia/Core/Event/CategoryToggleVisibilityEvent.php b/core/lib/Thelia/Core/Event/CategoryToggleVisibilityEvent.php index ef921a0de..103c5207e 100644 --- a/core/lib/Thelia/Core/Event/CategoryToggleVisibilityEvent.php +++ b/core/lib/Thelia/Core/Event/CategoryToggleVisibilityEvent.php @@ -22,35 +22,7 @@ /*************************************************************************************/ namespace Thelia\Core\Event; -use Thelia\Model\Category; -class CategoryToggleVisibilityEvent extends ActionEvent +class CategoryToggleVisibilityEvent extends BaseToggleVisibilityEvent { - protected $category_id; - protected $category; - - public function __construct($category_id) - { - $this->category_id = $category_id; - } - - public function getCategoryId() - { - return $this->category_id; - } - - public function setCategoryId($category_id) - { - $this->category_id = $category_id; - } - - public function getCategory() - { - return $this->category; - } - - public function setCategory(Category $category) - { - $this->category = $category; - } } \ No newline at end of file diff --git a/core/lib/Thelia/Core/Event/CategoryUpdateEvent.php b/core/lib/Thelia/Core/Event/CategoryUpdateEvent.php index 8103864c5..305cf9369 100644 --- a/core/lib/Thelia/Core/Event/CategoryUpdateEvent.php +++ b/core/lib/Thelia/Core/Event/CategoryUpdateEvent.php @@ -22,17 +22,16 @@ /*************************************************************************************/ namespace Thelia\Core\Event; - use Thelia\Model\Category; -class CategoryUpdateEvent extends ActionEvent +class CategoryUpdateEvent extends CategoryCreateEvent { protected $category_id; - protected $locale; - protected $title; + protected $chapo; protected $description; protected $postscriptum; + protected $url; protected $visibility; protected $parent; @@ -41,4 +40,81 @@ class CategoryUpdateEvent extends ActionEvent { $this->category_id = $category_id; } + + public function getCategoryId() + { + return $this->category_id; + } + + public function setCategoryId($category_id) + { + $this->category_id = $category_id; + return $this; + } + + public function getChapo() + { + return $this->chapo; + } + + public function setChapo($chapo) + { + $this->chapo = $chapo; + return $this; + } + + public function getDescription() + { + return $this->description; + } + + public function setDescription($description) + { + $this->description = $description; + return $this; + } + + public function getPostscriptum() + { + return $this->postscriptum; + } + + public function setPostscriptum($postscriptum) + { + $this->postscriptum = $postscriptum; + return $this; + } + + public function getUrl() + { + return $this->url; + } + + public function setUrl($url) + { + $this->url = $url; + return $this; + } + + public function getVisibility() + { + return $this->visibility; + } + + public function setVisibility($visibility) + { + $this->visibility = $visibility; + return $this; + } + + public function getParent() + { + return $this->parent; + } + + public function setParent($parent) + { + $this->parent = $parent; + return $this; + } } diff --git a/core/lib/Thelia/Core/Event/CategoryChangePositionEvent.php b/core/lib/Thelia/Core/Event/CategoryUpdatePositionEvent.php similarity index 96% rename from core/lib/Thelia/Core/Event/CategoryChangePositionEvent.php rename to core/lib/Thelia/Core/Event/CategoryUpdatePositionEvent.php index 3a3dbb18f..44af9b946 100644 --- a/core/lib/Thelia/Core/Event/CategoryChangePositionEvent.php +++ b/core/lib/Thelia/Core/Event/CategoryUpdatePositionEvent.php @@ -23,6 +23,6 @@ namespace Thelia\Core\Event; -class CurrencyUpdatePositionEvent extends BaseUpdatePositionEvent +class CategoryUpdatePositionEvent extends BaseUpdatePositionEvent { } \ No newline at end of file diff --git a/core/lib/Thelia/Core/Event/ConfigEvent.php b/core/lib/Thelia/Core/Event/ConfigEvent.php index eb5ec57c7..5e1c673cf 100644 --- a/core/lib/Thelia/Core/Event/ConfigEvent.php +++ b/core/lib/Thelia/Core/Event/ConfigEvent.php @@ -26,13 +26,17 @@ use Thelia\Model\Config; class ConfigEvent extends ActionEvent { - protected $config; + protected $config = null; public function __construct(Config $config = null) { $this->config = $config; } + public function hasConfig() { + return ! is_null($this->config); + } + public function getConfig() { return $this->config; diff --git a/core/lib/Thelia/Core/Event/Coupon/CouponCreateOrUpdateEvent.php b/core/lib/Thelia/Core/Event/Coupon/CouponCreateOrUpdateEvent.php new file mode 100644 index 000000000..796baed08 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Coupon/CouponCreateOrUpdateEvent.php @@ -0,0 +1,312 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Core\Event\Coupon; +use Thelia\Core\Event\ActionEvent; +use Thelia\Coupon\CouponRuleCollection; +use Thelia\Model\Coupon; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/29/13 + * Time: 3:45 PM + * + * Occurring when a Coupon is created + * + * @package Coupon + * @author Guillaume MOREL + * + */ +class CouponCreateOrUpdateEvent extends ActionEvent +{ + /** @var CouponRuleCollection Array of CouponRuleInterface */ + protected $rules = null; + + /** @var string Coupon code (ex: XMAS) */ + protected $code = null; + + /** @var string Coupon title (ex: Coupon for XMAS) */ + protected $title = null; + + /** @var string Coupon short description */ + protected $shortDescription = null; + + /** @var string Coupon description */ + protected $description = null; + + /** @var bool if Coupon is enabled */ + protected $isEnabled = false; + + /** @var \DateTime Coupon expiration date */ + protected $expirationDate = null; + + /** @var bool if Coupon is cumulative */ + protected $isCumulative = false; + + /** @var bool if Coupon is removing postage */ + protected $isRemovingPostage = false; + + /** @var float Amount that will be removed from the Checkout (Coupon Effect) */ + protected $amount = 0; + + /** @var int Max time a Coupon can be used (-1 = unlimited) */ + protected $maxUsage = -1; + + /** @var bool if Coupon is available for Products already on special offers */ + protected $isAvailableOnSpecialOffers = false; + + /** @var Coupon Coupon model */ + protected $coupon = null; + + /** @var string Coupon effect */ + protected $effect; + + /** @var string Language code ISO (ex: fr_FR) */ + protected $locale = null; + + /** + * Constructor + * + * @param string $code Coupon Code + * @param string $title Coupon title + * @param float $amount Amount removed from the Total Checkout + * @param string $effect Coupon effect + * @param string $shortDescription Coupon short description + * @param string $description Coupon description + * @param boolean $isEnabled Enable/Disable + * @param \DateTime $expirationDate Coupon expiration date + * @param boolean $isAvailableOnSpecialOffers Is available on special offers + * @param boolean $isCumulative Is cumulative + * @param boolean $isRemovingPostage Is removing Postage + * @param int $maxUsage Coupon quantity + * @param CouponRuleCollection $rules CouponRuleInterface to add + * @param string $locale Coupon Language code ISO (ex: fr_FR) + */ + function __construct( + $code, + $title, + $amount, + $effect, + $shortDescription, + $description, + $isEnabled, + \DateTime $expirationDate, + $isAvailableOnSpecialOffers, + $isCumulative, + $isRemovingPostage, + $maxUsage, + $rules, + $locale + ) { + $this->amount = $amount; + $this->code = $code; + $this->description = $description; + $this->expirationDate = $expirationDate; + $this->isAvailableOnSpecialOffers = $isAvailableOnSpecialOffers; + $this->isCumulative = $isCumulative; + $this->isEnabled = $isEnabled; + $this->isRemovingPostage = $isRemovingPostage; + $this->maxUsage = $maxUsage; + $this->rules = $rules; + $this->shortDescription = $shortDescription; + $this->title = $title; + $this->effect = $effect; + $this->locale = $locale; + } + + /** + * Return Coupon code (ex: XMAS) + * + * @return string + */ + public function getCode() + { + return $this->code; + } + + /** + * Return Coupon title (ex: Coupon for XMAS) + * + * @return string + */ + public function getTitle() + { + return $this->title; + } + + /** + * Return Coupon short description + * + * @return string + */ + public function getShortDescription() + { + return $this->shortDescription; + } + + /** + * Return Coupon description + * + * @return string + */ + public function getDescription() + { + return $this->description; + } + + /** + * If Coupon is cumulative or prevent any accumulation + * If is cumulative you can sum Coupon effects + * If not cancel all other Coupon and take the last given + * + * @return bool + */ + public function isCumulative() + { + return $this->isCumulative; + } + + /** + * If Coupon is removing Checkout Postage + * + * @return bool + */ + public function isRemovingPostage() + { + return $this->isRemovingPostage; + } + + /** + * Return effects generated by the coupon + * + * @return float Amount removed from the Total Checkout + */ + public function getAmount() + { + return $this->amount; + } + + /** + * Return condition to validate the Coupon or not + * + * @return CouponRuleCollection + */ + public function getRules() + { + if ($this->rules === null || !is_object($this->rules)) { + $rules = $this->rules; + } else { + $rules = clone $this->rules; + } + + return $rules; + } + + /** + * Return Coupon expiration date + * + * @return \DateTime + */ + public function getExpirationDate() + { + return clone $this->expirationDate; + } + + /** + * If Coupon is available on special offers + * + * @return boolean + */ + public function isAvailableOnSpecialOffers() + { + return $this->isAvailableOnSpecialOffers; + } + + /** + * Get if Coupon is enabled or not + * + * @return boolean + */ + public function isEnabled() + { + return $this->isEnabled; + } + + /** + * Return how many time the Coupon can be used again + * Ex : -1 unlimited + * + * @return int + */ + public function getMaxUsage() + { + return $this->maxUsage; + } + + /** + * Get Coupon effect + * + * @return string + */ + public function getEffect() + { + return $this->effect; + } + + /** + * Coupon Language code ISO (ex: fr_FR) + * + * @return string + */ + public function getLocale() + { + return $this->locale; + } + + /** + * Set Coupon Model + * + * @param \Thelia\Model\Coupon $coupon Coupon Model + * + * @return $this + */ + public function setCoupon($coupon) + { + $this->coupon = $coupon; + + return $this; + } + + /** + * Return Coupon Model + * + * @return \Thelia\Model\Coupon + */ + public function getCoupon() + { + return $this->coupon; + } + + + +} diff --git a/core/lib/Thelia/Core/Event/Coupon/CouponDisableEvent.php b/core/lib/Thelia/Core/Event/Coupon/CouponDisableEvent.php new file mode 100644 index 000000000..db8e14243 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Coupon/CouponDisableEvent.php @@ -0,0 +1,103 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Core\Event\Coupon; +use Thelia\Model\Coupon; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/29/13 + * Time: 3:45 PM + * + * Occurring when a Coupon is disabled + * + * @package Coupon + * @author Guillaume MOREL + * + */ +class CouponDisableEvent extends ActionEvent +{ + /** @var int Coupon id */ + protected $couponId; + + /** @var Coupon Coupon being disabled */ + protected $disabledCoupon; + + /** + * Constructor + * + * @param int $id Coupon Id + */ + public function __construct($id) + { + $this->id = $id; + } + + /** + * Get Coupon id + * + * @return int + */ + public function getId() + { + return $this->id; + } + + /** + * Set Coupon id + * + * @param int $id Coupon id + * + * @return $this + */ + public function setId($id) + { + $this->id = $id; + + return $this; + } + + /** + * Get Coupon being disabled + * + * @return Coupon + */ + public function getDisabledCoupon() + { + return $this->disabledCoupon; + } + + /** + * Set Coupon to be disabled + * + * @param Coupon $disabledCoupon Coupon to disable + * + * @return $this + */ + public function setDisabledCoupon(Coupon $disabledCoupon) + { + $this->disabledCoupon = $disabledCoupon; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Coupon/CouponEnableEvent.php b/core/lib/Thelia/Core/Event/Coupon/CouponEnableEvent.php new file mode 100644 index 000000000..ab06953e5 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Coupon/CouponEnableEvent.php @@ -0,0 +1,103 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Core\Event\Coupon; +use Thelia\Model\Coupon; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/29/13 + * Time: 3:45 PM + * + * Occurring when a Coupon is enabled + * + * @package Coupon + * @author Guillaume MOREL + * + */ +class CouponEnableEvent extends ActionEvent +{ + /** @var int Coupon id */ + protected $couponId; + + /** @var Coupon Coupon being enabled */ + protected $enabledCoupon; + + /** + * Constructor + * + * @param int $id Coupon Id + */ + public function __construct($id) + { + $this->id = $id; + } + + /** + * Get Coupon id + * + * @return int + */ + public function getId() + { + return $this->id; + } + + /** + * Set Coupon id + * + * @param int $id Coupon id + * + * @return $this + */ + public function setId($id) + { + $this->id = $id; + + return $this; + } + + /** + * Get Coupon being enabled + * + * @return Coupon + */ + public function getEnabledCoupon() + { + return $this->enabledCoupon; + } + + /** + * Set Coupon to be enabled + * + * @param Coupon $enabledCoupon Coupon to enabled + * + * @return $this + */ + public function setEnabledCoupon(Coupon $enabledCoupon) + { + $this->enabledCoupon = $enabledCoupon; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/CurrencyEvent.php b/core/lib/Thelia/Core/Event/CurrencyEvent.php index e0716da0c..65ac60513 100644 --- a/core/lib/Thelia/Core/Event/CurrencyEvent.php +++ b/core/lib/Thelia/Core/Event/CurrencyEvent.php @@ -26,13 +26,17 @@ use Thelia\Model\Currency; class CurrencyEvent extends ActionEvent { - protected $currency; + protected $currency = null; public function __construct(Currency $currency = null) { $this->currency = $currency; } + public function hasCurrency() { + return ! is_null($this->currency); + } + public function getCurrency() { return $this->currency; diff --git a/core/lib/Thelia/Core/Event/MessageEvent.php b/core/lib/Thelia/Core/Event/MessageEvent.php index 18433a36b..0f46ae590 100644 --- a/core/lib/Thelia/Core/Event/MessageEvent.php +++ b/core/lib/Thelia/Core/Event/MessageEvent.php @@ -26,13 +26,17 @@ use Thelia\Model\Message; class MessageEvent extends ActionEvent { - protected $message; + protected $message = null; public function __construct(Message $message = null) { $this->message = $message; } + public function hasMessage() { + return ! is_null($this->message); + } + public function getMessage() { return $this->message; diff --git a/core/lib/Thelia/Core/Event/TheliaEvents.php b/core/lib/Thelia/Core/Event/TheliaEvents.php index 97d92e110..c5ae0afbf 100755 --- a/core/lib/Thelia/Core/Event/TheliaEvents.php +++ b/core/lib/Thelia/Core/Event/TheliaEvents.php @@ -33,6 +33,11 @@ namespace Thelia\Core\Event; final class TheliaEvents { + /** + * sent at the beginning + */ + const BOOT = "thelia.boot"; + /** * ACTION event * @@ -199,6 +204,130 @@ final class TheliaEvents */ const IMAGE_CLEAR_CACHE = "action.clearImageCache"; + + + /** + * Sent when creating a Coupon + */ + const COUPON_CREATE = "action.create_coupon"; + + /** + * Sent just before a successful insert of a new Coupon in the database. + */ + const BEFORE_CREATE_COUPON = "action.before_create_coupon"; + + /** + * Sent just after a successful insert of a new Coupon in the database. + */ + const AFTER_CREATE_COUPON = "action.after_create_coupon"; + + /** + * Sent when editing a Coupon + */ + const COUPON_UPDATE = "action.update_coupon"; + + /** + * Sent just before a successful update of a new Coupon in the database. + */ + const BEFORE_UPDATE_COUPON = "action.before_update_coupon"; + + /** + * Sent just after a successful update of a new Coupon in the database. + */ + const AFTER_UPDATE_COUPON = "action.after_update_coupon"; + + /** + * Sent when disabling a Coupon + */ + const COUPON_DISABLE = "action.disable_coupon"; + + /** + * Sent just before a successful disable of a new Coupon in the database. + */ + const BEFORE_DISABLE_COUPON = "action.before_disable_coupon"; + + /** + * Sent just after a successful disable of a new Coupon in the database. + */ + const AFTER_DISABLE_COUPON = "action.after_disable_coupon"; + + /** + * Sent when enabling a Coupon + */ + const COUPON_ENABLE = "action.enable_coupon"; + + /** + * Sent just before a successful enable of a new Coupon in the database. + */ + const BEFORE_ENABLE_COUPON = "action.before_enable_coupon"; + + /** + * Sent just after a successful enable of a new Coupon in the database. + */ + 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_CONSUME_COUPON = "action.before_consume_coupon"; + + /** + * Sent just after an attempt to use a 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 --------------------------------------------- const CONFIG_CREATE = "action.createConfig"; diff --git a/core/lib/Thelia/Core/HttpFoundation/Session/Session.php b/core/lib/Thelia/Core/HttpFoundation/Session/Session.php index 4a486e488..fc2726647 100755 --- a/core/lib/Thelia/Core/HttpFoundation/Session/Session.php +++ b/core/lib/Thelia/Core/HttpFoundation/Session/Session.php @@ -28,6 +28,7 @@ use Thelia\Core\Security\User\UserInterface; use Thelia\Exception\InvalidCartException; use Thelia\Model\CartQuery; use Thelia\Model\Cart; +use Thelia\Model\Currency; use Thelia\Tools\URL; use Thelia\Model\Lang; @@ -44,9 +45,9 @@ class Session extends BaseSession /** * @return \Thelia\Model\Lang|null */ - public function getLang() + public function getLang($forceDefault = true) { - return $this->get("thelia.current.lang", Lang::getDefaultLanguage()); + return $this->get("thelia.current.lang", $forceDefault ? Lang::getDefaultLanguage():null); } public function setLang(Lang $lang) @@ -68,6 +69,16 @@ class Session extends BaseSession return $this; } + public function setCurrency(Currency $currency) + { + $this->set("thelia.current.currency", $currency); + } + + public function getCurrency($forceDefault = true) + { + return $this->get("thelia.current.currency", $forceDefault ? Currency::getDefaultCurrency():null); + } + // -- Customer user -------------------------------------------------------- public function setCustomerUser(UserInterface $user) @@ -164,10 +175,28 @@ class Session extends BaseSession * assign cart id in session * * @param $cart_id + * @return $this */ public function setCart($cart_id) { $this->set("thelia.cart_id", $cart_id); return $this; } + + /** + * assign delivery id in session + * + * @param $delivery_id + * @return $this + */ + public function setDelivery($delivery_id) + { + $this->set("thelia.delivery_id", $delivery_id); + return $this; + } + + public function getDelivery() + { + return $this->get("thelia.delivery_id"); + } } \ No newline at end of file diff --git a/core/lib/Thelia/Core/Template/Element/BaseI18nLoop.php b/core/lib/Thelia/Core/Template/Element/BaseI18nLoop.php index 18eadce3c..792389b1c 100644 --- a/core/lib/Thelia/Core/Template/Element/BaseI18nLoop.php +++ b/core/lib/Thelia/Core/Template/Element/BaseI18nLoop.php @@ -59,11 +59,12 @@ abstract class BaseI18nLoop extends BaseLoop * @param array $columns the i18n columns * @param string $foreignTable the specified table (default to criteria table) * @param string $foreignKey the foreign key in this table (default to criteria table) + * @param bool $forceReturn * * @return mixed the locale */ - protected function configureI18nProcessing(ModelCriteria $search, $columns = array('TITLE', 'CHAPO', 'DESCRIPTION', 'POSTSCRIPTUM'), $foreignTable = null, $foreignKey = 'ID', $forceReturn = false) { - + protected function configureI18nProcessing(ModelCriteria $search, $columns = array('TITLE', 'CHAPO', 'DESCRIPTION', 'POSTSCRIPTUM'), $foreignTable = null, $foreignKey = 'ID', $forceReturn = false) + { /* manage translations */ return ModelCriteriaTools::getI18n( $this->getBackend_context(), diff --git a/core/lib/Thelia/Core/Template/Element/BaseLoop.php b/core/lib/Thelia/Core/Template/Element/BaseLoop.php index 98ed8af33..209973112 100755 --- a/core/lib/Thelia/Core/Template/Element/BaseLoop.php +++ b/core/lib/Thelia/Core/Template/Element/BaseLoop.php @@ -23,6 +23,7 @@ namespace Thelia\Core\Template\Element; +use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Thelia\Core\Template\Loop\Argument\Argument; @@ -52,6 +53,9 @@ abstract class BaseLoop */ protected $securityContext; + /** @var ContainerInterface Service Container */ + protected $container = null; + protected $args; public $countable = true; @@ -61,15 +65,15 @@ abstract class BaseLoop /** * Create a new Loop * - * @param Request $request - * @param EventDispatcherInterface $dispatcher - * @param SecurityContext $securityContext + * @param ContainerInterface $container */ - public function __construct(Request $request, EventDispatcherInterface $dispatcher, SecurityContext $securityContext) + public function __construct(ContainerInterface $container) { - $this->request = $request; - $this->dispatcher = $dispatcher; - $this->securityContext = $securityContext; + $this->container = $container; + + $this->request = $container->get('request'); + $this->dispatcher = $container->get('event_dispatcher'); + $this->securityContext = $container->get('thelia.securityContext'); $this->args = $this->getArgDefinitions()->addArguments($this->getDefaultArgs(), false); } @@ -243,23 +247,9 @@ abstract class BaseLoop * * this function have to be implement in your own loop class. * - * All your parameters are defined in defineArgs() and can be accessible like a class property. + * All loops parameters can be accessible via getter. * - * example : - * - * public function defineArgs() - * { - * return array ( - * "ref", - * "id" => "optional", - * "stock" => array( - * "optional", - * "default" => 10 - * ) - * ); - * } - * - * you can retrieve ref value using $this->ref + * for example, ref parameter is accessible through getRef method * * @param $pagination * @@ -271,18 +261,31 @@ abstract class BaseLoop * * define all args used in your loop * - * array key is your arg name. * * example : * - * return array ( - * "ref", - * "id" => "optional", - * "stock" => array( - * "optional", - * "default" => 10 - * ) - * ); + * public function getArgDefinitions() + * { + * return new ArgumentCollection( + * Argument::createIntListTypeArgument('id'), + * new Argument( + * 'ref', + * new TypeCollection( + * new Type\AlphaNumStringListType() + * ) + * ), + * Argument::createIntListTypeArgument('category'), + * Argument::createBooleanTypeArgument('new'), + * Argument::createBooleanTypeArgument('promo'), + * Argument::createFloatTypeArgument('min_price'), + * Argument::createFloatTypeArgument('max_price'), + * Argument::createIntTypeArgument('min_stock'), + * Argument::createFloatTypeArgument('min_weight'), + * Argument::createFloatTypeArgument('max_weight'), + * Argument::createBooleanTypeArgument('current'), + * + * ); + * } * * @return \Thelia\Core\Template\Loop\Argument\ArgumentCollection */ diff --git a/core/lib/Thelia/Core/Template/Loop/Address.php b/core/lib/Thelia/Core/Template/Loop/Address.php index 757cc11b8..3ac9370f8 100755 --- a/core/lib/Thelia/Core/Template/Loop/Address.php +++ b/core/lib/Thelia/Core/Template/Loop/Address.php @@ -87,7 +87,7 @@ class Address extends BaseLoop $customer = $this->getCustomer(); if ($customer === 'current') { - $currentCustomer = $this->request->getSession()->getCustomerUser(); + $currentCustomer = $this->securityContext->getCustomerUser(); if ($currentCustomer === null) { return new LoopResult(); } else { diff --git a/core/lib/Thelia/Core/Template/Loop/BaseSpecificModule.php b/core/lib/Thelia/Core/Template/Loop/BaseSpecificModule.php new file mode 100644 index 000000000..3b4e54be6 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/BaseSpecificModule.php @@ -0,0 +1,109 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Core\Template\Loop; +use Propel\Runtime\ActiveQuery\Criteria; +use Thelia\Core\Template\Element\BaseI18nLoop; +use Thelia\Core\Template\Loop\Argument\Argument; +use Thelia\Core\Template\Loop\Argument\ArgumentCollection; +use Thelia\Model\ModuleQuery; + + +/** + * Class Delivery + * @package Thelia\Core\Template\Loop + * @author Manuel Raynaud + */ +class BaseSpecificModule extends BaseI18nLoop { + public $timestampable = true; + + /** + * + * define all args used in your loop + * + * + * example : + * + * public function getArgDefinitions() + * { + * return new ArgumentCollection( + * Argument::createIntListTypeArgument('id'), + * new Argument( + * 'ref', + * new TypeCollection( + * new Type\AlphaNumStringListType() + * ) + * ), + * Argument::createIntListTypeArgument('category'), + * Argument::createBooleanTypeArgument('new'), + * Argument::createBooleanTypeArgument('promo'), + * Argument::createFloatTypeArgument('min_price'), + * Argument::createFloatTypeArgument('max_price'), + * Argument::createIntTypeArgument('min_stock'), + * Argument::createFloatTypeArgument('min_weight'), + * Argument::createFloatTypeArgument('max_weight'), + * Argument::createBooleanTypeArgument('current'), + * + * ); + * } + * + * @return \Thelia\Core\Template\Loop\Argument\ArgumentCollection + */ + protected function getArgDefinitions() + { + return new ArgumentCollection( + Argument::createIntTypeArgument('id'), + Argument::createIntListTypeArgument('exclude') + ); + } + + /** + * + * this function have to be implement in your own loop class. + * + * All loops parameters can be accesible via getter. + * + * for example, ref parameter is accessible through getRef method + * + * @param $pagination + * + * @return \Thelia\Model\ModuleQuery + */ + public function exec(&$pagination) + { + $search = ModuleQuery::create(); + + if(null !== $id = $this->getId()) + { + $search->filterById($id); + } + + + if (null !== $exclude = $this->getExclude()) { + $search->filterById($exclude, Criteria::NOT_IN); + } + + return $search; + } + +} \ No newline at end of file diff --git a/core/lib/Thelia/Core/Template/Loop/Coupon.php b/core/lib/Thelia/Core/Template/Loop/Coupon.php new file mode 100755 index 000000000..ee3cc0a5a --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/Coupon.php @@ -0,0 +1,110 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Core\Template\Loop; + +use Propel\Runtime\ActiveQuery\Criteria; +use Thelia\Core\Template\Element\BaseI18nLoop; +use Thelia\Core\Template\Element\LoopResult; +use Thelia\Core\Template\Element\LoopResultRow; + +use Thelia\Core\Template\Loop\Argument\ArgumentCollection; +use Thelia\Core\Template\Loop\Argument\Argument; + +use Thelia\Model\Base\CategoryQuery; +use Thelia\Model\ConfigQuery; +use Thelia\Model\CouponQuery; +use Thelia\Model\Coupon as MCoupon; +use Thelia\Model\Map\ProductCategoryTableMap; +use Thelia\Type; +use Thelia\Type\BooleanOrBothType; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Coupon Loop + * + * @package Thelia\Core\Template\Loop + * @author Guillaume MOREL + * + */ +class Coupon extends BaseI18nLoop +{ + /** + * @return ArgumentCollection + */ + protected function getArgDefinitions() + { + return new ArgumentCollection( + Argument::createIntListTypeArgument('id') + ); + } + + /** + * @param $pagination + * + * @return \Thelia\Core\Template\Element\LoopResult + */ + public function exec(&$pagination) + { + $search = CouponQuery::create(); + + /* manage translations */ + $locale = $this->configureI18nProcessing($search, array('TITLE', 'DESCRIPTION', 'SHORT_DESCRIPTION')); + + $id = $this->getId(); + + if (null !== $id) { + $search->filterById($id, Criteria::IN); + } + + // Perform search + $coupons = $this->search($search, $pagination); + + $loopResult = new LoopResult(); + + /** @var MCoupon $coupon */ + foreach ($coupons as $coupon) { + $loopResultRow = new LoopResultRow(); + $loopResultRow->set("ID", $coupon->getId()) + ->set("IS_TRANSLATED", $coupon->getVirtualColumn('IS_TRANSLATED')) + ->set("LOCALE", $locale) + ->set("CODE", $coupon->getCode()) + ->set("TITLE", $coupon->getVirtualColumn('i18n_TITLE')) + ->set("SHORT_DESCRIPTION", $coupon->getVirtualColumn('i18n_SHORT_DESCRIPTION')) + ->set("DESCRIPTION", $coupon->getVirtualColumn('i18n_DESCRIPTION')) + ->set("EXPIRATION_DATE", $coupon->getExpirationDate()) + ->set("USAGE_LEFT", $coupon->getMaxUsage()) + ->set("IS_CUMULATIVE", $coupon->getIsCumulative()) + ->set("IS_REMOVING_POSTAGE", $coupon->getIsRemovingPostage()) + ->set("IS_ENABLED", $coupon->getIsEnabled()) + ->set("AMOUNT", $coupon->getAmount()) + ->set("APPLICATION_CONDITIONS", $coupon->getRules()); + $loopResult->addRow($loopResultRow); + } + + return $loopResult; + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/Customer.php b/core/lib/Thelia/Core/Template/Loop/Customer.php index 1a4b84105..9861be29a 100755 --- a/core/lib/Thelia/Core/Template/Loop/Customer.php +++ b/core/lib/Thelia/Core/Template/Loop/Customer.php @@ -64,6 +64,7 @@ class Customer extends BaseLoop ) ), Argument::createBooleanTypeArgument('reseller'), + Argument::createBooleanTypeArgument('last_order'), Argument::createIntTypeArgument('sponsor') ); } @@ -80,7 +81,7 @@ class Customer extends BaseLoop $current = $this->getCurrent(); if ($current === true) { - $currentCustomer = $this->request->getSession()->getCustomerUser(); + $currentCustomer = $this->securityContext->getCustomerUser(); if ($currentCustomer === null) { return new LoopResult(); } else { @@ -130,6 +131,20 @@ class Customer extends BaseLoop $loopResultRow->set("SPONSOR", $customer->getSponsor()); $loopResultRow->set("DISCOUNT", $customer->getDiscount()); + $lastOrderDate = ""; + $lastOrderAmount = ""; + + if ($this->getLastOrder()) { + $order = $customer->getOrders()->getFirst(); + if ($order) { + $lastOrderDate = $order->getCreatedAt(); + $lastOrderAmount = $order->getTotalAmount(); + } + } + + $loopResultRow->set("LASTORDER_DATE", $lastOrderDate); + $loopResultRow->set("LASTORDER_AMOUNT", $lastOrderAmount); + $loopResult->addRow($loopResultRow); } diff --git a/core/lib/Thelia/Core/Template/Loop/Delivery.php b/core/lib/Thelia/Core/Template/Loop/Delivery.php new file mode 100644 index 000000000..7ef46eedc --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/Delivery.php @@ -0,0 +1,85 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Core\Template\Loop; +use Thelia\Core\Template\Element\LoopResult; +use Thelia\Core\Template\Element\LoopResultRow; +use Thelia\Core\Template\Loop\Argument\Argument; + + +/** + * Class Delivery + * @package Thelia\Core\Template\Loop + * @author Manuel Raynaud + */ +class Delivery extends BaseSpecificModule +{ + + public function getArgDefinitions() + { + $collection = parent::getArgDefinitions(); + + $collection->addArgument( + Argument::createIntTypeArgument("country") + ); + + return $collection; + } + + public function exec(&$pagination) + { + $search = parent::exec($pagination); + /* manage translations */ + $locale = $this->configureI18nProcessing($search); + /* perform search */ + $deliveryModules = $this->search($search, $pagination); + + $loopResult = new LoopResult($deliveryModules); + + foreach ($deliveryModules as $deliveryModule) { + $loopResultRow = new LoopResultRow($loopResult, $deliveryModule, $this->versionable, $this->timestampable, $this->countable); + + $moduleReflection = new \ReflectionClass($deliveryModule->getFullNamespace()); + if($moduleReflection->isSubclassOf("Thelia\Module\DeliveryModuleInterface") === false) { + throw new \RuntimeException(sprintf("delivery module %s is not a Thelia\Module\DeliveryModuleInterface", $deliveryModule->getCode())); + } + $moduleInstance = $moduleReflection->newInstance(); + + $moduleInstance->setRequest($this->request); + $moduleInstance->setDispatcher($this->dispatcher); + + $loopResultRow + ->set('ID', $deliveryModule->getId()) + ->set('TITLE', $deliveryModule->getVirtualColumn('i18n_TITLE')) + ->set('CHAPO', $deliveryModule->getVirtualColumn('i18n_CHAPO')) + ->set('DESCRIPTION', $deliveryModule->getVirtualColumn('i18n_DESCRIPTION')) + ->set('POSTSCRIPTUM', $deliveryModule->getVirtualColumn('i18n_POSTSCRIPTUM')) + ->set('PRICE', $moduleInstance->calculate($this->getCountry())) + ; + + $loopResult->addRow($loopResultRow); + } + + return $loopResult; + } +} \ No newline at end of file diff --git a/core/lib/Thelia/Core/Template/Loop/Product.php b/core/lib/Thelia/Core/Template/Loop/Product.php index 4d785b8b0..b7a7c13fe 100755 --- a/core/lib/Thelia/Core/Template/Loop/Product.php +++ b/core/lib/Thelia/Core/Template/Loop/Product.php @@ -34,6 +34,7 @@ use Thelia\Core\Template\Loop\Argument\Argument; use Thelia\Log\Tlog; use Thelia\Model\CategoryQuery; +use Thelia\Model\CountryQuery; use Thelia\Model\Map\FeatureProductTableMap; use Thelia\Model\Map\ProductPriceTableMap; use Thelia\Model\Map\ProductSaleElementsTableMap; @@ -333,10 +334,10 @@ class Product extends BaseI18nLoop foreach($isProductPriceLeftJoinList as $pSE => $isProductPriceLeftJoin) { $booleanMatchedPriceList[] = 'CASE WHEN `' . $pSE . '`.PROMO=1 THEN `' . $isProductPriceLeftJoin . '`.PROMO_PRICE ELSE `' . $isProductPriceLeftJoin . '`.PRICE END'; } - $search->withColumn('MAX(' . implode(' OR ', $booleanMatchedPromoList) . ')', 'main_product_is_promo'); - $search->withColumn('MAX(' . implode(' OR ', $booleanMatchedNewnessList) . ')', 'main_product_is_new'); - $search->withColumn('MAX(' . implode(' OR ', $booleanMatchedPriceList) . ')', 'real_highest_price'); - $search->withColumn('MIN(' . implode(' OR ', $booleanMatchedPriceList) . ')', 'real_lowest_price'); + $search->withColumn('ROUND(MAX(' . implode(' OR ', $booleanMatchedPromoList) . '), 2)', 'main_product_is_promo'); + $search->withColumn('ROUND(MAX(' . implode(' OR ', $booleanMatchedNewnessList) . '), 2)', 'main_product_is_new'); + $search->withColumn('ROUND(MAX(' . implode(' OR ', $booleanMatchedPriceList) . '), 2)', 'real_highest_price'); + $search->withColumn('ROUND(MIN(' . implode(' OR ', $booleanMatchedPriceList) . '), 2)', 'real_lowest_price'); $current = $this->getCurrent(); @@ -509,6 +510,12 @@ class Product extends BaseI18nLoop foreach ($products as $product) { $loopResultRow = new LoopResultRow($loopResult, $product, $this->versionable, $this->timestampable, $this->countable); + $price = $product->getRealLowestPrice(); + $taxedPrice = $product->getTaxedPrice( + CountryQuery::create()->findOneById(64) // @TODO : make it magic + ); + + $loopResultRow->set("ID", $product->getId()) ->set("REF",$product->getRef()) ->set("IS_TRANSLATED",$product->getVirtualColumn('IS_TRANSLATED')) @@ -518,7 +525,9 @@ class Product extends BaseI18nLoop ->set("DESCRIPTION", $product->getVirtualColumn('i18n_DESCRIPTION')) ->set("POSTSCRIPTUM", $product->getVirtualColumn('i18n_POSTSCRIPTUM')) ->set("URL", $product->getUrl($locale)) - ->set("BEST_PRICE", $product->getVirtualColumn('real_lowest_price')) + ->set("BEST_PRICE", $price) + ->set("BEST_PRICE_TAX", $taxedPrice - $price) + ->set("BEST_TAXED_PRICE", $taxedPrice) ->set("IS_PROMO", $product->getVirtualColumn('main_product_is_promo')) ->set("IS_NEW", $product->getVirtualColumn('main_product_is_new')) ->set("POSITION", $product->getPosition()) diff --git a/core/lib/Thelia/Core/Template/Loop/ProductSaleElement.php b/core/lib/Thelia/Core/Template/Loop/ProductSaleElements.php similarity index 87% rename from core/lib/Thelia/Core/Template/Loop/ProductSaleElement.php rename to core/lib/Thelia/Core/Template/Loop/ProductSaleElements.php index 7a1a0b8c8..ec4c73230 100755 --- a/core/lib/Thelia/Core/Template/Loop/ProductSaleElement.php +++ b/core/lib/Thelia/Core/Template/Loop/ProductSaleElements.php @@ -35,6 +35,7 @@ use Thelia\Log\Tlog; use Thelia\Model\Base\ProductSaleElementsQuery; use Thelia\Model\ConfigQuery; +use Thelia\Model\CountryQuery; use Thelia\Type\TypeCollection; use Thelia\Type; @@ -124,6 +125,15 @@ class ProductSaleElements extends BaseLoop foreach ($PSEValues as $PSEValue) { $loopResultRow = new LoopResultRow($loopResult, $PSEValue, $this->versionable, $this->timestampable, $this->countable); + $price = $PSEValue->getPrice(); + $taxedPrice = $PSEValue->getTaxedPrice( + CountryQuery::create()->findOneById(64) // @TODO : make it magic + ); + $promoPrice = $PSEValue->getPromoPrice(); + $taxedPromoPrice = $PSEValue->getTaxedPromoPrice( + CountryQuery::create()->findOneById(64) // @TODO : make it magic + ); + $loopResultRow->set("ID", $PSEValue->getId()) ->set("QUANTITY", $PSEValue->getQuantity()) ->set("IS_PROMO", $PSEValue->getPromo() === 1 ? 1 : 0) @@ -131,8 +141,12 @@ class ProductSaleElements extends BaseLoop ->set("WEIGHT", $PSEValue->getWeight()) ->set("CURRENCY", $PSEValue->getVirtualColumn('price_CURRENCY_ID')) - ->set("PRICE", $PSEValue->getVirtualColumn('price_PRICE')) - ->set("PROMO_PRICE", $PSEValue->getVirtualColumn('price_PROMO_PRICE')); + ->set("PRICE", $price) + ->set("PRICE_TAX", $taxedPrice - $price) + ->set("TAXED_PRICE", $taxedPrice) + ->set("PROMO_PRICE", $promoPrice) + ->set("PROMO_PRICE_TAX", $taxedPromoPrice - $promoPrice) + ->set("TAXED_PROMO_PRICE", $taxedPromoPrice); $loopResult->addRow($loopResultRow); } diff --git a/core/lib/Thelia/Core/Template/Smarty/Plugins/DataAccessFunctions.php b/core/lib/Thelia/Core/Template/Smarty/Plugins/DataAccessFunctions.php index 1fdb6e4bf..fded12c0e 100755 --- a/core/lib/Thelia/Core/Template/Smarty/Plugins/DataAccessFunctions.php +++ b/core/lib/Thelia/Core/Template/Smarty/Plugins/DataAccessFunctions.php @@ -31,6 +31,7 @@ use Thelia\Core\Template\ParserContext; use Thelia\Core\Template\Smarty\SmartyPluginDescriptor; use Thelia\Model\CategoryQuery; use Thelia\Model\ContentQuery; +use Thelia\Model\CurrencyQuery; use Thelia\Model\FolderQuery; use Thelia\Model\Product; use Thelia\Model\ProductQuery; @@ -132,6 +133,35 @@ class DataAccessFunctions extends AbstractSmartyPlugin } } + /** + * currency global data + * + * @param $params + * @param $smarty + */ + public function currencyDataAccess($params, $smarty) + { + $currency = $this->request->getSession()->getCurrency(); + + if ($currency) { + $currencyQuery = CurrencyQuery::create() + ->filterById($currency->getId()); + + return $this->dataAccessWithI18n("Currency", $params, $currencyQuery, array("NAME")); + } + } + + /** + * Lang global data + * + * @param $params + * @param $smarty + */ + public function langDataAccess($params, $smarty) + { + return $this->dataAccess("Lang", $params, $this->request->getSession()->getLang()); + } + /** * @param $objectLabel * @param $params @@ -231,6 +261,8 @@ class DataAccessFunctions extends AbstractSmartyPlugin new SmartyPluginDescriptor('function', 'category', $this, 'categoryDataAccess'), new SmartyPluginDescriptor('function', 'content', $this, 'contentDataAccess'), new SmartyPluginDescriptor('function', 'folder', $this, 'folderDataAccess'), + new SmartyPluginDescriptor('function', 'currency', $this, 'currencyDataAccess'), + new SmartyPluginDescriptor('function', 'lang', $this, 'langDataAccess'), ); } } diff --git a/core/lib/Thelia/Core/Template/Smarty/Plugins/Form.php b/core/lib/Thelia/Core/Template/Smarty/Plugins/Form.php index 0b22111cd..625c89e1f 100755 --- a/core/lib/Thelia/Core/Template/Smarty/Plugins/Form.php +++ b/core/lib/Thelia/Core/Template/Smarty/Plugins/Form.php @@ -120,8 +120,15 @@ class Form extends AbstractSmartyPlugin $formFieldView = $this->getFormFieldView($params); $template->assign("options", $formFieldView->vars); + $template->assign("name", $formFieldView->vars["full_name"]); $template->assign("value", $formFieldView->vars["value"]); + + // If Checkbox input type + if ($formFieldView->vars['checked'] !== null) { + $this->renderFormFieldCheckBox($template, $formFieldView); + } + $template->assign("label", $formFieldView->vars["label"]); $template->assign("label_attr", $formFieldView->vars["label_attr"]); @@ -266,4 +273,17 @@ class Form extends AbstractSmartyPlugin new SmartyPluginDescriptor("block", "form_error", $this, "formError") ); } + + /** + * @param \Smarty_Internal_Template $template + * @param $formFieldView + */ + public function renderFormFieldCheckBox(\Smarty_Internal_Template $template, $formFieldView) + { + $template->assign("value", 0); + if ($formFieldView->vars['checked']) { + $template->assign("value", 1); + } + $template->assign("value", $formFieldView->vars['checked']); + } } diff --git a/core/lib/Thelia/Core/Template/Smarty/Plugins/Format.php b/core/lib/Thelia/Core/Template/Smarty/Plugins/Format.php index daaff3fc1..3deffc1aa 100644 --- a/core/lib/Thelia/Core/Template/Smarty/Plugins/Format.php +++ b/core/lib/Thelia/Core/Template/Smarty/Plugins/Format.php @@ -113,9 +113,15 @@ class Format extends AbstractSmartyPlugin throw new SmartyPluginException("number is a mandatory parameter in format_number function"); } + $number = $params["number"]; + + if(empty($number)) { + return ""; + } + $lang = $this->request->getSession()->getLang(); - $number = $params["number"]; + $decimals = array_key_exists("decimals", $params) ? $params["decimals"] : $lang->getDecimals(); $decPoint = array_key_exists("dec_point", $params) ? $params["dec_point"] : $lang->getDecimalSeparator(); $thousandsSep = array_key_exists("thousands_sep", $params) ? $params["thousands_sep"] : $lang->getThousandsSeparator(); diff --git a/core/lib/Thelia/Core/Template/Smarty/Plugins/TheliaLoop.php b/core/lib/Thelia/Core/Template/Smarty/Plugins/TheliaLoop.php index a65e15a8e..2c7601dc4 100755 --- a/core/lib/Thelia/Core/Template/Smarty/Plugins/TheliaLoop.php +++ b/core/lib/Thelia/Core/Template/Smarty/Plugins/TheliaLoop.php @@ -23,6 +23,7 @@ namespace Thelia\Core\Template\Smarty\Plugins; +use Symfony\Component\DependencyInjection\ContainerInterface; use Thelia\Core\Template\Element\BaseLoop; use Thelia\Core\Template\Smarty\AbstractSmartyPlugin; use Thelia\Core\Template\Smarty\SmartyPluginDescriptor; @@ -44,14 +45,22 @@ class TheliaLoop extends AbstractSmartyPlugin protected $dispatcher; protected $securityContext; + /** @var ContainerInterface Service Container */ + protected $container = null; + protected $loopstack = array(); protected $varstack = array(); - public function __construct(Request $request, EventDispatcherInterface $dispatcher, SecurityContext $securityContext) + /** + * @param ContainerInterface $container + */ + public function __construct(ContainerInterface $container) { - $this->request = $request; - $this->dispatcher = $dispatcher; - $this->securityContext = $securityContext; + $this->container = $container; + + $this->request = $container->get('request'); + $this->dispatcher = $container->get('event_dispatcher'); + $this->securityContext = $container->get('thelia.securityContext'); } /** @@ -293,13 +302,11 @@ class TheliaLoop extends AbstractSmartyPlugin } /** + * @param $smartyParams * - * find the loop class with his name and construct an instance of this class - * - * @param string $name - * @return \Thelia\Core\Template\Element\BaseLoop - * @throws InvalidElementException - * @throws ElementNotFoundException + * @return object + * @throws \Thelia\Core\Template\Element\Exception\InvalidElementException + * @throws \Thelia\Core\Template\Element\Exception\ElementNotFoundException */ protected function createLoopInstance($smartyParams) { @@ -317,9 +324,7 @@ class TheliaLoop extends AbstractSmartyPlugin } $loop = $class->newInstance( - $this->request, - $this->dispatcher, - $this->securityContext + $this->container ); $loop->initializeArgs($smartyParams); diff --git a/core/lib/Thelia/Core/Template/Smarty/SmartyParser.php b/core/lib/Thelia/Core/Template/Smarty/SmartyParser.php index 85619bc8a..ad656df32 100755 --- a/core/lib/Thelia/Core/Template/Smarty/SmartyParser.php +++ b/core/lib/Thelia/Core/Template/Smarty/SmartyParser.php @@ -65,9 +65,7 @@ class SmartyParser extends Smarty implements ParserInterface $this->setTemplate($template ?: ConfigQuery::read('active-template', 'default')); $this->debugging = $debug; - - $this->escape_html = true; - + // Prevent smarty ErrorException: Notice: Undefined index bla bla bla... $this->error_reporting = E_ALL ^ E_NOTICE; @@ -86,12 +84,13 @@ class SmartyParser extends Smarty implements ParserInterface $this->registerFilter('pre', array($this, "preThelia")); $this->registerFilter('output', array($this, "removeBlankLines")); + $this->registerFilter('variable', array(__CLASS__, "theliaEscape")); } public function preThelia($tpl_source, \Smarty_Internal_Template $template) { - $new_source = preg_replace('`{#([a-zA-Z][a-zA-Z0-9\-_]*)(.*)}`', '{\$$1$2}', $tpl_source); - $new_source = preg_replace('`#([a-zA-Z][a-zA-Z0-9\-_]*)`', '{\$$1|dieseCanceller:\'#$1\'}', $new_source); + $new_source = preg_replace('`{#([a-zA-Z][a-zA-Z0-9_]*)(.*)}`', '{\$$1$2}', $tpl_source); + $new_source = preg_replace('`#([a-zA-Z][a-zA-Z0-9_]*)`', '{\$$1|dieseCanceller:\'#$1\'}', $new_source); return $new_source; } @@ -101,6 +100,15 @@ class SmartyParser extends Smarty implements ParserInterface return preg_replace("/(^[\r\n]*|[\r\n]+)[\s\t]*[\r\n]+/", "\n", $tpl_source); } + public static function theliaEscape($content, $smarty) + { + if(!is_object($content)) { + return htmlspecialchars($content ,ENT_QUOTES, Smarty::$_CHARSET); + } else { + return $content; + } + } + public function setTemplate($template_path_from_template_base) { $this->template = $template_path_from_template_base; diff --git a/core/lib/Thelia/Core/Thelia.php b/core/lib/Thelia/Core/Thelia.php index b28b23156..e5148e408 100755 --- a/core/lib/Thelia/Core/Thelia.php +++ b/core/lib/Thelia/Core/Thelia.php @@ -33,12 +33,15 @@ namespace Thelia\Core; */ use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\Config\Loader\LoaderInterface; +use Symfony\Component\Validator\Tests\Fixtures\Reference; use Symfony\Component\Yaml\Yaml; use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; use Thelia\Core\Bundle; +use Thelia\Core\Event\TheliaEvents; use Thelia\Log\Tlog; use Thelia\Config\DatabaseConfiguration; use Thelia\Config\DefinePropel; @@ -73,7 +76,6 @@ class Thelia extends Kernel $definePropel = new DefinePropel(new DatabaseConfiguration(), Yaml::parse(THELIA_ROOT . '/local/config/database.yml')); - $propelConfig = $definePropel->getConfig(); $serviceContainer = Propel::getServiceContainer(); $serviceContainer->setAdapterClass('thelia', 'mysql'); $manager = new ConnectionManagerSingle(); @@ -81,13 +83,21 @@ class Thelia extends Kernel $serviceContainer->setConnectionManager('thelia', $manager); if ($this->isDebug()) { - $serviceContainer->setLogger('defaultLogger', Tlog::getInstance()); - $con = Propel::getConnection(\Thelia\Model\Map\ProductTableMap::DATABASE_NAME); $con->useDebug(true); } } + /** + * dispatch an event when application is boot + */ + public function boot() + { + parent::boot(); + + $this->getContainer()->get("event_dispatcher")->dispatch(TheliaEvents::BOOT); + } + /** * * Load some configuration @@ -107,6 +117,16 @@ class Thelia extends Kernel foreach ($modules as $module) { try { + + $defintion = new Definition(); + $defintion->setClass($module->getFullNamespace()); + $defintion->addMethodCall("setContainer", array('service_container')); + + $container->setDefinition( + "module.".$module->getCode(), + $defintion + ); + $loader = new XmlFileLoader($container, new FileLocator(THELIA_MODULE_DIR . "/" . ucfirst($module->getCode()) . "/Config")); $loader->load("config.xml"); } catch (\InvalidArgumentException $e) { diff --git a/core/lib/Thelia/Core/TheliaHttpKernel.php b/core/lib/Thelia/Core/TheliaHttpKernel.php index 20197d9c6..319173f5f 100755 --- a/core/lib/Thelia/Core/TheliaHttpKernel.php +++ b/core/lib/Thelia/Core/TheliaHttpKernel.php @@ -127,14 +127,34 @@ class TheliaHttpKernel extends HttpKernel // See Thelia\Tools\URL class. $this->container->get('thelia.url.manager'); + // Same thing for the Translator service. + $this->container->get('thelia.translator'); + $lang = $this->detectLang($request); if ($lang) { $request->getSession() ->setLang($lang) - ->setLocale($lang->getLocale()) ; } + + $request->getSession()->setCurrency($this->defineCurrency($request)); + } + + protected function defineCurrency(Request $request) + { + $currency = null; + if ($request->query->has("currency")) { + $currency = Model\CurrencyQuery::create()->findOneByCode($request->query->get("currency")); + } else { + $currency = $request->getSession()->getCurrency(false); + } + + if(null === $currency) { + $currency = Model\Currency::getDefaultCurrency(); + } + + return $currency; } /** @@ -150,7 +170,7 @@ class TheliaHttpKernel extends HttpKernel $lang = Model\LangQuery::create()->findOneByCode($request->query->get("lang")); if (is_null($lang)) { - return; + return Model\Lang::getDefaultLanguage(); } //if each lang had is own domain, we redirect the user to the good one. @@ -172,7 +192,7 @@ class TheliaHttpKernel extends HttpKernel } //check if lang is not defined. If not we have to search the good one. - if (null === $request->getSession()->getLang()) { + if (null === $request->getSession()->getLang(false)) { if (Model\ConfigQuery::read("one_domain_foreach_lang", false) == 1) { //find lang with domain @@ -180,7 +200,7 @@ class TheliaHttpKernel extends HttpKernel } //find default lang - return Model\LangQuery::create()->findOneByByDefault(1); + return Model\Lang::getDefaultLanguage(); } } diff --git a/core/lib/Thelia/Core/Translation/Translator.php b/core/lib/Thelia/Core/Translation/Translator.php index 83114d478..770091403 100755 --- a/core/lib/Thelia/Core/Translation/Translator.php +++ b/core/lib/Thelia/Core/Translation/Translator.php @@ -5,6 +5,29 @@ use Symfony\Component\Translation\Translator as BaseTranslator; class Translator extends BaseTranslator { + + protected static $instance = null; + + public function __construct() + { + // Allow singleton style calls once intanciated. + // For this to work, the Translator service has to be instanciated very early. This is done manually + // in TheliaHttpKernel, by calling $this->container->get('thelia.translator'); + self::$instance = $this; + } + + /** + * Return this class instance, only once instanciated. + * + * @throws \RuntimeException if the class has not been instanciated. + * @return \Thelia\Core\Translation\Translator the instance. + */ + public static function getInstance() { + if (self::$instance == null) throw new \RuntimeException("Translator instance is not initialized."); + + return self::$instance; + } + /** * {@inheritdoc} * @@ -21,7 +44,7 @@ class Translator extends BaseTranslator } if ($this->catalogues[$locale]->has((string) $id, $domain)) - return parent::trans($id, $parameters, $domain = 'messages', $locale = null); + return parent::trans($id, $parameters, $domain, $locale); else return strtr($id, $parameters); } diff --git a/core/lib/Thelia/Coupon/CouponAdapterInterface.php b/core/lib/Thelia/Coupon/CouponAdapterInterface.php new file mode 100644 index 000000000..134d061be --- /dev/null +++ b/core/lib/Thelia/Coupon/CouponAdapterInterface.php @@ -0,0 +1,158 @@ +. */ +/* */ +/**********************************************************************************/ + +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; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Allow a CouponManager class to be fed with relevant Thelia data + * + * @package Coupon + * @author Guillaume MOREL + * + */ +interface CouponAdapterInterface +{ + + /** + * Constructor + * + * @param ContainerInterface $container Service container + */ + function __construct(ContainerInterface $container); + + /** + * Return a Cart a CouponManager can process + * + * @return \Thelia\Model\Cart + */ + public function getCart(); + + /** + * Return an Address a CouponManager can process + * + * @return \Thelia\Model\Address + */ + public function getDeliveryAddress(); + + /** + * Return an Customer a CouponManager can process + * + * @return \Thelia\Model\Customer + */ + public function getCustomer(); + + /** + * Return Checkout total price + * + * @return float + */ + public function getCheckoutTotalPrice(); + + /** + * Return Products total price + * CartTotalPrice = Checkout total - discount - postage + * + * @return float + */ + public function getCartTotalPrice(); + + /** + * Return the Checkout currency EUR|USD + * + * @return string + */ + public function getCheckoutCurrency(); + + /** + * Return Checkout total postage (only) price + * + * @return float + */ + public function getCheckoutPostagePrice(); + + /** + * Return the number of Products in the Cart + * + * @return int + */ + public function getNbArticlesInCart(); + + /** + * Return all Coupon given during the Checkout + * + * @return array Array of CouponInterface + */ + public function getCurrentCoupons(); + + /** + * Find one Coupon in the database from its code + * + * @param string $code Coupon code + * + * @return Coupon + */ + public function findOneCouponByCode($code); + + /** + * Save a Coupon in the database + * + * @param CouponInterface $coupon Coupon + * + * @return $this + */ + public function saveCoupon(CouponInterface $coupon); + + /** + * Return platform Container + * + * @return Container + */ + public function getContainer(); + + /** + * Return platform TranslatorInterface + * + * @return TranslatorInterface + */ + public function getTranslator(); + + /** + * Return the main currency + * THe one used to set prices in BackOffice + * + * @return string + */ + public function getMainCurrency(); + +} \ No newline at end of file diff --git a/core/lib/Thelia/Coupon/CouponBaseAdapter.php b/core/lib/Thelia/Coupon/CouponBaseAdapter.php new file mode 100644 index 000000000..3e77a56be --- /dev/null +++ b/core/lib/Thelia/Coupon/CouponBaseAdapter.php @@ -0,0 +1,235 @@ +. */ +/* */ +/**********************************************************************************/ + +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; +use Thelia\Model\CouponQuery; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * @package Coupon + * @author Guillaume MOREL + * @todo implements + * + */ +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 + * + * @return \Thelia\Model\Cart + */ + public function getCart() + { + // TODO: Implement getCart() method. + } + + /** + * Return an Address a CouponManager can process + * + * @return \Thelia\Model\Address + */ + public function getDeliveryAddress() + { + // TODO: Implement getDeliveryAddress() method. + } + + /** + * Return an Customer a CouponManager can process + * + * @return \Thelia\Model\Customer + */ + public function getCustomer() + { + // TODO: Implement getCustomer() method. + } + + /** + * Return Checkout total price + * + * @return float + */ + public function getCheckoutTotalPrice() + { + // TODO: Implement getCheckoutTotalPrice() method. + } + + /** + * Return Checkout total postage (only) price + * + * @return float + */ + public function getCheckoutPostagePrice() + { + // TODO: Implement getCheckoutPostagePrice() method. + } + + /** + * Return Products total price + * + * @return float + */ + public function getCartTotalPrice() + { + // TODO: Implement getCartTotalPrice() method. + } + + /** + * Return the Checkout currency EUR|USD + * + * @return string + */ + public function getCheckoutCurrency() + { + // TODO: Implement getCheckoutCurrency() method. + } + + + /** + * Return the number of Products in the Cart + * + * @return int + */ + public function getNbArticlesInCart() + { + // TODO: Implement getNbArticlesInCart() method. + } + + /** + * Return all Coupon given during the Checkout + * + * @return array Array of CouponInterface + */ + public function getCurrentCoupons() + { + $couponFactory = $this->container->get('thelia.coupon.factory'); + + // @todo Get from Session + $couponCodes = array('XMAS', 'SPRINGBREAK'); + + $coupons = array(); + foreach ($couponCodes as $couponCode) { + $coupons[] = $couponFactory->buildCouponFromCode($couponCode); + } + + return $coupons; + } + + /** + * Find one Coupon in the database from its code + * + * @param string $code Coupon code + * + * @return Coupon + */ + public function findOneCouponByCode($code) + { + $couponQuery = CouponQuery::create(); + + return $couponQuery->findOneByCode($code); + } + + /** + * Save a Coupon in the database + * + * @param CouponInterface $coupon Coupon + * + * @return $this + */ + public function saveCoupon(CouponInterface $coupon) + { +// $couponModel = new Coupon(); +// $couponModel->setCode($coupon->getCode()); +// $couponModel->setType(get_class($coupon)); +// $couponModel->setTitle($coupon->getTitle()); +// $couponModel->setShortDescription($coupon->getShortDescription()); +// $couponModel->setDescription($coupon->getDescription()); +// $couponModel->setAmount($coupon->getDiscount()); +// $couponModel->setIsUsed(0); +// $couponModel->setIsEnabled(1); +// $couponModel->set +// $couponModel->set +// $couponModel->set +// $couponModel->set +// $couponModel->set +// $couponModel->set +// $couponModel->set + } + + /** + * Return plateform Container + * + * @return Container + */ + public function getContainer() + { + // TODO: Implement getContainer() method. + } + + /** + * Return platform TranslatorInterface + * + * @return TranslatorInterface + */ + public function getTranslator() + { + return $this->container->get('thelia.translator'); + } + + + /** + * Return the main currency + * THe one used to set prices in BackOffice + * + * @return string + */ + public function getMainCurrency() + { + // TODO: Implement getMainCurrency() method. + } +} diff --git a/core/lib/Thelia/Coupon/CouponFactory.php b/core/lib/Thelia/Coupon/CouponFactory.php new file mode 100644 index 000000000..2f0c799a8 --- /dev/null +++ b/core/lib/Thelia/Coupon/CouponFactory.php @@ -0,0 +1,146 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Coupon; + +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\Translation\Exception\NotFoundResourceException; +use Thelia\Constraint\ConstraintFactory; +use Thelia\Constraint\Rule\CouponRuleInterface; +use Thelia\Coupon\Type\CouponInterface; +use Thelia\Exception\CouponExpiredException; +use Thelia\Exception\InvalidRuleException; +use Thelia\Model\Coupon; +use Symfony\Component\Serializer\Encoder\JsonEncoder; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Generate a CouponInterface + * + * @package Coupon + * @author Guillaume MOREL + * + */ +class CouponFactory +{ + /** @var ContainerInterface Service Container */ + protected $container = null; + + /** @var CouponAdapterInterface Provide necessary value from Thelia*/ + protected $adapter; + + /** + * Constructor + * + * @param ContainerInterface $container Service container + */ + function __construct(ContainerInterface $container) + { + $this->container = $container; + $this->adapter = $container->get('thelia.adapter'); + } + + /** + * Build a CouponInterface from its database data + * + * @param string $couponCode Coupon code ex: XMAS + * + * @throws \Thelia\Exception\CouponExpiredException + * @throws \Symfony\Component\Translation\Exception\NotFoundResourceException + * @return CouponInterface ready to be processed + */ + public function buildCouponFromCode($couponCode) + { + /** @var Coupon $couponModel */ + $couponModel = $this->adapter->findOneCouponByCode($couponCode); + if ($couponModel === null) { + throw new NotFoundResourceException( + 'Coupon ' . $couponCode . ' not found in Database' + ); + } + + if ($couponModel->getExpirationDate() < new \DateTime()) { + throw new CouponExpiredException($couponCode); + } + + /** @var CouponInterface $couponInterface */ + $couponInterface = $this->buildCouponInterfacFromModel($couponModel); + if ($couponInterface->getRules()->isEmpty()) { + throw new InvalidRuleException( + get_class($couponInterface) + ); + } + + return $couponInterface; + } + + /** + * Build a CouponInterface from its Model data contained in the DataBase + * + * @param Coupon $model Database data + * + * @return CouponInterface ready to use CouponInterface object instance + */ + protected function buildCouponInterfacFromModel(Coupon $model) + { + $isCumulative = ($model->getIsCumulative() == 1 ? true : false); + $isRemovingPostage = ($model->getIsRemovingPostage() == 1 ? true : false); + + if (!$this->container->has($model->getType())) { + return false; + } + + /** @var CouponInterface $couponManager*/ + $couponManager = $this->container->get($model->getType()); + $couponManager->set( + $this->adapter, + $model->getCode(), + $model->getTitle(), + $model->getShortDescription(), + $model->getDescription(), + $model->getAmount(), + $isCumulative, + $isRemovingPostage, + $model->getIsAvailableOnSpecialOffers(), + $model->getIsEnabled(), + $model->getMaxUsage(), + $model->getExpirationDate() + ); + + /** @var ConstraintFactory $constraintFactory */ + $constraintFactory = $this->container->get('thelia.constraint.factory'); + $rules = $constraintFactory->unserializeCouponRuleCollection( + $model->getSerializedRules() + ); + + $couponManager->setRules($rules); + + return $couponManager; + } + + + +} diff --git a/core/lib/Thelia/Coupon/CouponManager.php b/core/lib/Thelia/Coupon/CouponManager.php new file mode 100644 index 000000000..93cdd21fe --- /dev/null +++ b/core/lib/Thelia/Coupon/CouponManager.php @@ -0,0 +1,257 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Coupon; + +use Symfony\Component\DependencyInjection\ContainerInterface; +use Thelia\Constraint\Rule\CouponRuleInterface; +use Thelia\Coupon\Type\CouponInterface; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Manage how Coupons could interact with a Checkout + * + * @package Coupon + * @author Guillaume MOREL + * + */ +class CouponManager +{ + /** @var CouponAdapterInterface Provides necessary value from Thelia */ + protected $adapter = null; + + /** @var ContainerInterface Service Container */ + protected $container = null; + + /** @var array CouponInterface to process*/ + protected $coupons = array(); + + /** @var array Available Coupons (Services) */ + protected $availableCoupons = array(); + + /** @var array Available Rules (Services) */ + protected $availableRules = array(); + + /** + * Constructor + * + * @param ContainerInterface $container Service container + */ + function __construct(ContainerInterface $container) + { + $this->container = $container; + $this->adapter = $container->get('thelia.adapter'); + $this->coupons = $this->adapter->getCurrentCoupons(); + } + + + /** + * Get Discount for the given Coupons + * + * @api + * @return float checkout discount + */ + public function getDiscount() + { + $discount = 0.00; + + if (count($this->coupons) > 0) { + $couponsKept = $this->sortCoupons($this->coupons); + + $isRemovingPostage = $this->isCouponRemovingPostage($couponsKept); + + $discount = $this->getEffect($couponsKept); + + if ($isRemovingPostage) { + $postage = $this->adapter->getCheckoutPostagePrice(); + $discount += $postage; + } + + // Just In Case test + $checkoutTotalPrice = $this->adapter->getCartTotalPrice(); + if ($discount >= $checkoutTotalPrice) { + $discount = $checkoutTotalPrice; + } + } + + return $discount; + } + + /** + * Check if there is a Coupon removing Postage + * + * @param array $couponsKept Array of CouponInterface sorted + * + * @return bool + */ + protected function isCouponRemovingPostage(array $couponsKept) + { + $isRemovingPostage = false; + + /** @var CouponInterface $coupon */ + foreach ($couponsKept as $coupon) { + if ($coupon->isRemovingPostage()) { + $isRemovingPostage = true; + } + } + + return $isRemovingPostage; + } + + /** + * Sort Coupon to keep + * Coupon not cumulative cancels previous + * + * @param array $coupons CouponInterface to process + * + * @return array Array of CouponInterface sorted + */ + protected function sortCoupons(array $coupons) + { + $couponsKept = array(); + + /** @var CouponInterface $coupon */ + foreach ($coupons as $coupon) { + if (!$coupon->isExpired()) { + if ($coupon->isCumulative()) { + if (isset($couponsKept[0])) { + /** @var CouponInterface $previousCoupon */ + $previousCoupon = $couponsKept[0]; + if ($previousCoupon->isCumulative()) { + // Add Coupon + $couponsKept[] = $coupon; + } else { + // Reset Coupons, add last + $couponsKept = array($coupon); + } + } else { + // Reset Coupons, add last + $couponsKept = array($coupon); + } + } else { + // Reset Coupons, add last + $couponsKept = array($coupon); + } + } + } + + $coupons = $couponsKept; + $couponsKept = array(); + + /** @var CouponInterface $coupon */ + foreach ($coupons as $coupon) { + if ($coupon->isMatching($this->adapter)) { + $couponsKept[] = $coupon; + } + } + + return $couponsKept; + } + + /** + * Process given Coupon in order to get their cumulative effects + * + * @param array $coupons CouponInterface to process + * + * @return float discount + */ + protected function getEffect(array $coupons) + { + $discount = 0.00; + /** @var CouponInterface $coupon */ + foreach ($coupons as $coupon) { + $discount += $coupon->getDiscount($this->adapter); + } + + 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; + } + + /** + * Add an available CouponManager (Services) + * + * @param CouponInterface $coupon CouponManager + */ + public function addAvailableCoupon(CouponInterface $coupon) + { + $this->availableCoupons[] = $coupon; + } + + /** + * Get all available CouponManagers (Services) + * + * @return array + */ + public function getAvailableCoupons() + { + return $this->availableCoupons; + } + + /** + * Add an available ConstraintManager (Services) + * + * @param CouponRuleInterface $rule CouponRuleInterface + */ + public function addAvailableRule(CouponRuleInterface $rule) + { + $this->availableRules[] = $rule; + } + + /** + * Get all available ConstraintManagers (Services) + * + * @return array + */ + public function getAvailableRules() + { + return $this->availableRules; + } +} \ No newline at end of file diff --git a/core/lib/Thelia/Coupon/CouponRuleCollection.php b/core/lib/Thelia/Coupon/CouponRuleCollection.php new file mode 100644 index 000000000..29bf170e9 --- /dev/null +++ b/core/lib/Thelia/Coupon/CouponRuleCollection.php @@ -0,0 +1,105 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Coupon; + +use Symfony\Component\DependencyInjection\ContainerInterface; +use Thelia\Constraint\Rule\CouponRuleInterface; +use Thelia\Constraint\Rule\SerializableRule; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Manage a set of CouponRuleInterface + * + * @package Coupon + * @author Guillaume MOREL + * + */ +class CouponRuleCollection +{ + /** @var array Array of CouponRuleInterface */ + protected $rules = array(); + + /** + * Constructor + */ + function __construct() + { + + } + + /** + * Get Rules + * + * @return array Array of CouponRuleInterface + */ + public function getRules() + { + return $this->rules; + } + + /** + * Add a CouponRuleInterface to the Collection + * + * @param CouponRuleInterface $rule Rule + * + * @return $this + */ + public function add(CouponRuleInterface $rule) + { + $this->rules[] = $rule; + + return $this; + } + + /** + * Check if there is at least one rule in the collection + * + * @return bool + */ + public function isEmpty() + { + return (empty($this->rules)); + } + + /** + * Allow to compare 2 set of rules + * + * @return string Jsoned data + */ + public function __toString() + { + $arrayToSerialize = array(); + /** @var CouponRuleInterface $rule */ + foreach ($this->getRules() as $rule) { + $arrayToSerialize[] = $rule->getSerializableRule(); + } + + return json_encode($arrayToSerialize); + } + + +} \ No newline at end of file diff --git a/core/lib/Thelia/Coupon/RuleOrganizer.php b/core/lib/Thelia/Coupon/RuleOrganizer.php new file mode 100644 index 000000000..4c16ea1ff --- /dev/null +++ b/core/lib/Thelia/Coupon/RuleOrganizer.php @@ -0,0 +1,51 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Coupon; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Manage how Coupons could interact with a Checkout + * + * @package Coupon + * @author Guillaume MOREL + * + */ +class RuleOrganizer implements RuleOrganizerInterface +{ + /** + * Organize CouponRuleInterface + * + * @param array $rules Array of CouponRuleInterface + * + * @return array Array of CouponRuleInterface sorted + */ + public function organize(array $rules) + { + // TODO: Implement organize() method. + } + +} \ No newline at end of file diff --git a/core/lib/Thelia/Coupon/RuleOrganizerInterface.php b/core/lib/Thelia/Coupon/RuleOrganizerInterface.php new file mode 100644 index 000000000..b8b222028 --- /dev/null +++ b/core/lib/Thelia/Coupon/RuleOrganizerInterface.php @@ -0,0 +1,47 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Coupon; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Manage how Coupons could interact with a Checkout + * + * @package Coupon + * @author Guillaume MOREL + * + */ +interface RuleOrganizerInterface +{ + /** + * Organize CouponRuleInterface + * + * @param array $rules Array of CouponRuleInterface + * + * @return array Array of CouponRuleInterface sorted + */ + public function organize(array $rules); +} \ No newline at end of file diff --git a/core/lib/Thelia/Coupon/Type/CouponAbstract.php b/core/lib/Thelia/Coupon/Type/CouponAbstract.php new file mode 100644 index 000000000..647635024 --- /dev/null +++ b/core/lib/Thelia/Coupon/Type/CouponAbstract.php @@ -0,0 +1,305 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Coupon\Type; + +use Symfony\Component\Intl\Exception\NotImplementedException; +use Thelia\Constraint\ConstraintManager; +use Thelia\Constraint\ConstraintValidator; +use Thelia\Coupon\CouponAdapterInterface; +use Thelia\Coupon\CouponRuleCollection; +use Thelia\Coupon\RuleOrganizerInterface; +use Thelia\Exception\InvalidRuleException; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Assist in writing a CouponInterface + * + * @package Coupon + * @author Guillaume MOREL + * + */ +abstract class CouponAbstract implements CouponInterface +{ + /** @var string Service Id */ + protected $serviceId = null; + + /** @var CouponAdapterInterface Provide necessary value from Thelia */ + protected $adapter = null; + + /** @var Translator Service Translator */ + protected $translator = null; + + /** @var RuleOrganizerInterface */ + protected $organizer = null; + + /** @var CouponRuleCollection Array of CouponRuleInterface */ + protected $rules = null; + + /** @var ConstraintValidator Constraint validator */ + protected $constraintValidator = null; + + /** @var string Coupon code (ex: XMAS) */ + protected $code = null; + + /** @var string Coupon title (ex: Coupon for XMAS) */ + protected $title = null; + + /** @var string Coupon short description */ + protected $shortDescription = null; + + /** @var string Coupon description */ + protected $description = null; + + /** @var bool if Coupon is enabled */ + protected $isEnabled = false; + + /** @var \DateTime Coupon expiration date */ + protected $expirationDate = null; + + /** @var bool if Coupon is cumulative */ + protected $isCumulative = false; + + /** @var bool if Coupon is removing postage */ + protected $isRemovingPostage = false; + + /** @var float Amount that will be removed from the Checkout (Coupon Effect) */ + protected $amount = 0; + + /** @var int Max time a Coupon can be used (-1 = unlimited) */ + protected $maxUsage = -1; + + /** @var bool if Coupon is available for Products already on special offers */ + protected $isAvailableOnSpecialOffers = false; + + + /** + * Constructor + * + * @param CouponAdapterInterface $adapter Service adapter + */ + function __construct(CouponAdapterInterface $adapter) + { + $this->adapter = $adapter; + $this->translator = $adapter->getTranslator(); + } + + /** + * Set Rule Organizer + * + * @param RuleOrganizerInterface $organizer Manage Rule groups (&& and ||) + * + * @return $this + */ + public function setOrganizer($organizer) + { + $this->organizer = $organizer; + + return $this; + } + + /** + * Return Coupon code (ex: XMAS) + * + * @return string + */ + public function getCode() + { + return $this->code; + } + + /** + * Return Coupon title (ex: Coupon for XMAS) + * + * @return string + */ + public function getTitle() + { + return $this->title; + } + + /** + * Return Coupon short description + * + * @return string + */ + public function getShortDescription() + { + return $this->shortDescription; + } + + /** + * Return Coupon description + * + * @return string + */ + public function getDescription() + { + return $this->description; + } + + /** + * If Coupon is cumulative or prevent any accumulation + * If is cumulative you can sum Coupon effects + * If not cancel all other Coupon and take the last given + * + * @return bool + */ + public function isCumulative() + { + return $this->isCumulative; + } + + /** + * If Coupon is removing Checkout Postage + * + * @return bool + */ + public function isRemovingPostage() + { + return $this->isRemovingPostage; + } + + /** + * Return effects generated by the coupon + * A negative value + * + * @return float Amount removed from the Total Checkout + */ + public function getDiscount() + { + return $this->amount; + } + + /** + * Return condition to validate the Coupon or not + * + * @return CouponRuleCollection + */ + public function getRules() + { + return clone $this->rules; + } + + /** + * Replace the existing Rules by those given in parameter + * If one Rule is badly implemented, no Rule will be added + * + * @param CouponRuleCollection $rules CouponRuleInterface to add + * + * @return $this + * @throws \Thelia\Exception\InvalidRuleException + */ + public function setRules(CouponRuleCollection $rules) + { + $this->rules = $rules; + + return $this; + } + + /** + * Check if the current Coupon is matching its conditions (Rules) + * Thelia variables are given by the CouponAdapterInterface + * + * @return bool + */ + public function isMatching() + { + return $this->constraintValidator->test($this->rules); + } + + /** + * Return Coupon expiration date + * + * @return \DateTime + */ + public function getExpirationDate() + { + return clone $this->expirationDate; + } + + /** + * Check if the Coupon can be used against a + * product already with a special offer price + * + * @return boolean + */ + public function isAvailableOnSpecialOffers() + { + return $this->isAvailableOnSpecialOffers; + } + + + /** + * Check if Coupon has been disabled by admin + * + * @return boolean + */ + public function isEnabled() + { + return $this->isEnabled; + } + + /** + * Return how many time the Coupon can be used again + * Ex : -1 unlimited + * + * @return int + */ + public function getMaxUsage() + { + return $this->maxUsage; + } + + /** + * Check if the Coupon is already Expired + * + * @return bool + */ + public function isExpired() + { + $ret = true; + + $now = new \DateTime(); + if ($this->expirationDate > $now) { + $ret = false; + } + + return $ret; + } + + /** + * Get Coupon Manager service Id + * + * @return string + */ + public function getServiceId() + { + return $this->serviceId; + } + + +} diff --git a/core/lib/Thelia/Coupon/Type/CouponInterface.php b/core/lib/Thelia/Coupon/Type/CouponInterface.php new file mode 100644 index 000000000..f0426298f --- /dev/null +++ b/core/lib/Thelia/Coupon/Type/CouponInterface.php @@ -0,0 +1,215 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Coupon\Type; + +use Thelia\Coupon\CouponAdapterInterface; +use Thelia\Coupon\CouponRuleCollection; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Represents a Coupon ready to be processed in a Checkout process + * + * @package Coupon + * @author Guillaume MOREL + * + */ +interface CouponInterface +{ + /** + * Set Coupon + * + * @param CouponInterface $adapter Provides necessary value from Thelia + * @param string $code Coupon code (ex: XMAS) + * @param string $title Coupon title (ex: Coupon for XMAS) + * @param string $shortDescription Coupon short description + * @param string $description Coupon description + * @param float $effect Coupon amount/percentage to deduce + * @param bool $isCumulative If Coupon is cumulative + * @param bool $isRemovingPostage If Coupon is removing postage + * @param bool $isAvailableOnSpecialOffers If available on Product already + * on special offer price + * @param bool $isEnabled False if Coupon is disabled by admin + * @param int $maxUsage How many usage left + * @param \Datetime $expirationDate When the Code is expiring + */ + public function set( + $adapter, + $code, + $title, + $shortDescription, + $description, + $effect, + $isCumulative, + $isRemovingPostage, + $isAvailableOnSpecialOffers, + $isEnabled, + $maxUsage, + \DateTime $expirationDate); + + /** + * Return Coupon code (ex: XMAS) + * + * @return string + */ + public function getCode(); + + /** + * Return Coupon title (ex: Coupon for XMAS) + * + * @return string + */ + public function getTitle(); + + /** + * Return Coupon short description + * + * @return string + */ + public function getShortDescription(); + + /** + * Return Coupon description + * + * @return string + */ + public function getDescription(); + + /** + * If Coupon is cumulative or prevent any accumulation + * If is cumulative you can sum Coupon effects + * If not cancel all other Coupon and take the last given + * + * @return bool + */ + public function isCumulative(); + + /** + * If Coupon is removing Checkout Postage + * + * @return bool + */ + public function isRemovingPostage(); + + /** + * Return effects generated by the coupon + * A positive value + * + * Effects could also affect something else than the final Checkout price + * CouponAdapter $adapter could be use to directly pass a Session value + * some would wish to modify + * Hence affecting a wide variety of Thelia elements + * + * @return float Amount removed from the Total Checkout + */ + public function getDiscount(); + + /** + * Return condition to validate the Coupon or not + * + * @return CouponRuleCollection A set of CouponRuleInterface + */ + public function getRules(); + + /** + * Check if the current Coupon is matching its conditions (Rules) + * Thelia variables are given by the CouponAdapterInterface + * + * @return bool + */ + public function isMatching(); + + /** + * Replace the existing Rules by those given in parameter + * If one Rule is badly implemented, no Rule will be added + * + * @param CouponRuleCollection $rules CouponRuleInterface to add + * + * @return $this + * @throws \Thelia\Exception\InvalidRuleException + */ + public function setRules(CouponRuleCollection $rules); + + /** + * Return Coupon expiration date + * + * @return \DateTime + */ + public function getExpirationDate(); + + /** + * Check if the Coupon can be used against a + * product already with a special offer price + * + * @return boolean + */ + public function isAvailableOnSpecialOffers(); + + + /** + * Check if Coupon has been disabled by admin + * + * @return boolean + */ + public function isEnabled(); + + /** + * Return how many time the Coupon can be used again + * Ex : -1 unlimited + * + * @return int + */ + public function getMaxUsage(); + + /** + * Check if the Coupon is already Expired + * + * @return bool + */ + public function isExpired(); + + /** + * Get I18n name + * + * @return string + */ + public function getName(); + + /** + * Get I18n tooltip + * + * @return string + */ + public function getToolTip(); + + /** + * Get Coupon Manager service Id + * + * @return string + */ + public function getServiceId(); + +} diff --git a/core/lib/Thelia/Coupon/Type/RemoveXAmountManager.php b/core/lib/Thelia/Coupon/Type/RemoveXAmountManager.php new file mode 100644 index 000000000..eb5dc4548 --- /dev/null +++ b/core/lib/Thelia/Coupon/Type/RemoveXAmountManager.php @@ -0,0 +1,123 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Coupon\Type; + +use Thelia\Constraint\ConstraintManager; +use Thelia\Coupon\Type\CouponAbstract; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Allow to remove an amount from the checkout total + * + * @package Coupon + * @author Guillaume MOREL + * + */ +class RemoveXAmountManager extends CouponAbstract +{ + /** @var string Service Id */ + protected $serviceId = 'thelia.coupon.type.remove_x_amount'; + + /** + * Set Coupon + * + * @param CouponInterface $adapter Provides necessary value from Thelia + * @param string $code Coupon code (ex: XMAS) + * @param string $title Coupon title (ex: Coupon for XMAS) + * @param string $shortDescription Coupon short description + * @param string $description Coupon description + * @param float $amount Coupon amount to deduce + * @param bool $isCumulative If Coupon is cumulative + * @param bool $isRemovingPostage If Coupon is removing postage + * @param bool $isAvailableOnSpecialOffers If available on Product already + * on special offer price + * @param bool $isEnabled False if Coupon is disabled by admin + * @param int $maxUsage How many usage left + * @param \Datetime $expirationDate When the Code is expiring + */ + public function set( + $adapter, + $code, + $title, + $shortDescription, + $description, + $amount, + $isCumulative, + $isRemovingPostage, + $isAvailableOnSpecialOffers, + $isEnabled, + $maxUsage, + \DateTime $expirationDate + ) + { + $this->code = $code; + $this->title = $title; + $this->shortDescription = $shortDescription; + $this->description = $description; + + $this->isCumulative = $isCumulative; + $this->isRemovingPostage = $isRemovingPostage; + + $this->amount = $amount; + + $this->isAvailableOnSpecialOffers = $isAvailableOnSpecialOffers; + $this->isEnabled = $isEnabled; + $this->maxUsage = $maxUsage; + $this->expirationDate = $expirationDate; + $this->adapter = $adapter; + } + + /** + * Get I18n name + * + * @return string + */ + public function getName() + { + return $this->adapter + ->getTranslator() + ->trans('Remove X amount to total cart', array(), 'constraint'); + } + + /** + * Get I18n tooltip + * + * @return string + */ + public function getToolTip() + { + $toolTip = $this->adapter + ->getTranslator() + ->trans( + 'This coupon will remove the entered amount to the customer total checkout. If the discount is superior to the total checkout price the customer will only pay the postage. Unless if the coupon is set to remove postage too.', + array(), + 'constraint' + ); + + return $toolTip; + } +} diff --git a/core/lib/Thelia/Coupon/Type/RemoveXPercentForAttributeY.php b/core/lib/Thelia/Coupon/Type/RemoveXPercentForAttributeY.php new file mode 100644 index 000000000..f0a7ef472 --- /dev/null +++ b/core/lib/Thelia/Coupon/Type/RemoveXPercentForAttributeY.php @@ -0,0 +1,38 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Coupon\Type; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * @package Coupon + * @author Guillaume MOREL + * + */ +class RemoveXPercentForAttributeY extends RemoveXPercent +{ + +} \ No newline at end of file diff --git a/core/lib/Thelia/Coupon/Type/RemoveXPercentForCategoryY.php b/core/lib/Thelia/Coupon/Type/RemoveXPercentForCategoryY.php new file mode 100644 index 000000000..717807da7 --- /dev/null +++ b/core/lib/Thelia/Coupon/Type/RemoveXPercentForCategoryY.php @@ -0,0 +1,38 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Coupon\Type; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * @package Coupon + * @author Guillaume MOREL + * + */ +class RemoveXPercentForCategoryY extends RemoveXPercent +{ + +} \ No newline at end of file diff --git a/core/lib/Thelia/Coupon/Type/RemoveXPercentForProductSaleElementIdY.php b/core/lib/Thelia/Coupon/Type/RemoveXPercentForProductSaleElementIdY.php new file mode 100644 index 000000000..bb052cd68 --- /dev/null +++ b/core/lib/Thelia/Coupon/Type/RemoveXPercentForProductSaleElementIdY.php @@ -0,0 +1,38 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Coupon\Type; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * @package Coupon + * @author Guillaume MOREL + * + */ +class RemoveXPercentForProductSaleElementIdY extends RemoveXPercent +{ + +} \ No newline at end of file diff --git a/core/lib/Thelia/Coupon/Type/RemoveXPercentForProductY.php b/core/lib/Thelia/Coupon/Type/RemoveXPercentForProductY.php new file mode 100644 index 000000000..0b88ca44d --- /dev/null +++ b/core/lib/Thelia/Coupon/Type/RemoveXPercentForProductY.php @@ -0,0 +1,38 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Coupon\Type; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * @package Coupon + * @author Guillaume MOREL + * + */ +class RemoveXPercentForProductY extends RemoveXPercent +{ + +} \ No newline at end of file diff --git a/core/lib/Thelia/Coupon/Type/RemoveXPercentManager.php b/core/lib/Thelia/Coupon/Type/RemoveXPercentManager.php new file mode 100644 index 000000000..c200c620e --- /dev/null +++ b/core/lib/Thelia/Coupon/Type/RemoveXPercentManager.php @@ -0,0 +1,146 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Coupon\Type; + +use Thelia\Coupon\CouponAdapterInterface; +use Thelia\Coupon\Type\CouponAbstract; +use Thelia\Exception\MissingAdapterException; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * @package Coupon + * @author Guillaume MOREL + * + */ +class RemoveXPercentManager extends CouponAbstract +{ + /** @var string Service Id */ + protected $serviceId = 'thelia.coupon.type.remove_x_percent'; + + protected $percent = 0; + + /** + * Set Coupon + * + * @param CouponInterface $adapter Provides necessary value from Thelia + * @param string $code Coupon code (ex: XMAS) + * @param string $title Coupon title (ex: Coupon for XMAS) + * @param string $shortDescription Coupon short description + * @param string $description Coupon description + * @param float $percent Coupon percentage to deduce + * @param bool $isCumulative If Coupon is cumulative + * @param bool $isRemovingPostage If Coupon is removing postage + * @param bool $isAvailableOnSpecialOffers If available on Product already + * on special offer price + * @param bool $isEnabled False if Coupon is disabled by admin + * @param int $maxUsage How many usage left + * @param \Datetime $expirationDate When the Code is expiring + */ + public function set( + $adapter, + $code, + $title, + $shortDescription, + $description, + $percent, + $isCumulative, + $isRemovingPostage, + $isAvailableOnSpecialOffers, + $isEnabled, + $maxUsage, + \DateTime $expirationDate) + { + $this->code = $code; + $this->title = $title; + $this->shortDescription = $shortDescription; + $this->description = $description; + + $this->isCumulative = $isCumulative; + $this->isRemovingPostage = $isRemovingPostage; + + $this->percent = $percent; + + $this->isAvailableOnSpecialOffers = $isAvailableOnSpecialOffers; + $this->isEnabled = $isEnabled; + $this->maxUsage = $maxUsage; + $this->expirationDate = $expirationDate; + $this->adapter = $adapter; + } + + /** + * Return effects generated by the coupon + * A negative value + * + * @throws \Thelia\Exception\MissingAdapterException + * @throws \InvalidArgumentException + * @return float + */ + public function getDiscount() + { + if ($this->percent >= 100) { + throw new \InvalidArgumentException( + 'Percentage must be inferior to 100' + ); + } + + $basePrice = $this->adapter->getCartTotalPrice(); + + return $basePrice * (( $this->percent ) / 100); + } + + + /** + * Get I18n name + * + * @return string + */ + public function getName() + { + return $this->adapter + ->getTranslator() + ->trans('Remove X percent to total cart', array(), 'constraint'); + } + + /** + * Get I18n tooltip + * + * @return string + */ + public function getToolTip() + { + $toolTip = $this->adapter + ->getTranslator() + ->trans( + 'This coupon will remove the entered percentage to the customer total checkout. If the discount is superior to the total checkout price the customer will only pay the postage. Unless if the coupon is set to remove postage too.', + array(), + 'constraint' + ); + + return $toolTip; + } + +} \ No newline at end of file diff --git a/core/lib/Thelia/Exception/CouponExpiredException.php b/core/lib/Thelia/Exception/CouponExpiredException.php new file mode 100644 index 000000000..c1ccace0a --- /dev/null +++ b/core/lib/Thelia/Exception/CouponExpiredException.php @@ -0,0 +1,53 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Exception; + +use Thelia\Log\Tlog; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Thrown when an Expired Coupon is tried + * + * @package Coupon + * @author Guillaume MOREL + * + */ +class CouponExpiredException extends \Exception +{ + /** + * CouponExpiredException thrown when a Coupon is expired + * + * @param string $couponCode Coupon code + */ + public function __construct($couponCode) + { + $message = 'Expired Coupon ' . $couponCode . 'attempt'; + Tlog::getInstance()->addInfo($message); + + parent::__construct($message); + } +} diff --git a/core/lib/Thelia/Exception/InvalidRuleException.php b/core/lib/Thelia/Exception/InvalidRuleException.php new file mode 100644 index 000000000..a891ded4a --- /dev/null +++ b/core/lib/Thelia/Exception/InvalidRuleException.php @@ -0,0 +1,54 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Exception; + +use Thelia\Log\Tlog; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Thrown when a Rule is badly implemented + * + * @package Coupon + * @author Guillaume MOREL + * + */ +class InvalidRuleException extends \RuntimeException +{ + /** + * InvalidRuleOperatorException thrown when a Rule is badly implemented + * + * @param string $className Class name + */ + public function __construct($className) + { + + $message = 'Invalid Rule given to ' . $className; + Tlog::getInstance()->addError($message); + + parent::__construct($message); + } +} diff --git a/core/lib/Thelia/Exception/InvalidRuleOperatorException.php b/core/lib/Thelia/Exception/InvalidRuleOperatorException.php new file mode 100644 index 000000000..d40c723c2 --- /dev/null +++ b/core/lib/Thelia/Exception/InvalidRuleOperatorException.php @@ -0,0 +1,55 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Exception; + +use Thelia\Log\Tlog; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Thrown when a Rule receive an invalid Operator + * + * @package Coupon + * @author Guillaume MOREL + * + */ +class InvalidRuleOperatorException extends \RuntimeException +{ + /** + * InvalidRuleOperatorException thrown when a Rule is given a bad Operator + * + * @param string $className Class name + * @param string $parameter array key parameter + */ + public function __construct($className, $parameter) + { + + $message = 'Invalid Operator for Rule ' . $className . ' on parameter ' . $parameter; + Tlog::getInstance()->addError($message); + + parent::__construct($message); + } +} diff --git a/core/lib/Thelia/Exception/InvalidRuleValueException.php b/core/lib/Thelia/Exception/InvalidRuleValueException.php new file mode 100644 index 000000000..2f16f32f1 --- /dev/null +++ b/core/lib/Thelia/Exception/InvalidRuleValueException.php @@ -0,0 +1,55 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Exception; + +use Thelia\Log\Tlog; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Thrown when a Rule receive an invalid Parameter + * + * @package Coupon + * @author Guillaume MOREL + * + */ +class InvalidRuleValueException extends \RuntimeException +{ + /** + * InvalidRuleValueException thrown when a Rule is given a bad Parameter + * + * @param string $className Class name + * @param string $parameter array key parameter + */ + public function __construct($className, $parameter) + { + + $message = 'Invalid Parameter for Rule ' . $className . ' on parameter ' . $parameter; + Tlog::getInstance()->addError($message); + + parent::__construct($message); + } +} diff --git a/core/lib/Thelia/Exception/MissingAdapterException.php b/core/lib/Thelia/Exception/MissingAdapterException.php new file mode 100644 index 000000000..645020cab --- /dev/null +++ b/core/lib/Thelia/Exception/MissingAdapterException.php @@ -0,0 +1,50 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Exception; + +use Thelia\Log\Tlog; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Thrown when the Adapter is not set + * + * @package Coupon + * @author Guillaume MOREL + * + */ +class MissingAdapterException extends \RuntimeException +{ + /** + * {@inheritdoc} + */ + public function __construct($message, $code = null, $previous = null) { + + Tlog::getInstance()->addError($message); + + parent::__construct($message, $code, $previous); + } +} diff --git a/core/lib/Thelia/Exception/NotImplementedException.php b/core/lib/Thelia/Exception/NotImplementedException.php new file mode 100644 index 000000000..991f4d325 --- /dev/null +++ b/core/lib/Thelia/Exception/NotImplementedException.php @@ -0,0 +1,43 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Exception; + +use Symfony\Component\DependencyInjection\Exception\BadMethodCallException; +use Thelia\Log\Tlog; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Thrown when an Abstract method has not been implemented + * + * @package Exception + * @author Guillaume MOREL + * + */ +class NotImplementedException extends BadMethodCallException +{ + +} diff --git a/core/lib/Thelia/Exception/TaxEngineException.php b/core/lib/Thelia/Exception/TaxEngineException.php new file mode 100755 index 000000000..2a2718d4b --- /dev/null +++ b/core/lib/Thelia/Exception/TaxEngineException.php @@ -0,0 +1,44 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Exception; + +use Thelia\Log\Tlog; + +class TaxEngineException extends \RuntimeException +{ + const UNKNOWN_EXCEPTION = 0; + + const UNDEFINED_PRODUCT = 501; + const UNDEFINED_COUNTRY = 502; + const UNDEFINED_TAX_RULES_COLLECTION = 503; + + const BAD_AMOUNT_FORMAT = 601; + + public function __construct($message, $code = null, $previous = null) { + if($code === null) { + $code = self::UNKNOWN_EXCEPTION; + } + parent::__construct($message, $code, $previous); + } +} diff --git a/core/lib/Thelia/Form/BaseForm.php b/core/lib/Thelia/Form/BaseForm.php index 870f94505..f15dd7525 100755 --- a/core/lib/Thelia/Form/BaseForm.php +++ b/core/lib/Thelia/Form/BaseForm.php @@ -102,6 +102,10 @@ abstract class BaseForm $this->formBuilder->add("success_url", "text"); } + if (! $this->formBuilder->has('error_message')) { + $this->formBuilder->add("error_message", "text"); + } + $this->form = $this->formBuilder->getForm(); } @@ -141,6 +145,8 @@ abstract class BaseForm public function createView() { $this->view = $this->form->createView(); + + return $this; } public function getView() @@ -159,6 +165,8 @@ abstract class BaseForm public function setError($has_error = true) { $this->has_error = $has_error; + + return $this; } /** @@ -180,6 +188,8 @@ abstract class BaseForm { $this->setError(true); $this->error_message = $message; + + return $this; } /** diff --git a/core/lib/Thelia/Form/CategoryCreationForm.php b/core/lib/Thelia/Form/CategoryCreationForm.php index a125ad090..5dce6a049 100755 --- a/core/lib/Thelia/Form/CategoryCreationForm.php +++ b/core/lib/Thelia/Form/CategoryCreationForm.php @@ -23,6 +23,7 @@ namespace Thelia\Form; use Symfony\Component\Validator\Constraints\NotBlank; +use Thelia\Core\Translation\Translator; class CategoryCreationForm extends BaseForm { @@ -33,7 +34,7 @@ class CategoryCreationForm extends BaseForm "constraints" => array( new NotBlank() ), - "label" => "Category title *", + "label" => Translator::getInstance()->trans("Category title *"), "label_attr" => array( "for" => "title" ) diff --git a/core/lib/Thelia/Form/CategoryModificationForm.php b/core/lib/Thelia/Form/CategoryModificationForm.php new file mode 100644 index 000000000..a27389324 --- /dev/null +++ b/core/lib/Thelia/Form/CategoryModificationForm.php @@ -0,0 +1,55 @@ +. */ +/* */ +/*************************************************************************************/ +namespace Thelia\Form; + +use Symfony\Component\Validator\Constraints\NotBlank; +use Thelia\Model\LangQuery; +use Propel\Runtime\ActiveQuery\Criteria; +use Symfony\Component\Validator\Constraints\GreaterThan; +use Thelia\Core\Translation\Translator; + +class CategoryModificationForm extends CategoryCreationForm +{ + use StandardDescriptionFieldsTrait; + + protected function buildForm() + { + parent::buildForm(true); + + $this->formBuilder + ->add("id", "hidden", array("constraints" => array(new GreaterThan(array('value' => 0))))) + + ->add("visible", "checkbox", array( + "label" => Translator::getInstance()->trans("This category is online on the front office.") + )) + ; + + // Add standard description fields + $this->addStandardDescFields(array('title', 'locale')); + } + + public function getName() + { + return "thelia_category_modification"; + } +} \ No newline at end of file diff --git a/core/lib/Thelia/Form/ConfigModificationForm.php b/core/lib/Thelia/Form/ConfigModificationForm.php index 295c0403d..ce508137f 100644 --- a/core/lib/Thelia/Form/ConfigModificationForm.php +++ b/core/lib/Thelia/Form/ConfigModificationForm.php @@ -27,12 +27,12 @@ use Thelia\Model\LangQuery; use Propel\Runtime\ActiveQuery\Criteria; use Symfony\Component\Validator\Constraints\GreaterThan; -class ConfigModificationForm extends BaseDescForm +class ConfigModificationForm extends BaseForm { + use StandardDescriptionFieldsTrait; + protected function buildForm() { - parent::buildForm(true); - $this->formBuilder ->add("id", "hidden", array( "constraints" => array( @@ -61,6 +61,9 @@ class ConfigModificationForm extends BaseDescForm "label" => "Prevent variable modification or deletion, except for super-admin" )) ; + + // Add standard description fields + $this->addStandardDescFields(); } public function getName() diff --git a/core/lib/Thelia/Form/CouponCreationForm.php b/core/lib/Thelia/Form/CouponCreationForm.php new file mode 100755 index 000000000..4761bb28f --- /dev/null +++ b/core/lib/Thelia/Form/CouponCreationForm.php @@ -0,0 +1,160 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Form; + +use Symfony\Component\Validator\Constraints\NotBlank; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/29/13 + * Time: 3:45 PM + * + * Allow to build a form Coupon + * + * @package Coupon + * @author Guillaume MOREL + * + */ +class CouponCreationForm extends BaseForm +{ + /** + * Build Coupon form + * + * @return void + */ + protected function buildForm() + { + $this->formBuilder + ->add( + 'code', + 'text', + array( + 'constraints' => array( + new NotBlank() + ) + ) + ) + ->add( + 'title', + 'text', + array( + 'constraints' => array( + new NotBlank() + ) + ) + ) + ->add( + 'shortDescription', + 'text', + array( + 'invalid_message' => 'test', + 'constraints' => array( + new NotBlank() + ) + ) + ) + ->add( + 'description', + 'textarea', + array( + 'invalid_message' => 'test', + 'constraints' => array( + new NotBlank() + ) + ) + ) + ->add( + 'effect', + 'text', + array( + 'invalid_message' => 'test', + 'constraints' => array( + new NotBlank() + ) + ) + ) + ->add( + 'amount', + 'money', + array() + ) + ->add( + 'isEnabled', + 'checkbox', + array() + ) + ->add( + 'expirationDate', + 'text', + array( + 'constraints' => array( + new NotBlank() + ) + ) + ) + ->add( + 'isCumulative', + 'checkbox', + array() + ) + ->add( + 'isRemovingPostage', + 'checkbox', + array() + ) + ->add( + 'isAvailableOnSpecialOffers', + 'checkbox', + array() + ) + ->add( + 'maxUsage', + 'text', + array( + 'constraints' => array( + new NotBlank() + ) + ) + ) + ->add( + 'locale', + 'hidden', + array( + 'constraints' => array( + new NotBlank() + ) + ) + ); + } + + /** + * Get form name + * + * @return string + */ + public function getName() + { + return 'thelia_coupon_creation'; + } +} diff --git a/core/lib/Thelia/Form/CustomerLogin.php b/core/lib/Thelia/Form/CustomerLogin.php index 12b5a2775..3081ceed7 100755 --- a/core/lib/Thelia/Form/CustomerLogin.php +++ b/core/lib/Thelia/Form/CustomerLogin.php @@ -22,24 +22,38 @@ /*************************************************************************************/ namespace Thelia\Form; +use Symfony\Component\Validator\Constraints\Callback; use Symfony\Component\Validator\Constraints\NotBlank; use Symfony\Component\Validator\Constraints\Email; +use Symfony\Component\Validator\ExecutionContextInterface; +use Thelia\Core\Translation\Translator; +use Thelia\Model\CustomerQuery; class CustomerLogin extends BaseForm { protected function buildForm() { $this->formBuilder - ->add("email", "text", array( + ->add("email", "email", array( "constraints" => array( new NotBlank(), new Email() - ) + ), + "label" => Translator::getInstance()->trans("Please enter your email address"), + "label_attr" => array( + "for" => "email" + ), + "required" => true )) ->add("password", "password", array( "constraints" => array( new NotBlank() - ) + ), + "label" => Translator::getInstance()->trans("Please enter your password"), + "label_attr" => array( + "for" => "password" + ), + "required" => true )) ->add("remember_me", "checkbox") ; @@ -49,4 +63,5 @@ class CustomerLogin extends BaseForm { return "thelia_customer_login"; } + } diff --git a/core/lib/Thelia/Form/BaseDescForm.php b/core/lib/Thelia/Form/ProductCreationForm.php similarity index 67% rename from core/lib/Thelia/Form/BaseDescForm.php rename to core/lib/Thelia/Form/ProductCreationForm.php index 2b35f3e6e..396f6d0d5 100644 --- a/core/lib/Thelia/Form/BaseDescForm.php +++ b/core/lib/Thelia/Form/ProductCreationForm.php @@ -24,50 +24,44 @@ namespace Thelia\Form; use Symfony\Component\Validator\Constraints\NotBlank; -/** - * A base form for all objects with standard contents. - * - * @author Franck Allimant - */ -abstract class BaseDescForm extends BaseForm +class ProductCreationForm extends BaseForm { protected function buildForm() { $this->formBuilder - ->add("locale", "hidden", array( - "constraints" => array( - new NotBlank() - ) + ->add("ref", "text", array( + "constraints" => array( + new NotBlank() + ), + "label" => "Product reference *", + "label_attr" => array( + "for" => "ref" ) - ) + )) ->add("title", "text", array( - "constraints" => array( - new NotBlank() - ), - "label" => "Title", - "label_attr" => array( - "for" => "title" - ) - ) - ) - ->add("chapo", "text", array( - "label" => "Summary", + "constraints" => array( + new NotBlank() + ), + "label" => "Product title *", "label_attr" => array( - "for" => "summary" + "for" => "title" ) )) - ->add("description", "text", array( - "label" => "Detailed description", - "label_attr" => array( - "for" => "detailed_description" + ->add("parent", "integer", array( + "constraints" => array( + new NotBlank() ) )) - ->add("postscriptum", "text", array( - "label" => "Conclusion", - "label_attr" => array( - "for" => "conclusion" + ->add("locale", "text", array( + "constraints" => array( + new NotBlank() ) )) ; - } -} \ No newline at end of file + } + + public function getName() + { + return "thelia_product_creation"; + } +} diff --git a/core/lib/Thelia/Form/StandardDescriptionFieldsTrait.php b/core/lib/Thelia/Form/StandardDescriptionFieldsTrait.php new file mode 100644 index 000000000..7c0a51a31 --- /dev/null +++ b/core/lib/Thelia/Form/StandardDescriptionFieldsTrait.php @@ -0,0 +1,92 @@ +. */ +/* */ +/*************************************************************************************/ +namespace Thelia\Form; + +use Symfony\Component\Validator\Constraints\NotBlank; + +use Thelia\Core\Translation\Translator; + +/** + * A trait to add standard localized description fields to a form. + * + * @author Franck Allimant + */ +trait StandardDescriptionFieldsTrait +{ + /** + * Add standard description fields + locale tot the form + * + * @param array $exclude name of the fields that should not be added to the form + */ + protected function addStandardDescFields($exclude = array()) + { + if (! in_array('locale', $exclude)) + $this->formBuilder + ->add("locale", "hidden", array( + "constraints" => array( + new NotBlank() + ) + ) + ); + + if (! in_array('title', $exclude)) + $this->formBuilder + ->add("title", "text", array( + "constraints" => array( + new NotBlank() + ), + "label" => Translator::getInstance()->trans("Title"), + "label_attr" => array( + "for" => "title" + ) + ) + ); + + if (! in_array('chapo', $exclude)) + $this->formBuilder + ->add("chapo", "text", array( + "label" => Translator::getInstance()->trans("Summary"), + "label_attr" => array( + "for" => "summary" + ) + )); + + if (! in_array('description', $exclude)) + $this->formBuilder + ->add("description", "text", array( + "label" => Translator::getInstance()->trans("Detailed description"), + "label_attr" => array( + "for" => "detailed_description" + ) + )); + + if (! in_array('postscriptum', $exclude)) + $this->formBuilder + ->add("postscriptum", "text", array( + "label" => Translator::getInstance()->trans("Conclusion"), + "label_attr" => array( + "for" => "conclusion" + ) + )); + } +} \ No newline at end of file diff --git a/core/lib/Thelia/Model/Base/Accessory.php b/core/lib/Thelia/Model/Base/Accessory.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/AccessoryQuery.php b/core/lib/Thelia/Model/Base/AccessoryQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/Address.php b/core/lib/Thelia/Model/Base/Address.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/AddressQuery.php b/core/lib/Thelia/Model/Base/AddressQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/Admin.php b/core/lib/Thelia/Model/Base/Admin.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/AdminGroup.php b/core/lib/Thelia/Model/Base/AdminGroup.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/AdminGroupQuery.php b/core/lib/Thelia/Model/Base/AdminGroupQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/AdminLog.php b/core/lib/Thelia/Model/Base/AdminLog.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/AdminLogQuery.php b/core/lib/Thelia/Model/Base/AdminLogQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/AdminQuery.php b/core/lib/Thelia/Model/Base/AdminQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/Area.php b/core/lib/Thelia/Model/Base/Area.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/AreaQuery.php b/core/lib/Thelia/Model/Base/AreaQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/Attribute.php b/core/lib/Thelia/Model/Base/Attribute.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/AttributeAv.php b/core/lib/Thelia/Model/Base/AttributeAv.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/AttributeAvI18n.php b/core/lib/Thelia/Model/Base/AttributeAvI18n.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/AttributeAvI18nQuery.php b/core/lib/Thelia/Model/Base/AttributeAvI18nQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/AttributeAvQuery.php b/core/lib/Thelia/Model/Base/AttributeAvQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/AttributeCategory.php b/core/lib/Thelia/Model/Base/AttributeCategory.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/AttributeCategoryQuery.php b/core/lib/Thelia/Model/Base/AttributeCategoryQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/AttributeCombination.php b/core/lib/Thelia/Model/Base/AttributeCombination.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/AttributeCombinationQuery.php b/core/lib/Thelia/Model/Base/AttributeCombinationQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/AttributeI18n.php b/core/lib/Thelia/Model/Base/AttributeI18n.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/AttributeI18nQuery.php b/core/lib/Thelia/Model/Base/AttributeI18nQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/AttributeQuery.php b/core/lib/Thelia/Model/Base/AttributeQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/Cart.php b/core/lib/Thelia/Model/Base/Cart.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/CartItem.php b/core/lib/Thelia/Model/Base/CartItem.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/CartItemQuery.php b/core/lib/Thelia/Model/Base/CartItemQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/CartQuery.php b/core/lib/Thelia/Model/Base/CartQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/Category.php b/core/lib/Thelia/Model/Base/Category.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/CategoryDocument.php b/core/lib/Thelia/Model/Base/CategoryDocument.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/CategoryDocumentI18n.php b/core/lib/Thelia/Model/Base/CategoryDocumentI18n.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/CategoryDocumentI18nQuery.php b/core/lib/Thelia/Model/Base/CategoryDocumentI18nQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/CategoryDocumentQuery.php b/core/lib/Thelia/Model/Base/CategoryDocumentQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/CategoryI18n.php b/core/lib/Thelia/Model/Base/CategoryI18n.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/CategoryI18nQuery.php b/core/lib/Thelia/Model/Base/CategoryI18nQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/CategoryImage.php b/core/lib/Thelia/Model/Base/CategoryImage.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/CategoryImageI18n.php b/core/lib/Thelia/Model/Base/CategoryImageI18n.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/CategoryImageI18nQuery.php b/core/lib/Thelia/Model/Base/CategoryImageI18nQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/CategoryImageQuery.php b/core/lib/Thelia/Model/Base/CategoryImageQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/CategoryQuery.php b/core/lib/Thelia/Model/Base/CategoryQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/CategoryVersion.php b/core/lib/Thelia/Model/Base/CategoryVersion.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/CategoryVersionQuery.php b/core/lib/Thelia/Model/Base/CategoryVersionQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/Config.php b/core/lib/Thelia/Model/Base/Config.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/ConfigI18n.php b/core/lib/Thelia/Model/Base/ConfigI18n.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/ConfigI18nQuery.php b/core/lib/Thelia/Model/Base/ConfigI18nQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/ConfigQuery.php b/core/lib/Thelia/Model/Base/ConfigQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/Content.php b/core/lib/Thelia/Model/Base/Content.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/ContentDocument.php b/core/lib/Thelia/Model/Base/ContentDocument.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/ContentDocumentI18n.php b/core/lib/Thelia/Model/Base/ContentDocumentI18n.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/ContentDocumentI18nQuery.php b/core/lib/Thelia/Model/Base/ContentDocumentI18nQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/ContentDocumentQuery.php b/core/lib/Thelia/Model/Base/ContentDocumentQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/ContentFolder.php b/core/lib/Thelia/Model/Base/ContentFolder.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/ContentFolderQuery.php b/core/lib/Thelia/Model/Base/ContentFolderQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/ContentI18n.php b/core/lib/Thelia/Model/Base/ContentI18n.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/ContentI18nQuery.php b/core/lib/Thelia/Model/Base/ContentI18nQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/ContentImage.php b/core/lib/Thelia/Model/Base/ContentImage.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/ContentImageI18n.php b/core/lib/Thelia/Model/Base/ContentImageI18n.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/ContentImageI18nQuery.php b/core/lib/Thelia/Model/Base/ContentImageI18nQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/ContentImageQuery.php b/core/lib/Thelia/Model/Base/ContentImageQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/ContentQuery.php b/core/lib/Thelia/Model/Base/ContentQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/ContentVersion.php b/core/lib/Thelia/Model/Base/ContentVersion.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/ContentVersionQuery.php b/core/lib/Thelia/Model/Base/ContentVersionQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/Country.php b/core/lib/Thelia/Model/Base/Country.php old mode 100755 new mode 100644 index e0541a151..90fd48880 --- a/core/lib/Thelia/Model/Base/Country.php +++ b/core/lib/Thelia/Model/Base/Country.php @@ -1631,7 +1631,10 @@ abstract class Country implements ActiveRecordInterface $taxRuleCountriesToDelete = $this->getTaxRuleCountries(new Criteria(), $con)->diff($taxRuleCountries); - $this->taxRuleCountriesScheduledForDeletion = $taxRuleCountriesToDelete; + //since at least one column in the foreign key is at the same time a PK + //we can not just set a PK to NULL in the lines below. We have to store + //a backup of all values, so we are able to manipulate these items based on the onDelete value later. + $this->taxRuleCountriesScheduledForDeletion = clone $taxRuleCountriesToDelete; foreach ($taxRuleCountriesToDelete as $taxRuleCountryRemoved) { $taxRuleCountryRemoved->setCountry(null); @@ -1724,7 +1727,7 @@ abstract class Country implements ActiveRecordInterface $this->taxRuleCountriesScheduledForDeletion = clone $this->collTaxRuleCountries; $this->taxRuleCountriesScheduledForDeletion->clear(); } - $this->taxRuleCountriesScheduledForDeletion[]= $taxRuleCountry; + $this->taxRuleCountriesScheduledForDeletion[]= clone $taxRuleCountry; $taxRuleCountry->setCountry(null); } diff --git a/core/lib/Thelia/Model/Base/CountryI18n.php b/core/lib/Thelia/Model/Base/CountryI18n.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/CountryI18nQuery.php b/core/lib/Thelia/Model/Base/CountryI18nQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/CountryQuery.php b/core/lib/Thelia/Model/Base/CountryQuery.php old mode 100755 new mode 100644 index 6c3a1c950..1e565e9c0 --- a/core/lib/Thelia/Model/Base/CountryQuery.php +++ b/core/lib/Thelia/Model/Base/CountryQuery.php @@ -616,7 +616,7 @@ abstract class CountryQuery extends ModelCriteria * * @return ChildCountryQuery The current query, for fluid interface */ - public function joinTaxRuleCountry($relationAlias = null, $joinType = Criteria::LEFT_JOIN) + public function joinTaxRuleCountry($relationAlias = null, $joinType = Criteria::INNER_JOIN) { $tableMap = $this->getTableMap(); $relationMap = $tableMap->getRelation('TaxRuleCountry'); @@ -651,7 +651,7 @@ abstract class CountryQuery extends ModelCriteria * * @return \Thelia\Model\TaxRuleCountryQuery A secondary query class using the current class as primary query */ - public function useTaxRuleCountryQuery($relationAlias = null, $joinType = Criteria::LEFT_JOIN) + public function useTaxRuleCountryQuery($relationAlias = null, $joinType = Criteria::INNER_JOIN) { return $this ->joinTaxRuleCountry($relationAlias, $joinType) diff --git a/core/lib/Thelia/Model/Base/Coupon.php b/core/lib/Thelia/Model/Base/Coupon.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/CouponOrder.php b/core/lib/Thelia/Model/Base/CouponOrder.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/CouponOrderQuery.php b/core/lib/Thelia/Model/Base/CouponOrderQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/CouponQuery.php b/core/lib/Thelia/Model/Base/CouponQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/CouponRule.php b/core/lib/Thelia/Model/Base/CouponRule.php deleted file mode 100755 index 8a34f5d0b..000000000 --- a/core/lib/Thelia/Model/Base/CouponRule.php +++ /dev/null @@ -1,1534 +0,0 @@ -modifiedColumns); - } - - /** - * Has specified column been modified? - * - * @param string $col column fully qualified name (TableMap::TYPE_COLNAME), e.g. Book::AUTHOR_ID - * @return boolean True if $col has been modified. - */ - public function isColumnModified($col) - { - return in_array($col, $this->modifiedColumns); - } - - /** - * Get the columns that have been modified in this object. - * @return array A unique list of the modified column names for this object. - */ - public function getModifiedColumns() - { - return array_unique($this->modifiedColumns); - } - - /** - * Returns whether the object has ever been saved. This will - * be false, if the object was retrieved from storage or was created - * and then saved. - * - * @return true, if the object has never been persisted. - */ - public function isNew() - { - return $this->new; - } - - /** - * Setter for the isNew attribute. This method will be called - * by Propel-generated children and objects. - * - * @param boolean $b the state of the object. - */ - public function setNew($b) - { - $this->new = (Boolean) $b; - } - - /** - * Whether this object has been deleted. - * @return boolean The deleted state of this object. - */ - public function isDeleted() - { - return $this->deleted; - } - - /** - * Specify whether this object has been deleted. - * @param boolean $b The deleted state of this object. - * @return void - */ - public function setDeleted($b) - { - $this->deleted = (Boolean) $b; - } - - /** - * Sets the modified state for the object to be false. - * @param string $col If supplied, only the specified column is reset. - * @return void - */ - public function resetModified($col = null) - { - if (null !== $col) { - while (false !== ($offset = array_search($col, $this->modifiedColumns))) { - array_splice($this->modifiedColumns, $offset, 1); - } - } else { - $this->modifiedColumns = array(); - } - } - - /** - * Compares this with another CouponRule instance. If - * obj is an instance of CouponRule, delegates to - * equals(CouponRule). Otherwise, returns false. - * - * @param obj The object to compare to. - * @return Whether equal to the object specified. - */ - public function equals($obj) - { - $thisclazz = get_class($this); - if (!is_object($obj) || !($obj instanceof $thisclazz)) { - return false; - } - - if ($this === $obj) { - return true; - } - - if (null === $this->getPrimaryKey() - || null === $obj->getPrimaryKey()) { - return false; - } - - return $this->getPrimaryKey() === $obj->getPrimaryKey(); - } - - /** - * If the primary key is not null, return the hashcode of the - * primary key. Otherwise, return the hash code of the object. - * - * @return int Hashcode - */ - public function hashCode() - { - if (null !== $this->getPrimaryKey()) { - return crc32(serialize($this->getPrimaryKey())); - } - - return crc32(serialize(clone $this)); - } - - /** - * Get the associative array of the virtual columns in this object - * - * @param string $name The virtual column name - * - * @return array - */ - public function getVirtualColumns() - { - return $this->virtualColumns; - } - - /** - * Checks the existence of a virtual column in this object - * - * @return boolean - */ - public function hasVirtualColumn($name) - { - return array_key_exists($name, $this->virtualColumns); - } - - /** - * Get the value of a virtual column in this object - * - * @return mixed - */ - public function getVirtualColumn($name) - { - if (!$this->hasVirtualColumn($name)) { - throw new PropelException(sprintf('Cannot get value of inexistent virtual column %s.', $name)); - } - - return $this->virtualColumns[$name]; - } - - /** - * Set the value of a virtual column in this object - * - * @param string $name The virtual column name - * @param mixed $value The value to give to the virtual column - * - * @return CouponRule The current object, for fluid interface - */ - public function setVirtualColumn($name, $value) - { - $this->virtualColumns[$name] = $value; - - return $this; - } - - /** - * Logs a message using Propel::log(). - * - * @param string $msg - * @param int $priority One of the Propel::LOG_* logging levels - * @return boolean - */ - protected function log($msg, $priority = Propel::LOG_INFO) - { - return Propel::log(get_class($this) . ': ' . $msg, $priority); - } - - /** - * Populate the current object from a string, using a given parser format - * - * $book = new Book(); - * $book->importFrom('JSON', '{"Id":9012,"Title":"Don Juan","ISBN":"0140422161","Price":12.99,"PublisherId":1234,"AuthorId":5678}'); - * - * - * @param mixed $parser A AbstractParser instance, - * or a format name ('XML', 'YAML', 'JSON', 'CSV') - * @param string $data The source data to import from - * - * @return CouponRule The current object, for fluid interface - */ - public function importFrom($parser, $data) - { - if (!$parser instanceof AbstractParser) { - $parser = AbstractParser::getParser($parser); - } - - return $this->fromArray($parser->toArray($data), TableMap::TYPE_PHPNAME); - } - - /** - * Export the current object properties to a string, using a given parser format - * - * $book = BookQuery::create()->findPk(9012); - * echo $book->exportTo('JSON'); - * => {"Id":9012,"Title":"Don Juan","ISBN":"0140422161","Price":12.99,"PublisherId":1234,"AuthorId":5678}'); - * - * - * @param mixed $parser A AbstractParser instance, or a format name ('XML', 'YAML', 'JSON', 'CSV') - * @param boolean $includeLazyLoadColumns (optional) Whether to include lazy load(ed) columns. Defaults to TRUE. - * @return string The exported data - */ - public function exportTo($parser, $includeLazyLoadColumns = true) - { - if (!$parser instanceof AbstractParser) { - $parser = AbstractParser::getParser($parser); - } - - return $parser->fromArray($this->toArray(TableMap::TYPE_PHPNAME, $includeLazyLoadColumns, array(), true)); - } - - /** - * Clean up internal collections prior to serializing - * Avoids recursive loops that turn into segmentation faults when serializing - */ - public function __sleep() - { - $this->clearAllReferences(); - - return array_keys(get_object_vars($this)); - } - - /** - * Get the [id] column value. - * - * @return int - */ - public function getId() - { - - return $this->id; - } - - /** - * Get the [coupon_id] column value. - * - * @return int - */ - public function getCouponId() - { - - return $this->coupon_id; - } - - /** - * Get the [controller] column value. - * - * @return string - */ - public function getController() - { - - return $this->controller; - } - - /** - * Get the [operation] column value. - * - * @return string - */ - public function getOperation() - { - - return $this->operation; - } - - /** - * Get the [value] column value. - * - * @return double - */ - public function getValue() - { - - return $this->value; - } - - /** - * Get the [optionally formatted] temporal [created_at] column value. - * - * - * @param string $format The date/time format string (either date()-style or strftime()-style). - * If format is NULL, then the raw \DateTime object will be returned. - * - * @return mixed Formatted date/time value as string or \DateTime object (if format is NULL), NULL if column is NULL, and 0 if column value is 0000-00-00 00:00:00 - * - * @throws PropelException - if unable to parse/validate the date/time value. - */ - public function getCreatedAt($format = NULL) - { - if ($format === null) { - return $this->created_at; - } else { - return $this->created_at !== null ? $this->created_at->format($format) : null; - } - } - - /** - * Get the [optionally formatted] temporal [updated_at] column value. - * - * - * @param string $format The date/time format string (either date()-style or strftime()-style). - * If format is NULL, then the raw \DateTime object will be returned. - * - * @return mixed Formatted date/time value as string or \DateTime object (if format is NULL), NULL if column is NULL, and 0 if column value is 0000-00-00 00:00:00 - * - * @throws PropelException - if unable to parse/validate the date/time value. - */ - public function getUpdatedAt($format = NULL) - { - if ($format === null) { - return $this->updated_at; - } else { - return $this->updated_at !== null ? $this->updated_at->format($format) : null; - } - } - - /** - * Set the value of [id] column. - * - * @param int $v new value - * @return \Thelia\Model\CouponRule The current object (for fluent API support) - */ - public function setId($v) - { - if ($v !== null) { - $v = (int) $v; - } - - if ($this->id !== $v) { - $this->id = $v; - $this->modifiedColumns[] = CouponRuleTableMap::ID; - } - - - return $this; - } // setId() - - /** - * Set the value of [coupon_id] column. - * - * @param int $v new value - * @return \Thelia\Model\CouponRule The current object (for fluent API support) - */ - public function setCouponId($v) - { - if ($v !== null) { - $v = (int) $v; - } - - if ($this->coupon_id !== $v) { - $this->coupon_id = $v; - $this->modifiedColumns[] = CouponRuleTableMap::COUPON_ID; - } - - if ($this->aCoupon !== null && $this->aCoupon->getId() !== $v) { - $this->aCoupon = null; - } - - - return $this; - } // setCouponId() - - /** - * Set the value of [controller] column. - * - * @param string $v new value - * @return \Thelia\Model\CouponRule The current object (for fluent API support) - */ - public function setController($v) - { - if ($v !== null) { - $v = (string) $v; - } - - if ($this->controller !== $v) { - $this->controller = $v; - $this->modifiedColumns[] = CouponRuleTableMap::CONTROLLER; - } - - - return $this; - } // setController() - - /** - * Set the value of [operation] column. - * - * @param string $v new value - * @return \Thelia\Model\CouponRule The current object (for fluent API support) - */ - public function setOperation($v) - { - if ($v !== null) { - $v = (string) $v; - } - - if ($this->operation !== $v) { - $this->operation = $v; - $this->modifiedColumns[] = CouponRuleTableMap::OPERATION; - } - - - return $this; - } // setOperation() - - /** - * Set the value of [value] column. - * - * @param double $v new value - * @return \Thelia\Model\CouponRule The current object (for fluent API support) - */ - public function setValue($v) - { - if ($v !== null) { - $v = (double) $v; - } - - if ($this->value !== $v) { - $this->value = $v; - $this->modifiedColumns[] = CouponRuleTableMap::VALUE; - } - - - return $this; - } // setValue() - - /** - * Sets the value of [created_at] column to a normalized version of the date/time value specified. - * - * @param mixed $v string, integer (timestamp), or \DateTime value. - * Empty strings are treated as NULL. - * @return \Thelia\Model\CouponRule The current object (for fluent API support) - */ - public function setCreatedAt($v) - { - $dt = PropelDateTime::newInstance($v, null, '\DateTime'); - if ($this->created_at !== null || $dt !== null) { - if ($dt !== $this->created_at) { - $this->created_at = $dt; - $this->modifiedColumns[] = CouponRuleTableMap::CREATED_AT; - } - } // if either are not null - - - return $this; - } // setCreatedAt() - - /** - * Sets the value of [updated_at] column to a normalized version of the date/time value specified. - * - * @param mixed $v string, integer (timestamp), or \DateTime value. - * Empty strings are treated as NULL. - * @return \Thelia\Model\CouponRule The current object (for fluent API support) - */ - public function setUpdatedAt($v) - { - $dt = PropelDateTime::newInstance($v, null, '\DateTime'); - if ($this->updated_at !== null || $dt !== null) { - if ($dt !== $this->updated_at) { - $this->updated_at = $dt; - $this->modifiedColumns[] = CouponRuleTableMap::UPDATED_AT; - } - } // if either are not null - - - return $this; - } // setUpdatedAt() - - /** - * Indicates whether the columns in this object are only set to default values. - * - * This method can be used in conjunction with isModified() to indicate whether an object is both - * modified _and_ has some values set which are non-default. - * - * @return boolean Whether the columns in this object are only been set with default values. - */ - public function hasOnlyDefaultValues() - { - // otherwise, everything was equal, so return TRUE - return true; - } // hasOnlyDefaultValues() - - /** - * Hydrates (populates) the object variables with values from the database resultset. - * - * An offset (0-based "start column") is specified so that objects can be hydrated - * with a subset of the columns in the resultset rows. This is needed, for example, - * for results of JOIN queries where the resultset row includes columns from two or - * more tables. - * - * @param array $row The row returned by DataFetcher->fetch(). - * @param int $startcol 0-based offset column which indicates which restultset column to start with. - * @param boolean $rehydrate Whether this object is being re-hydrated from the database. - * @param string $indexType The index type of $row. Mostly DataFetcher->getIndexType(). - One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME - * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. - * - * @return int next starting column - * @throws PropelException - Any caught Exception will be rewrapped as a PropelException. - */ - public function hydrate($row, $startcol = 0, $rehydrate = false, $indexType = TableMap::TYPE_NUM) - { - try { - - - $col = $row[TableMap::TYPE_NUM == $indexType ? 0 + $startcol : CouponRuleTableMap::translateFieldName('Id', TableMap::TYPE_PHPNAME, $indexType)]; - $this->id = (null !== $col) ? (int) $col : null; - - $col = $row[TableMap::TYPE_NUM == $indexType ? 1 + $startcol : CouponRuleTableMap::translateFieldName('CouponId', TableMap::TYPE_PHPNAME, $indexType)]; - $this->coupon_id = (null !== $col) ? (int) $col : null; - - $col = $row[TableMap::TYPE_NUM == $indexType ? 2 + $startcol : CouponRuleTableMap::translateFieldName('Controller', TableMap::TYPE_PHPNAME, $indexType)]; - $this->controller = (null !== $col) ? (string) $col : null; - - $col = $row[TableMap::TYPE_NUM == $indexType ? 3 + $startcol : CouponRuleTableMap::translateFieldName('Operation', TableMap::TYPE_PHPNAME, $indexType)]; - $this->operation = (null !== $col) ? (string) $col : null; - - $col = $row[TableMap::TYPE_NUM == $indexType ? 4 + $startcol : CouponRuleTableMap::translateFieldName('Value', TableMap::TYPE_PHPNAME, $indexType)]; - $this->value = (null !== $col) ? (double) $col : null; - - $col = $row[TableMap::TYPE_NUM == $indexType ? 5 + $startcol : CouponRuleTableMap::translateFieldName('CreatedAt', TableMap::TYPE_PHPNAME, $indexType)]; - if ($col === '0000-00-00 00:00:00') { - $col = null; - } - $this->created_at = (null !== $col) ? PropelDateTime::newInstance($col, null, '\DateTime') : null; - - $col = $row[TableMap::TYPE_NUM == $indexType ? 6 + $startcol : CouponRuleTableMap::translateFieldName('UpdatedAt', TableMap::TYPE_PHPNAME, $indexType)]; - if ($col === '0000-00-00 00:00:00') { - $col = null; - } - $this->updated_at = (null !== $col) ? PropelDateTime::newInstance($col, null, '\DateTime') : null; - $this->resetModified(); - - $this->setNew(false); - - if ($rehydrate) { - $this->ensureConsistency(); - } - - return $startcol + 7; // 7 = CouponRuleTableMap::NUM_HYDRATE_COLUMNS. - - } catch (Exception $e) { - throw new PropelException("Error populating \Thelia\Model\CouponRule object", 0, $e); - } - } - - /** - * Checks and repairs the internal consistency of the object. - * - * This method is executed after an already-instantiated object is re-hydrated - * from the database. It exists to check any foreign keys to make sure that - * the objects related to the current object are correct based on foreign key. - * - * You can override this method in the stub class, but you should always invoke - * the base method from the overridden method (i.e. parent::ensureConsistency()), - * in case your model changes. - * - * @throws PropelException - */ - public function ensureConsistency() - { - if ($this->aCoupon !== null && $this->coupon_id !== $this->aCoupon->getId()) { - $this->aCoupon = null; - } - } // ensureConsistency - - /** - * Reloads this object from datastore based on primary key and (optionally) resets all associated objects. - * - * This will only work if the object has been saved and has a valid primary key set. - * - * @param boolean $deep (optional) Whether to also de-associated any related objects. - * @param ConnectionInterface $con (optional) The ConnectionInterface connection to use. - * @return void - * @throws PropelException - if this object is deleted, unsaved or doesn't have pk match in db - */ - public function reload($deep = false, ConnectionInterface $con = null) - { - if ($this->isDeleted()) { - throw new PropelException("Cannot reload a deleted object."); - } - - if ($this->isNew()) { - throw new PropelException("Cannot reload an unsaved object."); - } - - if ($con === null) { - $con = Propel::getServiceContainer()->getReadConnection(CouponRuleTableMap::DATABASE_NAME); - } - - // We don't need to alter the object instance pool; we're just modifying this instance - // already in the pool. - - $dataFetcher = ChildCouponRuleQuery::create(null, $this->buildPkeyCriteria())->setFormatter(ModelCriteria::FORMAT_STATEMENT)->find($con); - $row = $dataFetcher->fetch(); - $dataFetcher->close(); - if (!$row) { - throw new PropelException('Cannot find matching row in the database to reload object values.'); - } - $this->hydrate($row, 0, true, $dataFetcher->getIndexType()); // rehydrate - - if ($deep) { // also de-associate any related objects? - - $this->aCoupon = null; - } // if (deep) - } - - /** - * Removes this object from datastore and sets delete attribute. - * - * @param ConnectionInterface $con - * @return void - * @throws PropelException - * @see CouponRule::setDeleted() - * @see CouponRule::isDeleted() - */ - public function delete(ConnectionInterface $con = null) - { - if ($this->isDeleted()) { - throw new PropelException("This object has already been deleted."); - } - - if ($con === null) { - $con = Propel::getServiceContainer()->getWriteConnection(CouponRuleTableMap::DATABASE_NAME); - } - - $con->beginTransaction(); - try { - $deleteQuery = ChildCouponRuleQuery::create() - ->filterByPrimaryKey($this->getPrimaryKey()); - $ret = $this->preDelete($con); - if ($ret) { - $deleteQuery->delete($con); - $this->postDelete($con); - $con->commit(); - $this->setDeleted(true); - } else { - $con->commit(); - } - } catch (Exception $e) { - $con->rollBack(); - throw $e; - } - } - - /** - * Persists this object to the database. - * - * If the object is new, it inserts it; otherwise an update is performed. - * All modified related objects will also be persisted in the doSave() - * method. This method wraps all precipitate database operations in a - * single transaction. - * - * @param ConnectionInterface $con - * @return int The number of rows affected by this insert/update and any referring fk objects' save() operations. - * @throws PropelException - * @see doSave() - */ - public function save(ConnectionInterface $con = null) - { - if ($this->isDeleted()) { - throw new PropelException("You cannot save an object that has been deleted."); - } - - if ($con === null) { - $con = Propel::getServiceContainer()->getWriteConnection(CouponRuleTableMap::DATABASE_NAME); - } - - $con->beginTransaction(); - $isInsert = $this->isNew(); - try { - $ret = $this->preSave($con); - if ($isInsert) { - $ret = $ret && $this->preInsert($con); - // timestampable behavior - if (!$this->isColumnModified(CouponRuleTableMap::CREATED_AT)) { - $this->setCreatedAt(time()); - } - if (!$this->isColumnModified(CouponRuleTableMap::UPDATED_AT)) { - $this->setUpdatedAt(time()); - } - } else { - $ret = $ret && $this->preUpdate($con); - // timestampable behavior - if ($this->isModified() && !$this->isColumnModified(CouponRuleTableMap::UPDATED_AT)) { - $this->setUpdatedAt(time()); - } - } - if ($ret) { - $affectedRows = $this->doSave($con); - if ($isInsert) { - $this->postInsert($con); - } else { - $this->postUpdate($con); - } - $this->postSave($con); - CouponRuleTableMap::addInstanceToPool($this); - } else { - $affectedRows = 0; - } - $con->commit(); - - return $affectedRows; - } catch (Exception $e) { - $con->rollBack(); - throw $e; - } - } - - /** - * Performs the work of inserting or updating the row in the database. - * - * If the object is new, it inserts it; otherwise an update is performed. - * All related objects are also updated in this method. - * - * @param ConnectionInterface $con - * @return int The number of rows affected by this insert/update and any referring fk objects' save() operations. - * @throws PropelException - * @see save() - */ - protected function doSave(ConnectionInterface $con) - { - $affectedRows = 0; // initialize var to track total num of affected rows - if (!$this->alreadyInSave) { - $this->alreadyInSave = true; - - // We call the save method on the following object(s) if they - // were passed to this object by their corresponding set - // method. This object relates to these object(s) by a - // foreign key reference. - - if ($this->aCoupon !== null) { - if ($this->aCoupon->isModified() || $this->aCoupon->isNew()) { - $affectedRows += $this->aCoupon->save($con); - } - $this->setCoupon($this->aCoupon); - } - - if ($this->isNew() || $this->isModified()) { - // persist changes - if ($this->isNew()) { - $this->doInsert($con); - } else { - $this->doUpdate($con); - } - $affectedRows += 1; - $this->resetModified(); - } - - $this->alreadyInSave = false; - - } - - return $affectedRows; - } // doSave() - - /** - * Insert the row in the database. - * - * @param ConnectionInterface $con - * - * @throws PropelException - * @see doSave() - */ - protected function doInsert(ConnectionInterface $con) - { - $modifiedColumns = array(); - $index = 0; - - $this->modifiedColumns[] = CouponRuleTableMap::ID; - if (null !== $this->id) { - throw new PropelException('Cannot insert a value for auto-increment primary key (' . CouponRuleTableMap::ID . ')'); - } - - // check the columns in natural order for more readable SQL queries - if ($this->isColumnModified(CouponRuleTableMap::ID)) { - $modifiedColumns[':p' . $index++] = 'ID'; - } - if ($this->isColumnModified(CouponRuleTableMap::COUPON_ID)) { - $modifiedColumns[':p' . $index++] = 'COUPON_ID'; - } - if ($this->isColumnModified(CouponRuleTableMap::CONTROLLER)) { - $modifiedColumns[':p' . $index++] = 'CONTROLLER'; - } - if ($this->isColumnModified(CouponRuleTableMap::OPERATION)) { - $modifiedColumns[':p' . $index++] = 'OPERATION'; - } - if ($this->isColumnModified(CouponRuleTableMap::VALUE)) { - $modifiedColumns[':p' . $index++] = 'VALUE'; - } - if ($this->isColumnModified(CouponRuleTableMap::CREATED_AT)) { - $modifiedColumns[':p' . $index++] = 'CREATED_AT'; - } - if ($this->isColumnModified(CouponRuleTableMap::UPDATED_AT)) { - $modifiedColumns[':p' . $index++] = 'UPDATED_AT'; - } - - $sql = sprintf( - 'INSERT INTO coupon_rule (%s) VALUES (%s)', - implode(', ', $modifiedColumns), - implode(', ', array_keys($modifiedColumns)) - ); - - try { - $stmt = $con->prepare($sql); - foreach ($modifiedColumns as $identifier => $columnName) { - switch ($columnName) { - case 'ID': - $stmt->bindValue($identifier, $this->id, PDO::PARAM_INT); - break; - case 'COUPON_ID': - $stmt->bindValue($identifier, $this->coupon_id, PDO::PARAM_INT); - break; - case 'CONTROLLER': - $stmt->bindValue($identifier, $this->controller, PDO::PARAM_STR); - break; - case 'OPERATION': - $stmt->bindValue($identifier, $this->operation, PDO::PARAM_STR); - break; - case 'VALUE': - $stmt->bindValue($identifier, $this->value, PDO::PARAM_STR); - break; - case 'CREATED_AT': - $stmt->bindValue($identifier, $this->created_at ? $this->created_at->format("Y-m-d H:i:s") : null, PDO::PARAM_STR); - break; - case 'UPDATED_AT': - $stmt->bindValue($identifier, $this->updated_at ? $this->updated_at->format("Y-m-d H:i:s") : null, PDO::PARAM_STR); - break; - } - } - $stmt->execute(); - } catch (Exception $e) { - Propel::log($e->getMessage(), Propel::LOG_ERR); - throw new PropelException(sprintf('Unable to execute INSERT statement [%s]', $sql), 0, $e); - } - - try { - $pk = $con->lastInsertId(); - } catch (Exception $e) { - throw new PropelException('Unable to get autoincrement id.', 0, $e); - } - $this->setId($pk); - - $this->setNew(false); - } - - /** - * Update the row in the database. - * - * @param ConnectionInterface $con - * - * @return Integer Number of updated rows - * @see doSave() - */ - protected function doUpdate(ConnectionInterface $con) - { - $selectCriteria = $this->buildPkeyCriteria(); - $valuesCriteria = $this->buildCriteria(); - - return $selectCriteria->doUpdate($valuesCriteria, $con); - } - - /** - * Retrieves a field from the object by name passed in as a string. - * - * @param string $name name - * @param string $type The type of fieldname the $name is of: - * one of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME - * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. - * Defaults to TableMap::TYPE_PHPNAME. - * @return mixed Value of field. - */ - public function getByName($name, $type = TableMap::TYPE_PHPNAME) - { - $pos = CouponRuleTableMap::translateFieldName($name, $type, TableMap::TYPE_NUM); - $field = $this->getByPosition($pos); - - return $field; - } - - /** - * Retrieves a field from the object by Position as specified in the xml schema. - * Zero-based. - * - * @param int $pos position in xml schema - * @return mixed Value of field at $pos - */ - public function getByPosition($pos) - { - switch ($pos) { - case 0: - return $this->getId(); - break; - case 1: - return $this->getCouponId(); - break; - case 2: - return $this->getController(); - break; - case 3: - return $this->getOperation(); - break; - case 4: - return $this->getValue(); - break; - case 5: - return $this->getCreatedAt(); - break; - case 6: - return $this->getUpdatedAt(); - break; - default: - return null; - break; - } // switch() - } - - /** - * Exports the object as an array. - * - * You can specify the key type of the array by passing one of the class - * type constants. - * - * @param string $keyType (optional) One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME, - * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. - * Defaults to TableMap::TYPE_PHPNAME. - * @param boolean $includeLazyLoadColumns (optional) Whether to include lazy loaded columns. Defaults to TRUE. - * @param array $alreadyDumpedObjects List of objects to skip to avoid recursion - * @param boolean $includeForeignObjects (optional) Whether to include hydrated related objects. Default to FALSE. - * - * @return array an associative array containing the field names (as keys) and field values - */ - public function toArray($keyType = TableMap::TYPE_PHPNAME, $includeLazyLoadColumns = true, $alreadyDumpedObjects = array(), $includeForeignObjects = false) - { - if (isset($alreadyDumpedObjects['CouponRule'][$this->getPrimaryKey()])) { - return '*RECURSION*'; - } - $alreadyDumpedObjects['CouponRule'][$this->getPrimaryKey()] = true; - $keys = CouponRuleTableMap::getFieldNames($keyType); - $result = array( - $keys[0] => $this->getId(), - $keys[1] => $this->getCouponId(), - $keys[2] => $this->getController(), - $keys[3] => $this->getOperation(), - $keys[4] => $this->getValue(), - $keys[5] => $this->getCreatedAt(), - $keys[6] => $this->getUpdatedAt(), - ); - $virtualColumns = $this->virtualColumns; - foreach($virtualColumns as $key => $virtualColumn) - { - $result[$key] = $virtualColumn; - } - - if ($includeForeignObjects) { - if (null !== $this->aCoupon) { - $result['Coupon'] = $this->aCoupon->toArray($keyType, $includeLazyLoadColumns, $alreadyDumpedObjects, true); - } - } - - return $result; - } - - /** - * Sets a field from the object by name passed in as a string. - * - * @param string $name - * @param mixed $value field value - * @param string $type The type of fieldname the $name is of: - * one of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME - * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. - * Defaults to TableMap::TYPE_PHPNAME. - * @return void - */ - public function setByName($name, $value, $type = TableMap::TYPE_PHPNAME) - { - $pos = CouponRuleTableMap::translateFieldName($name, $type, TableMap::TYPE_NUM); - - return $this->setByPosition($pos, $value); - } - - /** - * Sets a field from the object by Position as specified in the xml schema. - * Zero-based. - * - * @param int $pos position in xml schema - * @param mixed $value field value - * @return void - */ - public function setByPosition($pos, $value) - { - switch ($pos) { - case 0: - $this->setId($value); - break; - case 1: - $this->setCouponId($value); - break; - case 2: - $this->setController($value); - break; - case 3: - $this->setOperation($value); - break; - case 4: - $this->setValue($value); - break; - case 5: - $this->setCreatedAt($value); - break; - case 6: - $this->setUpdatedAt($value); - break; - } // switch() - } - - /** - * Populates the object using an array. - * - * This is particularly useful when populating an object from one of the - * request arrays (e.g. $_POST). This method goes through the column - * names, checking to see whether a matching key exists in populated - * array. If so the setByName() method is called for that column. - * - * You can specify the key type of the array by additionally passing one - * of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME, - * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. - * The default key type is the column's TableMap::TYPE_PHPNAME. - * - * @param array $arr An array to populate the object from. - * @param string $keyType The type of keys the array uses. - * @return void - */ - public function fromArray($arr, $keyType = TableMap::TYPE_PHPNAME) - { - $keys = CouponRuleTableMap::getFieldNames($keyType); - - if (array_key_exists($keys[0], $arr)) $this->setId($arr[$keys[0]]); - if (array_key_exists($keys[1], $arr)) $this->setCouponId($arr[$keys[1]]); - if (array_key_exists($keys[2], $arr)) $this->setController($arr[$keys[2]]); - if (array_key_exists($keys[3], $arr)) $this->setOperation($arr[$keys[3]]); - if (array_key_exists($keys[4], $arr)) $this->setValue($arr[$keys[4]]); - if (array_key_exists($keys[5], $arr)) $this->setCreatedAt($arr[$keys[5]]); - if (array_key_exists($keys[6], $arr)) $this->setUpdatedAt($arr[$keys[6]]); - } - - /** - * Build a Criteria object containing the values of all modified columns in this object. - * - * @return Criteria The Criteria object containing all modified values. - */ - public function buildCriteria() - { - $criteria = new Criteria(CouponRuleTableMap::DATABASE_NAME); - - if ($this->isColumnModified(CouponRuleTableMap::ID)) $criteria->add(CouponRuleTableMap::ID, $this->id); - if ($this->isColumnModified(CouponRuleTableMap::COUPON_ID)) $criteria->add(CouponRuleTableMap::COUPON_ID, $this->coupon_id); - if ($this->isColumnModified(CouponRuleTableMap::CONTROLLER)) $criteria->add(CouponRuleTableMap::CONTROLLER, $this->controller); - if ($this->isColumnModified(CouponRuleTableMap::OPERATION)) $criteria->add(CouponRuleTableMap::OPERATION, $this->operation); - if ($this->isColumnModified(CouponRuleTableMap::VALUE)) $criteria->add(CouponRuleTableMap::VALUE, $this->value); - if ($this->isColumnModified(CouponRuleTableMap::CREATED_AT)) $criteria->add(CouponRuleTableMap::CREATED_AT, $this->created_at); - if ($this->isColumnModified(CouponRuleTableMap::UPDATED_AT)) $criteria->add(CouponRuleTableMap::UPDATED_AT, $this->updated_at); - - return $criteria; - } - - /** - * Builds a Criteria object containing the primary key for this object. - * - * Unlike buildCriteria() this method includes the primary key values regardless - * of whether or not they have been modified. - * - * @return Criteria The Criteria object containing value(s) for primary key(s). - */ - public function buildPkeyCriteria() - { - $criteria = new Criteria(CouponRuleTableMap::DATABASE_NAME); - $criteria->add(CouponRuleTableMap::ID, $this->id); - - return $criteria; - } - - /** - * Returns the primary key for this object (row). - * @return int - */ - public function getPrimaryKey() - { - return $this->getId(); - } - - /** - * Generic method to set the primary key (id column). - * - * @param int $key Primary key. - * @return void - */ - public function setPrimaryKey($key) - { - $this->setId($key); - } - - /** - * Returns true if the primary key for this object is null. - * @return boolean - */ - public function isPrimaryKeyNull() - { - - return null === $this->getId(); - } - - /** - * Sets contents of passed object to values from current object. - * - * If desired, this method can also make copies of all associated (fkey referrers) - * objects. - * - * @param object $copyObj An object of \Thelia\Model\CouponRule (or compatible) type. - * @param boolean $deepCopy Whether to also copy all rows that refer (by fkey) to the current row. - * @param boolean $makeNew Whether to reset autoincrement PKs and make the object new. - * @throws PropelException - */ - public function copyInto($copyObj, $deepCopy = false, $makeNew = true) - { - $copyObj->setCouponId($this->getCouponId()); - $copyObj->setController($this->getController()); - $copyObj->setOperation($this->getOperation()); - $copyObj->setValue($this->getValue()); - $copyObj->setCreatedAt($this->getCreatedAt()); - $copyObj->setUpdatedAt($this->getUpdatedAt()); - if ($makeNew) { - $copyObj->setNew(true); - $copyObj->setId(NULL); // this is a auto-increment column, so set to default value - } - } - - /** - * Makes a copy of this object that will be inserted as a new row in table when saved. - * It creates a new object filling in the simple attributes, but skipping any primary - * keys that are defined for the table. - * - * If desired, this method can also make copies of all associated (fkey referrers) - * objects. - * - * @param boolean $deepCopy Whether to also copy all rows that refer (by fkey) to the current row. - * @return \Thelia\Model\CouponRule Clone of current object. - * @throws PropelException - */ - public function copy($deepCopy = false) - { - // we use get_class(), because this might be a subclass - $clazz = get_class($this); - $copyObj = new $clazz(); - $this->copyInto($copyObj, $deepCopy); - - return $copyObj; - } - - /** - * Declares an association between this object and a ChildCoupon object. - * - * @param ChildCoupon $v - * @return \Thelia\Model\CouponRule The current object (for fluent API support) - * @throws PropelException - */ - public function setCoupon(ChildCoupon $v = null) - { - if ($v === null) { - $this->setCouponId(NULL); - } else { - $this->setCouponId($v->getId()); - } - - $this->aCoupon = $v; - - // Add binding for other direction of this n:n relationship. - // If this object has already been added to the ChildCoupon object, it will not be re-added. - if ($v !== null) { - $v->addCouponRule($this); - } - - - return $this; - } - - - /** - * Get the associated ChildCoupon object - * - * @param ConnectionInterface $con Optional Connection object. - * @return ChildCoupon The associated ChildCoupon object. - * @throws PropelException - */ - public function getCoupon(ConnectionInterface $con = null) - { - if ($this->aCoupon === null && ($this->coupon_id !== null)) { - $this->aCoupon = ChildCouponQuery::create()->findPk($this->coupon_id, $con); - /* The following can be used additionally to - guarantee the related object contains a reference - to this object. This level of coupling may, however, be - undesirable since it could result in an only partially populated collection - in the referenced object. - $this->aCoupon->addCouponRules($this); - */ - } - - return $this->aCoupon; - } - - /** - * Clears the current object and sets all attributes to their default values - */ - public function clear() - { - $this->id = null; - $this->coupon_id = null; - $this->controller = null; - $this->operation = null; - $this->value = null; - $this->created_at = null; - $this->updated_at = null; - $this->alreadyInSave = false; - $this->clearAllReferences(); - $this->resetModified(); - $this->setNew(true); - $this->setDeleted(false); - } - - /** - * Resets all references to other model objects or collections of model objects. - * - * This method is a user-space workaround for PHP's inability to garbage collect - * objects with circular references (even in PHP 5.3). This is currently necessary - * when using Propel in certain daemon or large-volume/high-memory operations. - * - * @param boolean $deep Whether to also clear the references on all referrer objects. - */ - public function clearAllReferences($deep = false) - { - if ($deep) { - } // if ($deep) - - $this->aCoupon = null; - } - - /** - * Return the string representation of this object - * - * @return string - */ - public function __toString() - { - return (string) $this->exportTo(CouponRuleTableMap::DEFAULT_STRING_FORMAT); - } - - // timestampable behavior - - /** - * Mark the current object so that the update date doesn't get updated during next save - * - * @return ChildCouponRule The current object (for fluent API support) - */ - public function keepUpdateDateUnchanged() - { - $this->modifiedColumns[] = CouponRuleTableMap::UPDATED_AT; - - return $this; - } - - /** - * Code to be run before persisting the object - * @param ConnectionInterface $con - * @return boolean - */ - public function preSave(ConnectionInterface $con = null) - { - return true; - } - - /** - * Code to be run after persisting the object - * @param ConnectionInterface $con - */ - public function postSave(ConnectionInterface $con = null) - { - - } - - /** - * Code to be run before inserting to database - * @param ConnectionInterface $con - * @return boolean - */ - public function preInsert(ConnectionInterface $con = null) - { - return true; - } - - /** - * Code to be run after inserting to database - * @param ConnectionInterface $con - */ - public function postInsert(ConnectionInterface $con = null) - { - - } - - /** - * Code to be run before updating the object in database - * @param ConnectionInterface $con - * @return boolean - */ - public function preUpdate(ConnectionInterface $con = null) - { - return true; - } - - /** - * Code to be run after updating the object in database - * @param ConnectionInterface $con - */ - public function postUpdate(ConnectionInterface $con = null) - { - - } - - /** - * Code to be run before deleting the object in database - * @param ConnectionInterface $con - * @return boolean - */ - public function preDelete(ConnectionInterface $con = null) - { - return true; - } - - /** - * Code to be run after deleting the object in database - * @param ConnectionInterface $con - */ - public function postDelete(ConnectionInterface $con = null) - { - - } - - - /** - * Derived method to catches calls to undefined methods. - * - * Provides magic import/export method support (fromXML()/toXML(), fromYAML()/toYAML(), etc.). - * Allows to define default __call() behavior if you overwrite __call() - * - * @param string $name - * @param mixed $params - * - * @return array|string - */ - public function __call($name, $params) - { - if (0 === strpos($name, 'get')) { - $virtualColumn = substr($name, 3); - if ($this->hasVirtualColumn($virtualColumn)) { - return $this->getVirtualColumn($virtualColumn); - } - - $virtualColumn = lcfirst($virtualColumn); - if ($this->hasVirtualColumn($virtualColumn)) { - return $this->getVirtualColumn($virtualColumn); - } - } - - if (0 === strpos($name, 'from')) { - $format = substr($name, 4); - - return $this->importFrom($format, reset($params)); - } - - if (0 === strpos($name, 'to')) { - $format = substr($name, 2); - $includeLazyLoadColumns = isset($params[0]) ? $params[0] : true; - - return $this->exportTo($format, $includeLazyLoadColumns); - } - - throw new BadMethodCallException(sprintf('Call to undefined method: %s.', $name)); - } - -} diff --git a/core/lib/Thelia/Model/Base/CouponRuleQuery.php b/core/lib/Thelia/Model/Base/CouponRuleQuery.php deleted file mode 100755 index 0789f84d6..000000000 --- a/core/lib/Thelia/Model/Base/CouponRuleQuery.php +++ /dev/null @@ -1,744 +0,0 @@ -setModelAlias($modelAlias); - } - if ($criteria instanceof Criteria) { - $query->mergeWith($criteria); - } - - return $query; - } - - /** - * Find object by primary key. - * Propel uses the instance pool to skip the database if the object exists. - * Go fast if the query is untouched. - * - * - * $obj = $c->findPk(12, $con); - * - * - * @param mixed $key Primary key to use for the query - * @param ConnectionInterface $con an optional connection object - * - * @return ChildCouponRule|array|mixed the result, formatted by the current formatter - */ - public function findPk($key, $con = null) - { - if ($key === null) { - return null; - } - if ((null !== ($obj = CouponRuleTableMap::getInstanceFromPool((string) $key))) && !$this->formatter) { - // the object is already in the instance pool - return $obj; - } - if ($con === null) { - $con = Propel::getServiceContainer()->getReadConnection(CouponRuleTableMap::DATABASE_NAME); - } - $this->basePreSelect($con); - if ($this->formatter || $this->modelAlias || $this->with || $this->select - || $this->selectColumns || $this->asColumns || $this->selectModifiers - || $this->map || $this->having || $this->joins) { - return $this->findPkComplex($key, $con); - } else { - return $this->findPkSimple($key, $con); - } - } - - /** - * Find object by primary key using raw SQL to go fast. - * Bypass doSelect() and the object formatter by using generated code. - * - * @param mixed $key Primary key to use for the query - * @param ConnectionInterface $con A connection object - * - * @return ChildCouponRule A model object, or null if the key is not found - */ - protected function findPkSimple($key, $con) - { - $sql = 'SELECT ID, COUPON_ID, CONTROLLER, OPERATION, VALUE, CREATED_AT, UPDATED_AT FROM coupon_rule WHERE ID = :p0'; - try { - $stmt = $con->prepare($sql); - $stmt->bindValue(':p0', $key, PDO::PARAM_INT); - $stmt->execute(); - } catch (Exception $e) { - Propel::log($e->getMessage(), Propel::LOG_ERR); - throw new PropelException(sprintf('Unable to execute SELECT statement [%s]', $sql), 0, $e); - } - $obj = null; - if ($row = $stmt->fetch(\PDO::FETCH_NUM)) { - $obj = new ChildCouponRule(); - $obj->hydrate($row); - CouponRuleTableMap::addInstanceToPool($obj, (string) $key); - } - $stmt->closeCursor(); - - return $obj; - } - - /** - * Find object by primary key. - * - * @param mixed $key Primary key to use for the query - * @param ConnectionInterface $con A connection object - * - * @return ChildCouponRule|array|mixed the result, formatted by the current formatter - */ - protected function findPkComplex($key, $con) - { - // As the query uses a PK condition, no limit(1) is necessary. - $criteria = $this->isKeepQuery() ? clone $this : $this; - $dataFetcher = $criteria - ->filterByPrimaryKey($key) - ->doSelect($con); - - return $criteria->getFormatter()->init($criteria)->formatOne($dataFetcher); - } - - /** - * Find objects by primary key - * - * $objs = $c->findPks(array(12, 56, 832), $con); - * - * @param array $keys Primary keys to use for the query - * @param ConnectionInterface $con an optional connection object - * - * @return ObjectCollection|array|mixed the list of results, formatted by the current formatter - */ - public function findPks($keys, $con = null) - { - if (null === $con) { - $con = Propel::getServiceContainer()->getReadConnection($this->getDbName()); - } - $this->basePreSelect($con); - $criteria = $this->isKeepQuery() ? clone $this : $this; - $dataFetcher = $criteria - ->filterByPrimaryKeys($keys) - ->doSelect($con); - - return $criteria->getFormatter()->init($criteria)->format($dataFetcher); - } - - /** - * Filter the query by primary key - * - * @param mixed $key Primary key to use for the query - * - * @return ChildCouponRuleQuery The current query, for fluid interface - */ - public function filterByPrimaryKey($key) - { - - return $this->addUsingAlias(CouponRuleTableMap::ID, $key, Criteria::EQUAL); - } - - /** - * Filter the query by a list of primary keys - * - * @param array $keys The list of primary key to use for the query - * - * @return ChildCouponRuleQuery The current query, for fluid interface - */ - public function filterByPrimaryKeys($keys) - { - - return $this->addUsingAlias(CouponRuleTableMap::ID, $keys, Criteria::IN); - } - - /** - * Filter the query on the id column - * - * Example usage: - * - * $query->filterById(1234); // WHERE id = 1234 - * $query->filterById(array(12, 34)); // WHERE id IN (12, 34) - * $query->filterById(array('min' => 12)); // WHERE id > 12 - * - * - * @param mixed $id The value to use as filter. - * Use scalar values for equality. - * Use array values for in_array() equivalent. - * Use associative array('min' => $minValue, 'max' => $maxValue) for intervals. - * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL - * - * @return ChildCouponRuleQuery The current query, for fluid interface - */ - public function filterById($id = null, $comparison = null) - { - if (is_array($id)) { - $useMinMax = false; - if (isset($id['min'])) { - $this->addUsingAlias(CouponRuleTableMap::ID, $id['min'], Criteria::GREATER_EQUAL); - $useMinMax = true; - } - if (isset($id['max'])) { - $this->addUsingAlias(CouponRuleTableMap::ID, $id['max'], Criteria::LESS_EQUAL); - $useMinMax = true; - } - if ($useMinMax) { - return $this; - } - if (null === $comparison) { - $comparison = Criteria::IN; - } - } - - return $this->addUsingAlias(CouponRuleTableMap::ID, $id, $comparison); - } - - /** - * Filter the query on the coupon_id column - * - * Example usage: - * - * $query->filterByCouponId(1234); // WHERE coupon_id = 1234 - * $query->filterByCouponId(array(12, 34)); // WHERE coupon_id IN (12, 34) - * $query->filterByCouponId(array('min' => 12)); // WHERE coupon_id > 12 - * - * - * @see filterByCoupon() - * - * @param mixed $couponId The value to use as filter. - * Use scalar values for equality. - * Use array values for in_array() equivalent. - * Use associative array('min' => $minValue, 'max' => $maxValue) for intervals. - * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL - * - * @return ChildCouponRuleQuery The current query, for fluid interface - */ - public function filterByCouponId($couponId = null, $comparison = null) - { - if (is_array($couponId)) { - $useMinMax = false; - if (isset($couponId['min'])) { - $this->addUsingAlias(CouponRuleTableMap::COUPON_ID, $couponId['min'], Criteria::GREATER_EQUAL); - $useMinMax = true; - } - if (isset($couponId['max'])) { - $this->addUsingAlias(CouponRuleTableMap::COUPON_ID, $couponId['max'], Criteria::LESS_EQUAL); - $useMinMax = true; - } - if ($useMinMax) { - return $this; - } - if (null === $comparison) { - $comparison = Criteria::IN; - } - } - - return $this->addUsingAlias(CouponRuleTableMap::COUPON_ID, $couponId, $comparison); - } - - /** - * Filter the query on the controller column - * - * Example usage: - * - * $query->filterByController('fooValue'); // WHERE controller = 'fooValue' - * $query->filterByController('%fooValue%'); // WHERE controller LIKE '%fooValue%' - * - * - * @param string $controller The value to use as filter. - * Accepts wildcards (* and % trigger a LIKE) - * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL - * - * @return ChildCouponRuleQuery The current query, for fluid interface - */ - public function filterByController($controller = null, $comparison = null) - { - if (null === $comparison) { - if (is_array($controller)) { - $comparison = Criteria::IN; - } elseif (preg_match('/[\%\*]/', $controller)) { - $controller = str_replace('*', '%', $controller); - $comparison = Criteria::LIKE; - } - } - - return $this->addUsingAlias(CouponRuleTableMap::CONTROLLER, $controller, $comparison); - } - - /** - * Filter the query on the operation column - * - * Example usage: - * - * $query->filterByOperation('fooValue'); // WHERE operation = 'fooValue' - * $query->filterByOperation('%fooValue%'); // WHERE operation LIKE '%fooValue%' - * - * - * @param string $operation The value to use as filter. - * Accepts wildcards (* and % trigger a LIKE) - * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL - * - * @return ChildCouponRuleQuery The current query, for fluid interface - */ - public function filterByOperation($operation = null, $comparison = null) - { - if (null === $comparison) { - if (is_array($operation)) { - $comparison = Criteria::IN; - } elseif (preg_match('/[\%\*]/', $operation)) { - $operation = str_replace('*', '%', $operation); - $comparison = Criteria::LIKE; - } - } - - return $this->addUsingAlias(CouponRuleTableMap::OPERATION, $operation, $comparison); - } - - /** - * Filter the query on the value column - * - * Example usage: - * - * $query->filterByValue(1234); // WHERE value = 1234 - * $query->filterByValue(array(12, 34)); // WHERE value IN (12, 34) - * $query->filterByValue(array('min' => 12)); // WHERE value > 12 - * - * - * @param mixed $value The value to use as filter. - * Use scalar values for equality. - * Use array values for in_array() equivalent. - * Use associative array('min' => $minValue, 'max' => $maxValue) for intervals. - * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL - * - * @return ChildCouponRuleQuery The current query, for fluid interface - */ - public function filterByValue($value = null, $comparison = null) - { - if (is_array($value)) { - $useMinMax = false; - if (isset($value['min'])) { - $this->addUsingAlias(CouponRuleTableMap::VALUE, $value['min'], Criteria::GREATER_EQUAL); - $useMinMax = true; - } - if (isset($value['max'])) { - $this->addUsingAlias(CouponRuleTableMap::VALUE, $value['max'], Criteria::LESS_EQUAL); - $useMinMax = true; - } - if ($useMinMax) { - return $this; - } - if (null === $comparison) { - $comparison = Criteria::IN; - } - } - - return $this->addUsingAlias(CouponRuleTableMap::VALUE, $value, $comparison); - } - - /** - * Filter the query on the created_at column - * - * Example usage: - * - * $query->filterByCreatedAt('2011-03-14'); // WHERE created_at = '2011-03-14' - * $query->filterByCreatedAt('now'); // WHERE created_at = '2011-03-14' - * $query->filterByCreatedAt(array('max' => 'yesterday')); // WHERE created_at > '2011-03-13' - * - * - * @param mixed $createdAt The value to use as filter. - * Values can be integers (unix timestamps), DateTime objects, or strings. - * Empty strings are treated as NULL. - * Use scalar values for equality. - * Use array values for in_array() equivalent. - * Use associative array('min' => $minValue, 'max' => $maxValue) for intervals. - * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL - * - * @return ChildCouponRuleQuery The current query, for fluid interface - */ - public function filterByCreatedAt($createdAt = null, $comparison = null) - { - if (is_array($createdAt)) { - $useMinMax = false; - if (isset($createdAt['min'])) { - $this->addUsingAlias(CouponRuleTableMap::CREATED_AT, $createdAt['min'], Criteria::GREATER_EQUAL); - $useMinMax = true; - } - if (isset($createdAt['max'])) { - $this->addUsingAlias(CouponRuleTableMap::CREATED_AT, $createdAt['max'], Criteria::LESS_EQUAL); - $useMinMax = true; - } - if ($useMinMax) { - return $this; - } - if (null === $comparison) { - $comparison = Criteria::IN; - } - } - - return $this->addUsingAlias(CouponRuleTableMap::CREATED_AT, $createdAt, $comparison); - } - - /** - * Filter the query on the updated_at column - * - * Example usage: - * - * $query->filterByUpdatedAt('2011-03-14'); // WHERE updated_at = '2011-03-14' - * $query->filterByUpdatedAt('now'); // WHERE updated_at = '2011-03-14' - * $query->filterByUpdatedAt(array('max' => 'yesterday')); // WHERE updated_at > '2011-03-13' - * - * - * @param mixed $updatedAt The value to use as filter. - * Values can be integers (unix timestamps), DateTime objects, or strings. - * Empty strings are treated as NULL. - * Use scalar values for equality. - * Use array values for in_array() equivalent. - * Use associative array('min' => $minValue, 'max' => $maxValue) for intervals. - * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL - * - * @return ChildCouponRuleQuery The current query, for fluid interface - */ - public function filterByUpdatedAt($updatedAt = null, $comparison = null) - { - if (is_array($updatedAt)) { - $useMinMax = false; - if (isset($updatedAt['min'])) { - $this->addUsingAlias(CouponRuleTableMap::UPDATED_AT, $updatedAt['min'], Criteria::GREATER_EQUAL); - $useMinMax = true; - } - if (isset($updatedAt['max'])) { - $this->addUsingAlias(CouponRuleTableMap::UPDATED_AT, $updatedAt['max'], Criteria::LESS_EQUAL); - $useMinMax = true; - } - if ($useMinMax) { - return $this; - } - if (null === $comparison) { - $comparison = Criteria::IN; - } - } - - return $this->addUsingAlias(CouponRuleTableMap::UPDATED_AT, $updatedAt, $comparison); - } - - /** - * Filter the query by a related \Thelia\Model\Coupon object - * - * @param \Thelia\Model\Coupon|ObjectCollection $coupon The related object(s) to use as filter - * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL - * - * @return ChildCouponRuleQuery The current query, for fluid interface - */ - public function filterByCoupon($coupon, $comparison = null) - { - if ($coupon instanceof \Thelia\Model\Coupon) { - return $this - ->addUsingAlias(CouponRuleTableMap::COUPON_ID, $coupon->getId(), $comparison); - } elseif ($coupon instanceof ObjectCollection) { - if (null === $comparison) { - $comparison = Criteria::IN; - } - - return $this - ->addUsingAlias(CouponRuleTableMap::COUPON_ID, $coupon->toKeyValue('PrimaryKey', 'Id'), $comparison); - } else { - throw new PropelException('filterByCoupon() only accepts arguments of type \Thelia\Model\Coupon or Collection'); - } - } - - /** - * Adds a JOIN clause to the query using the Coupon relation - * - * @param string $relationAlias optional alias for the relation - * @param string $joinType Accepted values are null, 'left join', 'right join', 'inner join' - * - * @return ChildCouponRuleQuery The current query, for fluid interface - */ - public function joinCoupon($relationAlias = null, $joinType = Criteria::INNER_JOIN) - { - $tableMap = $this->getTableMap(); - $relationMap = $tableMap->getRelation('Coupon'); - - // create a ModelJoin object for this join - $join = new ModelJoin(); - $join->setJoinType($joinType); - $join->setRelationMap($relationMap, $this->useAliasInSQL ? $this->getModelAlias() : null, $relationAlias); - if ($previousJoin = $this->getPreviousJoin()) { - $join->setPreviousJoin($previousJoin); - } - - // add the ModelJoin to the current object - if ($relationAlias) { - $this->addAlias($relationAlias, $relationMap->getRightTable()->getName()); - $this->addJoinObject($join, $relationAlias); - } else { - $this->addJoinObject($join, 'Coupon'); - } - - return $this; - } - - /** - * Use the Coupon relation Coupon object - * - * @see useQuery() - * - * @param string $relationAlias optional alias for the relation, - * to be used as main alias in the secondary query - * @param string $joinType Accepted values are null, 'left join', 'right join', 'inner join' - * - * @return \Thelia\Model\CouponQuery A secondary query class using the current class as primary query - */ - public function useCouponQuery($relationAlias = null, $joinType = Criteria::INNER_JOIN) - { - return $this - ->joinCoupon($relationAlias, $joinType) - ->useQuery($relationAlias ? $relationAlias : 'Coupon', '\Thelia\Model\CouponQuery'); - } - - /** - * Exclude object from result - * - * @param ChildCouponRule $couponRule Object to remove from the list of results - * - * @return ChildCouponRuleQuery The current query, for fluid interface - */ - public function prune($couponRule = null) - { - if ($couponRule) { - $this->addUsingAlias(CouponRuleTableMap::ID, $couponRule->getId(), Criteria::NOT_EQUAL); - } - - return $this; - } - - /** - * Deletes all rows from the coupon_rule table. - * - * @param ConnectionInterface $con the connection to use - * @return int The number of affected rows (if supported by underlying database driver). - */ - public function doDeleteAll(ConnectionInterface $con = null) - { - if (null === $con) { - $con = Propel::getServiceContainer()->getWriteConnection(CouponRuleTableMap::DATABASE_NAME); - } - $affectedRows = 0; // initialize var to track total num of affected rows - try { - // use transaction because $criteria could contain info - // for more than one table or we could emulating ON DELETE CASCADE, etc. - $con->beginTransaction(); - $affectedRows += parent::doDeleteAll($con); - // Because this db requires some delete cascade/set null emulation, we have to - // clear the cached instance *after* the emulation has happened (since - // instances get re-added by the select statement contained therein). - CouponRuleTableMap::clearInstancePool(); - CouponRuleTableMap::clearRelatedInstancePool(); - - $con->commit(); - } catch (PropelException $e) { - $con->rollBack(); - throw $e; - } - - return $affectedRows; - } - - /** - * Performs a DELETE on the database, given a ChildCouponRule or Criteria object OR a primary key value. - * - * @param mixed $values Criteria or ChildCouponRule object or primary key or array of primary keys - * which is used to create the DELETE statement - * @param ConnectionInterface $con the connection to use - * @return int The number of affected rows (if supported by underlying database driver). This includes CASCADE-related rows - * if supported by native driver or if emulated using Propel. - * @throws PropelException Any exceptions caught during processing will be - * rethrown wrapped into a PropelException. - */ - public function delete(ConnectionInterface $con = null) - { - if (null === $con) { - $con = Propel::getServiceContainer()->getWriteConnection(CouponRuleTableMap::DATABASE_NAME); - } - - $criteria = $this; - - // Set the correct dbName - $criteria->setDbName(CouponRuleTableMap::DATABASE_NAME); - - $affectedRows = 0; // initialize var to track total num of affected rows - - try { - // use transaction because $criteria could contain info - // for more than one table or we could emulating ON DELETE CASCADE, etc. - $con->beginTransaction(); - - - CouponRuleTableMap::removeInstanceFromPool($criteria); - - $affectedRows += ModelCriteria::delete($con); - CouponRuleTableMap::clearRelatedInstancePool(); - $con->commit(); - - return $affectedRows; - } catch (PropelException $e) { - $con->rollBack(); - throw $e; - } - } - - // timestampable behavior - - /** - * Filter by the latest updated - * - * @param int $nbDays Maximum age of the latest update in days - * - * @return ChildCouponRuleQuery The current query, for fluid interface - */ - public function recentlyUpdated($nbDays = 7) - { - return $this->addUsingAlias(CouponRuleTableMap::UPDATED_AT, time() - $nbDays * 24 * 60 * 60, Criteria::GREATER_EQUAL); - } - - /** - * Filter by the latest created - * - * @param int $nbDays Maximum age of in days - * - * @return ChildCouponRuleQuery The current query, for fluid interface - */ - public function recentlyCreated($nbDays = 7) - { - return $this->addUsingAlias(CouponRuleTableMap::CREATED_AT, time() - $nbDays * 24 * 60 * 60, Criteria::GREATER_EQUAL); - } - - /** - * Order by update date desc - * - * @return ChildCouponRuleQuery The current query, for fluid interface - */ - public function lastUpdatedFirst() - { - return $this->addDescendingOrderByColumn(CouponRuleTableMap::UPDATED_AT); - } - - /** - * Order by update date asc - * - * @return ChildCouponRuleQuery The current query, for fluid interface - */ - public function firstUpdatedFirst() - { - return $this->addAscendingOrderByColumn(CouponRuleTableMap::UPDATED_AT); - } - - /** - * Order by create date desc - * - * @return ChildCouponRuleQuery The current query, for fluid interface - */ - public function lastCreatedFirst() - { - return $this->addDescendingOrderByColumn(CouponRuleTableMap::CREATED_AT); - } - - /** - * Order by create date asc - * - * @return ChildCouponRuleQuery The current query, for fluid interface - */ - public function firstCreatedFirst() - { - return $this->addAscendingOrderByColumn(CouponRuleTableMap::CREATED_AT); - } - -} // CouponRuleQuery diff --git a/core/lib/Thelia/Model/Base/Currency.php b/core/lib/Thelia/Model/Base/Currency.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/CurrencyI18n.php b/core/lib/Thelia/Model/Base/CurrencyI18n.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/CurrencyI18nQuery.php b/core/lib/Thelia/Model/Base/CurrencyI18nQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/CurrencyQuery.php b/core/lib/Thelia/Model/Base/CurrencyQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/Customer.php b/core/lib/Thelia/Model/Base/Customer.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/CustomerQuery.php b/core/lib/Thelia/Model/Base/CustomerQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/CustomerTitle.php b/core/lib/Thelia/Model/Base/CustomerTitle.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/CustomerTitleI18n.php b/core/lib/Thelia/Model/Base/CustomerTitleI18n.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/CustomerTitleI18nQuery.php b/core/lib/Thelia/Model/Base/CustomerTitleI18nQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/CustomerTitleQuery.php b/core/lib/Thelia/Model/Base/CustomerTitleQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/Delivzone.php b/core/lib/Thelia/Model/Base/Delivzone.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/DelivzoneQuery.php b/core/lib/Thelia/Model/Base/DelivzoneQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/Feature.php b/core/lib/Thelia/Model/Base/Feature.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/FeatureAv.php b/core/lib/Thelia/Model/Base/FeatureAv.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/FeatureAvI18n.php b/core/lib/Thelia/Model/Base/FeatureAvI18n.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/FeatureAvI18nQuery.php b/core/lib/Thelia/Model/Base/FeatureAvI18nQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/FeatureAvQuery.php b/core/lib/Thelia/Model/Base/FeatureAvQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/FeatureCategory.php b/core/lib/Thelia/Model/Base/FeatureCategory.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/FeatureCategoryQuery.php b/core/lib/Thelia/Model/Base/FeatureCategoryQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/FeatureI18n.php b/core/lib/Thelia/Model/Base/FeatureI18n.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/FeatureI18nQuery.php b/core/lib/Thelia/Model/Base/FeatureI18nQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/FeatureProduct.php b/core/lib/Thelia/Model/Base/FeatureProduct.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/FeatureProductQuery.php b/core/lib/Thelia/Model/Base/FeatureProductQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/FeatureQuery.php b/core/lib/Thelia/Model/Base/FeatureQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/Folder.php b/core/lib/Thelia/Model/Base/Folder.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/FolderDocument.php b/core/lib/Thelia/Model/Base/FolderDocument.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/FolderDocumentI18n.php b/core/lib/Thelia/Model/Base/FolderDocumentI18n.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/FolderDocumentI18nQuery.php b/core/lib/Thelia/Model/Base/FolderDocumentI18nQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/FolderDocumentQuery.php b/core/lib/Thelia/Model/Base/FolderDocumentQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/FolderI18n.php b/core/lib/Thelia/Model/Base/FolderI18n.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/FolderI18nQuery.php b/core/lib/Thelia/Model/Base/FolderI18nQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/FolderImage.php b/core/lib/Thelia/Model/Base/FolderImage.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/FolderImageI18n.php b/core/lib/Thelia/Model/Base/FolderImageI18n.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/FolderImageI18nQuery.php b/core/lib/Thelia/Model/Base/FolderImageI18nQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/FolderImageQuery.php b/core/lib/Thelia/Model/Base/FolderImageQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/FolderQuery.php b/core/lib/Thelia/Model/Base/FolderQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/FolderVersion.php b/core/lib/Thelia/Model/Base/FolderVersion.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/FolderVersionQuery.php b/core/lib/Thelia/Model/Base/FolderVersionQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/Group.php b/core/lib/Thelia/Model/Base/Group.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/GroupI18n.php b/core/lib/Thelia/Model/Base/GroupI18n.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/GroupI18nQuery.php b/core/lib/Thelia/Model/Base/GroupI18nQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/GroupModule.php b/core/lib/Thelia/Model/Base/GroupModule.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/GroupModuleQuery.php b/core/lib/Thelia/Model/Base/GroupModuleQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/GroupQuery.php b/core/lib/Thelia/Model/Base/GroupQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/GroupResource.php b/core/lib/Thelia/Model/Base/GroupResource.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/GroupResourceQuery.php b/core/lib/Thelia/Model/Base/GroupResourceQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/Lang.php b/core/lib/Thelia/Model/Base/Lang.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/LangQuery.php b/core/lib/Thelia/Model/Base/LangQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/Message.php b/core/lib/Thelia/Model/Base/Message.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/MessageI18n.php b/core/lib/Thelia/Model/Base/MessageI18n.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/MessageI18nQuery.php b/core/lib/Thelia/Model/Base/MessageI18nQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/MessageQuery.php b/core/lib/Thelia/Model/Base/MessageQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/MessageVersion.php b/core/lib/Thelia/Model/Base/MessageVersion.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/MessageVersionQuery.php b/core/lib/Thelia/Model/Base/MessageVersionQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/Module.php b/core/lib/Thelia/Model/Base/Module.php old mode 100755 new mode 100644 index 556ef9ff6..9cc89381a --- a/core/lib/Thelia/Model/Base/Module.php +++ b/core/lib/Thelia/Model/Base/Module.php @@ -89,6 +89,12 @@ abstract class Module implements ActiveRecordInterface */ protected $position; + /** + * The value for the full_namespace field. + * @var string + */ + protected $full_namespace; + /** * The value for the created_at field. * @var string @@ -456,6 +462,17 @@ abstract class Module implements ActiveRecordInterface return $this->position; } + /** + * Get the [full_namespace] column value. + * + * @return string + */ + public function getFullNamespace() + { + + return $this->full_namespace; + } + /** * Get the [optionally formatted] temporal [created_at] column value. * @@ -601,6 +618,27 @@ abstract class Module implements ActiveRecordInterface return $this; } // setPosition() + /** + * Set the value of [full_namespace] column. + * + * @param string $v new value + * @return \Thelia\Model\Module The current object (for fluent API support) + */ + public function setFullNamespace($v) + { + if ($v !== null) { + $v = (string) $v; + } + + if ($this->full_namespace !== $v) { + $this->full_namespace = $v; + $this->modifiedColumns[] = ModuleTableMap::FULL_NAMESPACE; + } + + + return $this; + } // setFullNamespace() + /** * Sets the value of [created_at] column to a normalized version of the date/time value specified. * @@ -695,13 +733,16 @@ abstract class Module implements ActiveRecordInterface $col = $row[TableMap::TYPE_NUM == $indexType ? 4 + $startcol : ModuleTableMap::translateFieldName('Position', TableMap::TYPE_PHPNAME, $indexType)]; $this->position = (null !== $col) ? (int) $col : null; - $col = $row[TableMap::TYPE_NUM == $indexType ? 5 + $startcol : ModuleTableMap::translateFieldName('CreatedAt', TableMap::TYPE_PHPNAME, $indexType)]; + $col = $row[TableMap::TYPE_NUM == $indexType ? 5 + $startcol : ModuleTableMap::translateFieldName('FullNamespace', TableMap::TYPE_PHPNAME, $indexType)]; + $this->full_namespace = (null !== $col) ? (string) $col : null; + + $col = $row[TableMap::TYPE_NUM == $indexType ? 6 + $startcol : ModuleTableMap::translateFieldName('CreatedAt', TableMap::TYPE_PHPNAME, $indexType)]; if ($col === '0000-00-00 00:00:00') { $col = null; } $this->created_at = (null !== $col) ? PropelDateTime::newInstance($col, null, '\DateTime') : null; - $col = $row[TableMap::TYPE_NUM == $indexType ? 6 + $startcol : ModuleTableMap::translateFieldName('UpdatedAt', TableMap::TYPE_PHPNAME, $indexType)]; + $col = $row[TableMap::TYPE_NUM == $indexType ? 7 + $startcol : ModuleTableMap::translateFieldName('UpdatedAt', TableMap::TYPE_PHPNAME, $indexType)]; if ($col === '0000-00-00 00:00:00') { $col = null; } @@ -714,7 +755,7 @@ abstract class Module implements ActiveRecordInterface $this->ensureConsistency(); } - return $startcol + 7; // 7 = ModuleTableMap::NUM_HYDRATE_COLUMNS. + return $startcol + 8; // 8 = ModuleTableMap::NUM_HYDRATE_COLUMNS. } catch (Exception $e) { throw new PropelException("Error populating \Thelia\Model\Module object", 0, $e); @@ -987,6 +1028,9 @@ abstract class Module implements ActiveRecordInterface if ($this->isColumnModified(ModuleTableMap::POSITION)) { $modifiedColumns[':p' . $index++] = 'POSITION'; } + if ($this->isColumnModified(ModuleTableMap::FULL_NAMESPACE)) { + $modifiedColumns[':p' . $index++] = 'FULL_NAMESPACE'; + } if ($this->isColumnModified(ModuleTableMap::CREATED_AT)) { $modifiedColumns[':p' . $index++] = 'CREATED_AT'; } @@ -1019,6 +1063,9 @@ abstract class Module implements ActiveRecordInterface case 'POSITION': $stmt->bindValue($identifier, $this->position, PDO::PARAM_INT); break; + case 'FULL_NAMESPACE': + $stmt->bindValue($identifier, $this->full_namespace, PDO::PARAM_STR); + break; case 'CREATED_AT': $stmt->bindValue($identifier, $this->created_at ? $this->created_at->format("Y-m-d H:i:s") : null, PDO::PARAM_STR); break; @@ -1103,9 +1150,12 @@ abstract class Module implements ActiveRecordInterface return $this->getPosition(); break; case 5: - return $this->getCreatedAt(); + return $this->getFullNamespace(); break; case 6: + return $this->getCreatedAt(); + break; + case 7: return $this->getUpdatedAt(); break; default: @@ -1142,8 +1192,9 @@ abstract class Module implements ActiveRecordInterface $keys[2] => $this->getType(), $keys[3] => $this->getActivate(), $keys[4] => $this->getPosition(), - $keys[5] => $this->getCreatedAt(), - $keys[6] => $this->getUpdatedAt(), + $keys[5] => $this->getFullNamespace(), + $keys[6] => $this->getCreatedAt(), + $keys[7] => $this->getUpdatedAt(), ); $virtualColumns = $this->virtualColumns; foreach($virtualColumns as $key => $virtualColumn) @@ -1208,9 +1259,12 @@ abstract class Module implements ActiveRecordInterface $this->setPosition($value); break; case 5: - $this->setCreatedAt($value); + $this->setFullNamespace($value); break; case 6: + $this->setCreatedAt($value); + break; + case 7: $this->setUpdatedAt($value); break; } // switch() @@ -1242,8 +1296,9 @@ abstract class Module implements ActiveRecordInterface if (array_key_exists($keys[2], $arr)) $this->setType($arr[$keys[2]]); if (array_key_exists($keys[3], $arr)) $this->setActivate($arr[$keys[3]]); if (array_key_exists($keys[4], $arr)) $this->setPosition($arr[$keys[4]]); - if (array_key_exists($keys[5], $arr)) $this->setCreatedAt($arr[$keys[5]]); - if (array_key_exists($keys[6], $arr)) $this->setUpdatedAt($arr[$keys[6]]); + if (array_key_exists($keys[5], $arr)) $this->setFullNamespace($arr[$keys[5]]); + if (array_key_exists($keys[6], $arr)) $this->setCreatedAt($arr[$keys[6]]); + if (array_key_exists($keys[7], $arr)) $this->setUpdatedAt($arr[$keys[7]]); } /** @@ -1260,6 +1315,7 @@ abstract class Module implements ActiveRecordInterface if ($this->isColumnModified(ModuleTableMap::TYPE)) $criteria->add(ModuleTableMap::TYPE, $this->type); if ($this->isColumnModified(ModuleTableMap::ACTIVATE)) $criteria->add(ModuleTableMap::ACTIVATE, $this->activate); if ($this->isColumnModified(ModuleTableMap::POSITION)) $criteria->add(ModuleTableMap::POSITION, $this->position); + if ($this->isColumnModified(ModuleTableMap::FULL_NAMESPACE)) $criteria->add(ModuleTableMap::FULL_NAMESPACE, $this->full_namespace); if ($this->isColumnModified(ModuleTableMap::CREATED_AT)) $criteria->add(ModuleTableMap::CREATED_AT, $this->created_at); if ($this->isColumnModified(ModuleTableMap::UPDATED_AT)) $criteria->add(ModuleTableMap::UPDATED_AT, $this->updated_at); @@ -1329,6 +1385,7 @@ abstract class Module implements ActiveRecordInterface $copyObj->setType($this->getType()); $copyObj->setActivate($this->getActivate()); $copyObj->setPosition($this->getPosition()); + $copyObj->setFullNamespace($this->getFullNamespace()); $copyObj->setCreatedAt($this->getCreatedAt()); $copyObj->setUpdatedAt($this->getUpdatedAt()); @@ -1876,6 +1933,7 @@ abstract class Module implements ActiveRecordInterface $this->type = null; $this->activate = null; $this->position = null; + $this->full_namespace = null; $this->created_at = null; $this->updated_at = null; $this->alreadyInSave = false; diff --git a/core/lib/Thelia/Model/Base/ModuleI18n.php b/core/lib/Thelia/Model/Base/ModuleI18n.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/ModuleI18nQuery.php b/core/lib/Thelia/Model/Base/ModuleI18nQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/ModuleQuery.php b/core/lib/Thelia/Model/Base/ModuleQuery.php old mode 100755 new mode 100644 index e1bd9de68..6f8d4b551 --- a/core/lib/Thelia/Model/Base/ModuleQuery.php +++ b/core/lib/Thelia/Model/Base/ModuleQuery.php @@ -27,6 +27,7 @@ use Thelia\Model\Map\ModuleTableMap; * @method ChildModuleQuery orderByType($order = Criteria::ASC) Order by the type column * @method ChildModuleQuery orderByActivate($order = Criteria::ASC) Order by the activate column * @method ChildModuleQuery orderByPosition($order = Criteria::ASC) Order by the position column + * @method ChildModuleQuery orderByFullNamespace($order = Criteria::ASC) Order by the full_namespace column * @method ChildModuleQuery orderByCreatedAt($order = Criteria::ASC) Order by the created_at column * @method ChildModuleQuery orderByUpdatedAt($order = Criteria::ASC) Order by the updated_at column * @@ -35,6 +36,7 @@ use Thelia\Model\Map\ModuleTableMap; * @method ChildModuleQuery groupByType() Group by the type column * @method ChildModuleQuery groupByActivate() Group by the activate column * @method ChildModuleQuery groupByPosition() Group by the position column + * @method ChildModuleQuery groupByFullNamespace() Group by the full_namespace column * @method ChildModuleQuery groupByCreatedAt() Group by the created_at column * @method ChildModuleQuery groupByUpdatedAt() Group by the updated_at column * @@ -58,6 +60,7 @@ use Thelia\Model\Map\ModuleTableMap; * @method ChildModule findOneByType(int $type) Return the first ChildModule filtered by the type column * @method ChildModule findOneByActivate(int $activate) Return the first ChildModule filtered by the activate column * @method ChildModule findOneByPosition(int $position) Return the first ChildModule filtered by the position column + * @method ChildModule findOneByFullNamespace(string $full_namespace) Return the first ChildModule filtered by the full_namespace column * @method ChildModule findOneByCreatedAt(string $created_at) Return the first ChildModule filtered by the created_at column * @method ChildModule findOneByUpdatedAt(string $updated_at) Return the first ChildModule filtered by the updated_at column * @@ -66,6 +69,7 @@ use Thelia\Model\Map\ModuleTableMap; * @method array findByType(int $type) Return ChildModule objects filtered by the type column * @method array findByActivate(int $activate) Return ChildModule objects filtered by the activate column * @method array findByPosition(int $position) Return ChildModule objects filtered by the position column + * @method array findByFullNamespace(string $full_namespace) Return ChildModule objects filtered by the full_namespace column * @method array findByCreatedAt(string $created_at) Return ChildModule objects filtered by the created_at column * @method array findByUpdatedAt(string $updated_at) Return ChildModule objects filtered by the updated_at column * @@ -156,7 +160,7 @@ abstract class ModuleQuery extends ModelCriteria */ protected function findPkSimple($key, $con) { - $sql = 'SELECT ID, CODE, TYPE, ACTIVATE, POSITION, CREATED_AT, UPDATED_AT FROM module WHERE ID = :p0'; + $sql = 'SELECT ID, CODE, TYPE, ACTIVATE, POSITION, FULL_NAMESPACE, CREATED_AT, UPDATED_AT FROM module WHERE ID = :p0'; try { $stmt = $con->prepare($sql); $stmt->bindValue(':p0', $key, PDO::PARAM_INT); @@ -438,6 +442,35 @@ abstract class ModuleQuery extends ModelCriteria return $this->addUsingAlias(ModuleTableMap::POSITION, $position, $comparison); } + /** + * Filter the query on the full_namespace column + * + * Example usage: + * + * $query->filterByFullNamespace('fooValue'); // WHERE full_namespace = 'fooValue' + * $query->filterByFullNamespace('%fooValue%'); // WHERE full_namespace LIKE '%fooValue%' + * + * + * @param string $fullNamespace The value to use as filter. + * Accepts wildcards (* and % trigger a LIKE) + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildModuleQuery The current query, for fluid interface + */ + public function filterByFullNamespace($fullNamespace = null, $comparison = null) + { + if (null === $comparison) { + if (is_array($fullNamespace)) { + $comparison = Criteria::IN; + } elseif (preg_match('/[\%\*]/', $fullNamespace)) { + $fullNamespace = str_replace('*', '%', $fullNamespace); + $comparison = Criteria::LIKE; + } + } + + return $this->addUsingAlias(ModuleTableMap::FULL_NAMESPACE, $fullNamespace, $comparison); + } + /** * Filter the query on the created_at column * diff --git a/core/lib/Thelia/Model/Base/Order.php b/core/lib/Thelia/Model/Base/Order.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/OrderAddress.php b/core/lib/Thelia/Model/Base/OrderAddress.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/OrderAddressQuery.php b/core/lib/Thelia/Model/Base/OrderAddressQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/OrderFeature.php b/core/lib/Thelia/Model/Base/OrderFeature.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/OrderFeatureQuery.php b/core/lib/Thelia/Model/Base/OrderFeatureQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/OrderProduct.php b/core/lib/Thelia/Model/Base/OrderProduct.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/OrderProductQuery.php b/core/lib/Thelia/Model/Base/OrderProductQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/OrderQuery.php b/core/lib/Thelia/Model/Base/OrderQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/OrderStatus.php b/core/lib/Thelia/Model/Base/OrderStatus.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/OrderStatusI18n.php b/core/lib/Thelia/Model/Base/OrderStatusI18n.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/OrderStatusI18nQuery.php b/core/lib/Thelia/Model/Base/OrderStatusI18nQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/OrderStatusQuery.php b/core/lib/Thelia/Model/Base/OrderStatusQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/Product.php b/core/lib/Thelia/Model/Base/Product.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/ProductCategory.php b/core/lib/Thelia/Model/Base/ProductCategory.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/ProductCategoryQuery.php b/core/lib/Thelia/Model/Base/ProductCategoryQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/ProductDocument.php b/core/lib/Thelia/Model/Base/ProductDocument.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/ProductDocumentI18n.php b/core/lib/Thelia/Model/Base/ProductDocumentI18n.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/ProductDocumentI18nQuery.php b/core/lib/Thelia/Model/Base/ProductDocumentI18nQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/ProductDocumentQuery.php b/core/lib/Thelia/Model/Base/ProductDocumentQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/ProductI18n.php b/core/lib/Thelia/Model/Base/ProductI18n.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/ProductI18nQuery.php b/core/lib/Thelia/Model/Base/ProductI18nQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/ProductImage.php b/core/lib/Thelia/Model/Base/ProductImage.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/ProductImageI18n.php b/core/lib/Thelia/Model/Base/ProductImageI18n.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/ProductImageI18nQuery.php b/core/lib/Thelia/Model/Base/ProductImageI18nQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/ProductImageQuery.php b/core/lib/Thelia/Model/Base/ProductImageQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/ProductPrice.php b/core/lib/Thelia/Model/Base/ProductPrice.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/ProductPriceQuery.php b/core/lib/Thelia/Model/Base/ProductPriceQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/ProductQuery.php b/core/lib/Thelia/Model/Base/ProductQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/ProductSaleElements.php b/core/lib/Thelia/Model/Base/ProductSaleElements.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/ProductSaleElementsQuery.php b/core/lib/Thelia/Model/Base/ProductSaleElementsQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/ProductVersion.php b/core/lib/Thelia/Model/Base/ProductVersion.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/ProductVersionQuery.php b/core/lib/Thelia/Model/Base/ProductVersionQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/Resource.php b/core/lib/Thelia/Model/Base/Resource.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/ResourceI18n.php b/core/lib/Thelia/Model/Base/ResourceI18n.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/ResourceI18nQuery.php b/core/lib/Thelia/Model/Base/ResourceI18nQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/ResourceQuery.php b/core/lib/Thelia/Model/Base/ResourceQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/Tax.php b/core/lib/Thelia/Model/Base/Tax.php old mode 100755 new mode 100644 index 02e6bc3b0..ed4bb40f7 --- a/core/lib/Thelia/Model/Base/Tax.php +++ b/core/lib/Thelia/Model/Base/Tax.php @@ -791,10 +791,9 @@ abstract class Tax implements ActiveRecordInterface if ($this->taxRuleCountriesScheduledForDeletion !== null) { if (!$this->taxRuleCountriesScheduledForDeletion->isEmpty()) { - foreach ($this->taxRuleCountriesScheduledForDeletion as $taxRuleCountry) { - // need to save related object because we set the relation to null - $taxRuleCountry->save($con); - } + \Thelia\Model\TaxRuleCountryQuery::create() + ->filterByPrimaryKeys($this->taxRuleCountriesScheduledForDeletion->getPrimaryKeys(false)) + ->delete($con); $this->taxRuleCountriesScheduledForDeletion = null; } } @@ -1346,7 +1345,10 @@ abstract class Tax implements ActiveRecordInterface $taxRuleCountriesToDelete = $this->getTaxRuleCountries(new Criteria(), $con)->diff($taxRuleCountries); - $this->taxRuleCountriesScheduledForDeletion = $taxRuleCountriesToDelete; + //since at least one column in the foreign key is at the same time a PK + //we can not just set a PK to NULL in the lines below. We have to store + //a backup of all values, so we are able to manipulate these items based on the onDelete value later. + $this->taxRuleCountriesScheduledForDeletion = clone $taxRuleCountriesToDelete; foreach ($taxRuleCountriesToDelete as $taxRuleCountryRemoved) { $taxRuleCountryRemoved->setTax(null); @@ -1439,7 +1441,7 @@ abstract class Tax implements ActiveRecordInterface $this->taxRuleCountriesScheduledForDeletion = clone $this->collTaxRuleCountries; $this->taxRuleCountriesScheduledForDeletion->clear(); } - $this->taxRuleCountriesScheduledForDeletion[]= $taxRuleCountry; + $this->taxRuleCountriesScheduledForDeletion[]= clone $taxRuleCountry; $taxRuleCountry->setTax(null); } diff --git a/core/lib/Thelia/Model/Base/TaxI18n.php b/core/lib/Thelia/Model/Base/TaxI18n.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/TaxI18nQuery.php b/core/lib/Thelia/Model/Base/TaxI18nQuery.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Base/TaxQuery.php b/core/lib/Thelia/Model/Base/TaxQuery.php old mode 100755 new mode 100644 index 307ace57c..07316bf69 --- a/core/lib/Thelia/Model/Base/TaxQuery.php +++ b/core/lib/Thelia/Model/Base/TaxQuery.php @@ -432,7 +432,7 @@ abstract class TaxQuery extends ModelCriteria * * @return ChildTaxQuery The current query, for fluid interface */ - public function joinTaxRuleCountry($relationAlias = null, $joinType = Criteria::LEFT_JOIN) + public function joinTaxRuleCountry($relationAlias = null, $joinType = Criteria::INNER_JOIN) { $tableMap = $this->getTableMap(); $relationMap = $tableMap->getRelation('TaxRuleCountry'); @@ -467,7 +467,7 @@ abstract class TaxQuery extends ModelCriteria * * @return \Thelia\Model\TaxRuleCountryQuery A secondary query class using the current class as primary query */ - public function useTaxRuleCountryQuery($relationAlias = null, $joinType = Criteria::LEFT_JOIN) + public function useTaxRuleCountryQuery($relationAlias = null, $joinType = Criteria::INNER_JOIN) { return $this ->joinTaxRuleCountry($relationAlias, $joinType) diff --git a/core/lib/Thelia/Model/Base/TaxRule.php b/core/lib/Thelia/Model/Base/TaxRule.php old mode 100755 new mode 100644 index d33d47e2b..61f21d4e1 --- a/core/lib/Thelia/Model/Base/TaxRule.php +++ b/core/lib/Thelia/Model/Base/TaxRule.php @@ -67,24 +67,6 @@ abstract class TaxRule implements ActiveRecordInterface */ protected $id; - /** - * The value for the code field. - * @var string - */ - protected $code; - - /** - * The value for the title field. - * @var string - */ - protected $title; - - /** - * The value for the description field. - * @var string - */ - protected $description; - /** * The value for the created_at field. * @var string @@ -420,39 +402,6 @@ abstract class TaxRule implements ActiveRecordInterface return $this->id; } - /** - * Get the [code] column value. - * - * @return string - */ - public function getCode() - { - - return $this->code; - } - - /** - * Get the [title] column value. - * - * @return string - */ - public function getTitle() - { - - return $this->title; - } - - /** - * Get the [description] column value. - * - * @return string - */ - public function getDescription() - { - - return $this->description; - } - /** * Get the [optionally formatted] temporal [created_at] column value. * @@ -514,69 +463,6 @@ abstract class TaxRule implements ActiveRecordInterface return $this; } // setId() - /** - * Set the value of [code] column. - * - * @param string $v new value - * @return \Thelia\Model\TaxRule The current object (for fluent API support) - */ - public function setCode($v) - { - if ($v !== null) { - $v = (string) $v; - } - - if ($this->code !== $v) { - $this->code = $v; - $this->modifiedColumns[] = TaxRuleTableMap::CODE; - } - - - return $this; - } // setCode() - - /** - * Set the value of [title] column. - * - * @param string $v new value - * @return \Thelia\Model\TaxRule The current object (for fluent API support) - */ - public function setTitle($v) - { - if ($v !== null) { - $v = (string) $v; - } - - if ($this->title !== $v) { - $this->title = $v; - $this->modifiedColumns[] = TaxRuleTableMap::TITLE; - } - - - return $this; - } // setTitle() - - /** - * Set the value of [description] column. - * - * @param string $v new value - * @return \Thelia\Model\TaxRule The current object (for fluent API support) - */ - public function setDescription($v) - { - if ($v !== null) { - $v = (string) $v; - } - - if ($this->description !== $v) { - $this->description = $v; - $this->modifiedColumns[] = TaxRuleTableMap::DESCRIPTION; - } - - - return $this; - } // setDescription() - /** * Sets the value of [created_at] column to a normalized version of the date/time value specified. * @@ -659,22 +545,13 @@ abstract class TaxRule implements ActiveRecordInterface $col = $row[TableMap::TYPE_NUM == $indexType ? 0 + $startcol : TaxRuleTableMap::translateFieldName('Id', TableMap::TYPE_PHPNAME, $indexType)]; $this->id = (null !== $col) ? (int) $col : null; - $col = $row[TableMap::TYPE_NUM == $indexType ? 1 + $startcol : TaxRuleTableMap::translateFieldName('Code', TableMap::TYPE_PHPNAME, $indexType)]; - $this->code = (null !== $col) ? (string) $col : null; - - $col = $row[TableMap::TYPE_NUM == $indexType ? 2 + $startcol : TaxRuleTableMap::translateFieldName('Title', TableMap::TYPE_PHPNAME, $indexType)]; - $this->title = (null !== $col) ? (string) $col : null; - - $col = $row[TableMap::TYPE_NUM == $indexType ? 3 + $startcol : TaxRuleTableMap::translateFieldName('Description', TableMap::TYPE_PHPNAME, $indexType)]; - $this->description = (null !== $col) ? (string) $col : null; - - $col = $row[TableMap::TYPE_NUM == $indexType ? 4 + $startcol : TaxRuleTableMap::translateFieldName('CreatedAt', TableMap::TYPE_PHPNAME, $indexType)]; + $col = $row[TableMap::TYPE_NUM == $indexType ? 1 + $startcol : TaxRuleTableMap::translateFieldName('CreatedAt', TableMap::TYPE_PHPNAME, $indexType)]; if ($col === '0000-00-00 00:00:00') { $col = null; } $this->created_at = (null !== $col) ? PropelDateTime::newInstance($col, null, '\DateTime') : null; - $col = $row[TableMap::TYPE_NUM == $indexType ? 5 + $startcol : TaxRuleTableMap::translateFieldName('UpdatedAt', TableMap::TYPE_PHPNAME, $indexType)]; + $col = $row[TableMap::TYPE_NUM == $indexType ? 2 + $startcol : TaxRuleTableMap::translateFieldName('UpdatedAt', TableMap::TYPE_PHPNAME, $indexType)]; if ($col === '0000-00-00 00:00:00') { $col = null; } @@ -687,7 +564,7 @@ abstract class TaxRule implements ActiveRecordInterface $this->ensureConsistency(); } - return $startcol + 6; // 6 = TaxRuleTableMap::NUM_HYDRATE_COLUMNS. + return $startcol + 3; // 3 = TaxRuleTableMap::NUM_HYDRATE_COLUMNS. } catch (Exception $e) { throw new PropelException("Error populating \Thelia\Model\TaxRule object", 0, $e); @@ -968,15 +845,6 @@ abstract class TaxRule implements ActiveRecordInterface if ($this->isColumnModified(TaxRuleTableMap::ID)) { $modifiedColumns[':p' . $index++] = 'ID'; } - if ($this->isColumnModified(TaxRuleTableMap::CODE)) { - $modifiedColumns[':p' . $index++] = 'CODE'; - } - if ($this->isColumnModified(TaxRuleTableMap::TITLE)) { - $modifiedColumns[':p' . $index++] = 'TITLE'; - } - if ($this->isColumnModified(TaxRuleTableMap::DESCRIPTION)) { - $modifiedColumns[':p' . $index++] = 'DESCRIPTION'; - } if ($this->isColumnModified(TaxRuleTableMap::CREATED_AT)) { $modifiedColumns[':p' . $index++] = 'CREATED_AT'; } @@ -997,15 +865,6 @@ abstract class TaxRule implements ActiveRecordInterface case 'ID': $stmt->bindValue($identifier, $this->id, PDO::PARAM_INT); break; - case 'CODE': - $stmt->bindValue($identifier, $this->code, PDO::PARAM_STR); - break; - case 'TITLE': - $stmt->bindValue($identifier, $this->title, PDO::PARAM_STR); - break; - case 'DESCRIPTION': - $stmt->bindValue($identifier, $this->description, PDO::PARAM_STR); - break; case 'CREATED_AT': $stmt->bindValue($identifier, $this->created_at ? $this->created_at->format("Y-m-d H:i:s") : null, PDO::PARAM_STR); break; @@ -1078,18 +937,9 @@ abstract class TaxRule implements ActiveRecordInterface return $this->getId(); break; case 1: - return $this->getCode(); - break; - case 2: - return $this->getTitle(); - break; - case 3: - return $this->getDescription(); - break; - case 4: return $this->getCreatedAt(); break; - case 5: + case 2: return $this->getUpdatedAt(); break; default: @@ -1122,11 +972,8 @@ abstract class TaxRule implements ActiveRecordInterface $keys = TaxRuleTableMap::getFieldNames($keyType); $result = array( $keys[0] => $this->getId(), - $keys[1] => $this->getCode(), - $keys[2] => $this->getTitle(), - $keys[3] => $this->getDescription(), - $keys[4] => $this->getCreatedAt(), - $keys[5] => $this->getUpdatedAt(), + $keys[1] => $this->getCreatedAt(), + $keys[2] => $this->getUpdatedAt(), ); $virtualColumns = $this->virtualColumns; foreach($virtualColumns as $key => $virtualColumn) @@ -1182,18 +1029,9 @@ abstract class TaxRule implements ActiveRecordInterface $this->setId($value); break; case 1: - $this->setCode($value); - break; - case 2: - $this->setTitle($value); - break; - case 3: - $this->setDescription($value); - break; - case 4: $this->setCreatedAt($value); break; - case 5: + case 2: $this->setUpdatedAt($value); break; } // switch() @@ -1221,11 +1059,8 @@ abstract class TaxRule implements ActiveRecordInterface $keys = TaxRuleTableMap::getFieldNames($keyType); if (array_key_exists($keys[0], $arr)) $this->setId($arr[$keys[0]]); - if (array_key_exists($keys[1], $arr)) $this->setCode($arr[$keys[1]]); - if (array_key_exists($keys[2], $arr)) $this->setTitle($arr[$keys[2]]); - if (array_key_exists($keys[3], $arr)) $this->setDescription($arr[$keys[3]]); - if (array_key_exists($keys[4], $arr)) $this->setCreatedAt($arr[$keys[4]]); - if (array_key_exists($keys[5], $arr)) $this->setUpdatedAt($arr[$keys[5]]); + if (array_key_exists($keys[1], $arr)) $this->setCreatedAt($arr[$keys[1]]); + if (array_key_exists($keys[2], $arr)) $this->setUpdatedAt($arr[$keys[2]]); } /** @@ -1238,9 +1073,6 @@ abstract class TaxRule implements ActiveRecordInterface $criteria = new Criteria(TaxRuleTableMap::DATABASE_NAME); if ($this->isColumnModified(TaxRuleTableMap::ID)) $criteria->add(TaxRuleTableMap::ID, $this->id); - if ($this->isColumnModified(TaxRuleTableMap::CODE)) $criteria->add(TaxRuleTableMap::CODE, $this->code); - if ($this->isColumnModified(TaxRuleTableMap::TITLE)) $criteria->add(TaxRuleTableMap::TITLE, $this->title); - if ($this->isColumnModified(TaxRuleTableMap::DESCRIPTION)) $criteria->add(TaxRuleTableMap::DESCRIPTION, $this->description); if ($this->isColumnModified(TaxRuleTableMap::CREATED_AT)) $criteria->add(TaxRuleTableMap::CREATED_AT, $this->created_at); if ($this->isColumnModified(TaxRuleTableMap::UPDATED_AT)) $criteria->add(TaxRuleTableMap::UPDATED_AT, $this->updated_at); @@ -1306,9 +1138,6 @@ abstract class TaxRule implements ActiveRecordInterface */ public function copyInto($copyObj, $deepCopy = false, $makeNew = true) { - $copyObj->setCode($this->getCode()); - $copyObj->setTitle($this->getTitle()); - $copyObj->setDescription($this->getDescription()); $copyObj->setCreatedAt($this->getCreatedAt()); $copyObj->setUpdatedAt($this->getUpdatedAt()); @@ -1723,7 +1552,10 @@ abstract class TaxRule implements ActiveRecordInterface $taxRuleCountriesToDelete = $this->getTaxRuleCountries(new Criteria(), $con)->diff($taxRuleCountries); - $this->taxRuleCountriesScheduledForDeletion = $taxRuleCountriesToDelete; + //since at least one column in the foreign key is at the same time a PK + //we can not just set a PK to NULL in the lines below. We have to store + //a backup of all values, so we are able to manipulate these items based on the onDelete value later. + $this->taxRuleCountriesScheduledForDeletion = clone $taxRuleCountriesToDelete; foreach ($taxRuleCountriesToDelete as $taxRuleCountryRemoved) { $taxRuleCountryRemoved->setTaxRule(null); @@ -1816,7 +1648,7 @@ abstract class TaxRule implements ActiveRecordInterface $this->taxRuleCountriesScheduledForDeletion = clone $this->collTaxRuleCountries; $this->taxRuleCountriesScheduledForDeletion->clear(); } - $this->taxRuleCountriesScheduledForDeletion[]= $taxRuleCountry; + $this->taxRuleCountriesScheduledForDeletion[]= clone $taxRuleCountry; $taxRuleCountry->setTaxRule(null); } @@ -2104,9 +1936,6 @@ abstract class TaxRule implements ActiveRecordInterface public function clear() { $this->id = null; - $this->code = null; - $this->title = null; - $this->description = null; $this->created_at = null; $this->updated_at = null; $this->alreadyInSave = false; @@ -2286,6 +2115,54 @@ abstract class TaxRule implements ActiveRecordInterface return $this->getTranslation($this->getLocale(), $con); } + + /** + * Get the [title] column value. + * + * @return string + */ + public function getTitle() + { + return $this->getCurrentTranslation()->getTitle(); + } + + + /** + * Set the value of [title] column. + * + * @param string $v new value + * @return \Thelia\Model\TaxRuleI18n The current object (for fluent API support) + */ + public function setTitle($v) + { $this->getCurrentTranslation()->setTitle($v); + + return $this; + } + + + /** + * Get the [description] column value. + * + * @return string + */ + public function getDescription() + { + return $this->getCurrentTranslation()->getDescription(); + } + + + /** + * Set the value of [description] column. + * + * @param string $v new value + * @return \Thelia\Model\TaxRuleI18n The current object (for fluent API support) + */ + public function setDescription($v) + { $this->getCurrentTranslation()->setDescription($v); + + return $this; + } + /** * Code to be run before persisting the object * @param ConnectionInterface $con diff --git a/core/lib/Thelia/Model/Base/TaxRuleCountry.php b/core/lib/Thelia/Model/Base/TaxRuleCountry.php old mode 100755 new mode 100644 index 66f6f585b..0cc3e74eb --- a/core/lib/Thelia/Model/Base/TaxRuleCountry.php +++ b/core/lib/Thelia/Model/Base/TaxRuleCountry.php @@ -60,12 +60,6 @@ abstract class TaxRuleCountry implements ActiveRecordInterface */ protected $virtualColumns = array(); - /** - * The value for the id field. - * @var int - */ - protected $id; - /** * The value for the tax_rule_id field. * @var int @@ -85,10 +79,10 @@ abstract class TaxRuleCountry implements ActiveRecordInterface protected $tax_id; /** - * The value for the none field. + * The value for the position field. * @var int */ - protected $none; + protected $position; /** * The value for the created_at field. @@ -379,17 +373,6 @@ abstract class TaxRuleCountry implements ActiveRecordInterface return array_keys(get_object_vars($this)); } - /** - * Get the [id] column value. - * - * @return int - */ - public function getId() - { - - return $this->id; - } - /** * Get the [tax_rule_id] column value. * @@ -424,14 +407,14 @@ abstract class TaxRuleCountry implements ActiveRecordInterface } /** - * Get the [none] column value. + * Get the [position] column value. * * @return int */ - public function getNone() + public function getPosition() { - return $this->none; + return $this->position; } /** @@ -474,27 +457,6 @@ abstract class TaxRuleCountry implements ActiveRecordInterface } } - /** - * Set the value of [id] column. - * - * @param int $v new value - * @return \Thelia\Model\TaxRuleCountry The current object (for fluent API support) - */ - public function setId($v) - { - if ($v !== null) { - $v = (int) $v; - } - - if ($this->id !== $v) { - $this->id = $v; - $this->modifiedColumns[] = TaxRuleCountryTableMap::ID; - } - - - return $this; - } // setId() - /** * Set the value of [tax_rule_id] column. * @@ -571,25 +533,25 @@ abstract class TaxRuleCountry implements ActiveRecordInterface } // setTaxId() /** - * Set the value of [none] column. + * Set the value of [position] column. * * @param int $v new value * @return \Thelia\Model\TaxRuleCountry The current object (for fluent API support) */ - public function setNone($v) + public function setPosition($v) { if ($v !== null) { $v = (int) $v; } - if ($this->none !== $v) { - $this->none = $v; - $this->modifiedColumns[] = TaxRuleCountryTableMap::NONE; + if ($this->position !== $v) { + $this->position = $v; + $this->modifiedColumns[] = TaxRuleCountryTableMap::POSITION; } return $this; - } // setNone() + } // setPosition() /** * Sets the value of [created_at] column to a normalized version of the date/time value specified. @@ -670,28 +632,25 @@ abstract class TaxRuleCountry implements ActiveRecordInterface try { - $col = $row[TableMap::TYPE_NUM == $indexType ? 0 + $startcol : TaxRuleCountryTableMap::translateFieldName('Id', TableMap::TYPE_PHPNAME, $indexType)]; - $this->id = (null !== $col) ? (int) $col : null; - - $col = $row[TableMap::TYPE_NUM == $indexType ? 1 + $startcol : TaxRuleCountryTableMap::translateFieldName('TaxRuleId', TableMap::TYPE_PHPNAME, $indexType)]; + $col = $row[TableMap::TYPE_NUM == $indexType ? 0 + $startcol : TaxRuleCountryTableMap::translateFieldName('TaxRuleId', TableMap::TYPE_PHPNAME, $indexType)]; $this->tax_rule_id = (null !== $col) ? (int) $col : null; - $col = $row[TableMap::TYPE_NUM == $indexType ? 2 + $startcol : TaxRuleCountryTableMap::translateFieldName('CountryId', TableMap::TYPE_PHPNAME, $indexType)]; + $col = $row[TableMap::TYPE_NUM == $indexType ? 1 + $startcol : TaxRuleCountryTableMap::translateFieldName('CountryId', TableMap::TYPE_PHPNAME, $indexType)]; $this->country_id = (null !== $col) ? (int) $col : null; - $col = $row[TableMap::TYPE_NUM == $indexType ? 3 + $startcol : TaxRuleCountryTableMap::translateFieldName('TaxId', TableMap::TYPE_PHPNAME, $indexType)]; + $col = $row[TableMap::TYPE_NUM == $indexType ? 2 + $startcol : TaxRuleCountryTableMap::translateFieldName('TaxId', TableMap::TYPE_PHPNAME, $indexType)]; $this->tax_id = (null !== $col) ? (int) $col : null; - $col = $row[TableMap::TYPE_NUM == $indexType ? 4 + $startcol : TaxRuleCountryTableMap::translateFieldName('None', TableMap::TYPE_PHPNAME, $indexType)]; - $this->none = (null !== $col) ? (int) $col : null; + $col = $row[TableMap::TYPE_NUM == $indexType ? 3 + $startcol : TaxRuleCountryTableMap::translateFieldName('Position', TableMap::TYPE_PHPNAME, $indexType)]; + $this->position = (null !== $col) ? (int) $col : null; - $col = $row[TableMap::TYPE_NUM == $indexType ? 5 + $startcol : TaxRuleCountryTableMap::translateFieldName('CreatedAt', TableMap::TYPE_PHPNAME, $indexType)]; + $col = $row[TableMap::TYPE_NUM == $indexType ? 4 + $startcol : TaxRuleCountryTableMap::translateFieldName('CreatedAt', TableMap::TYPE_PHPNAME, $indexType)]; if ($col === '0000-00-00 00:00:00') { $col = null; } $this->created_at = (null !== $col) ? PropelDateTime::newInstance($col, null, '\DateTime') : null; - $col = $row[TableMap::TYPE_NUM == $indexType ? 6 + $startcol : TaxRuleCountryTableMap::translateFieldName('UpdatedAt', TableMap::TYPE_PHPNAME, $indexType)]; + $col = $row[TableMap::TYPE_NUM == $indexType ? 5 + $startcol : TaxRuleCountryTableMap::translateFieldName('UpdatedAt', TableMap::TYPE_PHPNAME, $indexType)]; if ($col === '0000-00-00 00:00:00') { $col = null; } @@ -704,7 +663,7 @@ abstract class TaxRuleCountry implements ActiveRecordInterface $this->ensureConsistency(); } - return $startcol + 7; // 7 = TaxRuleCountryTableMap::NUM_HYDRATE_COLUMNS. + return $startcol + 6; // 6 = TaxRuleCountryTableMap::NUM_HYDRATE_COLUMNS. } catch (Exception $e) { throw new PropelException("Error populating \Thelia\Model\TaxRuleCountry object", 0, $e); @@ -958,9 +917,6 @@ abstract class TaxRuleCountry implements ActiveRecordInterface // check the columns in natural order for more readable SQL queries - if ($this->isColumnModified(TaxRuleCountryTableMap::ID)) { - $modifiedColumns[':p' . $index++] = 'ID'; - } if ($this->isColumnModified(TaxRuleCountryTableMap::TAX_RULE_ID)) { $modifiedColumns[':p' . $index++] = 'TAX_RULE_ID'; } @@ -970,8 +926,8 @@ abstract class TaxRuleCountry implements ActiveRecordInterface if ($this->isColumnModified(TaxRuleCountryTableMap::TAX_ID)) { $modifiedColumns[':p' . $index++] = 'TAX_ID'; } - if ($this->isColumnModified(TaxRuleCountryTableMap::NONE)) { - $modifiedColumns[':p' . $index++] = 'NONE'; + if ($this->isColumnModified(TaxRuleCountryTableMap::POSITION)) { + $modifiedColumns[':p' . $index++] = 'POSITION'; } if ($this->isColumnModified(TaxRuleCountryTableMap::CREATED_AT)) { $modifiedColumns[':p' . $index++] = 'CREATED_AT'; @@ -990,9 +946,6 @@ abstract class TaxRuleCountry implements ActiveRecordInterface $stmt = $con->prepare($sql); foreach ($modifiedColumns as $identifier => $columnName) { switch ($columnName) { - case 'ID': - $stmt->bindValue($identifier, $this->id, PDO::PARAM_INT); - break; case 'TAX_RULE_ID': $stmt->bindValue($identifier, $this->tax_rule_id, PDO::PARAM_INT); break; @@ -1002,8 +955,8 @@ abstract class TaxRuleCountry implements ActiveRecordInterface case 'TAX_ID': $stmt->bindValue($identifier, $this->tax_id, PDO::PARAM_INT); break; - case 'NONE': - $stmt->bindValue($identifier, $this->none, PDO::PARAM_INT); + case 'POSITION': + $stmt->bindValue($identifier, $this->position, PDO::PARAM_INT); break; case 'CREATED_AT': $stmt->bindValue($identifier, $this->created_at ? $this->created_at->format("Y-m-d H:i:s") : null, PDO::PARAM_STR); @@ -1067,24 +1020,21 @@ abstract class TaxRuleCountry implements ActiveRecordInterface { switch ($pos) { case 0: - return $this->getId(); - break; - case 1: return $this->getTaxRuleId(); break; - case 2: + case 1: return $this->getCountryId(); break; - case 3: + case 2: return $this->getTaxId(); break; - case 4: - return $this->getNone(); + case 3: + return $this->getPosition(); break; - case 5: + case 4: return $this->getCreatedAt(); break; - case 6: + case 5: return $this->getUpdatedAt(); break; default: @@ -1110,19 +1060,18 @@ abstract class TaxRuleCountry implements ActiveRecordInterface */ public function toArray($keyType = TableMap::TYPE_PHPNAME, $includeLazyLoadColumns = true, $alreadyDumpedObjects = array(), $includeForeignObjects = false) { - if (isset($alreadyDumpedObjects['TaxRuleCountry'][$this->getPrimaryKey()])) { + if (isset($alreadyDumpedObjects['TaxRuleCountry'][serialize($this->getPrimaryKey())])) { return '*RECURSION*'; } - $alreadyDumpedObjects['TaxRuleCountry'][$this->getPrimaryKey()] = true; + $alreadyDumpedObjects['TaxRuleCountry'][serialize($this->getPrimaryKey())] = true; $keys = TaxRuleCountryTableMap::getFieldNames($keyType); $result = array( - $keys[0] => $this->getId(), - $keys[1] => $this->getTaxRuleId(), - $keys[2] => $this->getCountryId(), - $keys[3] => $this->getTaxId(), - $keys[4] => $this->getNone(), - $keys[5] => $this->getCreatedAt(), - $keys[6] => $this->getUpdatedAt(), + $keys[0] => $this->getTaxRuleId(), + $keys[1] => $this->getCountryId(), + $keys[2] => $this->getTaxId(), + $keys[3] => $this->getPosition(), + $keys[4] => $this->getCreatedAt(), + $keys[5] => $this->getUpdatedAt(), ); $virtualColumns = $this->virtualColumns; foreach($virtualColumns as $key => $virtualColumn) @@ -1175,24 +1124,21 @@ abstract class TaxRuleCountry implements ActiveRecordInterface { switch ($pos) { case 0: - $this->setId($value); - break; - case 1: $this->setTaxRuleId($value); break; - case 2: + case 1: $this->setCountryId($value); break; - case 3: + case 2: $this->setTaxId($value); break; - case 4: - $this->setNone($value); + case 3: + $this->setPosition($value); break; - case 5: + case 4: $this->setCreatedAt($value); break; - case 6: + case 5: $this->setUpdatedAt($value); break; } // switch() @@ -1219,13 +1165,12 @@ abstract class TaxRuleCountry implements ActiveRecordInterface { $keys = TaxRuleCountryTableMap::getFieldNames($keyType); - if (array_key_exists($keys[0], $arr)) $this->setId($arr[$keys[0]]); - if (array_key_exists($keys[1], $arr)) $this->setTaxRuleId($arr[$keys[1]]); - if (array_key_exists($keys[2], $arr)) $this->setCountryId($arr[$keys[2]]); - if (array_key_exists($keys[3], $arr)) $this->setTaxId($arr[$keys[3]]); - if (array_key_exists($keys[4], $arr)) $this->setNone($arr[$keys[4]]); - if (array_key_exists($keys[5], $arr)) $this->setCreatedAt($arr[$keys[5]]); - if (array_key_exists($keys[6], $arr)) $this->setUpdatedAt($arr[$keys[6]]); + if (array_key_exists($keys[0], $arr)) $this->setTaxRuleId($arr[$keys[0]]); + if (array_key_exists($keys[1], $arr)) $this->setCountryId($arr[$keys[1]]); + if (array_key_exists($keys[2], $arr)) $this->setTaxId($arr[$keys[2]]); + if (array_key_exists($keys[3], $arr)) $this->setPosition($arr[$keys[3]]); + if (array_key_exists($keys[4], $arr)) $this->setCreatedAt($arr[$keys[4]]); + if (array_key_exists($keys[5], $arr)) $this->setUpdatedAt($arr[$keys[5]]); } /** @@ -1237,11 +1182,10 @@ abstract class TaxRuleCountry implements ActiveRecordInterface { $criteria = new Criteria(TaxRuleCountryTableMap::DATABASE_NAME); - if ($this->isColumnModified(TaxRuleCountryTableMap::ID)) $criteria->add(TaxRuleCountryTableMap::ID, $this->id); if ($this->isColumnModified(TaxRuleCountryTableMap::TAX_RULE_ID)) $criteria->add(TaxRuleCountryTableMap::TAX_RULE_ID, $this->tax_rule_id); if ($this->isColumnModified(TaxRuleCountryTableMap::COUNTRY_ID)) $criteria->add(TaxRuleCountryTableMap::COUNTRY_ID, $this->country_id); if ($this->isColumnModified(TaxRuleCountryTableMap::TAX_ID)) $criteria->add(TaxRuleCountryTableMap::TAX_ID, $this->tax_id); - if ($this->isColumnModified(TaxRuleCountryTableMap::NONE)) $criteria->add(TaxRuleCountryTableMap::NONE, $this->none); + if ($this->isColumnModified(TaxRuleCountryTableMap::POSITION)) $criteria->add(TaxRuleCountryTableMap::POSITION, $this->position); if ($this->isColumnModified(TaxRuleCountryTableMap::CREATED_AT)) $criteria->add(TaxRuleCountryTableMap::CREATED_AT, $this->created_at); if ($this->isColumnModified(TaxRuleCountryTableMap::UPDATED_AT)) $criteria->add(TaxRuleCountryTableMap::UPDATED_AT, $this->updated_at); @@ -1259,29 +1203,39 @@ abstract class TaxRuleCountry implements ActiveRecordInterface public function buildPkeyCriteria() { $criteria = new Criteria(TaxRuleCountryTableMap::DATABASE_NAME); - $criteria->add(TaxRuleCountryTableMap::ID, $this->id); + $criteria->add(TaxRuleCountryTableMap::TAX_RULE_ID, $this->tax_rule_id); + $criteria->add(TaxRuleCountryTableMap::COUNTRY_ID, $this->country_id); + $criteria->add(TaxRuleCountryTableMap::TAX_ID, $this->tax_id); return $criteria; } /** - * Returns the primary key for this object (row). - * @return int + * Returns the composite primary key for this object. + * The array elements will be in same order as specified in XML. + * @return array */ public function getPrimaryKey() { - return $this->getId(); + $pks = array(); + $pks[0] = $this->getTaxRuleId(); + $pks[1] = $this->getCountryId(); + $pks[2] = $this->getTaxId(); + + return $pks; } /** - * Generic method to set the primary key (id column). + * Set the [composite] primary key. * - * @param int $key Primary key. + * @param array $keys The elements of the composite key (order must match the order in XML file). * @return void */ - public function setPrimaryKey($key) + public function setPrimaryKey($keys) { - $this->setId($key); + $this->setTaxRuleId($keys[0]); + $this->setCountryId($keys[1]); + $this->setTaxId($keys[2]); } /** @@ -1291,7 +1245,7 @@ abstract class TaxRuleCountry implements ActiveRecordInterface public function isPrimaryKeyNull() { - return null === $this->getId(); + return (null === $this->getTaxRuleId()) && (null === $this->getCountryId()) && (null === $this->getTaxId()); } /** @@ -1307,11 +1261,10 @@ abstract class TaxRuleCountry implements ActiveRecordInterface */ public function copyInto($copyObj, $deepCopy = false, $makeNew = true) { - $copyObj->setId($this->getId()); $copyObj->setTaxRuleId($this->getTaxRuleId()); $copyObj->setCountryId($this->getCountryId()); $copyObj->setTaxId($this->getTaxId()); - $copyObj->setNone($this->getNone()); + $copyObj->setPosition($this->getPosition()); $copyObj->setCreatedAt($this->getCreatedAt()); $copyObj->setUpdatedAt($this->getUpdatedAt()); if ($makeNew) { @@ -1499,11 +1452,10 @@ abstract class TaxRuleCountry implements ActiveRecordInterface */ public function clear() { - $this->id = null; $this->tax_rule_id = null; $this->country_id = null; $this->tax_id = null; - $this->none = null; + $this->position = null; $this->created_at = null; $this->updated_at = null; $this->alreadyInSave = false; diff --git a/core/lib/Thelia/Model/Base/TaxRuleCountryQuery.php b/core/lib/Thelia/Model/Base/TaxRuleCountryQuery.php old mode 100755 new mode 100644 index b4d4cd1c2..5674643f7 --- a/core/lib/Thelia/Model/Base/TaxRuleCountryQuery.php +++ b/core/lib/Thelia/Model/Base/TaxRuleCountryQuery.php @@ -21,19 +21,17 @@ use Thelia\Model\Map\TaxRuleCountryTableMap; * * * - * @method ChildTaxRuleCountryQuery orderById($order = Criteria::ASC) Order by the id column * @method ChildTaxRuleCountryQuery orderByTaxRuleId($order = Criteria::ASC) Order by the tax_rule_id column * @method ChildTaxRuleCountryQuery orderByCountryId($order = Criteria::ASC) Order by the country_id column * @method ChildTaxRuleCountryQuery orderByTaxId($order = Criteria::ASC) Order by the tax_id column - * @method ChildTaxRuleCountryQuery orderByNone($order = Criteria::ASC) Order by the none column + * @method ChildTaxRuleCountryQuery orderByPosition($order = Criteria::ASC) Order by the position column * @method ChildTaxRuleCountryQuery orderByCreatedAt($order = Criteria::ASC) Order by the created_at column * @method ChildTaxRuleCountryQuery orderByUpdatedAt($order = Criteria::ASC) Order by the updated_at column * - * @method ChildTaxRuleCountryQuery groupById() Group by the id column * @method ChildTaxRuleCountryQuery groupByTaxRuleId() Group by the tax_rule_id column * @method ChildTaxRuleCountryQuery groupByCountryId() Group by the country_id column * @method ChildTaxRuleCountryQuery groupByTaxId() Group by the tax_id column - * @method ChildTaxRuleCountryQuery groupByNone() Group by the none column + * @method ChildTaxRuleCountryQuery groupByPosition() Group by the position column * @method ChildTaxRuleCountryQuery groupByCreatedAt() Group by the created_at column * @method ChildTaxRuleCountryQuery groupByUpdatedAt() Group by the updated_at column * @@ -56,19 +54,17 @@ use Thelia\Model\Map\TaxRuleCountryTableMap; * @method ChildTaxRuleCountry findOne(ConnectionInterface $con = null) Return the first ChildTaxRuleCountry matching the query * @method ChildTaxRuleCountry findOneOrCreate(ConnectionInterface $con = null) Return the first ChildTaxRuleCountry matching the query, or a new ChildTaxRuleCountry object populated from the query conditions when no match is found * - * @method ChildTaxRuleCountry findOneById(int $id) Return the first ChildTaxRuleCountry filtered by the id column * @method ChildTaxRuleCountry findOneByTaxRuleId(int $tax_rule_id) Return the first ChildTaxRuleCountry filtered by the tax_rule_id column * @method ChildTaxRuleCountry findOneByCountryId(int $country_id) Return the first ChildTaxRuleCountry filtered by the country_id column * @method ChildTaxRuleCountry findOneByTaxId(int $tax_id) Return the first ChildTaxRuleCountry filtered by the tax_id column - * @method ChildTaxRuleCountry findOneByNone(int $none) Return the first ChildTaxRuleCountry filtered by the none column + * @method ChildTaxRuleCountry findOneByPosition(int $position) Return the first ChildTaxRuleCountry filtered by the position column * @method ChildTaxRuleCountry findOneByCreatedAt(string $created_at) Return the first ChildTaxRuleCountry filtered by the created_at column * @method ChildTaxRuleCountry findOneByUpdatedAt(string $updated_at) Return the first ChildTaxRuleCountry filtered by the updated_at column * - * @method array findById(int $id) Return ChildTaxRuleCountry objects filtered by the id column * @method array findByTaxRuleId(int $tax_rule_id) Return ChildTaxRuleCountry objects filtered by the tax_rule_id column * @method array findByCountryId(int $country_id) Return ChildTaxRuleCountry objects filtered by the country_id column * @method array findByTaxId(int $tax_id) Return ChildTaxRuleCountry objects filtered by the tax_id column - * @method array findByNone(int $none) Return ChildTaxRuleCountry objects filtered by the none column + * @method array findByPosition(int $position) Return ChildTaxRuleCountry objects filtered by the position column * @method array findByCreatedAt(string $created_at) Return ChildTaxRuleCountry objects filtered by the created_at column * @method array findByUpdatedAt(string $updated_at) Return ChildTaxRuleCountry objects filtered by the updated_at column * @@ -118,10 +114,10 @@ abstract class TaxRuleCountryQuery extends ModelCriteria * Go fast if the query is untouched. * * - * $obj = $c->findPk(12, $con); + * $obj = $c->findPk(array(12, 34, 56), $con); * * - * @param mixed $key Primary key to use for the query + * @param array[$tax_rule_id, $country_id, $tax_id] $key Primary key to use for the query * @param ConnectionInterface $con an optional connection object * * @return ChildTaxRuleCountry|array|mixed the result, formatted by the current formatter @@ -131,7 +127,7 @@ abstract class TaxRuleCountryQuery extends ModelCriteria if ($key === null) { return null; } - if ((null !== ($obj = TaxRuleCountryTableMap::getInstanceFromPool((string) $key))) && !$this->formatter) { + if ((null !== ($obj = TaxRuleCountryTableMap::getInstanceFromPool(serialize(array((string) $key[0], (string) $key[1], (string) $key[2]))))) && !$this->formatter) { // the object is already in the instance pool return $obj; } @@ -159,10 +155,12 @@ abstract class TaxRuleCountryQuery extends ModelCriteria */ protected function findPkSimple($key, $con) { - $sql = 'SELECT ID, TAX_RULE_ID, COUNTRY_ID, TAX_ID, NONE, CREATED_AT, UPDATED_AT FROM tax_rule_country WHERE ID = :p0'; + $sql = 'SELECT TAX_RULE_ID, COUNTRY_ID, TAX_ID, POSITION, CREATED_AT, UPDATED_AT FROM tax_rule_country WHERE TAX_RULE_ID = :p0 AND COUNTRY_ID = :p1 AND TAX_ID = :p2'; try { $stmt = $con->prepare($sql); - $stmt->bindValue(':p0', $key, PDO::PARAM_INT); + $stmt->bindValue(':p0', $key[0], PDO::PARAM_INT); + $stmt->bindValue(':p1', $key[1], PDO::PARAM_INT); + $stmt->bindValue(':p2', $key[2], PDO::PARAM_INT); $stmt->execute(); } catch (Exception $e) { Propel::log($e->getMessage(), Propel::LOG_ERR); @@ -172,7 +170,7 @@ abstract class TaxRuleCountryQuery extends ModelCriteria if ($row = $stmt->fetch(\PDO::FETCH_NUM)) { $obj = new ChildTaxRuleCountry(); $obj->hydrate($row); - TaxRuleCountryTableMap::addInstanceToPool($obj, (string) $key); + TaxRuleCountryTableMap::addInstanceToPool($obj, serialize(array((string) $key[0], (string) $key[1], (string) $key[2]))); } $stmt->closeCursor(); @@ -201,7 +199,7 @@ abstract class TaxRuleCountryQuery extends ModelCriteria /** * Find objects by primary key * - * $objs = $c->findPks(array(12, 56, 832), $con); + * $objs = $c->findPks(array(array(12, 56), array(832, 123), array(123, 456)), $con); * * @param array $keys Primary keys to use for the query * @param ConnectionInterface $con an optional connection object @@ -231,8 +229,11 @@ abstract class TaxRuleCountryQuery extends ModelCriteria */ public function filterByPrimaryKey($key) { + $this->addUsingAlias(TaxRuleCountryTableMap::TAX_RULE_ID, $key[0], Criteria::EQUAL); + $this->addUsingAlias(TaxRuleCountryTableMap::COUNTRY_ID, $key[1], Criteria::EQUAL); + $this->addUsingAlias(TaxRuleCountryTableMap::TAX_ID, $key[2], Criteria::EQUAL); - return $this->addUsingAlias(TaxRuleCountryTableMap::ID, $key, Criteria::EQUAL); + return $this; } /** @@ -244,49 +245,19 @@ abstract class TaxRuleCountryQuery extends ModelCriteria */ public function filterByPrimaryKeys($keys) { - - return $this->addUsingAlias(TaxRuleCountryTableMap::ID, $keys, Criteria::IN); - } - - /** - * Filter the query on the id column - * - * Example usage: - * - * $query->filterById(1234); // WHERE id = 1234 - * $query->filterById(array(12, 34)); // WHERE id IN (12, 34) - * $query->filterById(array('min' => 12)); // WHERE id > 12 - * - * - * @param mixed $id The value to use as filter. - * Use scalar values for equality. - * Use array values for in_array() equivalent. - * Use associative array('min' => $minValue, 'max' => $maxValue) for intervals. - * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL - * - * @return ChildTaxRuleCountryQuery The current query, for fluid interface - */ - public function filterById($id = null, $comparison = null) - { - if (is_array($id)) { - $useMinMax = false; - if (isset($id['min'])) { - $this->addUsingAlias(TaxRuleCountryTableMap::ID, $id['min'], Criteria::GREATER_EQUAL); - $useMinMax = true; - } - if (isset($id['max'])) { - $this->addUsingAlias(TaxRuleCountryTableMap::ID, $id['max'], Criteria::LESS_EQUAL); - $useMinMax = true; - } - if ($useMinMax) { - return $this; - } - if (null === $comparison) { - $comparison = Criteria::IN; - } + if (empty($keys)) { + return $this->add(null, '1<>1', Criteria::CUSTOM); + } + foreach ($keys as $key) { + $cton0 = $this->getNewCriterion(TaxRuleCountryTableMap::TAX_RULE_ID, $key[0], Criteria::EQUAL); + $cton1 = $this->getNewCriterion(TaxRuleCountryTableMap::COUNTRY_ID, $key[1], Criteria::EQUAL); + $cton0->addAnd($cton1); + $cton2 = $this->getNewCriterion(TaxRuleCountryTableMap::TAX_ID, $key[2], Criteria::EQUAL); + $cton0->addAnd($cton2); + $this->addOr($cton0); } - return $this->addUsingAlias(TaxRuleCountryTableMap::ID, $id, $comparison); + return $this; } /** @@ -419,16 +390,16 @@ abstract class TaxRuleCountryQuery extends ModelCriteria } /** - * Filter the query on the none column + * Filter the query on the position column * * Example usage: * - * $query->filterByNone(1234); // WHERE none = 1234 - * $query->filterByNone(array(12, 34)); // WHERE none IN (12, 34) - * $query->filterByNone(array('min' => 12)); // WHERE none > 12 + * $query->filterByPosition(1234); // WHERE position = 1234 + * $query->filterByPosition(array(12, 34)); // WHERE position IN (12, 34) + * $query->filterByPosition(array('min' => 12)); // WHERE position > 12 * * - * @param mixed $none The value to use as filter. + * @param mixed $position The value to use as filter. * Use scalar values for equality. * Use array values for in_array() equivalent. * Use associative array('min' => $minValue, 'max' => $maxValue) for intervals. @@ -436,16 +407,16 @@ abstract class TaxRuleCountryQuery extends ModelCriteria * * @return ChildTaxRuleCountryQuery The current query, for fluid interface */ - public function filterByNone($none = null, $comparison = null) + public function filterByPosition($position = null, $comparison = null) { - if (is_array($none)) { + if (is_array($position)) { $useMinMax = false; - if (isset($none['min'])) { - $this->addUsingAlias(TaxRuleCountryTableMap::NONE, $none['min'], Criteria::GREATER_EQUAL); + if (isset($position['min'])) { + $this->addUsingAlias(TaxRuleCountryTableMap::POSITION, $position['min'], Criteria::GREATER_EQUAL); $useMinMax = true; } - if (isset($none['max'])) { - $this->addUsingAlias(TaxRuleCountryTableMap::NONE, $none['max'], Criteria::LESS_EQUAL); + if (isset($position['max'])) { + $this->addUsingAlias(TaxRuleCountryTableMap::POSITION, $position['max'], Criteria::LESS_EQUAL); $useMinMax = true; } if ($useMinMax) { @@ -456,7 +427,7 @@ abstract class TaxRuleCountryQuery extends ModelCriteria } } - return $this->addUsingAlias(TaxRuleCountryTableMap::NONE, $none, $comparison); + return $this->addUsingAlias(TaxRuleCountryTableMap::POSITION, $position, $comparison); } /** @@ -578,7 +549,7 @@ abstract class TaxRuleCountryQuery extends ModelCriteria * * @return ChildTaxRuleCountryQuery The current query, for fluid interface */ - public function joinTax($relationAlias = null, $joinType = Criteria::LEFT_JOIN) + public function joinTax($relationAlias = null, $joinType = Criteria::INNER_JOIN) { $tableMap = $this->getTableMap(); $relationMap = $tableMap->getRelation('Tax'); @@ -613,7 +584,7 @@ abstract class TaxRuleCountryQuery extends ModelCriteria * * @return \Thelia\Model\TaxQuery A secondary query class using the current class as primary query */ - public function useTaxQuery($relationAlias = null, $joinType = Criteria::LEFT_JOIN) + public function useTaxQuery($relationAlias = null, $joinType = Criteria::INNER_JOIN) { return $this ->joinTax($relationAlias, $joinType) @@ -653,7 +624,7 @@ abstract class TaxRuleCountryQuery extends ModelCriteria * * @return ChildTaxRuleCountryQuery The current query, for fluid interface */ - public function joinTaxRule($relationAlias = null, $joinType = Criteria::LEFT_JOIN) + public function joinTaxRule($relationAlias = null, $joinType = Criteria::INNER_JOIN) { $tableMap = $this->getTableMap(); $relationMap = $tableMap->getRelation('TaxRule'); @@ -688,7 +659,7 @@ abstract class TaxRuleCountryQuery extends ModelCriteria * * @return \Thelia\Model\TaxRuleQuery A secondary query class using the current class as primary query */ - public function useTaxRuleQuery($relationAlias = null, $joinType = Criteria::LEFT_JOIN) + public function useTaxRuleQuery($relationAlias = null, $joinType = Criteria::INNER_JOIN) { return $this ->joinTaxRule($relationAlias, $joinType) @@ -728,7 +699,7 @@ abstract class TaxRuleCountryQuery extends ModelCriteria * * @return ChildTaxRuleCountryQuery The current query, for fluid interface */ - public function joinCountry($relationAlias = null, $joinType = Criteria::LEFT_JOIN) + public function joinCountry($relationAlias = null, $joinType = Criteria::INNER_JOIN) { $tableMap = $this->getTableMap(); $relationMap = $tableMap->getRelation('Country'); @@ -763,7 +734,7 @@ abstract class TaxRuleCountryQuery extends ModelCriteria * * @return \Thelia\Model\CountryQuery A secondary query class using the current class as primary query */ - public function useCountryQuery($relationAlias = null, $joinType = Criteria::LEFT_JOIN) + public function useCountryQuery($relationAlias = null, $joinType = Criteria::INNER_JOIN) { return $this ->joinCountry($relationAlias, $joinType) @@ -780,7 +751,10 @@ abstract class TaxRuleCountryQuery extends ModelCriteria public function prune($taxRuleCountry = null) { if ($taxRuleCountry) { - $this->addUsingAlias(TaxRuleCountryTableMap::ID, $taxRuleCountry->getId(), Criteria::NOT_EQUAL); + $this->addCond('pruneCond0', $this->getAliasedColName(TaxRuleCountryTableMap::TAX_RULE_ID), $taxRuleCountry->getTaxRuleId(), Criteria::NOT_EQUAL); + $this->addCond('pruneCond1', $this->getAliasedColName(TaxRuleCountryTableMap::COUNTRY_ID), $taxRuleCountry->getCountryId(), Criteria::NOT_EQUAL); + $this->addCond('pruneCond2', $this->getAliasedColName(TaxRuleCountryTableMap::TAX_ID), $taxRuleCountry->getTaxId(), Criteria::NOT_EQUAL); + $this->combine(array('pruneCond0', 'pruneCond1', 'pruneCond2'), Criteria::LOGICAL_OR); } return $this; diff --git a/core/lib/Thelia/Model/Base/TaxRuleI18n.php b/core/lib/Thelia/Model/Base/TaxRuleI18n.php old mode 100755 new mode 100644 index b1efadd6a..711dba307 --- a/core/lib/Thelia/Model/Base/TaxRuleI18n.php +++ b/core/lib/Thelia/Model/Base/TaxRuleI18n.php @@ -66,6 +66,18 @@ abstract class TaxRuleI18n implements ActiveRecordInterface */ protected $locale; + /** + * The value for the title field. + * @var string + */ + protected $title; + + /** + * The value for the description field. + * @var string + */ + protected $description; + /** * @var TaxRule */ @@ -368,6 +380,28 @@ abstract class TaxRuleI18n implements ActiveRecordInterface return $this->locale; } + /** + * Get the [title] column value. + * + * @return string + */ + public function getTitle() + { + + return $this->title; + } + + /** + * Get the [description] column value. + * + * @return string + */ + public function getDescription() + { + + return $this->description; + } + /** * Set the value of [id] column. * @@ -414,6 +448,48 @@ abstract class TaxRuleI18n implements ActiveRecordInterface return $this; } // setLocale() + /** + * Set the value of [title] column. + * + * @param string $v new value + * @return \Thelia\Model\TaxRuleI18n The current object (for fluent API support) + */ + public function setTitle($v) + { + if ($v !== null) { + $v = (string) $v; + } + + if ($this->title !== $v) { + $this->title = $v; + $this->modifiedColumns[] = TaxRuleI18nTableMap::TITLE; + } + + + return $this; + } // setTitle() + + /** + * Set the value of [description] column. + * + * @param string $v new value + * @return \Thelia\Model\TaxRuleI18n The current object (for fluent API support) + */ + public function setDescription($v) + { + if ($v !== null) { + $v = (string) $v; + } + + if ($this->description !== $v) { + $this->description = $v; + $this->modifiedColumns[] = TaxRuleI18nTableMap::DESCRIPTION; + } + + + return $this; + } // setDescription() + /** * Indicates whether the columns in this object are only set to default values. * @@ -460,6 +536,12 @@ abstract class TaxRuleI18n implements ActiveRecordInterface $col = $row[TableMap::TYPE_NUM == $indexType ? 1 + $startcol : TaxRuleI18nTableMap::translateFieldName('Locale', TableMap::TYPE_PHPNAME, $indexType)]; $this->locale = (null !== $col) ? (string) $col : null; + + $col = $row[TableMap::TYPE_NUM == $indexType ? 2 + $startcol : TaxRuleI18nTableMap::translateFieldName('Title', TableMap::TYPE_PHPNAME, $indexType)]; + $this->title = (null !== $col) ? (string) $col : null; + + $col = $row[TableMap::TYPE_NUM == $indexType ? 3 + $startcol : TaxRuleI18nTableMap::translateFieldName('Description', TableMap::TYPE_PHPNAME, $indexType)]; + $this->description = (null !== $col) ? (string) $col : null; $this->resetModified(); $this->setNew(false); @@ -468,7 +550,7 @@ abstract class TaxRuleI18n implements ActiveRecordInterface $this->ensureConsistency(); } - return $startcol + 2; // 2 = TaxRuleI18nTableMap::NUM_HYDRATE_COLUMNS. + return $startcol + 4; // 4 = TaxRuleI18nTableMap::NUM_HYDRATE_COLUMNS. } catch (Exception $e) { throw new PropelException("Error populating \Thelia\Model\TaxRuleI18n object", 0, $e); @@ -695,6 +777,12 @@ abstract class TaxRuleI18n implements ActiveRecordInterface if ($this->isColumnModified(TaxRuleI18nTableMap::LOCALE)) { $modifiedColumns[':p' . $index++] = 'LOCALE'; } + if ($this->isColumnModified(TaxRuleI18nTableMap::TITLE)) { + $modifiedColumns[':p' . $index++] = 'TITLE'; + } + if ($this->isColumnModified(TaxRuleI18nTableMap::DESCRIPTION)) { + $modifiedColumns[':p' . $index++] = 'DESCRIPTION'; + } $sql = sprintf( 'INSERT INTO tax_rule_i18n (%s) VALUES (%s)', @@ -712,6 +800,12 @@ abstract class TaxRuleI18n implements ActiveRecordInterface case 'LOCALE': $stmt->bindValue($identifier, $this->locale, PDO::PARAM_STR); break; + case 'TITLE': + $stmt->bindValue($identifier, $this->title, PDO::PARAM_STR); + break; + case 'DESCRIPTION': + $stmt->bindValue($identifier, $this->description, PDO::PARAM_STR); + break; } } $stmt->execute(); @@ -773,6 +867,12 @@ abstract class TaxRuleI18n implements ActiveRecordInterface case 1: return $this->getLocale(); break; + case 2: + return $this->getTitle(); + break; + case 3: + return $this->getDescription(); + break; default: return null; break; @@ -804,6 +904,8 @@ abstract class TaxRuleI18n implements ActiveRecordInterface $result = array( $keys[0] => $this->getId(), $keys[1] => $this->getLocale(), + $keys[2] => $this->getTitle(), + $keys[3] => $this->getDescription(), ); $virtualColumns = $this->virtualColumns; foreach($virtualColumns as $key => $virtualColumn) @@ -855,6 +957,12 @@ abstract class TaxRuleI18n implements ActiveRecordInterface case 1: $this->setLocale($value); break; + case 2: + $this->setTitle($value); + break; + case 3: + $this->setDescription($value); + break; } // switch() } @@ -881,6 +989,8 @@ abstract class TaxRuleI18n implements ActiveRecordInterface if (array_key_exists($keys[0], $arr)) $this->setId($arr[$keys[0]]); if (array_key_exists($keys[1], $arr)) $this->setLocale($arr[$keys[1]]); + if (array_key_exists($keys[2], $arr)) $this->setTitle($arr[$keys[2]]); + if (array_key_exists($keys[3], $arr)) $this->setDescription($arr[$keys[3]]); } /** @@ -894,6 +1004,8 @@ abstract class TaxRuleI18n implements ActiveRecordInterface if ($this->isColumnModified(TaxRuleI18nTableMap::ID)) $criteria->add(TaxRuleI18nTableMap::ID, $this->id); if ($this->isColumnModified(TaxRuleI18nTableMap::LOCALE)) $criteria->add(TaxRuleI18nTableMap::LOCALE, $this->locale); + if ($this->isColumnModified(TaxRuleI18nTableMap::TITLE)) $criteria->add(TaxRuleI18nTableMap::TITLE, $this->title); + if ($this->isColumnModified(TaxRuleI18nTableMap::DESCRIPTION)) $criteria->add(TaxRuleI18nTableMap::DESCRIPTION, $this->description); return $criteria; } @@ -966,6 +1078,8 @@ abstract class TaxRuleI18n implements ActiveRecordInterface { $copyObj->setId($this->getId()); $copyObj->setLocale($this->getLocale()); + $copyObj->setTitle($this->getTitle()); + $copyObj->setDescription($this->getDescription()); if ($makeNew) { $copyObj->setNew(true); } @@ -1051,6 +1165,8 @@ abstract class TaxRuleI18n implements ActiveRecordInterface { $this->id = null; $this->locale = null; + $this->title = null; + $this->description = null; $this->alreadyInSave = false; $this->clearAllReferences(); $this->applyDefaultValues(); diff --git a/core/lib/Thelia/Model/Base/TaxRuleI18nQuery.php b/core/lib/Thelia/Model/Base/TaxRuleI18nQuery.php old mode 100755 new mode 100644 index 02667f4ac..dfb3e100c --- a/core/lib/Thelia/Model/Base/TaxRuleI18nQuery.php +++ b/core/lib/Thelia/Model/Base/TaxRuleI18nQuery.php @@ -23,9 +23,13 @@ use Thelia\Model\Map\TaxRuleI18nTableMap; * * @method ChildTaxRuleI18nQuery orderById($order = Criteria::ASC) Order by the id column * @method ChildTaxRuleI18nQuery orderByLocale($order = Criteria::ASC) Order by the locale column + * @method ChildTaxRuleI18nQuery orderByTitle($order = Criteria::ASC) Order by the title column + * @method ChildTaxRuleI18nQuery orderByDescription($order = Criteria::ASC) Order by the description column * * @method ChildTaxRuleI18nQuery groupById() Group by the id column * @method ChildTaxRuleI18nQuery groupByLocale() Group by the locale column + * @method ChildTaxRuleI18nQuery groupByTitle() Group by the title column + * @method ChildTaxRuleI18nQuery groupByDescription() Group by the description column * * @method ChildTaxRuleI18nQuery leftJoin($relation) Adds a LEFT JOIN clause to the query * @method ChildTaxRuleI18nQuery rightJoin($relation) Adds a RIGHT JOIN clause to the query @@ -40,9 +44,13 @@ use Thelia\Model\Map\TaxRuleI18nTableMap; * * @method ChildTaxRuleI18n findOneById(int $id) Return the first ChildTaxRuleI18n filtered by the id column * @method ChildTaxRuleI18n findOneByLocale(string $locale) Return the first ChildTaxRuleI18n filtered by the locale column + * @method ChildTaxRuleI18n findOneByTitle(string $title) Return the first ChildTaxRuleI18n filtered by the title column + * @method ChildTaxRuleI18n findOneByDescription(string $description) Return the first ChildTaxRuleI18n filtered by the description column * * @method array findById(int $id) Return ChildTaxRuleI18n objects filtered by the id column * @method array findByLocale(string $locale) Return ChildTaxRuleI18n objects filtered by the locale column + * @method array findByTitle(string $title) Return ChildTaxRuleI18n objects filtered by the title column + * @method array findByDescription(string $description) Return ChildTaxRuleI18n objects filtered by the description column * */ abstract class TaxRuleI18nQuery extends ModelCriteria @@ -131,7 +139,7 @@ abstract class TaxRuleI18nQuery extends ModelCriteria */ protected function findPkSimple($key, $con) { - $sql = 'SELECT ID, LOCALE FROM tax_rule_i18n WHERE ID = :p0 AND LOCALE = :p1'; + $sql = 'SELECT ID, LOCALE, TITLE, DESCRIPTION FROM tax_rule_i18n WHERE ID = :p0 AND LOCALE = :p1'; try { $stmt = $con->prepare($sql); $stmt->bindValue(':p0', $key[0], PDO::PARAM_INT); @@ -304,6 +312,64 @@ abstract class TaxRuleI18nQuery extends ModelCriteria return $this->addUsingAlias(TaxRuleI18nTableMap::LOCALE, $locale, $comparison); } + /** + * Filter the query on the title column + * + * Example usage: + * + * $query->filterByTitle('fooValue'); // WHERE title = 'fooValue' + * $query->filterByTitle('%fooValue%'); // WHERE title LIKE '%fooValue%' + * + * + * @param string $title The value to use as filter. + * Accepts wildcards (* and % trigger a LIKE) + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildTaxRuleI18nQuery The current query, for fluid interface + */ + public function filterByTitle($title = null, $comparison = null) + { + if (null === $comparison) { + if (is_array($title)) { + $comparison = Criteria::IN; + } elseif (preg_match('/[\%\*]/', $title)) { + $title = str_replace('*', '%', $title); + $comparison = Criteria::LIKE; + } + } + + return $this->addUsingAlias(TaxRuleI18nTableMap::TITLE, $title, $comparison); + } + + /** + * Filter the query on the description column + * + * Example usage: + * + * $query->filterByDescription('fooValue'); // WHERE description = 'fooValue' + * $query->filterByDescription('%fooValue%'); // WHERE description LIKE '%fooValue%' + * + * + * @param string $description The value to use as filter. + * Accepts wildcards (* and % trigger a LIKE) + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildTaxRuleI18nQuery The current query, for fluid interface + */ + public function filterByDescription($description = null, $comparison = null) + { + if (null === $comparison) { + if (is_array($description)) { + $comparison = Criteria::IN; + } elseif (preg_match('/[\%\*]/', $description)) { + $description = str_replace('*', '%', $description); + $comparison = Criteria::LIKE; + } + } + + return $this->addUsingAlias(TaxRuleI18nTableMap::DESCRIPTION, $description, $comparison); + } + /** * Filter the query by a related \Thelia\Model\TaxRule object * diff --git a/core/lib/Thelia/Model/Base/TaxRuleQuery.php b/core/lib/Thelia/Model/Base/TaxRuleQuery.php old mode 100755 new mode 100644 index 2fb478b7a..8ee264415 --- a/core/lib/Thelia/Model/Base/TaxRuleQuery.php +++ b/core/lib/Thelia/Model/Base/TaxRuleQuery.php @@ -23,16 +23,10 @@ use Thelia\Model\Map\TaxRuleTableMap; * * * @method ChildTaxRuleQuery orderById($order = Criteria::ASC) Order by the id column - * @method ChildTaxRuleQuery orderByCode($order = Criteria::ASC) Order by the code column - * @method ChildTaxRuleQuery orderByTitle($order = Criteria::ASC) Order by the title column - * @method ChildTaxRuleQuery orderByDescription($order = Criteria::ASC) Order by the description column * @method ChildTaxRuleQuery orderByCreatedAt($order = Criteria::ASC) Order by the created_at column * @method ChildTaxRuleQuery orderByUpdatedAt($order = Criteria::ASC) Order by the updated_at column * * @method ChildTaxRuleQuery groupById() Group by the id column - * @method ChildTaxRuleQuery groupByCode() Group by the code column - * @method ChildTaxRuleQuery groupByTitle() Group by the title column - * @method ChildTaxRuleQuery groupByDescription() Group by the description column * @method ChildTaxRuleQuery groupByCreatedAt() Group by the created_at column * @method ChildTaxRuleQuery groupByUpdatedAt() Group by the updated_at column * @@ -56,16 +50,10 @@ use Thelia\Model\Map\TaxRuleTableMap; * @method ChildTaxRule findOneOrCreate(ConnectionInterface $con = null) Return the first ChildTaxRule matching the query, or a new ChildTaxRule object populated from the query conditions when no match is found * * @method ChildTaxRule findOneById(int $id) Return the first ChildTaxRule filtered by the id column - * @method ChildTaxRule findOneByCode(string $code) Return the first ChildTaxRule filtered by the code column - * @method ChildTaxRule findOneByTitle(string $title) Return the first ChildTaxRule filtered by the title column - * @method ChildTaxRule findOneByDescription(string $description) Return the first ChildTaxRule filtered by the description column * @method ChildTaxRule findOneByCreatedAt(string $created_at) Return the first ChildTaxRule filtered by the created_at column * @method ChildTaxRule findOneByUpdatedAt(string $updated_at) Return the first ChildTaxRule filtered by the updated_at column * * @method array findById(int $id) Return ChildTaxRule objects filtered by the id column - * @method array findByCode(string $code) Return ChildTaxRule objects filtered by the code column - * @method array findByTitle(string $title) Return ChildTaxRule objects filtered by the title column - * @method array findByDescription(string $description) Return ChildTaxRule objects filtered by the description column * @method array findByCreatedAt(string $created_at) Return ChildTaxRule objects filtered by the created_at column * @method array findByUpdatedAt(string $updated_at) Return ChildTaxRule objects filtered by the updated_at column * @@ -156,7 +144,7 @@ abstract class TaxRuleQuery extends ModelCriteria */ protected function findPkSimple($key, $con) { - $sql = 'SELECT ID, CODE, TITLE, DESCRIPTION, CREATED_AT, UPDATED_AT FROM tax_rule WHERE ID = :p0'; + $sql = 'SELECT ID, CREATED_AT, UPDATED_AT FROM tax_rule WHERE ID = :p0'; try { $stmt = $con->prepare($sql); $stmt->bindValue(':p0', $key, PDO::PARAM_INT); @@ -286,93 +274,6 @@ abstract class TaxRuleQuery extends ModelCriteria return $this->addUsingAlias(TaxRuleTableMap::ID, $id, $comparison); } - /** - * Filter the query on the code column - * - * Example usage: - * - * $query->filterByCode('fooValue'); // WHERE code = 'fooValue' - * $query->filterByCode('%fooValue%'); // WHERE code LIKE '%fooValue%' - * - * - * @param string $code The value to use as filter. - * Accepts wildcards (* and % trigger a LIKE) - * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL - * - * @return ChildTaxRuleQuery The current query, for fluid interface - */ - public function filterByCode($code = null, $comparison = null) - { - if (null === $comparison) { - if (is_array($code)) { - $comparison = Criteria::IN; - } elseif (preg_match('/[\%\*]/', $code)) { - $code = str_replace('*', '%', $code); - $comparison = Criteria::LIKE; - } - } - - return $this->addUsingAlias(TaxRuleTableMap::CODE, $code, $comparison); - } - - /** - * Filter the query on the title column - * - * Example usage: - * - * $query->filterByTitle('fooValue'); // WHERE title = 'fooValue' - * $query->filterByTitle('%fooValue%'); // WHERE title LIKE '%fooValue%' - * - * - * @param string $title The value to use as filter. - * Accepts wildcards (* and % trigger a LIKE) - * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL - * - * @return ChildTaxRuleQuery The current query, for fluid interface - */ - public function filterByTitle($title = null, $comparison = null) - { - if (null === $comparison) { - if (is_array($title)) { - $comparison = Criteria::IN; - } elseif (preg_match('/[\%\*]/', $title)) { - $title = str_replace('*', '%', $title); - $comparison = Criteria::LIKE; - } - } - - return $this->addUsingAlias(TaxRuleTableMap::TITLE, $title, $comparison); - } - - /** - * Filter the query on the description column - * - * Example usage: - * - * $query->filterByDescription('fooValue'); // WHERE description = 'fooValue' - * $query->filterByDescription('%fooValue%'); // WHERE description LIKE '%fooValue%' - * - * - * @param string $description The value to use as filter. - * Accepts wildcards (* and % trigger a LIKE) - * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL - * - * @return ChildTaxRuleQuery The current query, for fluid interface - */ - public function filterByDescription($description = null, $comparison = null) - { - if (null === $comparison) { - if (is_array($description)) { - $comparison = Criteria::IN; - } elseif (preg_match('/[\%\*]/', $description)) { - $description = str_replace('*', '%', $description); - $comparison = Criteria::LIKE; - } - } - - return $this->addUsingAlias(TaxRuleTableMap::DESCRIPTION, $description, $comparison); - } - /** * Filter the query on the created_at column * @@ -563,7 +464,7 @@ abstract class TaxRuleQuery extends ModelCriteria * * @return ChildTaxRuleQuery The current query, for fluid interface */ - public function joinTaxRuleCountry($relationAlias = null, $joinType = Criteria::LEFT_JOIN) + public function joinTaxRuleCountry($relationAlias = null, $joinType = Criteria::INNER_JOIN) { $tableMap = $this->getTableMap(); $relationMap = $tableMap->getRelation('TaxRuleCountry'); @@ -598,7 +499,7 @@ abstract class TaxRuleQuery extends ModelCriteria * * @return \Thelia\Model\TaxRuleCountryQuery A secondary query class using the current class as primary query */ - public function useTaxRuleCountryQuery($relationAlias = null, $joinType = Criteria::LEFT_JOIN) + public function useTaxRuleCountryQuery($relationAlias = null, $joinType = Criteria::INNER_JOIN) { return $this ->joinTaxRuleCountry($relationAlias, $joinType) diff --git a/core/lib/Thelia/Model/Cart.php b/core/lib/Thelia/Model/Cart.php index 7493546ae..55b697379 100755 --- a/core/lib/Thelia/Model/Cart.php +++ b/core/lib/Thelia/Model/Cart.php @@ -71,4 +71,9 @@ class Cart extends BaseCart ->findOne() ; } + + public function getTaxedAmount() + { + + } } diff --git a/core/lib/Thelia/Model/Coupon.php b/core/lib/Thelia/Model/Coupon.php index d135ccbb0..f5788ff4f 100755 --- a/core/lib/Thelia/Model/Coupon.php +++ b/core/lib/Thelia/Model/Coupon.php @@ -1,9 +1,132 @@ . */ +/* */ +/**********************************************************************************/ namespace Thelia\Model; +use Propel\Runtime\Propel; +use Thelia\Constraint\Rule\CouponRuleInterface; +use Thelia\Coupon\CouponRuleCollection; use Thelia\Model\Base\Coupon as BaseCoupon; +use Thelia\Model\Map\CouponTableMap; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Used to provide an effect (mostly a discount) + * at the end of the Customer checkout tunnel + * It will be usable for a Customer only if it matches the Coupon criteria (Rules) + * + * @package Coupon + * @author Guillaume MOREL + * + */ +class Coupon extends BaseCoupon +{ + + use \Thelia\Model\Tools\ModelEventDispatcherTrait; + + + /** + * Constructor + * + * @param string $code Coupon Code + * @param string $title Coupon title + * @param float $amount Amount removed from the Total Checkout + * @param string $effect Coupon effect + * @param string $shortDescription Coupon short description + * @param string $description Coupon description + * @param boolean $isEnabled Enable/Disable + * @param \DateTime $expirationDate Coupon expiration date + * @param boolean $isAvailableOnSpecialOffers Is available on special offers + * @param boolean $isCumulative Is cumulative + * @param boolean $isRemovingPostage Is removing Postage + * @param int $maxUsage Coupon quantity + * @param CouponRuleCollection $rules CouponRuleInterface to add + * @param string $locale Coupon Language code ISO (ex: fr_FR) + */ + function createOrUpdate($code, $title, $amount, $effect, $shortDescription, $description, $isEnabled, $expirationDate, $isAvailableOnSpecialOffers, $isCumulative, $maxUsage, $rules, $locale = null) + { + $this->setCode($code) + ->setTitle($title) + ->setShortDescription($shortDescription) + ->setDescription($description) + ->setType($effect) + ->setAmount($amount) + ->setType($amount) + ->setIsEnabled($isEnabled) + ->setExpirationDate($expirationDate) + ->setIsAvailableOnSpecialOffers($isAvailableOnSpecialOffers) + ->setIsCumulative($isCumulative) + ->setMaxUsage($maxUsage) + ->setRules($rules); + + // Set object language (i18n) + if (!is_null($locale)) { + $this->setLocale($locale); + } + + $con = Propel::getWriteConnection(CouponTableMap::DATABASE_NAME); + $con->beginTransaction(); + try { + $this->save($con); + $con->commit(); + + } catch(\Exception $e) { + $con->rollback(); + throw $e; + } + } + +// /** +// * Set the value of [serialized_rules] column. +// * Convert a CouponRuleCollection into a serialized array of SerializableRule +// * +// * @param CouponRuleCollection $rules A set of Rules +// * +// * @return \Thelia\Model\Coupon The current object (for fluent API support) +// */ +// public function setRules(CouponRuleCollection $rules) +// { +// $serializedRules = null; +// if ($rules !== null) { +// /** @var $rule CouponRuleInterface */ +// foreach ($rules->getRules() as $rule) { +// $serializedRules[] = $rule->getSerializableRule(); +// } +// +// $serializedRules = (string) base64_encode(serialize($serializedRules)); +// } +// +// if ($this->serialized_rules !== $serializedRules) { +// $this->serialized_rules = $serializedRules; +// $this->modifiedColumns[] = CouponTableMap::SERIALIZED_RULES; +// } +// +// return $this; +// } + -class Coupon extends BaseCoupon { } diff --git a/core/lib/Thelia/Model/Currency.php b/core/lib/Thelia/Model/Currency.php index ef8d73735..843211d5a 100755 --- a/core/lib/Thelia/Model/Currency.php +++ b/core/lib/Thelia/Model/Currency.php @@ -13,6 +13,17 @@ class Currency extends BaseCurrency { use \Thelia\Model\Tools\PositionManagementTrait; + public static function getDefaultCurrency() + { + $currency = CurrencyQuery::create()->findOneByByDefault(1); + + if (null === $currency) { + throw new \RuntimeException("No default currency is defined. Please define one."); + } + + return $currency; + } + /** * {@inheritDoc} */ diff --git a/core/lib/Thelia/Model/Map/AccessoryTableMap.php b/core/lib/Thelia/Model/Map/AccessoryTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/AddressTableMap.php b/core/lib/Thelia/Model/Map/AddressTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/AdminGroupTableMap.php b/core/lib/Thelia/Model/Map/AdminGroupTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/AdminLogTableMap.php b/core/lib/Thelia/Model/Map/AdminLogTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/AdminTableMap.php b/core/lib/Thelia/Model/Map/AdminTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/AreaTableMap.php b/core/lib/Thelia/Model/Map/AreaTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/AttributeAvI18nTableMap.php b/core/lib/Thelia/Model/Map/AttributeAvI18nTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/AttributeAvTableMap.php b/core/lib/Thelia/Model/Map/AttributeAvTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/AttributeCategoryTableMap.php b/core/lib/Thelia/Model/Map/AttributeCategoryTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/AttributeCombinationTableMap.php b/core/lib/Thelia/Model/Map/AttributeCombinationTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/AttributeI18nTableMap.php b/core/lib/Thelia/Model/Map/AttributeI18nTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/AttributeTableMap.php b/core/lib/Thelia/Model/Map/AttributeTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/CartItemTableMap.php b/core/lib/Thelia/Model/Map/CartItemTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/CartTableMap.php b/core/lib/Thelia/Model/Map/CartTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/CategoryDocumentI18nTableMap.php b/core/lib/Thelia/Model/Map/CategoryDocumentI18nTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/CategoryDocumentTableMap.php b/core/lib/Thelia/Model/Map/CategoryDocumentTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/CategoryI18nTableMap.php b/core/lib/Thelia/Model/Map/CategoryI18nTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/CategoryImageI18nTableMap.php b/core/lib/Thelia/Model/Map/CategoryImageI18nTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/CategoryImageTableMap.php b/core/lib/Thelia/Model/Map/CategoryImageTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/CategoryTableMap.php b/core/lib/Thelia/Model/Map/CategoryTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/CategoryVersionTableMap.php b/core/lib/Thelia/Model/Map/CategoryVersionTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/ConfigI18nTableMap.php b/core/lib/Thelia/Model/Map/ConfigI18nTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/ConfigTableMap.php b/core/lib/Thelia/Model/Map/ConfigTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/ContentDocumentI18nTableMap.php b/core/lib/Thelia/Model/Map/ContentDocumentI18nTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/ContentDocumentTableMap.php b/core/lib/Thelia/Model/Map/ContentDocumentTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/ContentFolderTableMap.php b/core/lib/Thelia/Model/Map/ContentFolderTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/ContentI18nTableMap.php b/core/lib/Thelia/Model/Map/ContentI18nTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/ContentImageI18nTableMap.php b/core/lib/Thelia/Model/Map/ContentImageI18nTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/ContentImageTableMap.php b/core/lib/Thelia/Model/Map/ContentImageTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/ContentTableMap.php b/core/lib/Thelia/Model/Map/ContentTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/ContentVersionTableMap.php b/core/lib/Thelia/Model/Map/ContentVersionTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/CountryI18nTableMap.php b/core/lib/Thelia/Model/Map/CountryI18nTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/CountryTableMap.php b/core/lib/Thelia/Model/Map/CountryTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/CouponOrderTableMap.php b/core/lib/Thelia/Model/Map/CouponOrderTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/CouponRuleTableMap.php b/core/lib/Thelia/Model/Map/CouponRuleTableMap.php deleted file mode 100755 index 99faeac59..000000000 --- a/core/lib/Thelia/Model/Map/CouponRuleTableMap.php +++ /dev/null @@ -1,463 +0,0 @@ - array('Id', 'CouponId', 'Controller', 'Operation', 'Value', 'CreatedAt', 'UpdatedAt', ), - self::TYPE_STUDLYPHPNAME => array('id', 'couponId', 'controller', 'operation', 'value', 'createdAt', 'updatedAt', ), - self::TYPE_COLNAME => array(CouponRuleTableMap::ID, CouponRuleTableMap::COUPON_ID, CouponRuleTableMap::CONTROLLER, CouponRuleTableMap::OPERATION, CouponRuleTableMap::VALUE, CouponRuleTableMap::CREATED_AT, CouponRuleTableMap::UPDATED_AT, ), - self::TYPE_RAW_COLNAME => array('ID', 'COUPON_ID', 'CONTROLLER', 'OPERATION', 'VALUE', 'CREATED_AT', 'UPDATED_AT', ), - self::TYPE_FIELDNAME => array('id', 'coupon_id', 'controller', 'operation', 'value', 'created_at', 'updated_at', ), - self::TYPE_NUM => array(0, 1, 2, 3, 4, 5, 6, ) - ); - - /** - * holds an array of keys for quick access to the fieldnames array - * - * first dimension keys are the type constants - * e.g. self::$fieldKeys[self::TYPE_PHPNAME]['Id'] = 0 - */ - protected static $fieldKeys = array ( - self::TYPE_PHPNAME => array('Id' => 0, 'CouponId' => 1, 'Controller' => 2, 'Operation' => 3, 'Value' => 4, 'CreatedAt' => 5, 'UpdatedAt' => 6, ), - self::TYPE_STUDLYPHPNAME => array('id' => 0, 'couponId' => 1, 'controller' => 2, 'operation' => 3, 'value' => 4, 'createdAt' => 5, 'updatedAt' => 6, ), - self::TYPE_COLNAME => array(CouponRuleTableMap::ID => 0, CouponRuleTableMap::COUPON_ID => 1, CouponRuleTableMap::CONTROLLER => 2, CouponRuleTableMap::OPERATION => 3, CouponRuleTableMap::VALUE => 4, CouponRuleTableMap::CREATED_AT => 5, CouponRuleTableMap::UPDATED_AT => 6, ), - self::TYPE_RAW_COLNAME => array('ID' => 0, 'COUPON_ID' => 1, 'CONTROLLER' => 2, 'OPERATION' => 3, 'VALUE' => 4, 'CREATED_AT' => 5, 'UPDATED_AT' => 6, ), - self::TYPE_FIELDNAME => array('id' => 0, 'coupon_id' => 1, 'controller' => 2, 'operation' => 3, 'value' => 4, 'created_at' => 5, 'updated_at' => 6, ), - self::TYPE_NUM => array(0, 1, 2, 3, 4, 5, 6, ) - ); - - /** - * Initialize the table attributes and columns - * Relations are not initialized by this method since they are lazy loaded - * - * @return void - * @throws PropelException - */ - public function initialize() - { - // attributes - $this->setName('coupon_rule'); - $this->setPhpName('CouponRule'); - $this->setClassName('\\Thelia\\Model\\CouponRule'); - $this->setPackage('Thelia.Model'); - $this->setUseIdGenerator(true); - // columns - $this->addPrimaryKey('ID', 'Id', 'INTEGER', true, null, null); - $this->addForeignKey('COUPON_ID', 'CouponId', 'INTEGER', 'coupon', 'ID', true, null, null); - $this->addColumn('CONTROLLER', 'Controller', 'VARCHAR', false, 255, null); - $this->addColumn('OPERATION', 'Operation', 'VARCHAR', false, 255, null); - $this->addColumn('VALUE', 'Value', 'FLOAT', false, null, null); - $this->addColumn('CREATED_AT', 'CreatedAt', 'TIMESTAMP', false, null, null); - $this->addColumn('UPDATED_AT', 'UpdatedAt', 'TIMESTAMP', false, null, null); - } // initialize() - - /** - * Build the RelationMap objects for this table relationships - */ - public function buildRelations() - { - $this->addRelation('Coupon', '\\Thelia\\Model\\Coupon', RelationMap::MANY_TO_ONE, array('coupon_id' => 'id', ), 'CASCADE', 'RESTRICT'); - } // buildRelations() - - /** - * - * Gets the list of behaviors registered for this table - * - * @return array Associative array (name => parameters) of behaviors - */ - public function getBehaviors() - { - return array( - 'timestampable' => array('create_column' => 'created_at', 'update_column' => 'updated_at', ), - ); - } // getBehaviors() - - /** - * Retrieves a string version of the primary key from the DB resultset row that can be used to uniquely identify a row in this table. - * - * For tables with a single-column primary key, that simple pkey value will be returned. For tables with - * a multi-column primary key, a serialize()d version of the primary key will be returned. - * - * @param array $row resultset row. - * @param int $offset The 0-based offset for reading from the resultset row. - * @param string $indexType One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME - * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM - */ - public static function getPrimaryKeyHashFromRow($row, $offset = 0, $indexType = TableMap::TYPE_NUM) - { - // If the PK cannot be derived from the row, return NULL. - if ($row[TableMap::TYPE_NUM == $indexType ? 0 + $offset : static::translateFieldName('Id', TableMap::TYPE_PHPNAME, $indexType)] === null) { - return null; - } - - return (string) $row[TableMap::TYPE_NUM == $indexType ? 0 + $offset : static::translateFieldName('Id', TableMap::TYPE_PHPNAME, $indexType)]; - } - - /** - * Retrieves the primary key from the DB resultset row - * For tables with a single-column primary key, that simple pkey value will be returned. For tables with - * a multi-column primary key, an array of the primary key columns will be returned. - * - * @param array $row resultset row. - * @param int $offset The 0-based offset for reading from the resultset row. - * @param string $indexType One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME - * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM - * - * @return mixed The primary key of the row - */ - public static function getPrimaryKeyFromRow($row, $offset = 0, $indexType = TableMap::TYPE_NUM) - { - - return (int) $row[ - $indexType == TableMap::TYPE_NUM - ? 0 + $offset - : self::translateFieldName('Id', TableMap::TYPE_PHPNAME, $indexType) - ]; - } - - /** - * The class that the tableMap will make instances of. - * - * If $withPrefix is true, the returned path - * uses a dot-path notation which is translated into a path - * relative to a location on the PHP include_path. - * (e.g. path.to.MyClass -> 'path/to/MyClass.php') - * - * @param boolean $withPrefix Whether or not to return the path with the class name - * @return string path.to.ClassName - */ - public static function getOMClass($withPrefix = true) - { - return $withPrefix ? CouponRuleTableMap::CLASS_DEFAULT : CouponRuleTableMap::OM_CLASS; - } - - /** - * Populates an object of the default type or an object that inherit from the default. - * - * @param array $row row returned by DataFetcher->fetch(). - * @param int $offset The 0-based offset for reading from the resultset row. - * @param string $indexType The index type of $row. Mostly DataFetcher->getIndexType(). - One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME - * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. - * - * @throws PropelException Any exceptions caught during processing will be - * rethrown wrapped into a PropelException. - * @return array (CouponRule object, last column rank) - */ - public static function populateObject($row, $offset = 0, $indexType = TableMap::TYPE_NUM) - { - $key = CouponRuleTableMap::getPrimaryKeyHashFromRow($row, $offset, $indexType); - if (null !== ($obj = CouponRuleTableMap::getInstanceFromPool($key))) { - // We no longer rehydrate the object, since this can cause data loss. - // See http://www.propelorm.org/ticket/509 - // $obj->hydrate($row, $offset, true); // rehydrate - $col = $offset + CouponRuleTableMap::NUM_HYDRATE_COLUMNS; - } else { - $cls = CouponRuleTableMap::OM_CLASS; - $obj = new $cls(); - $col = $obj->hydrate($row, $offset, false, $indexType); - CouponRuleTableMap::addInstanceToPool($obj, $key); - } - - return array($obj, $col); - } - - /** - * The returned array will contain objects of the default type or - * objects that inherit from the default. - * - * @param DataFetcherInterface $dataFetcher - * @return array - * @throws PropelException Any exceptions caught during processing will be - * rethrown wrapped into a PropelException. - */ - public static function populateObjects(DataFetcherInterface $dataFetcher) - { - $results = array(); - - // set the class once to avoid overhead in the loop - $cls = static::getOMClass(false); - // populate the object(s) - while ($row = $dataFetcher->fetch()) { - $key = CouponRuleTableMap::getPrimaryKeyHashFromRow($row, 0, $dataFetcher->getIndexType()); - if (null !== ($obj = CouponRuleTableMap::getInstanceFromPool($key))) { - // We no longer rehydrate the object, since this can cause data loss. - // See http://www.propelorm.org/ticket/509 - // $obj->hydrate($row, 0, true); // rehydrate - $results[] = $obj; - } else { - $obj = new $cls(); - $obj->hydrate($row); - $results[] = $obj; - CouponRuleTableMap::addInstanceToPool($obj, $key); - } // if key exists - } - - return $results; - } - /** - * Add all the columns needed to create a new object. - * - * Note: any columns that were marked with lazyLoad="true" in the - * XML schema will not be added to the select list and only loaded - * on demand. - * - * @param Criteria $criteria object containing the columns to add. - * @param string $alias optional table alias - * @throws PropelException Any exceptions caught during processing will be - * rethrown wrapped into a PropelException. - */ - public static function addSelectColumns(Criteria $criteria, $alias = null) - { - if (null === $alias) { - $criteria->addSelectColumn(CouponRuleTableMap::ID); - $criteria->addSelectColumn(CouponRuleTableMap::COUPON_ID); - $criteria->addSelectColumn(CouponRuleTableMap::CONTROLLER); - $criteria->addSelectColumn(CouponRuleTableMap::OPERATION); - $criteria->addSelectColumn(CouponRuleTableMap::VALUE); - $criteria->addSelectColumn(CouponRuleTableMap::CREATED_AT); - $criteria->addSelectColumn(CouponRuleTableMap::UPDATED_AT); - } else { - $criteria->addSelectColumn($alias . '.ID'); - $criteria->addSelectColumn($alias . '.COUPON_ID'); - $criteria->addSelectColumn($alias . '.CONTROLLER'); - $criteria->addSelectColumn($alias . '.OPERATION'); - $criteria->addSelectColumn($alias . '.VALUE'); - $criteria->addSelectColumn($alias . '.CREATED_AT'); - $criteria->addSelectColumn($alias . '.UPDATED_AT'); - } - } - - /** - * Returns the TableMap related to this object. - * This method is not needed for general use but a specific application could have a need. - * @return TableMap - * @throws PropelException Any exceptions caught during processing will be - * rethrown wrapped into a PropelException. - */ - public static function getTableMap() - { - return Propel::getServiceContainer()->getDatabaseMap(CouponRuleTableMap::DATABASE_NAME)->getTable(CouponRuleTableMap::TABLE_NAME); - } - - /** - * Add a TableMap instance to the database for this tableMap class. - */ - public static function buildTableMap() - { - $dbMap = Propel::getServiceContainer()->getDatabaseMap(CouponRuleTableMap::DATABASE_NAME); - if (!$dbMap->hasTable(CouponRuleTableMap::TABLE_NAME)) { - $dbMap->addTableObject(new CouponRuleTableMap()); - } - } - - /** - * Performs a DELETE on the database, given a CouponRule or Criteria object OR a primary key value. - * - * @param mixed $values Criteria or CouponRule object or primary key or array of primary keys - * which is used to create the DELETE statement - * @param ConnectionInterface $con the connection to use - * @return int The number of affected rows (if supported by underlying database driver). This includes CASCADE-related rows - * if supported by native driver or if emulated using Propel. - * @throws PropelException Any exceptions caught during processing will be - * rethrown wrapped into a PropelException. - */ - public static function doDelete($values, ConnectionInterface $con = null) - { - if (null === $con) { - $con = Propel::getServiceContainer()->getWriteConnection(CouponRuleTableMap::DATABASE_NAME); - } - - if ($values instanceof Criteria) { - // rename for clarity - $criteria = $values; - } elseif ($values instanceof \Thelia\Model\CouponRule) { // it's a model object - // create criteria based on pk values - $criteria = $values->buildPkeyCriteria(); - } else { // it's a primary key, or an array of pks - $criteria = new Criteria(CouponRuleTableMap::DATABASE_NAME); - $criteria->add(CouponRuleTableMap::ID, (array) $values, Criteria::IN); - } - - $query = CouponRuleQuery::create()->mergeWith($criteria); - - if ($values instanceof Criteria) { CouponRuleTableMap::clearInstancePool(); - } elseif (!is_object($values)) { // it's a primary key, or an array of pks - foreach ((array) $values as $singleval) { CouponRuleTableMap::removeInstanceFromPool($singleval); - } - } - - return $query->delete($con); - } - - /** - * Deletes all rows from the coupon_rule table. - * - * @param ConnectionInterface $con the connection to use - * @return int The number of affected rows (if supported by underlying database driver). - */ - public static function doDeleteAll(ConnectionInterface $con = null) - { - return CouponRuleQuery::create()->doDeleteAll($con); - } - - /** - * Performs an INSERT on the database, given a CouponRule or Criteria object. - * - * @param mixed $criteria Criteria or CouponRule object containing data that is used to create the INSERT statement. - * @param ConnectionInterface $con the ConnectionInterface connection to use - * @return mixed The new primary key. - * @throws PropelException Any exceptions caught during processing will be - * rethrown wrapped into a PropelException. - */ - public static function doInsert($criteria, ConnectionInterface $con = null) - { - if (null === $con) { - $con = Propel::getServiceContainer()->getWriteConnection(CouponRuleTableMap::DATABASE_NAME); - } - - if ($criteria instanceof Criteria) { - $criteria = clone $criteria; // rename for clarity - } else { - $criteria = $criteria->buildCriteria(); // build Criteria from CouponRule object - } - - if ($criteria->containsKey(CouponRuleTableMap::ID) && $criteria->keyContainsValue(CouponRuleTableMap::ID) ) { - throw new PropelException('Cannot insert a value for auto-increment primary key ('.CouponRuleTableMap::ID.')'); - } - - - // Set the correct dbName - $query = CouponRuleQuery::create()->mergeWith($criteria); - - try { - // use transaction because $criteria could contain info - // for more than one table (I guess, conceivably) - $con->beginTransaction(); - $pk = $query->doInsert($con); - $con->commit(); - } catch (PropelException $e) { - $con->rollBack(); - throw $e; - } - - return $pk; - } - -} // CouponRuleTableMap -// This is the static code needed to register the TableMap for this table with the main Propel class. -// -CouponRuleTableMap::buildTableMap(); diff --git a/core/lib/Thelia/Model/Map/CouponTableMap.php b/core/lib/Thelia/Model/Map/CouponTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/CurrencyI18nTableMap.php b/core/lib/Thelia/Model/Map/CurrencyI18nTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/CurrencyTableMap.php b/core/lib/Thelia/Model/Map/CurrencyTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/CustomerTableMap.php b/core/lib/Thelia/Model/Map/CustomerTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/CustomerTitleI18nTableMap.php b/core/lib/Thelia/Model/Map/CustomerTitleI18nTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/CustomerTitleTableMap.php b/core/lib/Thelia/Model/Map/CustomerTitleTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/DelivzoneTableMap.php b/core/lib/Thelia/Model/Map/DelivzoneTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/FeatureAvI18nTableMap.php b/core/lib/Thelia/Model/Map/FeatureAvI18nTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/FeatureAvTableMap.php b/core/lib/Thelia/Model/Map/FeatureAvTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/FeatureCategoryTableMap.php b/core/lib/Thelia/Model/Map/FeatureCategoryTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/FeatureI18nTableMap.php b/core/lib/Thelia/Model/Map/FeatureI18nTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/FeatureProductTableMap.php b/core/lib/Thelia/Model/Map/FeatureProductTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/FeatureTableMap.php b/core/lib/Thelia/Model/Map/FeatureTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/FolderDocumentI18nTableMap.php b/core/lib/Thelia/Model/Map/FolderDocumentI18nTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/FolderDocumentTableMap.php b/core/lib/Thelia/Model/Map/FolderDocumentTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/FolderI18nTableMap.php b/core/lib/Thelia/Model/Map/FolderI18nTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/FolderImageI18nTableMap.php b/core/lib/Thelia/Model/Map/FolderImageI18nTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/FolderImageTableMap.php b/core/lib/Thelia/Model/Map/FolderImageTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/FolderTableMap.php b/core/lib/Thelia/Model/Map/FolderTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/FolderVersionTableMap.php b/core/lib/Thelia/Model/Map/FolderVersionTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/GroupI18nTableMap.php b/core/lib/Thelia/Model/Map/GroupI18nTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/GroupModuleTableMap.php b/core/lib/Thelia/Model/Map/GroupModuleTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/GroupResourceTableMap.php b/core/lib/Thelia/Model/Map/GroupResourceTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/GroupTableMap.php b/core/lib/Thelia/Model/Map/GroupTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/LangTableMap.php b/core/lib/Thelia/Model/Map/LangTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/MessageI18nTableMap.php b/core/lib/Thelia/Model/Map/MessageI18nTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/MessageTableMap.php b/core/lib/Thelia/Model/Map/MessageTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/MessageVersionTableMap.php b/core/lib/Thelia/Model/Map/MessageVersionTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/ModuleI18nTableMap.php b/core/lib/Thelia/Model/Map/ModuleI18nTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/ModuleTableMap.php b/core/lib/Thelia/Model/Map/ModuleTableMap.php old mode 100755 new mode 100644 index cccaa890a..dae9fda4a --- a/core/lib/Thelia/Model/Map/ModuleTableMap.php +++ b/core/lib/Thelia/Model/Map/ModuleTableMap.php @@ -57,7 +57,7 @@ class ModuleTableMap extends TableMap /** * The total number of columns */ - const NUM_COLUMNS = 7; + const NUM_COLUMNS = 8; /** * The number of lazy-loaded columns @@ -67,7 +67,7 @@ class ModuleTableMap extends TableMap /** * The number of columns to hydrate (NUM_COLUMNS - NUM_LAZY_LOAD_COLUMNS) */ - const NUM_HYDRATE_COLUMNS = 7; + const NUM_HYDRATE_COLUMNS = 8; /** * the column name for the ID field @@ -94,6 +94,11 @@ class ModuleTableMap extends TableMap */ const POSITION = 'module.POSITION'; + /** + * the column name for the FULL_NAMESPACE field + */ + const FULL_NAMESPACE = 'module.FULL_NAMESPACE'; + /** * the column name for the CREATED_AT field */ @@ -125,12 +130,12 @@ class ModuleTableMap extends TableMap * e.g. self::$fieldNames[self::TYPE_PHPNAME][0] = 'Id' */ protected static $fieldNames = array ( - self::TYPE_PHPNAME => array('Id', 'Code', 'Type', 'Activate', 'Position', 'CreatedAt', 'UpdatedAt', ), - self::TYPE_STUDLYPHPNAME => array('id', 'code', 'type', 'activate', 'position', 'createdAt', 'updatedAt', ), - self::TYPE_COLNAME => array(ModuleTableMap::ID, ModuleTableMap::CODE, ModuleTableMap::TYPE, ModuleTableMap::ACTIVATE, ModuleTableMap::POSITION, ModuleTableMap::CREATED_AT, ModuleTableMap::UPDATED_AT, ), - self::TYPE_RAW_COLNAME => array('ID', 'CODE', 'TYPE', 'ACTIVATE', 'POSITION', 'CREATED_AT', 'UPDATED_AT', ), - self::TYPE_FIELDNAME => array('id', 'code', 'type', 'activate', 'position', 'created_at', 'updated_at', ), - self::TYPE_NUM => array(0, 1, 2, 3, 4, 5, 6, ) + self::TYPE_PHPNAME => array('Id', 'Code', 'Type', 'Activate', 'Position', 'FullNamespace', 'CreatedAt', 'UpdatedAt', ), + self::TYPE_STUDLYPHPNAME => array('id', 'code', 'type', 'activate', 'position', 'fullNamespace', 'createdAt', 'updatedAt', ), + self::TYPE_COLNAME => array(ModuleTableMap::ID, ModuleTableMap::CODE, ModuleTableMap::TYPE, ModuleTableMap::ACTIVATE, ModuleTableMap::POSITION, ModuleTableMap::FULL_NAMESPACE, ModuleTableMap::CREATED_AT, ModuleTableMap::UPDATED_AT, ), + self::TYPE_RAW_COLNAME => array('ID', 'CODE', 'TYPE', 'ACTIVATE', 'POSITION', 'FULL_NAMESPACE', 'CREATED_AT', 'UPDATED_AT', ), + self::TYPE_FIELDNAME => array('id', 'code', 'type', 'activate', 'position', 'full_namespace', 'created_at', 'updated_at', ), + self::TYPE_NUM => array(0, 1, 2, 3, 4, 5, 6, 7, ) ); /** @@ -140,12 +145,12 @@ class ModuleTableMap extends TableMap * e.g. self::$fieldKeys[self::TYPE_PHPNAME]['Id'] = 0 */ protected static $fieldKeys = array ( - self::TYPE_PHPNAME => array('Id' => 0, 'Code' => 1, 'Type' => 2, 'Activate' => 3, 'Position' => 4, 'CreatedAt' => 5, 'UpdatedAt' => 6, ), - self::TYPE_STUDLYPHPNAME => array('id' => 0, 'code' => 1, 'type' => 2, 'activate' => 3, 'position' => 4, 'createdAt' => 5, 'updatedAt' => 6, ), - self::TYPE_COLNAME => array(ModuleTableMap::ID => 0, ModuleTableMap::CODE => 1, ModuleTableMap::TYPE => 2, ModuleTableMap::ACTIVATE => 3, ModuleTableMap::POSITION => 4, ModuleTableMap::CREATED_AT => 5, ModuleTableMap::UPDATED_AT => 6, ), - self::TYPE_RAW_COLNAME => array('ID' => 0, 'CODE' => 1, 'TYPE' => 2, 'ACTIVATE' => 3, 'POSITION' => 4, 'CREATED_AT' => 5, 'UPDATED_AT' => 6, ), - self::TYPE_FIELDNAME => array('id' => 0, 'code' => 1, 'type' => 2, 'activate' => 3, 'position' => 4, 'created_at' => 5, 'updated_at' => 6, ), - self::TYPE_NUM => array(0, 1, 2, 3, 4, 5, 6, ) + self::TYPE_PHPNAME => array('Id' => 0, 'Code' => 1, 'Type' => 2, 'Activate' => 3, 'Position' => 4, 'FullNamespace' => 5, 'CreatedAt' => 6, 'UpdatedAt' => 7, ), + self::TYPE_STUDLYPHPNAME => array('id' => 0, 'code' => 1, 'type' => 2, 'activate' => 3, 'position' => 4, 'fullNamespace' => 5, 'createdAt' => 6, 'updatedAt' => 7, ), + self::TYPE_COLNAME => array(ModuleTableMap::ID => 0, ModuleTableMap::CODE => 1, ModuleTableMap::TYPE => 2, ModuleTableMap::ACTIVATE => 3, ModuleTableMap::POSITION => 4, ModuleTableMap::FULL_NAMESPACE => 5, ModuleTableMap::CREATED_AT => 6, ModuleTableMap::UPDATED_AT => 7, ), + self::TYPE_RAW_COLNAME => array('ID' => 0, 'CODE' => 1, 'TYPE' => 2, 'ACTIVATE' => 3, 'POSITION' => 4, 'FULL_NAMESPACE' => 5, 'CREATED_AT' => 6, 'UPDATED_AT' => 7, ), + self::TYPE_FIELDNAME => array('id' => 0, 'code' => 1, 'type' => 2, 'activate' => 3, 'position' => 4, 'full_namespace' => 5, 'created_at' => 6, 'updated_at' => 7, ), + self::TYPE_NUM => array(0, 1, 2, 3, 4, 5, 6, 7, ) ); /** @@ -169,6 +174,7 @@ class ModuleTableMap extends TableMap $this->addColumn('TYPE', 'Type', 'TINYINT', true, null, null); $this->addColumn('ACTIVATE', 'Activate', 'TINYINT', false, null, null); $this->addColumn('POSITION', 'Position', 'INTEGER', false, null, null); + $this->addColumn('FULL_NAMESPACE', 'FullNamespace', 'VARCHAR', false, 255, null); $this->addColumn('CREATED_AT', 'CreatedAt', 'TIMESTAMP', false, null, null); $this->addColumn('UPDATED_AT', 'UpdatedAt', 'TIMESTAMP', false, null, null); } // initialize() @@ -349,6 +355,7 @@ class ModuleTableMap extends TableMap $criteria->addSelectColumn(ModuleTableMap::TYPE); $criteria->addSelectColumn(ModuleTableMap::ACTIVATE); $criteria->addSelectColumn(ModuleTableMap::POSITION); + $criteria->addSelectColumn(ModuleTableMap::FULL_NAMESPACE); $criteria->addSelectColumn(ModuleTableMap::CREATED_AT); $criteria->addSelectColumn(ModuleTableMap::UPDATED_AT); } else { @@ -357,6 +364,7 @@ class ModuleTableMap extends TableMap $criteria->addSelectColumn($alias . '.TYPE'); $criteria->addSelectColumn($alias . '.ACTIVATE'); $criteria->addSelectColumn($alias . '.POSITION'); + $criteria->addSelectColumn($alias . '.FULL_NAMESPACE'); $criteria->addSelectColumn($alias . '.CREATED_AT'); $criteria->addSelectColumn($alias . '.UPDATED_AT'); } diff --git a/core/lib/Thelia/Model/Map/OrderAddressTableMap.php b/core/lib/Thelia/Model/Map/OrderAddressTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/OrderFeatureTableMap.php b/core/lib/Thelia/Model/Map/OrderFeatureTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/OrderProductTableMap.php b/core/lib/Thelia/Model/Map/OrderProductTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/OrderStatusI18nTableMap.php b/core/lib/Thelia/Model/Map/OrderStatusI18nTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/OrderStatusTableMap.php b/core/lib/Thelia/Model/Map/OrderStatusTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/OrderTableMap.php b/core/lib/Thelia/Model/Map/OrderTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/ProductCategoryTableMap.php b/core/lib/Thelia/Model/Map/ProductCategoryTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/ProductDocumentI18nTableMap.php b/core/lib/Thelia/Model/Map/ProductDocumentI18nTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/ProductDocumentTableMap.php b/core/lib/Thelia/Model/Map/ProductDocumentTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/ProductI18nTableMap.php b/core/lib/Thelia/Model/Map/ProductI18nTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/ProductImageI18nTableMap.php b/core/lib/Thelia/Model/Map/ProductImageI18nTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/ProductImageTableMap.php b/core/lib/Thelia/Model/Map/ProductImageTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/ProductPriceTableMap.php b/core/lib/Thelia/Model/Map/ProductPriceTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/ProductSaleElementsTableMap.php b/core/lib/Thelia/Model/Map/ProductSaleElementsTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/ProductTableMap.php b/core/lib/Thelia/Model/Map/ProductTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/ProductVersionTableMap.php b/core/lib/Thelia/Model/Map/ProductVersionTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/ResourceI18nTableMap.php b/core/lib/Thelia/Model/Map/ResourceI18nTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/ResourceTableMap.php b/core/lib/Thelia/Model/Map/ResourceTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/TaxI18nTableMap.php b/core/lib/Thelia/Model/Map/TaxI18nTableMap.php old mode 100755 new mode 100644 diff --git a/core/lib/Thelia/Model/Map/TaxRuleCountryTableMap.php b/core/lib/Thelia/Model/Map/TaxRuleCountryTableMap.php old mode 100755 new mode 100644 index 42b4e6f59..5282d67fa --- a/core/lib/Thelia/Model/Map/TaxRuleCountryTableMap.php +++ b/core/lib/Thelia/Model/Map/TaxRuleCountryTableMap.php @@ -57,7 +57,7 @@ class TaxRuleCountryTableMap extends TableMap /** * The total number of columns */ - const NUM_COLUMNS = 7; + const NUM_COLUMNS = 6; /** * The number of lazy-loaded columns @@ -67,12 +67,7 @@ class TaxRuleCountryTableMap extends TableMap /** * The number of columns to hydrate (NUM_COLUMNS - NUM_LAZY_LOAD_COLUMNS) */ - const NUM_HYDRATE_COLUMNS = 7; - - /** - * the column name for the ID field - */ - const ID = 'tax_rule_country.ID'; + const NUM_HYDRATE_COLUMNS = 6; /** * the column name for the TAX_RULE_ID field @@ -90,9 +85,9 @@ class TaxRuleCountryTableMap extends TableMap const TAX_ID = 'tax_rule_country.TAX_ID'; /** - * the column name for the NONE field + * the column name for the POSITION field */ - const NONE = 'tax_rule_country.NONE'; + const POSITION = 'tax_rule_country.POSITION'; /** * the column name for the CREATED_AT field @@ -116,12 +111,12 @@ class TaxRuleCountryTableMap extends TableMap * e.g. self::$fieldNames[self::TYPE_PHPNAME][0] = 'Id' */ protected static $fieldNames = array ( - self::TYPE_PHPNAME => array('Id', 'TaxRuleId', 'CountryId', 'TaxId', 'None', 'CreatedAt', 'UpdatedAt', ), - self::TYPE_STUDLYPHPNAME => array('id', 'taxRuleId', 'countryId', 'taxId', 'none', 'createdAt', 'updatedAt', ), - self::TYPE_COLNAME => array(TaxRuleCountryTableMap::ID, TaxRuleCountryTableMap::TAX_RULE_ID, TaxRuleCountryTableMap::COUNTRY_ID, TaxRuleCountryTableMap::TAX_ID, TaxRuleCountryTableMap::NONE, TaxRuleCountryTableMap::CREATED_AT, TaxRuleCountryTableMap::UPDATED_AT, ), - self::TYPE_RAW_COLNAME => array('ID', 'TAX_RULE_ID', 'COUNTRY_ID', 'TAX_ID', 'NONE', 'CREATED_AT', 'UPDATED_AT', ), - self::TYPE_FIELDNAME => array('id', 'tax_rule_id', 'country_id', 'tax_id', 'none', 'created_at', 'updated_at', ), - self::TYPE_NUM => array(0, 1, 2, 3, 4, 5, 6, ) + self::TYPE_PHPNAME => array('TaxRuleId', 'CountryId', 'TaxId', 'Position', 'CreatedAt', 'UpdatedAt', ), + self::TYPE_STUDLYPHPNAME => array('taxRuleId', 'countryId', 'taxId', 'position', 'createdAt', 'updatedAt', ), + self::TYPE_COLNAME => array(TaxRuleCountryTableMap::TAX_RULE_ID, TaxRuleCountryTableMap::COUNTRY_ID, TaxRuleCountryTableMap::TAX_ID, TaxRuleCountryTableMap::POSITION, TaxRuleCountryTableMap::CREATED_AT, TaxRuleCountryTableMap::UPDATED_AT, ), + self::TYPE_RAW_COLNAME => array('TAX_RULE_ID', 'COUNTRY_ID', 'TAX_ID', 'POSITION', 'CREATED_AT', 'UPDATED_AT', ), + self::TYPE_FIELDNAME => array('tax_rule_id', 'country_id', 'tax_id', 'position', 'created_at', 'updated_at', ), + self::TYPE_NUM => array(0, 1, 2, 3, 4, 5, ) ); /** @@ -131,12 +126,12 @@ class TaxRuleCountryTableMap extends TableMap * e.g. self::$fieldKeys[self::TYPE_PHPNAME]['Id'] = 0 */ protected static $fieldKeys = array ( - self::TYPE_PHPNAME => array('Id' => 0, 'TaxRuleId' => 1, 'CountryId' => 2, 'TaxId' => 3, 'None' => 4, 'CreatedAt' => 5, 'UpdatedAt' => 6, ), - self::TYPE_STUDLYPHPNAME => array('id' => 0, 'taxRuleId' => 1, 'countryId' => 2, 'taxId' => 3, 'none' => 4, 'createdAt' => 5, 'updatedAt' => 6, ), - self::TYPE_COLNAME => array(TaxRuleCountryTableMap::ID => 0, TaxRuleCountryTableMap::TAX_RULE_ID => 1, TaxRuleCountryTableMap::COUNTRY_ID => 2, TaxRuleCountryTableMap::TAX_ID => 3, TaxRuleCountryTableMap::NONE => 4, TaxRuleCountryTableMap::CREATED_AT => 5, TaxRuleCountryTableMap::UPDATED_AT => 6, ), - self::TYPE_RAW_COLNAME => array('ID' => 0, 'TAX_RULE_ID' => 1, 'COUNTRY_ID' => 2, 'TAX_ID' => 3, 'NONE' => 4, 'CREATED_AT' => 5, 'UPDATED_AT' => 6, ), - self::TYPE_FIELDNAME => array('id' => 0, 'tax_rule_id' => 1, 'country_id' => 2, 'tax_id' => 3, 'none' => 4, 'created_at' => 5, 'updated_at' => 6, ), - self::TYPE_NUM => array(0, 1, 2, 3, 4, 5, 6, ) + self::TYPE_PHPNAME => array('TaxRuleId' => 0, 'CountryId' => 1, 'TaxId' => 2, 'Position' => 3, 'CreatedAt' => 4, 'UpdatedAt' => 5, ), + self::TYPE_STUDLYPHPNAME => array('taxRuleId' => 0, 'countryId' => 1, 'taxId' => 2, 'position' => 3, 'createdAt' => 4, 'updatedAt' => 5, ), + self::TYPE_COLNAME => array(TaxRuleCountryTableMap::TAX_RULE_ID => 0, TaxRuleCountryTableMap::COUNTRY_ID => 1, TaxRuleCountryTableMap::TAX_ID => 2, TaxRuleCountryTableMap::POSITION => 3, TaxRuleCountryTableMap::CREATED_AT => 4, TaxRuleCountryTableMap::UPDATED_AT => 5, ), + self::TYPE_RAW_COLNAME => array('TAX_RULE_ID' => 0, 'COUNTRY_ID' => 1, 'TAX_ID' => 2, 'POSITION' => 3, 'CREATED_AT' => 4, 'UPDATED_AT' => 5, ), + self::TYPE_FIELDNAME => array('tax_rule_id' => 0, 'country_id' => 1, 'tax_id' => 2, 'position' => 3, 'created_at' => 4, 'updated_at' => 5, ), + self::TYPE_NUM => array(0, 1, 2, 3, 4, 5, ) ); /** @@ -155,11 +150,10 @@ class TaxRuleCountryTableMap extends TableMap $this->setPackage('Thelia.Model'); $this->setUseIdGenerator(false); // columns - $this->addPrimaryKey('ID', 'Id', 'INTEGER', true, null, null); - $this->addForeignKey('TAX_RULE_ID', 'TaxRuleId', 'INTEGER', 'tax_rule', 'ID', false, null, null); - $this->addForeignKey('COUNTRY_ID', 'CountryId', 'INTEGER', 'country', 'ID', false, null, null); - $this->addForeignKey('TAX_ID', 'TaxId', 'INTEGER', 'tax', 'ID', false, null, null); - $this->addColumn('NONE', 'None', 'TINYINT', false, null, null); + $this->addForeignPrimaryKey('TAX_RULE_ID', 'TaxRuleId', 'INTEGER' , 'tax_rule', 'ID', true, null, null); + $this->addForeignPrimaryKey('COUNTRY_ID', 'CountryId', 'INTEGER' , 'country', 'ID', true, null, null); + $this->addForeignPrimaryKey('TAX_ID', 'TaxId', 'INTEGER' , 'tax', 'ID', true, null, null); + $this->addColumn('POSITION', 'Position', 'INTEGER', true, null, null); $this->addColumn('CREATED_AT', 'CreatedAt', 'TIMESTAMP', false, null, null); $this->addColumn('UPDATED_AT', 'UpdatedAt', 'TIMESTAMP', false, null, null); } // initialize() @@ -169,7 +163,7 @@ class TaxRuleCountryTableMap extends TableMap */ public function buildRelations() { - $this->addRelation('Tax', '\\Thelia\\Model\\Tax', RelationMap::MANY_TO_ONE, array('tax_id' => 'id', ), 'SET NULL', 'RESTRICT'); + $this->addRelation('Tax', '\\Thelia\\Model\\Tax', RelationMap::MANY_TO_ONE, array('tax_id' => 'id', ), 'CASCADE', 'RESTRICT'); $this->addRelation('TaxRule', '\\Thelia\\Model\\TaxRule', RelationMap::MANY_TO_ONE, array('tax_rule_id' => 'id', ), 'CASCADE', 'RESTRICT'); $this->addRelation('Country', '\\Thelia\\Model\\Country', RelationMap::MANY_TO_ONE, array('country_id' => 'id', ), 'CASCADE', 'RESTRICT'); } // buildRelations() @@ -187,6 +181,59 @@ class TaxRuleCountryTableMap extends TableMap ); } // getBehaviors() + /** + * Adds an object to the instance pool. + * + * Propel keeps cached copies of objects in an instance pool when they are retrieved + * from the database. In some cases you may need to explicitly add objects + * to the cache in order to ensure that the same objects are always returned by find*() + * and findPk*() calls. + * + * @param \Thelia\Model\TaxRuleCountry $obj A \Thelia\Model\TaxRuleCountry object. + * @param string $key (optional) key to use for instance map (for performance boost if key was already calculated externally). + */ + public static function addInstanceToPool($obj, $key = null) + { + if (Propel::isInstancePoolingEnabled()) { + if (null === $key) { + $key = serialize(array((string) $obj->getTaxRuleId(), (string) $obj->getCountryId(), (string) $obj->getTaxId())); + } // if key === null + self::$instances[$key] = $obj; + } + } + + /** + * Removes an object from the instance pool. + * + * Propel keeps cached copies of objects in an instance pool when they are retrieved + * from the database. In some cases -- especially when you override doDelete + * methods in your stub classes -- you may need to explicitly remove objects + * from the cache in order to prevent returning objects that no longer exist. + * + * @param mixed $value A \Thelia\Model\TaxRuleCountry object or a primary key value. + */ + public static function removeInstanceFromPool($value) + { + if (Propel::isInstancePoolingEnabled() && null !== $value) { + if (is_object($value) && $value instanceof \Thelia\Model\TaxRuleCountry) { + $key = serialize(array((string) $value->getTaxRuleId(), (string) $value->getCountryId(), (string) $value->getTaxId())); + + } elseif (is_array($value) && count($value) === 3) { + // assume we've been passed a primary key"; + $key = serialize(array((string) $value[0], (string) $value[1], (string) $value[2])); + } elseif ($value instanceof Criteria) { + self::$instances = []; + + return; + } else { + $e = new PropelException("Invalid value passed to removeInstanceFromPool(). Expected primary key or \Thelia\Model\TaxRuleCountry object; got " . (is_object($value) ? get_class($value) . ' object.' : var_export($value, true))); + throw $e; + } + + unset(self::$instances[$key]); + } + } + /** * Retrieves a string version of the primary key from the DB resultset row that can be used to uniquely identify a row in this table. * @@ -201,11 +248,11 @@ class TaxRuleCountryTableMap extends TableMap public static function getPrimaryKeyHashFromRow($row, $offset = 0, $indexType = TableMap::TYPE_NUM) { // If the PK cannot be derived from the row, return NULL. - if ($row[TableMap::TYPE_NUM == $indexType ? 0 + $offset : static::translateFieldName('Id', TableMap::TYPE_PHPNAME, $indexType)] === null) { + if ($row[TableMap::TYPE_NUM == $indexType ? 0 + $offset : static::translateFieldName('TaxRuleId', TableMap::TYPE_PHPNAME, $indexType)] === null && $row[TableMap::TYPE_NUM == $indexType ? 1 + $offset : static::translateFieldName('CountryId', TableMap::TYPE_PHPNAME, $indexType)] === null && $row[TableMap::TYPE_NUM == $indexType ? 2 + $offset : static::translateFieldName('TaxId', TableMap::TYPE_PHPNAME, $indexType)] === null) { return null; } - return (string) $row[TableMap::TYPE_NUM == $indexType ? 0 + $offset : static::translateFieldName('Id', TableMap::TYPE_PHPNAME, $indexType)]; + return serialize(array((string) $row[TableMap::TYPE_NUM == $indexType ? 0 + $offset : static::translateFieldName('TaxRuleId', TableMap::TYPE_PHPNAME, $indexType)], (string) $row[TableMap::TYPE_NUM == $indexType ? 1 + $offset : static::translateFieldName('CountryId', TableMap::TYPE_PHPNAME, $indexType)], (string) $row[TableMap::TYPE_NUM == $indexType ? 2 + $offset : static::translateFieldName('TaxId', TableMap::TYPE_PHPNAME, $indexType)])); } /** @@ -223,11 +270,7 @@ class TaxRuleCountryTableMap extends TableMap public static function getPrimaryKeyFromRow($row, $offset = 0, $indexType = TableMap::TYPE_NUM) { - return (int) $row[ - $indexType == TableMap::TYPE_NUM - ? 0 + $offset - : self::translateFieldName('Id', TableMap::TYPE_PHPNAME, $indexType) - ]; + return $pks; } /** @@ -325,19 +368,17 @@ class TaxRuleCountryTableMap extends TableMap public static function addSelectColumns(Criteria $criteria, $alias = null) { if (null === $alias) { - $criteria->addSelectColumn(TaxRuleCountryTableMap::ID); $criteria->addSelectColumn(TaxRuleCountryTableMap::TAX_RULE_ID); $criteria->addSelectColumn(TaxRuleCountryTableMap::COUNTRY_ID); $criteria->addSelectColumn(TaxRuleCountryTableMap::TAX_ID); - $criteria->addSelectColumn(TaxRuleCountryTableMap::NONE); + $criteria->addSelectColumn(TaxRuleCountryTableMap::POSITION); $criteria->addSelectColumn(TaxRuleCountryTableMap::CREATED_AT); $criteria->addSelectColumn(TaxRuleCountryTableMap::UPDATED_AT); } else { - $criteria->addSelectColumn($alias . '.ID'); $criteria->addSelectColumn($alias . '.TAX_RULE_ID'); $criteria->addSelectColumn($alias . '.COUNTRY_ID'); $criteria->addSelectColumn($alias . '.TAX_ID'); - $criteria->addSelectColumn($alias . '.NONE'); + $criteria->addSelectColumn($alias . '.POSITION'); $criteria->addSelectColumn($alias . '.CREATED_AT'); $criteria->addSelectColumn($alias . '.UPDATED_AT'); } @@ -391,7 +432,18 @@ class TaxRuleCountryTableMap extends TableMap $criteria = $values->buildPkeyCriteria(); } else { // it's a primary key, or an array of pks $criteria = new Criteria(TaxRuleCountryTableMap::DATABASE_NAME); - $criteria->add(TaxRuleCountryTableMap::ID, (array) $values, Criteria::IN); + // primary key is composite; we therefore, expect + // the primary key passed to be an array of pkey values + if (count($values) == count($values, COUNT_RECURSIVE)) { + // array is not multi-dimensional + $values = array($values); + } + foreach ($values as $value) { + $criterion = $criteria->getNewCriterion(TaxRuleCountryTableMap::TAX_RULE_ID, $value[0]); + $criterion->addAnd($criteria->getNewCriterion(TaxRuleCountryTableMap::COUNTRY_ID, $value[1])); + $criterion->addAnd($criteria->getNewCriterion(TaxRuleCountryTableMap::TAX_ID, $value[2])); + $criteria->addOr($criterion); + } } $query = TaxRuleCountryQuery::create()->mergeWith($criteria); diff --git a/core/lib/Thelia/Model/Map/TaxRuleI18nTableMap.php b/core/lib/Thelia/Model/Map/TaxRuleI18nTableMap.php old mode 100755 new mode 100644 index 1f0ed1e96..012ad2e72 --- a/core/lib/Thelia/Model/Map/TaxRuleI18nTableMap.php +++ b/core/lib/Thelia/Model/Map/TaxRuleI18nTableMap.php @@ -57,7 +57,7 @@ class TaxRuleI18nTableMap extends TableMap /** * The total number of columns */ - const NUM_COLUMNS = 2; + const NUM_COLUMNS = 4; /** * The number of lazy-loaded columns @@ -67,7 +67,7 @@ class TaxRuleI18nTableMap extends TableMap /** * The number of columns to hydrate (NUM_COLUMNS - NUM_LAZY_LOAD_COLUMNS) */ - const NUM_HYDRATE_COLUMNS = 2; + const NUM_HYDRATE_COLUMNS = 4; /** * the column name for the ID field @@ -79,6 +79,16 @@ class TaxRuleI18nTableMap extends TableMap */ const LOCALE = 'tax_rule_i18n.LOCALE'; + /** + * the column name for the TITLE field + */ + const TITLE = 'tax_rule_i18n.TITLE'; + + /** + * the column name for the DESCRIPTION field + */ + const DESCRIPTION = 'tax_rule_i18n.DESCRIPTION'; + /** * The default string format for model objects of the related table */ @@ -91,12 +101,12 @@ class TaxRuleI18nTableMap extends TableMap * e.g. self::$fieldNames[self::TYPE_PHPNAME][0] = 'Id' */ protected static $fieldNames = array ( - self::TYPE_PHPNAME => array('Id', 'Locale', ), - self::TYPE_STUDLYPHPNAME => array('id', 'locale', ), - self::TYPE_COLNAME => array(TaxRuleI18nTableMap::ID, TaxRuleI18nTableMap::LOCALE, ), - self::TYPE_RAW_COLNAME => array('ID', 'LOCALE', ), - self::TYPE_FIELDNAME => array('id', 'locale', ), - self::TYPE_NUM => array(0, 1, ) + self::TYPE_PHPNAME => array('Id', 'Locale', 'Title', 'Description', ), + self::TYPE_STUDLYPHPNAME => array('id', 'locale', 'title', 'description', ), + self::TYPE_COLNAME => array(TaxRuleI18nTableMap::ID, TaxRuleI18nTableMap::LOCALE, TaxRuleI18nTableMap::TITLE, TaxRuleI18nTableMap::DESCRIPTION, ), + self::TYPE_RAW_COLNAME => array('ID', 'LOCALE', 'TITLE', 'DESCRIPTION', ), + self::TYPE_FIELDNAME => array('id', 'locale', 'title', 'description', ), + self::TYPE_NUM => array(0, 1, 2, 3, ) ); /** @@ -106,12 +116,12 @@ class TaxRuleI18nTableMap extends TableMap * e.g. self::$fieldKeys[self::TYPE_PHPNAME]['Id'] = 0 */ protected static $fieldKeys = array ( - self::TYPE_PHPNAME => array('Id' => 0, 'Locale' => 1, ), - self::TYPE_STUDLYPHPNAME => array('id' => 0, 'locale' => 1, ), - self::TYPE_COLNAME => array(TaxRuleI18nTableMap::ID => 0, TaxRuleI18nTableMap::LOCALE => 1, ), - self::TYPE_RAW_COLNAME => array('ID' => 0, 'LOCALE' => 1, ), - self::TYPE_FIELDNAME => array('id' => 0, 'locale' => 1, ), - self::TYPE_NUM => array(0, 1, ) + self::TYPE_PHPNAME => array('Id' => 0, 'Locale' => 1, 'Title' => 2, 'Description' => 3, ), + self::TYPE_STUDLYPHPNAME => array('id' => 0, 'locale' => 1, 'title' => 2, 'description' => 3, ), + self::TYPE_COLNAME => array(TaxRuleI18nTableMap::ID => 0, TaxRuleI18nTableMap::LOCALE => 1, TaxRuleI18nTableMap::TITLE => 2, TaxRuleI18nTableMap::DESCRIPTION => 3, ), + self::TYPE_RAW_COLNAME => array('ID' => 0, 'LOCALE' => 1, 'TITLE' => 2, 'DESCRIPTION' => 3, ), + self::TYPE_FIELDNAME => array('id' => 0, 'locale' => 1, 'title' => 2, 'description' => 3, ), + self::TYPE_NUM => array(0, 1, 2, 3, ) ); /** @@ -132,6 +142,8 @@ class TaxRuleI18nTableMap extends TableMap // columns $this->addForeignPrimaryKey('ID', 'Id', 'INTEGER' , 'tax_rule', 'ID', true, null, null); $this->addPrimaryKey('LOCALE', 'Locale', 'VARCHAR', true, 5, 'en_US'); + $this->addColumn('TITLE', 'Title', 'VARCHAR', false, 255, null); + $this->addColumn('DESCRIPTION', 'Description', 'LONGVARCHAR', false, null, null); } // initialize() /** @@ -331,9 +343,13 @@ class TaxRuleI18nTableMap extends TableMap if (null === $alias) { $criteria->addSelectColumn(TaxRuleI18nTableMap::ID); $criteria->addSelectColumn(TaxRuleI18nTableMap::LOCALE); + $criteria->addSelectColumn(TaxRuleI18nTableMap::TITLE); + $criteria->addSelectColumn(TaxRuleI18nTableMap::DESCRIPTION); } else { $criteria->addSelectColumn($alias . '.ID'); $criteria->addSelectColumn($alias . '.LOCALE'); + $criteria->addSelectColumn($alias . '.TITLE'); + $criteria->addSelectColumn($alias . '.DESCRIPTION'); } } diff --git a/core/lib/Thelia/Model/Map/TaxRuleTableMap.php b/core/lib/Thelia/Model/Map/TaxRuleTableMap.php old mode 100755 new mode 100644 index cc5f628b9..391e23b6d --- a/core/lib/Thelia/Model/Map/TaxRuleTableMap.php +++ b/core/lib/Thelia/Model/Map/TaxRuleTableMap.php @@ -57,7 +57,7 @@ class TaxRuleTableMap extends TableMap /** * The total number of columns */ - const NUM_COLUMNS = 6; + const NUM_COLUMNS = 3; /** * The number of lazy-loaded columns @@ -67,28 +67,13 @@ class TaxRuleTableMap extends TableMap /** * The number of columns to hydrate (NUM_COLUMNS - NUM_LAZY_LOAD_COLUMNS) */ - const NUM_HYDRATE_COLUMNS = 6; + const NUM_HYDRATE_COLUMNS = 3; /** * the column name for the ID field */ const ID = 'tax_rule.ID'; - /** - * the column name for the CODE field - */ - const CODE = 'tax_rule.CODE'; - - /** - * the column name for the TITLE field - */ - const TITLE = 'tax_rule.TITLE'; - - /** - * the column name for the DESCRIPTION field - */ - const DESCRIPTION = 'tax_rule.DESCRIPTION'; - /** * the column name for the CREATED_AT field */ @@ -120,12 +105,12 @@ class TaxRuleTableMap extends TableMap * e.g. self::$fieldNames[self::TYPE_PHPNAME][0] = 'Id' */ protected static $fieldNames = array ( - self::TYPE_PHPNAME => array('Id', 'Code', 'Title', 'Description', 'CreatedAt', 'UpdatedAt', ), - self::TYPE_STUDLYPHPNAME => array('id', 'code', 'title', 'description', 'createdAt', 'updatedAt', ), - self::TYPE_COLNAME => array(TaxRuleTableMap::ID, TaxRuleTableMap::CODE, TaxRuleTableMap::TITLE, TaxRuleTableMap::DESCRIPTION, TaxRuleTableMap::CREATED_AT, TaxRuleTableMap::UPDATED_AT, ), - self::TYPE_RAW_COLNAME => array('ID', 'CODE', 'TITLE', 'DESCRIPTION', 'CREATED_AT', 'UPDATED_AT', ), - self::TYPE_FIELDNAME => array('id', 'code', 'title', 'description', 'created_at', 'updated_at', ), - self::TYPE_NUM => array(0, 1, 2, 3, 4, 5, ) + self::TYPE_PHPNAME => array('Id', 'CreatedAt', 'UpdatedAt', ), + self::TYPE_STUDLYPHPNAME => array('id', 'createdAt', 'updatedAt', ), + self::TYPE_COLNAME => array(TaxRuleTableMap::ID, TaxRuleTableMap::CREATED_AT, TaxRuleTableMap::UPDATED_AT, ), + self::TYPE_RAW_COLNAME => array('ID', 'CREATED_AT', 'UPDATED_AT', ), + self::TYPE_FIELDNAME => array('id', 'created_at', 'updated_at', ), + self::TYPE_NUM => array(0, 1, 2, ) ); /** @@ -135,12 +120,12 @@ class TaxRuleTableMap extends TableMap * e.g. self::$fieldKeys[self::TYPE_PHPNAME]['Id'] = 0 */ protected static $fieldKeys = array ( - self::TYPE_PHPNAME => array('Id' => 0, 'Code' => 1, 'Title' => 2, 'Description' => 3, 'CreatedAt' => 4, 'UpdatedAt' => 5, ), - self::TYPE_STUDLYPHPNAME => array('id' => 0, 'code' => 1, 'title' => 2, 'description' => 3, 'createdAt' => 4, 'updatedAt' => 5, ), - self::TYPE_COLNAME => array(TaxRuleTableMap::ID => 0, TaxRuleTableMap::CODE => 1, TaxRuleTableMap::TITLE => 2, TaxRuleTableMap::DESCRIPTION => 3, TaxRuleTableMap::CREATED_AT => 4, TaxRuleTableMap::UPDATED_AT => 5, ), - self::TYPE_RAW_COLNAME => array('ID' => 0, 'CODE' => 1, 'TITLE' => 2, 'DESCRIPTION' => 3, 'CREATED_AT' => 4, 'UPDATED_AT' => 5, ), - self::TYPE_FIELDNAME => array('id' => 0, 'code' => 1, 'title' => 2, 'description' => 3, 'created_at' => 4, 'updated_at' => 5, ), - self::TYPE_NUM => array(0, 1, 2, 3, 4, 5, ) + self::TYPE_PHPNAME => array('Id' => 0, 'CreatedAt' => 1, 'UpdatedAt' => 2, ), + self::TYPE_STUDLYPHPNAME => array('id' => 0, 'createdAt' => 1, 'updatedAt' => 2, ), + self::TYPE_COLNAME => array(TaxRuleTableMap::ID => 0, TaxRuleTableMap::CREATED_AT => 1, TaxRuleTableMap::UPDATED_AT => 2, ), + self::TYPE_RAW_COLNAME => array('ID' => 0, 'CREATED_AT' => 1, 'UPDATED_AT' => 2, ), + self::TYPE_FIELDNAME => array('id' => 0, 'created_at' => 1, 'updated_at' => 2, ), + self::TYPE_NUM => array(0, 1, 2, ) ); /** @@ -160,9 +145,6 @@ class TaxRuleTableMap extends TableMap $this->setUseIdGenerator(true); // columns $this->addPrimaryKey('ID', 'Id', 'INTEGER', true, null, null); - $this->addColumn('CODE', 'Code', 'VARCHAR', false, 45, null); - $this->addColumn('TITLE', 'Title', 'VARCHAR', false, 255, null); - $this->addColumn('DESCRIPTION', 'Description', 'LONGVARCHAR', false, null, null); $this->addColumn('CREATED_AT', 'CreatedAt', 'TIMESTAMP', false, null, null); $this->addColumn('UPDATED_AT', 'UpdatedAt', 'TIMESTAMP', false, null, null); } // initialize() @@ -187,7 +169,7 @@ class TaxRuleTableMap extends TableMap { return array( 'timestampable' => array('create_column' => 'created_at', 'update_column' => 'updated_at', ), - 'i18n' => array('i18n_table' => '%TABLE%_i18n', 'i18n_phpname' => '%PHPNAME%I18n', 'i18n_columns' => '', 'locale_column' => 'locale', 'locale_length' => '5', 'default_locale' => '', 'locale_alias' => '', ), + 'i18n' => array('i18n_table' => '%TABLE%_i18n', 'i18n_phpname' => '%PHPNAME%I18n', 'i18n_columns' => 'title, description', 'locale_column' => 'locale', 'locale_length' => '5', 'default_locale' => '', 'locale_alias' => '', ), ); } // getBehaviors() /** @@ -341,16 +323,10 @@ class TaxRuleTableMap extends TableMap { if (null === $alias) { $criteria->addSelectColumn(TaxRuleTableMap::ID); - $criteria->addSelectColumn(TaxRuleTableMap::CODE); - $criteria->addSelectColumn(TaxRuleTableMap::TITLE); - $criteria->addSelectColumn(TaxRuleTableMap::DESCRIPTION); $criteria->addSelectColumn(TaxRuleTableMap::CREATED_AT); $criteria->addSelectColumn(TaxRuleTableMap::UPDATED_AT); } else { $criteria->addSelectColumn($alias . '.ID'); - $criteria->addSelectColumn($alias . '.CODE'); - $criteria->addSelectColumn($alias . '.TITLE'); - $criteria->addSelectColumn($alias . '.DESCRIPTION'); $criteria->addSelectColumn($alias . '.CREATED_AT'); $criteria->addSelectColumn($alias . '.UPDATED_AT'); } diff --git a/core/lib/Thelia/Model/Map/TaxTableMap.php b/core/lib/Thelia/Model/Map/TaxTableMap.php old mode 100755 new mode 100644 index 6d43f20e9..11e5047ce --- a/core/lib/Thelia/Model/Map/TaxTableMap.php +++ b/core/lib/Thelia/Model/Map/TaxTableMap.php @@ -160,7 +160,7 @@ class TaxTableMap extends TableMap */ public function buildRelations() { - $this->addRelation('TaxRuleCountry', '\\Thelia\\Model\\TaxRuleCountry', RelationMap::ONE_TO_MANY, array('id' => 'tax_id', ), 'SET NULL', 'RESTRICT', 'TaxRuleCountries'); + $this->addRelation('TaxRuleCountry', '\\Thelia\\Model\\TaxRuleCountry', RelationMap::ONE_TO_MANY, array('id' => 'tax_id', ), 'CASCADE', 'RESTRICT', 'TaxRuleCountries'); $this->addRelation('TaxI18n', '\\Thelia\\Model\\TaxI18n', RelationMap::ONE_TO_MANY, array('id' => 'id', ), 'CASCADE', null, 'TaxI18ns'); } // buildRelations() diff --git a/core/lib/Thelia/Model/Order.php b/core/lib/Thelia/Model/Order.php index 91582750a..f8e6db193 100755 --- a/core/lib/Thelia/Model/Order.php +++ b/core/lib/Thelia/Model/Order.php @@ -6,4 +6,15 @@ use Thelia\Model\Base\Order as BaseOrder; class Order extends BaseOrder { + /** + * calculate the total amount + * + * @TODO create body method + * + * @return int + */ + public function getTotalAmount() + { + return 2; + } } diff --git a/core/lib/Thelia/Model/Product.php b/core/lib/Thelia/Model/Product.php index 6c7ffbe44..06c4640d0 100755 --- a/core/lib/Thelia/Model/Product.php +++ b/core/lib/Thelia/Model/Product.php @@ -2,8 +2,10 @@ namespace Thelia\Model; +use Propel\Runtime\Exception\PropelException; use Thelia\Model\Base\Product as BaseProduct; use Thelia\Tools\URL; +use Thelia\TaxEngine\Calculator; class Product extends BaseProduct { @@ -11,4 +13,21 @@ class Product extends BaseProduct { return URL::getInstance()->retrieve('product', $this->getId(), $locale)->toString(); } + + public function getRealLowestPrice($virtualColumnName = 'real_lowest_price') + { + try { + $amount = $this->getVirtualColumn($virtualColumnName); + } catch(PropelException $e) { + throw new PropelException("Virtual column `$virtualColumnName` does not exist in Product::getRealLowestPrice"); + } + + return $amount; + } + + public function getTaxedPrice(Country $country) + { + $taxCalculator = new Calculator(); + return $taxCalculator->load($this, $country)->getTaxedPrice($this->getRealLowestPrice()); + } } diff --git a/core/lib/Thelia/Model/ProductSaleElements.php b/core/lib/Thelia/Model/ProductSaleElements.php index cec9c49a7..184e37d0a 100755 --- a/core/lib/Thelia/Model/ProductSaleElements.php +++ b/core/lib/Thelia/Model/ProductSaleElements.php @@ -3,8 +3,41 @@ namespace Thelia\Model; use Thelia\Model\Base\ProductSaleElements as BaseProductSaleElements; +use Thelia\TaxEngine\Calculator; - class ProductSaleElements extends BaseProductSaleElements +class ProductSaleElements extends BaseProductSaleElements { + public function getPrice($virtualColumnName = 'price_PRICE') + { + try { + $amount = $this->getVirtualColumn($virtualColumnName); + } catch(PropelException $e) { + throw new PropelException("Virtual column `$virtualColumnName` does not exist in ProductSaleElements::getPrice"); + } + return $amount; + } + + public function getPromoPrice($virtualColumnName = 'price_PROMO_PRICE') + { + try { + $amount = $this->getVirtualColumn($virtualColumnName); + } catch(PropelException $e) { + throw new PropelException("Virtual column `$virtualColumnName` does not exist in ProductSaleElements::getPromoPrice"); + } + + return $amount; + } + + public function getTaxedPrice(Country $country) + { + $taxCalculator = new Calculator(); + return $taxCalculator->load($this->getProduct(), $country)->getTaxedPrice($this->getPrice()); + } + + public function getTaxedPromoPrice(Country $country) + { + $taxCalculator = new Calculator(); + return $taxCalculator->load($this->getProduct(), $country)->getTaxedPrice($this->getPromoPrice()); + } } diff --git a/core/lib/Thelia/Model/Rewriting.php b/core/lib/Thelia/Model/Rewriting.php new file mode 100644 index 000000000..8d6f75fab --- /dev/null +++ b/core/lib/Thelia/Model/Rewriting.php @@ -0,0 +1,9 @@ +getRate(); + + if($rate === null) { + return 0; + } + + return $amount * $rate * 0.01; + } + + public function getTaxRuleCountryPosition() + { + try { + $taxRuleCountryPosition = $this->getVirtualColumn(TaxRuleQuery::ALIAS_FOR_TAX_RULE_COUNTRY_POSITION); + } catch(PropelException $e) { + throw new PropelException("Virtual column `" . TaxRuleQuery::ALIAS_FOR_TAX_RULE_COUNTRY_POSITION . "` does not exist in Tax::getTaxRuleCountryPosition"); + } + + return $taxRuleCountryPosition; + } + + public function getTaxRuleRateSum() + { + try { + $taxRuleRateSum = $this->getVirtualColumn(TaxRuleQuery::ALIAS_FOR_TAX_RATE_SUM); + } catch(PropelException $e) { + throw new PropelException("Virtual column `" . TaxRuleQuery::ALIAS_FOR_TAX_RATE_SUM . "` does not exist in Tax::getTaxRuleRateSum"); + } + + return $taxRuleRateSum; + } } diff --git a/core/lib/Thelia/Model/TaxRuleQuery.php b/core/lib/Thelia/Model/TaxRuleQuery.php index 8cb79562d..f9c6cf1e5 100755 --- a/core/lib/Thelia/Model/TaxRuleQuery.php +++ b/core/lib/Thelia/Model/TaxRuleQuery.php @@ -2,8 +2,10 @@ namespace Thelia\Model; +use Propel\Runtime\ActiveQuery\Criteria; use Thelia\Model\Base\TaxRuleQuery as BaseTaxRuleQuery; - +use Thelia\Model\Map\TaxRuleCountryTableMap; +use Thelia\Model\Map\TaxTableMap; /** * Skeleton subclass for performing query and update operations on the 'tax_rule' table. @@ -15,6 +17,26 @@ use Thelia\Model\Base\TaxRuleQuery as BaseTaxRuleQuery; * long as it does not already exist in the output directory. * */ -class TaxRuleQuery extends BaseTaxRuleQuery { +class TaxRuleQuery extends BaseTaxRuleQuery +{ + const ALIAS_FOR_TAX_RULE_COUNTRY_POSITION = 'taxRuleCountryPosition'; + const ALIAS_FOR_TAX_RATE_SUM = 'taxRateSum'; + public function getTaxCalculatorGroupedCollection(Product $product, Country $country) + { + $search = TaxQuery::create() + ->filterByTaxRuleCountry( + TaxRuleCountryQuery::create() + ->filterByCountry($country, Criteria::EQUAL) + ->filterByTaxRuleId($product->getTaxRuleId()) + ->groupByPosition() + ->orderByPosition() + ->find() + ) + ->withColumn(TaxRuleCountryTableMap::POSITION, self::ALIAS_FOR_TAX_RULE_COUNTRY_POSITION) + ->withColumn('ROUND(SUM(' . TaxTableMap::RATE . '), 2)', self::ALIAS_FOR_TAX_RATE_SUM) + ; + + return $search->find(); + } } // TaxRuleQuery diff --git a/core/lib/Thelia/Model/Tools/PositionManagementTrait.php b/core/lib/Thelia/Model/Tools/PositionManagementTrait.php index 9e0b1f35c..eb71564eb 100644 --- a/core/lib/Thelia/Model/Tools/PositionManagementTrait.php +++ b/core/lib/Thelia/Model/Tools/PositionManagementTrait.php @@ -55,7 +55,7 @@ trait PositionManagementTrait { ->orderByPosition(Criteria::DESC) ->limit(1); - if ($parent !== null) $last->filterByParent($parent); + if ($parent !== null) $query->filterByParent($parent); $last = $query->findOne() ; diff --git a/core/lib/Thelia/Module/BaseModule.php b/core/lib/Thelia/Module/BaseModule.php index 07cc1d116..145da3c02 100755 --- a/core/lib/Thelia/Module/BaseModule.php +++ b/core/lib/Thelia/Module/BaseModule.php @@ -24,7 +24,9 @@ namespace Thelia\Module; -abstract class BaseModule +use Symfony\Component\DependencyInjection\ContainerAware; + +abstract class BaseModule extends ContainerAware { public function __construct() @@ -37,6 +39,19 @@ abstract class BaseModule } + public function hasContainer() + { + return null === $this->container; + } + + public function getContainer() + { + if($this->hasContainer() === false) { + throw new \RuntimeException("Sorry, container his not available in this context"); + } + return $this->container; + } + abstract public function install(); abstract public function destroy(); diff --git a/core/lib/Thelia/Module/BaseModuleInterface.php b/core/lib/Thelia/Module/BaseModuleInterface.php new file mode 100644 index 000000000..2db450830 --- /dev/null +++ b/core/lib/Thelia/Module/BaseModuleInterface.php @@ -0,0 +1,37 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Module; + + +use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\HttpFoundation\Request; + +interface BaseModuleInterface { + + public function setRequest(Request $request); + public function getRequest(); + + public function setDispatcher(EventDispatcherInterface $dispatcher); + public function getDispatcher(); +} \ No newline at end of file diff --git a/core/lib/Thelia/Module/DeliveryModuleInterface.php b/core/lib/Thelia/Module/DeliveryModuleInterface.php new file mode 100644 index 000000000..b8ffcfc01 --- /dev/null +++ b/core/lib/Thelia/Module/DeliveryModuleInterface.php @@ -0,0 +1,36 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Module; + + +interface DeliveryModuleInterface extends BaseModuleInterface { + + /** + * + * calculate and return delivery price + * + * @return mixed + */ + public function calculate($country = null); +} \ No newline at end of file diff --git a/core/lib/Thelia/TaxEngine/Calculator.php b/core/lib/Thelia/TaxEngine/Calculator.php new file mode 100755 index 000000000..66c4fcbbf --- /dev/null +++ b/core/lib/Thelia/TaxEngine/Calculator.php @@ -0,0 +1,95 @@ +. */ +/* */ +/*************************************************************************************/ +namespace Thelia\TaxEngine; + +use Thelia\Exception\TaxEngineException; +use Thelia\Model\Country; +use Thelia\Model\Product; +use Thelia\Model\TaxRuleQuery; + +/** + * Class Calculator + * @package Thelia\TaxEngine + * @author Etienne Roudeix + */ +class Calculator +{ + protected $taxRuleQuery = null; + + protected $taxRulesGroupedCollection = null; + + protected $product = null; + protected $country = null; + + public function __construct() + { + $this->taxRuleQuery = new TaxRuleQuery(); + } + + public function load(Product $product, Country $country) + { + $this->product = null; + $this->country = null; + $this->taxRulesGroupedCollection = null; + + if($product->getId() === null) { + throw new TaxEngineException('Product id is empty in Calculator::load', TaxEngineException::UNDEFINED_PRODUCT); + } + if($country->getId() === null) { + throw new TaxEngineException('Country id is empty in Calculator::load', TaxEngineException::UNDEFINED_COUNTRY); + } + + $this->product = $product; + $this->country = $country; + + $this->taxRulesGroupedCollection = $this->taxRuleQuery->getTaxCalculatorGroupedCollection($product, $country); + + return $this; + } + + public function getTaxAmount($amount) + { + if(null === $this->taxRulesGroupedCollection) { + throw new TaxEngineException('Tax rules collection is empty in Calculator::getTaxAmount', TaxEngineException::UNDEFINED_TAX_RULES_COLLECTION); + } + + if(false === filter_var($amount, FILTER_VALIDATE_FLOAT)) { + throw new TaxEngineException('BAD AMOUNT FORMAT', TaxEngineException::BAD_AMOUNT_FORMAT); + } + + $totalTaxAmount = 0; + foreach($this->taxRulesGroupedCollection as $taxRule) { + $rateSum = $taxRule->getTaxRuleRateSum(); + $taxAmount = $amount * $rateSum * 0.01; + $totalTaxAmount += $taxAmount; + $amount += $taxAmount; + } + + return $totalTaxAmount; + } + + public function getTaxedPrice($amount) + { + return $amount + $this->getTaxAmount($amount); + } +} diff --git a/core/lib/Thelia/Tests/Constraint/ConstraintFactoryTest.php b/core/lib/Thelia/Tests/Constraint/ConstraintFactoryTest.php new file mode 100644 index 000000000..70d6e498c --- /dev/null +++ b/core/lib/Thelia/Tests/Constraint/ConstraintFactoryTest.php @@ -0,0 +1,229 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Constraint; + +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Thelia\Constraint\Rule\AvailableForTotalAmountManager; +use Thelia\Constraint\Rule\AvailableForXArticlesManager; +use Thelia\Constraint\Rule\Operators; +use Thelia\Coupon\CouponBaseAdapter; +use Thelia\Coupon\CouponRuleCollection; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Unit Test ConstraintManager Class + * + * @package Constraint + * @author Guillaume MOREL + * + */ +class ConstraintFactoryTest extends \PHPUnit_Framework_TestCase +{ + + /** + * Sets up the fixture, for example, opens a network connection. + * This method is called before a test is executed. + */ + public function setUp() + { + } + + /** + * Check the Rules serialization module + */ + public function testBuild() + { + $stubTranslator = $this->getMockBuilder('\Thelia\Core\Translation\Translator') + ->disableOriginalConstructor() + ->getMock(); + + $stubAdapter = $this->getMockBuilder('\Thelia\Coupon\CouponBaseAdapter') + ->disableOriginalConstructor() + ->getMock(); + + $stubAdapter->expects($this->any()) + ->method('getTranslator') + ->will($this->returnValue($stubTranslator)); + + $rule1 = new AvailableForTotalAmountManager($stubAdapter); + $operators = array( + AvailableForTotalAmountManager::INPUT1 => Operators::SUPERIOR, + AvailableForTotalAmountManager::INPUT2 => Operators::EQUAL + ); + $values = array( + AvailableForTotalAmountManager::INPUT1 => 40.00, + AvailableForTotalAmountManager::INPUT2 => 'EUR' + ); + $rule1->setValidatorsFromForm($operators, $values); + + /** @var ConstraintManager $constraintManager */ + $constraintFactory = new ConstraintFactory($this->getContainer()); + $ruleManager1 = $constraintFactory->build($rule1->getServiceId(), $operators, $values); + + $expected = $rule1; + $actual = $ruleManager1; + + $this->assertEquals($expected, $actual); + $this->assertEquals($rule1->getServiceId(), $ruleManager1->getServiceId()); + $this->assertEquals($rule1->getValidators(), $ruleManager1->getValidators()); + } + + /** + * Check the Rules serialization module + */ + public function testBuildFail() + { + $stubTranslator = $this->getMockBuilder('\Thelia\Core\Translation\Translator') + ->disableOriginalConstructor() + ->getMock(); + + $stubAdapter = $this->getMockBuilder('\Thelia\Coupon\CouponBaseAdapter') + ->disableOriginalConstructor() + ->getMock(); + + $stubAdapter->expects($this->any()) + ->method('getTranslator') + ->will($this->returnValue($stubTranslator)); + + $rule1 = new AvailableForTotalAmountManager($stubAdapter); + $operators = array( + AvailableForTotalAmountManager::INPUT1 => Operators::SUPERIOR, + AvailableForTotalAmountManager::INPUT2 => Operators::EQUAL + ); + $values = array( + AvailableForTotalAmountManager::INPUT1 => 40.00, + AvailableForTotalAmountManager::INPUT2 => 'EUR' + ); + $rule1->setValidatorsFromForm($operators, $values); + + /** @var ConstraintManager $constraintManager */ + $constraintFactory = new ConstraintFactory($this->getContainer()); + $ruleManager1 = $constraintFactory->build('unset.service', $operators, $values); + + $expected = false; + $actual = $ruleManager1; + + $this->assertEquals($expected, $actual); + } + + + /** + * Check the Rules serialization module + */ + public function testRuleSerialisation() + { + $stubTranslator = $this->getMockBuilder('\Thelia\Core\Translation\Translator') + ->disableOriginalConstructor() + ->getMock(); + + $stubAdapter = $this->getMockBuilder('\Thelia\Coupon\CouponBaseAdapter') + ->disableOriginalConstructor() + ->getMock(); + + $stubAdapter->expects($this->any()) + ->method('getTranslator') + ->will($this->returnValue($stubTranslator)); + + $rule1 = new AvailableForTotalAmountManager($stubAdapter); + $operators = array( + AvailableForTotalAmountManager::INPUT1 => Operators::SUPERIOR, + AvailableForTotalAmountManager::INPUT2 => Operators::EQUAL + ); + $values = array( + AvailableForTotalAmountManager::INPUT1 => 40.00, + AvailableForTotalAmountManager::INPUT2 => 'EUR' + ); + $rule1->setValidatorsFromForm($operators, $values); + + $rule2 = new AvailableForTotalAmountManager($stubAdapter); + $operators = array( + AvailableForTotalAmountManager::INPUT1 => Operators::SUPERIOR, + AvailableForTotalAmountManager::INPUT2 => Operators::EQUAL + ); + $values = array( + AvailableForTotalAmountManager::INPUT1 => 400.00, + AvailableForTotalAmountManager::INPUT2 => 'EUR' + ); + $rule2->setValidatorsFromForm($operators, $values); + + $rules = new CouponRuleCollection(); + $rules->add($rule1); + $rules->add($rule2); + + /** @var ConstraintManager $constraintManager */ + $constraintFactory = new ConstraintFactory($this->getContainer()); + + $serializedRules = $constraintFactory->serializeCouponRuleCollection($rules); + $unserializedRules = $constraintFactory->unserializeCouponRuleCollection($serializedRules); + + $expected = (string)$rules; + $actual = (string)$unserializedRules; + + $this->assertEquals($expected, $actual); + } + + /** + * Get Mocked Container with 2 Rules + * + * @return ContainerBuilder + */ + public function getContainer() + { + $container = new ContainerBuilder(); + + $stubTranslator = $this->getMockBuilder('\Thelia\Core\Translation\Translator') + ->disableOriginalConstructor() + ->getMock(); + + $stubAdapter = $this->getMockBuilder('\Thelia\Coupon\CouponBaseAdapter') + ->disableOriginalConstructor() + ->getMock(); + + $stubAdapter->expects($this->any()) + ->method('getTranslator') + ->will($this->returnValue($stubTranslator)); + + $rule1 = new AvailableForTotalAmountManager($stubAdapter); + $rule2 = new AvailableForXArticlesManager($stubAdapter); + + $adapter = new CouponBaseAdapter($container); + + $container->set('thelia.constraint.rule.available_for_total_amount', $rule1); + $container->set('thelia.constraint.rule.available_for_x_articles', $rule2); + $container->set('thelia.adapter', $adapter); + + return $container; + } + + /** + * Tears down the fixture, for example, closes a network connection. + * This method is called after a test is executed. + */ + protected function tearDown() + { + } +} diff --git a/core/lib/Thelia/Tests/Constraint/ConstraintValidatorTest.php b/core/lib/Thelia/Tests/Constraint/ConstraintValidatorTest.php new file mode 100644 index 000000000..28ac4b952 --- /dev/null +++ b/core/lib/Thelia/Tests/Constraint/ConstraintValidatorTest.php @@ -0,0 +1,337 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Constraint; + +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Thelia\Constraint\Rule\AvailableForTotalAmountManager; +use Thelia\Constraint\Rule\AvailableForXArticlesManager; +use Thelia\Constraint\Rule\Operators; +use Thelia\Coupon\CouponBaseAdapter; +use Thelia\Coupon\CouponRuleCollection; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Unit Test ConstraintValidator Class + * + * @package Constraint + * @author Guillaume MOREL + * + */ +class ConstraintValidatorTest extends \PHPUnit_Framework_TestCase +{ + + /** + * Sets up the fixture, for example, opens a network connection. + * This method is called before a test is executed. + */ + public function setUp() + { + } + + public function testTestSuccess1Rules() + { + $ConstraintValidator = new ConstraintValidator(); + $stubAdapter = $this->getMockBuilder('\Thelia\Coupon\CouponBaseAdapter') + ->disableOriginalConstructor() + ->getMock(); + + $stubAdapter->expects($this->any()) + ->method('getCartTotalPrice') + ->will($this->returnValue(401)); + $stubAdapter->expects($this->any()) + ->method('getCheckoutCurrency') + ->will($this->returnValue('EUR')); + + $rule1 = new AvailableForTotalAmountManager($stubAdapter); + $operators = array( + AvailableForTotalAmountManager::INPUT1 => '>', + AvailableForTotalAmountManager::INPUT2 => '==' + ); + $values = array( + AvailableForTotalAmountManager::INPUT1 => 400.00, + AvailableForTotalAmountManager::INPUT2 => 'EUR'); + $rule1->setValidatorsFromForm($operators, $values); + + + $rules = new CouponRuleCollection(); + $rules->add($rule1); + + $isValid = $ConstraintValidator->test($rules); + + $expected = true; + $actual =$isValid; + $this->assertEquals($expected, $actual); + } + + public function testTestFail1Rules() + { + $ConstraintValidator = new ConstraintValidator(); + $stubAdapter = $this->getMockBuilder('\Thelia\Coupon\CouponBaseAdapter') + ->disableOriginalConstructor() + ->getMock(); + + $stubAdapter->expects($this->any()) + ->method('getCartTotalPrice') + ->will($this->returnValue(400)); + $stubAdapter->expects($this->any()) + ->method('getCheckoutCurrency') + ->will($this->returnValue('EUR')); + + $rule1 = new AvailableForTotalAmountManager($stubAdapter); + $operators = array( + AvailableForTotalAmountManager::INPUT1 => '>', + AvailableForTotalAmountManager::INPUT2 => '==' + ); + $values = array( + AvailableForTotalAmountManager::INPUT1 => 400.00, + AvailableForTotalAmountManager::INPUT2 => 'EUR'); + $rule1->setValidatorsFromForm($operators, $values); + + + $rules = new CouponRuleCollection(); + $rules->add($rule1); + + $isValid = $ConstraintValidator->test($rules); + + $expected = false; + $actual =$isValid; + $this->assertEquals($expected, $actual, 'Constraints validator always think Customer is matching rules'); + } + + public function testTestSuccess2Rules() + { + $ConstraintValidator = new ConstraintValidator(); + $stubAdapter = $this->getMockBuilder('\Thelia\Coupon\CouponBaseAdapter') + ->disableOriginalConstructor() + ->getMock(); + + $stubAdapter->expects($this->any()) + ->method('getCartTotalPrice') + ->will($this->returnValue(401)); + $stubAdapter->expects($this->any()) + ->method('getCheckoutCurrency') + ->will($this->returnValue('EUR')); + $stubAdapter->expects($this->any()) + ->method('getNbArticlesInCart') + ->will($this->returnValue(5)); + + $rule1 = new AvailableForTotalAmountManager($stubAdapter); + $operators = array( + AvailableForTotalAmountManager::INPUT1 => '>', + AvailableForTotalAmountManager::INPUT2 => '==' + ); + $values = array( + AvailableForTotalAmountManager::INPUT1 => 400.00, + AvailableForTotalAmountManager::INPUT2 => 'EUR'); + $rule1->setValidatorsFromForm($operators, $values); + + $rule2 = new AvailableForXArticlesManager($stubAdapter); + $operators = array( + AvailableForXArticlesManager::INPUT1 => '>' + ); + $values = array( + AvailableForXArticlesManager::INPUT1 => 4 + ); + $rule2->setValidatorsFromForm($operators, $values); + + $rules = new CouponRuleCollection(); + $rules->add($rule1); + $rules->add($rule2); + + $isValid = $ConstraintValidator->test($rules); + + $expected = true; + $actual =$isValid; + $this->assertEquals($expected, $actual); + } + + public function testTestFail2Rules() + { + $ConstraintValidator = new ConstraintValidator(); + $stubAdapter = $this->getMockBuilder('\Thelia\Coupon\CouponBaseAdapter') + ->disableOriginalConstructor() + ->getMock(); + + $stubAdapter->expects($this->any()) + ->method('getCartTotalPrice') + ->will($this->returnValue(400)); + $stubAdapter->expects($this->any()) + ->method('getCheckoutCurrency') + ->will($this->returnValue('EUR')); + $stubAdapter->expects($this->any()) + ->method('getNbArticlesInCart') + ->will($this->returnValue(5)); + + $rule1 = new AvailableForTotalAmountManager($stubAdapter); + $operators = array( + AvailableForTotalAmountManager::INPUT1 => '>', + AvailableForTotalAmountManager::INPUT2 => '==' + ); + $values = array( + AvailableForTotalAmountManager::INPUT1 => 400.00, + AvailableForTotalAmountManager::INPUT2 => 'EUR'); + $rule1->setValidatorsFromForm($operators, $values); + + $rule2 = new AvailableForXArticlesManager($stubAdapter); + $operators = array( + AvailableForXArticlesManager::INPUT1 => '>' + ); + $values = array( + AvailableForXArticlesManager::INPUT1 => 4 + ); + $rule2->setValidatorsFromForm($operators, $values); + + $rules = new CouponRuleCollection(); + $rules->add($rule1); + $rules->add($rule2); + + $isValid = $ConstraintValidator->test($rules); + + $expected = false; + $actual =$isValid; + $this->assertEquals($expected, $actual, 'Constraints validator always think Customer is matching rules'); + } + + + public function testVariableOpComparisonSuccess() + { + $ConstraintValidator = new ConstraintValidator(); + $expected = true; + $actual = $ConstraintValidator->variableOpComparison(1, Operators::EQUAL, 1); + $this->assertEquals($expected, $actual); + + $actual = $ConstraintValidator->variableOpComparison(1, Operators::DIFFERENT, 2); + $this->assertEquals($expected, $actual); + + $actual = $ConstraintValidator->variableOpComparison(1, Operators::SUPERIOR, 0); + $this->assertEquals($expected, $actual); + + $actual = $ConstraintValidator->variableOpComparison(1, Operators::INFERIOR, 2); + $this->assertEquals($expected, $actual); + + $actual = $ConstraintValidator->variableOpComparison(1, Operators::INFERIOR_OR_EQUAL, 1); + $this->assertEquals($expected, $actual); + + $actual = $ConstraintValidator->variableOpComparison(1, Operators::INFERIOR_OR_EQUAL, 2); + $this->assertEquals($expected, $actual); + + $actual = $ConstraintValidator->variableOpComparison(1, Operators::SUPERIOR_OR_EQUAL, 1); + $this->assertEquals($expected, $actual); + + $actual = $ConstraintValidator->variableOpComparison(1, Operators::SUPERIOR_OR_EQUAL, 0); + $this->assertEquals($expected, $actual); + + $actual = $ConstraintValidator->variableOpComparison(1, Operators::IN, array(1, 2, 3)); + $this->assertEquals($expected, $actual); + + $actual = $ConstraintValidator->variableOpComparison(1, Operators::OUT, array(0, 2, 3)); + $this->assertEquals($expected, $actual); + + } + + public function testVariableOpComparisonFail() + { + $ConstraintValidator = new ConstraintValidator(); + $expected = false; + $actual = $ConstraintValidator->variableOpComparison(2, Operators::EQUAL, 1); + $this->assertEquals($expected, $actual); + + $actual = $ConstraintValidator->variableOpComparison(2, Operators::DIFFERENT, 2); + $this->assertEquals($expected, $actual); + + $actual = $ConstraintValidator->variableOpComparison(0, Operators::SUPERIOR, 0); + $this->assertEquals($expected, $actual); + + $actual = $ConstraintValidator->variableOpComparison(3, Operators::INFERIOR, 2); + $this->assertEquals($expected, $actual); + + $actual = $ConstraintValidator->variableOpComparison(2, Operators::INFERIOR_OR_EQUAL, 1); + $this->assertEquals($expected, $actual); + + $actual = $ConstraintValidator->variableOpComparison(3, Operators::SUPERIOR_OR_EQUAL, 4); + $this->assertEquals($expected, $actual); + + $actual = $ConstraintValidator->variableOpComparison(0, Operators::IN, array(1, 2, 3)); + $this->assertEquals($expected, $actual); + + $actual = $ConstraintValidator->variableOpComparison(2, Operators::OUT, array(0, 2, 3)); + $this->assertEquals($expected, $actual); + + } + + /** + * @expectedException \Exception + */ + public function testVariableOpComparisonException() + { + $ConstraintValidator = new ConstraintValidator(); + $expected = true; + $actual = $ConstraintValidator->variableOpComparison(1, 'bad', 1); + $this->assertEquals($expected, $actual); + } + + /** + * Get Mocked Container with 2 Rules + * + * @return ContainerBuilder + */ + public function getContainer() + { + $container = new ContainerBuilder(); + + $stubTranslator = $this->getMockBuilder('\Thelia\Core\Translation\Translator') + ->disableOriginalConstructor() + ->getMock(); + + $stubAdapter = $this->getMockBuilder('\Thelia\Coupon\CouponBaseAdapter') + ->disableOriginalConstructor() + ->getMock(); + + $stubAdapter->expects($this->any()) + ->method('getTranslator') + ->will($this->returnValue($stubTranslator)); + + $rule1 = new AvailableForTotalAmountManager($stubAdapter); + $rule2 = new AvailableForXArticlesManager($stubAdapter); + + $adapter = new CouponBaseAdapter($container); + + $container->set('thelia.constraint.rule.available_for_total_amount', $rule1); + $container->set('thelia.constraint.rule.available_for_x_articles', $rule2); + $container->set('thelia.adapter', $adapter); + + return $container; + } + + /** + * Tears down the fixture, for example, closes a network connection. + * This method is called after a test is executed. + */ + protected function tearDown() + { + } +} diff --git a/core/lib/Thelia/Tests/Constraint/Rule/AvailableForTotalAmountTest.php b/core/lib/Thelia/Tests/Constraint/Rule/AvailableForTotalAmountTest.php new file mode 100644 index 000000000..bfcde8a21 --- /dev/null +++ b/core/lib/Thelia/Tests/Constraint/Rule/AvailableForTotalAmountTest.php @@ -0,0 +1,670 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Coupon; + +use Thelia\Constraint\Rule\AvailableForTotalAmountManager; +use Thelia\Constraint\Rule\Operators; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Unit Test AvailableForTotalAmount Class + * + * @package Constraint + * @author Guillaume MOREL + * + */ +class AvailableForTotalAmountTest extends \PHPUnit_Framework_TestCase +{ + /** @var CouponAdapterInterface $stubTheliaAdapter */ + protected $stubTheliaAdapter = null; + + /** + * Sets up the fixture, for example, opens a network connection. + * This method is called before a test is executed. + */ + protected function setUp() + { +// /** @var CouponAdapterInterface $stubTheliaAdapter */ +// $this->stubTheliaAdapter = $this->generateValidCouponBaseAdapterMock(); + } + +// /** +// * Generate valid CouponBaseAdapter +// * +// * @param float $cartTotalPrice Total amount of the current Cart +// * +// * @return CouponAdapterInterface +// */ +// protected function generateValidCouponBaseAdapterMock($cartTotalPrice = 421.23) +// { +// /** @var CouponAdapterInterface $stubTheliaAdapter */ +// $stubTheliaAdapter = $this->getMock( +// 'Thelia\Coupon\CouponBaseAdapter', +// array('getCartTotalPrice'), +// array() +// ); +// $stubTheliaAdapter->expects($this->any()) +// ->method('getCartTotalPrice') +// ->will($this->returnValue($cartTotalPrice)); +// +// return $stubTheliaAdapter; +// } + +// /** +// * Check if validity test on BackOffice inputs are working +// * +// * @covers Thelia\Coupon\Rule\AvailableForTotalAmount::checkBackOfficeInput +// * +// */ +// public function testValidBackOfficeInput() +// { +// $adapter = new CouponBaseAdapter(); +// +// $validators = array( +// AvailableForTotalAmount::PARAM1_PRICE => new RuleValidator( +// Operators::SUPERIOR, +// new PriceParam( +// $adapter, 421.23, 'EUR' +// ) +// ) +// ); +// $rule = new AvailableForTotalAmount($adapter, $validators); +// +// $expected = true; +// $actual = $rule->checkBackOfficeInput(); +// $this->assertEquals($expected, $actual); +// } + +// /** +// * Check if validity test on BackOffice inputs are working +// * +// * @covers Thelia\Coupon\Rule\AvailableForTotalAmount::checkBackOfficeInput +// * @expectedException \Thelia\Exception\InvalidRuleOperatorException +// * +// */ +// public function testInValidBackOfficeInputOperator() +// { +// $adapter = new CouponBaseAdapter(); +// +// $validators = array( +// AvailableForTotalAmount::PARAM1_PRICE => new RuleValidator( +// 'X', +// new PriceParam( +// $adapter, 421.23, 'EUR' +// ) +// ) +// ); +// +// $rule = new AvailableForTotalAmount($adapter, $validators); +// +// $expected = false; +// $actual = $rule->checkBackOfficeInput(); +// $this->assertEquals($expected, $actual); +// } + +// /** +// * Check if validity test on BackOffice inputs are working +// * +// * @covers Thelia\Coupon\Rule\AvailableForTotalAmount::checkBackOfficeInput +// * @expectedException \ErrorException +// * +// */ +// public function testInValidBackOfficeInputValue() +// { +// $adapter = $this->generateValidCouponBaseAdapterMock(); +// +// $validators = array( +// AvailableForTotalAmount::PARAM1_PRICE => new RuleValidator( +// Operators::SUPERIOR, +// 421 +// ) +// ); +// +// $rule = new AvailableForTotalAmount($adapter, $validators); +// +// $expected = false; +// $actual = $rule->checkBackOfficeInput(); +// $this->assertEquals($expected, $actual); +// } + + + /** + * Check if test inferior operator is working + * + * @covers Thelia\Constraint\Rule\AvailableForTotalAmountManager::isMatching + * + */ + public function testMatchingRuleInferior() + { + $stubAdapter = $this->getMockBuilder('\Thelia\Coupon\CouponBaseAdapter') + ->disableOriginalConstructor() + ->getMock(); + + $stubAdapter->expects($this->any()) + ->method('getCartTotalPrice') + ->will($this->returnValue(399)); + $stubAdapter->expects($this->any()) + ->method('getCheckoutCurrency') + ->will($this->returnValue('EUR')); + + $rule1 = new AvailableForTotalAmountManager($stubAdapter); + $operators = array( + AvailableForTotalAmountManager::INPUT1 => Operators::INFERIOR, + AvailableForTotalAmountManager::INPUT2 => Operators::EQUAL + ); + $values = array( + AvailableForTotalAmountManager::INPUT1 => 400.00, + AvailableForTotalAmountManager::INPUT2 => 'EUR'); + $rule1->setValidatorsFromForm($operators, $values); + + $isValid = $rule1->isMatching(); + + $expected = true; + $actual =$isValid; + $this->assertEquals($expected, $actual); + } + + /** + * Check if test inferior operator is working + * + * @covers Thelia\Constraint\Rule\AvailableForTotalAmountManager::isMatching + * + */ + public function testNotMatchingRuleInferior() + { + $stubAdapter = $this->getMockBuilder('\Thelia\Coupon\CouponBaseAdapter') + ->disableOriginalConstructor() + ->getMock(); + + $stubAdapter->expects($this->any()) + ->method('getCartTotalPrice') + ->will($this->returnValue(400)); + $stubAdapter->expects($this->any()) + ->method('getCheckoutCurrency') + ->will($this->returnValue('EUR')); + + $rule1 = new AvailableForTotalAmountManager($stubAdapter); + $operators = array( + AvailableForTotalAmountManager::INPUT1 => Operators::INFERIOR, + AvailableForTotalAmountManager::INPUT2 => Operators::EQUAL + ); + $values = array( + AvailableForTotalAmountManager::INPUT1 => 400.00, + AvailableForTotalAmountManager::INPUT2 => 'EUR'); + $rule1->setValidatorsFromForm($operators, $values); + + $isValid = $rule1->isMatching(); + + $expected = false; + $actual =$isValid; + $this->assertEquals($expected, $actual); + } + + /** + * Check if test inferior operator is working + * + * @covers Thelia\Constraint\Rule\AvailableForTotalAmountManager::isMatching + * + */ + public function testMatchingRuleInferiorEquals() + { + $stubAdapter = $this->getMockBuilder('\Thelia\Coupon\CouponBaseAdapter') + ->disableOriginalConstructor() + ->getMock(); + + $stubAdapter->expects($this->any()) + ->method('getCartTotalPrice') + ->will($this->returnValue(400)); + $stubAdapter->expects($this->any()) + ->method('getCheckoutCurrency') + ->will($this->returnValue('EUR')); + + $rule1 = new AvailableForTotalAmountManager($stubAdapter); + $operators = array( + AvailableForTotalAmountManager::INPUT1 => Operators::INFERIOR_OR_EQUAL, + AvailableForTotalAmountManager::INPUT2 => Operators::EQUAL + ); + $values = array( + AvailableForTotalAmountManager::INPUT1 => 400.00, + AvailableForTotalAmountManager::INPUT2 => 'EUR'); + $rule1->setValidatorsFromForm($operators, $values); + + $isValid = $rule1->isMatching(); + + $expected = true; + $actual =$isValid; + $this->assertEquals($expected, $actual); + } + + /** + * Check if test inferior operator is working + * + * @covers Thelia\Constraint\Rule\AvailableForTotalAmountManager::isMatching + * + */ + public function testMatchingRuleInferiorEquals2() + { + $stubAdapter = $this->getMockBuilder('\Thelia\Coupon\CouponBaseAdapter') + ->disableOriginalConstructor() + ->getMock(); + + $stubAdapter->expects($this->any()) + ->method('getCartTotalPrice') + ->will($this->returnValue(399)); + $stubAdapter->expects($this->any()) + ->method('getCheckoutCurrency') + ->will($this->returnValue('EUR')); + + $rule1 = new AvailableForTotalAmountManager($stubAdapter); + $operators = array( + AvailableForTotalAmountManager::INPUT1 => Operators::INFERIOR_OR_EQUAL, + AvailableForTotalAmountManager::INPUT2 => Operators::EQUAL + ); + $values = array( + AvailableForTotalAmountManager::INPUT1 => 400.00, + AvailableForTotalAmountManager::INPUT2 => 'EUR'); + $rule1->setValidatorsFromForm($operators, $values); + + $isValid = $rule1->isMatching(); + + $expected = true; + $actual =$isValid; + $this->assertEquals($expected, $actual); + } + + /** + * Check if test inferior operator is working + * + * @covers Thelia\Constraint\Rule\AvailableForTotalAmountManager::isMatching + * + */ + public function testNotMatchingRuleInferiorEquals() + { + $stubAdapter = $this->getMockBuilder('\Thelia\Coupon\CouponBaseAdapter') + ->disableOriginalConstructor() + ->getMock(); + + $stubAdapter->expects($this->any()) + ->method('getCartTotalPrice') + ->will($this->returnValue(401)); + $stubAdapter->expects($this->any()) + ->method('getCheckoutCurrency') + ->will($this->returnValue('EUR')); + + $rule1 = new AvailableForTotalAmountManager($stubAdapter); + $operators = array( + AvailableForTotalAmountManager::INPUT1 => Operators::INFERIOR_OR_EQUAL, + AvailableForTotalAmountManager::INPUT2 => Operators::EQUAL + ); + $values = array( + AvailableForTotalAmountManager::INPUT1 => 400.00, + AvailableForTotalAmountManager::INPUT2 => 'EUR'); + $rule1->setValidatorsFromForm($operators, $values); + + $isValid = $rule1->isMatching(); + + $expected = false; + $actual =$isValid; + $this->assertEquals($expected, $actual); + } + + /** + * Check if test equals operator is working + * + * @covers Thelia\Constraint\Rule\AvailableForTotalAmountManager::isMatching + * + */ + public function testMatchingRuleEqual() + { + $stubAdapter = $this->getMockBuilder('\Thelia\Coupon\CouponBaseAdapter') + ->disableOriginalConstructor() + ->getMock(); + + $stubAdapter->expects($this->any()) + ->method('getCartTotalPrice') + ->will($this->returnValue(400)); + $stubAdapter->expects($this->any()) + ->method('getCheckoutCurrency') + ->will($this->returnValue('EUR')); + + $rule1 = new AvailableForTotalAmountManager($stubAdapter); + $operators = array( + AvailableForTotalAmountManager::INPUT1 => Operators::EQUAL, + AvailableForTotalAmountManager::INPUT2 => Operators::EQUAL + ); + $values = array( + AvailableForTotalAmountManager::INPUT1 => 400.00, + AvailableForTotalAmountManager::INPUT2 => 'EUR'); + $rule1->setValidatorsFromForm($operators, $values); + + $isValid = $rule1->isMatching(); + + $expected = true; + $actual =$isValid; + $this->assertEquals($expected, $actual); + } + + /** + * Check if test equals operator is working + * + * @covers Thelia\Constraint\Rule\AvailableForTotalAmountManager::isMatching + * + */ + public function testNotMatchingRuleEqual() + { + $stubAdapter = $this->getMockBuilder('\Thelia\Coupon\CouponBaseAdapter') + ->disableOriginalConstructor() + ->getMock(); + + $stubAdapter->expects($this->any()) + ->method('getCartTotalPrice') + ->will($this->returnValue(399)); + $stubAdapter->expects($this->any()) + ->method('getCheckoutCurrency') + ->will($this->returnValue('EUR')); + + $rule1 = new AvailableForTotalAmountManager($stubAdapter); + $operators = array( + AvailableForTotalAmountManager::INPUT1 => Operators::EQUAL, + AvailableForTotalAmountManager::INPUT2 => Operators::EQUAL + ); + $values = array( + AvailableForTotalAmountManager::INPUT1 => 400.00, + AvailableForTotalAmountManager::INPUT2 => 'EUR'); + $rule1->setValidatorsFromForm($operators, $values); + + $isValid = $rule1->isMatching(); + + $expected = false; + $actual =$isValid; + $this->assertEquals($expected, $actual); + } + + /** + * Check if test superior operator is working + * + * @covers Thelia\Constraint\Rule\AvailableForTotalAmountManager::isMatching + * + */ + public function testMatchingRuleSuperiorEquals() + { + $stubAdapter = $this->getMockBuilder('\Thelia\Coupon\CouponBaseAdapter') + ->disableOriginalConstructor() + ->getMock(); + + $stubAdapter->expects($this->any()) + ->method('getCartTotalPrice') + ->will($this->returnValue(401)); + $stubAdapter->expects($this->any()) + ->method('getCheckoutCurrency') + ->will($this->returnValue('EUR')); + + $rule1 = new AvailableForTotalAmountManager($stubAdapter); + $operators = array( + AvailableForTotalAmountManager::INPUT1 => Operators::SUPERIOR_OR_EQUAL, + AvailableForTotalAmountManager::INPUT2 => Operators::EQUAL + ); + $values = array( + AvailableForTotalAmountManager::INPUT1 => 400.00, + AvailableForTotalAmountManager::INPUT2 => 'EUR'); + $rule1->setValidatorsFromForm($operators, $values); + + $isValid = $rule1->isMatching(); + + $expected = true; + $actual =$isValid; + $this->assertEquals($expected, $actual); + } + + /** + * Check if test superior operator is working + * + * @covers Thelia\Constraint\Rule\AvailableForTotalAmountManager::isMatching + * + */ + public function testMatchingRuleSuperiorEquals2() + { + $stubAdapter = $this->getMockBuilder('\Thelia\Coupon\CouponBaseAdapter') + ->disableOriginalConstructor() + ->getMock(); + + $stubAdapter->expects($this->any()) + ->method('getCartTotalPrice') + ->will($this->returnValue(400)); + $stubAdapter->expects($this->any()) + ->method('getCheckoutCurrency') + ->will($this->returnValue('EUR')); + + $rule1 = new AvailableForTotalAmountManager($stubAdapter); + $operators = array( + AvailableForTotalAmountManager::INPUT1 => Operators::SUPERIOR_OR_EQUAL, + AvailableForTotalAmountManager::INPUT2 => Operators::EQUAL + ); + $values = array( + AvailableForTotalAmountManager::INPUT1 => 400.00, + AvailableForTotalAmountManager::INPUT2 => 'EUR'); + $rule1->setValidatorsFromForm($operators, $values); + + $isValid = $rule1->isMatching(); + + $expected = true; + $actual =$isValid; + $this->assertEquals($expected, $actual); + } + + /** + * Check if test superior operator is working + * + * @covers Thelia\Constraint\Rule\AvailableForTotalAmountManager::isMatching + * + */ + public function testNotMatchingRuleSuperiorEquals() + { + $stubAdapter = $this->getMockBuilder('\Thelia\Coupon\CouponBaseAdapter') + ->disableOriginalConstructor() + ->getMock(); + + $stubAdapter->expects($this->any()) + ->method('getCartTotalPrice') + ->will($this->returnValue(399.00)); + $stubAdapter->expects($this->any()) + ->method('getCheckoutCurrency') + ->will($this->returnValue('EUR')); + + $rule1 = new AvailableForTotalAmountManager($stubAdapter); + $operators = array( + AvailableForTotalAmountManager::INPUT1 => Operators::SUPERIOR_OR_EQUAL, + AvailableForTotalAmountManager::INPUT2 => Operators::EQUAL + ); + $values = array( + AvailableForTotalAmountManager::INPUT1 => 400.00, + AvailableForTotalAmountManager::INPUT2 => 'EUR'); + $rule1->setValidatorsFromForm($operators, $values); + + $isValid = $rule1->isMatching(); + + $expected = false; + $actual =$isValid; + $this->assertEquals($expected, $actual); + } + + + /** + * Check if test superior operator is working + * + * @covers Thelia\Constraint\Rule\AvailableForTotalAmountManager::isMatching + * + */ + public function testMatchingRuleSuperior() + { + $stubAdapter = $this->getMockBuilder('\Thelia\Coupon\CouponBaseAdapter') + ->disableOriginalConstructor() + ->getMock(); + + $stubAdapter->expects($this->any()) + ->method('getCartTotalPrice') + ->will($this->returnValue(401)); + $stubAdapter->expects($this->any()) + ->method('getCheckoutCurrency') + ->will($this->returnValue('EUR')); + + $rule1 = new AvailableForTotalAmountManager($stubAdapter); + $operators = array( + AvailableForTotalAmountManager::INPUT1 => Operators::SUPERIOR, + AvailableForTotalAmountManager::INPUT2 => Operators::EQUAL + ); + $values = array( + AvailableForTotalAmountManager::INPUT1 => 400.00, + AvailableForTotalAmountManager::INPUT2 => 'EUR'); + $rule1->setValidatorsFromForm($operators, $values); + + $isValid = $rule1->isMatching(); + + $expected = true; + $actual =$isValid; + $this->assertEquals($expected, $actual); + } + + /** + * Check if test superior operator is working + * + * @covers Thelia\Constraint\Rule\AvailableForTotalAmountManager::isMatching + * + */ + public function testNotMatchingRuleSuperior() + { + $stubAdapter = $this->getMockBuilder('\Thelia\Coupon\CouponBaseAdapter') + ->disableOriginalConstructor() + ->getMock(); + + $stubAdapter->expects($this->any()) + ->method('getCartTotalPrice') + ->will($this->returnValue(399.00)); + $stubAdapter->expects($this->any()) + ->method('getCheckoutCurrency') + ->will($this->returnValue('EUR')); + + $rule1 = new AvailableForTotalAmountManager($stubAdapter); + $operators = array( + AvailableForTotalAmountManager::INPUT1 => Operators::SUPERIOR, + AvailableForTotalAmountManager::INPUT2 => Operators::EQUAL + ); + $values = array( + AvailableForTotalAmountManager::INPUT1 => 400.00, + AvailableForTotalAmountManager::INPUT2 => 'EUR'); + $rule1->setValidatorsFromForm($operators, $values); + + $isValid = $rule1->isMatching(); + + $expected = false; + $actual =$isValid; + $this->assertEquals($expected, $actual); + } + + + /** + * Check currency is checked + * + * @covers Thelia\Constraint\Rule\AvailableForTotalAmountManager::isMatching + * + */ + public function testMatchingRuleCurrency() + { + $stubAdapter = $this->getMockBuilder('\Thelia\Coupon\CouponBaseAdapter') + ->disableOriginalConstructor() + ->getMock(); + + $stubAdapter->expects($this->any()) + ->method('getCartTotalPrice') + ->will($this->returnValue(400.00)); + $stubAdapter->expects($this->any()) + ->method('getCheckoutCurrency') + ->will($this->returnValue('EUR')); + + $rule1 = new AvailableForTotalAmountManager($stubAdapter); + $operators = array( + AvailableForTotalAmountManager::INPUT1 => Operators::EQUAL, + AvailableForTotalAmountManager::INPUT2 => Operators::EQUAL + ); + $values = array( + AvailableForTotalAmountManager::INPUT1 => 400.00, + AvailableForTotalAmountManager::INPUT2 => 'EUR'); + $rule1->setValidatorsFromForm($operators, $values); + + $isValid = $rule1->isMatching(); + + $expected = true; + $actual =$isValid; + $this->assertEquals($expected, $actual); + } + + /** + * Check currency is checked + * + * @covers Thelia\Constraint\Rule\AvailableForTotalAmountManager::isMatching + * + */ + public function testNotMatchingRuleCurrency() + { + $stubAdapter = $this->getMockBuilder('\Thelia\Coupon\CouponBaseAdapter') + ->disableOriginalConstructor() + ->getMock(); + + $stubAdapter->expects($this->any()) + ->method('getCartTotalPrice') + ->will($this->returnValue(400.00)); + $stubAdapter->expects($this->any()) + ->method('getCheckoutCurrency') + ->will($this->returnValue('EUR')); + + $rule1 = new AvailableForTotalAmountManager($stubAdapter); + $operators = array( + AvailableForTotalAmountManager::INPUT1 => Operators::EQUAL, + AvailableForTotalAmountManager::INPUT2 => Operators::EQUAL + ); + $values = array( + AvailableForTotalAmountManager::INPUT1 => 400.00, + AvailableForTotalAmountManager::INPUT2 => 'USD'); + $rule1->setValidatorsFromForm($operators, $values); + + $isValid = $rule1->isMatching(); + + $expected = false; + $actual =$isValid; + $this->assertEquals($expected, $actual); + } + + + /** + * Tears down the fixture, for example, closes a network connection. + * This method is called after a test is executed. + */ + protected function tearDown() + { + } + +} diff --git a/core/lib/Thelia/Tests/Constraint/Rule/AvailableForXArticlesTest.php b/core/lib/Thelia/Tests/Constraint/Rule/AvailableForXArticlesTest.php new file mode 100644 index 000000000..cc5caee2a --- /dev/null +++ b/core/lib/Thelia/Tests/Constraint/Rule/AvailableForXArticlesTest.php @@ -0,0 +1,673 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Coupon; + +use Thelia\Constraint\Rule\AvailableForXArticlesManager; +use Thelia\Constraint\Rule\Operators; +use Thelia\Constraint\Rule\SerializableRule; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Unit Test AvailableForXArticles Class + * + * @package Constraint + * @author Guillaume MOREL + * + */ +class AvailableForXArticlesTest extends \PHPUnit_Framework_TestCase +{ + +// /** @var CouponAdapterInterface $stubTheliaAdapter */ +// protected $stubTheliaAdapter = null; + + /** + * Sets up the fixture, for example, opens a network connection. + * This method is called before a test is executed. + */ + protected function setUp() + { +// /** @var CouponAdapterInterface $stubTheliaAdapter */ +// $this->stubTheliaAdapter = $this->generateValidCouponBaseAdapterMock(); + } + +// /** +// * Generate valid CouponBaseAdapter +// * +// * @param int $nbArticlesInCart Total articles in the current Cart +// * +// * @return CouponAdapterInterface +// */ +// protected function generateValidCouponBaseAdapterMock($nbArticlesInCart = 4) +// { +// /** @var CouponAdapterInterface $stubTheliaAdapter */ +// $stubTheliaAdapter = $this->getMockBuilder('\Thelia\Coupon\CouponBaseAdapter') +// ->disableOriginalConstructor() +// ->setMethods(array('getNbArticlesInCart')) +// ->getMock(); +// $stubTheliaAdapter->expects($this->any()) +// ->method('getNbArticlesInCart') +// ->will($this->returnValue($nbArticlesInCart)); +// +// return $stubTheliaAdapter; +// } + +// /** +// * Check if validity test on BackOffice inputs are working +// * +// * @covers Thelia\Coupon\Rule\AvailableForXArticles::checkBackOfficeInput +// * +// */ +// public function testValidBackOfficeInput() +// { +// $translator = $this->getMockBuilder('\Thelia\Core\Translation\Translator') +// ->disableOriginalConstructor() +// ->getMock(); +// +// $rule = new AvailableForXArticles($translator); +// $operators = array(AvailableForXArticles::PARAM1_QUANTITY => Operators::SUPERIOR); +// $values = array( +// AvailableForXArticles::PARAM1_QUANTITY => 4 +// ); +// $rule->populateFromForm($operators, $values); +// +// $expected = true; +// $actual = $rule->checkBackOfficeInput(); +// $this->assertEquals($expected, $actual); +// } + +// /** +// * Check if validity test on BackOffice inputs are working +// * +// * @covers Thelia\Coupon\Rule\AvailableForXArticles::checkBackOfficeInput +// * @expectedException \Thelia\Exception\InvalidRuleValueException +// */ +// public function testInValidBackOfficeInputFloat() +// { +// $adapter = $this->stubTheliaAdapter; +// +// $validators = array( +// AvailableForXArticles::PARAM1_QUANTITY => new RuleValidator( +// Operators::SUPERIOR, +// new QuantityParam( +// $adapter, +// 4.5 +// ) +// ) +// ); +// $rule = new AvailableForXArticles($adapter, $validators); +// +// $expected = false; +// $actual = $rule->checkBackOfficeInput(); +// $this->assertEquals($expected, $actual); +// } + +// /** +// * Check if validity test on BackOffice inputs are working +// * +// * @covers Thelia\Coupon\Rule\AvailableForXArticles::checkBackOfficeInput +// * @expectedException \Thelia\Exception\InvalidRuleValueException +// */ +// public function testInValidBackOfficeInputNegative() +// { +// $adapter = $this->stubTheliaAdapter; +// +// $validators = array( +// AvailableForXArticles::PARAM1_QUANTITY => new RuleValidator( +// Operators::SUPERIOR, +// new QuantityParam( +// $adapter, +// -1 +// ) +// ) +// ); +// $rule = new AvailableForXArticles($adapter, $validators); +// +// $expected = false; +// $actual = $rule->checkBackOfficeInput(); +// $this->assertEquals($expected, $actual); +// } + +// /** +// * Check if validity test on BackOffice inputs are working +// * +// * @covers Thelia\Coupon\Rule\AvailableForXArticles::checkBackOfficeInput +// * @expectedException \Thelia\Exception\InvalidRuleValueException +// */ +// public function testInValidBackOfficeInputString() +// { +// $adapter = $this->stubTheliaAdapter; +// +// $validators = array( +// AvailableForXArticles::PARAM1_QUANTITY => new RuleValidator( +// Operators::SUPERIOR, +// new QuantityParam( +// $adapter, +// 'bad' +// ) +// ) +// ); +// $rule = new AvailableForXArticles($adapter, $validators); +// +// $expected = false; +// $actual = $rule->checkBackOfficeInput(); +// $this->assertEquals($expected, $actual); +// } + + + + + + /** + * Check if test inferior operator is working + * + * @covers Thelia\Constraint\Rule\AvailableForXArticlesManager::isMatching + * + */ + public function testMatchingRuleInferior() + { + $stubAdapter = $this->getMockBuilder('\Thelia\Coupon\CouponBaseAdapter') + ->disableOriginalConstructor() + ->getMock(); + + $stubAdapter->expects($this->any()) + ->method('getNbArticlesInCart') + ->will($this->returnValue(4)); + + $rule1 = new AvailableForXArticlesManager($stubAdapter); + $operators = array( + AvailableForXArticlesManager::INPUT1 => Operators::INFERIOR + ); + $values = array( + AvailableForXArticlesManager::INPUT1 => 5 + ); + $rule1->setValidatorsFromForm($operators, $values); + + $isValid = $rule1->isMatching(); + + $expected = true; + $actual =$isValid; + $this->assertEquals($expected, $actual); + } + + /** + * Check if test inferior operator is working + * + * @covers Thelia\Constraint\Rule\AvailableForXArticlesManager::isMatching + * + */ + public function testNotMatchingRuleInferior() + { + $stubAdapter = $this->getMockBuilder('\Thelia\Coupon\CouponBaseAdapter') + ->disableOriginalConstructor() + ->getMock(); + + $stubAdapter->expects($this->any()) + ->method('getNbArticlesInCart') + ->will($this->returnValue(4)); + + $rule1 = new AvailableForXArticlesManager($stubAdapter); + $operators = array( + AvailableForXArticlesManager::INPUT1 => Operators::INFERIOR + ); + $values = array( + AvailableForXArticlesManager::INPUT1 => 4, + ); + $rule1->setValidatorsFromForm($operators, $values); + + $isValid = $rule1->isMatching(); + + $expected = false; + $actual =$isValid; + $this->assertEquals($expected, $actual); + } + + /** + * Check if test inferior operator is working + * + * @covers Thelia\Constraint\Rule\AvailableForXArticlesManager::isMatching + * + */ + public function testMatchingRuleInferiorEquals() + { + $stubAdapter = $this->getMockBuilder('\Thelia\Coupon\CouponBaseAdapter') + ->disableOriginalConstructor() + ->getMock(); + + $stubAdapter->expects($this->any()) + ->method('getNbArticlesInCart') + ->will($this->returnValue(4)); + + $rule1 = new AvailableForXArticlesManager($stubAdapter); + $operators = array( + AvailableForXArticlesManager::INPUT1 => Operators::INFERIOR_OR_EQUAL, + ); + $values = array( + AvailableForXArticlesManager::INPUT1 => 5, + ); + $rule1->setValidatorsFromForm($operators, $values); + + $isValid = $rule1->isMatching(); + + $expected = true; + $actual =$isValid; + $this->assertEquals($expected, $actual); + } + + /** + * Check if test inferior operator is working + * + * @covers Thelia\Constraint\Rule\AvailableForXArticlesManager::isMatching + * + */ + public function testMatchingRuleInferiorEquals2() + { + $stubAdapter = $this->getMockBuilder('\Thelia\Coupon\CouponBaseAdapter') + ->disableOriginalConstructor() + ->getMock(); + + $stubAdapter->expects($this->any()) + ->method('getNbArticlesInCart') + ->will($this->returnValue(4)); + + $rule1 = new AvailableForXArticlesManager($stubAdapter); + $operators = array( + AvailableForXArticlesManager::INPUT1 => Operators::INFERIOR_OR_EQUAL + ); + $values = array( + AvailableForXArticlesManager::INPUT1 => 4 + ); + $rule1->setValidatorsFromForm($operators, $values); + + $isValid = $rule1->isMatching(); + + $expected = true; + $actual =$isValid; + $this->assertEquals($expected, $actual); + } + + /** + * Check if test inferior operator is working + * + * @covers Thelia\Constraint\Rule\AvailableForXArticlesManager::isMatching + * + */ + public function testNotMatchingRuleInferiorEquals() + { + $stubAdapter = $this->getMockBuilder('\Thelia\Coupon\CouponBaseAdapter') + ->disableOriginalConstructor() + ->getMock(); + + $stubAdapter->expects($this->any()) + ->method('getNbArticlesInCart') + ->will($this->returnValue(4)); + + $rule1 = new AvailableForXArticlesManager($stubAdapter); + $operators = array( + AvailableForXArticlesManager::INPUT1 => Operators::INFERIOR_OR_EQUAL + ); + $values = array( + AvailableForXArticlesManager::INPUT1 => 3 + ); + $rule1->setValidatorsFromForm($operators, $values); + + $isValid = $rule1->isMatching(); + + $expected = false; + $actual =$isValid; + $this->assertEquals($expected, $actual); + } + + /** + * Check if test equals operator is working + * + * @covers Thelia\Constraint\Rule\AvailableForXArticlesManager::isMatching + * + */ + public function testMatchingRuleEqual() + { + $stubAdapter = $this->getMockBuilder('\Thelia\Coupon\CouponBaseAdapter') + ->disableOriginalConstructor() + ->getMock(); + + $stubAdapter->expects($this->any()) + ->method('getNbArticlesInCart') + ->will($this->returnValue(4)); + + $rule1 = new AvailableForXArticlesManager($stubAdapter); + $operators = array( + AvailableForXArticlesManager::INPUT1 => Operators::EQUAL + ); + $values = array( + AvailableForXArticlesManager::INPUT1 => 4 + ); + $rule1->setValidatorsFromForm($operators, $values); + + $isValid = $rule1->isMatching(); + + $expected = true; + $actual =$isValid; + $this->assertEquals($expected, $actual); + } + + /** + * Check if test equals operator is working + * + * @covers Thelia\Constraint\Rule\AvailableForXArticlesManager::isMatching + * + */ + public function testNotMatchingRuleEqual() + { + $stubAdapter = $this->getMockBuilder('\Thelia\Coupon\CouponBaseAdapter') + ->disableOriginalConstructor() + ->getMock(); + + $stubAdapter->expects($this->any()) + ->method('getNbArticlesInCart') + ->will($this->returnValue(4)); + + $rule1 = new AvailableForXArticlesManager($stubAdapter); + $operators = array( + AvailableForXArticlesManager::INPUT1 => Operators::EQUAL + ); + $values = array( + AvailableForXArticlesManager::INPUT1 => 5 + ); + $rule1->setValidatorsFromForm($operators, $values); + + $isValid = $rule1->isMatching(); + + $expected = false; + $actual =$isValid; + $this->assertEquals($expected, $actual); + } + + /** + * Check if test superior operator is working + * + * @covers Thelia\Constraint\Rule\AvailableForXArticlesManager::isMatching + * + */ + public function testMatchingRuleSuperiorEquals() + { + $stubAdapter = $this->getMockBuilder('\Thelia\Coupon\CouponBaseAdapter') + ->disableOriginalConstructor() + ->getMock(); + + $stubAdapter->expects($this->any()) + ->method('getNbArticlesInCart') + ->will($this->returnValue(4)); + + $rule1 = new AvailableForXArticlesManager($stubAdapter); + $operators = array( + AvailableForXArticlesManager::INPUT1 => Operators::SUPERIOR_OR_EQUAL + ); + $values = array( + AvailableForXArticlesManager::INPUT1 => 4 + ); + $rule1->setValidatorsFromForm($operators, $values); + + $isValid = $rule1->isMatching(); + + $expected = true; + $actual =$isValid; + $this->assertEquals($expected, $actual); + } + + /** + * Check if test superior operator is working + * + * @covers Thelia\Constraint\Rule\AvailableForXArticlesManager::isMatching + * + */ + public function testMatchingRuleSuperiorEquals2() + { + $stubAdapter = $this->getMockBuilder('\Thelia\Coupon\CouponBaseAdapter') + ->disableOriginalConstructor() + ->getMock(); + + $stubAdapter->expects($this->any()) + ->method('getNbArticlesInCart') + ->will($this->returnValue(4)); + + $rule1 = new AvailableForXArticlesManager($stubAdapter); + $operators = array( + AvailableForXArticlesManager::INPUT1 => Operators::SUPERIOR_OR_EQUAL + ); + $values = array( + AvailableForXArticlesManager::INPUT1 => 3 + ); + $rule1->setValidatorsFromForm($operators, $values); + + $isValid = $rule1->isMatching(); + + $expected = true; + $actual =$isValid; + $this->assertEquals($expected, $actual); + } + + /** + * Check if test superior operator is working + * + * @covers Thelia\Constraint\Rule\AvailableForXArticlesManager::isMatching + * + */ + public function testNotMatchingRuleSuperiorEquals() + { + $stubAdapter = $this->getMockBuilder('\Thelia\Coupon\CouponBaseAdapter') + ->disableOriginalConstructor() + ->getMock(); + + $stubAdapter->expects($this->any()) + ->method('getNbArticlesInCart') + ->will($this->returnValue(4)); + + $rule1 = new AvailableForXArticlesManager($stubAdapter); + $operators = array( + AvailableForXArticlesManager::INPUT1 => Operators::SUPERIOR_OR_EQUAL + ); + $values = array( + AvailableForXArticlesManager::INPUT1 => 5 + ); + $rule1->setValidatorsFromForm($operators, $values); + + $isValid = $rule1->isMatching(); + + $expected = false; + $actual =$isValid; + $this->assertEquals($expected, $actual); + } + + + /** + * Check if test superior operator is working + * + * @covers Thelia\Constraint\Rule\AvailableForXArticlesManager::isMatching + * + */ + public function testMatchingRuleSuperior() + { + $stubAdapter = $this->getMockBuilder('\Thelia\Coupon\CouponBaseAdapter') + ->disableOriginalConstructor() + ->getMock(); + + $stubAdapter->expects($this->any()) + ->method('getNbArticlesInCart') + ->will($this->returnValue(4)); + + $rule1 = new AvailableForXArticlesManager($stubAdapter); + $operators = array( + AvailableForXArticlesManager::INPUT1 => Operators::SUPERIOR + ); + $values = array( + AvailableForXArticlesManager::INPUT1 => 3 + ); + $rule1->setValidatorsFromForm($operators, $values); + + $isValid = $rule1->isMatching(); + + $expected = true; + $actual =$isValid; + $this->assertEquals($expected, $actual); + } + + /** + * Check if test superior operator is working + * + * @covers Thelia\Constraint\Rule\AvailableForXArticlesManager::isMatching + * + */ + public function testNotMatchingRuleSuperior() + { + $stubAdapter = $this->getMockBuilder('\Thelia\Coupon\CouponBaseAdapter') + ->disableOriginalConstructor() + ->getMock(); + + $stubAdapter->expects($this->any()) + ->method('getNbArticlesInCart') + ->will($this->returnValue(4)); + + $rule1 = new AvailableForXArticlesManager($stubAdapter); + $operators = array( + AvailableForXArticlesManager::INPUT1 => Operators::SUPERIOR + ); + $values = array( + AvailableForXArticlesManager::INPUT1 => 4 + ); + $rule1->setValidatorsFromForm($operators, $values); + + $isValid = $rule1->isMatching(); + + $expected = false; + $actual =$isValid; + $this->assertEquals($expected, $actual); + } + + public function testGetSerializableRule() + { + $stubAdapter = $this->getMockBuilder('\Thelia\Coupon\CouponBaseAdapter') + ->disableOriginalConstructor() + ->getMock(); + + $stubAdapter->expects($this->any()) + ->method('getNbArticlesInCart') + ->will($this->returnValue(4)); + + $rule1 = new AvailableForXArticlesManager($stubAdapter); + $operators = array( + AvailableForXArticlesManager::INPUT1 => Operators::SUPERIOR + ); + $values = array( + AvailableForXArticlesManager::INPUT1 => 4 + ); + $rule1->setValidatorsFromForm($operators, $values); + + $serializableRule = $rule1->getSerializableRule(); + + $expected = new SerializableRule(); + $expected->ruleServiceId = $rule1->getServiceId(); + $expected->operators = $operators; + $expected->values = $values; + + $actual = $serializableRule; + + $this->assertEquals($expected, $actual); + + } + + public function testGetAvailableOperators() + { + $stubAdapter = $this->getMockBuilder('\Thelia\Coupon\CouponBaseAdapter') + ->disableOriginalConstructor() + ->getMock(); + + $stubAdapter->expects($this->any()) + ->method('getNbArticlesInCart') + ->will($this->returnValue(4)); + + $rule1 = new AvailableForXArticlesManager($stubAdapter); + $operators = array( + AvailableForXArticlesManager::INPUT1 => Operators::SUPERIOR + ); + $values = array( + AvailableForXArticlesManager::INPUT1 => 4 + ); + $rule1->setValidatorsFromForm($operators, $values); + + $expected = array( + AvailableForXArticlesManager::INPUT1 => array( + Operators::INFERIOR, + Operators::INFERIOR_OR_EQUAL, + Operators::EQUAL, + Operators::SUPERIOR_OR_EQUAL, + Operators::SUPERIOR + ) + ); + $actual = $rule1->getAvailableOperators(); + + $this->assertEquals($expected, $actual); + + } + +// public function testGetValidators() +// { +// $stubAdapter = $this->getMockBuilder('\Thelia\Coupon\CouponBaseAdapter') +// ->disableOriginalConstructor() +// ->getMock(); +// +// $stubAdapter->expects($this->any()) +// ->method('getNbArticlesInCart') +// ->will($this->returnValue(4)); +// +// $rule1 = new AvailableForXArticlesManager($stubAdapter); +// $operators = array( +// AvailableForXArticlesManager::INPUT1 => Operators::SUPERIOR +// ); +// $values = array( +// AvailableForXArticlesManager::INPUT1 => 4 +// ); +// $rule1->setValidatorsFromForm($operators, $values); +// +// $expected = array( +// $operators, +// $values +// ); +// $actual = $rule1->getValidators(); +// +// $this->assertEquals($expected, $actual); +// +// } + + + /** + * Tears down the fixture, for example, closes a network connection. + * This method is called after a test is executed. + */ + protected function tearDown() + { + } + +} diff --git a/core/lib/Thelia/Tests/Constraint/Rule/OperatorsTest.php b/core/lib/Thelia/Tests/Constraint/Rule/OperatorsTest.php new file mode 100644 index 000000000..c86e827b6 --- /dev/null +++ b/core/lib/Thelia/Tests/Constraint/Rule/OperatorsTest.php @@ -0,0 +1,429 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Coupon; + +use Thelia\Constraint\Validator\QuantityParam; +use Thelia\Constraint\Rule\Operators; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Unit Test Operators Class + * + * @package Constraint + * @author Guillaume MOREL + * + */ +class OperatorsTest extends \PHPUnit_Framework_TestCase +{ + + /** + * Sets up the fixture, for example, opens a network connection. + * This method is called before a test is executed. + */ + protected function setUp() + { + } + + public function testSomething() + { + // Stop here and mark this test as incomplete. + $this->markTestIncomplete( + 'This test has not been implemented yet.' + ); + } + +// /** +// * +// * @covers Thelia\Coupon\Rule\Operator::isValidAccordingToOperator +// * +// */ +// public function testOperatorInferiorValidBefore() +// { +// $adapter = new CouponBaseAdapter(); +// // Given +// $a = 11; +// $operator = Operators::INFERIOR; +// $b = new QuantityParam($adapter, 12); +// +// // When +// $actual = Operators::isValid($a, $operator, $b); +// +// // Then +// $this->assertTrue($actual); +// } +// +// /** +// * +// * @covers Thelia\Coupon\Rule\Operator::isValidAccordingToOperator +// * +// */ +// public function testOperatorInferiorInvalidEquals() +// { +// // Given +// $adapter = new CouponBaseAdapter(); +// $a = 12; +// $operator = Operators::INFERIOR; +// $b = new QuantityParam($adapter, 12); +// +// // When +// $actual = Operators::isValid($a, $operator, $b); +// +// // Then +// $this->assertFalse($actual); +// } +// +// /** +// * +// * @covers Thelia\Coupon\Rule\Operator::isValidAccordingToOperator +// * +// */ +// public function testOperatorInferiorInvalidAfter() +// { +// // Given +// $adapter = new CouponBaseAdapter(); +// $a = 13; +// $operator = Operators::INFERIOR; +// $b = new QuantityParam($adapter, 12); +// +// // When +// $actual = Operators::isValid($a, $operator, $b); +// +// // Then +// $this->assertFalse($actual); +// } +// +// /** +// * +// * @covers Thelia\Coupon\Rule\Operator::isValidAccordingToOperator +// * +// */ +// public function testOperatorInferiorOrEqualValidEqual() +// { +// // Given +// $adapter = new CouponBaseAdapter(); +// $a = 11; +// $operator = Operators::INFERIOR_OR_EQUAL; +// $b = new QuantityParam($adapter, 11); +// +// // When +// $actual = Operators::isValid($a, $operator, $b); +// +// // Then +// $this->assertTrue($actual); +// } +// +// /** +// * +// * @covers Thelia\Coupon\Rule\Operator::isValidAccordingToOperator +// * +// */ +// public function testOperatorInferiorOrEqualValidBefore() +// { +// // Given +// $adapter = new CouponBaseAdapter(); +// $a = 10; +// $operator = Operators::INFERIOR_OR_EQUAL; +// $b = new QuantityParam($adapter, 11); +// +// // When +// $actual = Operators::isValid($a, $operator, $b); +// +// // Then +// $this->assertTrue($actual); +// } +// +// /** +// * +// * @covers Thelia\Coupon\Rule\Operator::isValidAccordingToOperator +// * +// */ +// public function testOperatorInferiorOrEqualInValidAfter() +// { +// // Given +// $adapter = new CouponBaseAdapter(); +// $a = 12; +// $operator = Operators::INFERIOR_OR_EQUAL; +// $b = new QuantityParam($adapter, 11); +// +// // When +// $actual = Operators::isValid($a, $operator, $b); +// +// // Then +// $this->assertFalse($actual); +// } +// +// /** +// * +// * @covers Thelia\Coupon\Rule\Operator::isValidAccordingToOperator +// * +// */ +// public function testOperatorEqualValidEqual() +// { +// // Given +// $adapter = new CouponBaseAdapter(); +// $a = 12; +// $operator = Operators::EQUAL; +// $b = new QuantityParam($adapter, 12); +// +// // When +// $actual = Operators::isValid($a, $operator, $b); +// +// // Then +// $this->assertTrue($actual); +// } +// +// /** +// * +// * @covers Thelia\Coupon\Rule\Operator::isValidAccordingToOperator +// * +// */ +// public function testOperatorEqualInValidBefore() +// { +// // Given +// $adapter = new CouponBaseAdapter(); +// $a = 11; +// $operator = Operators::EQUAL; +// $b = new QuantityParam($adapter, 12); +// +// // When +// $actual = Operators::isValid($a, $operator, $b); +// +// // Then +// $this->assertFalse($actual); +// } +// +// /** +// * +// * @covers Thelia\Coupon\Rule\Operator::isValidAccordingToOperator +// * +// */ +// public function testOperatorEqualInValidAfter() +// { +// // Given +// $adapter = new CouponBaseAdapter(); +// $a = 13; +// $operator = Operators::EQUAL; +// $b = new QuantityParam($adapter, 12); +// +// // When +// $actual = Operators::isValid($a, $operator, $b); +// +// // Then +// $this->assertFalse($actual); +// } +// +// /** +// * +// * @covers Thelia\Coupon\Rule\Operator::isValidAccordingToOperator +// * +// */ +// public function testOperatorSuperiorOrEqualValidEqual() +// { +// // Given +// $adapter = new CouponBaseAdapter(); +// $a = 13; +// $operator = Operators::SUPERIOR_OR_EQUAL; +// $b = new QuantityParam($adapter, 13); +// +// // When +// $actual = Operators::isValid($a, $operator, $b); +// +// // Then +// $this->assertTrue($actual); +// } +// +// /** +// * +// * @covers Thelia\Coupon\Rule\Operator::isValidAccordingToOperator +// * +// */ +// public function testOperatorSuperiorOrEqualAfter() +// { +// // Given +// $adapter = new CouponBaseAdapter(); +// $a = 14; +// $operator = Operators::SUPERIOR_OR_EQUAL; +// $b = new QuantityParam($adapter, 13); +// +// // When +// $actual = Operators::isValid($a, $operator, $b); +// +// // Then +// $this->assertTrue($actual); +// } +// +// /** +// * +// * @covers Thelia\Coupon\Rule\Operator::isValidAccordingToOperator +// * +// */ +// public function testOperatorSuperiorOrEqualInvalidBefore() +// { +// // Given +// $adapter = new CouponBaseAdapter(); +// $a = 12; +// $operator = Operators::SUPERIOR_OR_EQUAL; +// $b = new QuantityParam($adapter, 13); +// +// // When +// $actual = Operators::isValid($a, $operator, $b); +// +// // Then +// $this->assertFalse($actual); +// } +// +// /** +// * +// * @covers Thelia\Coupon\Rule\Operator::isValidAccordingToOperator +// * +// */ +// public function testOperatorSuperiorValidAfter() +// { +// // Given +// $adapter = new CouponBaseAdapter(); +// $a = 13; +// $operator = Operators::SUPERIOR; +// $b = new QuantityParam($adapter, 12); +// +// // When +// $actual = Operators::isValid($a, $operator, $b); +// +// // Then +// $this->assertTrue($actual); +// } +// +// /** +// * +// * @covers Thelia\Coupon\Rule\Operator::isValidAccordingToOperator +// * +// */ +// public function testOperatorSuperiorInvalidEqual() +// { +// // Given +// $adapter = new CouponBaseAdapter(); +// $a = 12; +// $operator = Operators::SUPERIOR; +// $b = new QuantityParam($adapter, 12); +// +// // When +// $actual = Operators::isValid($a, $operator, $b); +// +// // Then +// $this->assertFalse($actual); +// } +// +// /** +// * +// * @covers Thelia\Coupon\Rule\Operator::isValidAccordingToOperator +// * +// */ +// public function testOperatorSuperiorInvalidBefore() +// { +// // Given +// $adapter = new CouponBaseAdapter(); +// $a = 11; +// $operator = Operators::SUPERIOR; +// $b = new QuantityParam($adapter, 12); +// +// // When +// $actual = Operators::isValid($a, $operator, $b); +// +// // Then +// $this->assertFalse($actual); +// } +// +// /** +// * +// * @covers Thelia\Coupon\Rule\Operator::isValidAccordingToOperator +// * +// */ +// public function testOperatorDifferentValid() +// { +// // Given +// $adapter = new CouponBaseAdapter(); +// $a = 12; +// $operator = Operators::DIFFERENT; +// $b = new QuantityParam($adapter, 11); +// +// // When +// $actual = Operators::isValid($a, $operator, $b); +// +// // Then +// $this->assertTrue($actual); +// } +// +// /** +// * +// * @covers Thelia\Coupon\Rule\Operator::isValidAccordingToOperator +// * +// */ +// public function testOperatorDifferentInvalidEquals() +// { +// // Given +// $adapter = new CouponBaseAdapter(); +// $a = 11; +// $operator = Operators::DIFFERENT; +// $b = new QuantityParam($adapter, 11); +// +// // When +// $actual = Operators::isValid($a, $operator, $b); +// +// // Then +// $this->assertFalse($actual); +// } +// +// /** +// * +// * @covers Thelia\Coupon\Rule\Operator::isValidAccordingToOperator +// * +// */ +// public function testOperatorInValid() +// { +// // Given +// $adapter = new CouponBaseAdapter(); +// $a = 12; +// $operator = 'X'; +// $b = new QuantityParam($adapter, 11); +// +// // When +// $actual = Operators::isValid($a, $operator, $b); +// +// // Then +// $this->assertFalse($actual); +// } + + + + /** + * Tears down the fixture, for example, closes a network connection. + * This method is called after a test is executed. + */ + protected function tearDown() + { + } + +} diff --git a/core/lib/Thelia/Tests/Constraint/Validator/CustomerParamTest.php b/core/lib/Thelia/Tests/Constraint/Validator/CustomerParamTest.php new file mode 100644 index 000000000..afb7b8c80 --- /dev/null +++ b/core/lib/Thelia/Tests/Constraint/Validator/CustomerParamTest.php @@ -0,0 +1,169 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Coupon; + +use InvalidArgumentException; +use Thelia\Constraint\Validator\CustomerParam; +use Thelia\Constraint\Validator\PriceParam; +use Thelia\Constraint\Validator\QuantityParam; +use Thelia\Model\Customer; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Unit Test CustomerParam Class + * + * @package Constraint + * @author Guillaume MOREL + * + */ +class CustomerParamTest extends \PHPUnit_Framework_TestCase +{ + + public function testSomething() + { + // Stop here and mark this test as incomplete. + $this->markTestIncomplete( + 'This test has not been implemented yet.' + ); + } + +// /** @var CouponAdapterInterface $stubTheliaAdapter */ +// protected $stubTheliaAdapter = null; +// +// /** +// * Sets up the fixture, for example, opens a network connection. +// * This method is called before a test is executed. +// */ +// protected function setUp() +// { +// /** @var CouponAdapterInterface $stubTheliaAdapter */ +// $this->stubTheliaAdapter = $this->generateValidCouponBaseAdapterMock(); +// } +// +// /** +// * Generate valid CouponBaseAdapter +// * +// * @param int $customerId Customer id +// * +// * @return CouponAdapterInterface +// */ +// protected function generateValidCouponBaseAdapterMock($customerId = 4521) +// { +// $customer = new Customer(); +// $customer->setId($customerId); +// $customer->setFirstname('Firstname'); +// $customer->setLastname('Lastname'); +// $customer->setEmail('em@il.com'); +// +// /** @var CouponAdapterInterface $stubTheliaAdapter */ +// $stubTheliaAdapter = $this->getMock( +// 'Thelia\Coupon\CouponBaseAdapter', +// array('getCustomer'), +// array() +// ); +// $stubTheliaAdapter->expects($this->any()) +// ->method('getCustomer') +// ->will($this->returnValue($customer)); +// +// return $stubTheliaAdapter; +// } +// +// /** +// * +// * @covers Thelia\Coupon\Parameter\QuantityParam::compareTo +// * +// */ +// public function testCanUseCoupon() +// { +// $customerId = 4521; +// $couponValidForCustomerId = 4521; +// +// $adapter = $this->generateValidCouponBaseAdapterMock($customerId); +// +// $customerParam = new CustomerParam($adapter, $couponValidForCustomerId); +// +// $expected = 0; +// $actual = $customerParam->compareTo($customerId); +// $this->assertEquals($expected, $actual); +// } +// +//// /** +//// * +//// * @covers Thelia\Coupon\Parameter\QuantityParam::compareTo +//// * +//// */ +//// public function testCanNotUseCouponTest() +//// { +//// +//// } +//// +//// /** +//// * +//// * @covers Thelia\Coupon\Parameter\QuantityParam::compareTo +//// * @expectedException InvalidArgumentException +//// * +//// */ +//// public function testCanNotUseCouponCustomerNotFoundTest() +//// { +//// +//// } +// +// +// +// +//// /** +//// * Test is the object is serializable +//// * If no data is lost during the process +//// */ +//// public function isSerializableTest() +//// { +//// $adapter = new CouponBaseAdapter(); +//// $intValidator = 42; +//// $intToValidate = -1; +//// +//// $param = new QuantityParam($adapter, $intValidator); +//// +//// $serialized = base64_encode(serialize($param)); +//// /** @var QuantityParam $unserialized */ +//// $unserialized = base64_decode(serialize($serialized)); +//// +//// $this->assertEquals($param->getValue(), $unserialized->getValue()); +//// $this->assertEquals($param->getInteger(), $unserialized->getInteger()); +//// +//// $new = new QuantityParam($adapter, $unserialized->getInteger()); +//// $this->assertEquals($param->getInteger(), $new->getInteger()); +//// } +// +// /** +// * Tears down the fixture, for example, closes a network connection. +// * This method is called after a test is executed. +// */ +// protected function tearDown() +// { +// } + +} diff --git a/core/lib/Thelia/Tests/Constraint/Validator/DateParamTest.php b/core/lib/Thelia/Tests/Constraint/Validator/DateParamTest.php new file mode 100644 index 000000000..53a5c70eb --- /dev/null +++ b/core/lib/Thelia/Tests/Constraint/Validator/DateParamTest.php @@ -0,0 +1,158 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Coupon; + +use InvalidArgumentException; +use Thelia\Constraint\Validator\DateParam; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Unit Test DateParam Class + * + * @package Constraint + * @author Guillaume MOREL + * + */ +class DateParamTest extends \PHPUnit_Framework_TestCase +{ + public function testSomething() + { + // Stop here and mark this test as incomplete. + $this->markTestIncomplete( + 'This test has not been implemented yet.' + ); + } + +// /** +// * Sets up the fixture, for example, opens a network connection. +// * This method is called before a test is executed. +// */ +// protected function setUp() +// { +// } +// +// /** +// * +// * @covers Thelia\Coupon\Parameter\DateParam::compareTo +// * +// */ +// public function testInferiorDate() +// { +// $adapter = new CouponBaseAdapter(); +// $dateValidator = new \DateTime("2012-07-08"); +// $dateToValidate = new \DateTime("2012-07-07"); +// +// $dateParam = new DateParam($adapter, $dateValidator); +// +// $expected = 1; +// $actual = $dateParam->compareTo($dateToValidate); +// $this->assertEquals($expected, $actual); +// } +// +// /** +// * +// * @covers Thelia\Coupon\Parameter\DateParam::compareTo +// * +// */ +// public function testEqualsDate() +// { +// $adapter = new CouponBaseAdapter(); +// $dateValidator = new \DateTime("2012-07-08"); +// $dateToValidate = new \DateTime("2012-07-08"); +// +// $dateParam = new DateParam($adapter, $dateValidator); +// +// $expected = 0; +// $actual = $dateParam->compareTo($dateToValidate); +// $this->assertEquals($expected, $actual); +// } +// +// /** +// * +// * @covers Thelia\Coupon\Parameter\DateParam::compareTo +// * +// */ +// public function testSuperiorDate() +// { +// $adapter = new CouponBaseAdapter(); +// $dateValidator = new \DateTime("2012-07-08"); +// $dateToValidate = new \DateTime("2012-07-09"); +// +// $dateParam = new DateParam($adapter, $dateValidator); +// +// $expected = -1; +// $actual = $dateParam->compareTo($dateToValidate); +// $this->assertEquals($expected, $actual); +// } +// +// /** +// * @covers Thelia\Coupon\Parameter\DateParam::compareTo +// * @expectedException InvalidArgumentException +// */ +// public function testInvalidArgumentException() +// { +// $adapter = new CouponBaseAdapter(); +// $dateValidator = new \DateTime("2012-07-08"); +// $dateToValidate = 1377012588; +// +// $dateParam = new DateParam($adapter, $dateValidator); +// +// $dateParam->compareTo($dateToValidate); +// } +// +// /** +// * Test is the object is serializable +// * If no data is lost during the process +// */ +// public function isSerializableTest() +// { +// $adapter = new CouponBaseAdapter(); +// $dateValidator = new \DateTime("2012-07-08"); +// +// $param = new DateParam($adapter, $dateValidator); +// +// $serialized = base64_encode(serialize($param)); +// /** @var DateParam $unserialized */ +// $unserialized = base64_decode(serialize($serialized)); +// +// $this->assertEquals($param->getValue(), $unserialized->getValue()); +// $this->assertEquals($param->getDateTime(), $unserialized->getDateTime()); +// +// $new = new DateParam($adapter, $unserialized->getDateTime()); +// $this->assertEquals($param->getDateTime(), $new->getDateTime()); +// } +// +// +// /** +// * Tears down the fixture, for example, closes a network connection. +// * This method is called after a test is executed. +// */ +// protected function tearDown() +// { +// } + +} diff --git a/core/lib/Thelia/Tests/Constraint/Validator/IntegerParamTest.php b/core/lib/Thelia/Tests/Constraint/Validator/IntegerParamTest.php new file mode 100644 index 000000000..edf71b138 --- /dev/null +++ b/core/lib/Thelia/Tests/Constraint/Validator/IntegerParamTest.php @@ -0,0 +1,159 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Coupon; + +use InvalidArgumentException; +use Thelia\Constraint\Validator\IntegerParam; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Unit Test IntegerParam Class + * + * @package Constraint + * @author Guillaume MOREL + * + */ +class IntegerParamTest extends \PHPUnit_Framework_TestCase +{ + + public function testSomething() + { + // Stop here and mark this test as incomplete. + $this->markTestIncomplete( + 'This test has not been implemented yet.' + ); + } +// /** +// * Sets up the fixture, for example, opens a network connection. +// * This method is called before a test is executed. +// */ +// protected function setUp() +// { +// } +// +// /** +// * +// * @covers Thelia\Coupon\Parameter\IntegerParam::compareTo +// * +// */ +// public function testInferiorInteger() +// { +// $adapter = new CouponBaseAdapter(); +// $intValidator = 42; +// $intToValidate = 41; +// +// $integerParam = new IntegerParam($adapter, $intValidator); +// +// $expected = 1; +// $actual = $integerParam->compareTo($intToValidate); +// $this->assertEquals($expected, $actual); +// } +// +// /** +// * +// * @covers Thelia\Coupon\Parameter\IntegerParam::compareTo +// * +// */ +// public function testEqualsInteger() +// { +// $adapter = new CouponBaseAdapter(); +// $intValidator = 42; +// $intToValidate = 42; +// +// $integerParam = new IntegerParam($adapter, $intValidator); +// +// $expected = 0; +// $actual = $integerParam->compareTo($intToValidate); +// $this->assertEquals($expected, $actual); +// } +// +// /** +// * +// * @covers Thelia\Coupon\Parameter\IntegerParam::compareTo +// * +// */ +// public function testSuperiorInteger() +// { +// $adapter = new CouponBaseAdapter(); +// $intValidator = 42; +// $intToValidate = 43; +// +// $integerParam = new IntegerParam($adapter, $intValidator); +// +// $expected = -1; +// $actual = $integerParam->compareTo($intToValidate); +// $this->assertEquals($expected, $actual); +// } +// +// /** +// * @covers Thelia\Coupon\Parameter\IntegerParam::compareTo +// * @expectedException InvalidArgumentException +// */ +// public function testInvalidArgumentException() +// { +// $adapter = new CouponBaseAdapter(); +// $intValidator = 42; +// $intToValidate = '42'; +// +// $integerParam = new IntegerParam($adapter, $intValidator); +// +// $expected = 0; +// $actual = $integerParam->compareTo($intToValidate); +// $this->assertEquals($expected, $actual); +// } +// +// /** +// * Test is the object is serializable +// * If no data is lost during the process +// */ +// public function isSerializableTest() +// { +// $adapter = new CouponBaseAdapter(); +// $intValidator = 42; +// +// $param = new IntegerParam($adapter, $intValidator); +// +// $serialized = base64_encode(serialize($param)); +// /** @var IntegerParam $unserialized */ +// $unserialized = base64_decode(serialize($serialized)); +// +// $this->assertEquals($param->getValue(), $unserialized->getValue()); +// $this->assertEquals($param->getInteger(), $unserialized->getInteger()); +// +// $new = new IntegerParam($adapter, $unserialized->getInteger()); +// $this->assertEquals($param->getInteger(), $new->getInteger()); +// } +// +// /** +// * Tears down the fixture, for example, closes a network connection. +// * This method is called after a test is executed. +// */ +// protected function tearDown() +// { +// } + +} diff --git a/core/lib/Thelia/Tests/Constraint/Validator/IntervalParamTest.php b/core/lib/Thelia/Tests/Constraint/Validator/IntervalParamTest.php new file mode 100644 index 000000000..e98c5f719 --- /dev/null +++ b/core/lib/Thelia/Tests/Constraint/Validator/IntervalParamTest.php @@ -0,0 +1,184 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Coupon; + +use InvalidArgumentException; +use Thelia\Constraint\Validator\IntervalParam; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Unit Test IntervalParam Class + * + * @package Constraint + * @author Guillaume MOREL + * + */ +class IntervalParamTest extends \PHPUnit_Framework_TestCase +{ + public function testSomething() + { + // Stop here and mark this test as incomplete. + $this->markTestIncomplete( + 'This test has not been implemented yet.' + ); + } + +// /** +// * Sets up the fixture, for example, opens a network connection. +// * This method is called before a test is executed. +// */ +// protected function setUp() +// { +// } +// +// /** +// * +// * @covers Thelia\Coupon\Parameter\IntervalParam::compareTo +// * +// */ +// public function testInferiorDate() +// { +// $adapter = new CouponBaseAdapter(); +// $dateValidatorStart = new \DateTime("2012-07-08"); +// $dateValidatorInterval = new \DateInterval("P1M"); //1month +// $dateToValidate = new \DateTime("2012-07-07"); +// +// $dateParam = new IntervalParam($adapter, $dateValidatorStart, $dateValidatorInterval); +// +// $expected = 1; +// $actual = $dateParam->compareTo($dateToValidate); +// $this->assertEquals($expected, $actual); +// } +// +// /** +// * +// * @covers Thelia\Coupon\Parameter\IntervalParam::compareTo +// * +// */ +// public function testEqualsDate() +// { +// $adapter = new CouponBaseAdapter(); +// $dateValidatorStart = new \DateTime("2012-07-08"); +// $dateValidatorInterval = new \DateInterval("P1M"); //1month +// $dateToValidate = new \DateTime("2012-07-08"); +// +// echo '1 ' . date_format($dateValidatorStart, 'g:ia \o\n l jS F Y') . "\n"; +// echo '2 ' . date_format($dateToValidate, 'g:ia \o\n l jS F Y') . "\n"; +// +// $dateParam = new IntervalParam($adapter, $dateValidatorStart, $dateValidatorInterval); +// +// $expected = 0; +// $actual = $dateParam->compareTo($dateToValidate); +// $this->assertEquals($expected, $actual); +// } +// +// /** +// * +// * @covers Thelia\Coupon\Parameter\IntervalParam::compareTo +// * +// */ +// public function testEqualsDate2() +// { +// $adapter = new CouponBaseAdapter(); +// $dateValidatorStart = new \DateTime("2012-07-08"); +// $dateValidatorInterval = new \DateInterval("P1M"); //1month +// $dateToValidate = new \DateTime("2012-08-08"); +// +// $dateParam = new IntervalParam($adapter, $dateValidatorStart, $dateValidatorInterval); +// +// $expected = 0; +// $actual = $dateParam->compareTo($dateToValidate); +// $this->assertEquals($expected, $actual); +// } +// +// /** +// * +// * @covers Thelia\Coupon\Parameter\IntervalParam::compareTo +// * +// */ +// public function testSuperiorDate() +// { +// $adapter = new CouponBaseAdapter(); +// $dateValidatorStart = new \DateTime("2012-07-08"); +// $dateValidatorInterval = new \DateInterval("P1M"); //1month +// $dateToValidate = new \DateTime("2012-08-09"); +// +// $dateParam = new IntervalParam($adapter, $dateValidatorStart, $dateValidatorInterval); +// +// $expected = -1; +// $actual = $dateParam->compareTo($dateToValidate); +// $this->assertEquals($expected, $actual); +// } +// +// /** +// * @covers Thelia\Coupon\Parameter\DateParam::compareTo +// * @expectedException InvalidArgumentException +// */ +// public function testInvalidArgumentException() +// { +// $adapter = new CouponBaseAdapter(); +// $dateValidatorStart = new \DateTime("2012-07-08"); +// $dateValidatorInterval = new \DateInterval("P1M"); //1month +// $dateToValidate = 1377012588; +// +// $dateParam = new IntervalParam($adapter, $dateValidatorStart, $dateValidatorInterval); +// +// $dateParam->compareTo($dateToValidate); +// } +// +// /** +// * Test is the object is serializable +// * If no data is lost during the process +// */ +// public function isSerializableTest() +// { +// $adapter = new CouponBaseAdapter(); +// $dateValidatorStart = new \DateTime("2012-07-08"); +// $dateValidatorInterval = new \DateInterval("P1M"); //1month +// +// $param = new IntervalParam($adapter, $dateValidatorStart, $dateValidatorInterval); +// +// $serialized = base64_encode(serialize($param)); +// /** @var IntervalParam $unserialized */ +// $unserialized = base64_decode(serialize($serialized)); +// +// $this->assertEquals($param->getValue(), $unserialized->getValue()); +// $this->assertEquals($param->getDatePeriod(), $unserialized->getDatePeriod()); +// +// $new = new IntervalParam($adapter, $unserialized->getStart(), $unserialized->getInterval()); +// $this->assertEquals($param->getDatePeriod(), $new->getDatePeriod()); +// } +// +// /** +// * Tears down the fixture, for example, closes a network connection. +// * This method is called after a test is executed. +// */ +// protected function tearDown() +// { +// } + +} diff --git a/core/lib/Thelia/Tests/Constraint/Validator/PriceParamTest.php b/core/lib/Thelia/Tests/Constraint/Validator/PriceParamTest.php new file mode 100644 index 000000000..4eb04a77e --- /dev/null +++ b/core/lib/Thelia/Tests/Constraint/Validator/PriceParamTest.php @@ -0,0 +1,237 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Coupon; + +use InvalidArgumentException; +use Thelia\Constraint\Validator\PriceParam; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Unit Test PriceParam Class + * + * @package Constraint + * @author Guillaume MOREL + * + */ +class PriceParamTest extends \PHPUnit_Framework_TestCase +{ + + public function testSomething() + { + // Stop here and mark this test as incomplete. + $this->markTestIncomplete( + 'This test has not been implemented yet.' + ); + } +// /** +// * Sets up the fixture, for example, opens a network connection. +// * This method is called before a test is executed. +// */ +// protected function setUp() +// { +// } +// +// /** +// * +// * @covers Thelia\Coupon\Parameter\PriceParam::compareTo +// * +// */ +// public function testInferiorPrice() +// { +// $adapter = new CouponBaseAdapter(); +// +// $priceValidator = 42.50; +// $priceToValidate = 1.00; +// +// $integerParam = new PriceParam($adapter, $priceValidator, 'EUR'); +// +// $expected = 1; +// $actual = $integerParam->compareTo($priceToValidate); +// $this->assertEquals($expected, $actual); +// } +// +// /** +// * +// * @covers Thelia\Coupon\Parameter\PriceParam::compareTo +// * +// */ +// public function testInferiorPrice2() +// { +// $adapter = new CouponBaseAdapter(); +// +// $priceValidator = 42.50; +// $priceToValidate = 42.49; +// +// $integerParam = new PriceParam($adapter, $priceValidator, 'EUR'); +// +// $expected = 1; +// $actual = $integerParam->compareTo($priceToValidate); +// $this->assertEquals($expected, $actual); +// } +// +// /** +// * +// * @covers Thelia\Coupon\Parameter\PriceParam::compareTo +// * +// */ +// public function testEqualsPrice() +// { +// $adapter = new CouponBaseAdapter(); +// +// $priceValidator = 42.50; +// $priceToValidate = 42.50; +// +// $integerParam = new PriceParam($adapter, $priceValidator, 'EUR'); +// +// $expected = 0; +// $actual = $integerParam->compareTo($priceToValidate); +// $this->assertEquals($expected, $actual); +// } +// +// /** +// * +// * @covers Thelia\Coupon\Parameter\PriceParam::compareTo +// * +// */ +// public function testSuperiorPrice() +// { +// $adapter = new CouponBaseAdapter(); +// +// $priceValidator = 42.50; +// $priceToValidate = 42.51; +// +// $integerParam = new PriceParam($adapter, $priceValidator, 'EUR'); +// +// $expected = -1; +// $actual = $integerParam->compareTo($priceToValidate); +// $this->assertEquals($expected, $actual); +// } +// +// /** +// * @covers Thelia\Coupon\Parameter\PriceParam::compareTo +// * @expectedException InvalidArgumentException +// */ +// public function testInvalidArgumentException() +// { +// $adapter = new CouponBaseAdapter(); +// +// $priceValidator = 42.50; +// $priceToValidate = '42.50'; +// +// $integerParam = new PriceParam($adapter, $priceValidator, 'EUR'); +// +// $expected = 0; +// $actual = $integerParam->compareTo($priceToValidate); +// $this->assertEquals($expected, $actual); +// } +// +// /** +// * @covers Thelia\Coupon\Parameter\PriceParam::compareTo +// * @expectedException InvalidArgumentException +// */ +// public function testInvalidArgumentException2() +// { +// $adapter = new CouponBaseAdapter(); +// +// $priceValidator = 42.50; +// $priceToValidate = -1; +// +// $integerParam = new PriceParam($adapter, $priceValidator, 'EUR'); +// +// $expected = 0; +// $actual = $integerParam->compareTo($priceToValidate); +// $this->assertEquals($expected, $actual); +// } +// +// /** +// * @covers Thelia\Coupon\Parameter\PriceParam::compareTo +// * @expectedException InvalidArgumentException +// */ +// public function testInvalidArgumentException3() +// { +// $adapter = new CouponBaseAdapter(); +// +// $priceValidator = 42.50; +// $priceToValidate = 0; +// +// $integerParam = new PriceParam($adapter, $priceValidator, 'EUR'); +// +// $expected = 0; +// $actual = $integerParam->compareTo($priceToValidate); +// $this->assertEquals($expected, $actual); +// } +// +// /** +// * @covers Thelia\Coupon\Parameter\PriceParam::compareTo +// * @expectedException InvalidArgumentException +// */ +// public function testInvalidArgumentException4() +// { +// $adapter = new CouponBaseAdapter(); +// $priceValidator = 42.50; +// $priceToValidate = 1; +// +// $integerParam = new PriceParam($adapter, $priceValidator, 'GBP'); +// +// $expected = 0; +// $actual = $integerParam->compareTo($priceToValidate); +// $this->assertEquals($expected, $actual); +// } +// +// /** +// * Test is the object is serializable +// * If no data is lost during the process +// */ +// public function isSerializableTest() +// { +// $adapter = new CouponBaseAdapter(); +// $priceValidator = 42.50; +// +// $param = new PriceParam($adapter, $priceValidator, 'GBP'); +// +// $serialized = base64_encode(serialize($param)); +// /** @var PriceParam $unserialized */ +// $unserialized = base64_decode(serialize($serialized)); +// +// $this->assertEquals($param->getValue(), $unserialized->getValue()); +// $this->assertEquals($param->getPrice(), $unserialized->getPrice()); +// $this->assertEquals($param->getCurrency(), $unserialized->getCurrency()); +// +// $new = new PriceParam($adapter, $unserialized->getPrice(), $unserialized->getCurrency()); +// $this->assertEquals($param->getPrice(), $new->getPrice()); +// $this->assertEquals($param->getCurrency(), $new->getCurrency()); +// } +// +// /** +// * Tears down the fixture, for example, closes a network connection. +// * This method is called after a test is executed. +// */ +// protected function tearDown() +// { +// } + +} diff --git a/core/lib/Thelia/Tests/Constraint/Validator/QuantityParamTest.php b/core/lib/Thelia/Tests/Constraint/Validator/QuantityParamTest.php new file mode 100644 index 000000000..afcc62f6e --- /dev/null +++ b/core/lib/Thelia/Tests/Constraint/Validator/QuantityParamTest.php @@ -0,0 +1,196 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Coupon; + +use InvalidArgumentException; +use Thelia\Constraint\Validator\PriceParam; +use Thelia\Constraint\Validator\QuantityParam; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Unit Test QuantityParam Class + * + * @package Constraint + * @author Guillaume MOREL + * + */ +class QuantityParamTest extends \PHPUnit_Framework_TestCase +{ + public function testSomething() + { + // Stop here and mark this test as incomplete. + $this->markTestIncomplete( + 'This test has not been implemented yet.' + ); + } + +// /** +// * Sets up the fixture, for example, opens a network connection. +// * This method is called before a test is executed. +// */ +// protected function setUp() +// { +// } +// +// /** +// * +// * @covers Thelia\Coupon\Parameter\QuantityParam::compareTo +// * +// */ +// public function testInferiorQuantity() +// { +// $adapter = new CouponBaseAdapter(); +// $intValidator = 42; +// $intToValidate = 0; +// +// $integerParam = new QuantityParam($adapter, $intValidator); +// +// $expected = 1; +// $actual = $integerParam->compareTo($intToValidate); +// $this->assertEquals($expected, $actual); +// } +// +// /** +// * +// * @covers Thelia\Coupon\Parameter\QuantityParam::compareTo +// * +// */ +// public function testInferiorQuantity2() +// { +// $adapter = new CouponBaseAdapter(); +// $intValidator = 42; +// $intToValidate = 41; +// +// $integerParam = new QuantityParam($adapter, $intValidator); +// +// $expected = 1; +// $actual = $integerParam->compareTo($intToValidate); +// $this->assertEquals($expected, $actual); +// } +// +// /** +// * +// * @covers Thelia\Coupon\Parameter\QuantityParam::compareTo +// * +// */ +// public function testEqualsQuantity() +// { +// $adapter = new CouponBaseAdapter(); +// $intValidator = 42; +// $intToValidate = 42; +// +// $integerParam = new QuantityParam($adapter, $intValidator); +// +// $expected = 0; +// $actual = $integerParam->compareTo($intToValidate); +// $this->assertEquals($expected, $actual); +// } +// +// /** +// * +// * @covers Thelia\Coupon\Parameter\QuantityParam::compareTo +// * +// */ +// public function testSuperiorQuantity() +// { +// $adapter = new CouponBaseAdapter(); +// $intValidator = 42; +// $intToValidate = 43; +// +// $integerParam = new QuantityParam($adapter, $intValidator); +// +// $expected = -1; +// $actual = $integerParam->compareTo($intToValidate); +// $this->assertEquals($expected, $actual); +// } +// +// /** +// * @covers Thelia\Coupon\Parameter\QuantityParam::compareTo +// * @expectedException InvalidArgumentException +// */ +// public function testInvalidArgumentException() +// { +// $adapter = new CouponBaseAdapter(); +// $intValidator = 42; +// $intToValidate = '42'; +// +// $integerParam = new QuantityParam($adapter, $intValidator); +// +// $expected = 0; +// $actual = $integerParam->compareTo($intToValidate); +// $this->assertEquals($expected, $actual); +// } +// +// /** +// * @covers Thelia\Coupon\Parameter\QuantityParam::compareTo +// * @expectedException InvalidArgumentException +// */ +// public function testInvalidArgumentException2() +// { +// $adapter = new CouponBaseAdapter(); +// $intValidator = 42; +// $intToValidate = -1; +// +// $integerParam = new QuantityParam($adapter, $intValidator); +// +// $expected = 0; +// $actual = $integerParam->compareTo($intToValidate); +// $this->assertEquals($expected, $actual); +// } +// +// /** +// * Test is the object is serializable +// * If no data is lost during the process +// */ +// public function isSerializableTest() +// { +// $adapter = new CouponBaseAdapter(); +// $intValidator = 42; +// $intToValidate = -1; +// +// $param = new QuantityParam($adapter, $intValidator); +// +// $serialized = base64_encode(serialize($param)); +// /** @var QuantityParam $unserialized */ +// $unserialized = base64_decode(serialize($serialized)); +// +// $this->assertEquals($param->getValue(), $unserialized->getValue()); +// $this->assertEquals($param->getInteger(), $unserialized->getInteger()); +// +// $new = new QuantityParam($adapter, $unserialized->getInteger()); +// $this->assertEquals($param->getInteger(), $new->getInteger()); +// } +// +// /** +// * Tears down the fixture, for example, closes a network connection. +// * This method is called after a test is executed. +// */ +// protected function tearDown() +// { +// } + +} diff --git a/core/lib/Thelia/Tests/Constraint/Validator/RepeatedDateParamTest.php b/core/lib/Thelia/Tests/Constraint/Validator/RepeatedDateParamTest.php new file mode 100644 index 000000000..677117348 --- /dev/null +++ b/core/lib/Thelia/Tests/Constraint/Validator/RepeatedDateParamTest.php @@ -0,0 +1,310 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Coupon; + +use InvalidArgumentException; +use Symfony\Component\Intl\Exception\NotImplementedException; +use Thelia\Constraint\Validator\RepeatedDateParam; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Unit Test RepeatedDateParam Class + * + * @package Constraint + * @author Guillaume MOREL + * + */ +class RepeatedDateParamTest extends \PHPUnit_Framework_TestCase +{ + public function testSomething() + { + // Stop here and mark this test as incomplete. + $this->markTestIncomplete( + 'This test has not been implemented yet.' + ); + } + +// /** +// * Sets up the fixture, for example, opens a network connection. +// * This method is called before a test is executed. +// */ +// protected function setUp() +// { +// } +// +// /** +// * +// * @covers Thelia\Coupon\Parameter\RepeatedDateParam::compareTo +// * +// */ +// public function testInferiorDate() +// { +// $adapter = new CouponBaseAdapter(); +// $startDateValidator = new \DateTime("2012-07-08"); +// $dateToValidate = new \DateTime("2012-07-07"); +// +// $repeatedDateParam = new RepeatedDateParam($adapter); +// $repeatedDateParam->setFrom($startDateValidator); +// $repeatedDateParam->repeatEveryMonth(); +// +// $expected = -1; +// $actual = $repeatedDateParam->compareTo($dateToValidate); +// $this->assertEquals($expected, $actual); +// } +// +// /** +// * +// * @covers Thelia\Coupon\Parameter\RepeatedDateParam::compareTo +// * +// */ +// public function testEqualsDateRepeatEveryMonthOneTimeFirstPeriod() +// { +// $adapter = new CouponBaseAdapter(); +// $startDateValidator = new \DateTime("2012-07-08"); +// $dateToValidate = new \DateTime("2012-07-08"); +// +// $repeatedDateParam = new RepeatedDateParam($adapter); +// $repeatedDateParam->setFrom($startDateValidator); +// $repeatedDateParam->repeatEveryMonth(); +// +// $expected = 0; +// $actual = $repeatedDateParam->compareTo($dateToValidate); +// $this->assertEquals($expected, $actual); +// } +// +// /** +// * +// * @covers Thelia\Coupon\Parameter\RepeatedDateParam::compareTo +// * +// */ +// public function testEqualsDateRepeatEveryMonthOneTimeSecondPeriod() +// { +// $adapter = new CouponBaseAdapter(); +// $startDateValidator = new \DateTime("2012-07-08"); +// $dateToValidate = new \DateTime("2012-08-08"); +// +// $repeatedDateParam = new RepeatedDateParam($adapter); +// $repeatedDateParam->setFrom($startDateValidator); +// $repeatedDateParam->repeatEveryMonth(1, 1); +// +// $expected = 0; +// $actual = $repeatedDateParam->compareTo($dateToValidate); +// $this->assertEquals($expected, $actual); +// } +// +// /** +// * +// * @covers Thelia\Coupon\Parameter\RepeatedDateParam::compareTo +// * +// */ +// public function testEqualsDateRepeatEveryMonthTenTimesThirdPeriod() +// { +// $adapter = new CouponBaseAdapter(); +// $startDateValidator = new \DateTime("2012-07-08"); +// $dateToValidate = new \DateTime("2012-09-08"); +// +// $repeatedDateParam = new RepeatedDateParam($adapter); +// $repeatedDateParam->setFrom($startDateValidator); +// $repeatedDateParam->repeatEveryMonth(1, 10); +// +// $expected = 0; +// $actual = $repeatedDateParam->compareTo($dateToValidate); +// $this->assertEquals($expected, $actual); +// } +// +// /** +// * +// * @covers Thelia\Coupon\Parameter\RepeatedDateParam::compareTo +// * +// */ +// public function testEqualsDateRepeatEveryMonthTenTimesTensPeriod() +// { +// $adapter = new CouponBaseAdapter(); +// $startDateValidator = new \DateTime("2012-07-08"); +// $dateToValidate = new \DateTime("2013-05-08"); +// +// $repeatedDateParam = new RepeatedDateParam($adapter); +// $repeatedDateParam->setFrom($startDateValidator); +// $repeatedDateParam->repeatEveryMonth(1, 10); +// +// $expected = 0; +// $actual = $repeatedDateParam->compareTo($dateToValidate); +// $this->assertEquals($expected, $actual); +// } +// +// /** +// * +// * @covers Thelia\Coupon\Parameter\RepeatedDateParam::compareTo +// * +// */ +// public function testEqualsDateRepeatEveryFourMonthTwoTimesSecondPeriod() +// { +// $adapter = new CouponBaseAdapter(); +// $startDateValidator = new \DateTime("2012-07-08"); +// $dateToValidate = new \DateTime("2012-11-08"); +// +// $repeatedDateParam = new RepeatedDateParam($adapter); +// $repeatedDateParam->setFrom($startDateValidator); +// $repeatedDateParam->repeatEveryMonth(4, 2); +// +// $expected = 0; +// $actual = $repeatedDateParam->compareTo($dateToValidate); +// $this->assertEquals($expected, $actual); +// } +// +// /** +// * +// * @covers Thelia\Coupon\Parameter\RepeatedDateParam::compareTo +// * +// */ +// public function testEqualsDateRepeatEveryFourMonthTwoTimesLastPeriod() +// { +// $adapter = new CouponBaseAdapter(); +// $startDateValidator = new \DateTime("2012-07-08"); +// $dateToValidate = new \DateTime("2013-03-08"); +// +// $repeatedDateParam = new RepeatedDateParam($adapter); +// $repeatedDateParam->setFrom($startDateValidator); +// $repeatedDateParam->repeatEveryMonth(4, 2); +// +// $expected = 0; +// $actual = $repeatedDateParam->compareTo($dateToValidate); +// $this->assertEquals($expected, $actual); +// } +// +// /** +// * +// * @covers Thelia\Coupon\Parameter\RepeatedDateParam::compareTo +// * +// */ +// public function testNotEqualsDateRepeatEveryFourMonthTwoTimes1() +// { +// $adapter = new CouponBaseAdapter(); +// $startDateValidator = new \DateTime("2012-07-08"); +// $dateToValidate = new \DateTime("2012-08-08"); +// +// $repeatedDateParam = new RepeatedDateParam($adapter); +// $repeatedDateParam->setFrom($startDateValidator); +// $repeatedDateParam->repeatEveryMonth(4, 2); +// +// $expected = -1; +// $actual = $repeatedDateParam->compareTo($dateToValidate); +// $this->assertEquals($expected, $actual); +// } +// +// /** +// * +// * @covers Thelia\Coupon\Parameter\RepeatedDateParam::compareTo +// * +// */ +// public function testNotEqualsDateRepeatEveryFourMonthTwoTimes2() +// { +// $adapter = new CouponBaseAdapter(); +// $startDateValidator = new \DateTime("2012-07-08"); +// $dateToValidate = new \DateTime("2012-12-08"); +// +// $repeatedDateParam = new RepeatedDateParam($adapter); +// $repeatedDateParam->setFrom($startDateValidator); +// $repeatedDateParam->repeatEveryMonth(4, 2); +// +// $expected = -1; +// $actual = $repeatedDateParam->compareTo($dateToValidate); +// $this->assertEquals($expected, $actual); +// } +// +// /** +// * +// * @covers Thelia\Coupon\Parameter\RepeatedDateParam::compareTo +// * +// */ +// public function testSuperiorDateRepeatEveryFourMonthTwoTimes() +// { +// $adapter = new CouponBaseAdapter(); +// $startDateValidator = new \DateTime("2012-07-08"); +// $dateToValidate = new \DateTime("2013-03-09"); +// +// $repeatedDateParam = new RepeatedDateParam($adapter); +// $repeatedDateParam->setFrom($startDateValidator); +// $repeatedDateParam->repeatEveryMonth(4, 2); +// +// $expected = -1; +// $actual = $repeatedDateParam->compareTo($dateToValidate); +// $this->assertEquals($expected, $actual); +// } +// +// /** +// * @covers Thelia\Coupon\Parameter\DateParam::compareTo +// * @expectedException InvalidArgumentException +// */ +// public function testInvalidArgumentException() +// { +// $adapter = new CouponBaseAdapter(); +// $startDateValidator = new \DateTime("2012-07-08"); +// $dateToValidate = 1377012588; +// +// $repeatedDateParam = new RepeatedDateParam($adapter); +// $repeatedDateParam->setFrom($startDateValidator); +// $repeatedDateParam->repeatEveryMonth(4, 2); +// +// $repeatedDateParam->compareTo($dateToValidate); +// } +// +// /** +// * Test is the object is serializable +// * If no data is lost during the process +// */ +// public function isSerializableTest() +// { +// $adapter = new CouponBaseAdapter(); +// $startDateValidator = new \DateTime("2012-07-08"); +// +// $param = new RepeatedDateParam($adapter); +// $param->setFrom($startDateValidator); +// $param->repeatEveryMonth(4, 2); +// +// $serialized = base64_encode(serialize($param)); +// /** @var RepeatedDateParam $unserialized */ +// $unserialized = base64_decode(serialize($serialized)); +// +// $this->assertEquals($param->getValue(), $unserialized->getValue()); +// $this->assertEquals($param->getDatePeriod(), $unserialized->getDatePeriod()); +// +// $new = new RepeatedDateParam($adapter); +// $new->setFrom($unserialized->getFrom()); +// $new->repeatEveryMonth($unserialized->getFrequency(), $unserialized->getNbRepetition()); +// $this->assertEquals($param->getDatePeriod(), $new->getDatePeriod()); +// } +// +// /** +// * Tears down the fixture, for example, closes a network connection. +// * This method is called after a test is executed. +// */ +// protected function tearDown() +// { +// } + +} diff --git a/core/lib/Thelia/Tests/Constraint/Validator/RepeatedIntervalParamTest.php b/core/lib/Thelia/Tests/Constraint/Validator/RepeatedIntervalParamTest.php new file mode 100644 index 000000000..513e85836 --- /dev/null +++ b/core/lib/Thelia/Tests/Constraint/Validator/RepeatedIntervalParamTest.php @@ -0,0 +1,427 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Coupon; + +use Symfony\Component\Intl\Exception\NotImplementedException; +use Thelia\Constraint\Validator\RepeatedIntervalParam; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Unit Test RepeatedIntervalParam Class + * + * @package Constraint + * @author Guillaume MOREL + * + */ +class RepeatedIntervalParamTest extends \PHPUnit_Framework_TestCase +{ + + public function testSomething() + { + // Stop here and mark this test as incomplete. + $this->markTestIncomplete( + 'This test has not been implemented yet.' + ); + } +// /** +// * Sets up the fixture, for example, opens a network connection. +// * This method is called before a test is executed. +// */ +// protected function setUp() +// { +// } +// +// /** +// * +// * @covers Thelia\Coupon\Parameter\RepeatedIntervalParam::compareTo +// * +// */ +// public function testInferiorDate() +// { +// $adapter = new CouponBaseAdapter(); +// $startDateValidator = new \DateTime("2012-07-08"); +// $dateToValidate = new \DateTime("2012-07-07"); +// $duration = 10; +// +// $RepeatedIntervalParam = new RepeatedIntervalParam($adapter); +// $RepeatedIntervalParam->setFrom($startDateValidator); +// $RepeatedIntervalParam->setDurationInDays($duration); +// +// $RepeatedIntervalParam->repeatEveryMonth(); +// +// $expected = -1; +// $actual = $RepeatedIntervalParam->compareTo($dateToValidate); +// $this->assertEquals($expected, $actual); +// } +// +// /** +// * +// * @covers Thelia\Coupon\Parameter\RepeatedIntervalParam::compareTo +// * +// */ +// public function testEqualsDateRepeatEveryMonthOneTimeFirstPeriodBeginning() +// { +// $adapter = new CouponBaseAdapter(); +// $startDateValidator = new \DateTime("2012-07-08"); +// $dateToValidate = new \DateTime("2012-07-08"); +// $duration = 10; +// +// $RepeatedIntervalParam = new RepeatedIntervalParam($adapter); +// $RepeatedIntervalParam->setFrom($startDateValidator); +// $RepeatedIntervalParam->setDurationInDays($duration); +// $RepeatedIntervalParam->repeatEveryMonth(); +// +// $expected = 0; +// $actual = $RepeatedIntervalParam->compareTo($dateToValidate); +// $this->assertEquals($expected, $actual); +// } +// +// /** +// * +// * @covers Thelia\Coupon\Parameter\RepeatedIntervalParam::compareTo +// * +// */ +// public function testEqualsDateRepeatEveryMonthOneTimeFirstPeriodMiddle() +// { +// $adapter = new CouponBaseAdapter(); +// $startDateValidator = new \DateTime("2012-07-08"); +// $dateToValidate = new \DateTime("2012-07-13"); +// $duration = 10; +// +// $RepeatedIntervalParam = new RepeatedIntervalParam($adapter); +// $RepeatedIntervalParam->setFrom($startDateValidator); +// $RepeatedIntervalParam->setDurationInDays($duration); +// $RepeatedIntervalParam->repeatEveryMonth(); +// +// $expected = 0; +// $actual = $RepeatedIntervalParam->compareTo($dateToValidate); +// $this->assertEquals($expected, $actual); +// } +// +// /** +// * +// * @covers Thelia\Coupon\Parameter\RepeatedIntervalParam::compareTo +// * +// */ +// public function testEqualsDateRepeatEveryMonthOneTimeFirstPeriodEnding() +// { +// $adapter = new CouponBaseAdapter(); +// $startDateValidator = new \DateTime("2012-07-08"); +// $dateToValidate = new \DateTime("2012-07-18"); +// $duration = 10; +// +// $RepeatedIntervalParam = new RepeatedIntervalParam($adapter); +// $RepeatedIntervalParam->setFrom($startDateValidator); +// $RepeatedIntervalParam->setDurationInDays($duration); +// $RepeatedIntervalParam->repeatEveryMonth(); +// +// $expected = 0; +// $actual = $RepeatedIntervalParam->compareTo($dateToValidate); +// $this->assertEquals($expected, $actual); +// } +// +// /** +// * +// * @covers Thelia\Coupon\Parameter\RepeatedIntervalParam::compareTo +// * +// */ +// public function testEqualsDateRepeatEveryMonthOneTimeSecondPeriodBeginning() +// { +// $adapter = new CouponBaseAdapter(); +// $startDateValidator = new \DateTime("2012-08-08"); +// $dateToValidate = new \DateTime("2012-08-08"); +// $duration = 10; +// +// $RepeatedIntervalParam = new RepeatedIntervalParam($adapter); +// $RepeatedIntervalParam->setFrom($startDateValidator); +// $RepeatedIntervalParam->setDurationInDays($duration); +// $RepeatedIntervalParam->repeatEveryMonth(); +// +// $expected = 0; +// $actual = $RepeatedIntervalParam->compareTo($dateToValidate); +// $this->assertEquals($expected, $actual); +// } +// +// /** +// * +// * @covers Thelia\Coupon\Parameter\RepeatedIntervalParam::compareTo +// * +// */ +// public function testEqualsDateRepeatEveryMonthOneTimeSecondPeriodMiddle() +// { +// $adapter = new CouponBaseAdapter(); +// $startDateValidator = new \DateTime("2012-08-08"); +// $dateToValidate = new \DateTime("2012-08-13"); +// $duration = 10; +// +// $RepeatedIntervalParam = new RepeatedIntervalParam($adapter); +// $RepeatedIntervalParam->setFrom($startDateValidator); +// $RepeatedIntervalParam->setDurationInDays($duration); +// $RepeatedIntervalParam->repeatEveryMonth(); +// +// $expected = 0; +// $actual = $RepeatedIntervalParam->compareTo($dateToValidate); +// $this->assertEquals($expected, $actual); +// } +// +// /** +// * +// * @covers Thelia\Coupon\Parameter\RepeatedIntervalParam::compareTo +// * +// */ +// public function testEqualsDateRepeatEveryMonthOneTimeSecondPeriodEnding() +// { +// $adapter = new CouponBaseAdapter(); +// $startDateValidator = new \DateTime("2012-08-08"); +// $dateToValidate = new \DateTime("2012-08-18"); +// $duration = 10; +// +// $RepeatedIntervalParam = new RepeatedIntervalParam($adapter); +// $RepeatedIntervalParam->setFrom($startDateValidator); +// $RepeatedIntervalParam->setDurationInDays($duration); +// $RepeatedIntervalParam->repeatEveryMonth(); +// +// $expected = 0; +// $actual = $RepeatedIntervalParam->compareTo($dateToValidate); +// $this->assertEquals($expected, $actual); +// } +// +// /** +// * +// * @covers Thelia\Coupon\Parameter\RepeatedIntervalParam::compareTo +// * +// */ +// public function testEqualsDateRepeatEveryMonthFourTimeLastPeriodBeginning() +// { +// $adapter = new CouponBaseAdapter(); +// $startDateValidator = new \DateTime("2012-10-08"); +// $dateToValidate = new \DateTime("2012-10-08"); +// $duration = 10; +// +// $RepeatedIntervalParam = new RepeatedIntervalParam($adapter); +// $RepeatedIntervalParam->setFrom($startDateValidator); +// $RepeatedIntervalParam->setDurationInDays($duration); +// $RepeatedIntervalParam->repeatEveryMonth(1, 4); +// +// $expected = 0; +// $actual = $RepeatedIntervalParam->compareTo($dateToValidate); +// $this->assertEquals($expected, $actual); +// } +// +// /** +// * +// * @covers Thelia\Coupon\Parameter\RepeatedIntervalParam::compareTo +// * +// */ +// public function testEqualsDateRepeatEveryMonthFourTimeLastPeriodMiddle() +// { +// $adapter = new CouponBaseAdapter(); +// $startDateValidator = new \DateTime("2012-10-08"); +// $dateToValidate = new \DateTime("2012-10-13"); +// $duration = 10; +// +// $RepeatedIntervalParam = new RepeatedIntervalParam($adapter); +// $RepeatedIntervalParam->setFrom($startDateValidator); +// $RepeatedIntervalParam->setDurationInDays($duration); +// $RepeatedIntervalParam->repeatEveryMonth(1, 4); +// +// $expected = 0; +// $actual = $RepeatedIntervalParam->compareTo($dateToValidate); +// $this->assertEquals($expected, $actual); +// } +// +// /** +// * +// * @covers Thelia\Coupon\Parameter\RepeatedIntervalParam::compareTo +// * +// */ +// public function testEqualsDateRepeatEveryMonthFourTimeLastPeriodEnding() +// { +// $adapter = new CouponBaseAdapter(); +// $startDateValidator = new \DateTime("2012-10-08"); +// $dateToValidate = new \DateTime("2012-10-18"); +// $duration = 10; +// +// $RepeatedIntervalParam = new RepeatedIntervalParam($adapter); +// $RepeatedIntervalParam->setFrom($startDateValidator); +// $RepeatedIntervalParam->setDurationInDays($duration); +// $RepeatedIntervalParam->repeatEveryMonth(1, 4); +// +// $expected = 0; +// $actual = $RepeatedIntervalParam->compareTo($dateToValidate); +// $this->assertEquals($expected, $actual); +// } +// +// /** +// * +// * @covers Thelia\Coupon\Parameter\RepeatedIntervalParam::compareTo +// * +// */ +// public function testNotEqualsDateRepeatEveryMonthFourTimeInTheBeginning() +// { +// $adapter = new CouponBaseAdapter(); +// $startDateValidator = new \DateTime("2012-10-08"); +// $dateToValidate = new \DateTime("2012-07-19"); +// $duration = 10; +// +// $RepeatedIntervalParam = new RepeatedIntervalParam($adapter); +// $RepeatedIntervalParam->setFrom($startDateValidator); +// $RepeatedIntervalParam->setDurationInDays($duration); +// $RepeatedIntervalParam->repeatEveryMonth(1, 4); +// +// $expected = -1; +// $actual = $RepeatedIntervalParam->compareTo($dateToValidate); +// $this->assertEquals($expected, $actual); +// } +// +// /** +// * +// * @covers Thelia\Coupon\Parameter\RepeatedIntervalParam::compareTo +// * +// */ +// public function testNotEqualsDateRepeatEveryMonthFourTimeInTheMiddle() +// { +// $adapter = new CouponBaseAdapter(); +// $startDateValidator = new \DateTime("2012-10-08"); +// $dateToValidate = new \DateTime("2012-08-01"); +// $duration = 10; +// +// $RepeatedIntervalParam = new RepeatedIntervalParam($adapter); +// $RepeatedIntervalParam->setFrom($startDateValidator); +// $RepeatedIntervalParam->setDurationInDays($duration); +// $RepeatedIntervalParam->repeatEveryMonth(1, 4); +// +// $expected = -1; +// $actual = $RepeatedIntervalParam->compareTo($dateToValidate); +// $this->assertEquals($expected, $actual); +// } +// +// +// /** +// * +// * @covers Thelia\Coupon\Parameter\RepeatedIntervalParam::compareTo +// * +// */ +// public function testNotEqualsDateRepeatEveryMonthFourTimeInTheEnd() +// { +// $adapter = new CouponBaseAdapter(); +// $startDateValidator = new \DateTime("2012-10-08"); +// $dateToValidate = new \DateTime("2012-08-07"); +// $duration = 10; +// +// $RepeatedIntervalParam = new RepeatedIntervalParam($adapter); +// $RepeatedIntervalParam->setFrom($startDateValidator); +// $RepeatedIntervalParam->setDurationInDays($duration); +// $RepeatedIntervalParam->repeatEveryMonth(1, 4); +// +// $expected = -1; +// $actual = $RepeatedIntervalParam->compareTo($dateToValidate); +// $this->assertEquals($expected, $actual); +// } +// +// +// +// /** +// * +// * @covers Thelia\Coupon\Parameter\RepeatedIntervalParam::compareTo +// * +// */ +// public function testSuperiorDateRepeatEveryMonthFourTime() +// { +// $adapter = new CouponBaseAdapter(); +// $startDateValidator = new \DateTime("2012-07-08"); +// $dateToValidate = new \DateTime("2012-10-19"); +// $duration = 10; +// +// $RepeatedIntervalParam = new RepeatedIntervalParam($adapter); +// $RepeatedIntervalParam->setFrom($startDateValidator); +// $RepeatedIntervalParam->setDurationInDays($duration); +// $RepeatedIntervalParam->repeatEveryMonth(1, 0); +// +// $expected = -1; +// $actual = $RepeatedIntervalParam->compareTo($dateToValidate); +// $this->assertEquals($expected, $actual); +// } +// +// /** +// * @covers Thelia\Coupon\Parameter\DateParam::compareTo +// * @expectedException \InvalidArgumentException +// */ +// public function testInvalidArgumentException() +// { +// $adapter = new CouponBaseAdapter(); +// $startDateValidator = new \DateTime("2012-07-08"); +// $dateToValidate = 1377012588; +// $duration = 10; +// +// $RepeatedIntervalParam = new RepeatedIntervalParam($adapter); +// $RepeatedIntervalParam->setFrom($startDateValidator); +// $RepeatedIntervalParam->setDurationInDays($duration); +// $RepeatedIntervalParam->repeatEveryMonth(1, 4); +// +// $RepeatedIntervalParam->compareTo($dateToValidate); +// } +// +// /** +// * Test is the object is serializable +// * If no data is lost during the process +// */ +// public function isSerializableTest() +// { +// $adapter = new CouponBaseAdapter(); +// $startDateValidator = new \DateTime("2012-07-08"); +// $dateToValidate = 1377012588; +// $duration = 10; +// +// $param = new RepeatedIntervalParam($adapter); +// $param->setFrom($startDateValidator); +// $param->setDurationInDays($duration); +// $param->repeatEveryMonth(1, 4); +// +// $serialized = base64_encode(serialize($param)); +// /** @var RepeatedIntervalParam $unserialized */ +// $unserialized = base64_decode(serialize($serialized)); +// +// $this->assertEquals($param->getValue(), $unserialized->getValue()); +// $this->assertEquals($param->getDatePeriod(), $unserialized->getDatePeriod()); +// +// $new = new RepeatedIntervalParam($adapter); +// $new->setFrom($unserialized->getFrom()); +// $new->repeatEveryMonth($unserialized->getFrequency(), $unserialized->getNbRepetition()); +// $new->setDurationInDays($unserialized->getDurationInDays()); +// $this->assertEquals($param->getDatePeriod(), $new->getDatePeriod()); +// } +// +// /** +// * Tears down the fixture, for example, closes a network connection. +// * This method is called after a test is executed. +// */ +// protected function tearDown() +// { +// } + +} diff --git a/core/lib/Thelia/Tests/Core/Template/Element/BaseLoopTestor.php b/core/lib/Thelia/Tests/Core/Template/Element/BaseLoopTestor.php index 7d14fbbc5..4a9cb4158 100755 --- a/core/lib/Thelia/Tests/Core/Template/Element/BaseLoopTestor.php +++ b/core/lib/Thelia/Tests/Core/Template/Element/BaseLoopTestor.php @@ -23,6 +23,7 @@ namespace Thelia\Tests\Core\Template\Element; +use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\EventDispatcher\EventDispatcher; use Thelia\Core\HttpFoundation\Request; use Thelia\Core\Security\SecurityContext; @@ -34,11 +35,9 @@ use Thelia\Core\HttpFoundation\Session\Session; * @author Etienne Roudeix * */ -abstract class BaseLoopTestor extends \Thelia\Tests\TestCaseWithURLToolSetup +abstract class BaseLoopTestor extends \PHPUnit_Framework_TestCase { - protected $request; - protected $dispatcher; - protected $securityContext; + protected $container; protected $instance; @@ -57,12 +56,35 @@ abstract class BaseLoopTestor extends \Thelia\Tests\TestCaseWithURLToolSetup public function setUp() { - $this->request = new Request(); + $this->container = new ContainerBuilder(); + + $session = new Session(new MockArraySessionStorage()); + $request = new Request(); + + $request->setSession($session); + + /*$stubEventdispatcher = $this->getMockBuilder('\Symfony\Component\EventDispatcher\EventDispatcher') + ->disableOriginalConstructor() + ->getMock(); + + $stubSecurityContext = $this->getMockBuilder('\Thelia\Core\Security\SecurityContext') + ->disableOriginalConstructor() + ->getMock();*/ + + /*$stubAdapter->expects($this->any()) + ->method('getTranslator') + ->will($this->returnValue($stubTranslator));*/ + + /*$this->request = new Request(); $this->request->setSession(new Session(new MockArraySessionStorage())); $this->dispatcher = new EventDispatcher(); - $this->securityContext = new SecurityContext($this->request); + $this->securityContext = new SecurityContext($this->request);*/ + + $this->container->set('request', $request); + $this->container->set('event_dispatcher', new EventDispatcher()); + $this->container->set('thelia.securityContext', new SecurityContext($request)); $this->instance = $this->getTestedInstance(); $this->instance->initializeArgs($this->getMandatoryArguments()); diff --git a/core/lib/Thelia/Tests/Core/Template/Loop/AccessoryTest.php b/core/lib/Thelia/Tests/Core/Template/Loop/AccessoryTest.php index 99f5a0310..64bd4b5b6 100755 --- a/core/lib/Thelia/Tests/Core/Template/Loop/AccessoryTest.php +++ b/core/lib/Thelia/Tests/Core/Template/Loop/AccessoryTest.php @@ -41,7 +41,7 @@ class AccessoryTest extends BaseLoopTestor public function getTestedInstance() { - return new Accessory($this->request, $this->dispatcher, $this->securityContext); + return new Accessory($this->container); } public function getMandatoryArguments() diff --git a/core/lib/Thelia/Tests/Core/Template/Loop/AddressTest.php b/core/lib/Thelia/Tests/Core/Template/Loop/AddressTest.php index 7ca5c094b..447646b8b 100755 --- a/core/lib/Thelia/Tests/Core/Template/Loop/AddressTest.php +++ b/core/lib/Thelia/Tests/Core/Template/Loop/AddressTest.php @@ -41,7 +41,7 @@ class AddressTest extends BaseLoopTestor public function getTestedInstance() { - return new Address($this->request, $this->dispatcher, $this->securityContext); + return new Address($this->container); } public function getMandatoryArguments() diff --git a/core/lib/Thelia/Tests/Core/Template/Loop/AssociatedContentTest.php b/core/lib/Thelia/Tests/Core/Template/Loop/AssociatedContentTest.php index 0a12ad076..5d6c2579c 100755 --- a/core/lib/Thelia/Tests/Core/Template/Loop/AssociatedContentTest.php +++ b/core/lib/Thelia/Tests/Core/Template/Loop/AssociatedContentTest.php @@ -41,7 +41,7 @@ class AssociatedContentTest extends BaseLoopTestor public function getTestedInstance() { - return new AssociatedContent($this->request, $this->dispatcher, $this->securityContext); + return new AssociatedContent($this->container); } public function getMandatoryArguments() diff --git a/core/lib/Thelia/Tests/Core/Template/Loop/AttributeAvailabilityTest.php b/core/lib/Thelia/Tests/Core/Template/Loop/AttributeAvailabilityTest.php index c870f32ef..ca880daa8 100755 --- a/core/lib/Thelia/Tests/Core/Template/Loop/AttributeAvailabilityTest.php +++ b/core/lib/Thelia/Tests/Core/Template/Loop/AttributeAvailabilityTest.php @@ -41,7 +41,7 @@ class AttributeAvailabilityTest extends BaseLoopTestor public function getTestedInstance() { - return new AttributeAvailability($this->request, $this->dispatcher, $this->securityContext); + return new AttributeAvailability($this->container); } public function getMandatoryArguments() diff --git a/core/lib/Thelia/Tests/Core/Template/Loop/AttributeCombinationTest.php b/core/lib/Thelia/Tests/Core/Template/Loop/AttributeCombinationTest.php index 98d0575eb..f811c7de9 100755 --- a/core/lib/Thelia/Tests/Core/Template/Loop/AttributeCombinationTest.php +++ b/core/lib/Thelia/Tests/Core/Template/Loop/AttributeCombinationTest.php @@ -41,7 +41,7 @@ class AttributeCombinationTest extends BaseLoopTestor public function getTestedInstance() { - return new AttributeCombination($this->request, $this->dispatcher, $this->securityContext); + return new AttributeCombination($this->container); } public function getMandatoryArguments() diff --git a/core/lib/Thelia/Tests/Core/Template/Loop/AttributeTest.php b/core/lib/Thelia/Tests/Core/Template/Loop/AttributeTest.php index 653de34e9..46b19e3ac 100755 --- a/core/lib/Thelia/Tests/Core/Template/Loop/AttributeTest.php +++ b/core/lib/Thelia/Tests/Core/Template/Loop/AttributeTest.php @@ -41,7 +41,7 @@ class AttributeTest extends BaseLoopTestor public function getTestedInstance() { - return new Attribute($this->request, $this->dispatcher, $this->securityContext); + return new Attribute($this->container); } public function getMandatoryArguments() diff --git a/core/lib/Thelia/Tests/Core/Template/Loop/CategoryTest.php b/core/lib/Thelia/Tests/Core/Template/Loop/CategoryTest.php index f33d07868..a2a320693 100755 --- a/core/lib/Thelia/Tests/Core/Template/Loop/CategoryTest.php +++ b/core/lib/Thelia/Tests/Core/Template/Loop/CategoryTest.php @@ -41,7 +41,7 @@ class CategoryTest extends BaseLoopTestor public function getTestedInstance() { - return new Category($this->request, $this->dispatcher, $this->securityContext); + return new Category($this->container); } public function getMandatoryArguments() diff --git a/core/lib/Thelia/Tests/Core/Template/Loop/ContentTest.php b/core/lib/Thelia/Tests/Core/Template/Loop/ContentTest.php index 71922dbab..b6f9d0e3d 100755 --- a/core/lib/Thelia/Tests/Core/Template/Loop/ContentTest.php +++ b/core/lib/Thelia/Tests/Core/Template/Loop/ContentTest.php @@ -41,7 +41,7 @@ class ContentTest extends BaseLoopTestor public function getTestedInstance() { - return new Content($this->request, $this->dispatcher, $this->securityContext); + return new Content($this->container); } public function getMandatoryArguments() diff --git a/core/lib/Thelia/Tests/Core/Template/Loop/CountryTest.php b/core/lib/Thelia/Tests/Core/Template/Loop/CountryTest.php index 389d0bc5d..0eb37a6fd 100755 --- a/core/lib/Thelia/Tests/Core/Template/Loop/CountryTest.php +++ b/core/lib/Thelia/Tests/Core/Template/Loop/CountryTest.php @@ -41,7 +41,7 @@ class CountryTest extends BaseLoopTestor public function getTestedInstance() { - return new Country($this->request, $this->dispatcher, $this->securityContext); + return new Country($this->container); } public function getMandatoryArguments() diff --git a/core/lib/Thelia/Tests/Core/Template/Loop/CurrencyTest.php b/core/lib/Thelia/Tests/Core/Template/Loop/CurrencyTest.php index 95dd5a5c6..a866fae0c 100755 --- a/core/lib/Thelia/Tests/Core/Template/Loop/CurrencyTest.php +++ b/core/lib/Thelia/Tests/Core/Template/Loop/CurrencyTest.php @@ -41,7 +41,7 @@ class CurrencyTest extends BaseLoopTestor public function getTestedInstance() { - return new Currency($this->request, $this->dispatcher, $this->securityContext); + return new Currency($this->container); } public function getMandatoryArguments() diff --git a/core/lib/Thelia/Tests/Core/Template/Loop/CustomerTest.php b/core/lib/Thelia/Tests/Core/Template/Loop/CustomerTest.php index 62bcaa3be..4239414fa 100755 --- a/core/lib/Thelia/Tests/Core/Template/Loop/CustomerTest.php +++ b/core/lib/Thelia/Tests/Core/Template/Loop/CustomerTest.php @@ -41,7 +41,7 @@ class CustomerTest extends BaseLoopTestor public function getTestedInstance() { - return new Customer($this->request, $this->dispatcher, $this->securityContext); + return new Customer($this->container); } public function getMandatoryArguments() diff --git a/core/lib/Thelia/Tests/Core/Template/Loop/FeatureAvailabilityTest.php b/core/lib/Thelia/Tests/Core/Template/Loop/FeatureAvailabilityTest.php index d3a045f33..aae4ec254 100755 --- a/core/lib/Thelia/Tests/Core/Template/Loop/FeatureAvailabilityTest.php +++ b/core/lib/Thelia/Tests/Core/Template/Loop/FeatureAvailabilityTest.php @@ -41,7 +41,7 @@ class FeatureAvailabilityTest extends BaseLoopTestor public function getTestedInstance() { - return new FeatureAvailability($this->request, $this->dispatcher, $this->securityContext); + return new FeatureAvailability($this->container); } public function getMandatoryArguments() diff --git a/core/lib/Thelia/Tests/Core/Template/Loop/FeatureTest.php b/core/lib/Thelia/Tests/Core/Template/Loop/FeatureTest.php index 155088173..7324856f6 100755 --- a/core/lib/Thelia/Tests/Core/Template/Loop/FeatureTest.php +++ b/core/lib/Thelia/Tests/Core/Template/Loop/FeatureTest.php @@ -41,7 +41,7 @@ class FeatureTest extends BaseLoopTestor public function getTestedInstance() { - return new Feature($this->request, $this->dispatcher, $this->securityContext); + return new Feature($this->container); } public function getMandatoryArguments() diff --git a/core/lib/Thelia/Tests/Core/Template/Loop/FeatureValueTest.php b/core/lib/Thelia/Tests/Core/Template/Loop/FeatureValueTest.php index 3f6a14a16..19966ba71 100755 --- a/core/lib/Thelia/Tests/Core/Template/Loop/FeatureValueTest.php +++ b/core/lib/Thelia/Tests/Core/Template/Loop/FeatureValueTest.php @@ -41,7 +41,7 @@ class FeatureValueTest extends BaseLoopTestor public function getTestedInstance() { - return new FeatureValue($this->request, $this->dispatcher, $this->securityContext); + return new FeatureValue($this->container); } public function getMandatoryArguments() diff --git a/core/lib/Thelia/Tests/Core/Template/Loop/FolderTest.php b/core/lib/Thelia/Tests/Core/Template/Loop/FolderTest.php index 2505c2fc2..2388a86c0 100755 --- a/core/lib/Thelia/Tests/Core/Template/Loop/FolderTest.php +++ b/core/lib/Thelia/Tests/Core/Template/Loop/FolderTest.php @@ -41,7 +41,7 @@ class FolderTest extends BaseLoopTestor public function getTestedInstance() { - return new Folder($this->request, $this->dispatcher, $this->securityContext); + return new Folder($this->container); } public function getMandatoryArguments() diff --git a/core/lib/Thelia/Tests/Core/Template/Loop/ProductSaleElementTest.php b/core/lib/Thelia/Tests/Core/Template/Loop/ProductSaleElementTest.php index 612519e04..d8ed243ca 100755 --- a/core/lib/Thelia/Tests/Core/Template/Loop/ProductSaleElementTest.php +++ b/core/lib/Thelia/Tests/Core/Template/Loop/ProductSaleElementTest.php @@ -41,7 +41,7 @@ class ProductSaleElementsTest extends BaseLoopTestor public function getTestedInstance() { - return new ProductSaleElements($this->request, $this->dispatcher, $this->securityContext); + return new ProductSaleElements($this->container); } public function getMandatoryArguments() diff --git a/core/lib/Thelia/Tests/Core/Template/Loop/ProductTest.php b/core/lib/Thelia/Tests/Core/Template/Loop/ProductTest.php index 1ac5cb3b3..8fc7d5ae5 100755 --- a/core/lib/Thelia/Tests/Core/Template/Loop/ProductTest.php +++ b/core/lib/Thelia/Tests/Core/Template/Loop/ProductTest.php @@ -32,7 +32,7 @@ use Thelia\Core\Template\Loop\Product; * @author Etienne Roudeix * */ -/*class ProductTest extends BaseLoopTestor +class ProductTest extends BaseLoopTestor { public function getTestedClassName() { @@ -41,11 +41,11 @@ use Thelia\Core\Template\Loop\Product; public function getTestedInstance() { - return new Product($this->request, $this->dispatcher, $this->securityContext); + return new Product($this->container); } public function getMandatoryArguments() { return array(); } -}*/ +} diff --git a/core/lib/Thelia/Tests/Core/Template/Loop/TitleTest.php b/core/lib/Thelia/Tests/Core/Template/Loop/TitleTest.php index 392e97930..63e4a7a9a 100755 --- a/core/lib/Thelia/Tests/Core/Template/Loop/TitleTest.php +++ b/core/lib/Thelia/Tests/Core/Template/Loop/TitleTest.php @@ -41,7 +41,7 @@ class TitleTest extends BaseLoopTestor public function getTestedInstance() { - return new Title($this->request, $this->dispatcher, $this->securityContext); + return new Title($this->container); } public function getMandatoryArguments() diff --git a/core/lib/Thelia/Tests/Coupon/CouponBaseAdapterTest.php b/core/lib/Thelia/Tests/Coupon/CouponBaseAdapterTest.php new file mode 100644 index 000000000..45f097a77 --- /dev/null +++ b/core/lib/Thelia/Tests/Coupon/CouponBaseAdapterTest.php @@ -0,0 +1,103 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Coupon; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Unit Test CouponBaseAdapter Class + * + * @package Coupon + * @author Guillaume MOREL + * + */ +class CouponBaseAdapterTest extends \PHPUnit_Framework_TestCase +{ + public function testSomething() + { + // Stop here and mark this test as incomplete. + $this->markTestIncomplete( + 'This test has not been implemented yet.' + ); + } +// /** +// * @var CouponBaseAdapter +// */ +// protected $object; +// +// /** +// * Sets up the fixture, for example, opens a network connection. +// * This method is called before a test is executed. +// */ +// protected function setUp() +// { +// $this->object = new CouponBaseAdapter; +// } +// +// /** +// * Tears down the fixture, for example, closes a network connection. +// * This method is called after a test is executed. +// */ +// protected function tearDown() +// { +// } +// +// /** +// * @covers Thelia\Coupon\CouponBaseAdapter::getCart +// * @todo Implement testGetCart(). +// */ +// public function testGetCart() +// { +// // Remove the following lines when you implement this test. +// $this->markTestIncomplete( +// 'This test has not been implemented yet.' +// ); +// } +// +// /** +// * @covers Thelia\Coupon\CouponBaseAdapter::getDeliveryAddress +// * @todo Implement testGetDeliveryAddress(). +// */ +// public function testGetDeliveryAddress() +// { +// // Remove the following lines when you implement this test. +// $this->markTestIncomplete( +// 'This test has not been implemented yet.' +// ); +// } +// +// /** +// * @covers Thelia\Coupon\CouponBaseAdapter::getCustomer +// * @todo Implement testGetCustomer(). +// */ +// public function testGetCustomer() +// { +// // Remove the following lines when you implement this test. +// $this->markTestIncomplete( +// 'This test has not been implemented yet.' +// ); +// } +} diff --git a/core/lib/Thelia/Tests/Coupon/CouponFactoryTest.php b/core/lib/Thelia/Tests/Coupon/CouponFactoryTest.php new file mode 100644 index 000000000..261f0e100 --- /dev/null +++ b/core/lib/Thelia/Tests/Coupon/CouponFactoryTest.php @@ -0,0 +1,345 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Coupon; + +use Thelia\Constraint\Validator\PriceParam; +use Thelia\Constraint\Validator\RuleValidator; +use Thelia\Constraint\Rule\AvailableForTotalAmount; +use Thelia\Constraint\Rule\Operators; +use Thelia\Coupon\Type\CouponInterface; +use Thelia\Exception\CouponExpiredException; +use Thelia\Model\Coupon; + +require_once 'CouponManagerTest.php'; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Unit Test CouponFactory Class + * + * @package Coupon + * @author Guillaume MOREL + * + */ +class CouponFactoryTest extends \PHPUnit_Framework_TestCase +{ + public function testSomething() + { + // Stop here and mark this test as incomplete. + $this->markTestIncomplete( + 'This test has not been implemented yet.' + ); + } + +// /** +// * Sets up the fixture, for example, opens a network connection. +// * This method is called before a test is executed. +// */ +// protected function setUp() +// { +// } +// +// /** +// * Fake CouponQuery->findByCode +// * +// * @param string $code Coupon code +// * @param string $type Coupon type (object) +// * @param string $title Coupon title +// * @param string $shortDescription Coupon short description +// * @param string $description Coupon description +// * @param float $amount Coupon amount +// * @param bool $isUsed If Coupon has been used yet +// * @param bool $isEnabled If Coupon is enabled +// * @param \DateTime $expirationDate When Coupon expires +// * @param CouponRuleCollection $rules Coupon rules +// * @param bool $isCumulative If Coupon is cumulative +// * @param bool $isRemovingPostage If Coupon is removing postage +// * +// * @return Coupon +// */ +// public function generateCouponModelMock( +// $code = null, +// $type = null, +// $title = null, +// $shortDescription = null, +// $description = null, +// $amount = null, +// $isUsed = null, +// $isEnabled = null, +// $expirationDate = null, +// $rules = null, +// $isCumulative = null, +// $isRemovingPostage = null +// ) { +// $coupon = $this->generateValidCoupon( +// $code, +// $type, +// $title, +// $shortDescription, +// $description, +// $amount, +// $isUsed, +// $isEnabled, +// $expirationDate, +// $rules, +// $isCumulative, +// $isRemovingPostage +// ); +// +// /** @var CouponAdapterInterface $stubCouponBaseAdapter */ +// $stubCouponBaseAdapter = $this->getMock( +// 'Thelia\Coupon\CouponBaseAdapter', +// array('findOneCouponByCode'), +// array() +// ); +// $stubCouponBaseAdapter->expects($this->any()) +// ->method('findOneCouponByCode') +// ->will($this->returnValue($coupon)); +// +// return $stubCouponBaseAdapter; +// } +// +// +// +// /** +// * Test if an expired Coupon is build or not (superior) +// * +// * @covers Thelia\Coupon\CouponFactory::buildCouponFromCode +// * @expectedException \Thelia\Exception\CouponExpiredException +// */ +// public function testBuildCouponFromCodeExpiredDateBefore() +// { +// $date = new \DateTime(); +// $date->setTimestamp(strtotime("today - 2 months")); +// +// /** @var CouponAdapterInterface $mockAdapter */ +// $mockAdapter = $this->generateCouponModelMock(null, null, null, null, null, null, null, null, $date); +// $couponFactory = new CouponFactory($mockAdapter); +// $coupon = $couponFactory->buildCouponFromCode('XMAS1'); +// } +// +// /** +// * Test if an expired Coupon is build or not (equal) +// * +// * @covers Thelia\Coupon\CouponFactory::buildCouponFromCode +// * @expectedException \Thelia\Exception\CouponExpiredException +// */ +// public function testBuildCouponFromCodeExpiredDateEquals() +// { +// $date = new \DateTime(); +// +// /** @var CouponAdapterInterface $mockAdapter */ +// $mockAdapter = $this->generateCouponModelMock(null, null, null, null, null, null, null, null, $date); +// $couponFactory = new CouponFactory($mockAdapter); +// $coupon = $couponFactory->buildCouponFromCode('XMAS1'); +// } +// +// /** +// * Test if an expired Coupon is build or not (equal) +// * +// * @covers Thelia\Coupon\CouponFactory::buildCouponFromCode +// * @expectedException \Thelia\Exception\InvalidRuleException +// */ +// public function testBuildCouponFromCodeWithoutRule() +// { +// /** @var CouponAdapterInterface $mockAdapter */ +// $mockAdapter = $this->generateCouponModelMock(null, null, null, null, null, null, null, null, null, new CouponRuleCollection(array())); +// $couponFactory = new CouponFactory($mockAdapter); +// $coupon = $couponFactory->buildCouponFromCode('XMAS1'); +// } +// +// /** +// * Test if a CouponInterface can be built from database +// * +// * @covers Thelia\Coupon\CouponFactory::buildCouponFromCode +// */ +// public function testBuildCouponFromCode() +// { +// /** @var CouponAdapterInterface $mockAdapter */ +// $mockAdapter = $this->generateCouponModelMock(); +// $couponFactory = new CouponFactory($mockAdapter); +// /** @var CouponInterface $coupon */ +// $coupon = $couponFactory->buildCouponFromCode('XMAS1'); +// +// $this->assertEquals('XMAS1', $coupon->getCode()); +// $this->assertEquals('Thelia\Coupon\Type\RemoveXAmount', get_class($coupon)); +// $this->assertEquals(CouponManagerTest::VALID_TITLE, $coupon->getTitle()); +// $this->assertEquals(CouponManagerTest::VALID_SHORT_DESCRIPTION, $coupon->getShortDescription()); +// $this->assertEquals(CouponManagerTest::VALID_DESCRIPTION, $coupon->getDescription()); +// $this->assertEquals(10.00, $coupon->getDiscount()); +// $this->assertEquals(1, $coupon->isEnabled()); +// +// $date = new \DateTime(); +// $date->setTimestamp(strtotime("today + 2 months")); +// $this->assertEquals($date, $coupon->getExpirationDate()); +// +// $rules = $this->generateValidRules(); +// $this->assertEquals($rules, $coupon->getRules()); +// +// $this->assertEquals(1, $coupon->isCumulative()); +// $this->assertEquals(0, $coupon->isRemovingPostage()); +// } +// +// /** +// * Generate valid CouponRuleInterfaces +// * +// * @return CouponRuleCollection Set of CouponRuleInterface +// */ +// protected function generateValidRules() +// { +//// $rule1 = new AvailableForTotalAmount( +//// , array( +//// AvailableForTotalAmount::PARAM1_PRICE => new RuleValidator( +//// Operators::SUPERIOR, +//// new PriceParam( +//// , 40.00, 'EUR' +//// ) +//// ) +//// ) +//// ); +//// $rule2 = new AvailableForTotalAmount( +//// , array( +//// AvailableForTotalAmount::PARAM1_PRICE => new RuleValidator( +//// Operators::INFERIOR, +//// new PriceParam( +//// , 400.00, 'EUR' +//// ) +//// ) +//// ) +//// ); +//// $rules = new CouponRuleCollection(array($rule1, $rule2)); +//// +//// return $rules; +// } +// +// /** +// * Generate valid CouponInterface +// * +// * @param string $code Coupon code +// * @param string $type Coupon type (object) +// * @param string $title Coupon title +// * @param string $shortDescription Coupon short description +// * @param string $description Coupon description +// * @param float $amount Coupon amount +// * @param bool $isUsed If Coupon has been used yet +// * @param bool $isEnabled If Coupon is enabled +// * @param \DateTime $expirationDate When Coupon expires +// * @param CouponRuleCollection $rules Coupon rules +// * @param bool $isCumulative If Coupon is cumulative +// * @param bool $isRemovingPostage If Coupon is removing postage +// * +// * @return Coupon +// */ +// public function generateValidCoupon( +// $code = null, +// $type = null, +// $title = null, +// $shortDescription = null, +// $description = null, +// $amount = null, +// $isUsed = null, +// $isEnabled = null, +// $expirationDate = null, +// $rules = null, +// $isCumulative = null, +// $isRemovingPostage = null +// ) { +// $coupon = new Coupon(); +// +// if ($code === null) { +// $code = 'XMAS1'; +// } +// $coupon->setCode($code); +// +// if ($type === null) { +// $type = 'Thelia\Coupon\Type\RemoveXAmount'; +// } +// $coupon->setType($type); +// +// if ($title === null) { +// $title = CouponManagerTest::VALID_TITLE; +// } +// $coupon->setTitle($title); +// +// if ($shortDescription === null) { +// $shortDescription = CouponManagerTest::VALID_SHORT_DESCRIPTION; +// } +// $coupon->setShortDescription($shortDescription); +// +// if ($description === null) { +// $description = CouponManagerTest::VALID_DESCRIPTION; +// } +// $coupon->setDescription($description); +// +// if ($amount === null) { +// $amount = 10.00; +// } +// $coupon->setAmount($amount); +// +// if ($isUsed === null) { +// $isUsed = 1; +// } +// $coupon->setIsUsed($isUsed); +// +// if ($isEnabled === null) { +// $isEnabled = 1; +// } +// $coupon->setIsEnabled($isEnabled); +// +// if ($isCumulative === null) { +// $isCumulative = 1; +// } +// if ($isRemovingPostage === null) { +// $isRemovingPostage = 0; +// } +// +// if ($expirationDate === null) { +// $date = new \DateTime(); +// $coupon->setExpirationDate( +// $date->setTimestamp(strtotime("today + 2 months")) +// ); +// } +// +// if ($rules === null) { +// $rules = $this->generateValidRules(); +// } +// +// $coupon->setSerializedRules(base64_encode(serialize($rules))); +// +// $coupon->setIsCumulative($isCumulative); +// $coupon->setIsRemovingPostage($isRemovingPostage); +// +// return $coupon; +// } +// +// /** +// * Tears down the fixture, for example, closes a network connection. +// * This method is called after a test is executed. +// */ +// protected function tearDown() +// { +// } +} diff --git a/core/lib/Thelia/Tests/Coupon/CouponManagerTest.php b/core/lib/Thelia/Tests/Coupon/CouponManagerTest.php new file mode 100644 index 000000000..5a3d7881f --- /dev/null +++ b/core/lib/Thelia/Tests/Coupon/CouponManagerTest.php @@ -0,0 +1,811 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Coupon; + +use Thelia\Constraint\Validator\PriceParam; +use Thelia\Constraint\Validator\RuleValidator; +use Thelia\Constraint\Rule\AvailableForTotalAmountManager; +use Thelia\Constraint\Rule\Operators; +use Thelia\Coupon\Type\CouponInterface; +use Thelia\Coupon\Type\RemoveXAmountManager; +use Thelia\Tools\PhpUnitUtils; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Unit Test CouponManager Class + * + * @package Coupon + * @author Guillaume MOREL + * + */ +class CouponManagerTest extends \PHPUnit_Framework_TestCase +{ + public function testSomething() + { + // Stop here and mark this test as incomplete. + $this->markTestIncomplete( + 'This test has not been implemented yet.' + ); + } +// CONST VALID_CODE = 'XMAS'; +// CONST VALID_TITLE = 'XMAS coupon'; +// CONST VALID_SHORT_DESCRIPTION = 'Coupon for Christmas removing 10€ if your total checkout is more than 40€'; +// CONST VALID_DESCRIPTION = '

Lorem ipsum dolor sit amet

Consectetur adipiscing elit. Cras at luctus tellus. Integer turpis mauris, aliquet vitae risus tristique, pellentesque vestibulum urna. Vestibulum sodales laoreet lectus dictum suscipit. Praesent vulputate, sem id varius condimentum, quam magna tempor elit, quis venenatis ligula nulla eget libero. Cras egestas euismod tellus, id pharetra leo suscipit quis. Donec lacinia ac lacus et ultricies. Nunc in porttitor neque. Proin at quam congue, consectetur orci sed, congue nulla. Nulla eleifend nunc ligula, nec pharetra elit tempus quis. Vivamus vel mauris sed est dictum blandit. Maecenas blandit dapibus velit ut sollicitudin. In in euismod mauris, consequat viverra magna. Cras velit velit, sollicitudin commodo tortor gravida, tempus varius nulla. +// +//Donec rhoncus leo mauris, id porttitor ante luctus tempus. +// +//Curabitur quis augue feugiat, ullamcorper mauris ac, interdum mi. Quisque aliquam lorem vitae felis lobortis, id interdum turpis mattis. Vestibulum diam massa, ornare congue blandit quis, facilisis at nisl. In tortor metus, venenatis non arcu nec, sollicitudin ornare nisl. Nunc erat risus, varius nec urna at, iaculis lacinia elit. Aenean ut felis tempus, tincidunt odio non, sagittis nisl. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Donec vitae hendrerit elit. Nunc sit amet gravida risus, euismod lobortis massa. Nam a erat mauris. Nam a malesuada lorem. Nulla id accumsan dolor, sed rhoncus tellus. Quisque dictum felis sed leo auctor, at volutpat lectus viverra. Morbi rutrum, est ac aliquam imperdiet, nibh sem sagittis justo, ac mattis magna lacus eu nulla. +// +//Duis interdum lectus nulla, nec pellentesque sapien condimentum at. Suspendisse potenti. Sed eu purus tellus. Nunc quis rhoncus metus. Fusce vitae tellus enim. Interdum et malesuada fames ac ante ipsum primis in faucibus. Etiam tempor porttitor erat vitae iaculis. Sed est elit, consequat non ornare vitae, vehicula eget lectus. Etiam consequat sapien mauris, eget consectetur magna imperdiet eget. Nunc sollicitudin luctus velit, in commodo nulla adipiscing fermentum. Fusce nisi sapien, posuere vitae metus sit amet, facilisis sollicitudin dui. Fusce ultricies auctor enim sit amet iaculis. Morbi at vestibulum enim, eget adipiscing eros. +// +//Praesent ligula lorem, faucibus ut metus quis, fermentum iaculis erat. Pellentesque elit erat, lacinia sed semper ac, sagittis vel elit. Nam eu convallis est. Curabitur rhoncus odio vitae consectetur pellentesque. Nam vitae arcu nec ante scelerisque dignissim vel nec neque. Suspendisse augue nulla, mollis eget dui et, tempor facilisis erat. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi ac diam ipsum. Donec convallis dui ultricies velit auctor, non lobortis nulla ultrices. Morbi vitae dignissim ante, sit amet lobortis tortor. Nunc dapibus condimentum augue, in molestie neque congue non. +// +//Sed facilisis pellentesque nisl, eu tincidunt erat scelerisque a. Nullam malesuada tortor vel erat volutpat tincidunt. In vehicula diam est, a convallis eros scelerisque ut. Donec aliquet venenatis iaculis. Ut a arcu gravida, placerat dui eu, iaculis nisl. Quisque adipiscing orci sit amet dui dignissim lacinia. Sed vulputate lorem non dolor adipiscing ornare. Morbi ornare id nisl id aliquam. Ut fringilla elit ante, nec lacinia enim fermentum sit amet. Aenean rutrum lorem eu convallis pharetra. Cras malesuada varius metus, vitae gravida velit. Nam a varius ipsum, ac commodo dolor. Phasellus nec elementum elit. Etiam vel adipiscing leo.'; +// +// /** +// * Sets up the fixture, for example, opens a network connection. +// * This method is called before a test is executed. +// */ +// protected function setUp() +// { +// } +// +// /** +// * Test getDiscount() behaviour +// * Entering : 1 valid Coupon (If 40 < total amount 400) - 10euros +// * +// * @covers Thelia\Coupon\CouponManager::getDiscount +// */ +// public function testGetDiscountOneCoupon() +// { +// $cartTotalPrice = 100.00; +// $checkoutTotalPrice = 120.00; +// +// /** @var CouponInterface $coupon */ +// $coupon = self::generateValidCoupon(); +// +// /** @var CouponAdapterInterface $stubCouponBaseAdapter */ +// $stubCouponBaseAdapter = $this->generateFakeAdapter(array($coupon), $cartTotalPrice, $checkoutTotalPrice); +// +// $couponManager = new CouponManager($stubCouponBaseAdapter); +// $discount = $couponManager->getDiscount(); +// +// $expected = 10.00; +// $actual = $discount; +// $this->assertEquals($expected, $actual); +// } +// +// /** +// * Test getDiscount() behaviour +// * Entering : 1 valid Coupon (If 40 < total amount 400) - 10euros +// * 1 valid Coupon (If total amount > 20) - 15euros +// * +// * @covers Thelia\Coupon\CouponManager::getDiscount +// */ +// public function testGetDiscountTwoCoupon() +// { +// $adapter = new CouponBaseAdapter(); +// $cartTotalPrice = 100.00; +// $checkoutTotalPrice = 120.00; +// +// /** @var CouponInterface $coupon1 */ +// $coupon1 = self::generateValidCoupon(); +// $rule1 = new AvailableForTotalAmount( +// $adapter, array( +// AvailableForTotalAmount::PARAM1_PRICE => new RuleValidator( +// Operators::SUPERIOR, +// new PriceParam( +// $adapter, 40.00, 'EUR' +// ) +// ) +// ) +// ); +// $rules = new CouponRuleCollection(array($rule1)); +// /** @var CouponInterface $coupon2 */ +// $coupon2 = $this->generateValidCoupon('XMAS2', null, null, null, 15.00, null, null, $rules); +// +// /** @var CouponAdapterInterface $stubCouponBaseAdapter */ +// $stubCouponBaseAdapter = $this->generateFakeAdapter(array($coupon1, $coupon2), $cartTotalPrice, $checkoutTotalPrice); +// +// $couponManager = new CouponManager($stubCouponBaseAdapter); +// $discount = $couponManager->getDiscount(); +// +// $expected = 25.00; +// $actual = $discount; +// $this->assertEquals($expected, $actual); +// } +// +// /** +// * Test getDiscount() behaviour +// * For a Cart of 21euros +// * Entering : 1 valid Coupon (If total amount > 20) - 30euros +// * +// * @covers Thelia\Coupon\CouponManager::getDiscount +// */ +// public function testGetDiscountAlwaysInferiorToPrice() +// { +// $adapter = new CouponBaseAdapter(); +// $cartTotalPrice = 21.00; +// $checkoutTotalPrice = 26.00; +// +// $rule1 = new AvailableForTotalAmount( +// $adapter, array( +// AvailableForTotalAmount::PARAM1_PRICE => new RuleValidator( +// Operators::SUPERIOR, +// new PriceParam( +// $adapter, 20.00, 'EUR' +// ) +// ) +// ) +// ); +// $rules = new CouponRuleCollection(array($rule1)); +// /** @var CouponInterface $coupon */ +// $coupon = $this->generateValidCoupon('XMAS2', null, null, null, 30.00, null, null, $rules); +// +// /** @var CouponAdapterInterface $stubCouponBaseAdapter */ +// $stubCouponBaseAdapter = $this->generateFakeAdapter(array($coupon), $cartTotalPrice, $checkoutTotalPrice); +// +// $couponManager = new CouponManager($stubCouponBaseAdapter); +// $discount = $couponManager->getDiscount(); +// +// $expected = 21.00; +// $actual = $discount; +// $this->assertEquals($expected, $actual); +// } +// +// +// /** +// * Check if removing postage on discout is working +// * @covers Thelia\Coupon\CouponManager::isCouponRemovingPostage +// * @covers Thelia\Coupon\CouponManager::sortCoupons +// */ +// public function testIsCouponRemovingPostage() +// { +// $adapter = new CouponBaseAdapter(); +// $cartTotalPrice = 21.00; +// $checkoutTotalPrice = 27.00; +// +// $rule1 = new AvailableForTotalAmount( +// $adapter, array( +// AvailableForTotalAmount::PARAM1_PRICE => new RuleValidator( +// Operators::SUPERIOR, +// new PriceParam( +// $adapter, 20.00, 'EUR' +// ) +// ) +// ) +// ); +// $rules = new CouponRuleCollection(array($rule1)); +// /** @var CouponInterface $coupon */ +// $coupon = $this->generateValidCoupon('XMAS2', null, null, null, 30.00, null, null, $rules, null, true); +// +// /** @var CouponAdapterInterface $stubCouponBaseAdapter */ +// $stubCouponBaseAdapter = $this->generateFakeAdapter(array($coupon), $cartTotalPrice, $checkoutTotalPrice); +// +// $couponManager = new CouponManager($stubCouponBaseAdapter); +// $discount = $couponManager->getDiscount(); +// +// $expected = 21.00; +// $actual = $discount; +// $this->assertEquals($expected, $actual); +// } +// +// /** +// * Testing how multiple Coupon behaviour +// * Entering 1 Coupon not cumulative +// * +// * @covers Thelia\Coupon\CouponManager::sortCoupons +// */ +// public function testCouponCumulationOneCouponNotCumulative() +// { +// $cartTotalPrice = 100.00; +// $checkoutTotalPrice = 120.00; +// +// // Given +// /** @var CouponInterface $coupon */ +// $couponCumulative1 = $this->generateValidCoupon(null, null, null, null, null, null, null, null, false); +// +// $coupons = array($couponCumulative1); +// +// /** @var CouponAdapterInterface $stubCouponBaseAdapter */ +// $stubCouponBaseAdapter = $this->generateFakeAdapter($coupons, $cartTotalPrice, $checkoutTotalPrice); +// +// // When +// $sortedCoupons = PhpUnitUtils::callMethod( +// new CouponManager($stubCouponBaseAdapter), +// 'sortCoupons', +// array($coupons) +// ); +// +// // Then +// $expected = $coupons; +// $actual = $sortedCoupons; +// +// $this->assertSame($expected, $actual, 'Array Sorted despite there is only once'); +// } +// +// /** +// * Testing how multiple Coupon behaviour +// * Entering 1 Coupon cumulative +// * +// * @covers Thelia\Coupon\CouponManager::sortCoupons +// */ +// public function testCouponCumulationOneCouponCumulative() +// { +// $cartTotalPrice = 100.00; +// $checkoutTotalPrice = 120.00; +// +// // Given +// /** @var CouponInterface $coupon */ +// $couponCumulative1 = $this->generateValidCoupon(null, null, null, null, null, null, null, null, true); +// +// $coupons = array($couponCumulative1); +// /** @var CouponAdapterInterface $stubCouponBaseAdapter */ +// $stubCouponBaseAdapter = $this->generateFakeAdapter($coupons, $cartTotalPrice, $checkoutTotalPrice); +// +// // When +// $sortedCoupons = PhpUnitUtils::callMethod( +// new CouponManager($stubCouponBaseAdapter), +// 'sortCoupons', +// array($coupons) +// ); +// +// // Then +// $expected = $coupons; +// $actual = $sortedCoupons; +// +// $this->assertSame($expected, $actual, 'Array Sorted despite there is only once'); +// } +// +// /** +// * Testing how multiple Coupon behaviour +// * Entering 1 Coupon cumulative +// * 1 Coupon cumulative +// * +// * @covers Thelia\Coupon\CouponManager::sortCoupons +// */ +// public function testCouponCumulationTwoCouponCumulative() +// { +// $cartTotalPrice = 100.00; +// $checkoutTotalPrice = 120.00; +// +// // Given +// /** @var CouponInterface $coupon */ +// $couponCumulative1 = $this->generateValidCoupon('XMAS1', null, null, null, null, null, null, null, true); +// $couponCumulative2 = $this->generateValidCoupon('XMAS2', null, null, null, null, null, null, null, true); +// +// $coupons = array($couponCumulative1, $couponCumulative2); +// /** @var CouponAdapterInterface $stubCouponBaseAdapter */ +// $stubCouponBaseAdapter = $this->generateFakeAdapter($coupons, $cartTotalPrice, $checkoutTotalPrice); +// +// // When +// $sortedCoupons = PhpUnitUtils::callMethod( +// new CouponManager($stubCouponBaseAdapter), +// 'sortCoupons', +// array($coupons) +// ); +// +// // Then +// $expected = $coupons; +// $actual = $sortedCoupons; +// +// $this->assertSame($expected, $actual, 'Array Sorted despite both Coupon can be accumulated'); +// } +// +// /** +// * Testing how multiple Coupon behaviour +// * Entering 1 Coupon cumulative +// * 1 Coupon non cumulative +// * +// * @covers Thelia\Coupon\CouponManager::sortCoupons +// */ +// public function testCouponCumulationOneCouponCumulativeOneNonCumulative() +// { +// $cartTotalPrice = 100.00; +// $checkoutTotalPrice = 120.00; +// +// // Given +// /** @var CouponInterface $coupon */ +// $couponCumulative1 = $this->generateValidCoupon('XMAS1', null, null, null, null, null, null, null, true); +// $couponCumulative2 = $this->generateValidCoupon('XMAS2', null, null, null, null, null, null, null, false); +// +// $coupons = array($couponCumulative1, $couponCumulative2); +// /** @var CouponAdapterInterface $stubCouponBaseAdapter */ +// $stubCouponBaseAdapter = $this->generateFakeAdapter($coupons, $cartTotalPrice, $checkoutTotalPrice); +// +// // When +// $sortedCoupons = PhpUnitUtils::callMethod( +// new CouponManager($stubCouponBaseAdapter), +// 'sortCoupons', +// array($coupons) +// ); +// +// // Then +// $expected = array($couponCumulative2); +// $actual = $sortedCoupons; +// +// $this->assertSame($expected, $actual, 'Array Sorted despite both Coupon can be accumulated'); +// } +// +// /** +// * Testing how multiple Coupon behaviour +// * Entering 1 Coupon non cumulative +// * 1 Coupon cumulative +// * +// * @covers Thelia\Coupon\CouponManager::sortCoupons +// */ +// public function testCouponCumulationOneCouponNonCumulativeOneCumulative() +// { +// $cartTotalPrice = 100.00; +// $checkoutTotalPrice = 120.00; +// +// // Given +// /** @var CouponInterface $coupon */ +// $couponCumulative1 = $this->generateValidCoupon('XMAS1', null, null, null, null, null, null, null, false); +// $couponCumulative2 = $this->generateValidCoupon('XMAS2', null, null, null, null, null, null, null, true); +// +// $coupons = array($couponCumulative1, $couponCumulative2); +// /** @var CouponAdapterInterface $stubCouponBaseAdapter */ +// $stubCouponBaseAdapter = $this->generateFakeAdapter($coupons, $cartTotalPrice, $checkoutTotalPrice); +// +// // When +// $sortedCoupons = PhpUnitUtils::callMethod( +// new CouponManager($stubCouponBaseAdapter), +// 'sortCoupons', +// array($coupons) +// ); +// +// // Then +// $expected = array($couponCumulative2); +// $actual = $sortedCoupons; +// +// $this->assertSame($expected, $actual, 'Array Sorted despite both Coupon can be accumulated'); +// } +// +// /** +// * Testing how multiple Coupon behaviour +// * Entering 1 Coupon non cumulative +// * 1 Coupon non cumulative +// * +// * @covers Thelia\Coupon\CouponManager::sortCoupons +// */ +// public function testCouponCumulationTwoCouponNonCumulative() +// { +// $cartTotalPrice = 100.00; +// $checkoutTotalPrice = 120.00; +// +// // Given +// /** @var CouponInterface $coupon */ +// $couponCumulative1 = $this->generateValidCoupon('XMAS1', null, null, null, null, null, null, null, false); +// $couponCumulative2 = $this->generateValidCoupon('XMAS2', null, null, null, null, null, null, null, false); +// +// $coupons = array($couponCumulative1, $couponCumulative2); +// /** @var CouponAdapterInterface $stubCouponBaseAdapter */ +// $stubCouponBaseAdapter = $this->generateFakeAdapter($coupons, $cartTotalPrice, $checkoutTotalPrice); +// +// // When +// $sortedCoupons = PhpUnitUtils::callMethod( +// new CouponManager($stubCouponBaseAdapter), +// 'sortCoupons', +// array($coupons) +// ); +// +// // Then +// $expected = array($couponCumulative2); +// $actual = $sortedCoupons; +// +// $this->assertSame($expected, $actual, 'Array Sorted despite both Coupon can be accumulated'); +// } +// +// /** +// * Testing how multiple Coupon behaviour +// * Entering 1 Coupon cumulative expired +// * +// * @covers Thelia\Coupon\CouponManager::sortCoupons +// */ +// public function testCouponCumulationOneCouponCumulativeExpired() +// { +// $cartTotalPrice = 100.00; +// $checkoutTotalPrice = 120.00; +// +// // Given +// /** @var CouponInterface $coupon */ +// $couponCumulative1 = $this->generateValidCoupon('XMAS1', null, null, null, null, null, new \DateTime(), null, true); +// +// $coupons = array($couponCumulative1); +// /** @var CouponAdapterInterface $stubCouponBaseAdapter */ +// $stubCouponBaseAdapter = $this->generateFakeAdapter($coupons, $cartTotalPrice, $checkoutTotalPrice); +// +// // When +// $sortedCoupons = PhpUnitUtils::callMethod( +// new CouponManager($stubCouponBaseAdapter), +// 'sortCoupons', +// array($coupons) +// ); +// +// // Then +// $expected = array(); +// $actual = $sortedCoupons; +// +// $this->assertSame($expected, $actual, 'Coupon expired ignored'); +// } +// +// /** +// * Testing how multiple Coupon behaviour +// * Entering 1 Coupon cumulative expired +// * 1 Coupon cumulative expired +// * +// * @covers Thelia\Coupon\CouponManager::sortCoupons +// */ +// public function testCouponCumulationTwoCouponCumulativeExpired() +// { +// $cartTotalPrice = 100.00; +// $checkoutTotalPrice = 120.00; +// +// // Given +// /** @var CouponInterface $coupon */ +// $couponCumulative1 = $this->generateValidCoupon('XMAS1', null, null, null, null, null, new \DateTime(), null, true); +// $couponCumulative2 = $this->generateValidCoupon('XMAS2', null, null, null, null, null, new \DateTime(), null, true); +// +// $coupons = array($couponCumulative1, $couponCumulative2); +// /** @var CouponAdapterInterface $stubCouponBaseAdapter */ +// $stubCouponBaseAdapter = $this->generateFakeAdapter($coupons, $cartTotalPrice, $checkoutTotalPrice); +// +// // When +// $sortedCoupons = PhpUnitUtils::callMethod( +// new CouponManager($stubCouponBaseAdapter), +// 'sortCoupons', +// array($coupons) +// ); +// +// // Then +// $expected = array(); +// $actual = $sortedCoupons; +// +// $this->assertSame($expected, $actual, 'Coupon expired ignored'); +// } +// +// /** +// * Testing how multiple Coupon behaviour +// * Entering 1 Coupon cumulative expired +// * 1 Coupon cumulative valid +// * +// * @covers Thelia\Coupon\CouponManager::sortCoupons +// */ +// public function testCouponCumulationOneCouponCumulativeExpiredOneNonExpired() +// { +// $cartTotalPrice = 100.00; +// $checkoutTotalPrice = 120.00; +// +// // Given +// /** @var CouponInterface $coupon */ +// $couponCumulative1 = $this->generateValidCoupon('XMAS1', null, null, null, null, null, new \DateTime(), null, true); +// $couponCumulative2 = $this->generateValidCoupon('XMAS2', null, null, null, null, null, null, null, true); +// +// $coupons = array($couponCumulative1, $couponCumulative2); +// /** @var CouponAdapterInterface $stubCouponBaseAdapter */ +// $stubCouponBaseAdapter = $this->generateFakeAdapter($coupons, $cartTotalPrice, $checkoutTotalPrice); +// +// // When +// $sortedCoupons = PhpUnitUtils::callMethod( +// new CouponManager($stubCouponBaseAdapter), +// 'sortCoupons', +// array($coupons) +// ); +// +// // Then +// $expected = array($couponCumulative2); +// $actual = $sortedCoupons; +// +// $this->assertSame($expected, $actual, 'Coupon expired ignored'); +// } +// +// /** +// * Testing how multiple Coupon behaviour +// * Entering 1 Coupon cumulative valid +// * 1 Coupon cumulative expired +// * +// * @covers Thelia\Coupon\CouponManager::sortCoupons +// */ +// public function testCouponCumulationOneCouponCumulativeNonExpiredOneExpired() +// { +// $cartTotalPrice = 100.00; +// $checkoutTotalPrice = 120.00; +// +// // Given +// /** @var CouponInterface $coupon */ +// $couponCumulative1 = $this->generateValidCoupon('XMAS1', null, null, null, null, null, null, null, true); +// $couponCumulative2 = $this->generateValidCoupon('XMAS2', null, null, null, null, null, new \DateTime(), null, true); +// +// $coupons = array($couponCumulative1, $couponCumulative2); +// /** @var CouponAdapterInterface $stubCouponBaseAdapter */ +// $stubCouponBaseAdapter = $this->generateFakeAdapter($coupons, $cartTotalPrice, $checkoutTotalPrice); +// +// // When +// $sortedCoupons = PhpUnitUtils::callMethod( +// new CouponManager($stubCouponBaseAdapter), +// 'sortCoupons', +// array($coupons) +// ); +// +// // Then +// $expected = array($couponCumulative1); +// $actual = $sortedCoupons; +// +// $this->assertSame($expected, $actual, 'Coupon expired ignored'); +// } +// +// /** +// * Testing how multiple Coupon behaviour +// * Entering 1 Coupon cumulative valid +// * 1 Coupon cumulative valid +// * 1 Coupon cumulative valid +// * 1 Coupon cumulative valid +// * +// * @covers Thelia\Coupon\CouponManager::sortCoupons +// */ +// public function testCouponCumulationFourCouponCumulative() +// { +// $cartTotalPrice = 100.00; +// $checkoutTotalPrice = 120.00; +// +// // Given +// /** @var CouponInterface $coupon */ +// $couponCumulative1 = $this->generateValidCoupon('XMAS1', null, null, null, null, null, null, null, true); +// $couponCumulative2 = $this->generateValidCoupon('XMAS2', null, null, null, null, null, null, null, true); +// $couponCumulative3 = $this->generateValidCoupon('XMAS3', null, null, null, null, null, null, null, true); +// $couponCumulative4 = $this->generateValidCoupon('XMAS4', null, null, null, null, null, null, null, true); +// +// $coupons = array($couponCumulative1, $couponCumulative2, $couponCumulative3, $couponCumulative4); +// /** @var CouponAdapterInterface $stubCouponBaseAdapter */ +// $stubCouponBaseAdapter = $this->generateFakeAdapter($coupons, $cartTotalPrice, $checkoutTotalPrice); +// +// // When +// $sortedCoupons = PhpUnitUtils::callMethod( +// new CouponManager($stubCouponBaseAdapter), +// 'sortCoupons', +// array($coupons) +// ); +// +// // Then +// $expected = $coupons; +// $actual = $sortedCoupons; +// +// $this->assertSame($expected, $actual, 'Coupon cumulative ignored'); +// } +// +// /** +// * Testing how multiple Coupon behaviour +// * Entering 1 Coupon cumulative valid +// * 1 Coupon cumulative valid +// * 1 Coupon cumulative valid +// * 1 Coupon non cumulative valid +// * +// * @covers Thelia\Coupon\CouponManager::sortCoupons +// */ +// public function testCouponCumulationThreeCouponCumulativeOneNonCumulative() +// { +// $cartTotalPrice = 100.00; +// $checkoutTotalPrice = 120.00; +// +// // Given +// /** @var CouponInterface $coupon */ +// $couponCumulative1 = $this->generateValidCoupon('XMAS1', null, null, null, null, null, null, null, true); +// $couponCumulative2 = $this->generateValidCoupon('XMAS2', null, null, null, null, null, null, null, true); +// $couponCumulative3 = $this->generateValidCoupon('XMAS3', null, null, null, null, null, null, null, true); +// $couponCumulative4 = $this->generateValidCoupon('XMAS4', null, null, null, null, null, null, null, false); +// +// $coupons = array($couponCumulative1, $couponCumulative2, $couponCumulative3, $couponCumulative4); +// /** @var CouponAdapterInterface $stubCouponBaseAdapter */ +// $stubCouponBaseAdapter = $this->generateFakeAdapter($coupons, $cartTotalPrice, $checkoutTotalPrice); +// +// // When +// $sortedCoupons = PhpUnitUtils::callMethod( +// new CouponManager($stubCouponBaseAdapter), +// 'sortCoupons', +// array($coupons) +// ); +// +// // Then +// $expected = array($couponCumulative4); +// $actual = $sortedCoupons; +// +// $this->assertSame($expected, $actual, 'Coupon cumulative ignored'); +// } +// +// +// /** +// * Generate valid CouponRuleInterfaces +// * +// * @return array Array of CouponRuleInterface +// */ +// public static function generateValidRules() +// { +// $adapter = new CouponBaseAdapter(); +// $rule1 = new AvailableForTotalAmount( +// $adapter, array( +// AvailableForTotalAmount::PARAM1_PRICE => new RuleValidator( +// Operators::SUPERIOR, +// new PriceParam( +// $adapter, 40.00, 'EUR' +// ) +// ) +// ) +// ); +// $rule2 = new AvailableForTotalAmount( +// $adapter, array( +// AvailableForTotalAmount::PARAM1_PRICE => new RuleValidator( +// Operators::INFERIOR, +// new PriceParam( +// $adapter, 400.00, 'EUR' +// ) +// ) +// ) +// ); +// $rules = new CouponRuleCollection(array($rule1, $rule2)); +// +// return $rules; +// } +// +// /** +// * Tears down the fixture, for example, closes a network connection. +// * This method is called after a test is executed. +// */ +// protected function tearDown() +// { +// } +// +// /** +// * Generate a fake Adapter +// * +// * @param array $coupons Coupons +// * @param float $cartTotalPrice Cart total price +// * @param float $checkoutTotalPrice Checkout total price +// * @param float $postagePrice Checkout postage price +// * +// * @return \PHPUnit_Framework_MockObject_MockObject +// */ +// public function generateFakeAdapter(array $coupons, $cartTotalPrice, $checkoutTotalPrice, $postagePrice = 6.00) +// { +// $stubCouponBaseAdapter = $this->getMock( +// 'Thelia\Coupon\CouponBaseAdapter', +// array( +// 'getCurrentCoupons', +// 'getCartTotalPrice', +// 'getCheckoutTotalPrice', +// 'getCheckoutPostagePrice' +// ), +// array() +// ); +// +// $stubCouponBaseAdapter->expects($this->any()) +// ->method('getCurrentCoupons') +// ->will($this->returnValue(($coupons))); +// +// // Return Cart product amount = $cartTotalPrice euros +// $stubCouponBaseAdapter->expects($this->any()) +// ->method('getCartTotalPrice') +// ->will($this->returnValue($cartTotalPrice)); +// +// // Return Checkout amount = $checkoutTotalPrice euros +// $stubCouponBaseAdapter->expects($this->any()) +// ->method('getCheckoutTotalPrice') +// ->will($this->returnValue($checkoutTotalPrice)); +// +// $stubCouponBaseAdapter->expects($this->any()) +// ->method('getCheckoutPostagePrice') +// ->will($this->returnValue($postagePrice)); +// +// return $stubCouponBaseAdapter; +// } +// +// /** +// * Generate valid CouponInterface +// * +// * @param string $code Coupon Code +// * @param string $title Coupon Title +// * @param string $shortDescription Coupon short +// * description +// * @param string $description Coupon description +// * @param float $amount Coupon discount +// * @param bool $isEnabled Is Coupon enabled +// * @param \DateTime $expirationDate Coupon expiration date +// * @param CouponRuleCollection $rules Coupon rules +// * @param bool $isCumulative If is cumulative +// * @param bool $isRemovingPostage If is removing postage +// * @param bool $isAvailableOnSpecialOffers If is available on +// * special offers or not +// * @param int $maxUsage How many time a Coupon +// * can be used +// * +// * @return CouponInterface +// */ +// public static function generateValidCoupon( +// $code = null, +// $title = null, +// $shortDescription = null, +// $description = null, +// $amount = null, +// $isEnabled = null, +// $expirationDate = null, +// $rules = null, +// $isCumulative = null, +// $isRemovingPostage = null, +// $isAvailableOnSpecialOffers = null, +// $maxUsage = null +// ) { +// $adapter = new CouponBaseAdapter(); +// if ($code === null) { +// $code = self::VALID_CODE; +// } +// if ($title === null) { +// $title = self::VALID_TITLE; +// } +// if ($shortDescription === null) { +// $shortDescription = self::VALID_SHORT_DESCRIPTION; +// } +// if ($description === null) { +// $description = self::VALID_DESCRIPTION; +// } +// if ($amount === null) { +// $amount = 10.00; +// } +// if ($isEnabled === null) { +// $isEnabled = true; +// } +// if ($isCumulative === null) { +// $isCumulative = true; +// } +// if ($isRemovingPostage === null) { +// $isRemovingPostage = false; +// } +// if ($isAvailableOnSpecialOffers === null) { +// $isAvailableOnSpecialOffers = true; +// } +// if ($maxUsage === null) { +// $maxUsage = 40; +// } +// +// if ($expirationDate === null) { +// $expirationDate = new \DateTime(); +// $expirationDate->setTimestamp(strtotime("today + 2 months")); +// } +// +// $coupon = new RemoveXAmount($adapter, $code, $title, $shortDescription, $description, $amount, $isCumulative, $isRemovingPostage, $isAvailableOnSpecialOffers, $isEnabled, $maxUsage, $expirationDate); +// +// if ($rules === null) { +// $rules = self::generateValidRules(); +// } +// +// $coupon->setRules($rules); +// +// return $coupon; +// } + +} diff --git a/core/lib/Thelia/Tests/Coupon/CouponRuleCollectionTest.php b/core/lib/Thelia/Tests/Coupon/CouponRuleCollectionTest.php new file mode 100644 index 000000000..803000779 --- /dev/null +++ b/core/lib/Thelia/Tests/Coupon/CouponRuleCollectionTest.php @@ -0,0 +1,86 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Coupon; + +use Thelia\Constraint\Validator\PriceParam; +use Thelia\Constraint\Validator\RuleValidator; +use Thelia\Constraint\Rule\AvailableForTotalAmount; +use Thelia\Constraint\Rule\Operators; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Unit Test CouponRuleCollection Class + * + * @package Coupon + * @author Guillaume MOREL + * + */ +class CouponRuleCollectionTest extends \PHPUnit_Framework_TestCase +{ + public function testSomething() + { + // Stop here and mark this test as incomplete. + $this->markTestIncomplete( + 'This test has not been implemented yet.' + ); + } +// /** +// * +// */ +// public function testRuleSerialisation() +// { +//// $rule1 = new AvailableForTotalAmount( +//// , array( +//// AvailableForTotalAmount::PARAM1_PRICE => new RuleValidator( +//// Operators::SUPERIOR, +//// new PriceParam( +//// , 40.00, 'EUR' +//// ) +//// ) +//// ) +//// ); +//// $rule2 = new AvailableForTotalAmount( +//// , array( +//// AvailableForTotalAmount::PARAM1_PRICE => new RuleValidator( +//// Operators::INFERIOR, +//// new PriceParam( +//// , 400.00, 'EUR' +//// ) +//// ) +//// ) +//// ); +//// $rules = new CouponRuleCollection(array($rule1, $rule2)); +//// +//// $serializedRules = base64_encode(serialize($rules)); +//// $unserializedRules = unserialize(base64_decode($serializedRules)); +//// +//// $expected = $rules; +//// $actual = $unserializedRules; +//// +//// $this->assertEquals($expected, $actual); +// } +} diff --git a/core/lib/Thelia/Tests/Coupon/RuleOrganizerTest.php b/core/lib/Thelia/Tests/Coupon/RuleOrganizerTest.php new file mode 100644 index 000000000..3300cb19b --- /dev/null +++ b/core/lib/Thelia/Tests/Coupon/RuleOrganizerTest.php @@ -0,0 +1,72 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Coupon; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Unit Test RuleOrganizer Class + * + * @package Coupon + * @author Guillaume MOREL + * + */ +class RuleOrganizerTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var RuleOrganizer + */ + protected $object; + + /** + * Sets up the fixture, for example, opens a network connection. + * This method is called before a test is executed. + */ + protected function setUp() + { + $this->object = new RuleOrganizer; + } + + /** + * Tears down the fixture, for example, closes a network connection. + * This method is called after a test is executed. + */ + protected function tearDown() + { + } + + /** + * @covers Thelia\Coupon\RuleOrganizer::organize + * @todo Implement testOrganize(). + */ + public function testOrganize() + { + // Remove the following lines when you implement this test. + $this->markTestIncomplete( + 'This test has not been implemented yet.' + ); + } +} diff --git a/core/lib/Thelia/Tests/Coupon/Type/RemoveXAmountTest.php b/core/lib/Thelia/Tests/Coupon/Type/RemoveXAmountTest.php new file mode 100644 index 000000000..8467852ac --- /dev/null +++ b/core/lib/Thelia/Tests/Coupon/Type/RemoveXAmountTest.php @@ -0,0 +1,384 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Coupon; + +use Thelia\Constraint\Validator\PriceParam; +use Thelia\Constraint\Validator\RuleValidator; +use Thelia\Constraint\Rule\AvailableForTotalAmountManager; +use Thelia\Constraint\Rule\Operators; +use Thelia\Coupon\Type\RemoveXAmountManager; + +//require_once '../CouponManagerTest.php'; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Unit Test RemoveXAmount Class + * + * @package Coupon + * @author Guillaume MOREL + * + */ +class RemoveXAmountTest extends \PHPUnit_Framework_TestCase +{ + public function testSomething() + { + // Stop here and mark this test as incomplete. + $this->markTestIncomplete( + 'This test has not been implemented yet.' + ); + } +// /** +// * Sets up the fixture, for example, opens a network connection. +// * This method is called before a test is executed. +// */ +// protected function setUp() +// { +// +// } +// +// /** +// * Test if a Coupon is well displayed +// * +// * @covers Thelia\Coupon\type\RemoveXAmountManager::getCode +// * @covers Thelia\Coupon\type\RemoveXAmountManager::getTitle +// * @covers Thelia\Coupon\type\RemoveXAmountManager::getShortDescription +// * @covers Thelia\Coupon\type\RemoveXAmountManager::getDescription +// * +// */ +// public function testDisplay() +// { +// $coupon = CouponManagerTest::generateValidCoupon(null, null, null, null, null, null, null, null, true, true); +// +// $expected = CouponManagerTest::VALID_CODE; +// $actual = $coupon->getCode(); +// $this->assertEquals($expected, $actual); +// +// $expected = CouponManagerTest::VALID_TITLE; +// $actual = $coupon->getTitle(); +// $this->assertEquals($expected, $actual); +// +// $expected = CouponManagerTest::VALID_SHORT_DESCRIPTION; +// $actual = $coupon->getShortDescription(); +// $this->assertEquals($expected, $actual); +// +// $expected = CouponManagerTest::VALID_DESCRIPTION; +// $actual = $coupon->getDescription(); +// $this->assertEquals($expected, $actual); +// } +// +// /** +// * Test if a Coupon can be Cumulative +// * +// * @covers Thelia\Coupon\type\RemoveXAmountManager::isCumulative +// * +// */ +// public function testIsCumulative() +// { +// $coupon = CouponManagerTest::generateValidCoupon(null, null, null, null, null, null, null, null, true, true); +// +// $actual = $coupon->isCumulative(); +// $this->assertTrue($actual); +// } +// +// /** +// * Test if a Coupon can be non cumulative +// * +// * @covers Thelia\Coupon\type\RemoveXAmountManager::isCumulative +// * +// */ +// public function testIsNotCumulative() +// { +// $coupon = CouponManagerTest::generateValidCoupon(null, null, null, null, null, null, null, null, false, false); +// +// $actual = $coupon->isCumulative(); +// $this->assertFalse($actual); +// } +// +// +// /** +// * Test if a Coupon can remove postage +// * +// * @covers Thelia\Coupon\type\RemoveXAmountManager::isRemovingPostage +// * +// */ +// public function testIsRemovingPostage() +// { +// $coupon = CouponManagerTest::generateValidCoupon(null, null, null, null, null, null, null, null, true, true); +// +// $actual = $coupon->isRemovingPostage(); +// $this->assertTrue($actual); +// } +// +// /** +// * Test if a Coupon won't remove postage if not set to +// * +// * @covers Thelia\Coupon\type\RemoveXAmountManager::isRemovingPostage +// */ +// public function testIsNotRemovingPostage() +// { +// $coupon = CouponManagerTest::generateValidCoupon(null, null, null, null, null, null, null, null, false, false); +// +// $actual = $coupon->isRemovingPostage(); +// $this->assertFalse($actual); +// } +// +// +// /** +// * Test if a Coupon has the effect expected (discount 10euros) +// * +// * @covers Thelia\Coupon\type\RemoveXAmountManager::getEffect +// */ +// public function testGetEffect() +// { +// $adapter = new CouponBaseAdapter(); +// $coupon = CouponManagerTest::generateValidCoupon(null, null, null, null, null, null, null, null, false, false); +// +// $expected = 10; +// $actual = $coupon->getDiscount(); +// $this->assertEquals($expected, $actual); +// } +// +// /** +// * Test Coupon rule setter +// * +// * @covers Thelia\Coupon\type\RemoveXAmountManager::setRules +// * @covers Thelia\Coupon\type\RemoveXAmountManager::getRules +// */ +// public function testSetRulesValid() +// { +// // Given +// $rule0 = $this->generateValidRuleAvailableForTotalAmountOperatorTo( +// Operators::EQUAL, +// 20.00 +// ); +// $rule1 = $this->generateValidRuleAvailableForTotalAmountOperatorTo( +// Operators::INFERIOR, +// 100.23 +// ); +// $rule2 = $this->generateValidRuleAvailableForTotalAmountOperatorTo( +// Operators::SUPERIOR, +// 421.23 +// ); +// +// $coupon = CouponManagerTest::generateValidCoupon(null, null, null, null, null, null, null, null, false, false); +// +// // When +// $coupon->setRules(new CouponRuleCollection(array($rule0, $rule1, $rule2))); +// +// // Then +// $expected = 3; +// $this->assertCount($expected, $coupon->getRules()->getRules()); +// } +// +// /** +// * Test Coupon rule setter +// * +// * @covers Thelia\Coupon\type\RemoveXAmountManager::setRules +// * @expectedException \Thelia\Exception\InvalidRuleException +// * +// */ +// public function testSetRulesInvalid() +// { +// // Given +// $rule0 = $this->generateValidRuleAvailableForTotalAmountOperatorTo( +// Operators::EQUAL, +// 20.00 +// ); +// $rule1 = $this->generateValidRuleAvailableForTotalAmountOperatorTo( +// Operators::INFERIOR, +// 100.23 +// ); +// $rule2 = $this; +// +// $coupon = CouponManagerTest::generateValidCoupon(null, null, null, null, null, null, null, null, false, false); +// +// // When +// $coupon->setRules(new CouponRuleCollection(array($rule0, $rule1, $rule2))); +// } +// +// /** +// * Test Coupon effect for rule Total Amount < 400 +// * +// * @covers Thelia\Coupon\type\RemoveXAmountManager::getEffect +// * +// */ +// public function testGetEffectIfTotalAmountInferiorTo400Valid() +// { +// // Given +// $adapter = new CouponBaseAdapter(); +// $rule0 = $this->generateValidRuleAvailableForTotalAmountOperatorTo( +// Operators::INFERIOR, +// 400.00 +// ); +// $coupon = CouponManagerTest::generateValidCoupon(null, null, null, null, null, null, null, null, false, false); +// +// // When +// $coupon->setRules(new CouponRuleCollection(array($rule0))); +// +// // Then +// $expected = 10.00; +// $actual = $coupon->getDiscount(); +// $this->assertEquals($expected, $actual); +// } +// +// /** +// * Test Coupon effect for rule Total Amount <= 400 +// * +// * @covers Thelia\Coupon\type\RemoveXAmountManager::getEffect +// * +// */ +// public function testGetEffectIfTotalAmountInferiorOrEqualTo400Valid() +// { +// // Given +// $adapter = new CouponBaseAdapter(); +// $rule0 = $this->generateValidRuleAvailableForTotalAmountOperatorTo( +// Operators::INFERIOR_OR_EQUAL, +// 400.00 +// ); +// $coupon = CouponManagerTest::generateValidCoupon(null, null, null, null, null, null, null, null, false, false); +// +// // When +// $coupon->setRules(new CouponRuleCollection(array($rule0))); +// +// // Then +// $expected = 10.00; +// $actual = $coupon->getDiscount(); +// $this->assertEquals($expected, $actual); +// } +// +// /** +// * Test Coupon effect for rule Total Amount == 400 +// * +// * @covers Thelia\Coupon\type\RemoveXAmountManager::getEffect +// * +// */ +// public function testGetEffectIfTotalAmountEqualTo400Valid() +// { +// // Given +// $adapter = new CouponBaseAdapter(); +// $rule0 = $this->generateValidRuleAvailableForTotalAmountOperatorTo( +// Operators::EQUAL, +// 400.00 +// ); +// $coupon = CouponManagerTest::generateValidCoupon(null, null, null, null, null, null, null, null, false, false); +// +// // When +// $coupon->setRules(new CouponRuleCollection(array($rule0))); +// +// // Then +// $expected = 10.00; +// $actual = $coupon->getDiscount(); +// $this->assertEquals($expected, $actual); +// } +// +// /** +// * Test Coupon effect for rule Total Amount >= 400 +// * +// * @covers Thelia\Coupon\type\RemoveXAmountManager::getEffect +// * +// */ +// public function testGetEffectIfTotalAmountSuperiorOrEqualTo400Valid() +// { +// // Given +// $adapter = new CouponBaseAdapter(); +// $rule0 = $this->generateValidRuleAvailableForTotalAmountOperatorTo( +// Operators::SUPERIOR_OR_EQUAL, +// 400.00 +// ); +// $coupon = CouponManagerTest::generateValidCoupon(null, null, null, null, null, null, null, null, false, false); +// +// // When +// $coupon->setRules(new CouponRuleCollection(array($rule0))); +// +// // Then +// $expected = 10.00; +// $actual = $coupon->getDiscount(); +// $this->assertEquals($expected, $actual); +// } +// +// /** +// * Test Coupon effect for rule Total Amount > 400 +// * +// * @covers Thelia\Coupon\type\RemoveXAmountManager::getEffect +// * +// */ +// public function testGetEffectIfTotalAmountSuperiorTo400Valid() +// { +// // Given +// $adapter = new CouponBaseAdapter(); +// $rule0 = $this->generateValidRuleAvailableForTotalAmountOperatorTo( +// Operators::SUPERIOR, +// 400.00 +// ); +// $coupon = CouponManagerTest::generateValidCoupon(null, null, null, null, null, null, null, null, false, false); +// +// // When +// $coupon->setRules(new CouponRuleCollection(array($rule0))); +// +// // Then +// $expected = 10.00; +// $actual = $coupon->getDiscount(); +// $this->assertEquals($expected, $actual); +// } +// +// +// +// /** +// * Tears down the fixture, for example, closes a network connection. +// * This method is called after a test is executed. +// */ +// protected function tearDown() +// { +// } +// +// /** +// * Generate valid rule AvailableForTotalAmount +// * according to given operator and amount +// * +// * @param string $operator Operators::CONST +// * @param float $amount Amount with 2 decimals +// * +// * @return AvailableForTotalAmount +// */ +// protected function generateValidRuleAvailableForTotalAmountOperatorTo($operator, $amount) +// { +// $adapter = new CouponBaseAdapter(); +// $validators = array( +// AvailableForTotalAmount::PARAM1_PRICE => new RuleValidator( +// $operator, +// new PriceParam( +// $adapter, +// $amount, +// 'EUR' +// ) +// ) +// ); +// +// return new AvailableForTotalAmount($adapter, $validators); +// } + +} diff --git a/core/lib/Thelia/Tests/Coupon/Type/RemoveXPercentForCategoryYTest.php b/core/lib/Thelia/Tests/Coupon/Type/RemoveXPercentForCategoryYTest.php new file mode 100644 index 000000000..ac13d4ea0 --- /dev/null +++ b/core/lib/Thelia/Tests/Coupon/Type/RemoveXPercentForCategoryYTest.php @@ -0,0 +1,70 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Coupon; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Unit Test RemoveXPercentForCategoryY Class + * + * @package Coupon + * @author Guillaume MOREL + * + */ +class RemoveXPercentForCategoryYTest extends \PHPUnit_Framework_TestCase +{ + public function testSomething() + { + // Stop here and mark this test as incomplete. + $this->markTestIncomplete( + 'This test has not been implemented yet.' + ); + } + +// /** +// * Sets up the fixture, for example, opens a network connection. +// * This method is called before a test is executed. +// */ +// protected function setUp() +// { +// } +// +// public function incompleteTest() +// { +// $this->markTestIncomplete( +// 'This test has not been implemented yet.' +// ); +// } +// +// /** +// * Tears down the fixture, for example, closes a network connection. +// * This method is called after a test is executed. +// */ +// protected function tearDown() +// { +// } + +} diff --git a/core/lib/Thelia/Tests/Coupon/Type/RemoveXPercentTest.php b/core/lib/Thelia/Tests/Coupon/Type/RemoveXPercentTest.php new file mode 100644 index 000000000..7fc327df6 --- /dev/null +++ b/core/lib/Thelia/Tests/Coupon/Type/RemoveXPercentTest.php @@ -0,0 +1,458 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Coupon; + +use PHPUnit_Framework_TestCase; +use Thelia\Constraint\Rule\AvailableForTotalAmountManager; +use Thelia\Constraint\Rule\Operators; +use Thelia\Constraint\Validator\PriceParam; +use Thelia\Constraint\Validator\RuleValidator; +use Thelia\Coupon\Type\CouponInterface; +use Thelia\Coupon\Type\RemoveXPercentManager; + +//require_once '../CouponManagerTest.php'; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Unit Test RemoveXPercent Class + * + * @package Coupon + * @author Guillaume MOREL + * + */ +class RemoveXPercentTest extends \PHPUnit_Framework_TestCase +{ + + public function testSomething() + { + // Stop here and mark this test as incomplete. + $this->markTestIncomplete( + 'This test has not been implemented yet.' + ); + } +// /** +// * Sets up the fixture, for example, opens a network connection. +// * This method is called before a test is executed. +// */ +// protected function setUp() +// { +// } +// +// /** +// * Test if a Coupon can be Cumulative +// * +// * @covers Thelia\Coupon\type\RemoveXPercentManager::isCumulative +// * +// */ +// public function testIsCumulative() +// { +// $coupon = $this->generateValidCoupon(null, null, null, null, null, null, null, null, true, true); +// +// $actual = $coupon->isCumulative(); +// $this->assertTrue($actual); +// } +// +// /** +// * Test if a Coupon can be non cumulative +// * +// * @covers Thelia\Coupon\type\RemoveXPercentManager::isCumulative +// * +// */ +// public function testIsNotCumulative() +// { +// $coupon = $this->generateValidCoupon(null, null, null, null, null, null, null, null, false, false); +// +// $actual = $coupon->isCumulative(); +// $this->assertFalse($actual); +// } +// +// +// /** +// * Test if a Coupon can remove postage +// * +// * @covers Thelia\Coupon\type\RemoveXPercentManager::isRemovingPostage +// * +// */ +// public function testIsRemovingPostage() +// { +// $coupon = $this->generateValidCoupon(null, null, null, null, null, null, null, null, true, true); +// +// $actual = $coupon->isRemovingPostage(); +// $this->assertTrue($actual); +// } +// +// /** +// * Test if a Coupon won't remove postage if not set to +// * +// * @covers Thelia\Coupon\type\RemoveXPercentManager::isRemovingPostage +// */ +// public function testIsNotRemovingPostage() +// { +// $coupon = $this->generateValidCoupon(null, null, null, null, null, null, null, null, false, false); +// +// $actual = $coupon->isRemovingPostage(); +// $this->assertFalse($actual); +// } +// +// +// /** +// * Test if a Coupon has the effect expected (discount 10euros) +// * +// * @covers Thelia\Coupon\type\RemoveXPercentManager::getEffect +// */ +// public function testGetEffect() +// { +// $adapter = $this->generateFakeAdapter(245); +// $coupon = $this->generateValidCoupon(null, null, null, null, null, null, null, null, false, false); +// +// $expected = 24.50; +// $actual = $coupon->getDiscount($adapter); +// $this->assertEquals($expected, $actual); +// } +// +// /** +// * Test Coupon rule setter +// * +// * @covers Thelia\Coupon\type\RemoveXPercentManager::setRules +// * @covers Thelia\Coupon\type\RemoveXPercentManager::getRules +// */ +// public function testSetRulesValid() +// { +// // Given +// $rule0 = $this->generateValidRuleAvailableForTotalAmountOperatorTo( +// Operators::EQUAL, +// 20.00 +// ); +// $rule1 = $this->generateValidRuleAvailableForTotalAmountOperatorTo( +// Operators::INFERIOR, +// 100.23 +// ); +// $rule2 = $this->generateValidRuleAvailableForTotalAmountOperatorTo( +// Operators::SUPERIOR, +// 421.23 +// ); +// +// $coupon = $this->generateValidCoupon(null, null, null, null, null, null, null, null, false, false); +// +// // When +// $coupon->setRules(new CouponRuleCollection(array($rule0, $rule1, $rule2))); +// +// // Then +// $expected = 3; +// $this->assertCount($expected, $coupon->getRules()->getRules()); +// } +// +// /** +// * Test Coupon rule setter +// * +// * @covers Thelia\Coupon\type\RemoveXPercentManager::setRules +// * @expectedException \Thelia\Exception\InvalidRuleException +// * +// */ +// public function testSetRulesInvalid() +// { +// // Given +// $rule0 = $this->generateValidRuleAvailableForTotalAmountOperatorTo( +// Operators::EQUAL, +// 20.00 +// ); +// $rule1 = $this->generateValidRuleAvailableForTotalAmountOperatorTo( +// Operators::INFERIOR, +// 100.23 +// ); +// $rule2 = $this; +// +// $coupon = $this->generateValidCoupon(null, null, null, null, null, null, null, null, false, false); +// +// // When +// $coupon->setRules(new CouponRuleCollection(array($rule0, $rule1, $rule2))); +// } +// +// /** +// * Test Coupon effect for rule Total Amount < 400 +// * +// * @covers Thelia\Coupon\type\RemoveXPercentManager::getEffect +// * +// */ +// public function testGetEffectIfTotalAmountInferiorTo400Valid() +// { +// // Given +// $rule0 = $this->generateValidRuleAvailableForTotalAmountOperatorTo( +// Operators::INFERIOR, +// 400.00 +// ); +// $coupon = $this->generateValidCoupon(null, null, null, null, null, null, null, null, false, false); +// +// // When +// $coupon->setRules(new CouponRuleCollection(array($rule0))); +// +// // Then +// $expected = 24.50; +// $actual = $coupon->getDiscount(); +// $this->assertEquals($expected, $actual); +// } +// +// /** +// * Test Coupon effect for rule Total Amount <= 400 +// * +// * @covers Thelia\Coupon\type\RemoveXPercentManager::getEffect +// * +// */ +// public function testGetEffectIfTotalAmountInferiorOrEqualTo400Valid() +// { +// // Given +// $rule0 = $this->generateValidRuleAvailableForTotalAmountOperatorTo( +// Operators::INFERIOR_OR_EQUAL, +// 400.00 +// ); +// $coupon = $this->generateValidCoupon(null, null, null, null, null, null, null, null, false, false); +// +// // When +// $coupon->setRules(new CouponRuleCollection(array($rule0))); +// +// // Then +// $expected = 24.50; +// $actual = $coupon->getDiscount(); +// $this->assertEquals($expected, $actual); +// } +// +// /** +// * Test Coupon effect for rule Total Amount == 400 +// * +// * @covers Thelia\Coupon\type\RemoveXPercentManager::getEffect +// * +// */ +// public function testGetEffectIfTotalAmountEqualTo400Valid() +// { +// // Given +// $rule0 = $this->generateValidRuleAvailableForTotalAmountOperatorTo( +// Operators::EQUAL, +// 400.00 +// ); +// $coupon = $this->generateValidCoupon(null, null, null, null, null, null, null, null, false, false); +// +// // When +// $coupon->setRules(new CouponRuleCollection(array($rule0))); +// +// // Then +// $expected = 24.50; +// $actual = $coupon->getDiscount(); +// $this->assertEquals($expected, $actual); +// } +// +// /** +// * Test Coupon effect for rule Total Amount >= 400 +// * +// * @covers Thelia\Coupon\type\RemoveXPercentManager::getEffect +// * +// */ +// public function testGetEffectIfTotalAmountSuperiorOrEqualTo400Valid() +// { +// // Given +// $rule0 = $this->generateValidRuleAvailableForTotalAmountOperatorTo( +// Operators::SUPERIOR_OR_EQUAL, +// 400.00 +// ); +// $coupon = $this->generateValidCoupon(null, null, null, null, null, null, null, null, false, false); +// +// // When +// $coupon->setRules(new CouponRuleCollection(array($rule0))); +// +// // Then +// $expected = 24.50; +// $actual = $coupon->getDiscount(); +// $this->assertEquals($expected, $actual); +// } +// +// /** +// * Test Coupon effect for rule Total Amount > 400 +// * +// * @covers Thelia\Coupon\type\RemoveXPercentManager::getEffect +// * +// */ +// public function testGetEffectIfTotalAmountSuperiorTo400Valid() +// { +// // Given +// $rule0 = $this->generateValidRuleAvailableForTotalAmountOperatorTo( +// Operators::SUPERIOR, +// 400.00 +// ); +// $coupon = $this->generateValidCoupon(null, null, null, null, null, null, null, null, false, false); +// +// // When +// $coupon->setRules(new CouponRuleCollection(array($rule0))); +// +// // Then +// $expected = 24.50; +// $actual = $coupon->getDiscount(); +// $this->assertEquals($expected, $actual); +// } +// +// /** +// * Generate valid CouponInterface +// * +// * @param string $code Coupon Code +// * @param string $title Coupon Title +// * @param string $shortDescription Coupon short +// * description +// * @param string $description Coupon description +// * @param float $amount Coupon discount +// * @param bool $isEnabled Is Coupon enabled +// * @param \DateTime $expirationDate Coupon expiration date +// * @param CouponRuleCollection $rules Coupon rules +// * @param bool $isCumulative If is cumulative +// * @param bool $isRemovingPostage If is removing postage +// * @param bool $isAvailableOnSpecialOffers If is available on +// * special offers or not +// * @param int $maxUsage How many time a Coupon +// * can be used +// * +// * @return CouponInterface +// */ +// public function generateValidCoupon( +// $code = null, +// $title = null, +// $shortDescription = null, +// $description = null, +// $percent = null, +// $isEnabled = null, +// $expirationDate = null, +// $rules = null, +// $isCumulative = null, +// $isRemovingPostage = null, +// $isAvailableOnSpecialOffers = null, +// $maxUsage = null +// ) { +// $adapter = $this->generateFakeAdapter(245); +// +// if ($code === null) { +// $code = CouponManagerTest::VALID_CODE; +// } +// if ($title === null) { +// $title = CouponManagerTest::VALID_TITLE; +// } +// if ($shortDescription === null) { +// $shortDescription = CouponManagerTest::VALID_SHORT_DESCRIPTION; +// } +// if ($description === null) { +// $description = CouponManagerTest::VALID_DESCRIPTION; +// } +// if ($percent === null) { +// $percent = 10.00; +// } +// if ($isEnabled === null) { +// $isEnabled = true; +// } +// if ($isCumulative === null) { +// $isCumulative = true; +// } +// if ($isRemovingPostage === null) { +// $isRemovingPostage = false; +// } +// if ($isAvailableOnSpecialOffers === null) { +// $isAvailableOnSpecialOffers = true; +// } +// if ($maxUsage === null) { +// $maxUsage = 40; +// } +// +// if ($expirationDate === null) { +// $expirationDate = new \DateTime(); +// $expirationDate->setTimestamp(strtotime("today + 2 months")); +// } +// +// $coupon = new RemoveXPercent($adapter, $code, $title, $shortDescription, $description, $percent, $isCumulative, $isRemovingPostage, $isAvailableOnSpecialOffers, $isEnabled, $maxUsage, $expirationDate); +// +// if ($rules === null) { +// $rules = CouponManagerTest::generateValidRules(); +// } +// +// $coupon->setRules($rules); +// +// return $coupon; +// } +// +// +// /** +// * Generate valid rule AvailableForTotalAmount +// * according to given operator and amount +// * +// * @param string $operator Operators::CONST +// * @param float $amount Amount with 2 decimals +// * +// * @return AvailableForTotalAmount +// */ +// protected function generateValidRuleAvailableForTotalAmountOperatorTo($operator, $amount) +// { +// $adapter = new CouponBaseAdapter(); +// $validators = array( +// AvailableForTotalAmount::PARAM1_PRICE => new RuleValidator( +// $operator, +// new PriceParam( +// $adapter, +// $amount, +// 'EUR' +// ) +// ) +// ); +// +// return new AvailableForTotalAmount($adapter, $validators); +// } +// +// /** +// * Generate a fake Adapter +// * +// * @param float $cartTotalPrice Cart total price +// * +// * @return \PHPUnit_Framework_MockObject_MockObject +// */ +// public function generateFakeAdapter($cartTotalPrice) +// { +// $stubCouponBaseAdapter = $this->getMock( +// 'Thelia\Coupon\CouponBaseAdapter', +// array( +// 'getCartTotalPrice' +// ), +// array() +// ); +// +// $stubCouponBaseAdapter->expects($this->any()) +// ->method('getCartTotalPrice') +// ->will($this->returnValue(($cartTotalPrice))); +// +// return $stubCouponBaseAdapter; +// } +// +// /** +// * Tears down the fixture, for example, closes a network connection. +// * This method is called after a test is executed. +// */ +// protected function tearDown() +// { +// } + +} diff --git a/core/lib/Thelia/Tests/Rewriting/RewritingResolverTest.php b/core/lib/Thelia/Tests/Rewriting/RewritingResolverTest.php index a3ec561d2..6cd4bdf42 100755 --- a/core/lib/Thelia/Tests/Rewriting/RewritingResolverTest.php +++ b/core/lib/Thelia/Tests/Rewriting/RewritingResolverTest.php @@ -61,7 +61,7 @@ class RewritingResolverTest extends \PHPUnit_Framework_TestCase $resolver = new RewritingResolver(); $method = $this->getMethod('getOtherParameters'); - $actual = $method->invoke($resolver); + $method->invoke($resolver); } public function testGetOtherParameters() diff --git a/core/lib/Thelia/Tests/TaxEngine/CalculatorTest.php b/core/lib/Thelia/Tests/TaxEngine/CalculatorTest.php new file mode 100755 index 000000000..fac6ca643 --- /dev/null +++ b/core/lib/Thelia/Tests/TaxEngine/CalculatorTest.php @@ -0,0 +1,169 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Tests\TaxEngine; + +use Propel\Runtime\Collection\ObjectCollection; +use Thelia\Model\Country; +use Thelia\Model\CountryQuery; +use Thelia\Model\Product; +use Thelia\Model\ProductQuery; +use Thelia\Model\Tax; +use Thelia\TaxEngine\Calculator; + +/** + * + * @author Etienne Roudeix + * + */ +class CalculatorTest extends \PHPUnit_Framework_TestCase +{ + protected function getMethod($name) + { + $class = new \ReflectionClass('\Thelia\TaxEngine\Calculator'); + $method = $class->getMethod($name); + $method->setAccessible(true); + + return $method; + } + + protected function getProperty($name) + { + $class = new \ReflectionClass('\Thelia\TaxEngine\Calculator'); + $property = $class->getProperty($name); + $property->setAccessible(true); + + return $property; + } + + /** + * @expectedException \Thelia\Exception\TaxEngineException + * @expectedExceptionCode 501 + */ + public function testLoadEmptyProductException() + { + $calculator = new Calculator(); + $calculator->load(new Product(), CountryQuery::create()->findOne()); + } + + /** + * @expectedException \Thelia\Exception\TaxEngineException + * @expectedExceptionCode 502 + */ + public function testLoadEmptyCountryException() + { + $calculator = new Calculator(); + $calculator->load(ProductQuery::create()->findOne(), new Country()); + } + + public function testLoad() + { + $productQuery = ProductQuery::create()->findOneById(1); + $countryQuery = CountryQuery::create()->findOneById(64); + + $calculator = new Calculator(); + + $taxRuleQuery = $this->getMock('\Thelia\Model\TaxRuleQuery', array('getTaxCalculatorGroupedCollection')); + $taxRuleQuery->expects($this->once()) + ->method('getTaxCalculatorGroupedCollection') + ->with($productQuery, $countryQuery) + ->will($this->returnValue('foo')); + + $rewritingUrlQuery = $this->getProperty('taxRuleQuery'); + $rewritingUrlQuery->setValue($calculator, $taxRuleQuery); + + $calculator->load($productQuery, $countryQuery); + + $this->assertEquals( + $productQuery, + $this->getProperty('product')->getValue($calculator) + ); + $this->assertEquals( + $countryQuery, + $this->getProperty('country')->getValue($calculator) + ); + $this->assertEquals( + 'foo', + $this->getProperty('taxRulesGroupedCollection')->getValue($calculator) + ); + } + + /** + * @expectedException \Thelia\Exception\TaxEngineException + * @expectedExceptionCode 503 + */ + public function testGetTaxAmountBadTaxRulesCollection() + { + $calculator = new Calculator(); + $calculator->getTaxAmount(500); + } + + /** + * @expectedException \Thelia\Exception\TaxEngineException + * @expectedExceptionCode 601 + */ + public function testGetTaxAmountBadAmount() + { + $taxRulesGroupedCollection = new ObjectCollection(); + + $calculator = new Calculator(); + + $rewritingUrlQuery = $this->getProperty('taxRulesGroupedCollection'); + $rewritingUrlQuery->setValue($calculator, $taxRulesGroupedCollection); + + $calculator->getTaxAmount('foo'); + } + + public function testGetTaxAmountAndGetTaxedPrice() + { + $taxRulesGroupedCollection = new ObjectCollection(); + $taxRulesGroupedCollection->setModel('\Thelia\Model\Tax'); + + $tax = new Tax(); + $tax->setVirtualColumn('taxRateSum', 10); + + $taxRulesGroupedCollection->append($tax); + + $tax = new Tax(); + $tax->setVirtualColumn('taxRateSum', 8); + + $taxRulesGroupedCollection->append($tax); + + $calculator = new Calculator(); + + $rewritingUrlQuery = $this->getProperty('taxRulesGroupedCollection'); + $rewritingUrlQuery->setValue($calculator, $taxRulesGroupedCollection); + + $taxAmount = $calculator->getTaxAmount(500); + $taxedPrice = $calculator->getTaxedPrice(500); + + /* + * expect : + * tax 1 = 500*0.10 = 50 // amout with tax 1 : 550 + * tax 2 = 550*0.08 = 44 // amout with tax 2 : 594 + * total tax amount = 94 + */ + $this->assertEquals(94, $taxAmount); + $this->assertEquals(594, $taxedPrice); + } +} diff --git a/core/lib/Thelia/Tools/I18n.php b/core/lib/Thelia/Tools/I18n.php new file mode 100644 index 000000000..4467bebcd --- /dev/null +++ b/core/lib/Thelia/Tools/I18n.php @@ -0,0 +1,57 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Tools; + +use Thelia\Model\Lang; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Helper for translations + * + * @package I18n + * @author Guillaume MOREL + * + */ +class I18n +{ + /** + * Create a \DateTime from a date picker form input + * The date format is the same as the one from the current User Session + * Ex : $lang = $session->getLang() + * + * @param Lang $lang Object containing date format + * @param string $date String to convert + * + * @return \DateTime + */ + public function getDateTimeFromForm(Lang $lang, $date) + { + $currentDateFormat = $lang->getDateFormat(); + + return \DateTime::createFromFormat($currentDateFormat, $date); + } +} \ No newline at end of file diff --git a/core/lib/Thelia/Tools/PhpUnitUtils.php b/core/lib/Thelia/Tools/PhpUnitUtils.php new file mode 100644 index 000000000..89bd3b148 --- /dev/null +++ b/core/lib/Thelia/Tools/PhpUnitUtils.php @@ -0,0 +1,55 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Tools; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/19/13 + * Time: 3:24 PM + * + * Helper for Unit Testing + * + * @package Coupon + * @author Guillaume MOREL + * + */ +class PhpUnitUtils +{ + /** + * Allow to call a protected methods + * + * @param Object $obj Class name + namespace + * @param string $name Method name + * @param array $args Method arguments + * + * @return mixed protected method result + */ + public static function callMethod($obj, $name, array $args) + { + $class = new \ReflectionClass(get_class($obj)); + $method = $class->getMethod($name); + $method->setAccessible(true); + return $method->invokeArgs($obj, $args); + } +} \ No newline at end of file diff --git a/core/lib/Thelia/Tools/Rest/ResponseRest.php b/core/lib/Thelia/Tools/Rest/ResponseRest.php new file mode 100644 index 000000000..8618d460f --- /dev/null +++ b/core/lib/Thelia/Tools/Rest/ResponseRest.php @@ -0,0 +1,83 @@ +format = $format; + $serializer = $this->getSerializer(); + + if (isset($data)) { + $this->setContent($serializer->serialize($data, $this->format)); + } + + $this->headers->set('Content-Type', 'application/' . $this->format); + } + + /** + * Set Content to be serialized in the response, array or object + * + * @param array $data array or object to be serialized + * + * @return $this + */ + public function setRestContent($data) + { + $serializer = $this->getSerializer(); + + if (isset($data)) { + $this->setContent($serializer->serialize($data, $this->format)); + } + + return $this; + } + + /** + * Get Serializer + * + * @return Serializer + */ + protected function getSerializer() + { + $encoders = array(new XmlEncoder(), new JsonEncoder()); + $normalizers = array(new GetSetMethodNormalizer()); + + return new Serializer($normalizers, $encoders); + } + +} diff --git a/core/lib/Thelia/Tools/URL.php b/core/lib/Thelia/Tools/URL.php index 161175bbf..ffb81992d 100755 --- a/core/lib/Thelia/Tools/URL.php +++ b/core/lib/Thelia/Tools/URL.php @@ -121,6 +121,11 @@ class URL $base_url = $this->getBaseUrl(); + // TODO fix this ugly patch + if(strpos($path, "index_dev.php")) { + $path = str_replace('index_dev.php', '', $path); + } + // If only a path is requested, be sure to remove the script name (index.php or index_dev.php), if any. if ($path_only == self::PATH_TO_FILE) { // As the base_url always ends with '/', if we don't find / at the end, we have a script. @@ -189,6 +194,14 @@ class URL { if(ConfigQuery::isRewritingEnable()) { $this->retriever->loadViewUrl($view, $viewLocale, $viewId); + } else { + $allParametersWithoutView = array(); + $allParametersWithoutView['locale'] = $viewLocale; + if(null !== $viewId) { + $allParametersWithoutView[$view . '_id'] = $viewId; + } + $this->retriever->rewrittenUrl = null; + $this->retriever->url = URL::getInstance()->viewUrl($view, $allParametersWithoutView); } return $this->retriever; @@ -220,6 +233,14 @@ class URL } $this->retriever->loadSpecificUrl($view, $viewLocale, $viewId, $allOtherParameters); + } else { + $allParametersWithoutView = $viewOtherParameters; + $allParametersWithoutView['locale'] = $viewLocale; + if(null !== $viewId) { + $allParametersWithoutView[$view . '_id'] = $viewId; + } + $this->retriever->rewrittenUrl = null; + $this->retriever->url = URL::getInstance()->viewUrl($view, $allParametersWithoutView); } return $this->retriever; diff --git a/install/faker.php b/install/faker.php index f1e7691d7..04495a15e 100755 --- a/install/faker.php +++ b/install/faker.php @@ -1,4 +1,11 @@ boot(); $faker = Faker\Factory::create(); -$con = \Propel\Runtime\Propel::getConnection(Thelia\Model\Map\ProductTableMap::DATABASE_NAME); +$con = \Propel\Runtime\Propel::getConnection( + Thelia\Model\Map\ProductTableMap::DATABASE_NAME +); $con->beginTransaction(); $currency = \Thelia\Model\CurrencyQuery::create()->filterByCode('EUR')->findOne(); @@ -358,6 +368,8 @@ try { } } + generateCouponFixtures($thelia); + $con->commit(); } catch (Exception $e) { echo "error : ".$e->getMessage()."\n"; @@ -371,6 +383,7 @@ function createProduct($faker, $category, $position, &$productIdList) $product->addCategory($category); $product->setVisible(rand(1, 10)>7 ? 0 : 1); $product->setPosition($position); + $product->setTaxRuleId(1); setI18n($faker, $product); $product->save(); @@ -398,7 +411,7 @@ function createCategory($faker, $parent, $position, &$categoryIdList, $contentId //add random associated content $alreadyPicked = array(); - for($i=1; $isetDescription($locale . ' : ' . $description); } } +/** + * Generate Coupon fixtures + */ +function generateCouponFixtures($thelia) +{ + $container = $thelia->getContainer(); + $adapter = $container->get('thelia.adapter'); + // Coupons + $coupon1 = new Thelia\Model\Coupon(); + $coupon1->setCode('XMAS'); + $coupon1->setType('thelia.coupon.type.remove_x_amount'); + $coupon1->setTitle('Christmas coupon'); + $coupon1->setShortDescription('Coupon for Christmas removing 10€ if your total checkout is more than 40€'); + $coupon1->setDescription('Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras at luctus tellus. Integer turpis mauris, aliquet vitae risus tristique, pellentesque vestibulum urna. Vestibulum sodales laoreet lectus dictum suscipit. Praesent vulputate, sem id varius condimentum, quam magna tempor elit, quis venenatis ligula nulla eget libero. Cras egestas euismod tellus, id pharetra leo suscipit quis. Donec lacinia ac lacus et ultricies. Nunc in porttitor neque. Proin at quam congue, consectetur orci sed, congue nulla. Nulla eleifend nunc ligula, nec pharetra elit tempus quis. Vivamus vel mauris sed est dictum blandit. Maecenas blandit dapibus velit ut sollicitudin. In in euismod mauris, consequat viverra magna. Cras velit velit, sollicitudin commodo tortor gravida, tempus varius nulla. + +Donec rhoncus leo mauris, id porttitor ante luctus tempus. Curabitur quis augue feugiat, ullamcorper mauris ac, interdum mi. Quisque aliquam lorem vitae felis lobortis, id interdum turpis mattis. Vestibulum diam massa, ornare congue blandit quis, facilisis at nisl. In tortor metus, venenatis non arcu nec, sollicitudin ornare nisl. Nunc erat risus, varius nec urna at, iaculis lacinia elit. Aenean ut felis tempus, tincidunt odio non, sagittis nisl. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Donec vitae hendrerit elit. Nunc sit amet gravida risus, euismod lobortis massa. Nam a erat mauris. Nam a malesuada lorem. Nulla id accumsan dolor, sed rhoncus tellus. Quisque dictum felis sed leo auctor, at volutpat lectus viverra. Morbi rutrum, est ac aliquam imperdiet, nibh sem sagittis justo, ac mattis magna lacus eu nulla. + +Duis interdum lectus nulla, nec pellentesque sapien condimentum at. Suspendisse potenti. Sed eu purus tellus. Nunc quis rhoncus metus. Fusce vitae tellus enim. Interdum et malesuada fames ac ante ipsum primis in faucibus. Etiam tempor porttitor erat vitae iaculis. Sed est elit, consequat non ornare vitae, vehicula eget lectus. Etiam consequat sapien mauris, eget consectetur magna imperdiet eget. Nunc sollicitudin luctus velit, in commodo nulla adipiscing fermentum. Fusce nisi sapien, posuere vitae metus sit amet, facilisis sollicitudin dui. Fusce ultricies auctor enim sit amet iaculis. Morbi at vestibulum enim, eget adipiscing eros. + +Praesent ligula lorem, faucibus ut metus quis, fermentum iaculis erat. Pellentesque elit erat, lacinia sed semper ac, sagittis vel elit. Nam eu convallis est. Curabitur rhoncus odio vitae consectetur pellentesque. Nam vitae arcu nec ante scelerisque dignissim vel nec neque. Suspendisse augue nulla, mollis eget dui et, tempor facilisis erat. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi ac diam ipsum. Donec convallis dui ultricies velit auctor, non lobortis nulla ultrices. Morbi vitae dignissim ante, sit amet lobortis tortor. Nunc dapibus condimentum augue, in molestie neque congue non. + +Sed facilisis pellentesque nisl, eu tincidunt erat scelerisque a. Nullam malesuada tortor vel erat volutpat tincidunt. In vehicula diam est, a convallis eros scelerisque ut. Donec aliquet venenatis iaculis. Ut a arcu gravida, placerat dui eu, iaculis nisl. Quisque adipiscing orci sit amet dui dignissim lacinia. Sed vulputate lorem non dolor adipiscing ornare. Morbi ornare id nisl id aliquam. Ut fringilla elit ante, nec lacinia enim fermentum sit amet. Aenean rutrum lorem eu convallis pharetra. Cras malesuada varius metus, vitae gravida velit. Nam a varius ipsum, ac commodo dolor. Phasellus nec elementum elit. Etiam vel adipiscing leo.'); + $coupon1->setAmount(10.00); + $coupon1->setIsUsed(1); + $coupon1->setIsEnabled(1); + $date = new \DateTime(); + $coupon1->setExpirationDate($date->setTimestamp(strtotime("today + 2 months"))); + + $rule1 = new AvailableForTotalAmountManager($adapter); + $operators = array( + AvailableForTotalAmountManager::INPUT1 => Operators::SUPERIOR, + AvailableForTotalAmountManager::INPUT2 => Operators::EQUAL + ); + $values = array( + AvailableForTotalAmountManager::INPUT1 => 40.00, + AvailableForTotalAmountManager::INPUT2 => 'EUR' + ); + $rule1->setValidatorsFromForm($operators, $values); + + $rule2 = new AvailableForTotalAmountManager($adapter); + $operators = array( + AvailableForTotalAmountManager::INPUT1 => Operators::INFERIOR, + AvailableForTotalAmountManager::INPUT2 => Operators::EQUAL + ); + $values = array( + AvailableForTotalAmountManager::INPUT1 => 400.00, + AvailableForTotalAmountManager::INPUT2 => 'EUR' + ); + $rule2->setValidatorsFromForm($operators, $values); + + $rules = new CouponRuleCollection(); + $rules->add($rule1); + $rules->add($rule2); + + /** @var ConstraintFactory $constraintFactory */ + $constraintFactory = $container->get('thelia.constraint.factory'); + + $serializedRules = $constraintFactory->serializeCouponRuleCollection($rules); + $coupon1->setSerializedRules($serializedRules); + + $coupon1->setIsCumulative(1); + $coupon1->setIsRemovingPostage(0); + $coupon1->save(); + + + + + + + + + // Coupons + $coupon2 = new Thelia\Model\Coupon(); + $coupon2->setCode('SPRINGBREAK'); + $coupon2->setType('thelia.coupon.type.remove_x_percent'); + $coupon2->setTitle('Springbreak coupon'); + $coupon2->setShortDescription('Coupon for Springbreak removing 10% if you have more than 4 articles in your cart'); + $coupon2->setDescription('Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras at luctus tellus. Integer turpis mauris, aliquet vitae risus tristique, pellentesque vestibulum urna. Vestibulum sodales laoreet lectus dictum suscipit. Praesent vulputate, sem id varius condimentum, quam magna tempor elit, quis venenatis ligula nulla eget libero. Cras egestas euismod tellus, id pharetra leo suscipit quis. Donec lacinia ac lacus et ultricies. Nunc in porttitor neque. Proin at quam congue, consectetur orci sed, congue nulla. Nulla eleifend nunc ligula, nec pharetra elit tempus quis. Vivamus vel mauris sed est dictum blandit. Maecenas blandit dapibus velit ut sollicitudin. In in euismod mauris, consequat viverra magna. Cras velit velit, sollicitudin commodo tortor gravida, tempus varius nulla. + +Donec rhoncus leo mauris, id porttitor ante luctus tempus. Curabitur quis augue feugiat, ullamcorper mauris ac, interdum mi. Quisque aliquam lorem vitae felis lobortis, id interdum turpis mattis. Vestibulum diam massa, ornare congue blandit quis, facilisis at nisl. In tortor metus, venenatis non arcu nec, sollicitudin ornare nisl. Nunc erat risus, varius nec urna at, iaculis lacinia elit. Aenean ut felis tempus, tincidunt odio non, sagittis nisl. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Donec vitae hendrerit elit. Nunc sit amet gravida risus, euismod lobortis massa. Nam a erat mauris. Nam a malesuada lorem. Nulla id accumsan dolor, sed rhoncus tellus. Quisque dictum felis sed leo auctor, at volutpat lectus viverra. Morbi rutrum, est ac aliquam imperdiet, nibh sem sagittis justo, ac mattis magna lacus eu nulla. + +Duis interdum lectus nulla, nec pellentesque sapien condimentum at. Suspendisse potenti. Sed eu purus tellus. Nunc quis rhoncus metus. Fusce vitae tellus enim. Interdum et malesuada fames ac ante ipsum primis in faucibus. Etiam tempor porttitor erat vitae iaculis. Sed est elit, consequat non ornare vitae, vehicula eget lectus. Etiam consequat sapien mauris, eget consectetur magna imperdiet eget. Nunc sollicitudin luctus velit, in commodo nulla adipiscing fermentum. Fusce nisi sapien, posuere vitae metus sit amet, facilisis sollicitudin dui. Fusce ultricies auctor enim sit amet iaculis. Morbi at vestibulum enim, eget adipiscing eros. + +Praesent ligula lorem, faucibus ut metus quis, fermentum iaculis erat. Pellentesque elit erat, lacinia sed semper ac, sagittis vel elit. Nam eu convallis est. Curabitur rhoncus odio vitae consectetur pellentesque. Nam vitae arcu nec ante scelerisque dignissim vel nec neque. Suspendisse augue nulla, mollis eget dui et, tempor facilisis erat. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi ac diam ipsum. Donec convallis dui ultricies velit auctor, non lobortis nulla ultrices. Morbi vitae dignissim ante, sit amet lobortis tortor. Nunc dapibus condimentum augue, in molestie neque congue non. + +Sed facilisis pellentesque nisl, eu tincidunt erat scelerisque a. Nullam malesuada tortor vel erat volutpat tincidunt. In vehicula diam est, a convallis eros scelerisque ut. Donec aliquet venenatis iaculis. Ut a arcu gravida, placerat dui eu, iaculis nisl. Quisque adipiscing orci sit amet dui dignissim lacinia. Sed vulputate lorem non dolor adipiscing ornare. Morbi ornare id nisl id aliquam. Ut fringilla elit ante, nec lacinia enim fermentum sit amet. Aenean rutrum lorem eu convallis pharetra. Cras malesuada varius metus, vitae gravida velit. Nam a varius ipsum, ac commodo dolor. Phasellus nec elementum elit. Etiam vel adipiscing leo.'); + $coupon2->setAmount(10.00); + $coupon2->setIsUsed(1); + $coupon2->setIsEnabled(1); + $date = new \DateTime(); + $coupon2->setExpirationDate($date->setTimestamp(strtotime("today + 2 months"))); + + $rule1 = new AvailableForXArticlesManager($adapter); + $operators = array( + AvailableForXArticlesManager::INPUT1 => Operators::SUPERIOR, + ); + $values = array( + AvailableForXArticlesManager::INPUT1 => 4, + ); + $rule1->setValidatorsFromForm($operators, $values); + + $rules = new CouponRuleCollection(); + $rules->add($rule1); + + /** @var ConstraintFactory $constraintFactory */ + $constraintFactory = $container->get('thelia.constraint.factory'); + + $serializedRules = $constraintFactory->serializeCouponRuleCollection($rules); + $coupon2->setSerializedRules($serializedRules); + + $coupon2->setIsCumulative(0); + $coupon2->setIsRemovingPostage(1); + $coupon2->save(); +} diff --git a/install/insert.sql b/install/insert.sql index a2e5868e4..917966893 100755 --- a/install/insert.sql +++ b/install/insert.sql @@ -17,7 +17,9 @@ INSERT INTO `config` (`name`, `value`, `secured`, `hidden`, `created_at`, `updat ('currency_rate_update_url', 'http://www.ecb.int/stats/eurofxref/eurofxref-daily.xml', 0, 0, NOW(), NOW()), ('page_not_found_view', '404.html', 0, 0, NOW(), NOW()); -INSERT INTO `module` (`code`, `type`, `activate`, `position`, `created_at`, `updated_at`) VALUES ('test', '1', '1', '1', NOW(), NOW()); + +INSERT INTO `module` (`id`, `code`, `type`, `activate`, `position`, `full_namespace`, `created_at`, `updated_at`) VALUES +(1, 'DebugBar', 1, 1, 1, 'DebugBar\\DebugBar', NOW(), NOW()); INSERT INTO `customer_title`(`id`, `by_default`, `position`, `created_at`, `updated_at`) VALUES (1, 1, 1, NOW(), NOW()), @@ -1107,3 +1109,25 @@ INSERT INTO `country_i18n` (`id`, `locale`, `title`, `description`, `chapo`, `po (268, 'en_UK', 'USA - Alabama', '', '', ''), (268, 'es_ES', 'USA - Alabama', '', '', ''), (268, 'fr_FR', 'USA - Alabama', '', '', ''); + +INSERT INTO `tax` (`id`, `rate`, `created_at`, `updated_at`) + VALUES + (1, '19.6', NOW(), NOW()); + +INSERT INTO `tax_i18n` (`id`, `locale`, `title`) + VALUES + (1, 'fr_FR', 'TVA française à 19.6%'), + (1, 'en_UK', 'french 19.6% tax'); + +INSERT INTO `tax_rule` (`id`, `created_at`, `updated_at`) + VALUES + (1, NOW(), NOW()); + +INSERT INTO `tax_rule_i18n` (`id`, `locale`, `title`) + VALUES + (1, 'fr_FR', 'TVA française à 19.6%'), + (1, 'en_UK', 'french 19.6% tax'); + +INSERT INTO `tax_rule_country` (`tax_rule_id`, `country_id`, `tax_id`, `position`, `created_at`, `updated_at`) + VALUES + (1, 64, 1, 1, NOW(), NOW()); \ No newline at end of file diff --git a/install/thelia.sql b/install/thelia.sql index 879f323b9..d38d45379 100755 --- a/install/thelia.sql +++ b/install/thelia.sql @@ -126,9 +126,6 @@ DROP TABLE IF EXISTS `tax_rule`; CREATE TABLE `tax_rule` ( `id` INTEGER NOT NULL AUTO_INCREMENT, - `code` VARCHAR(45), - `title` VARCHAR(255), - `description` TEXT, `created_at` DATETIME, `updated_at` DATETIME, PRIMARY KEY (`id`) @@ -142,14 +139,13 @@ DROP TABLE IF EXISTS `tax_rule_country`; CREATE TABLE `tax_rule_country` ( - `id` INTEGER NOT NULL, - `tax_rule_id` INTEGER, - `country_id` INTEGER, - `tax_id` INTEGER, - `none` TINYINT, + `tax_rule_id` INTEGER NOT NULL, + `country_id` INTEGER NOT NULL, + `tax_id` INTEGER NOT NULL, + `position` INTEGER NOT NULL, `created_at` DATETIME, `updated_at` DATETIME, - PRIMARY KEY (`id`), + PRIMARY KEY (`tax_rule_id`,`country_id`,`tax_id`), INDEX `idx_tax_rule_country_tax_id` (`tax_id`), INDEX `idx_tax_rule_country_tax_rule_id` (`tax_rule_id`), INDEX `idx_tax_rule_country_country_id` (`country_id`), @@ -157,7 +153,7 @@ CREATE TABLE `tax_rule_country` FOREIGN KEY (`tax_id`) REFERENCES `tax` (`id`) ON UPDATE RESTRICT - ON DELETE SET NULL, + ON DELETE CASCADE, CONSTRAINT `fk_tax_rule_country_tax_rule_id` FOREIGN KEY (`tax_rule_id`) REFERENCES `tax_rule` (`id`) @@ -803,6 +799,7 @@ CREATE TABLE `module` `type` TINYINT NOT NULL, `activate` TINYINT, `position` INTEGER, + `full_namespace` VARCHAR(255), `created_at` DATETIME, `updated_at` DATETIME, PRIMARY KEY (`id`), @@ -1573,6 +1570,8 @@ CREATE TABLE `tax_rule_i18n` ( `id` INTEGER NOT NULL, `locale` VARCHAR(5) DEFAULT 'en_US' NOT NULL, + `title` VARCHAR(255), + `description` TEXT, PRIMARY KEY (`id`,`locale`), CONSTRAINT `tax_rule_i18n_FK_1` FOREIGN KEY (`id`) diff --git a/local/config/schema.xml b/local/config/schema.xml index a9d7badc4..39f649650 100755 --- a/local/config/schema.xml +++ b/local/config/schema.xml @@ -1,4 +1,4 @@ - + @@ -96,19 +96,19 @@
- - + + +
- - - - - - + + + + + @@ -605,6 +605,7 @@ + diff --git a/local/modules/Colissimo/Colissimo.php b/local/modules/Colissimo/Colissimo.php new file mode 100644 index 000000000..4d24cc059 --- /dev/null +++ b/local/modules/Colissimo/Colissimo.php @@ -0,0 +1,83 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Colissimo; + +use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\HttpFoundation\Request; +use Thelia\Module\BaseModule; +use Thelia\Module\DeliveryModuleInterface; + +class Colissimo extends BaseModule implements DeliveryModuleInterface +{ + protected $request; + protected $dispatcher; + + public function setRequest(Request $request) + { + $this->request = $request; + } + + public function getRequest() + { + return $this->request; + } + + public function setDispatcher(EventDispatcherInterface $dispatcher) + { + $this->dispatcher = $dispatcher; + } + + public function getDispatcher() + { + return $this->dispatcher; + } + + /** + * + * calculate and return delivery price + * + * @param null $country + * @return mixed + */ + public function calculate($country = null) + { + // TODO: Implement calculate() method. + return 2; + } + + /** + * YOU HAVE TO IMPLEMENT HERE ABSTRACT METHODD FROM BaseModule Class + * Like install and destroy + */ + public function install() + { + // TODO: Implement install() method. + } + + public function destroy() + { + // TODO: Implement destroy() method. + } + +} diff --git a/local/modules/Colissimo/Config/config.xml b/local/modules/Colissimo/Config/config.xml new file mode 100644 index 000000000..2430f5027 --- /dev/null +++ b/local/modules/Colissimo/Config/config.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/templates/default/i18n/en.php b/local/modules/Colissimo/Config/plugin.xml old mode 100755 new mode 100644 similarity index 100% rename from templates/default/i18n/en.php rename to local/modules/Colissimo/Config/plugin.xml diff --git a/local/modules/Colissimo/Config/schema.xml b/local/modules/Colissimo/Config/schema.xml new file mode 100644 index 000000000..a4e2315b0 --- /dev/null +++ b/local/modules/Colissimo/Config/schema.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/local/modules/DebugBar/Config/config.xml b/local/modules/DebugBar/Config/config.xml new file mode 100644 index 000000000..6713c8ce6 --- /dev/null +++ b/local/modules/DebugBar/Config/config.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + %kernel.debug% + + + + + + + + + + + diff --git a/local/modules/DebugBar/Config/plugin.xml b/local/modules/DebugBar/Config/plugin.xml new file mode 100644 index 000000000..e69de29bb diff --git a/local/modules/DebugBar/Config/schema.xml b/local/modules/DebugBar/Config/schema.xml new file mode 100644 index 000000000..86ccca913 --- /dev/null +++ b/local/modules/DebugBar/Config/schema.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/local/modules/DebugBar/DataCollector/PropelCollector.php b/local/modules/DebugBar/DataCollector/PropelCollector.php new file mode 100644 index 000000000..881b1b64a --- /dev/null +++ b/local/modules/DebugBar/DataCollector/PropelCollector.php @@ -0,0 +1,236 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace DebugBar\DataCollector; +use Propel\Runtime\Propel; +use Psr\Log\LoggerInterface; + + +/** + * Class PropelCollector + * @package DebugBar\DataCollector + * @author Manuel Raynaud + */ +class PropelCollector extends DataCollector implements Renderable, LoggerInterface +{ + + protected $statements = array(); + + protected $accumulatedTime = 0; + + protected $peakMemory = 0; + + public function __construct() + { + $serviceContainer = Propel::getServiceContainer(); + $serviceContainer->setLogger('defaultLogger', $this); + + $con = Propel::getConnection(\Thelia\Model\Map\ProductTableMap::DATABASE_NAME); + $con->setLogMethods(array( + 'exec', + 'query', + 'execute', // these first three are the default + 'beginTransaction', + 'commit', + 'rollBack', + )); + } + + /** + * Called by the DebugBar when data needs to be collected + * + * @return array Collected data + */ + function collect() + { + return array( + 'nb_statements' => count($this->statements), + 'nb_failed_statements' => 0, + 'accumulated_duration' => '10', + 'accumulated_duration_str' => $this->formatDuration(1), + 'peak_memory_usage' => $this->peakMemory, + 'peak_memory_usage_str' => $this->formatBytes($this->peakMemory), + 'statements' => $this->statements + ); + } + + /** + * Returns the unique name of the collector + * + * @return string + */ + public function getName() + { + return 'propel'; + } + + /** + * Returns a hash where keys are control names and their values + * an array of options as defined in {@see DebugBar\JavascriptRenderer::addControl()} + * + * @return array + */ + public function getWidgets() + { + return array( + "propel" => array( + "widget" => "PhpDebugBar.Widgets.SQLQueriesWidget", + "map" => "propel", + "default" => "[]" + ), + "propel:badge" => array( + "map" => "propel.nb_statements", + "default" => 0 + ) + ); + } + + /** + * Logs with an arbitrary level. + * + * @param mixed $level + * @param string $message + * @param array $context + * @return null + */ + public function log($level, $message, array $context = array()) + { + $this->statements[] = array( + 'sql' => $message, + 'is_success' => true, + 'duration' => 0, + 'duration_str' => $this->formatDuration(1), + 'memory' => 1, + 'memory_str' => $this->formatBytes(1) + ); + } + + /** + * System is unusable. + * + * @param string $message + * @param array $context + * @return null + */ + public function emergency($message, array $context = array()) + { + $this->log(null, $message, $context); + } + + /** + * Action must be taken immediately. + * + * Example: Entire website down, database unavailable, etc. This should + * trigger the SMS alerts and wake you up. + * + * @param string $message + * @param array $context + * @return null + */ + public function alert($message, array $context = array()) + { + $this->log(null, $message, $context); + } + + /** + * Critical conditions. + * + * Example: Application component unavailable, unexpected exception. + * + * @param string $message + * @param array $context + * @return null + */ + public function critical($message, array $context = array()) + { + $this->log(null, $message, $context); + } + + /** + * Runtime errors that do not require immediate action but should typically + * be logged and monitored. + * + * @param string $message + * @param array $context + * @return null + */ + public function error($message, array $context = array()) + { + $this->log(null, $message, $context); + } + + /** + * Exceptional occurrences that are not errors. + * + * Example: Use of deprecated APIs, poor use of an API, undesirable things + * that are not necessarily wrong. + * + * @param string $message + * @param array $context + * @return null + */ + public function warning($message, array $context = array()) + { + $this->log(null, $message, $context); + } + + /** + * Normal but significant events. + * + * @param string $message + * @param array $context + * @return null + */ + public function notice($message, array $context = array()) + { + $this->log(null, $message, $context); + } + + /** + * Interesting events. + * + * Example: User logs in, SQL logs. + * + * @param string $message + * @param array $context + * @return null + */ + public function info($message, array $context = array()) + { + $this->log(null, $message, $context); + } + + /** + * Detailed debug information. + * + * @param string $message + * @param array $context + * @return null + */ + public function debug($message, array $context = array()) + { + $this->log(null, $message, $context); + } + + +} \ No newline at end of file diff --git a/core/lib/Thelia/Form/CategoryDeletionForm.php b/local/modules/DebugBar/DebugBar.php old mode 100755 new mode 100644 similarity index 81% rename from core/lib/Thelia/Form/CategoryDeletionForm.php rename to local/modules/DebugBar/DebugBar.php index 47c130fdd..7dde5fa8d --- a/core/lib/Thelia/Form/CategoryDeletionForm.php +++ b/local/modules/DebugBar/DebugBar.php @@ -20,25 +20,25 @@ /* along with this program. If not, see . */ /* */ /*************************************************************************************/ -namespace Thelia\Form; -use Symfony\Component\Validator\Constraints\NotBlank; +namespace DebugBar; -class CategoryDeletionForm extends BaseForm +use Thelia\Module\BaseModule; + +class DebugBar extends BaseModule { - protected function buildForm() + /** + * YOU HAVE TO IMPLEMENT HERE ABSTRACT METHODD FROM BaseModule Class + * Like install and destroy + */ + + public function install() { - $this->formBuilder - ->add("category_id", "integer", array( - "constraints" => array( - new NotBlank() - ) - )) - ; + // TODO: Implement install() method. } - public function getName() + public function destroy() { - return "thelia_category_deletion"; + // TODO: Implement destroy() method. } } diff --git a/local/modules/DebugBar/Listeners/DebugBarListeners.php b/local/modules/DebugBar/Listeners/DebugBarListeners.php new file mode 100644 index 000000000..7d0981d5d --- /dev/null +++ b/local/modules/DebugBar/Listeners/DebugBarListeners.php @@ -0,0 +1,72 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace DebugBar\Listeners; +use DebugBar\DataCollector\PropelCollector; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Component\HttpKernel\KernelEvents; +use Thelia\Action\BaseAction; +use Thelia\Core\Event\TheliaEvents; + + +/** + * Class DebugBarListeners + * @package DebugBar\Listeners + * @author Manuel Raynaud + */ +class DebugBarListeners extends BaseAction implements EventSubscriberInterface { + + public function initDebugBar() + { + $debugBar = $this->container->get("debugBar"); + + $debugBar->addCollector(new PropelCollector()); + } + + /** + * Returns an array of event names this subscriber wants to listen 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( + TheliaEvents::BOOT => array("initDebugBar", 128) + ); + } +} \ No newline at end of file diff --git a/local/modules/DebugBar/Smarty/Plugin/DebugBar.php b/local/modules/DebugBar/Smarty/Plugin/DebugBar.php new file mode 100644 index 000000000..9a333b1d6 --- /dev/null +++ b/local/modules/DebugBar/Smarty/Plugin/DebugBar.php @@ -0,0 +1,82 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace DebugBar\Smarty\Plugin; +use Thelia\Core\Template\Smarty\AbstractSmartyPlugin; +use Thelia\Core\Template\Smarty\an; +use Thelia\Core\Template\Smarty\SmartyPluginDescriptor; +use DebugBar\DebugBar as BaseDebugBar; + +/** + * Class DebugBar + * @author Manuel Raynaud + */ +class DebugBar extends AbstractSmartyPlugin +{ + protected $debugBar; + protected $debugMode; + + public function __construct(BaseDebugBar $debugbar, $debugMode) + { + $this->debugBar = $debugbar; + $this->debugMode = $debugMode; + } + + public function render($params, \Smarty_Internal_Template $template) + { + $render = ""; + if ($this->debugMode) { + $render = $this->debugBar->getJavascriptRenderer()->render(); + } + + return $render; + } + + public function renderHead($params, \Smarty_Internal_Template $template) + { + $render = ""; + if ($this->debugMode) { + $javascriptRenderer = $this->debugBar->getJavascriptRenderer(); + $assets = $javascriptRenderer->getAsseticCollection(); + + $cssCollection = $assets[0]; + $jsCollection = $assets[1]; + + $render .= sprintf('', $cssCollection->dump()); + $render .= sprintf('', $jsCollection->dump()); + } + + return $render; + } + + /** + * @return an array of SmartyPluginDescriptor + */ + public function getPluginDescriptors() + { + return array( + new SmartyPluginDescriptor("function", "debugbar_renderHead", $this, "renderHead"), + new SmartyPluginDescriptor("function", "debugbar_render", $this, "render") + ); + } +} \ No newline at end of file diff --git a/reset_install.bat b/reset_install.bat new file mode 100644 index 000000000..d117e525b --- /dev/null +++ b/reset_install.bat @@ -0,0 +1,35 @@ +echo off +REM @author Guillaume MOREL +REM v0.1 + +echo [WARN] This script will reset this Thelia2 install + +if exist local\config\database.yml ( + echo [INFO] Downloading vendors + composer install --prefer-dist + + cd local\config\ + + echo [INFO] Building Models file + ..\..\bin\propel build -v --output-dir=../../core/lib/ + + echo [INFO] Building SQL CREATE file + ..\..\bin\propel sql:build -v --output-dir=../../install/ + + + echo [INFO] Reloaded Thelia2 database + cd ..\.. + del install\sqldb.map + php Thelia thelia:dev:reloadDB + + echo [INFO] Installing fixtures + php install\faker.php + + echo [INFO] Adding admin + php Thelia thelia:create-admin + + echo [SUCCESS] Reset done +) +) else ( + echo [FAILED] Please add your database informations in local\config\database.yml and start this script again. +) \ No newline at end of file diff --git a/reset_install.sh b/reset_install.sh index 99a73573c..399156b67 100755 --- a/reset_install.sh +++ b/reset_install.sh @@ -1,34 +1,35 @@ #!/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" -if [ ! -f local/config/database.yml ]; then - echo "[FAILED] Please add your database informations in local/config/database.yml and start this script again." -else - echo -e "\n\e[01;34m[INFO] Downloading vendors\e[00m\n" - composer install --prefer-dist +echo -e "\n\e[01;34m[INFO] Clearing caches\e[00m\n" +php Thelia cache:clear - cd local/config/ +echo -e "\n\e[01;34m[INFO] Downloading vendors\e[00m\n" +composer install --prefer-dist - echo -e "\n\e[01;34m[INFO] Building Models file\e[00m\n" - ../../bin/propel build -v --output-dir=../../core/lib/ +cd local/config/ - 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] Building Models file\e[00m\n" +../../bin/propel build -v --output-dir=../../core/lib/ +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 +echo -e "\n\e[01;34m[INFO] Installing fixtures\e[00m\n" +php install/faker.php - echo -e "\n\e[01;34m[INFO] Adding admin\e[00m\n" - php Thelia thelia:create-admin +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 \ No newline at end of file +echo -e "\n\e[01;34m[INFO] Clearing caches\e[00m\n" +php Thelia cache:clear + +echo -e "\n\e[00;32m[SUCCESS] Reset done\e[00m\n" \ No newline at end of file diff --git a/templates/admin/default/admin-layout.tpl b/templates/admin/default/admin-layout.tpl index f968bb6df..6a6a529ab 100644 --- a/templates/admin/default/admin-layout.tpl +++ b/templates/admin/default/admin-layout.tpl @@ -18,11 +18,13 @@ {* -- Bootstrap CSS section --------------------------------------------- *} {block name="before-bootstrap-css"}{/block} - + {stylesheets file='assets/less/*' filters='less,cssembed'} {/stylesheets} + {debugbar_renderHead} + {block name="after-bootstrap-css"}{/block} {* -- Admin CSS section ------------------------------------------------- *} @@ -47,15 +49,15 @@
- +
{intl l='Version %ver' ver="{$THELIA_VERSION}"}
- {module_include location='inside_topbar'} - -
+ {module_include location='inside_topbar'} + +
- +
@@ -82,7 +84,7 @@ {module_include location='before_top_menu'}
'; + while (dowCnt < this.weekStart + 7) { + html += ''; + } + html += ''; + this.picker.find('.datepicker-days thead').append(html); + }, + + fillMonths: function(){ + var html = ''; + var i = 0 + while (i < 12) { + html += ''+DPGlobal.dates.monthsShort[i++]+''; + } + this.picker.find('.datepicker-months td').append(html); + }, + + fill: function() { + var d = new Date(this.viewDate), + year = d.getFullYear(), + month = d.getMonth(), + currentDate = this.date.valueOf(); + this.picker.find('.datepicker-days th:eq(1)') + .text(DPGlobal.dates.months[month]+' '+year); + var prevMonth = new Date(year, month-1, 28,0,0,0,0), + day = DPGlobal.getDaysInMonth(prevMonth.getFullYear(), prevMonth.getMonth()); + prevMonth.setDate(day); + prevMonth.setDate(day - (prevMonth.getDay() - this.weekStart + 7)%7); + var nextMonth = new Date(prevMonth); + nextMonth.setDate(nextMonth.getDate() + 42); + nextMonth = nextMonth.valueOf(); + var html = []; + var clsName, + prevY, + prevM; + while(prevMonth.valueOf() < nextMonth) { + if (prevMonth.getDay() === this.weekStart) { + html.push(''); + } + clsName = this.onRender(prevMonth); + prevY = prevMonth.getFullYear(); + prevM = prevMonth.getMonth(); + if ((prevM < month && prevY === year) || prevY < year) { + clsName += ' old'; + } else if ((prevM > month && prevY === year) || prevY > year) { + clsName += ' new'; + } + if (prevMonth.valueOf() === currentDate) { + clsName += ' active'; + } + html.push(''); + if (prevMonth.getDay() === this.weekEnd) { + html.push(''); + } + prevMonth.setDate(prevMonth.getDate()+1); + } + this.picker.find('.datepicker-days tbody').empty().append(html.join('')); + var currentYear = this.date.getFullYear(); + + var months = this.picker.find('.datepicker-months') + .find('th:eq(1)') + .text(year) + .end() + .find('span').removeClass('active'); + if (currentYear === year) { + months.eq(this.date.getMonth()).addClass('active'); + } + + html = ''; + year = parseInt(year/10, 10) * 10; + var yearCont = this.picker.find('.datepicker-years') + .find('th:eq(1)') + .text(year + '-' + (year + 9)) + .end() + .find('td'); + year -= 1; + for (var i = -1; i < 11; i++) { + html += ''+year+''; + year += 1; + } + yearCont.html(html); + }, + + click: function(e) { + e.stopPropagation(); + e.preventDefault(); + var target = $(e.target).closest('span, td, th'); + if (target.length === 1) { + switch(target[0].nodeName.toLowerCase()) { + case 'th': + switch(target[0].className) { + case 'switch': + this.showMode(1); + break; + case 'prev': + case 'next': + this.viewDate['set'+DPGlobal.modes[this.viewMode].navFnc].call( + this.viewDate, + this.viewDate['get'+DPGlobal.modes[this.viewMode].navFnc].call(this.viewDate) + + DPGlobal.modes[this.viewMode].navStep * (target[0].className === 'prev' ? -1 : 1) + ); + this.fill(); + this.set(); + break; + } + break; + case 'span': + if (target.is('.month')) { + var month = target.parent().find('span').index(target); + this.viewDate.setMonth(month); + } else { + var year = parseInt(target.text(), 10)||0; + this.viewDate.setFullYear(year); + } + if (this.viewMode !== 0) { + this.date = new Date(this.viewDate); + this.element.trigger({ + type: 'changeDate', + date: this.date, + viewMode: DPGlobal.modes[this.viewMode].clsName + }); + } + this.showMode(-1); + this.fill(); + this.set(); + break; + case 'td': + if (target.is('.day') && !target.is('.disabled')){ + var day = parseInt(target.text(), 10)||1; + var month = this.viewDate.getMonth(); + if (target.is('.old')) { + month -= 1; + } else if (target.is('.new')) { + month += 1; + } + var year = this.viewDate.getFullYear(); + this.date = new Date(year, month, day,0,0,0,0); + this.viewDate = new Date(year, month, Math.min(28, day),0,0,0,0); + this.fill(); + this.set(); + this.element.trigger({ + type: 'changeDate', + date: this.date, + viewMode: DPGlobal.modes[this.viewMode].clsName + }); + } + break; + } + } + }, + + mousedown: function(e){ + e.stopPropagation(); + e.preventDefault(); + }, + + showMode: function(dir) { + if (dir) { + this.viewMode = Math.max(this.minViewMode, Math.min(2, this.viewMode + dir)); + } + this.picker.find('>div').hide().filter('.datepicker-'+DPGlobal.modes[this.viewMode].clsName).show(); + } + }; + + $.fn.datepicker = function ( option, val ) { + return this.each(function () { + var $this = $(this), + data = $this.data('datepicker'), + options = typeof option === 'object' && option; + if (!data) { + $this.data('datepicker', (data = new Datepicker(this, $.extend({}, $.fn.datepicker.defaults,options)))); + } + if (typeof option === 'string') data[option](val); + }); + }; + + $.fn.datepicker.defaults = { + onRender: function(date) { + return ''; + } + }; + $.fn.datepicker.Constructor = Datepicker; + + var DPGlobal = { + modes: [ + { + clsName: 'days', + navFnc: 'Month', + navStep: 1 + }, + { + clsName: 'months', + navFnc: 'FullYear', + navStep: 1 + }, + { + clsName: 'years', + navFnc: 'FullYear', + navStep: 10 + }], + dates:{ + days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"], + daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"], + daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"], + months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"], + monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] + }, + isLeapYear: function (year) { + return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0)) + }, + getDaysInMonth: function (year, month) { + return [31, (DPGlobal.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month] + }, + parseFormat: function(format){ + var separator = format.match(/[.\/\-\s].*?/), + parts = format.split(/\W+/); + if (!separator || !parts || parts.length === 0){ + throw new Error("Invalid date format."); + } + return {separator: separator, parts: parts}; + }, + parseDate: function(date, format) { + var parts = date.split(format.separator), + date = new Date(), + val; + date.setHours(0); + date.setMinutes(0); + date.setSeconds(0); + date.setMilliseconds(0); + if (parts.length === format.parts.length) { + var year = date.getFullYear(), day = date.getDate(), month = date.getMonth(); + for (var i=0, cnt = format.parts.length; i < cnt; i++) { + val = parseInt(parts[i], 10)||1; + switch(format.parts[i]) { + case 'dd': + case 'd': + day = val; + date.setDate(val); + break; + case 'mm': + case 'm': + month = val - 1; + date.setMonth(val - 1); + break; + case 'yy': + year = 2000 + val; + date.setFullYear(2000 + val); + break; + case 'yyyy': + year = val; + date.setFullYear(val); + break; + } + } + date = new Date(year, month, day, 0 ,0 ,0); + } + return date; + }, + formatDate: function(date, format){ + var val = { + d: date.getDate(), + m: date.getMonth() + 1, + yy: date.getFullYear().toString().substring(2), + yyyy: date.getFullYear() + }; + val.dd = (val.d < 10 ? '0' : '') + val.d; + val.mm = (val.m < 10 ? '0' : '') + val.m; + var date = []; + for (var i=0, cnt = format.parts.length; i < cnt; i++) { + date.push(val[format.parts[i]]); + } + return date.join(format.separator); + }, + headTemplate: ''+ + ''+ + ''+ + ''+ + ''+ + ''+ + '', + contTemplate: '' + }; + DPGlobal.template = '
'+DPGlobal.dates.daysMin[(dowCnt++)%7]+'
'+prevMonth.getDate() + '
'+ + DPGlobal.headTemplate+ + ''+ + '
'+ + ''+ + '
'+ + ''+ + DPGlobal.headTemplate+ + DPGlobal.contTemplate+ + '
'+ + '
'+ + '
'+ + ''+ + DPGlobal.headTemplate+ + DPGlobal.contTemplate+ + '
'+ + '
'+ + ''; + +}( window.jQuery ); \ No newline at end of file diff --git a/templates/admin/default/assets/img/ajax-loader.gif b/templates/admin/default/assets/img/ajax-loader.gif new file mode 100644 index 000000000..1321dd374 Binary files /dev/null and b/templates/admin/default/assets/img/ajax-loader.gif differ diff --git a/templates/admin/default/assets/js/main.js b/templates/admin/default/assets/js/main.js new file mode 100644 index 000000000..c8fc1a7b7 --- /dev/null +++ b/templates/admin/default/assets/js/main.js @@ -0,0 +1,157 @@ +(function($, window, document){ + + $(function(){ + + // -- Init datepicker -- + if($('.date').length){ + //$('.date').datepicker(); + } + + // -- Init tablesorter -- + /*if($('.tablesorter').length){ + $('.tablesorter').tablesorter({ + widgets: ["filter", "stickyHeaders"], + widthFixed : false, + widgetOptions : { + filter_cssFilter : 'input-medium form-control', + filter_formatter : { + + 2 : function($cell, indx){ + return $.tablesorter.filterFormatter.uiDateCompare( $cell, indx, { + dateFormat: "dd/mm/yy", + changeMonth : true, + changeYear : true, + compare : '=' + }); + }, + + 3 : function($cell, indx){ + return $.tablesorter.filterFormatter.uiRange( $cell, indx, { + value: 1, + min: 1, + max: 50, + delayed: true, + valueToHeader: false, + exactMatch: false + }); + } + } + } + }); + }*/ + + // -- Effect description + if($('[name=effect]').length){ + var $effectSelect = $('[name=effect]'), + $helpBlock = $effectSelect.next('.help-block'); + + $effectSelect.change(function(){ + var description = $(this).find(":selected").data('description'); + $helpBlock.text(description); + }); + } + + // -- Max usage -- + if($('#is-unlimited').length){ + + if($('#is-unlimited').is(':checked')){ + $('#max-usage').hide().attr('value', '-1'); + } + + $('#is-unlimited').change(function(){ + if($('#is-unlimited').is(':checked')){ + $('#max-usage').hide().attr('value', '-1'); + } + else{ + $('#max-usage').show().val('').attr('value', ''); + } + }); + + } + + // -- Confirm Box -- + if($('[data-toggle="confirm"]').length){ + $('[data-toggle="confirm"]').click(function(e){ + + var $link = $(this); + var modal = $(this).data('target'); + + $(modal).modal('show'); + + $(modal).on('shown', function () { + $('[data-confirm]').attr('href', $link.attr('href')); + }); + + if($(modal).is(':hidden')){ + e.preventDefault(); + } + + }); + } + + // -- Mini browser -- + miniBrowser = function (root, url){ + + $.getJSON(url, { + root: root + }) + .done(function(data) { + var resultat = data; + + var breadcrumb = $('
'); + $(resultat.breadcrumb).each(function(k, v){ + breadcrumb.append( + $('').html(' > '), + $('').attr('href', '#').html(v.display).click(function(e){ + e.preventDefault(); + miniBrowser(v.url); + }) + ); + }); + + var categories = $('
'); + $(resultat.categories).each(function(k, v){ + categories.append( + $('

').append( + $('').attr('href', '#').html(v.titre).click(function(e){ + e.preventDefault(); + miniBrowser(v.id); + }) + ) + ); + }); + + var products = $('

'); + $(resultat.products).each(function(k, v){ + products.append( + $('

').append( + $('').attr('href', '#').html(v.titre).click(function(e){ + e.preventDefault(); + + $('#productToAdd_ref').val(v.ref); + $('#productToAdd_titre').val(v.titre); + $('#productToAdd_quantite').val(1); + + manageStock(v.variants, v.promo?v.prix2:v.prix); + + $('#productToAdd_tva').val(v.tva); + + $('.productToAddInformation').show(); + $('#btn_ajout_produit').show(); + }) + ) + ); + }); + + $('#minibrowser-breadcrumb').unbind().empty().append(breadcrumb); + $('#minibrowser-categories').unbind().empty().append(categories); + }) + .fail(function() { + console.log('An error occurred while reading from JSON file'); + }); + + } + + }); + +}(window.jQuery, window, document)); \ No newline at end of file diff --git a/templates/admin/default/assets/js/tablesorter/jquery.metadata.js b/templates/admin/default/assets/js/tablesorter/jquery.metadata.js new file mode 100644 index 000000000..07b10bae8 --- /dev/null +++ b/templates/admin/default/assets/js/tablesorter/jquery.metadata.js @@ -0,0 +1,116 @@ +/* + * Metadata - jQuery plugin for parsing metadata from elements + * + * Copyright (c) 2006 John Resig, Yehuda Katz, Jörn Zaefferer, Paul McLanahan + * + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html + * + */ + +/** + * Sets the type of metadata to use. Metadata is encoded in JSON, and each property + * in the JSON will become a property of the element itself. + * + * There are three supported types of metadata storage: + * + * attr: Inside an attribute. The name parameter indicates *which* attribute. + * + * class: Inside the class attribute, wrapped in curly braces: { } + * + * elem: Inside a child element (e.g. a script tag). The + * name parameter indicates *which* element. + * + * The metadata for an element is loaded the first time the element is accessed via jQuery. + * + * As a result, you can define the metadata type, use $(expr) to load the metadata into the elements + * matched by expr, then redefine the metadata type and run another $(expr) for other elements. + * + * @name $.metadata.setType + * + * @example

This is a p

+ * @before $.metadata.setType("class") + * @after $("#one").metadata().item_id == 1; $("#one").metadata().item_label == "Label" + * @desc Reads metadata from the class attribute + * + * @example

This is a p

+ * @before $.metadata.setType("attr", "data") + * @after $("#one").metadata().item_id == 1; $("#one").metadata().item_label == "Label" + * @desc Reads metadata from a "data" attribute + * + * @example

This is a p

+ * @before $.metadata.setType("elem", "script") + * @after $("#one").metadata().item_id == 1; $("#one").metadata().item_label == "Label" + * @desc Reads metadata from a nested script element + * + * @param String type The encoding type + * @param String name The name of the attribute to be used to get metadata (optional) + * @cat Plugins/Metadata + * @descr Sets the type of encoding to be used when loading metadata for the first time + * @type undefined + * @see metadata() + */ + +(function($) { + +$.extend({ + metadata : { + defaults : { + type: 'class', + name: 'metadata', + cre: /(\{.*\})/, + single: 'metadata' + }, + setType: function( type, name ){ + this.defaults.type = type; + this.defaults.name = name; + }, + get: function( elem, opts ){ + var data, m, e, attr, + settings = $.extend({},this.defaults,opts); + // check for empty string in single property + if ( !settings.single.length ) { settings.single = 'metadata'; } + + data = $.data(elem, settings.single); + // returned cached data if it already exists + if ( data ) { return data; } + + data = "{}"; + + if ( settings.type === "class" ) { + m = settings.cre.exec( elem.className ); + if ( m ) { data = m[1]; } + } else if ( settings.type === "elem" ) { + if( !elem.getElementsByTagName ) { return undefined; } + e = elem.getElementsByTagName(settings.name); + if ( e.length ) { data = $.trim(e[0].innerHTML); } + } else if ( elem.getAttribute !== undefined ) { + attr = elem.getAttribute( settings.name ); + if ( attr ) { data = attr; } + } + + if ( data.indexOf( '{' ) <0 ) { data = "{" + data + "}"; } + + data = eval("(" + data + ")"); + + $.data( elem, settings.single, data ); + return data; + } + } +}); + +/** + * Returns the metadata object for the first member of the jQuery object. + * + * @name metadata + * @descr Returns element's metadata object + * @param Object opts An object contianing settings to override the defaults + * @type jQuery + * @cat Plugins/Metadata + */ +$.fn.metadata = function( opts ){ + return $.metadata.get( this[0], opts ); +}; + +})(jQuery); \ No newline at end of file diff --git a/templates/admin/default/assets/js/tablesorter/jquery.tablesorter.min.js b/templates/admin/default/assets/js/tablesorter/jquery.tablesorter.min.js new file mode 100644 index 000000000..a955fb2c7 --- /dev/null +++ b/templates/admin/default/assets/js/tablesorter/jquery.tablesorter.min.js @@ -0,0 +1,1477 @@ +/*! +* TableSorter 2.10.8 - Client-side table sorting with ease! +* @requires jQuery v1.2.6+ +* +* Copyright (c) 2007 Christian Bach +* Examples and docs at: http://tablesorter.com +* Dual licensed under the MIT and GPL licenses: +* http://www.opensource.org/licenses/mit-license.php +* http://www.gnu.org/licenses/gpl.html +* +* @type jQuery +* @name tablesorter +* @cat Plugins/Tablesorter +* @author Christian Bach/christian.bach@polyester.se +* @contributor Rob Garrison/https://github.com/Mottie/tablesorter +*/ +/*jshint browser:true, jquery:true, unused:false, expr: true */ +/*global console:false, alert:false */ +!(function($) { + "use strict"; + $.extend({ + /*jshint supernew:true */ + tablesorter: new function() { + + var ts = this; + + ts.version = "2.10.8"; + + ts.parsers = []; + ts.widgets = []; + ts.defaults = { + + // *** appearance + theme : 'default', // adds tablesorter-{theme} to the table for styling + widthFixed : false, // adds colgroup to fix widths of columns + showProcessing : false, // show an indeterminate timer icon in the header when the table is sorted or filtered. + + headerTemplate : '{content}',// header layout template (HTML ok); {content} = innerHTML, {icon} = (class from cssIcon) + onRenderTemplate : null, // function(index, template){ return template; }, (template is a string) + onRenderHeader : null, // function(index){}, (nothing to return) + + // *** functionality + cancelSelection : true, // prevent text selection in the header + dateFormat : 'mmddyyyy', // other options: "ddmmyyy" or "yyyymmdd" + sortMultiSortKey : 'shiftKey', // key used to select additional columns + sortResetKey : 'ctrlKey', // key used to remove sorting on a column + usNumberFormat : true, // false for German "1.234.567,89" or French "1 234 567,89" + delayInit : false, // if false, the parsed table contents will not update until the first sort + serverSideSorting: false, // if true, server-side sorting should be performed because client-side sorting will be disabled, but the ui and events will still be used. + + // *** sort options + headers : {}, // set sorter, string, empty, locked order, sortInitialOrder, filter, etc. + ignoreCase : true, // ignore case while sorting + sortForce : null, // column(s) first sorted; always applied + sortList : [], // Initial sort order; applied initially; updated when manually sorted + sortAppend : null, // column(s) sorted last; always applied + + sortInitialOrder : 'asc', // sort direction on first click + sortLocaleCompare: false, // replace equivalent character (accented characters) + sortReset : false, // third click on the header will reset column to default - unsorted + sortRestart : false, // restart sort to "sortInitialOrder" when clicking on previously unsorted columns + + emptyTo : 'bottom', // sort empty cell to bottom, top, none, zero + stringTo : 'max', // sort strings in numerical column as max, min, top, bottom, zero + textExtraction : 'simple', // text extraction method/function - function(node, table, cellIndex){} + textSorter : null, // use custom text sorter - function(a,b){ return a.sort(b); } // basic sort + + // *** widget options + widgets: [], // method to add widgets, e.g. widgets: ['zebra'] + widgetOptions : { + zebra : [ 'even', 'odd' ] // zebra widget alternating row class names + }, + initWidgets : true, // apply widgets on tablesorter initialization + + // *** callbacks + initialized : null, // function(table){}, + + // *** css class names + tableClass : 'tablesorter', + cssAsc : 'tablesorter-headerAsc', + cssChildRow : 'tablesorter-childRow', // previously "expand-child" + cssDesc : 'tablesorter-headerDesc', + cssHeader : 'tablesorter-header', + cssHeaderRow : 'tablesorter-headerRow', + cssIcon : 'tablesorter-icon', // if this class exists, a will be added to the header automatically + cssInfoBlock : 'tablesorter-infoOnly', // don't sort tbody with this class name + cssProcessing : 'tablesorter-processing', // processing icon applied to header during sort/filter + + // *** selectors + selectorHeaders : '> thead th, > thead td', + selectorSort : 'th, td', // jQuery selector of content within selectorHeaders that is clickable to trigger a sort + selectorRemove : '.remove-me', + + // *** advanced + debug : false, + + // *** Internal variables + headerList: [], + empties: {}, + strings: {}, + parsers: [] + + // deprecated; but retained for backwards compatibility + // widgetZebra: { css: ["even", "odd"] } + + }; + + /* debuging utils */ + function log(s) { + if (typeof console !== "undefined" && typeof console.log !== "undefined") { + console.log(s); + } else { + alert(s); + } + } + + function benchmark(s, d) { + log(s + " (" + (new Date().getTime() - d.getTime()) + "ms)"); + } + + ts.log = log; + ts.benchmark = benchmark; + + function getElementText(table, node, cellIndex) { + if (!node) { return ""; } + var c = table.config, + t = c.textExtraction, text = ""; + if (t === "simple") { + if (c.supportsTextContent) { + text = node.textContent; // newer browsers support this + } else { + text = $(node).text(); + } + } else { + if (typeof t === "function") { + text = t(node, table, cellIndex); + } else if (typeof t === "object" && t.hasOwnProperty(cellIndex)) { + text = t[cellIndex](node, table, cellIndex); + } else { + text = c.supportsTextContent ? node.textContent : $(node).text(); + } + } + return $.trim(text); + } + + function detectParserForColumn(table, rows, rowIndex, cellIndex) { + var cur, + i = ts.parsers.length, + node = false, + nodeValue = '', + keepLooking = true; + while (nodeValue === '' && keepLooking) { + rowIndex++; + if (rows[rowIndex]) { + node = rows[rowIndex].cells[cellIndex]; + nodeValue = getElementText(table, node, cellIndex); + if (table.config.debug) { + log('Checking if value was empty on row ' + rowIndex + ', column: ' + cellIndex + ': "' + nodeValue + '"'); + } + } else { + keepLooking = false; + } + } + while (--i >= 0) { + cur = ts.parsers[i]; + // ignore the default text parser because it will always be true + if (cur && cur.id !== 'text' && cur.is && cur.is(nodeValue, table, node)) { + return cur; + } + } + // nothing found, return the generic parser (text) + return ts.getParserById('text'); + } + + function buildParserCache(table) { + var c = table.config, + // update table bodies in case we start with an empty table + tb = c.$tbodies = c.$table.children('tbody:not(.' + c.cssInfoBlock + ')'), + rows, list, l, i, h, ch, p, parsersDebug = ""; + if ( tb.length === 0) { + return c.debug ? log('*Empty table!* Not building a parser cache') : ''; + } + rows = tb[0].rows; + if (rows[0]) { + list = []; + l = rows[0].cells.length; + for (i = 0; i < l; i++) { + // tons of thanks to AnthonyM1229 for working out the following selector (issue #74) to make this work in IE8! + // More fixes to this selector to work properly in iOS and jQuery 1.8+ (issue #132 & #174) + h = c.$headers.filter(':not([colspan])'); + h = h.add( c.$headers.filter('[colspan="1"]') ) // ie8 fix + .filter('[data-column="' + i + '"]:last'); + ch = c.headers[i]; + // get column parser + p = ts.getParserById( ts.getData(h, ch, 'sorter') ); + // empty cells behaviour - keeping emptyToBottom for backwards compatibility + c.empties[i] = ts.getData(h, ch, 'empty') || c.emptyTo || (c.emptyToBottom ? 'bottom' : 'top' ); + // text strings behaviour in numerical sorts + c.strings[i] = ts.getData(h, ch, 'string') || c.stringTo || 'max'; + if (!p) { + p = detectParserForColumn(table, rows, -1, i); + } + if (c.debug) { + parsersDebug += "column:" + i + "; parser:" + p.id + "; string:" + c.strings[i] + '; empty: ' + c.empties[i] + "\n"; + } + list.push(p); + } + } + if (c.debug) { + log(parsersDebug); + } + c.parsers = list; + } + + /* utils */ + function buildCache(table) { + var b = table.tBodies, + tc = table.config, + totalRows, + totalCells, + parsers = tc.parsers, + t, v, i, j, k, c, cols, cacheTime, colMax = []; + tc.cache = {}; + // if no parsers found, return - it's an empty table. + if (!parsers) { + return tc.debug ? log('*Empty table!* Not building a cache') : ''; + } + if (tc.debug) { + cacheTime = new Date(); + } + // processing icon + if (tc.showProcessing) { + ts.isProcessing(table, true); + } + for (k = 0; k < b.length; k++) { + tc.cache[k] = { row: [], normalized: [] }; + // ignore tbodies with class name from css.cssInfoBlock + if (!$(b[k]).hasClass(tc.cssInfoBlock)) { + totalRows = (b[k] && b[k].rows.length) || 0; + totalCells = (b[k].rows[0] && b[k].rows[0].cells.length) || 0; + for (i = 0; i < totalRows; ++i) { + /** Add the table data to main data array */ + c = $(b[k].rows[i]); + cols = []; + // if this is a child row, add it to the last row's children and continue to the next row + if (c.hasClass(tc.cssChildRow)) { + tc.cache[k].row[tc.cache[k].row.length - 1] = tc.cache[k].row[tc.cache[k].row.length - 1].add(c); + // go to the next for loop + continue; + } + tc.cache[k].row.push(c); + for (j = 0; j < totalCells; ++j) { + t = getElementText(table, c[0].cells[j], j); + // allow parsing if the string is empty, previously parsing would change it to zero, + // in case the parser needs to extract data from the table cell attributes + v = parsers[j].format(t, table, c[0].cells[j], j); + cols.push(v); + if ((parsers[j].type || '').toLowerCase() === "numeric") { + colMax[j] = Math.max(Math.abs(v) || 0, colMax[j] || 0); // determine column max value (ignore sign) + } + } + cols.push(tc.cache[k].normalized.length); // add position for rowCache + tc.cache[k].normalized.push(cols); + } + tc.cache[k].colMax = colMax; + } + } + if (tc.showProcessing) { + ts.isProcessing(table); // remove processing icon + } + if (tc.debug) { + benchmark("Building cache for " + totalRows + " rows", cacheTime); + } + } + + // init flag (true) used by pager plugin to prevent widget application + function appendToTable(table, init) { + var c = table.config, + b = table.tBodies, + rows = [], + c2 = c.cache, + r, n, totalRows, checkCell, $bk, $tb, + i, j, k, l, pos, appendTime; + if (!c2[0]) { return; } // empty table - fixes #206 + if (c.debug) { + appendTime = new Date(); + } + for (k = 0; k < b.length; k++) { + $bk = $(b[k]); + if ($bk.length && !$bk.hasClass(c.cssInfoBlock)) { + // get tbody + $tb = ts.processTbody(table, $bk, true); + r = c2[k].row; + n = c2[k].normalized; + totalRows = n.length; + checkCell = totalRows ? (n[0].length - 1) : 0; + for (i = 0; i < totalRows; i++) { + pos = n[i][checkCell]; + rows.push(r[pos]); + // removeRows used by the pager plugin + if (!c.appender || !c.removeRows) { + l = r[pos].length; + for (j = 0; j < l; j++) { + $tb.append(r[pos][j]); + } + } + } + // restore tbody + ts.processTbody(table, $tb, false); + } + } + if (c.appender) { + c.appender(table, rows); + } + if (c.debug) { + benchmark("Rebuilt table", appendTime); + } + // apply table widgets + if (!init) { ts.applyWidget(table); } + // trigger sortend + $(table).trigger("sortEnd", table); + } + + // computeTableHeaderCellIndexes from: + // http://www.javascripttoolbox.com/lib/table/examples.php + // http://www.javascripttoolbox.com/temp/table_cellindex.html + function computeThIndexes(t) { + var matrix = [], + lookup = {}, + cols = 0, // determine the number of columns + trs = $(t).find('thead:eq(0), tfoot').children('tr'), // children tr in tfoot - see issue #196 + i, j, k, l, c, cells, rowIndex, cellId, rowSpan, colSpan, firstAvailCol, matrixrow; + for (i = 0; i < trs.length; i++) { + cells = trs[i].cells; + for (j = 0; j < cells.length; j++) { + c = cells[j]; + rowIndex = c.parentNode.rowIndex; + cellId = rowIndex + "-" + c.cellIndex; + rowSpan = c.rowSpan || 1; + colSpan = c.colSpan || 1; + if (typeof(matrix[rowIndex]) === "undefined") { + matrix[rowIndex] = []; + } + // Find first available column in the first row + for (k = 0; k < matrix[rowIndex].length + 1; k++) { + if (typeof(matrix[rowIndex][k]) === "undefined") { + firstAvailCol = k; + break; + } + } + lookup[cellId] = firstAvailCol; + cols = Math.max(firstAvailCol, cols); + // add data-column + $(c).attr({ 'data-column' : firstAvailCol }); // 'data-row' : rowIndex + for (k = rowIndex; k < rowIndex + rowSpan; k++) { + if (typeof(matrix[k]) === "undefined") { + matrix[k] = []; + } + matrixrow = matrix[k]; + for (l = firstAvailCol; l < firstAvailCol + colSpan; l++) { + matrixrow[l] = "x"; + } + } + } + } + t.config.columns = cols; // may not be accurate if # header columns !== # tbody columns + return lookup; + } + + function formatSortingOrder(v) { + // look for "d" in "desc" order; return true + return (/^d/i.test(v) || v === 1); + } + + function buildHeaders(table) { + var header_index = computeThIndexes(table), ch, $t, + h, i, t, lock, time, c = table.config; + c.headerList = []; + c.headerContent = []; + if (c.debug) { + time = new Date(); + } + i = c.cssIcon ? '' : ''; // add icon if cssIcon option exists + c.$headers = $(table).find(c.selectorHeaders).each(function(index) { + $t = $(this); + ch = c.headers[index]; + c.headerContent[index] = this.innerHTML; // save original header content + // set up header template + t = c.headerTemplate.replace(/\{content\}/g, this.innerHTML).replace(/\{icon\}/g, i); + if (c.onRenderTemplate) { + h = c.onRenderTemplate.apply($t, [index, t]); + if (h && typeof h === 'string') { t = h; } // only change t if something is returned + } + this.innerHTML = '
' + t + '
'; // faster than wrapInner + + if (c.onRenderHeader) { c.onRenderHeader.apply($t, [index]); } + + this.column = header_index[this.parentNode.rowIndex + "-" + this.cellIndex]; + this.order = formatSortingOrder( ts.getData($t, ch, 'sortInitialOrder') || c.sortInitialOrder ) ? [1,0,2] : [0,1,2]; + this.count = -1; // set to -1 because clicking on the header automatically adds one + this.lockedOrder = false; + lock = ts.getData($t, ch, 'lockedOrder') || false; + if (typeof lock !== 'undefined' && lock !== false) { + this.order = this.lockedOrder = formatSortingOrder(lock) ? [1,1,1] : [0,0,0]; + } + $t.addClass(c.cssHeader); + // add cell to headerList + c.headerList[index] = this; + // add to parent in case there are multiple rows + $t.parent().addClass(c.cssHeaderRow); + // allow keyboard cursor to focus on element + $t.attr("tabindex", 0); + }); + // enable/disable sorting + updateHeader(table); + if (c.debug) { + benchmark("Built headers:", time); + log(c.$headers); + } + } + + function commonUpdate(table, resort, callback) { + var c = table.config; + // remove rows/elements before update + c.$table.find(c.selectorRemove).remove(); + // rebuild parsers + buildParserCache(table); + // rebuild the cache map + buildCache(table); + checkResort(c.$table, resort, callback); + } + + function updateHeader(table) { + var s, c = table.config; + c.$headers.each(function(index, th){ + s = ts.getData( th, c.headers[index], 'sorter' ) === 'false'; + th.sortDisabled = s; + $(th)[ s ? 'addClass' : 'removeClass' ]('sorter-false'); + }); + } + + function setHeadersCss(table) { + var f, i, j, l, + c = table.config, + list = c.sortList, + css = [c.cssAsc, c.cssDesc], + // find the footer + $t = $(table).find('tfoot tr').children().removeClass(css.join(' ')); + // remove all header information + c.$headers.removeClass(css.join(' ')); + l = list.length; + for (i = 0; i < l; i++) { + // direction = 2 means reset! + if (list[i][1] !== 2) { + // multicolumn sorting updating - choose the :last in case there are nested columns + f = c.$headers.not('.sorter-false').filter('[data-column="' + list[i][0] + '"]' + (l === 1 ? ':last' : '') ); + if (f.length) { + for (j = 0; j < f.length; j++) { + if (!f[j].sortDisabled) { + f.eq(j).addClass(css[list[i][1]]); + // add sorted class to footer, if it exists + if ($t.length) { + $t.filter('[data-column="' + list[i][0] + '"]').eq(j).addClass(css[list[i][1]]); + } + } + } + } + } + } + } + + // automatically add col group, and column sizes if set + function fixColumnWidth(table) { + if (table.config.widthFixed && $(table).find('colgroup').length === 0) { + var colgroup = $(''), + overallWidth = $(table).width(); + $(table.tBodies[0]).find("tr:first").children("td").each(function() { + colgroup.append($('').css('width', parseInt(($(this).width()/overallWidth)*1000, 10)/10 + '%')); + }); + $(table).prepend(colgroup); + } + } + + function updateHeaderSortCount(table, list) { + var s, t, o, c = table.config, + sl = list || c.sortList; + c.sortList = []; + $.each(sl, function(i,v){ + // ensure all sortList values are numeric - fixes #127 + s = [ parseInt(v[0], 10), parseInt(v[1], 10) ]; + // make sure header exists + o = c.headerList[s[0]]; + if (o) { // prevents error if sorton array is wrong + c.sortList.push(s); + t = $.inArray(s[1], o.order); // fixes issue #167 + o.count = t >= 0 ? t : s[1] % (c.sortReset ? 3 : 2); + } + }); + } + + function getCachedSortType(parsers, i) { + return (parsers && parsers[i]) ? parsers[i].type || '' : ''; + } + + function initSort(table, cell, e){ + var a, i, j, o, s, + c = table.config, + k = !e[c.sortMultiSortKey], + $this = $(table); + // Only call sortStart if sorting is enabled + $this.trigger("sortStart", table); + // get current column sort order + cell.count = e[c.sortResetKey] ? 2 : (cell.count + 1) % (c.sortReset ? 3 : 2); + // reset all sorts on non-current column - issue #30 + if (c.sortRestart) { + i = cell; + c.$headers.each(function() { + // only reset counts on columns that weren't just clicked on and if not included in a multisort + if (this !== i && (k || !$(this).is('.' + c.cssDesc + ',.' + c.cssAsc))) { + this.count = -1; + } + }); + } + // get current column index + i = cell.column; + // user only wants to sort on one column + if (k) { + // flush the sort list + c.sortList = []; + if (c.sortForce !== null) { + a = c.sortForce; + for (j = 0; j < a.length; j++) { + if (a[j][0] !== i) { + c.sortList.push(a[j]); + } + } + } + // add column to sort list + o = cell.order[cell.count]; + if (o < 2) { + c.sortList.push([i, o]); + // add other columns if header spans across multiple + if (cell.colSpan > 1) { + for (j = 1; j < cell.colSpan; j++) { + c.sortList.push([i + j, o]); + } + } + } + // multi column sorting + } else { + // get rid of the sortAppend before adding more - fixes issue #115 + if (c.sortAppend && c.sortList.length > 1) { + if (ts.isValueInArray(c.sortAppend[0][0], c.sortList)) { + c.sortList.pop(); + } + } + // the user has clicked on an already sorted column + if (ts.isValueInArray(i, c.sortList)) { + // reverse the sorting direction for all tables + for (j = 0; j < c.sortList.length; j++) { + s = c.sortList[j]; + o = c.headerList[s[0]]; + if (s[0] === i) { + s[1] = o.order[o.count]; + if (s[1] === 2) { + c.sortList.splice(j,1); + o.count = -1; + } + } + } + } else { + // add column to sort list array + o = cell.order[cell.count]; + if (o < 2) { + c.sortList.push([i, o]); + // add other columns if header spans across multiple + if (cell.colSpan > 1) { + for (j = 1; j < cell.colSpan; j++) { + c.sortList.push([i + j, o]); + } + } + } + } + } + if (c.sortAppend !== null) { + a = c.sortAppend; + for (j = 0; j < a.length; j++) { + if (a[j][0] !== i) { + c.sortList.push(a[j]); + } + } + } + // sortBegin event triggered immediately before the sort + $this.trigger("sortBegin", table); + // setTimeout needed so the processing icon shows up + setTimeout(function(){ + // set css for headers + setHeadersCss(table); + multisort(table); + appendToTable(table); + }, 1); + } + + // sort multiple columns + function multisort(table) { /*jshint loopfunc:true */ + var dir = 0, tc = table.config, + sortList = tc.sortList, l = sortList.length, bl = table.tBodies.length, + sortTime, i, k, c, colMax, cache, lc, s, order, orgOrderCol; + if (tc.serverSideSorting || !tc.cache[0]) { // empty table - fixes #206 + return; + } + if (tc.debug) { sortTime = new Date(); } + for (k = 0; k < bl; k++) { + colMax = tc.cache[k].colMax; + cache = tc.cache[k].normalized; + lc = cache.length; + orgOrderCol = (cache && cache[0]) ? cache[0].length - 1 : 0; + cache.sort(function(a, b) { + // cache is undefined here in IE, so don't use it! + for (i = 0; i < l; i++) { + c = sortList[i][0]; + order = sortList[i][1]; + // fallback to natural sort since it is more robust + s = /n/i.test(getCachedSortType(tc.parsers, c)) ? "Numeric" : "Text"; + s += order === 0 ? "" : "Desc"; + if (/Numeric/.test(s) && tc.strings[c]) { + // sort strings in numerical columns + if (typeof (tc.string[tc.strings[c]]) === 'boolean') { + dir = (order === 0 ? 1 : -1) * (tc.string[tc.strings[c]] ? -1 : 1); + } else { + dir = (tc.strings[c]) ? tc.string[tc.strings[c]] || 0 : 0; + } + } + var sort = $.tablesorter["sort" + s](table, a[c], b[c], c, colMax[c], dir); + if (sort) { return sort; } + } + return a[orgOrderCol] - b[orgOrderCol]; + }); + } + if (tc.debug) { benchmark("Sorting on " + sortList.toString() + " and dir " + order + " time", sortTime); } + } + + function resortComplete($table, callback){ + $table.trigger('updateComplete'); + if (typeof callback === "function") { + callback($table[0]); + } + } + + function checkResort($table, flag, callback) { + // don't try to resort if the table is still processing + // this will catch spamming of the updateCell method + if (flag !== false && !$table[0].isProcessing) { + $table.trigger("sorton", [$table[0].config.sortList, function(){ + resortComplete($table, callback); + }]); + } else { + resortComplete($table, callback); + } + } + + function bindEvents(table){ + var c = table.config, + $this = c.$table, + j, downTime; + // apply event handling to headers + c.$headers + // http://stackoverflow.com/questions/5312849/jquery-find-self; + .find(c.selectorSort).add( c.$headers.filter(c.selectorSort) ) + .unbind('mousedown.tablesorter mouseup.tablesorter sort.tablesorter keypress.tablesorter') + .bind('mousedown.tablesorter mouseup.tablesorter sort.tablesorter keypress.tablesorter', function(e, external) { + // only recognize left clicks or enter + if ( ((e.which || e.button) !== 1 && !/sort|keypress/.test(e.type)) || (e.type === 'keypress' && e.which !== 13) ) { + return false; + } + // ignore long clicks (prevents resizable widget from initializing a sort) + if (e.type === 'mouseup' && external !== true && (new Date().getTime() - downTime > 250)) { return false; } + // set timer on mousedown + if (e.type === 'mousedown') { + downTime = new Date().getTime(); + return e.target.tagName === "INPUT" ? '' : !c.cancelSelection; + } + if (c.delayInit && !c.cache) { buildCache(table); } + // jQuery v1.2.6 doesn't have closest() + var $cell = /TH|TD/.test(this.tagName) ? $(this) : $(this).parents('th, td').filter(':first'), cell = $cell[0]; + if (!cell.sortDisabled) { + initSort(table, cell, e); + } + }); + if (c.cancelSelection) { + // cancel selection + c.$headers + .attr('unselectable', 'on') + .bind('selectstart', false) + .css({ + 'user-select': 'none', + 'MozUserSelect': 'none' // not needed for jQuery 1.8+ + }); + } + // apply easy methods that trigger bound events + $this + .unbind('sortReset update updateRows updateCell updateAll addRows sorton appendCache applyWidgetId applyWidgets refreshWidgets destroy mouseup mouseleave '.split(' ').join('.tablesorter ')) + .bind("sortReset.tablesorter", function(e){ + e.stopPropagation(); + c.sortList = []; + setHeadersCss(table); + multisort(table); + appendToTable(table); + }) + .bind("updateAll.tablesorter", function(e, resort, callback){ + e.stopPropagation(); + ts.refreshWidgets(table, true, true); + ts.restoreHeaders(table); + buildHeaders(table); + bindEvents(table); + commonUpdate(table, resort, callback); + }) + .bind("update.tablesorter updateRows.tablesorter", function(e, resort, callback) { + e.stopPropagation(); + // update sorting (if enabled/disabled) + updateHeader(table); + commonUpdate(table, resort, callback); + }) + .bind("updateCell.tablesorter", function(e, cell, resort, callback) { + e.stopPropagation(); + $this.find(c.selectorRemove).remove(); + // get position from the dom + var l, row, icell, + $tb = $this.find('tbody'), + // update cache - format: function(s, table, cell, cellIndex) + // no closest in jQuery v1.2.6 - tbdy = $tb.index( $(cell).closest('tbody') ),$row = $(cell).closest('tr'); + tbdy = $tb.index( $(cell).parents('tbody').filter(':first') ), + $row = $(cell).parents('tr').filter(':first'); + cell = $(cell)[0]; // in case cell is a jQuery object + // tbody may not exist if update is initialized while tbody is removed for processing + if ($tb.length && tbdy >= 0) { + row = $tb.eq(tbdy).find('tr').index( $row ); + icell = cell.cellIndex; + l = c.cache[tbdy].normalized[row].length - 1; + c.cache[tbdy].row[table.config.cache[tbdy].normalized[row][l]] = $row; + c.cache[tbdy].normalized[row][icell] = c.parsers[icell].format( getElementText(table, cell, icell), table, cell, icell ); + checkResort($this, resort, callback); + } + }) + .bind("addRows.tablesorter", function(e, $row, resort, callback) { + e.stopPropagation(); + var i, rows = $row.filter('tr').length, + dat = [], l = $row[0].cells.length, + tbdy = $this.find('tbody').index( $row.parents('tbody').filter(':first') ); + // fixes adding rows to an empty table - see issue #179 + if (!c.parsers) { + buildParserCache(table); + } + // add each row + for (i = 0; i < rows; i++) { + // add each cell + for (j = 0; j < l; j++) { + dat[j] = c.parsers[j].format( getElementText(table, $row[i].cells[j], j), table, $row[i].cells[j], j ); + } + // add the row index to the end + dat.push(c.cache[tbdy].row.length); + // update cache + c.cache[tbdy].row.push([$row[i]]); + c.cache[tbdy].normalized.push(dat); + dat = []; + } + // resort using current settings + checkResort($this, resort, callback); + }) + .bind("sorton.tablesorter", function(e, list, callback, init) { + e.stopPropagation(); + $this.trigger("sortStart", this); + // update header count index + updateHeaderSortCount(table, list); + // set css for headers + setHeadersCss(table); + $this.trigger("sortBegin", this); + // sort the table and append it to the dom + multisort(table); + appendToTable(table, init); + if (typeof callback === "function") { + callback(table); + } + }) + .bind("appendCache.tablesorter", function(e, callback, init) { + e.stopPropagation(); + appendToTable(table, init); + if (typeof callback === "function") { + callback(table); + } + }) + .bind("applyWidgetId.tablesorter", function(e, id) { + e.stopPropagation(); + ts.getWidgetById(id).format(table, c, c.widgetOptions); + }) + .bind("applyWidgets.tablesorter", function(e, init) { + e.stopPropagation(); + // apply widgets + ts.applyWidget(table, init); + }) + .bind("refreshWidgets.tablesorter", function(e, all, dontapply){ + e.stopPropagation(); + ts.refreshWidgets(table, all, dontapply); + }) + .bind("destroy.tablesorter", function(e, c, cb){ + e.stopPropagation(); + ts.destroy(table, c, cb); + }); + } + + /* public methods */ + ts.construct = function(settings) { + return this.each(function() { + // if no thead or tbody, or tablesorter is already present, quit + if (!this.tHead || this.tBodies.length === 0 || this.hasInitialized === true) { + return (this.config && this.config.debug) ? log('stopping initialization! No thead, tbody or tablesorter has already been initialized') : ''; + } + // declare + var $this = $(this), table = this, + c, k = '', + m = $.metadata; + // initialization flag + table.hasInitialized = false; + // table is being processed flag + table.isProcessing = true; + // new blank config object + table.config = {}; + // merge and extend + c = $.extend(true, table.config, ts.defaults, settings); + // save the settings where they read + $.data(table, "tablesorter", c); + if (c.debug) { $.data( table, 'startoveralltimer', new Date()); } + // constants + c.supportsTextContent = $('x')[0].textContent === 'x'; + c.supportsDataObject = parseFloat($.fn.jquery) >= 1.4; + // digit sort text location; keeping max+/- for backwards compatibility + c.string = { 'max': 1, 'min': -1, 'max+': 1, 'max-': -1, 'zero': 0, 'none': 0, 'null': 0, 'top': true, 'bottom': false }; + // add table theme class only if there isn't already one there + if (!/tablesorter\-/.test($this.attr('class'))) { + k = (c.theme !== '' ? ' tablesorter-' + c.theme : ''); + } + c.$table = $this.addClass(c.tableClass + k); + c.$tbodies = $this.children('tbody:not(.' + c.cssInfoBlock + ')'); + // build headers + buildHeaders(table); + // fixate columns if the users supplies the fixedWidth option + // do this after theme has been applied + fixColumnWidth(table); + // try to auto detect column type, and store in tables config + buildParserCache(table); + // build the cache for the tbody cells + // delayInit will delay building the cache until the user starts a sort + if (!c.delayInit) { buildCache(table); } + // bind all header events and methods + bindEvents(table); + // get sort list from jQuery data or metadata + // in jQuery < 1.4, an error occurs when calling $this.data() + if (c.supportsDataObject && typeof $this.data().sortlist !== 'undefined') { + c.sortList = $this.data().sortlist; + } else if (m && ($this.metadata() && $this.metadata().sortlist)) { + c.sortList = $this.metadata().sortlist; + } + // apply widget init code + ts.applyWidget(table, true); + // if user has supplied a sort list to constructor + if (c.sortList.length > 0) { + $this.trigger("sorton", [c.sortList, {}, !c.initWidgets]); + } else if (c.initWidgets) { + // apply widget format + ts.applyWidget(table); + } + + // show processesing icon + if (c.showProcessing) { + $this + .unbind('sortBegin.tablesorter sortEnd.tablesorter') + .bind('sortBegin.tablesorter sortEnd.tablesorter', function(e) { + ts.isProcessing(table, e.type === 'sortBegin'); + }); + } + + // initialized + table.hasInitialized = true; + table.isProcessing = false; + if (c.debug) { + ts.benchmark("Overall initialization time", $.data( table, 'startoveralltimer')); + } + $this.trigger('tablesorter-initialized', table); + if (typeof c.initialized === 'function') { c.initialized(table); } + }); + }; + + // *** Process table *** + // add processing indicator + ts.isProcessing = function(table, toggle, $ths) { + table = $(table); + var c = table[0].config, + // default to all headers + $h = $ths || table.find('.' + c.cssHeader); + if (toggle) { + if (c.sortList.length > 0) { + // get headers from the sortList + $h = $h.filter(function(){ + // get data-column from attr to keep compatibility with jQuery 1.2.6 + return this.sortDisabled ? false : ts.isValueInArray( parseFloat($(this).attr('data-column')), c.sortList); + }); + } + $h.addClass(c.cssProcessing); + } else { + $h.removeClass(c.cssProcessing); + } + }; + + // detach tbody but save the position + // don't use tbody because there are portions that look for a tbody index (updateCell) + ts.processTbody = function(table, $tb, getIt){ + var holdr; + if (getIt) { + table.isProcessing = true; + $tb.before(''); + holdr = ($.fn.detach) ? $tb.detach() : $tb.remove(); + return holdr; + } + holdr = $(table).find('span.tablesorter-savemyplace'); + $tb.insertAfter( holdr ); + holdr.remove(); + table.isProcessing = false; + }; + + ts.clearTableBody = function(table) { + $(table)[0].config.$tbodies.empty(); + }; + + // restore headers + ts.restoreHeaders = function(table){ + var c = table.config; + // don't use c.$headers here in case header cells were swapped + c.$table.find(c.selectorHeaders).each(function(i){ + // only restore header cells if it is wrapped + // because this is also used by the updateAll method + if ($(this).find('.tablesorter-header-inner').length){ + $(this).html( c.headerContent[i] ); + } + }); + }; + + ts.destroy = function(table, removeClasses, callback){ + table = $(table)[0]; + if (!table.hasInitialized) { return; } + // remove all widgets + ts.refreshWidgets(table, true, true); + var $t = $(table), c = table.config, + $h = $t.find('thead:first'), + $r = $h.find('tr.' + c.cssHeaderRow).removeClass(c.cssHeaderRow), + $f = $t.find('tfoot:first > tr').children('th, td'); + // remove widget added rows, just in case + $h.find('tr').not($r).remove(); + // disable tablesorter + $t + .removeData('tablesorter') + .unbind('sortReset update updateAll updateRows updateCell addRows sorton appendCache applyWidgetId applyWidgets refreshWidgets destroy mouseup mouseleave keypress sortBegin sortEnd '.split(' ').join('.tablesorter ')); + c.$headers.add($f) + .removeClass(c.cssHeader + ' ' + c.cssAsc + ' ' + c.cssDesc) + .removeAttr('data-column'); + $r.find(c.selectorSort).unbind('mousedown.tablesorter mouseup.tablesorter keypress.tablesorter'); + ts.restoreHeaders(table); + if (removeClasses !== false) { + $t.removeClass(c.tableClass + ' tablesorter-' + c.theme); + } + // clear flag in case the plugin is initialized again + table.hasInitialized = false; + if (typeof callback === 'function') { + callback(table); + } + }; + + // *** sort functions *** + // regex used in natural sort + ts.regex = [ + /(^([+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?)?$|^0x[0-9a-f]+$|\d+)/gi, // chunk/tokenize numbers & letters + /(^([\w ]+,?[\w ]+)?[\w ]+,?[\w ]+\d+:\d+(:\d+)?[\w ]?|^\d{1,4}[\/\-]\d{1,4}[\/\-]\d{1,4}|^\w+, \w+ \d+, \d{4})/, //date + /^0x[0-9a-f]+$/i // hex + ]; + + // Natural sort - https://github.com/overset/javascript-natural-sort + ts.sortText = function(table, a, b, col) { + if (a === b) { return 0; } + var c = table.config, e = c.string[ (c.empties[col] || c.emptyTo ) ], + r = ts.regex, xN, xD, yN, yD, xF, yF, i, mx; + if (a === '' && e !== 0) { return typeof e === 'boolean' ? (e ? -1 : 1) : -e || -1; } + if (b === '' && e !== 0) { return typeof e === 'boolean' ? (e ? 1 : -1) : e || 1; } + if (typeof c.textSorter === 'function') { return c.textSorter(a, b, table, col); } + // chunk/tokenize + xN = a.replace(r[0], '\\0$1\\0').replace(/\\0$/, '').replace(/^\\0/, '').split('\\0'); + yN = b.replace(r[0], '\\0$1\\0').replace(/\\0$/, '').replace(/^\\0/, '').split('\\0'); + // numeric, hex or date detection + xD = parseInt(a.match(r[2]),16) || (xN.length !== 1 && a.match(r[1]) && Date.parse(a)); + yD = parseInt(b.match(r[2]),16) || (xD && b.match(r[1]) && Date.parse(b)) || null; + // first try and sort Hex codes or Dates + if (yD) { + if ( xD < yD ) { return -1; } + if ( xD > yD ) { return 1; } + } + mx = Math.max(xN.length, yN.length); + // natural sorting through split numeric strings and default strings + for (i = 0; i < mx; i++) { + // find floats not starting with '0', string or 0 if not defined + xF = isNaN(xN[i]) ? xN[i] || 0 : parseFloat(xN[i]) || 0; + yF = isNaN(yN[i]) ? yN[i] || 0 : parseFloat(yN[i]) || 0; + // handle numeric vs string comparison - number < string - (Kyle Adams) + if (isNaN(xF) !== isNaN(yF)) { return (isNaN(xF)) ? 1 : -1; } + // rely on string comparison if different types - i.e. '02' < 2 != '02' < '2' + if (typeof xF !== typeof yF) { + xF += ''; + yF += ''; + } + if (xF < yF) { return -1; } + if (xF > yF) { return 1; } + } + return 0; + }; + + ts.sortTextDesc = function(table, a, b, col) { + if (a === b) { return 0; } + var c = table.config, e = c.string[ (c.empties[col] || c.emptyTo ) ]; + if (a === '' && e !== 0) { return typeof e === 'boolean' ? (e ? -1 : 1) : e || 1; } + if (b === '' && e !== 0) { return typeof e === 'boolean' ? (e ? 1 : -1) : -e || -1; } + if (typeof c.textSorter === 'function') { return c.textSorter(b, a, table, col); } + return ts.sortText(table, b, a); + }; + + // return text string value by adding up ascii value + // so the text is somewhat sorted when using a digital sort + // this is NOT an alphanumeric sort + ts.getTextValue = function(a, mx, d) { + if (mx) { + // make sure the text value is greater than the max numerical value (mx) + var i, l = a ? a.length : 0, n = mx + d; + for (i = 0; i < l; i++) { + n += a.charCodeAt(i); + } + return d * n; + } + return 0; + }; + + ts.sortNumeric = function(table, a, b, col, mx, d) { + if (a === b) { return 0; } + var c = table.config, e = c.string[ (c.empties[col] || c.emptyTo ) ]; + if (a === '' && e !== 0) { return typeof e === 'boolean' ? (e ? -1 : 1) : -e || -1; } + if (b === '' && e !== 0) { return typeof e === 'boolean' ? (e ? 1 : -1) : e || 1; } + if (isNaN(a)) { a = ts.getTextValue(a, mx, d); } + if (isNaN(b)) { b = ts.getTextValue(b, mx, d); } + return a - b; + }; + + ts.sortNumericDesc = function(table, a, b, col, mx, d) { + if (a === b) { return 0; } + var c = table.config, e = c.string[ (c.empties[col] || c.emptyTo ) ]; + if (a === '' && e !== 0) { return typeof e === 'boolean' ? (e ? -1 : 1) : e || 1; } + if (b === '' && e !== 0) { return typeof e === 'boolean' ? (e ? 1 : -1) : -e || -1; } + if (isNaN(a)) { a = ts.getTextValue(a, mx, d); } + if (isNaN(b)) { b = ts.getTextValue(b, mx, d); } + return b - a; + }; + + // used when replacing accented characters during sorting + ts.characterEquivalents = { + "a" : "\u00e1\u00e0\u00e2\u00e3\u00e4\u0105\u00e5", // áàâãäąå + "A" : "\u00c1\u00c0\u00c2\u00c3\u00c4\u0104\u00c5", // ÁÀÂÃÄĄÅ + "c" : "\u00e7\u0107\u010d", // çćč + "C" : "\u00c7\u0106\u010c", // ÇĆČ + "e" : "\u00e9\u00e8\u00ea\u00eb\u011b\u0119", // éèêëěę + "E" : "\u00c9\u00c8\u00ca\u00cb\u011a\u0118", // ÉÈÊËĚĘ + "i" : "\u00ed\u00ec\u0130\u00ee\u00ef\u0131", // íìİîïı + "I" : "\u00cd\u00cc\u0130\u00ce\u00cf", // ÍÌİÎÏ + "o" : "\u00f3\u00f2\u00f4\u00f5\u00f6", // óòôõö + "O" : "\u00d3\u00d2\u00d4\u00d5\u00d6", // ÓÒÔÕÖ + "ss": "\u00df", // ß (s sharp) + "SS": "\u1e9e", // ẞ (Capital sharp s) + "u" : "\u00fa\u00f9\u00fb\u00fc\u016f", // úùûüů + "U" : "\u00da\u00d9\u00db\u00dc\u016e" // ÚÙÛÜŮ + }; + ts.replaceAccents = function(s) { + var a, acc = '[', eq = ts.characterEquivalents; + if (!ts.characterRegex) { + ts.characterRegexArray = {}; + for (a in eq) { + if (typeof a === 'string') { + acc += eq[a]; + ts.characterRegexArray[a] = new RegExp('[' + eq[a] + ']', 'g'); + } + } + ts.characterRegex = new RegExp(acc + ']'); + } + if (ts.characterRegex.test(s)) { + for (a in eq) { + if (typeof a === 'string') { + s = s.replace( ts.characterRegexArray[a], a ); + } + } + } + return s; + }; + + // *** utilities *** + ts.isValueInArray = function(v, a) { + var i, l = a.length; + for (i = 0; i < l; i++) { + if (a[i][0] === v) { + return true; + } + } + return false; + }; + + ts.addParser = function(parser) { + var i, l = ts.parsers.length, a = true; + for (i = 0; i < l; i++) { + if (ts.parsers[i].id.toLowerCase() === parser.id.toLowerCase()) { + a = false; + } + } + if (a) { + ts.parsers.push(parser); + } + }; + + ts.getParserById = function(name) { + var i, l = ts.parsers.length; + for (i = 0; i < l; i++) { + if (ts.parsers[i].id.toLowerCase() === (name.toString()).toLowerCase()) { + return ts.parsers[i]; + } + } + return false; + }; + + ts.addWidget = function(widget) { + ts.widgets.push(widget); + }; + + ts.getWidgetById = function(name) { + var i, w, l = ts.widgets.length; + for (i = 0; i < l; i++) { + w = ts.widgets[i]; + if (w && w.hasOwnProperty('id') && w.id.toLowerCase() === name.toLowerCase()) { + return w; + } + } + }; + + ts.applyWidget = function(table, init) { + table = $(table)[0]; // in case this is called externally + var c = table.config, + wo = c.widgetOptions, + widgets = [], + time, i, w, wd; + if (c.debug) { time = new Date(); } + if (c.widgets.length) { + // ensure unique widget ids + c.widgets = $.grep(c.widgets, function(v, k){ + return $.inArray(v, c.widgets) === k; + }); + // build widget array & add priority as needed + $.each(c.widgets || [], function(i,n){ + wd = ts.getWidgetById(n); + if (wd && wd.id) { + // set priority to 10 if not defined + if (!wd.priority) { wd.priority = 10; } + widgets[i] = wd; + } + }); + // sort widgets by priority + widgets.sort(function(a, b){ + return a.priority < b.priority ? -1 : a.priority === b.priority ? 0 : 1; + }); + + // add/update selected widgets + $.each(widgets, function(i,w){ + if (w) { + if (init) { + if (w.hasOwnProperty('options')) { + wo = table.config.widgetOptions = $.extend( true, {}, w.options, wo ); + } + if (w.hasOwnProperty('init')) { + w.init(table, w, c, wo); + } + } else if (!init && w.hasOwnProperty('format')) { + w.format(table, c, wo, false); + } + } + }); + } + if (c.debug) { + w = c.widgets.length; + benchmark("Completed " + (init === true ? "initializing " : "applying ") + w + " widget" + (w !== 1 ? "s" : ""), time); + } + }; + + ts.refreshWidgets = function(table, doAll, dontapply) { + table = $(table)[0]; // see issue #243 + var i, c = table.config, + cw = c.widgets, + w = ts.widgets, l = w.length; + // remove previous widgets + for (i = 0; i < l; i++){ + if ( w[i] && w[i].id && (doAll || $.inArray( w[i].id, cw ) < 0) ) { + if (c.debug) { log( 'Refeshing widgets: Removing ' + w[i].id ); } + if (w[i].hasOwnProperty('remove')) { w[i].remove(table, c, c.widgetOptions); } + } + } + if (dontapply !== true) { + ts.applyWidget(table, doAll); + } + }; + + // get sorter, string, empty, etc options for each column from + // jQuery data, metadata, header option or header class name ("sorter-false") + // priority = jQuery data > meta > headers option > header class name + ts.getData = function(h, ch, key) { + var val = '', $h = $(h), m, cl; + if (!$h.length) { return ''; } + m = $.metadata ? $h.metadata() : false; + cl = ' ' + ($h.attr('class') || ''); + if (typeof $h.data(key) !== 'undefined' || typeof $h.data(key.toLowerCase()) !== 'undefined'){ + // "data-lockedOrder" is assigned to "lockedorder"; but "data-locked-order" is assigned to "lockedOrder" + // "data-sort-initial-order" is assigned to "sortInitialOrder" + val += $h.data(key) || $h.data(key.toLowerCase()); + } else if (m && typeof m[key] !== 'undefined') { + val += m[key]; + } else if (ch && typeof ch[key] !== 'undefined') { + val += ch[key]; + } else if (cl !== ' ' && cl.match(' ' + key + '-')) { + // include sorter class name "sorter-text", etc; now works with "sorter-my-custom-parser" + val = cl.match( new RegExp('\\s' + key + '-([\\w-]+)') )[1] || ''; + } + return $.trim(val); + }; + + ts.formatFloat = function(s, table) { + if (typeof s !== 'string' || s === '') { return s; } + // allow using formatFloat without a table; defaults to US number format + var i, + t = table && table.config ? table.config.usNumberFormat !== false : + typeof table !== "undefined" ? table : true; + if (t) { + // US Format - 1,234,567.89 -> 1234567.89 + s = s.replace(/,/g,''); + } else { + // German Format = 1.234.567,89 -> 1234567.89 + // French Format = 1 234 567,89 -> 1234567.89 + s = s.replace(/[\s|\.]/g,'').replace(/,/g,'.'); + } + if(/^\s*\([.\d]+\)/.test(s)) { + // make (#) into a negative number -> (10) = -10 + s = s.replace(/^\s*\(/,'-').replace(/\)/,''); + } + i = parseFloat(s); + // return the text instead of zero + return isNaN(i) ? $.trim(s) : i; + }; + + ts.isDigit = function(s) { + // replace all unwanted chars and match + return isNaN(s) ? (/^[\-+(]?\d+[)]?$/).test(s.toString().replace(/[,.'"\s]/g, '')) : true; + }; + + }() + }); + + // make shortcut + var ts = $.tablesorter; + + // extend plugin scope + $.fn.extend({ + tablesorter: ts.construct + }); + + // add default parsers + ts.addParser({ + id: "text", + is: function() { + return true; + }, + format: function(s, table) { + var c = table.config; + if (s) { + s = $.trim( c.ignoreCase ? s.toLocaleLowerCase() : s ); + s = c.sortLocaleCompare ? ts.replaceAccents(s) : s; + } + return s; + }, + type: "text" + }); + + ts.addParser({ + id: "digit", + is: function(s) { + return ts.isDigit(s); + }, + format: function(s, table) { + var n = ts.formatFloat((s || '').replace(/[^\w,. \-()]/g, ""), table); + return s && typeof n === 'number' ? n : s ? $.trim( s && table.config.ignoreCase ? s.toLocaleLowerCase() : s ) : s; + }, + type: "numeric" + }); + + ts.addParser({ + id: "currency", + is: function(s) { + return (/^\(?\d+[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]|[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]\d+\)?$/).test((s || '').replace(/[,. ]/g,'')); // £$€¤¥¢ + }, + format: function(s, table) { + var n = ts.formatFloat((s || '').replace(/[^\w,. \-()]/g, ""), table); + return s && typeof n === 'number' ? n : s ? $.trim( s && table.config.ignoreCase ? s.toLocaleLowerCase() : s ) : s; + }, + type: "numeric" + }); + + ts.addParser({ + id: "ipAddress", + is: function(s) { + return (/^\d{1,3}[\.]\d{1,3}[\.]\d{1,3}[\.]\d{1,3}$/).test(s); + }, + format: function(s, table) { + var i, a = s ? s.split(".") : '', + r = "", + l = a.length; + for (i = 0; i < l; i++) { + r += ("00" + a[i]).slice(-3); + } + return s ? ts.formatFloat(r, table) : s; + }, + type: "numeric" + }); + + ts.addParser({ + id: "url", + is: function(s) { + return (/^(https?|ftp|file):\/\//).test(s); + }, + format: function(s) { + return s ? $.trim(s.replace(/(https?|ftp|file):\/\//, '')) : s; + }, + type: "text" + }); + + ts.addParser({ + id: "isoDate", + is: function(s) { + return (/^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}/).test(s); + }, + format: function(s, table) { + return s ? ts.formatFloat((s !== "") ? (new Date(s.replace(/-/g, "/")).getTime() || "") : "", table) : s; + }, + type: "numeric" + }); + + ts.addParser({ + id: "percent", + is: function(s) { + return (/(\d\s*?%|%\s*?\d)/).test(s) && s.length < 15; + }, + format: function(s, table) { + return s ? ts.formatFloat(s.replace(/%/g, ""), table) : s; + }, + type: "numeric" + }); + + ts.addParser({ + id: "usLongDate", + is: function(s) { + // two digit years are not allowed cross-browser + // Jan 01, 2013 12:34:56 PM or 01 Jan 2013 + return (/^[A-Z]{3,10}\.?\s+\d{1,2},?\s+(\d{4})(\s+\d{1,2}:\d{2}(:\d{2})?(\s+[AP]M)?)?$/i).test(s) || (/^\d{1,2}\s+[A-Z]{3,10}\s+\d{4}/i).test(s); + }, + format: function(s, table) { + return s ? ts.formatFloat( (new Date(s.replace(/(\S)([AP]M)$/i, "$1 $2")).getTime() || ''), table) : s; + }, + type: "numeric" + }); + + ts.addParser({ + id: "shortDate", // "mmddyyyy", "ddmmyyyy" or "yyyymmdd" + is: function(s) { + // testing for ##-##-#### or ####-##-##, so it's not perfect; time can be included + return (/(^\d{1,2}[\/\s]\d{1,2}[\/\s]\d{4})|(^\d{4}[\/\s]\d{1,2}[\/\s]\d{1,2})/).test((s || '').replace(/\s+/g," ").replace(/[\-.,]/g, "/")); + }, + format: function(s, table, cell, cellIndex) { + if (s) { + var c = table.config, ci = c.headerList[cellIndex], + format = ci.dateFormat || ts.getData( ci, c.headers[cellIndex], 'dateFormat') || c.dateFormat; + s = s.replace(/\s+/g," ").replace(/[\-.,]/g, "/"); // escaped - because JSHint in Firefox was showing it as an error + if (format === "mmddyyyy") { + s = s.replace(/(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{4})/, "$3/$1/$2"); + } else if (format === "ddmmyyyy") { + s = s.replace(/(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{4})/, "$3/$2/$1"); + } else if (format === "yyyymmdd") { + s = s.replace(/(\d{4})[\/\s](\d{1,2})[\/\s](\d{1,2})/, "$1/$2/$3"); + } + } + return s ? ts.formatFloat( (new Date(s).getTime() || ''), table) : s; + }, + type: "numeric" + }); + + ts.addParser({ + id: "time", + is: function(s) { + return (/^(([0-2]?\d:[0-5]\d)|([0-1]?\d:[0-5]\d\s?([AP]M)))$/i).test(s); + }, + format: function(s, table) { + return s ? ts.formatFloat( (new Date("2000/01/01 " + s.replace(/(\S)([AP]M)$/i, "$1 $2")).getTime() || ""), table) : s; + }, + type: "numeric" + }); + + ts.addParser({ + id: "metadata", + is: function() { + return false; + }, + format: function(s, table, cell) { + var c = table.config, + p = (!c.parserMetadataName) ? 'sortValue' : c.parserMetadataName; + return $(cell).metadata()[p]; + }, + type: "numeric" + }); + + // add default widgets + ts.addWidget({ + id: "zebra", + priority: 90, + format: function(table, c, wo) { + var $tb, $tv, $tr, row, even, time, k, l, + child = new RegExp(c.cssChildRow, 'i'), + b = c.$tbodies; + if (c.debug) { + time = new Date(); + } + for (k = 0; k < b.length; k++ ) { + // loop through the visible rows + $tb = b.eq(k); + l = $tb.children('tr').length; + if (l > 1) { + row = 0; + $tv = $tb.children('tr:visible'); + // revered back to using jQuery each - strangely it's the fastest method + /*jshint loopfunc:true */ + $tv.each(function(){ + $tr = $(this); + // style children rows the same way the parent row was styled + if (!child.test(this.className)) { row++; } + even = (row % 2 === 0); + $tr.removeClass(wo.zebra[even ? 1 : 0]).addClass(wo.zebra[even ? 0 : 1]); + }); + } + } + if (c.debug) { + ts.benchmark("Applying Zebra widget", time); + } + }, + remove: function(table, c, wo){ + var k, $tb, + b = c.$tbodies, + rmv = (wo.zebra || [ "even", "odd" ]).join(' '); + for (k = 0; k < b.length; k++ ){ + $tb = $.tablesorter.processTbody(table, b.eq(k), true); // remove tbody + $tb.children().removeClass(rmv); + $.tablesorter.processTbody(table, $tb, false); // restore tbody + } + } + }); + +})(jQuery); diff --git a/templates/admin/default/assets/js/tablesorter/jquery.tablesorter.widgets-filter-formatter.js b/templates/admin/default/assets/js/tablesorter/jquery.tablesorter.widgets-filter-formatter.js new file mode 100644 index 000000000..83bb8b793 --- /dev/null +++ b/templates/admin/default/assets/js/tablesorter/jquery.tablesorter.widgets-filter-formatter.js @@ -0,0 +1,826 @@ +/*! Filter widget formatter functions - updated 6/4/2013 + * requires: tableSorter 2.7.7+ and jQuery 1.4.3+ + * + * uiSpinner (jQuery UI spinner) + * uiSlider (jQuery UI slider) + * uiRange (jQuery UI range slider) + * uiDateCompare (jQuery UI datepicker; 1 input) + * uiDatepicker (jQuery UI datepicker; 2 inputs, filter range) + * html5Number (spinner) + * html5Range (slider) + * html5Color (color) + */ +/*jshint browser:true, jquery:true, unused:false */ +/*global jQuery: false */ +;(function($){ +"use strict"; +$.tablesorter = $.tablesorter || {}; + +$.tablesorter.filterFormatter = { + + /**********************\ + jQuery UI Spinner + \**********************/ + uiSpinner: function($cell, indx, spinnerDef) { + var o = $.extend({ + min : 0, + max : 100, + step : 1, + value : 1, + delayed : true, + addToggle : true, + disabled : false, + exactMatch : true, + compare : '' + }, spinnerDef ), + // Add a hidden input to hold the range values + $input = $('') + .appendTo($cell) + // hidden filter update (.tsfilter) namespace trigger by filter widget + .bind('change.tsfilter', function(){ + updateSpinner({ value: this.value, delayed: false }); + }), + $shcell = [], + c = $cell.closest('table')[0].config, + + // this function updates the hidden input and adds the current values to the header cell text + updateSpinner = function(ui) { + var chkd = true, state, + // ui is not undefined on create + v = ui && ui.value && $.tablesorter.formatFloat((ui.value + '').replace(/[><=]/g,'')) || $cell.find('.spinner').val() || o.value; + if (o.addToggle) { + chkd = $cell.find('.toggle').is(':checked'); + } + state = o.disabled || !chkd ? 'disable' : 'enable'; + $cell.find('.filter') + // add equal to the beginning, so we filter exact numbers + .val( chkd ? (o.compare ? o.compare : o.exactMatch ? '=' : '') + v : '' ) + .trigger('search', ui && typeof ui.delayed === 'boolean' ? ui.delayed : o.delayed).end() + .find('.spinner').spinner(state).val(v); + // update sticky header cell + if ($shcell.length) { + $shcell.find('.spinner').spinner(state).val(v); + if (o.addToggle) { + $shcell.find('.toggle')[0].checked = chkd; + } + } + }; + + // add callbacks; preserve added callbacks + o.oldcreate = o.create; + o.oldspin = o.spin; + o.create = function(event, ui) { + updateSpinner(); // ui is an empty object on create + if (typeof o.oldcreate === 'function') { o.oldcreate(event, ui); } + }; + o.spin = function(event, ui) { + updateSpinner(ui); + if (typeof o.oldspin === 'function') { o.oldspin(event, ui); } + }; + if (o.addToggle) { + $('
') + .appendTo($cell) + .find('.toggle') + .bind('change', function(){ + updateSpinner(); + }); + } + // make sure we use parsed data + $cell.closest('thead').find('th[data-column=' + indx + ']').addClass('filter-parsed'); + // add a jQuery UI spinner! + $('') + .val(o.value) + .appendTo($cell) + .spinner(o) + .bind('change keyup', function(e){ + updateSpinner(); + }); + + // has sticky headers? + c.$table.bind('stickyHeadersInit', function(){ + $shcell = c.widgetOptions.$sticky.find('.tablesorter-filter-row').children().eq(indx).empty(); + if (o.addToggle) { + $('
') + .appendTo($shcell) + .find('.toggle') + .bind('change', function(){ + $cell.find('.toggle')[0].checked = this.checked; + updateSpinner(); + }); + } + // add a jQuery UI spinner! + $('') + .val(o.value) + .appendTo($shcell) + .spinner(o) + .bind('change keyup', function(e){ + $cell.find('.spinner').val( this.value ); + updateSpinner(); + }); + }); + + // on reset + c.$table.bind('filterReset', function(){ + // turn off the toggle checkbox + if (o.addToggle) { + $cell.find('.toggle')[0].checked = false; + } + updateSpinner(); + }); + + updateSpinner(); + return $input; + }, + + /**********************\ + jQuery UI Slider + \**********************/ + uiSlider: function($cell, indx, sliderDef) { + var o = $.extend({ + value : 0, + min : 0, + max : 100, + step : 1, + range : "min", + delayed : true, + valueToHeader : false, + exactMatch : true, + compare : '', + allText : 'all' + }, sliderDef ), + // Add a hidden input to hold the range values + $input = $('') + .appendTo($cell) + // hidden filter update (.tsfilter) namespace trigger by filter widget + .bind('change.tsfilter', function(){ + updateSlider({ value: this.value }); + }), + $shcell = [], + c = $cell.closest('table')[0].config, + + // this function updates the hidden input and adds the current values to the header cell text + updateSlider = function(ui) { + // ui is not undefined on create + var v = typeof ui !== "undefined" ? $.tablesorter.formatFloat((ui.value + '').replace(/[><=]/g,'')) || o.min : o.value, + val = o.compare ? v : v === o.min ? o.allText : v, + result = o.compare + val; + if (o.valueToHeader) { + // add range indication to the header cell above! + $cell.closest('thead').find('th[data-column=' + indx + ']').find('.curvalue').html(' (' + result + ')'); + } else { + // add values to the handle data-value attribute so the css tooltip will work properly + $cell.find('.ui-slider-handle').addClass('value-popup').attr('data-value', result); + } + // update the hidden input; + // ****** ADD AN EQUAL SIGN TO THE BEGINNING! <- this makes the slide exactly match the number ****** + // when the value is at the minimum, clear the hidden input so all rows will be seen + $cell.find('.filter') + .val( ( o.compare ? o.compare + v : v === o.min ? '' : (o.exactMatch ? '=' : '') + v ) ) + .trigger('search', ui && typeof ui.delayed === 'boolean' ? ui.delayed : o.delayed).end() + .find('.slider').slider('value', v); + + // update sticky header cell + if ($shcell.length) { + $shcell.find('.slider').slider('value', v); + if (o.valueToHeader) { + $shcell.closest('thead').find('th[data-column=' + indx + ']').find('.curvalue').html(' (' + result + ')'); + } else { + $shcell.find('.ui-slider-handle').addClass('value-popup').attr('data-value', result); + } + } + + }; + $cell.closest('thead').find('th[data-column=' + indx + ']').addClass('filter-parsed'); + + // add span to header for value - only works if the line in the updateSlider() function is also un-commented out + if (o.valueToHeader) { + $cell.closest('thead').find('th[data-column=' + indx + ']').find('.tablesorter-header-inner').append(''); + } + + // add callbacks; preserve added callbacks + o.oldcreate = o.create; + o.oldslide = o.slide; + o.create = function(event, ui) { + updateSlider(); // ui is an empty object on create + if (typeof o.oldcreate === 'function') { o.oldcreate(event, ui); } + }; + o.slide = function(event, ui) { + updateSlider(ui); + if (typeof o.oldslide === 'function') { o.oldslide(event, ui); } + }; + // add a jQuery UI slider! + $('
') + .appendTo($cell) + .slider(o); + + // on reset + c.$table.bind('filterReset', function(){ + $cell.find('.slider').slider('value', o.value); + updateSlider(); + }); + + // has sticky headers? + c.$table.bind('stickyHeadersInit', function(){ + $shcell = c.widgetOptions.$sticky.find('.tablesorter-filter-row').children().eq(indx).empty(); + + // add a jQuery UI slider! + $('
') + .val(o.value) + .appendTo($shcell) + .slider(o) + .bind('change keyup', function(e){ + $cell.find('.slider').val( this.value ); + updateSlider(); + }); + + }); + + return $input; + }, + + /*************************\ + jQuery UI Range Slider (2 handles) + \*************************/ + uiRange: function($cell, indx, rangeDef) { + var o = $.extend({ + values : [0, 100], + min : 0, + max : 100, + range : true, + delayed : true, + valueToHeader : false + }, rangeDef ), + // Add a hidden input to hold the range values + $input = $('') + .appendTo($cell) + // hidden filter update (.tsfilter) namespace trigger by filter widget + .bind('change.tsfilter', function(){ + var v = this.value.split(' - '); + if (this.value === '') { v = [ o.min, o.max ]; } + if (v && v[1]) { + updateUiRange({ values: v, delay: false }); + } + }), + $shcell = [], + c = $cell.closest('table')[0].config, + + // this function updates the hidden input and adds the current values to the header cell text + updateUiRange = function(ui) { + // ui.values are undefined for some reason on create + var val = ui && ui.values || o.values, + result = val[0] + ' - ' + val[1], + // make range an empty string if entire range is covered so the filter row will hide (if set) + range = val[0] === o.min && val[1] === o.max ? '' : result; + if (o.valueToHeader) { + // add range indication to the header cell above (if not using the css method)! + $cell.closest('thead').find('th[data-column=' + indx + ']').find('.currange').html(' (' + result + ')'); + } else { + // add values to the handle data-value attribute so the css tooltip will work properly + $cell.find('.ui-slider-handle') + .addClass('value-popup') + .eq(0).attr('data-value', val[0]).end() // adding value to data attribute + .eq(1).attr('data-value', val[1]); // value popup shown via css + } + // update the hidden input + $cell.find('.filter').val(range) + .trigger('search', ui && typeof ui.delayed === 'boolean' ? ui.delayed : o.delayed).end() + .find('.range').slider('values', val); + // update sticky header cell + if ($shcell.length) { + $shcell.find('.range').slider('values', val); + if (o.valueToHeader) { + $shcell.closest('thead').find('th[data-column=' + indx + ']').find('.currange').html(' (' + result + ')'); + } else { + $shcell.find('.ui-slider-handle') + .addClass('value-popup') + .eq(0).attr('data-value', val[0]).end() // adding value to data attribute + .eq(1).attr('data-value', val[1]); // value popup shown via css + } + } + + }; + $cell.closest('thead').find('th[data-column=' + indx + ']').addClass('filter-parsed'); + + // add span to header for value - only works if the line in the updateUiRange() function is also un-commented out + if (o.valueToHeader) { + $cell.closest('thead').find('th[data-column=' + indx + ']').find('.tablesorter-header-inner').append(''); + } + + // add callbacks; preserve added callbacks + o.oldcreate = o.create; + o.oldslide = o.slide; + // add a jQuery UI range slider! + o.create = function(event, ui) { + updateUiRange(); // ui is an empty object on create + if (typeof o.oldcreate === 'function') { o.oldcreate(event, ui); } + }; + o.slide = function(event, ui) { + updateUiRange(ui); + if (typeof o.oldslide === 'function') { o.oldslide(event, ui); } + }; + $('
') + .appendTo($cell) + .slider(o); + + // on reset + c.$table.bind('filterReset', function(){ + $cell.find('.range').slider('values', o.values); + updateUiRange(); + }); + + // has sticky headers? + c.$table.bind('stickyHeadersInit', function(){ + $shcell = c.widgetOptions.$sticky.find('.tablesorter-filter-row').children().eq(indx).empty(); + + // add a jQuery UI slider! + $('
') + .val(o.value) + .appendTo($shcell) + .slider(o) + .bind('change keyup', function(e){ + $cell.find('.range').val( this.value ); + updateUiRange(); + }); + + }); + + // return the hidden input so the filter widget has a reference to it + return $input; + }, + + /*************************\ + jQuery UI Datepicker compare (1 input) + \*************************/ + uiDateCompare: function($cell, indx, defDate) { + var o = $.extend({ + defaultDate : '', + cellText : '', + changeMonth : true, + changeYear : true, + numberOfMonths : 1, + compare : '' + }, defDate), + $hdr = $cell.closest('thead').find('th[data-column=' + indx + ']'), + // Add a hidden input to hold the range values + $input = $('') + .appendTo($cell) + // hidden filter update (.tsfilter) namespace trigger by filter widget + .bind('change.tsfilter', function(){ + var v = this.value; + if (v) { + o.onClose(v); + } + }), + t, $shcell = [], + c = $cell.closest('table')[0].config; + + // make sure we're using parsed dates in the search + $hdr.addClass('filter-parsed'); + // Add date range picker + t = ''; + $(t).appendTo($cell); + + // add callbacks; preserve added callbacks + o.oldonClose = o.onClose; + + o.onClose = function( selectedDate, ui ) { + var date = new Date(selectedDate + ( o.compare.match('<') ? ' 23:59:59' : '' )).getTime() || ''; + $cell + // update hidden input + .find('.dateCompare').val( o.compare + date ) + .trigger('search').end() + .find('.date') + .datepicker('setDate', selectedDate); + + // update sticky header cell + if ($shcell.length) { + $shcell.find('.date').datepicker('setDate', selectedDate); + } + + if (typeof o.oldonClose === 'function') { o.oldonClose(selectedDate, ui); } + }; + $cell.find('.date').datepicker(o); + + if (o.filterDate) { + $cell.find('.date').datepicker('setDate', o.filterDate); + } + + // on reset + c.$table.bind('filterReset', function(){ + $cell.find('.date').val('').datepicker('option', 'currentText', '' ); + if ($shcell.length) { + $shcell.find('.date').val('').datepicker('option', 'currentText', '' ); + } + }); + + // has sticky headers? + c.$table.bind('stickyHeadersInit', function(){ + $shcell = c.widgetOptions.$sticky.find('.tablesorter-filter-row').children().eq(indx).empty(); + // add a jQuery datepicker! + $shcell + .append(t) + .find('.date') + .datepicker(o); + }); + + // return the hidden input so the filter widget has a reference to it + return $input.val( o.defaultDate ? o.defaultDate : '' ); + }, + + /*************************\ + jQuery UI Datepicker (2 inputs) + \*************************/ + uiDatepicker: function($cell, indx, defDate) { + var o = $.extend({ + from : '', + to : '', + textFrom : 'from', + textTo : 'to', + changeMonth : true, + changeYear : true, + numberOfMonths : 1 + }, defDate), + t, closeFrom, $shcell = [], + // Add a hidden input to hold the range values + $input = $('') + .appendTo($cell) + // hidden filter update (.tsfilter) namespace trigger by filter widget + .bind('change.tsfilter', function(){ + var v = this.value; + if (v.match(' - ')) { + v = v.split(' - '); + $cell.find('.dateTo').val(v[1]); + closeFrom(v[0]); + } else if (v.match('>=')) { + closeFrom( v.replace('>=', '') ); + } else if (v.match('<=')) { + o.onClose( v.replace('<=', '') ); + } + }), + c = $cell.closest('table')[0].config; + + // make sure we're using parsed dates in the search + $cell.closest('thead').find('th[data-column=' + indx + ']').addClass('filter-parsed'); + // Add date range picker + t = ''; + $(t).appendTo($cell); + + // add callbacks; preserve added callbacks + o.oldonClose = o.onClose; + + o.defaultDate = o.from || o.defaultDate; + + closeFrom = o.onClose = function( selectedDate, ui ) { + var from = ( (new Date(selectedDate)).getTime() || ''), + to = (new Date($cell.find('.dateTo').val() + ' 23:59:59').getTime() || ''), + range = from ? ( to ? from + ' - ' + to : '>=' + from ) : (to ? '<=' + to : ''); + $cell + .find('.dateTo').datepicker('option', 'minDate', selectedDate ).end() + .find('.dateFrom').val(selectedDate).end() + // update hidden input + .find('.dateRange').val(range) + .trigger('search'); + // update sticky header cell + if ($shcell.length) { + $shcell + .find('.dateTo').datepicker('option', 'minDate', selectedDate ).end() + .find('.dateFrom').val(selectedDate); + } + if (typeof o.oldonClose === 'function') { o.oldonClose(selectedDate, ui); } + }; + + $cell.find('.dateFrom').datepicker(o); + o.defaultDate = o.to || '+7d'; // set to date +7 days from today (if not defined) + o.onClose = function( selectedDate, ui ) { + var from = new Date( $cell.find('.dateFrom').val() ).getTime() || '', + to = new Date( selectedDate + ' 23:59:59' ).getTime() || '', + range = from ? ( to ? from + ' - ' + to : '>=' + from ) : (to ? '<=' + to : ''); + $cell + .find('.dateFrom').datepicker('option', 'maxDate', selectedDate ).end() + .find('.dateTo').val(selectedDate).end() + .find('.dateRange').val(range) + .trigger('search'); + // update sticky header cell + if ($shcell.length) { + $shcell + .find('.dateFrom').datepicker('option', 'maxDate', selectedDate ).end() + .find('.dateTo').val(selectedDate); + } + if (typeof o.oldonClose === 'function') { o.oldonClose(selectedDate, ui); } + }; + $cell.find('.dateTo').datepicker(o); + + // has sticky headers? + c.$table.bind('stickyHeadersInit', function(){ + $shcell = c.widgetOptions.$sticky.find('.tablesorter-filter-row').children().eq(indx).empty(); + // add a jQuery datepicker! + $shcell.append(t).find('.dateTo').datepicker(o); + o.defaultDate = o.from || o.defaultDate || new Date(); + o.onClose = closeFrom; + $shcell.find('.dateFrom').datepicker(o); + }); + + // on reset + $cell.closest('table').bind('filterReset', function(){ + $cell.find('.dateFrom, .dateTo').val(''); + if ($shcell.length) { + $shcell.find('.dateFrom, .dateTo').val(''); + } + }); + + // return the hidden input so the filter widget has a reference to it + t = o.from ? ( o.to ? o.from + ' - ' + o.to : '>=' + o.from ) : (o.to ? '<=' + o.to : ''); + return $input.val( t ); + }, + + /**********************\ + HTML5 Number (spinner) + \**********************/ + html5Number : function($cell, indx, def5Num) { + var t, o = $.extend({ + value : 0, + min : 0, + max : 100, + step : 1, + delayed : true, + disabled : false, + addToggle : true, + exactMatch : true, + compare : '', + skipTest: false + }, def5Num), + + // test browser for HTML5 range support + $number = $('').appendTo($cell), + // test if HTML5 number is supported - from Modernizr + numberSupported = o.skipTest || $number.attr('type') === 'number' && $number.val() !== 'test', + $shcell = [], + c = $cell.closest('table')[0].config, + + updateNumber = function(v, delayed){ + var chkd = o.addToggle ? $cell.find('.toggle').is(':checked') : true; + $cell.find('input[type=hidden]') + // add equal to the beginning, so we filter exact numbers + .val( !o.addToggle || chkd ? (o.compare ? o.compare : o.exactMatch ? '=' : '') + v : '' ) + .trigger('search', delayed ? delayed : o.delayed).end() + .find('.number').val(v); + if ($cell.find('.number').length) { + $cell.find('.number')[0].disabled = (o.disabled || !chkd); + } + // update sticky header cell + if ($shcell.length) { + $shcell.find('.number').val(v)[0].disabled = (o.disabled || !chkd); + if (o.addToggle) { + $shcell.find('.toggle')[0].checked = chkd; + } + } + }; + $number.remove(); + + if (numberSupported) { + t = o.addToggle ? '
' : ''; + t += ''; + // add HTML5 number (spinner) + $cell + .html(t + '') + .find('.toggle, .number').bind('change', function(){ + updateNumber( $cell.find('.number').val() ); + }) + .closest('thead').find('th[data-column=' + indx + ']') + .addClass('filter-parsed') // get exact numbers from column + // on reset + .closest('table').bind('filterReset', function(){ + // turn off the toggle checkbox + if (o.addToggle) { + $cell.find('.toggle')[0].checked = false; + if ($shcell.length) { + $shcell.find('.toggle')[0].checked = false; + } + } + updateNumber( $cell.find('.number').val() ); + }); + + // hidden filter update (.tsfilter) namespace trigger by filter widget + $cell.find('input[type=hidden]').bind('change.tsfilter', function(){ + updateNumber( this.value ); + }); + + // has sticky headers? + c.$table.bind('stickyHeadersInit', function(){ + $shcell = c.widgetOptions.$sticky.find('.tablesorter-filter-row').children().eq(indx).empty(); + $shcell + .html(t) + .find('.toggle, .number').bind('change', function(){ + updateNumber( $shcell.find('.number').val() ); + }); + updateNumber( $cell.find('.number').val() ); + }); + + updateNumber( $cell.find('.number').val() ); + + } + + return numberSupported ? $cell.find('input[type="hidden"]') : $(''); + }, + + /**********************\ + HTML5 range slider + \**********************/ + html5Range : function($cell, indx, def5Range) { + var t, o = $.extend({ + value : 0, + min : 0, + max : 100, + step : 1, + delayed : true, + valueToHeader : true, + exactMatch : true, + compare : '', + allText : 'all', + skipTest : false + }, def5Range), + + // test browser for HTML5 range support + $range = $('').appendTo($cell), + // test if HTML5 range is supported - from Modernizr (but I left out the method to detect in Safari 2-4) + // see https://github.com/Modernizr/Modernizr/blob/master/feature-detects/inputtypes.js + rangeSupported = o.skipTest || $range.attr('type') === 'range' && $range.val() !== 'test', + $shcell = [], + c = $cell.closest('table')[0].config, + + updateRange = function(v, delayed){ + /*jshint eqeqeq:false */ + v = (v + '').replace(/[<>=]/g,'') || o.min; // hidden input changes may include compare symbols + var t = ' (' + (o.compare ? o.compare + v : v == o.min ? o.allText : v) + ')'; + $cell.find('input[type=hidden]') + // add equal to the beginning, so we filter exact numbers + .val( ( o.compare ? o.compare + v : ( v == o.min ? '' : ( o.exactMatch ? '=' : '' ) + v ) ) ) + //( val == o.min ? '' : val + (o.exactMatch ? '=' : '')) + .trigger('search', delayed ? delayed : o.delayed).end() + .find('.range').val(v); + // or add current value to the header cell, if desired + $cell.closest('thead').find('th[data-column=' + indx + ']').find('.curvalue').html(t); + // update sticky header cell + if ($shcell.length) { + $shcell.find('.range').val(v); + $shcell.closest('thead').find('th[data-column=' + indx + ']').find('.curvalue').html(t); + } + }; + $range.remove(); + + if (rangeSupported) { + // add HTML5 range + $cell + .html('') + .closest('thead').find('th[data-column=' + indx + ']') + .addClass('filter-parsed') // get exact numbers from column + // add span to header for the current slider value + .find('.tablesorter-header-inner').append(''); + + $cell.find('.range').bind('change', function(){ + updateRange( this.value ); + }); + + // hidden filter update (.tsfilter) namespace trigger by filter widget + $cell.find('input[type=hidden]').bind('change.tsfilter', function(){ + /*jshint eqeqeq:false */ + var v = this.value; + if (v !== this.lastValue) { + this.lastValue = ( o.compare ? o.compare + v : ( v == o.min ? '' : ( o.exactMatch ? '=' : '' ) + v ) ); + this.value = this.lastValue; + updateRange( v ); + } + }); + + // has sticky headers? + c.$table.bind('stickyHeadersInit', function(){ + $shcell = c.widgetOptions.$sticky.find('.tablesorter-filter-row').children().eq(indx).empty(); + $shcell + .html('') + .find('.range').bind('change', function(){ + updateRange( $shcell.find('.range').val() ); + }); + updateRange( $cell.find('.range').val() ); + }); + + // on reset + $cell.closest('table').bind('filterReset', function(){ + // just turn off the colorpicker + updateRange(o.value); + }); + + updateRange( $cell.find('.range').val() ); + + } + + return rangeSupported ? $cell.find('input[type="hidden"]') : $(''); + }, + + /**********************\ + HTML5 Color picker + \**********************/ + html5Color: function($cell, indx, defColor) { + var t, o = $.extend({ + value : '#000000', + disabled : false, + addToggle : true, + exactMatch : true, + valueToHeader : false, + skipTest : false + }, defColor), + // Add a hidden input to hold the range values + $color = $('').appendTo($cell), + // test if HTML5 color is supported - from Modernizr + colorSupported = o.skipTest || $color.attr('type') === 'color' && $color.val() !== 'test', + $shcell = [], + c = $cell.closest('table')[0].config, + + updateColor = function(v){ + v = v || o.value; + var chkd = true, + t = ' (' + v + ')'; + if (o.addToggle) { + chkd = $cell.find('.toggle').is(':checked'); + } + if ($cell.find('.colorpicker').length) { + $cell.find('.colorpicker').val(v)[0].disabled = (o.disabled || !chkd); + } + + $cell.find('input[type=hidden]') + .val( chkd ? v + (o.exactMatch ? '=' : '') : '' ) + .trigger('search'); + if (o.valueToHeader) { + // add current color to the header cell + $cell.closest('thead').find('th[data-column=' + indx + ']').find('.curcolor').html(t); + } else { + // current color to span in cell + $cell.find('.currentColor').html(t); + } + + // update sticky header cell + if ($shcell.length) { + $shcell.find('.colorpicker').val(v)[0].disabled = (o.disabled || !chkd); + if (o.addToggle) { + $shcell.find('.toggle')[0].checked = chkd; + } + if (o.valueToHeader) { + // add current color to the header cell + $shcell.closest('thead').find('th[data-column=' + indx + ']').find('.curcolor').html(t); + } else { + // current color to span in cell + $shcell.find('.currentColor').html(t); + } + } + }; + $color.remove(); + + if (colorSupported) { + // add HTML5 color picker + t = '
'; + t += o.addToggle ? '
' : ''; + t += ''; + t += (o.valueToHeader ? '' : '(#000000)') + '
'; + $cell.html(t); + + // add span to header for the current color value - only works if the line in the updateColor() function is also un-commented out + if (o.valueToHeader) { + $cell.closest('thead').find('th[data-column=' + indx + ']').find('.tablesorter-header-inner').append(''); + } + + $cell.find('.toggle, .colorpicker').bind('change', function(){ + updateColor( $cell.find('.colorpicker').val() ); + }); + + // hidden filter update (.tsfilter) namespace trigger by filter widget + $cell.find('input[type=hidden]').bind('change.tsfilter', function(){ + updateColor( this.value ); + }); + + // on reset + $cell.closest('table').bind('filterReset', function(){ + // just turn off the colorpicker + $cell.find('.toggle')[0].checked = false; + updateColor( $cell.find('.colorpicker').val() ); + }); + + // has sticky headers? + c.$table.bind('stickyHeadersInit', function(){ + $shcell = c.widgetOptions.$sticky.find('.tablesorter-filter-row').children().eq(indx); + $shcell + .html(t) + .find('.toggle, .colorpicker').bind('change', function(){ + updateColor( $shcell.find('.colorpicker').val() ); + }); + updateColor( $shcell.find('.colorpicker').val() ); + }); + + updateColor( o.value ); + } + return colorSupported ? $cell.find('input[type="hidden"]') : $(''); + } + +}; + +})(jQuery); \ No newline at end of file diff --git a/templates/admin/default/assets/js/tablesorter/jquery.tablesorter.widgets.js b/templates/admin/default/assets/js/tablesorter/jquery.tablesorter.widgets.js new file mode 100644 index 000000000..69c82b62f --- /dev/null +++ b/templates/admin/default/assets/js/tablesorter/jquery.tablesorter.widgets.js @@ -0,0 +1,1208 @@ +/*! tableSorter 2.8+ widgets - updated 6/4/2013 + * + * Column Styles + * Column Filters + * Column Resizing + * Sticky Header + * UI Theme (generalized) + * Save Sort + * [ "columns", "filter", "resizable", "stickyHeaders", "uitheme", "saveSort" ] + */ +/*jshint browser:true, jquery:true, unused:false, loopfunc:true */ +/*global jQuery: false, localStorage: false, navigator: false */ +;(function($){ +"use strict"; +var ts = $.tablesorter = $.tablesorter || {}; + +ts.themes = { + "bootstrap" : { + table : 'table table-bordered table-striped', + header : 'bootstrap-header', // give the header a gradient background + footerRow : '', + footerCells: '', + icons : '', // add "icon-white" to make them white; this icon class is added to the in the header + sortNone : 'bootstrap-icon-unsorted', + sortAsc : 'icon-chevron-up', + sortDesc : 'icon-chevron-down', + active : '', // applied when column is sorted + hover : '', // use custom css here - bootstrap class may not override it + filterRow : '', // filter row class + even : '', // even row zebra striping + odd : '' // odd row zebra striping + }, + "jui" : { + table : 'ui-widget ui-widget-content ui-corner-all', // table classes + header : 'ui-widget-header ui-corner-all ui-state-default', // header classes + footerRow : '', + footerCells: '', + icons : 'ui-icon', // icon class added to the in the header + sortNone : 'ui-icon-carat-2-n-s', + sortAsc : 'ui-icon-carat-1-n', + sortDesc : 'ui-icon-carat-1-s', + active : 'ui-state-active', // applied when column is sorted + hover : 'ui-state-hover', // hover class + filterRow : '', + even : 'ui-widget-content', // even row zebra striping + odd : 'ui-state-default' // odd row zebra striping + } +}; + +// *** Store data in local storage, with a cookie fallback *** +/* IE7 needs JSON library for JSON.stringify - (http://caniuse.com/#search=json) + if you need it, then include https://github.com/douglascrockford/JSON-js + + $.parseJSON is not available is jQuery versions older than 1.4.1, using older + versions will only allow storing information for one page at a time + + // *** Save data (JSON format only) *** + // val must be valid JSON... use http://jsonlint.com/ to ensure it is valid + var val = { "mywidget" : "data1" }; // valid JSON uses double quotes + // $.tablesorter.storage(table, key, val); + $.tablesorter.storage(table, 'tablesorter-mywidget', val); + + // *** Get data: $.tablesorter.storage(table, key); *** + v = $.tablesorter.storage(table, 'tablesorter-mywidget'); + // val may be empty, so also check for your data + val = (v && v.hasOwnProperty('mywidget')) ? v.mywidget : ''; + alert(val); // "data1" if saved, or "" if not +*/ +ts.storage = function(table, key, val){ + var d, k, ls = false, v = {}, + id = table.id || $('.tablesorter').index( $(table) ), + url = window.location.pathname; + // https://gist.github.com/paulirish/5558557 + if ("localStorage" in window) { + try { + window.localStorage.setItem('_tmptest', 'temp'); + ls = true; + window.localStorage.removeItem('_tmptest'); + } catch(e) {} + } + // *** get val *** + if ($.parseJSON){ + if (ls){ + v = $.parseJSON(localStorage[key] || '{}'); + } else { + k = document.cookie.split(/[;\s|=]/); // cookie + d = $.inArray(key, k) + 1; // add one to get from the key to the value + v = (d !== 0) ? $.parseJSON(k[d] || '{}') : {}; + } + } + // allow val to be an empty string to + if ((val || val === '') && window.JSON && JSON.hasOwnProperty('stringify')){ + // add unique identifiers = url pathname > table ID/index on page > data + if (!v[url]) { + v[url] = {}; + } + v[url][id] = val; + // *** set val *** + if (ls){ + localStorage[key] = JSON.stringify(v); + } else { + d = new Date(); + d.setTime(d.getTime() + (31536e+6)); // 365 days + document.cookie = key + '=' + (JSON.stringify(v)).replace(/\"/g,'\"') + '; expires=' + d.toGMTString() + '; path=/'; + } + } else { + return v && v[url] ? v[url][id] : {}; + } +}; + +// Add a resize event to table headers +// ************************** +ts.addHeaderResizeEvent = function(table, disable, options){ + var defaults = { + timer : 250 + }, + o = $.extend({}, defaults, options), + c = table.config, + wo = c.widgetOptions, + headers, + checkSizes = function(){ + wo.resize_flag = true; + headers = []; + c.$headers.each(function(){ + var d = $.data(this, 'savedSizes'), + w = this.offsetWidth, + h = this.offsetHeight; + if (w !== d[0] || h !== d[1]) { + $.data(this, 'savedSizes', [ w, h ]); + headers.push(this); + } + }); + if (headers.length) { c.$table.trigger('resize', [ headers ]); } + wo.resize_flag = false; + }; + clearInterval(wo.resize_timer); + if (disable) { + wo.resize_flag = false; + return false; + } + c.$headers.each(function(){ + $.data(this, 'savedSizes', [ this.offsetWidth, this.offsetHeight ]); + }); + wo.resize_timer = setInterval(function(){ + if (wo.resize_flag) { return; } + checkSizes(); + }, o.timer); +}; + +// Widget: General UI theme +// "uitheme" option in "widgetOptions" +// ************************** +ts.addWidget({ + id: "uitheme", + priority: 10, + options: { + uitheme : 'jui' + }, + format: function(table, c, wo){ + var time, klass, $el, $tar, + t = ts.themes, + $t = c.$table, + theme = c.theme !== 'default' ? c.theme : wo.uitheme || 'jui', + o = t[ t[theme] ? theme : t[wo.uitheme] ? wo.uitheme : 'jui'], + $h = c.$headers, + sh = 'tr.' + (wo.stickyHeaders || 'tablesorter-stickyHeader'), + rmv = o.sortNone + ' ' + o.sortDesc + ' ' + o.sortAsc; + if (c.debug) { time = new Date(); } + if (!$t.hasClass('tablesorter-' + theme) || c.theme === theme || !table.hasInitialized){ + // update zebra stripes + if (o.even !== '') { wo.zebra[0] += ' ' + o.even; } + if (o.odd !== '') { wo.zebra[1] += ' ' + o.odd; } + // add table/footer class names + t = $t + // remove other selected themes; use widgetOptions.theme_remove + .removeClass( c.theme === '' ? '' : 'tablesorter-' + c.theme ) + .addClass('tablesorter-' + theme + ' ' + o.table) // add theme widget class name + .find('tfoot'); + if (t.length) { + t + .find('tr').addClass(o.footerRow) + .children('th, td').addClass(o.footerCells); + } + // update header classes + $h + .addClass(o.header) + .filter(':not(.sorter-false)') + .bind('mouseenter.tsuitheme mouseleave.tsuitheme', function(e){ + // toggleClass with switch added in jQuery 1.3 + $(this)[ e.type === 'mouseenter' ? 'addClass' : 'removeClass' ](o.hover); + }); + if (!$h.find('.tablesorter-wrapper').length) { + // Firefox needs this inner div to position the resizer correctly + $h.wrapInner('
'); + } + if (c.cssIcon){ + // if c.cssIcon is '', then no is added to the header + $h.find('.' + c.cssIcon).addClass(o.icons); + } + if ($t.hasClass('hasFilters')){ + $h.find('.tablesorter-filter-row').addClass(o.filterRow); + } + } + $.each($h, function(i){ + $el = $(this); + $tar = (c.cssIcon) ? $el.find('.' + c.cssIcon) : $el; + if (this.sortDisabled){ + // no sort arrows for disabled columns! + $el.removeClass(rmv); + $tar.removeClass(rmv + ' tablesorter-icon ' + o.icons); + } else { + t = ($t.hasClass('hasStickyHeaders')) ? $t.find(sh).find('th').eq(i).add($el) : $el; + klass = ($el.hasClass(c.cssAsc)) ? o.sortAsc : ($el.hasClass(c.cssDesc)) ? o.sortDesc : $el.hasClass(c.cssHeader) ? o.sortNone : ''; + $el[klass === o.sortNone ? 'removeClass' : 'addClass'](o.active); + $tar.removeClass(rmv).addClass(klass); + } + }); + if (c.debug){ + ts.benchmark("Applying " + theme + " theme", time); + } + }, + remove: function(table, c, wo){ + var $t = c.$table, + theme = typeof wo.uitheme === 'object' ? 'jui' : wo.uitheme || 'jui', + o = typeof wo.uitheme === 'object' ? wo.uitheme : ts.themes[ ts.themes.hasOwnProperty(theme) ? theme : 'jui'], + $h = $t.children('thead').children(), + rmv = o.sortNone + ' ' + o.sortDesc + ' ' + o.sortAsc; + $t + .removeClass('tablesorter-' + theme + ' ' + o.table) + .find(c.cssHeader).removeClass(o.header); + $h + .unbind('mouseenter.tsuitheme mouseleave.tsuitheme') // remove hover + .removeClass(o.hover + ' ' + rmv + ' ' + o.active) + .find('.tablesorter-filter-row').removeClass(o.filterRow); + $h.find('.tablesorter-icon').removeClass(o.icons); + } +}); + +// Widget: Column styles +// "columns", "columns_thead" (true) and +// "columns_tfoot" (true) options in "widgetOptions" +// ************************** +ts.addWidget({ + id: "columns", + priority: 30, + options : { + columns : [ "primary", "secondary", "tertiary" ] + }, + format: function(table, c, wo){ + var $tb, $tr, $td, $t, time, last, rmv, i, k, l, + $tbl = c.$table, + b = c.$tbodies, + list = c.sortList, + len = list.length, + // keep backwards compatibility, for now + css = (c.widgetColumns && c.widgetColumns.hasOwnProperty('css')) ? c.widgetColumns.css || css : + (wo && wo.hasOwnProperty('columns')) ? wo.columns || css : css; + last = css.length-1; + rmv = css.join(' '); + if (c.debug){ + time = new Date(); + } + // check if there is a sort (on initialization there may not be one) + for (k = 0; k < b.length; k++ ){ + $tb = ts.processTbody(table, b.eq(k), true); // detach tbody + $tr = $tb.children('tr'); + l = $tr.length; + // loop through the visible rows + $tr.each(function(){ + $t = $(this); + if (this.style.display !== 'none'){ + // remove all columns class names + $td = $t.children().removeClass(rmv); + // add appropriate column class names + if (list && list[0]){ + // primary sort column class + $td.eq(list[0][0]).addClass(css[0]); + if (len > 1){ + for (i = 1; i < len; i++){ + // secondary, tertiary, etc sort column classes + $td.eq(list[i][0]).addClass( css[i] || css[last] ); + } + } + } + } + }); + ts.processTbody(table, $tb, false); + } + // add classes to thead and tfoot + $tr = wo.columns_thead !== false ? 'thead tr' : ''; + if (wo.columns_tfoot !== false) { + $tr += ($tr === '' ? '' : ',') + 'tfoot tr'; + } + if ($tr.length) { + $t = $tbl.find($tr).children().removeClass(rmv); + if (list && list[0]){ + // primary sort column class + $t.filter('[data-column="' + list[0][0] + '"]').addClass(css[0]); + if (len > 1){ + for (i = 1; i < len; i++){ + // secondary, tertiary, etc sort column classes + $t.filter('[data-column="' + list[i][0] + '"]').addClass(css[i] || css[last]); + } + } + } + } + if (c.debug){ + ts.benchmark("Applying Columns widget", time); + } + }, + remove: function(table, c, wo){ + var k, $tb, + b = c.$tbodies, + rmv = (wo.columns || [ "primary", "secondary", "tertiary" ]).join(' '); + c.$headers.removeClass(rmv); + c.$table.children('tfoot').children('tr').children('th, td').removeClass(rmv); + for (k = 0; k < b.length; k++ ){ + $tb = ts.processTbody(table, b.eq(k), true); // remove tbody + $tb.children('tr').each(function(){ + $(this).children().removeClass(rmv); + }); + ts.processTbody(table, $tb, false); // restore tbody + } + } +}); + +// Widget: filter +// ************************** +ts.addWidget({ + id: "filter", + priority: 50, + options : { + filter_childRows : false, // if true, filter includes child row content in the search + filter_columnFilters : true, // if true, a filter will be added to the top of each table column + filter_cssFilter : 'tablesorter-filter', // css class name added to the filter row & each input in the row + filter_filteredRow : 'filtered', // class added to filtered rows; needed by pager plugin + filter_formatter : null, // add custom filter elements to the filter row + filter_functions : null, // add custom filter functions using this option + filter_hideFilters : false, // collapse filter row when mouse leaves the area + filter_ignoreCase : true, // if true, make all searches case-insensitive + filter_liveSearch : true, // if true, search column content while the user types (with a delay) + filter_onlyAvail : 'filter-onlyAvail', // a header with a select dropdown & this class name will only show available (visible) options within the drop down + filter_reset : null, // jQuery selector string of an element used to reset the filters + filter_searchDelay : 300, // typing delay in milliseconds before starting a search + filter_startsWith : false, // if true, filter start from the beginning of the cell contents + filter_useParsedData : false, // filter all data using parsed content + filter_serversideFiltering : false, // if true, server-side filtering should be performed because client-side filtering will be disabled, but the ui and events will still be used. + filter_defaultAttrib : 'data-value', // data attribute in the header cell that contains the default filter value + + // regex used in filter "check" functions - not for general use and not documented + filter_regex : { + "regex" : /^\/((?:\\\/|[^\/])+)\/([mig]{0,3})?$/, // regex to test for regex + "child" : /tablesorter-childRow/, // child row class name; this gets updated in the script + "filtered" : /filtered/, // filtered (hidden) row class name; updated in the script + "type" : /undefined|number/, // check type + "exact" : /(^[\"|\'|=])|([\"|\'|=]$)/g, // exact match + "nondigit" : /[^\w,. \-()]/g, // replace non-digits (from digit & currency parser) + "operators" : /[<>=]/g // replace operators + } + }, + format: function(table, c, wo){ + if (c.parsers && !c.$table.hasClass('hasFilters')){ + var i, j, k, l, val, ff, x, xi, st, sel, str, + ft, ft2, $th, rg, s, t, dis, col, + fmt = ts.formatFloat, + last = '', // save last filter search + $ths = c.$headers, + css = wo.filter_cssFilter, + $t = c.$table.addClass('hasFilters'), + b = $t.find('tbody'), + cols = c.parsers.length, + parsed, time, timer, + + // dig fer gold + checkFilters = function(filter){ + var arry = $.isArray(filter), + v = (arry) ? filter : ts.getFilters(table), + cv = (v || []).join(''); // combined filter values + // add filter array back into inputs + if (arry) { + ts.setFilters( $t, v ); + } + if (wo.filter_hideFilters){ + // show/hide filter row as needed + $t.find('.tablesorter-filter-row').trigger( cv === '' ? 'mouseleave' : 'mouseenter' ); + } + // return if the last search is the same; but filter === false when updating the search + // see example-widget-filter.html filter toggle buttons + if (last === cv && filter !== false) { return; } + $t.trigger('filterStart', [v]); + if (c.showProcessing) { + // give it time for the processing icon to kick in + setTimeout(function(){ + findRows(filter, v, cv); + return false; + }, 30); + } else { + findRows(filter, v, cv); + return false; + } + }, + findRows = function(filter, v, cv){ + var $tb, $tr, $td, cr, r, l, ff, time, r1, r2, searchFiltered; + if (c.debug) { time = new Date(); } + for (k = 0; k < b.length; k++ ){ + if (b.eq(k).hasClass(c.cssInfoBlock)) { continue; } // ignore info blocks, issue #264 + $tb = ts.processTbody(table, b.eq(k), true); + $tr = $tb.children('tr:not(.' + c.cssChildRow + ')'); + l = $tr.length; + if (cv === '' || wo.filter_serversideFiltering){ + $tb.children().show().removeClass(wo.filter_filteredRow); + } else { + // optimize searching only through already filtered rows - see #313 + searchFiltered = true; + r = $t.data('lastSearch') || []; + $.each(v, function(i,val){ + // check for changes from beginning of filter; but ignore if there is a logical "or" in the string + searchFiltered = (val || '').indexOf(r[i] || '') === 0 && searchFiltered && !/(\s+or\s+|\|)/g.test(val || ''); + }); + // can't search when all rows are hidden - this happens when looking for exact matches + if (searchFiltered && $tr.filter(':visible').length === 0) { searchFiltered = false; } + // loop through the rows + for (j = 0; j < l; j++){ + r = $tr[j].className; + // skip child rows & already filtered rows + if ( wo.filter_regex.child.test(r) || (searchFiltered && wo.filter_regex.filtered.test(r)) ) { continue; } + r = true; + cr = $tr.eq(j).nextUntil('tr:not(.' + c.cssChildRow + ')'); + // so, if "table.config.widgetOptions.filter_childRows" is true and there is + // a match anywhere in the child row, then it will make the row visible + // checked here so the option can be changed dynamically + t = (cr.length && wo.filter_childRows) ? cr.text() : ''; + t = wo.filter_ignoreCase ? t.toLocaleLowerCase() : t; + $td = $tr.eq(j).children('td'); + for (i = 0; i < cols; i++){ + // ignore if filter is empty or disabled + if (v[i]){ + // check if column data should be from the cell or from parsed data + if (wo.filter_useParsedData || parsed[i]){ + x = c.cache[k].normalized[j][i]; + } else { + // using older or original tablesorter + x = $.trim($td.eq(i).text()); + } + xi = !wo.filter_regex.type.test(typeof x) && wo.filter_ignoreCase ? x.toLocaleLowerCase() : x; + ff = r; // if r is true, show that row + // val = case insensitive, v[i] = case sensitive + val = wo.filter_ignoreCase ? v[i].toLocaleLowerCase() : v[i]; + if (wo.filter_functions && wo.filter_functions[i]){ + if (wo.filter_functions[i] === true){ + // default selector; no "filter-select" class + ff = ($ths.filter('[data-column="' + i + '"]:last').hasClass('filter-match')) ? xi.search(val) >= 0 : v[i] === x; + } else if (typeof wo.filter_functions[i] === 'function'){ + // filter callback( exact cell content, parser normalized content, filter input value, column index ) + ff = wo.filter_functions[i](x, c.cache[k].normalized[j][i], v[i], i); + } else if (typeof wo.filter_functions[i][v[i]] === 'function'){ + // selector option function + ff = wo.filter_functions[i][v[i]](x, c.cache[k].normalized[j][i], v[i], i); + } + // Look for regex + } else if (wo.filter_regex.regex.test(val)){ + rg = wo.filter_regex.regex.exec(val); + try { + ff = new RegExp(rg[1], rg[2]).test(xi); + } catch (err){ + ff = false; + } + // Look for quotes or equals to get an exact match; ignore type since xi could be numeric + /*jshint eqeqeq:false */ + } else if (val.replace(wo.filter_regex.exact, '') == xi){ + ff = true; + // Look for a not match + } else if (/^\!/.test(val)){ + val = val.replace('!',''); + s = xi.search($.trim(val)); + ff = val === '' ? true : !(wo.filter_startsWith ? s === 0 : s >= 0); + // Look for operators >, >=, < or <= + } else if (/^[<>]=?/.test(val)){ + s = fmt(val.replace(wo.filter_regex.nondigit, '').replace(wo.filter_regex.operators,''), table); + // parse filter value in case we're comparing numbers (dates) + if (parsed[i] || c.parsers[i].type === 'numeric') { + rg = c.parsers[i].format('' + val.replace(wo.filter_regex.operators,''), table, $ths.eq(i), i); + s = (rg !== '' && !isNaN(rg)) ? rg : s; + } + // xi may be numeric - see issue #149; + // check if c.cache[k].normalized[j] is defined, because sometimes j goes out of range? (numeric columns) + rg = ( parsed[i] || c.parsers[i].type === 'numeric' ) && !isNaN(s) && c.cache[k].normalized[j] ? c.cache[k].normalized[j][i] : + isNaN(xi) ? fmt(xi.replace(wo.filter_regex.nondigit, ''), table) : fmt(xi, table); + if (/>/.test(val)) { ff = />=/.test(val) ? rg >= s : rg > s; } + if (/= 0; + r1 = s.length - 1; + while (ff && r1) { + ff = ff && xi.search($.trim(s[r1])) >= 0; + r1--; + } + // Look for a range (using " to " or " - ") - see issue #166; thanks matzhu! + } else if (/\s+(-|to)\s+/.test(val)){ + s = val.split(/(?: - | to )/); // make sure the dash is for a range and not indicating a negative number + r1 = fmt(s[0].replace(wo.filter_regex.nondigit, ''), table); + r2 = fmt(s[1].replace(wo.filter_regex.nondigit, ''), table); + // parse filter value in case we're comparing numbers (dates) + if (parsed[i] || c.parsers[i].type === 'numeric') { + rg = c.parsers[i].format('' + s[0], table, $ths.eq(i), i); + r1 = (rg !== '' && !isNaN(rg)) ? rg : r1; + rg = c.parsers[i].format('' + s[1], table, $ths.eq(i), i); + r2 = (rg !== '' && !isNaN(rg)) ? rg : r2; + } + rg = ( parsed[i] || c.parsers[i].type === 'numeric' ) && !isNaN(r1) && !isNaN(r2) ? c.cache[k].normalized[j][i] : + isNaN(xi) ? fmt(xi.replace(wo.filter_regex.nondigit, ''), table) : fmt(xi, table); + if (r1 > r2) { ff = r1; r1 = r2; r2 = ff; } // swap + ff = (rg >= r1 && rg <= r2) || (r1 === '' || r2 === '') ? true : false; + // Look for wild card: ? = single, * = multiple, or | = logical OR + } else if ( /[\?|\*]/.test(val) || /\s+OR\s+/.test(v[i]) ){ + s = val.replace(/\s+OR\s+/gi,"|"); + // look for an exact match with the "or" unless the "filter-match" class is found + if (!$ths.filter('[data-column="' + i + '"]:last').hasClass('filter-match') && /\|/.test(s)) { + s = '^(' + s + ')$'; + } + ff = new RegExp( s.replace(/\?/g, '\\S{1}').replace(/\*/g, '\\S*') ).test(xi); + // Look for match, and add child row data for matching + } else { + x = (xi + t).indexOf(val); + ff = ( (!wo.filter_startsWith && x >= 0) || (wo.filter_startsWith && x === 0) ); + } + r = (ff) ? (r ? true : false) : false; + } + } + $tr[j].style.display = (r ? '' : 'none'); + $tr.eq(j)[r ? 'removeClass' : 'addClass'](wo.filter_filteredRow); + if (cr.length) { cr[r ? 'show' : 'hide'](); } + } + } + ts.processTbody(table, $tb, false); + } + last = cv; // save last search + $t.data('lastSearch', v); + if (c.debug){ + ts.benchmark("Completed filter widget search", time); + } + $t.trigger('applyWidgets'); // make sure zebra widget is applied + $t.trigger('filterEnd'); + }, + buildSelect = function(i, updating, onlyavail){ + var o, t, arry = [], currentVal; + i = parseInt(i, 10); + t = $ths.filter('[data-column="' + i + '"]:last'); + // t.data('placeholder') won't work in jQuery older than 1.4.3 + o = ''; + for (k = 0; k < b.length; k++ ){ + l = c.cache[k].row.length; + // loop through the rows + for (j = 0; j < l; j++){ + // check if has class filtered + if (onlyavail && c.cache[k].row[j][0].className.match(wo.filter_filteredRow)) { continue; } + // get non-normalized cell content + if (wo.filter_useParsedData){ + arry.push( '' + c.cache[k].normalized[j][i] ); + } else { + t = c.cache[k].row[j][0].cells[i]; + if (t){ + arry.push( $.trim(c.supportsTextContent ? t.textContent : $(t).text()) ); + } + } + } + } + + // get unique elements and sort the list + // if $.tablesorter.sortText exists (not in the original tablesorter), + // then natural sort the list otherwise use a basic sort + arry = $.grep(arry, function(v, k){ + return $.inArray(v, arry) === k; + }); + arry = (ts.sortText) ? arry.sort(function(a, b){ return ts.sortText(table, a, b, i); }) : arry.sort(true); + + // Get curent filter value + currentVal = $t.find('thead').find('select.' + css + '[data-column="' + i + '"]').val(); + + // build option list + for (k = 0; k < arry.length; k++){ + t = arry[k].replace(/\"/g, """); + // replace quotes - fixes #242 & ignore empty strings - see http://stackoverflow.com/q/14990971/145346 + o += arry[k] !== '' ? '' : ''; + } + $t.find('thead').find('select.' + css + '[data-column="' + i + '"]')[ updating ? 'html' : 'append' ](o); + }, + buildDefault = function(updating){ + // build default select dropdown + for (i = 0; i < cols; i++){ + t = $ths.filter('[data-column="' + i + '"]:last'); + // look for the filter-select class; build/update it if found + if ((t.hasClass('filter-select') || wo.filter_functions && wo.filter_functions[i] === true) && !t.hasClass('filter-false')){ + if (!wo.filter_functions) { wo.filter_functions = {}; } + wo.filter_functions[i] = true; // make sure this select gets processed by filter_functions + buildSelect(i, updating, t.hasClass(wo.filter_onlyAvail)); + } + } + }, + searching = function(filter){ + if (typeof filter === 'undefined' || filter === true){ + // delay filtering + clearTimeout(timer); + timer = setTimeout(function(){ + checkFilters(filter); + }, wo.filter_liveSearch ? wo.filter_searchDelay : 10); + } else { + // skip delay + checkFilters(filter); + } + }; + if (c.debug){ + time = new Date(); + } + wo.filter_regex.child = new RegExp(c.cssChildRow); + wo.filter_regex.filtered = new RegExp(wo.filter_filteredRow); + // don't build filter row if columnFilters is false or all columns are set to "filter-false" - issue #156 + if (wo.filter_columnFilters !== false && $ths.filter('.filter-false').length !== $ths.length){ + // build filter row + t = ''; + for (i = 0; i < cols; i++){ + t += ''; + } + c.$filters = $(t += '').appendTo( $t.find('thead').eq(0) ).find('td'); + // build each filter input + for (i = 0; i < cols; i++){ + dis = false; + $th = $ths.filter('[data-column="' + i + '"]:last'); // assuming last cell of a column is the main column + sel = (wo.filter_functions && wo.filter_functions[i] && typeof wo.filter_functions[i] !== 'function') || $th.hasClass('filter-select'); + // use header option - headers: { 1: { filter: false } } OR add class="filter-false" + if (ts.getData){ + // get data from jQuery data, metadata, headers option or header class name + dis = ts.getData($th[0], c.headers[i], 'filter') === 'false'; + } else { + // only class names and header options - keep this for compatibility with tablesorter v2.0.5 + dis = (c.headers[i] && c.headers[i].hasOwnProperty('filter') && c.headers[i].filter === false) || $th.hasClass('filter-false'); + } + + if (sel){ + t = $('').appendTo( c.$filters.eq(i) ); + } + if (t) { + t.attr('placeholder', $th.data('placeholder') || $th.attr('data-placeholder') || ''); + } + } + if (t) { + t.addClass(css).attr('data-column', i); + if (dis) { + t.addClass('disabled')[0].disabled = true; // disabled! + } + } + } + } + $t + .bind('addRows updateCell update updateRows updateComplete appendCache filterReset filterEnd search '.split(' ').join('.tsfilter '), function(e, filter){ + if (!/(search|filterReset|filterEnd)/.test(e.type)){ + e.stopPropagation(); + buildDefault(true); + } + if (e.type === 'filterReset') { + $t.find('.' + css).val(''); + } + if (e.type === 'filterEnd') { + buildDefault(true); + } else { + // send false argument to force a new search; otherwise if the filter hasn't changed, it will return + filter = e.type === 'search' ? filter : e.type === 'updateComplete' ? $t.data('lastSearch') : ''; + searching(filter); + } + return false; + }) + .find('input.' + css).bind('keyup search', function(e, filter){ + // emulate what webkit does.... escape clears the filter + if (e.which === 27) { + this.value = ''; + // liveSearch can contain a min value length; ignore arrow and meta keys, but allow backspace + } else if ( (typeof wo.filter_liveSearch === 'number' && this.value.length < wo.filter_liveSearch && this.value !== '') || ( e.type === 'keyup' && + ( (e.which < 32 && e.which !== 8 && wo.filter_liveSearch === true && e.which !== 13) || (e.which >= 37 && e.which <=40) || (e.which !== 13 && wo.filter_liveSearch === false) ) ) ) { + return; + } + searching(filter); + }); + + // parse columns after formatter, in case the class is added at that point + parsed = $ths.map(function(i){ + return (ts.getData) ? ts.getData($ths.filter('[data-column="' + i + '"]:last'), c.headers[i], 'filter') === 'parsed' : $(this).hasClass('filter-parsed'); + }).get(); + + // reset button/link + if (wo.filter_reset && $(wo.filter_reset).length){ + $(wo.filter_reset).bind('click.tsfilter', function(){ + $t.trigger('filterReset'); + }); + } + if (wo.filter_functions){ + // i = column # (string) + for (col in wo.filter_functions){ + if (wo.filter_functions.hasOwnProperty(col) && typeof col === 'string'){ + t = $ths.filter('[data-column="' + col + '"]:last'); + ff = ''; + if (wo.filter_functions[col] === true && !t.hasClass('filter-false')){ + buildSelect(col); + } else if (typeof col === 'string' && !t.hasClass('filter-false')){ + // add custom drop down list + for (str in wo.filter_functions[col]){ + if (typeof str === 'string'){ + ff += ff === '' ? '' : ''; + ff += ''; + } + } + $t.find('thead').find('select.' + css + '[data-column="' + col + '"]').append(ff); + } + } + } + } + // not really updating, but if the column has both the "filter-select" class & filter_functions set to true, + // it would append the same options twice. + buildDefault(true); + + $t.find('select.' + css).bind('change search', function(e, filter){ + checkFilters(filter); + }); + + if (wo.filter_hideFilters){ + $t + .find('.tablesorter-filter-row') + .addClass('hideme') + .bind('mouseenter mouseleave', function(e){ + // save event object - http://bugs.jquery.com/ticket/12140 + var all, evt = e; + ft = $(this); + clearTimeout(st); + st = setTimeout(function(){ + if (/enter|over/.test(evt.type)){ + ft.removeClass('hideme'); + } else { + // don't hide if input has focus + // $(':focus') needs jQuery 1.6+ + if ($(document.activeElement).closest('tr')[0] !== ft[0]){ + // get all filter values + all = $t.find('.' + wo.filter_cssFilter).map(function(){ + return $(this).val() || ''; + }).get().join(''); + // don't hide row if any filter has a value + if (all === ''){ + ft.addClass('hideme'); + } + } + } + }, 200); + }) + .find('input, select').bind('focus blur', function(e){ + ft2 = $(this).closest('tr'); + clearTimeout(st); + st = setTimeout(function(){ + // don't hide row if any filter has a value + if ($t.find('.' + wo.filter_cssFilter).map(function(){ return $(this).val() || ''; }).get().join('') === ''){ + ft2[ e.type === 'focus' ? 'removeClass' : 'addClass']('hideme'); + } + }, 200); + }); + } + + // show processing icon + if (c.showProcessing) { + $t.bind('filterStart.tsfilter filterEnd.tsfilter', function(e, v) { + var fc = (v) ? $t.find('.' + c.cssHeader).filter('[data-column]').filter(function(){ + return v[$(this).data('column')] !== ''; + }) : ''; + ts.isProcessing($t[0], e.type === 'filterStart', v ? fc : ''); + }); + } + + if (c.debug){ + ts.benchmark("Applying Filter widget", time); + } + // add default values + $t.bind('tablesorter-initialized', function(){ + ff = ts.getFilters(table); + for (i = 0; i < ff.length; i++) { + ff[i] = $ths.filter('[data-column="' + i + '"]:last').attr(wo.filter_defaultAttrib) || ff[i]; + } + ts.setFilters(table, ff, true); + }); + // filter widget initialized + $t.trigger('filterInit'); + checkFilters(); + } + }, + remove: function(table, c, wo){ + var k, $tb, + $t = c.$table, + b = c.$tbodies; + $t + .removeClass('hasFilters') + // add .tsfilter namespace to all BUT search + .unbind('addRows updateCell update updateComplete appendCache search filterStart filterEnd '.split(' ').join('.tsfilter ')) + .find('.tablesorter-filter-row').remove(); + for (k = 0; k < b.length; k++ ){ + $tb = ts.processTbody(table, b.eq(k), true); // remove tbody + $tb.children().removeClass(wo.filter_filteredRow).show(); + ts.processTbody(table, $tb, false); // restore tbody + } + if (wo.filterreset) { $(wo.filter_reset).unbind('click.tsfilter'); } + } +}); +ts.getFilters = function(table) { + var c = table ? $(table)[0].config : {}; + if (c && c.widgetOptions && !c.widgetOptions.filter_columnFilters) { return $(table).data('lastSearch'); } + return c && c.$filters ? c.$filters.find('.' + c.widgetOptions.filter_cssFilter).map(function(i, el) { + return $(el).val(); + }).get() || [] : false; +}; +ts.setFilters = function(table, filter, apply) { + var $t = $(table), + c = $t.length ? $t[0].config : {}, + valid = c && c.$filters ? c.$filters.find('.' + c.widgetOptions.filter_cssFilter).each(function(i, el) { + $(el).val(filter[i] || ''); + }).trigger('change.tsfilter') || false : false; + if (apply) { $t.trigger('search', [filter, false]); } + return !!valid; +}; + +// Widget: Sticky headers +// based on this awesome article: +// http://css-tricks.com/13465-persistent-headers/ +// and https://github.com/jmosbech/StickyTableHeaders by Jonas Mosbech +// ************************** +ts.addWidget({ + id: "stickyHeaders", + priority: 60, + options: { + stickyHeaders : 'tablesorter-stickyHeader', + stickyHeaders_offset : 0, // number or jquery selector targeting the position:fixed element + stickyHeaders_cloneId : '-sticky', // added to table ID, if it exists + stickyHeaders_addResizeEvent : true, // trigger "resize" event on headers + stickyHeaders_includeCaption : true // if false and a caption exist, it won't be included in the sticky header + }, + format: function(table, c, wo){ + if (c.$table.hasClass('hasStickyHeaders')) { return; } + var $t = c.$table, + $win = $(window), + header = $t.children('thead:first'), + hdrCells = header.children('tr:not(.sticky-false)').children(), + innr = '.tablesorter-header-inner', + tfoot = $t.find('tfoot'), + filterInputs = '.' + (wo.filter_cssFilter || 'tablesorter-filter'), + $stickyOffset = isNaN(wo.stickyHeaders_offset) ? $(wo.stickyHeaders_offset) : '', + stickyOffset = $stickyOffset.length ? $stickyOffset.height() || 0 : parseInt(wo.stickyHeaders_offset, 10) || 0, + $stickyTable = wo.$sticky = $t.clone() + .addClass('containsStickyHeaders') + .css({ + position : 'fixed', + margin : 0, + top : stickyOffset, + visibility : 'hidden', + zIndex : 2 + }), + stkyHdr = $stickyTable.children('thead:first').addClass(wo.stickyHeaders), + stkyCells, + laststate = '', + spacing = 0, + flag = false, + resizeHdr = function(){ + stickyOffset = $stickyOffset.length ? $stickyOffset.height() || 0 : parseInt(wo.stickyHeaders_offset, 10) || 0; + var bwsr = navigator.userAgent; + spacing = 0; + // yes, I dislike browser sniffing, but it really is needed here :( + // webkit automatically compensates for border spacing + if ($t.css('border-collapse') !== 'collapse' && !/(webkit|msie)/i.test(bwsr)) { + // Firefox & Opera use the border-spacing + // update border-spacing here because of demos that switch themes + spacing = parseInt(hdrCells.eq(0).css('border-left-width'), 10) * 2; + } + $stickyTable.css({ + left : header.offset().left - $win.scrollLeft() - spacing, + width: $t.width() + }); + stkyCells.filter(':visible').each(function(i){ + var $h = hdrCells.filter(':visible').eq(i); + $(this) + .css({ + width: $h.width() - spacing, + height: $h.height() + }) + .find(innr).width( $h.find(innr).width() ); + }); + }; + // fix clone ID, if it exists - fixes #271 + if ($stickyTable.attr('id')) { $stickyTable[0].id += wo.stickyHeaders_cloneId; } + // clear out cloned table, except for sticky header + // include caption & filter row (fixes #126 & #249) + $stickyTable.find('thead:gt(0), tr.sticky-false, tbody, tfoot').remove(); + if (!wo.stickyHeaders_includeCaption) { + $stickyTable.find('caption').remove(); + } + // issue #172 - find td/th in sticky header + stkyCells = stkyHdr.children().children(); + $stickyTable.css({ height:0, width:0, padding:0, margin:0, border:0 }); + // remove resizable block + stkyCells.find('.tablesorter-resizer').remove(); + // update sticky header class names to match real header after sorting + $t + .addClass('hasStickyHeaders') + .bind('sortEnd.tsSticky', function(){ + hdrCells.filter(':visible').each(function(i){ + var t = stkyCells.filter(':visible').eq(i); + t + .attr('class', $(this).attr('class')) + // remove processing icon + .removeClass(c.cssProcessing); + if (c.cssIcon){ + t + .find('.' + c.cssIcon) + .attr('class', $(this).find('.' + c.cssIcon).attr('class')); + } + }); + }) + .bind('pagerComplete.tsSticky', function(){ + resizeHdr(); + }); + // http://stackoverflow.com/questions/5312849/jquery-find-self; + hdrCells.find(c.selectorSort).add( c.$headers.filter(c.selectorSort) ).each(function(i){ + var t = $(this), + // clicking on sticky will trigger sort + $cell = stkyHdr.children('tr.tablesorter-headerRow').children().eq(i).bind('mouseup', function(e){ + t.trigger(e, true); // external mouseup flag (click timer is ignored) + }); + // prevent sticky header text selection + if (c.cancelSelection) { + $cell + .attr('unselectable', 'on') + .bind('selectstart', false) + .css({ + 'user-select': 'none', + 'MozUserSelect': 'none' + }); + } + }); + // add stickyheaders AFTER the table. If the table is selected by ID, the original one (first) will be returned. + $t.after( $stickyTable ); + // make it sticky! + $win.bind('scroll.tsSticky resize.tsSticky', function(e){ + if (!$t.is(':visible')) { return; } // fixes #278 + var pre = 'tablesorter-sticky-', + offset = $t.offset(), + cap = -(wo.stickyHeaders_includeCaption ? 0 : $t.find('caption').height()), + sTop = $win.scrollTop() + stickyOffset, + tableHt = $t.height() - ($stickyTable.height() + (tfoot.height() || 0)), + vis = (sTop > offset.top - cap) && (sTop < offset.top - cap + tableHt) ? 'visible' : 'hidden'; + $stickyTable + .removeClass(pre + 'visible ' + pre + 'hidden') + .addClass(pre + vis) + .css({ + // adjust when scrolling horizontally - fixes issue #143 + left : header.offset().left - $win.scrollLeft() - spacing, + visibility : vis + }); + if (vis !== laststate || e.type === 'resize'){ + // make sure the column widths match + resizeHdr(); + laststate = vis; + } + }); + if (wo.stickyHeaders_addResizeEvent) { + ts.addHeaderResizeEvent(table); + } + + // look for filter widget + $t.bind('filterEnd', function(){ + if (flag) { return; } + stkyHdr.find('.tablesorter-filter-row').children().each(function(i){ + $(this).find(filterInputs).val( c.$filters.find(filterInputs).eq(i).val() ); + }); + }); + stkyCells.find(filterInputs).bind('keyup search change', function(e){ + // ignore arrow and meta keys; allow backspace + if ((e.which < 32 && e.which !== 8) || (e.which >= 37 && e.which <=40)) { return; } + flag = true; + var $f = $(this), col = $f.attr('data-column'); + c.$filters.find(filterInputs).eq(col) + .val( $f.val() ) + .trigger('search'); + setTimeout(function(){ + flag = false; + }, wo.filter_searchDelay); + }); + $t.trigger('stickyHeadersInit'); + + }, + remove: function(table, c, wo){ + c.$table + .removeClass('hasStickyHeaders') + .unbind('sortEnd.tsSticky pagerComplete.tsSticky') + .find('.' + wo.stickyHeaders).remove(); + if (wo.$sticky && wo.$sticky.length) { wo.$sticky.remove(); } // remove cloned table + // don't unbind if any table on the page still has stickyheaders applied + if (!$('.hasStickyHeaders').length) { + $(window).unbind('scroll.tsSticky resize.tsSticky'); + } + ts.addHeaderResizeEvent(table, false); + } +}); + +// Add Column resizing widget +// this widget saves the column widths if +// $.tablesorter.storage function is included +// ************************** +ts.addWidget({ + id: "resizable", + priority: 40, + options: { + resizable : true, + resizable_addLastColumn : false + }, + format: function(table, c, wo){ + if (c.$table.hasClass('hasResizable')) { return; } + c.$table.addClass('hasResizable'); + var $t, t, i, j, s = {}, $c, $cols, w, tw, + $tbl = c.$table, + position = 0, + $target = null, + $next = null, + fullWidth = Math.abs($tbl.parent().width() - $tbl.width()) < 20, + stopResize = function(){ + if (ts.storage && $target){ + s[$target.index()] = $target.width(); + s[$next.index()] = $next.width(); + $target.width( s[$target.index()] ); + $next.width( s[$next.index()] ); + if (wo.resizable !== false){ + ts.storage(table, 'tablesorter-resizable', s); + } + } + position = 0; + $target = $next = null; + $(window).trigger('resize'); // will update stickyHeaders, just in case + }; + s = (ts.storage && wo.resizable !== false) ? ts.storage(table, 'tablesorter-resizable') : {}; + // process only if table ID or url match + if (s){ + for (j in s){ + if (!isNaN(j) && j < c.$headers.length){ + c.$headers.eq(j).width(s[j]); // set saved resizable widths + } + } + } + $t = $tbl.children('thead:first').children('tr'); + // add resizable-false class name to headers (across rows as needed) + $t.children().each(function(){ + t = $(this); + i = t.attr('data-column'); + j = ts.getData( t, c.headers[i], 'resizable') === "false"; + $t.children().filter('[data-column="' + i + '"]').toggleClass('resizable-false', j); + }); + // add wrapper inside each cell to allow for positioning of the resizable target block + $t.each(function(){ + $c = $(this).children(':not(.resizable-false)'); + if (!$(this).find('.tablesorter-wrapper').length) { + // Firefox needs this inner div to position the resizer correctly + $c.wrapInner('
'); + } + // don't include the last column of the row + if (!wo.resizable_addLastColumn) { $c = $c.slice(0,-1); } + $cols = $cols ? $cols.add($c) : $c; + }); + $cols + .each(function(){ + $t = $(this); + j = parseInt($t.css('padding-right'), 10) + 10; // 8 is 1/2 of the 16px wide resizer grip + t = '
'; + $t + .find('.tablesorter-wrapper') + .append(t); + }) + .bind('mousemove.tsresize', function(e){ + // ignore mousemove if no mousedown + if (position === 0 || !$target) { return; } + // resize columns + w = e.pageX - position; + tw = $target.width(); + $target.width( tw + w ); + if ($target.width() !== tw && fullWidth){ + $next.width( $next.width() - w ); + } + position = e.pageX; + }) + .bind('mouseup.tsresize', function(){ + stopResize(); + }) + .find('.tablesorter-resizer,.tablesorter-resizer-grip') + .bind('mousedown', function(e){ + // save header cell and mouse position; closest() not supported by jQuery v1.2.6 + $target = $(e.target).closest('th'); + t = c.$headers.filter('[data-column="' + $target.attr('data-column') + '"]'); + if (t.length > 1) { $target = $target.add(t); } + // if table is not as wide as it's parent, then resize the table + $next = e.shiftKey ? $target.parent().find('th:not(.resizable-false)').filter(':last') : $target.nextAll(':not(.resizable-false)').eq(0); + position = e.pageX; + }); + $tbl.find('thead:first') + .bind('mouseup.tsresize mouseleave.tsresize', function(){ + stopResize(); + }) + // right click to reset columns to default widths + .bind('contextmenu.tsresize', function(){ + ts.resizableReset(table); + // $.isEmptyObject() needs jQuery 1.4+ + var rtn = $.isEmptyObject ? $.isEmptyObject(s) : s === {}; // allow right click if already reset + s = {}; + return rtn; + }); + }, + remove: function(table, c, wo){ + c.$table + .removeClass('hasResizable') + .find('thead') + .unbind('mouseup.tsresize mouseleave.tsresize contextmenu.tsresize') + .find('tr').children() + .unbind('mousemove.tsresize mouseup.tsresize') + // don't remove "tablesorter-wrapper" as uitheme uses it too + .find('.tablesorter-resizer,.tablesorter-resizer-grip').remove(); + ts.resizableReset(table); + } +}); +ts.resizableReset = function(table){ + table.config.$headers.filter(':not(.resizable-false)').css('width',''); + if (ts.storage) { ts.storage(table, 'tablesorter-resizable', {}); } +}; + +// Save table sort widget +// this widget saves the last sort only if the +// saveSort widget option is true AND the +// $.tablesorter.storage function is included +// ************************** +ts.addWidget({ + id: 'saveSort', + priority: 20, + options: { + saveSort : true + }, + init: function(table, thisWidget, c, wo){ + // run widget format before all other widgets are applied to the table + thisWidget.format(table, c, wo, true); + }, + format: function(table, c, wo, init){ + var sl, time, + $t = c.$table, + ss = wo.saveSort !== false, // make saveSort active/inactive; default to true + sortList = { "sortList" : c.sortList }; + if (c.debug){ + time = new Date(); + } + if ($t.hasClass('hasSaveSort')){ + if (ss && table.hasInitialized && ts.storage){ + ts.storage( table, 'tablesorter-savesort', sortList ); + if (c.debug){ + ts.benchmark('saveSort widget: Saving last sort: ' + c.sortList, time); + } + } + } else { + // set table sort on initial run of the widget + $t.addClass('hasSaveSort'); + sortList = ''; + // get data + if (ts.storage){ + sl = ts.storage( table, 'tablesorter-savesort' ); + sortList = (sl && sl.hasOwnProperty('sortList') && $.isArray(sl.sortList)) ? sl.sortList : ''; + if (c.debug){ + ts.benchmark('saveSort: Last sort loaded: "' + sortList + '"', time); + } + $t.bind('saveSortReset', function(e){ + e.stopPropagation(); + ts.storage( table, 'tablesorter-savesort', '' ); + }); + } + // init is true when widget init is run, this will run this widget before all other widgets have initialized + // this method allows using this widget in the original tablesorter plugin; but then it will run all widgets twice. + if (init && sortList && sortList.length > 0){ + c.sortList = sortList; + } else if (table.hasInitialized && sortList && sortList.length > 0){ + // update sort change + $t.trigger('sorton', [sortList]); + } + } + }, + remove: function(table){ + // clear storage + if (ts.storage) { ts.storage( table, 'tablesorter-savesort', '' ); } + } +}); + +})(jQuery); diff --git a/templates/admin/default/assets/less/main.less b/templates/admin/default/assets/less/main.less index 7ad14e013..3498441a2 100644 --- a/templates/admin/default/assets/less/main.less +++ b/templates/admin/default/assets/less/main.less @@ -2,5 +2,4 @@ @import "bootstrap/bootstrap.less"; /* Thelia Admin */ -@import "thelia/thelia.less"; -// @import "thelia/responsive.less"; \ No newline at end of file +@import "thelia/thelia.less"; \ No newline at end of file diff --git a/templates/admin/default/assets/less/thelia/thelia.less b/templates/admin/default/assets/less/thelia/thelia.less index 3883c7067..8576272bf 100644 --- a/templates/admin/default/assets/less/thelia/thelia.less +++ b/templates/admin/default/assets/less/thelia/thelia.less @@ -247,4 +247,10 @@ .ui-slider{ margin-top: 23px; +} + +.loading{ + background: url("@{imgDir}/ajax-loader.gif") no-repeat; + height: 24px; + width: 24px; } \ No newline at end of file diff --git a/templates/admin/default/categories.html b/templates/admin/default/categories.html index a3097f722..f08721828 100755 --- a/templates/admin/default/categories.html +++ b/templates/admin/default/categories.html @@ -8,9 +8,7 @@
- + {include file="includes/catalog-breadcrumb.html"} {module_include location='catalog_top'} @@ -20,7 +18,7 @@ + + @@ -59,8 +67,8 @@ current_order=$category_order order='visible' reverse_order='visible_reverse' - path={url path='/admin/catalog/category' id="{$current_category_id}"} - label={intl l='Online'} + path={url path='/admin/catalog' id_category=$current_category_id} + label="{intl l='Online'}" } @@ -69,8 +77,8 @@ current_order=$category_order order='manual' reverse_order='manual_reverse' - path={url path='/admin/catalog/category' id="{$current_category_id}"} - label={intl l='Position'} + path={url path='/admin/catalog' id_category=$current_category_id} + label="{intl l='Position'}" } @@ -81,22 +89,24 @@ {loop name="category_list" type="category" visible="*" parent=$current_category_id order=$category_order backend_context="1" lang=$lang_id} + + {module_include location='category_list_row'} - + {loop name="mailing-templates" type="message" secured="*" backend_context="1" lang="$lang_id"} @@ -71,7 +71,7 @@ {/loop} {loop type="auth" name="can_delete" roles="ADMIN" permissions="admin.configuration.messages.delete"} - + {/loop} {else} @@ -79,7 +79,7 @@ {/if} - {/loop} + {/loop} {elseloop rel="mailing-templates"}
{* display parent category name, and get current cat ID *} - {loop name="category_title" type="category" visible="*" id="{$current_category_id}"} + {loop name="category_title" type="category" visible="*" id=$current_category_id} {intl l="Categories in %cat" cat=$TITLE} {$cat_id = $ID} {/loop} @@ -30,7 +28,7 @@ {module_include location='category_list_caption'} - {loop type="auth" name="can_create" roles="ADMIN" permissions="admin.category.create"} + {loop type="auth" name="can_create" roles="ADMIN" permissions="admin.categories.create"} @@ -40,6 +38,16 @@ {ifloop rel="category_list"}
+ {admin_sortable_header + current_order=$category_order + order='id' + reverse_order='id_reverse' + path={url path='/admin/catalog' id_category=$current_category_id} + label="{intl l='ID'}" + } +   @@ -47,8 +55,8 @@ current_order=$category_order order='alpha' reverse_order='alpha_reverse' - path={url path='/admin/catalog/category' id="{$current_category_id}"} - label={intl l='Category title'} + path={url path='/admin/catalog' id_category=$current_category_id} + label="{intl l='Category title'}" }
{$ID} - i={$ID} {loop type="image" name="cat_image" source="category" source_id="$ID" limit="1" width="50" height="50" resize_mode="crop" backend_context="1"} - #TITLE + {loop type="image" name="cat_image" source="category" source_id="$ID" limit="1" width="50" height="50" resize_mode="crop" backend_context="1"} + #TITLE {/loop} - - {$ID} p={$POSITION} {$TITLE} + + {$TITLE} - {loop type="auth" name="can_change" roles="ADMIN" permissions="admin.category.edit"} + {loop type="auth" name="can_change" roles="ADMIN" permissions="admin.categories.edit"}
@@ -111,24 +121,24 @@
{admin_position_block - permission="admin.category.edit" - path={url path='admin/catalog/category' category_id="{$ID}"} + permission="admin.categories.edit" + path={url path='admin/category/update-position' category_id=$ID} url_parameter="category_id" in_place_edit_class="categoryPositionChange" - position="$POSITION" - id="$ID" + position=$POSITION + id=$ID }
- + - {loop type="auth" name="can_change" roles="ADMIN" permissions="admin.category.edit"} - + {loop type="auth" name="can_change" roles="ADMIN" permissions="admin.categories.edit"} + {/loop} - {loop type="auth" name="can_delete" roles="ADMIN" permissions="admin.category.delete"} + {loop type="auth" name="can_delete" roles="ADMIN" permissions="admin.categories.delete"} {/loop}
@@ -143,7 +153,7 @@
- {loop type="auth" name="can_create" roles="ADMIN" permissions="admin.category.create"} + {loop type="auth" name="can_create" roles="ADMIN" permissions="admin.categories.create"} {intl l="This category has no sub-categories. To create a new one, click the + button above."} {/loop} @@ -166,9 +176,10 @@ + + + @@ -211,8 +241,8 @@ current_order=$product_order order='manual' reverse_order='manual_reverse' - path={url path='/admin/catalog/product' id="{$current_category_id}"} - label={intl l='Position'} + path={url path='/admin/product' category_id=$current_category_id} + label="{intl l='Position'}" } @@ -221,39 +251,58 @@ - {loop name="product_list" type="product" category="{$current_category_id}" order="manual"} + {loop name="product_list" type="product" category=$current_category_id order="manual"} + + + + + {module_include location='product_list_row'} {/loop} @@ -276,8 +325,82 @@ -{include file="includes/add-category-dialog.html"} -{include file="includes/delete-category-dialog.html"} + {* Adding a new Category *} + + + {form name="thelia.admin.category.creation"} + + {* Capture the dialog body, to pass it to the generic dialog *} + {capture "category_creation_dialog"} + + {form_hidden_fields form=$form} + + {form_field form=$form field='success_url'} + {* on success, redirect to the edition page, _ID_ is replaced with the created object ID, see controller *} + + {/form_field} + + {form_field form=$form field='parent'} + + {/form_field} + + {form_field form=$form field='title'} +
+ + + {loop type="lang" name="default-lang" default_only="1"} + +
+ + $TITLE +
+ +
{intl l='Enter here the category name in the default language (%title)' title="$TITLE"}
+ + {* Switch edition to the current locale *} + + + {form_field form=$form field='locale'} + + {/form_field} + {/loop} +
+ {/form_field} + {/capture} + + {include + file = "includes/generic-create-dialog.html" + + dialog_id = "add_category_dialog" + dialog_title = {intl l="Create a new category"} + dialog_body = {$smarty.capture.category_creation_dialog nofilter} + + dialog_ok_label = {intl l="Create this category"} + dialog_cancel_label = {intl l="Cancel"} + + form_action = {url path='/admin/categories/create'} + form_enctype = {form_enctype form=$form} + form_error_message = $form_error_message + } + {/form} + + {* Delete category confirmation dialog *} + + {capture "category_delete_dialog"} + + + {/capture} + + {include + file = "includes/generic-confirm-dialog.html" + + dialog_id = "delete_category_dialog" + dialog_title = {intl l="Delete a category"} + dialog_message = {intl l="Do you really want to delete this category, and all its contents ?"} + + form_action = {url path='/admin/categories/delete'} + form_content = {$smarty.capture.category_delete_dialog nofilter} + } {/block} {block name="javascript-initialization"} @@ -290,68 +413,100 @@ {/javascripts} - + {* Inline editing of object position using bootstrap-editable *} + + $('.categoryPositionChange').editable({ + type : 'text', + title : '{intl l="Enter new category position"}', + mode : 'popup', + inputclass : 'input-mini', + placement : 'left', + success : function(response, newValue) { + // The URL template + var url = "{url path='/admin/categories/update-position' category_id='__ID__' position='__POS__'}"; + + // Perform subtitutions + url = url.replace('__ID__', $(this).data('id')) + .replace('__POS__', newValue); + + // Reload the page + location.href = url; + } + }); + + $('.productPositionChange').editable({ + type : 'text', + title : '{intl l="Enter new product position"}', + mode : 'popup', + inputclass : 'input-mini', + placement : 'left', + success : function(response, newValue) { + // The URL template + var url = "{url path='/admin/products/update-position' product_id='__ID__' position='__POS__'}"; + + // Perform subtitutions + url = url.replace('__ID__', $(this).data('id')) + .replace('__POS__', newValue); + + // Reload the page + location.href = url; + } + }); + +}) + {/block} \ No newline at end of file diff --git a/templates/admin/default/edit_category.html b/templates/admin/default/category-edit.html similarity index 99% rename from templates/admin/default/edit_category.html rename to templates/admin/default/category-edit.html index 85e6d42bd..13327ca3d 100755 --- a/templates/admin/default/edit_category.html +++ b/templates/admin/default/category-edit.html @@ -7,9 +7,8 @@ {block name="main-content"}
- + + {include file="includes/catalog-breadcrumb.html"}
{loop name="category_edit" type="category" visible="*" id="{$current_category_id}" backend_context="1" lang="$edit_language_id"} @@ -27,6 +26,7 @@
+
{* display parent category name *} - {loop name="category_title" type="category" visible="*" id="{$current_category_id}"} + {loop name="category_title" type="category" visible="*" id=$current_category_id} {intl l="Products in %cat" cat=$TITLE} {/loop} + {elseloop rel="category_title"} {intl l="Top level Products"} {/elseloop} @@ -183,15 +194,34 @@ {ifloop rel="product_list"}
+ {admin_sortable_header + current_order=$product_order + order='id' + reverse_order='id_reverse' + path={url path='/admin/product' category_id=$current_category_id} + label="{intl l='ID'}" + } +   + {admin_sortable_header + current_order=$product_order + order='ref' + reverse_order='ref_reverse' + path={url path='/admin/product' category_id=$current_category_id} + label="{intl l='Reference'}" + } + {admin_sortable_header current_order=$product_order order='alpha' reverse_order='alpha_reverse' - path={url path='/admin/catalog/product' id="{$current_category_id}"} - label={intl l='Product title'} + path={url path='/admin/product' category_id=$current_category_id} + label="{intl l='Product title'}" } {module_include location='product_list_header'} @@ -201,8 +231,8 @@ current_order=$product_order order='visible' reverse_order='visible_reverse' - path={url path='/admin/catalog/product' id="{$current_category_id}"} - label={intl l='Online'} + path={url path='/admin/product' category_id=$current_category_id} + label="{intl l='Online'}" }
{$ID} {loop type="image" name="cat_image" source="product" source_id="$ID" limit="1" width="50" height="50" resize_mode="crop" backend_context="1"} - + #TITLE {/loop} - {$TITLE}{$REF}{$TITLE} + {loop type="auth" name="can_change" roles="ADMIN" permissions="admin.products.edit"} +
+ +
+ {/loop} + + {elseloop rel="can_change"}
+ {/elseloop}
{admin_position_block permission="admin.product.edit" - path={url path='admin/catalog/product' category_id="{$ID}"} + path={url path='admin/product' category_id=$ID} url_parameter="product_id" in_place_edit_class="productPositionChange" - position="$POSITION" - id="$ID" + position=$POSITION + id=$ID } - - +
+ {loop type="auth" name="can_change" roles="ADMIN" permissions="admin.product.edit"} + + {/loop} + + {loop type="auth" name="can_change" roles="ADMIN" permissions="admin.product.delete"} + + {/loop} +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ List of enabled coupons +
CodeTitleExpiration dateUsage leftActions
XMAS13Coupon for XMAS -30 €18/10/201349 + Edit + Disable +
XMAS13Coupon for XMAS -30 €05/09/201320 + Edit + Disable +
XMAS13Coupon for XMAS -30 €03/12/20139 + Edit + Disable +
XMAS13Coupon for XMAS -30 €25/01/20134 + Edit + Disable +
+
+ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ List of disabled coupons +
CodeTitleExpiration dateUsage leftActions
XMAS13Coupon for XMAS -30 €18/10/201349 + Edit + Enabled +
XMAS13Coupon for XMAS -20 €05/09/201349 + Edit + Enabled +
XMAS13Coupon for XMAS -50 €03/12/201349 + Edit + Enabled +
XMAS13Coupon for XMAS -5 €25/01/201349 + Edit + Enabled +
+
+
+ + + +{include file='includes/confirmation-modal.html' id="disable" message="{intl l='Do you really want to disable this element ?'}"} +{include file='includes/confirmation-modal.html' id="enable" message="{intl l='Do you really want to enable this element ?'}"} + +{/block} + + +{block name="javascript-initialization"} + + {javascripts file='assets/bootstrap-editable/js/bootstrap-editable.js'} + + {/javascripts} + + {javascripts file='assets/js/tablesorter/jquery.tablesorter.min.js'} + + {/javascripts} + + {javascripts file='assets/js/tablesorter/jquery.metadata.js'} + + {/javascripts} + + {javascripts file='assets/js/tablesorter/jquery.tablesorter.widgets.js'} + + {/javascripts} + + {javascripts file='assets/js/tablesorter/jquery.tablesorter.widgets-filter-formatter.js'} + + {/javascripts} + + {javascripts file='assets/js/main.js'} + + {/javascripts} +{/block} diff --git a/templates/admin/default/coupon-read.html b/templates/admin/default/coupon-read.html new file mode 100755 index 000000000..f187df7a0 --- /dev/null +++ b/templates/admin/default/coupon-read.html @@ -0,0 +1,127 @@ +{extends file="admin-layout.tpl"} +{block name="check-permissions"}admin.coupon.view{/block} +{block name="page-title"}{intl l='Coupon'}{/block} + +{block name="main-content"} +
+ + + + + + +
+
+ {loop type="coupon" name="read_coupon" id=1 backend_context="true"} +
+ + {if #IS_ENABLED}{else}This coupon is disabled, you can enable to the bottom of this form.{/if} +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Code#CODE
Title#TITLE
Expiration dateEXPIRATION_DATE
Usage left + {if #USAGE_LEFT} + + #USAGE_LEFT + + {else} + + 0 + + {/if} +
#SHORT_DESCRIPTION
#DESCRIPTION
+ {if #IS_CUMULATIVE} + + {intl l="May be cumulative"} + + {else} + + {intl l="Can't be cumulative"} + + {/if} +
+ {if #IS_REMOVING_POSTAGE} + + {intl l="Will remove postage"} + + {else} + + {intl l="Won't remove postage"} + + {/if} +
Amount#AMOUNT
Conditions of application +
    +
  • Total cart supperior to 400 €
  • +
  • OR
  • +
  • At least 4 products
  • +
+
Actions + Edit + Enabled +
+ {/loop} +
+
+
+ +{include file='includes/confirmation-modal.html' id="enable" message="{intl l='Do you really want to enable this element ?'}"} + +{/block} + +{block name="javascript-initialization"} + {javascripts file='assets/js/main.js'} + + {/javascripts} + + {javascripts file='assets/bootstrap-editable/js/bootstrap-editable.js'} + + {/javascripts} +{/block} diff --git a/templates/admin/default/coupon-update.html b/templates/admin/default/coupon-update.html new file mode 100755 index 000000000..425d9a7ac --- /dev/null +++ b/templates/admin/default/coupon-update.html @@ -0,0 +1,70 @@ +{extends file="admin-layout.tpl"} +{block name="check-permissions"}admin.coupon.update{/block} +{block name="page-title"}{intl l='Update coupon'}{/block} + +{block name="main-content"} +
+ + + + + + {form name="thelia.admin.coupon.creation"} + {include file='coupon/form.html' formAction={url path={$formAction}} form=$form} + {/form} + +
+{/block} + +{include file='includes/confirmation-modal.html'} + +{block name="javascript-initialization"} + {javascripts file='assets/bootstrap-datepicker/js/bootstrap-datepicker.js'} + + {/javascripts} + + {javascripts file='assets/js/main.js'} + + {/javascripts} + + +{/block} diff --git a/templates/admin/default/coupon/form.html b/templates/admin/default/coupon/form.html new file mode 100644 index 000000000..b092e30b1 --- /dev/null +++ b/templates/admin/default/coupon/form.html @@ -0,0 +1,290 @@ +{$thelia_page_css_file = "assets/bootstrap-editable/css/bootstrap-editable.css"} +{include file='includes/notifications.html' message=$general_error} + +
+
+ + {form_hidden_fields form=$form} + + {form_field form=$form field='locale'} + + {/form_field} + + {form_field form=$form field='success_url'} + + {/form_field} + +
+
+
+
+ + {form_field form=$form field='code'} + + {if $error}{$message}{/if} + {/form_field} +
+ +
+ + {form_field form=$form field='title'} + + {if $error}{$message}{/if} + {/form_field} +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ {form_field form=$form field='expirationDate'} + + {if $error}{$message}{/if} + {/form_field} + +
+
+ +
+ + + {form_field form=$form field='maxUsage'} + + {if $error}{$message}{/if} + {/form_field} +
+
+ +
+
+
+
+ + {form_field form=$form field='effect'} + + {if $error}{$message}{/if} + {/form_field} + {$availableCoupons.0.toolTip} +
+
+ +
+
+ + {form_field form=$form field='amount'} + + {if $error}{$message}{/if} + {/form_field} +
+
+ + {*form_field form=$form field='category'*} + + {*if $error}{$message}{/if}*} + {*/form_field*} +
+
+
+ +
+ + {form_field form=$form field='shortDescription'} + + {if $error}{$message}{/if} + {/form_field} +
+
+ +
+
+ +
+ + {form_field form=$form field='description'} + + {if $error}{$message}{/if} + {/form_field} +
+ + +
+ +
+
+ +
+
+ + + + + + + + + + {foreach from=$rulesObject item=rule} + + + + + {/foreach} + +
+ {intl l='Rules'} + + + +
{intl l='Conditions'}{intl l='Actions'}
{$rule.tooltip} + {intl l='Edit'} + {intl l='Delete'} +
+
+
+ +
+
+ + + + +
+ + + +
+ +
+ + +
+ +
+ +
+
+ +
+
+ + +
+
+ + + +
+
+ +
+
+ + +
+
+ + +
+
+ +
+
+ +
+
+
+
+ + + + + + + + + + +
Categories list
+
+
+
+
+
+ + diff --git a/templates/admin/default/coupon/rule-input-ajax.html b/templates/admin/default/coupon/rule-input-ajax.html new file mode 100644 index 000000000..4e7ab4533 --- /dev/null +++ b/templates/admin/default/coupon/rule-input-ajax.html @@ -0,0 +1,74 @@ +{*test*} +{*{$ruleId}*} +{*{$inputs|var_dump}*} + +{foreach from=$inputs key=name item=input} + +
+
+ +
+
+ {if $input.type == 'select'} + + {else} + + {**} + {/if} +
+
+{/foreach} + {**} + {*
*} + {*
*} + {**} + {*
*} + {*
*} + {**} + {**} + {*
*} + {*
*} + {**} + {*
*} + {*
*} + {**} + {*
*} + {*
*} + {**} + {*
*} + {*
*} + {*
*} + {*
*} + {**} + {**} + {**} + {**} + {**} + {**} + {**} + {**} + {**} + {**} + {*
Categories list
*} + {*
*} + {*
*} \ No newline at end of file diff --git a/templates/admin/default/currencies.html b/templates/admin/default/currencies.html index 29bd582a2..5854b2f49 100644 --- a/templates/admin/default/currencies.html +++ b/templates/admin/default/currencies.html @@ -30,7 +30,7 @@ {loop type="auth" name="can_create" roles="ADMIN" permissions="admin.configuration.currencies.create"} - + @@ -122,7 +122,7 @@
{loop type="auth" name="can_change" roles="ADMIN" permissions="admin.configuration.currencies.change"} - {$NAME} + {$NAME} {/loop} {elseloop rel="can_change"} {$NAME} @@ -163,7 +163,7 @@ {/loop} {loop type="auth" name="can_delete" roles="ADMIN" permissions="admin.configuration.currencies.delete"} - + {/loop} @@ -199,116 +199,96 @@ {* Adding a new currency *} - + form_action = {url path='/admin/configuration/currencies/create'} + form_enctype = {form_enctype form=$form} + form_error_message = $form_error_message + } + {/form} {* Delete confirmation dialog *} - + form_action = {url path='/admin/configuration/currencies/delete'} + form_content = {$smarty.capture.delete_dialog nofilter} + } {/block} {block name="javascript-initialization"} @@ -329,27 +309,12 @@ $('#currency_delete_id').val($(this).data('id')); }); - {* display the form creation dialog if it contains errors *} - - {form name="thelia.admin.currency.creation"} - {if #form_error} - $('#add_currency_dialog').modal(); - {/if} - {/form} - - {* Always reset create dialog on close *} - - $('#add_currency_dialog').on('hidden',function() { - - // Hide error currency - $('#add_currency_dialog_error').remove(); - - // Clear error status - $("#add_currency_dialog .error").removeClass('error'); - - // Empty field values - $("#add_currency_dialog input[type=text]").val(''); - }); + // JS stuff for creation form + {include + file = "includes/generic-js-dialog.html" + dialog_id = "creation_dialog" + form_name = "thelia.admin.currency.creation" + } {* Inline editing of object position using bootstrap-editable *} diff --git a/templates/admin/default/customers.html b/templates/admin/default/customers.html new file mode 100644 index 000000000..923941c4e --- /dev/null +++ b/templates/admin/default/customers.html @@ -0,0 +1,139 @@ + +{extends file="admin-layout.tpl"} + +{block name="page-title"}{intl l='Customer'}{/block} + +{block name="check-permissions"}admin.customer.view{/block} + +{block name="main-content"} + {assign var=customer_page value={$smarty.get.page|default:1}} + + +
+
+ + + {module_include location='customer_top'} + +
+
+
+ + + + {ifloop rel="customer_list"} + + + + + + + {module_include location='category_list_header'} + + + + + + + + + + + + + {loop name="customer_list" type="customer" visible="*" last_order="1" backend_context="1" page={$customer_page} limit={$display_customer}} + + + + + + + + {module_include location='customer_list_row'} + + + + + + + + {/loop} + + {/ifloop} +
+ {intl l="Customers list"} + + {module_include location='customer_list_caption'} + + {loop type="auth" name="can_create" roles="ADMIN" permissions="admin.customers.create"} + + + + {/loop} +
+ {intl l="customer ref"} + + {intl l="company"} + + {intl l="firstname & lastname"} + + {intl l="last order"} + {intl l='order amount'}{intl l='Actions'}
{#REF} + {#COMPANY} + + {#FIRSTNAME} {#LASTNAME} + + {format_date date=$LASTORDER_DATE} + + {format_number number=$LASTORDER_AMOUNT} + +
+ + {loop type="auth" name="can_change" roles="ADMIN" permissions="admin.customer.edit"} + + {/loop} + {loop type="auth" name="can_send_mail" roles="ADMIN" permissions="admin.customer.sendMail"} + + {/loop} + {loop type="auth" name="can_delete" roles="ADMIN" permissions="admin.customer.delete"} + + {/loop} +
+
+
+
+
+ + + {module_include location='customer_bottom'} +
+
+ +
    + {if #customer_page != 1} +
  • «
  • + {else} +
  • «
  • + {/if} + + {pageloop rel="customer_list"} + {if #PAGE != #CURRENT} +
  • #PAGE
  • + {else} +
  • #PAGE
  • + {/if} + + {if #PAGE == #LAST && #LAST != #CURRENT} +
  • »
  • + {else} +
  • »
  • + {/if} + {/pageloop} +
+
+
+ +
+
+ +{/block} \ No newline at end of file diff --git a/templates/admin/default/includes/add-category-dialog.html b/templates/admin/default/includes/add-category-dialog.html deleted file mode 100755 index 631d0c06e..000000000 --- a/templates/admin/default/includes/add-category-dialog.html +++ /dev/null @@ -1,70 +0,0 @@ - -{* Adding a new Category *} - - \ No newline at end of file diff --git a/templates/admin/default/includes/catalog-breadcrumb.html b/templates/admin/default/includes/catalog-breadcrumb.html new file mode 100644 index 000000000..b9312f0dd --- /dev/null +++ b/templates/admin/default/includes/catalog-breadcrumb.html @@ -0,0 +1,26 @@ +{* Breadcrumb for categories browsing and editing *} + + \ No newline at end of file diff --git a/templates/admin/default/includes/category_breadcrumb.html b/templates/admin/default/includes/category_breadcrumb.html deleted file mode 100755 index bf14142b5..000000000 --- a/templates/admin/default/includes/category_breadcrumb.html +++ /dev/null @@ -1,13 +0,0 @@ -{* Breadcrumb for categories browsing and editing *} - -
  • Home
  • -
  • Catalog {ifloop rel="category_path"}
  • - -{loop name="category_path" type="category-path" visible="*" category="{$current_category_id}"} {if $ID == $current_category_id} -
  • {if $action == 'edit'} {intl l='Editing %cat' cat="{$TITLE}"} {else} {$TITLE} {intl l="(edit)"} {/if} -
  • -{else} -
  • {$TITLE}
  • -{/if} {/loop} {/ifloop} {elseloop rel="category_path"} - -{/elseloop} diff --git a/templates/admin/default/includes/confirmation-modal.html b/templates/admin/default/includes/confirmation-modal.html new file mode 100644 index 000000000..957960416 --- /dev/null +++ b/templates/admin/default/includes/confirmation-modal.html @@ -0,0 +1,36 @@ +{* + Params + - id : aside element id (default delete) + - title : modal title (default Confirmation) + - message : modal message (default Do you really want to delete this element ?) +*} +{block name="confirmation-modal"} + +{/block} \ No newline at end of file diff --git a/templates/admin/default/includes/coupon_breadcrumb.html b/templates/admin/default/includes/coupon_breadcrumb.html new file mode 100755 index 000000000..878d9605d --- /dev/null +++ b/templates/admin/default/includes/coupon_breadcrumb.html @@ -0,0 +1,5 @@ +{* Breadcrumb for coupon browsing and editing *} + +
  • Home
  • +
  • Coupon
  • +
  • Browse
  • \ No newline at end of file diff --git a/templates/admin/default/includes/delete-category-dialog.html b/templates/admin/default/includes/delete-category-dialog.html deleted file mode 100755 index 38e93a340..000000000 --- a/templates/admin/default/includes/delete-category-dialog.html +++ /dev/null @@ -1,48 +0,0 @@ - -{* Adding a new Category *} - - diff --git a/templates/admin/default/includes/generic-confirm-dialog.html b/templates/admin/default/includes/generic-confirm-dialog.html new file mode 100644 index 000000000..b5f3ad700 --- /dev/null +++ b/templates/admin/default/includes/generic-confirm-dialog.html @@ -0,0 +1,43 @@ +{* + +A generic modal confirmation dialog template. + +Parameters: + + dialog_id = the dialog id attribute + dialog_title = the dialog title + dialog_message = the dialog confirmation message + + dialog_ok_label = The OK button label (default: yes) + dialog_cancel_label = The Cancel button label (default: no) + + form_action = the form action URL, subtitted by a click on OK button + form_method = the form method, default "POST" + form_content = the form content + +*} + \ No newline at end of file diff --git a/templates/admin/default/includes/generic-create-dialog.html b/templates/admin/default/includes/generic-create-dialog.html new file mode 100755 index 000000000..c6a00a01b --- /dev/null +++ b/templates/admin/default/includes/generic-create-dialog.html @@ -0,0 +1,43 @@ +{* + +A generic modal creation dialog template. Parameters + + dialog_id = the dialog id attribute + dialog_title = the dialog title + dialog_body = the dialog body. In most cases, this is a creation form + + dialog_ok_label = The OK button label. Default create + dialog_cancel_label = The cancel button label. Default create + + form_action = The form action URL. Form is submitted when OK button is clicked + form_enctype = The form encoding + form_error_message = The form error message (optional) +*} + diff --git a/templates/admin/default/includes/generic-js-dialog.html b/templates/admin/default/includes/generic-js-dialog.html new file mode 100644 index 000000000..f1be39f03 --- /dev/null +++ b/templates/admin/default/includes/generic-js-dialog.html @@ -0,0 +1,35 @@ +{* +Javascript code to manage create dialog. Insert it in your template, in the javascript +initialisation: + + $(function() { + + } + +Parameters: + $dialog_id = the dialog ID + $form_name = the form name + +*} + +{* re-display the form creation dialog if it contains errors *} + +{form name="{$form_name}"} + {if #form_error} + $('#{$dialog_id}').modal(); + {/if} +{/form} + +{* Always reset create dialog on close *} + +$('#{$dialog_id}').on('hidden', function() { + + // Hide error message + $('#{$dialog_id}_error').remove(); + + // Clear error status + $("#{$dialog_id} .error").removeClass('error'); + + // Empty field values + $("#{$dialog_id} input[type=text]").val(''); +}); \ No newline at end of file diff --git a/templates/admin/default/includes/notifications.html b/templates/admin/default/includes/notifications.html new file mode 100644 index 000000000..d559caa65 --- /dev/null +++ b/templates/admin/default/includes/notifications.html @@ -0,0 +1,11 @@ +{* + Params + - type : notification type (default alert) + - message : modal message +*} +{if $message} +
    + + {$message} +
    +{/if} \ No newline at end of file diff --git a/templates/admin/default/messages.html b/templates/admin/default/messages.html index 08031bd3c..755388fcf 100644 --- a/templates/admin/default/messages.html +++ b/templates/admin/default/messages.html @@ -25,7 +25,7 @@
    {intl l='Thelia mailing templates'} {loop type="auth" name="can_create" roles="ADMIN" permissions="admin.configuration.messages.create"} - + {/loop} @@ -41,7 +41,7 @@
     
    @@ -102,110 +102,89 @@ -{* Adding a new message *} - - + {* Adding a new message *} -{* Delete confirmation dialog *} + {form name="thelia.admin.message.creation"} - + {form_field form=$form field='title'} +
    + + + {loop type="lang" name="default-lang" default_only="1"} + + {* Switch edition to the current locale *} + + +
    + + {intl l=$TITLE} +
    + +
    {intl l="Enter here the mailing template purpose in the default language ($TITLE)"}
    + + {form_field form=$form field='locale'} + + {/form_field} + {/loop} + +
    + {/form_field} + {/capture} + + {include + file = "includes/generic-create-dialog.html" + + dialog_id = "creation_dialog" + dialog_title = {intl l="Create a new mailing template"} + dialog_body = {$smarty.capture.creation_dialog nofilter} + + dialog_ok_label = {intl l="Create this mailing template"} + + form_action = {url path='/admin/configuration/messages/create'} + form_enctype = {form_enctype form=$form} + form_error_message = $form_error_message + } + {/form} + + {* Delete confirmation dialog *} + + {capture "delete_dialog"} + + {/capture} + + {include + file = "includes/generic-confirm-dialog.html" + + dialog_id = "delete_dialog" + dialog_title = {intl l="Delete mailing template"} + dialog_message = {intl l="Do you really want to delete this mailing template ?"} + + form_action = {url path='/admin/configuration/messages/delete'} + form_content = {$smarty.capture.delete_dialog nofilter} + } {/block} {block name="javascript-initialization"} @@ -217,26 +196,12 @@ $('#message_delete_id').val($(this).data('id')); }); - {* display the form creation dialog if it contains errors *} - - {form name="thelia.admin.message.creation"} - {if #form_error} - $('#add_message_dialog').modal(); - {/if} - {/form} - - {* Always reset create dialog on close *} - - $('#add_message_dialog').on('hidden',function() { - // Hide error message - $('#add_message_dialog_error').remove(); - - // Clear error status - $("#add_message_dialog .error").removeClass('error'); - - // Empty field values - $("#add_message_dialog input[type=text]").val(''); - }); + // JS stuff for creation form + {include + file = "includes/generic-js-dialog.html" + dialog_id = "creation_dialog" + form_name = "thelia.admin.message.creation" + } }); {/block} \ No newline at end of file diff --git a/templates/admin/default/variables.html b/templates/admin/default/variables.html index 6373618f9..0d1c948a0 100644 --- a/templates/admin/default/variables.html +++ b/templates/admin/default/variables.html @@ -26,7 +26,7 @@ {intl l='Thelia system variables'} {loop type="auth" name="can_create" roles="ADMIN" permissions="admin.configuration.variables.create"}
    - + @@ -135,148 +135,116 @@ {* Adding a new variable *} - + {include + file = "includes/generic-create-dialog.html" + dialog_id = "creation_dialog" + dialog_title = {intl l="Create a new variable"} + dialog_body = {$smarty.capture.creation_dialog nofilter} -{* Delete confirmation dialog *} + dialog_ok_label = {intl l="Create this variable"} - + dialog_id = "delete_variable_dialog" + dialog_title = {intl l="Delete a variable"} + dialog_message = {intl l="Do you really want to delete this variable ?"} + + form_action = {url path='/admin/configuration/variables/delete'} + form_content = {$smarty.capture.delete_dialog nofilter} + } {/block} {block name="javascript-initialization"} + + {block name="page-title"}Thelia - E-commerce plateform{/block} + + + + + + + {block name="meta"}{/block} + + + {stylesheets file='assets/less/styles.less' filters='less,cssembed'} + + {/stylesheets} + + {block name="stylesheet"}{/block} + + + + + +Skip to content + +
    + +
    + + + + + + +
    + +
    +
    + {block name="breadcrumb"}{/block} + {block name="main-content"}{/block} +
    +
    + + + +
    + +{block name="before-javascript-include"}{/block} + + + + + + +{javascripts file='assets/js/bootstrap/affix.js'} + +{/javascripts} +{javascripts file='assets/js/bootstrap/tooltip.js'} + +{/javascripts} +{javascripts file='assets/js/bootstrap/popover.js'} + +{/javascripts} +{javascripts file='assets/js/bootstrap/tab.js'} + +{/javascripts} +{javascripts file='assets/js/bootstrap/scrollspy.js'} + +{/javascripts} +{javascripts file='assets/js/bootstrap/transition.js'} + +{/javascripts} +{javascripts file='assets/js/bootstrap/alert.js'} + +{/javascripts} +{javascripts file='assets/js/bootstrap/button.js'} + +{/javascripts} +{javascripts file='assets/js/bootstrap/carousel.js'} + +{/javascripts} +{javascripts file='assets/js/bootstrap/collapse.js'} + +{/javascripts} +{javascripts file='assets/js/bootstrap/dropdown.js'} + +{/javascripts} +{javascripts file='assets/js/bootstrap/modal.js'} + +{/javascripts} + + +{javascripts file='assets/js/script.js'} + +{/javascripts} + + + +{block name="after-javascript-include"}{/block} + +{block name="javascript-initialization"}{/block} + + + \ No newline at end of file diff --git a/templates/default/login.html b/templates/default/login.html old mode 100755 new mode 100644 index 702f0a710..4fe25f276 --- a/templates/default/login.html +++ b/templates/default/login.html @@ -1,49 +1,77 @@ -{include file="includes/header.html"} +{extends file="layout.tpl"} -

    {intl l='Please login'}

    +{block name="breadcrumb"} + +{/block} -{form name="thelia.customer.login" } +{block name="main-content"} -
    - {* - The field below are not par of the Login form, it defines view to render if the form cannot be validated - *} - {* the view to return to if the form cannot be validated *} - {* - This field is common to all BaseForm instances (thus, this one), and defines - the URL the customer is redirected to once the form has been successfully - processed - *} +
    +
    +

    {intl l="Login"}

    + {form name="thelia.customer.login"} + + {if #form_error}
    #form_error_message
    {/if} + {form_field form=$form field='success_url'} + {* the url the user is redirected to on login success *} + {/form_field} - {form_field form=$form field='success_url'} - {* the url the user is redirected to on login success *} - {/form_field} + {form_field form=$form field='error_message'} + {* the url the user is redirected to on login success *} + {/form_field} + {form_hidden_fields form=$form} +
    + {form_field form=$form field="email"} +
    + +
    + + {if $error} + {$message} + {/if} +
    +
    + {/form_field} - {* - The form error status and the form error messages are defined in Customer action, - and passed back to the form plugin through the ParserContext. - *} +
    + {intl l="Do you have an account?"} +
    + +
    +
    + +
    + {form_field form=$form field="password"} +
    + +
    + + {if $error} + {$message} + {/if} +
    +
    + {/form_field} +
    +
    - {if #form_error}
    #form_error_message
    {/if} - - {form_hidden_fields form=$form} - - {form_field form=$form field="email"} - {if #error}{#message}{/if} -
    - {/form_field} - - {form_field form=$form field='password'} -
    - {/form_field} - - {form_field form=$form field='remember_me'} - - {/form_field} - - - -{/form} - -{include file='includes/footer.html'} \ No newline at end of file +
    + {intl l="Forgot your Password ?"} + +
    + + {/form} +
    +
    +{/block} \ No newline at end of file diff --git a/templates/default/register.html b/templates/default/register.html new file mode 100644 index 000000000..e38830743 --- /dev/null +++ b/templates/default/register.html @@ -0,0 +1,165 @@ +{extends file="layout.tpl"} + +{block name="breadcrumb"} + +{/block} + + +{block name="main-content"} +
    + +
    + +

    {intl l="Create New Account"}

    + {form name=""} +
    + +
    +
    + 1. {intl l="Personal Informations"} +
    + +
    +
    + +
    + + Available input! +
    +
    + +
    + +
    + + Invalid input! +
    +
    + +
    + +
    + +
    +
    + +
    + +
    + +
    +
    + +
    + +
    + +
    +
    +
    +
    + +
    +
    + 2. Delivery Informations +
    + +
    +
    + +
    + +
    +
    + +
    + +
    + +
    +
    + +
    + +
    + +
    +
    + +
    + +
    + +
    +
    + +
    + +
    + +
    +
    + +
    + +
    + +
    +
    +
    +
    +
    +
    + 3. Login Information +
    + +
    +
    + +
    + +
    +
    + +
    + +
    + +
    +
    +
    +
    + +
    +
    +
    + +
    +
    +
    + +
    +
    + +
    +
    +
    + {/form} +
    + +
    +{/block} \ No newline at end of file diff --git a/templates/default/404.html b/templates/default_save/404.html similarity index 100% rename from templates/default/404.html rename to templates/default_save/404.html diff --git a/templates/default/address.html b/templates/default_save/address.html similarity index 100% rename from templates/default/address.html rename to templates/default_save/address.html diff --git a/templates/default/address_edit.html b/templates/default_save/address_edit.html similarity index 100% rename from templates/default/address_edit.html rename to templates/default_save/address_edit.html diff --git a/templates/default/address_list.html b/templates/default_save/address_list.html similarity index 100% rename from templates/default/address_list.html rename to templates/default_save/address_list.html diff --git a/templates/default/assets/bootstrap/css/bootstrap-responsive.css b/templates/default_save/assets/bootstrap/css/bootstrap-responsive.css similarity index 100% rename from templates/default/assets/bootstrap/css/bootstrap-responsive.css rename to templates/default_save/assets/bootstrap/css/bootstrap-responsive.css diff --git a/templates/default/assets/bootstrap/css/bootstrap-responsive.min.css b/templates/default_save/assets/bootstrap/css/bootstrap-responsive.min.css similarity index 100% rename from templates/default/assets/bootstrap/css/bootstrap-responsive.min.css rename to templates/default_save/assets/bootstrap/css/bootstrap-responsive.min.css diff --git a/templates/default/assets/bootstrap/css/bootstrap.css b/templates/default_save/assets/bootstrap/css/bootstrap.css similarity index 100% rename from templates/default/assets/bootstrap/css/bootstrap.css rename to templates/default_save/assets/bootstrap/css/bootstrap.css diff --git a/templates/default/assets/bootstrap/css/bootstrap.min.css b/templates/default_save/assets/bootstrap/css/bootstrap.min.css similarity index 100% rename from templates/default/assets/bootstrap/css/bootstrap.min.css rename to templates/default_save/assets/bootstrap/css/bootstrap.min.css diff --git a/templates/default/assets/bootstrap/img/glyphicons-halflings-white.png b/templates/default_save/assets/bootstrap/img/glyphicons-halflings-white.png similarity index 100% rename from templates/default/assets/bootstrap/img/glyphicons-halflings-white.png rename to templates/default_save/assets/bootstrap/img/glyphicons-halflings-white.png diff --git a/templates/default/assets/bootstrap/img/glyphicons-halflings.png b/templates/default_save/assets/bootstrap/img/glyphicons-halflings.png similarity index 100% rename from templates/default/assets/bootstrap/img/glyphicons-halflings.png rename to templates/default_save/assets/bootstrap/img/glyphicons-halflings.png diff --git a/templates/default/assets/bootstrap/js/bootstrap.js b/templates/default_save/assets/bootstrap/js/bootstrap.js similarity index 100% rename from templates/default/assets/bootstrap/js/bootstrap.js rename to templates/default_save/assets/bootstrap/js/bootstrap.js diff --git a/templates/default/assets/bootstrap/js/bootstrap.min.js b/templates/default_save/assets/bootstrap/js/bootstrap.min.js similarity index 100% rename from templates/default/assets/bootstrap/js/bootstrap.min.js rename to templates/default_save/assets/bootstrap/js/bootstrap.min.js diff --git a/templates/default/assets/css/img/bg.jpg b/templates/default_save/assets/css/img/bg.jpg similarity index 100% rename from templates/default/assets/css/img/bg.jpg rename to templates/default_save/assets/css/img/bg.jpg diff --git a/templates/default/assets/css/style.less b/templates/default_save/assets/css/style.less similarity index 100% rename from templates/default/assets/css/style.less rename to templates/default_save/assets/css/style.less diff --git a/templates/default/assets/img/logo-thelia-34px.png b/templates/default_save/assets/img/logo-thelia-34px.png similarity index 100% rename from templates/default/assets/img/logo-thelia-34px.png rename to templates/default_save/assets/img/logo-thelia-34px.png diff --git a/templates/default/assets/img/test-background.jpg b/templates/default_save/assets/img/test-background.jpg similarity index 100% rename from templates/default/assets/img/test-background.jpg rename to templates/default_save/assets/img/test-background.jpg diff --git a/templates/default/assets/js/jquery.min.js b/templates/default_save/assets/js/jquery.min.js similarity index 100% rename from templates/default/assets/js/jquery.min.js rename to templates/default_save/assets/js/jquery.min.js diff --git a/templates/default/cart.html b/templates/default_save/cart.html similarity index 100% rename from templates/default/cart.html rename to templates/default_save/cart.html diff --git a/templates/default/category.html b/templates/default_save/category.html similarity index 95% rename from templates/default/category.html rename to templates/default_save/category.html index dd5c6a20a..a888605ff 100755 --- a/templates/default/category.html +++ b/templates/default_save/category.html @@ -1,3 +1,9 @@ + + + {debugbar_renderHead} + + +

    Category page

    @@ -26,6 +32,8 @@

    #TITLE

    #DESCRIPTION

    +

    Starting by #BEST_PRICE € HT (TAX : #BEST_PRICE_TAX ; #BEST_TAXED_PRICE € TTC)

    + {ifloop rel="ft"}
    Features
      @@ -140,4 +148,8 @@ {/loop}
    -
    \ No newline at end of file +
    + + {debugbar_render} + + \ No newline at end of file diff --git a/templates/default/connexion.html b/templates/default_save/connexion.html similarity index 100% rename from templates/default/connexion.html rename to templates/default_save/connexion.html diff --git a/templates/default/customer.html b/templates/default_save/customer.html similarity index 100% rename from templates/default/customer.html rename to templates/default_save/customer.html diff --git a/templates/default/debug.html b/templates/default_save/debug.html similarity index 100% rename from templates/default/debug.html rename to templates/default_save/debug.html diff --git a/templates/default_save/delivery_list.html b/templates/default_save/delivery_list.html new file mode 100644 index 000000000..2ea3cc166 --- /dev/null +++ b/templates/default_save/delivery_list.html @@ -0,0 +1,15 @@ +{include file="includes/header.html"} + +
      +{loop type="delivery" name="delivery.list"} +
    • +
        +
      • id : {#ID}
      • +
      • prix : {#PRICE}
      • +
      • Choisir : Choisir
      • +
      +
    • +{/loop} +
    + +{include file="includes/footer.html"} \ No newline at end of file diff --git a/templates/default/folder.html b/templates/default_save/folder.html similarity index 100% rename from templates/default/folder.html rename to templates/default_save/folder.html diff --git a/templates/default_save/i18n/en.php b/templates/default_save/i18n/en.php new file mode 100755 index 000000000..e69de29bb diff --git a/templates/default/i18n/fr.php b/templates/default_save/i18n/fr.php similarity index 100% rename from templates/default/i18n/fr.php rename to templates/default_save/i18n/fr.php diff --git a/templates/default/images.html b/templates/default_save/images.html similarity index 100% rename from templates/default/images.html rename to templates/default_save/images.html diff --git a/templates/default/included.html b/templates/default_save/included.html similarity index 100% rename from templates/default/included.html rename to templates/default_save/included.html diff --git a/templates/default/includes/footer.html b/templates/default_save/includes/footer.html similarity index 93% rename from templates/default/includes/footer.html rename to templates/default_save/includes/footer.html index 03188c367..2f14e2fd8 100755 --- a/templates/default/includes/footer.html +++ b/templates/default_save/includes/footer.html @@ -13,6 +13,6 @@ }); }); - + {debugbar_render} \ No newline at end of file diff --git a/templates/default/includes/header.html b/templates/default_save/includes/header.html similarity index 96% rename from templates/default/includes/header.html rename to templates/default_save/includes/header.html index 38e78478e..b605ecbb7 100755 --- a/templates/default/includes/header.html +++ b/templates/default_save/includes/header.html @@ -7,6 +7,7 @@ {stylesheets file='../assets/css/*' filters='less,cssembed'} {/stylesheets} + {debugbar_renderHead}
    diff --git a/templates/default_save/index.html b/templates/default_save/index.html new file mode 100755 index 000000000..53834febf --- /dev/null +++ b/templates/default_save/index.html @@ -0,0 +1,151 @@ +{include file="includes/header.html"} +
    + +{loop type="auth" name="auth_test" context="front" roles="CUSTOMER"} + +

    Customer is authentified :-)

    +{/loop} + +{elseloop rel="auth_test"} +

    Customer is not authentified :-(

    +{/elseloop} + +An image from asset directory : +{images file='assets/img/logo-thelia-34px.png'}{intl l='Thelia, solution e-commerce libre'}{/images} +
    + +
    +{intl l='An internationalized string'} +
    + + +
    + jQuery data: +
    + +
    +

    Category loop example

    +
      + {loop type="category" name="catloop1"} +
    • {$LOOP_COUNT}/{$LOOP_TOTAL} : {$ID} {$TITLE}, children: {$NB_CHILD} + {ifloop rel="inner1"} +
        + {loop type="category" name="inner1" parent="{$ID}"} +
      • Sub cat {$ID} (parent is {$PARENT}): {$TITLE}
      • + {/loop} +
      + {/ifloop} +
    • + {/loop} +
    +
    + + + + +
    +

    Conditional example #1

    + + {ifloop rel="catloop2"} + Hey ! Loop catloop2 is not empty: +
      + {loop type="category" name="catloop2" parent="12"} +
    • {$LOOP_COUNT}/{$LOOP_TOTAL} : {$ID} {$TITLE}
    • + {/loop} +
    + {/ifloop} + + {elseloop rel="catloop2"} +

    Loop catloop2 is empty

    + {/elseloop} +
    + +
    +

    Conditional example #2

    + + {ifloop rel="catloop3"} + Loop catloop3 is not empty: +
      + {loop type="category" name="catloop3" parent="0"} +
    • {$LOOP_COUNT}/{$LOOP_TOTAL} : {$ID} {$TITLE}
    • + {/loop} +
    + {/ifloop} + + {elseloop rel="catloop3"} +

    Loop catloop3 is empty

    + {/elseloop} + + {elseloop rel="catloop2"} +

    ... but catloop2 is still empty :-)

    + {/elseloop} + +
    + +
    +

    Traditional for loop

    + {for $index=5 to 12 step 1} + Compteur = {$index}
    + {/for} +
    + + + +
    +

    Some pagination

    +

    PAGE 1

    +
      + {loop type="category" name="catloopwithpagination1" limit="2" page="1"} +
    • {$LOOP_COUNT}/{$LOOP_TOTAL} : {$ID} {$TITLE}
    • + {/loop} +
    +

    PAGE 2

    +
      + {loop type="category" name="catloopwithpagination2" limit="2" page="2"} +
    • {$LOOP_COUNT}/{$LOOP_TOTAL} : {$ID} {$TITLE}
    • + {/loop} +
    +

    PAGE 1000

    +
      + + {loop type="category" name="catloopwithpagination1000" limit="2" page="1000"} +
    • {$LOOP_COUNT}/{$LOOP_TOTAL} : {$ID} {$TITLE}
    • + {/loop} + + {elseloop rel="catloopwithpagination1000"} + NO RESULTS + {/elseloop} +
    +
    + +
    +

    Some pagination with page choice

    + {assign var=current_page value=2} +

    PAGE {$current_page} :

    +
      + {loop type="category" name="catloopwithpaginationchoice" limit="2" page="{$current_page}"} +
    • {$LOOP_COUNT}/{$LOOP_TOTAL} : {$ID} {$TITLE}
    • + {/loop} +
    +

    page choice

    + {pageloop rel="catloopwithpaginationchoice"} + {if ${PAGE} != {$current_page}} + {if {$PAGE} > {$current_page}-10 AND {$PAGE} < {$current_page}+10} + {$PAGE} + {/if} + {if {$PAGE} == {$current_page}-10 OR {$PAGE} == {$current_page}+10} + ... + {/if} + {if ({$PAGE} < {$current_page}-10 OR {$PAGE} > {$current_page}+10) AND ({$PAGE}%10 == 0 OR ${PAGE} == {$LAST} OR ${PAGE} == 1)} + {$PAGE} + {/if} + {else} + { {$PAGE} } + {/if} + {if {$PAGE} != {$LAST}} + - + {/if} + {/pageloop} +
    + +{include file="includes/footer.html"} \ No newline at end of file diff --git a/templates/default_save/login.html b/templates/default_save/login.html new file mode 100755 index 000000000..702f0a710 --- /dev/null +++ b/templates/default_save/login.html @@ -0,0 +1,49 @@ +{include file="includes/header.html"} + +

    {intl l='Please login'}

    + +{form name="thelia.customer.login" } + +
    + {* + The field below are not par of the Login form, it defines view to render if the form cannot be validated + *} + {* the view to return to if the form cannot be validated *} + + {* + This field is common to all BaseForm instances (thus, this one), and defines + the URL the customer is redirected to once the form has been successfully + processed + *} + + {form_field form=$form field='success_url'} + {* the url the user is redirected to on login success *} + {/form_field} + + {* + The form error status and the form error messages are defined in Customer action, + and passed back to the form plugin through the ParserContext. + *} + + {if #form_error}
    #form_error_message
    {/if} + + {form_hidden_fields form=$form} + + {form_field form=$form field="email"} + {if #error}{#message}{/if} +
    + {/form_field} + + {form_field form=$form field='password'} +
    + {/form_field} + + {form_field form=$form field='remember_me'} + + {/form_field} + + +
    +{/form} + +{include file='includes/footer.html'} \ No newline at end of file diff --git a/templates/default/myaccount.html b/templates/default_save/myaccount.html similarity index 100% rename from templates/default/myaccount.html rename to templates/default_save/myaccount.html diff --git a/templates/default/pagination.html b/templates/default_save/pagination.html similarity index 100% rename from templates/default/pagination.html rename to templates/default_save/pagination.html diff --git a/templates/default/product.html b/templates/default_save/product.html similarity index 85% rename from templates/default/product.html rename to templates/default_save/product.html index 4f82b5fb8..4280fc88c 100755 --- a/templates/default/product.html +++ b/templates/default_save/product.html @@ -13,6 +13,8 @@ Index : {navigate to="index"}

    #TITLE

    #DESCRIPTION

    +

    Starting by #BEST_PRICE € HT (TAX : #BEST_PRICE_TAX ; #BEST_TAXED_PRICE € TTC)

    + {ifloop rel="acc"}

    Accessories

      @@ -64,7 +66,7 @@ Index : {navigate to="index"}
      #ATTRIBUTE_TITLE = #ATTRIBUTE_AVAILABILITY_TITLE
      {/loop}
      #WEIGHT g -
      {if #IS_PROMO == 1} #PROMO_PRICE € (instead of #PRICE) {else} #PRICE € {/if} +
      {if #IS_PROMO == 1} #PROMO_PRICE € HT // TAX : #PROMO_PRICE_TAX ; #TAXED_PROMO_PRICE € TTC (instead of #PRICE HT // TAX : #PRICE_TAX ; #TAXED_PRICE € TTC){else} #PRICE € HT // TAX : #PRICE_TAX ; #TAXED_PRICE € TTC{/if}

      Add