diff --git a/core/lib/Thelia/Action/Order.php b/core/lib/Thelia/Action/Order.php index a8a8d5af9..a5d4b922c 100644 --- a/core/lib/Thelia/Action/Order.php +++ b/core/lib/Thelia/Action/Order.php @@ -106,7 +106,14 @@ class Order extends BaseAction implements EventSubscriberInterface { $order = $event->getOrder(); - $order->setDeliveryModuleId($event->getDeliveryModule()); + $deliveryModuleId = $event->getDeliveryModule(); + + $order->setDeliveryModuleId($deliveryModuleId); + + // Reset postage cost if the delivery module had been removed + if ($deliveryModuleId <= 0) { + $order->setPostage(0); + } $event->setOrder($order); } diff --git a/core/lib/Thelia/Core/Template/Loop/Delivery.php b/core/lib/Thelia/Core/Template/Loop/Delivery.php index 2e7391c95..3eb858eb4 100644 --- a/core/lib/Thelia/Core/Template/Loop/Delivery.php +++ b/core/lib/Thelia/Core/Template/Loop/Delivery.php @@ -25,10 +25,11 @@ namespace Thelia\Core\Template\Loop; use Thelia\Core\Template\Element\LoopResult; use Thelia\Core\Template\Element\LoopResultRow; use Thelia\Core\Template\Loop\Argument\Argument; -use Thelia\Exception\OrderException; use Thelia\Model\CountryQuery; +use Thelia\Model\Module; use Thelia\Module\BaseModule; use Thelia\Module\DeliveryModuleInterface; +use Thelia\Module\Exception\DeliveryException; /** * Class Delivery @@ -62,9 +63,11 @@ class Delivery extends BaseSpecificModule $country = $this->container->get('thelia.taxEngine')->getDeliveryCountry(); } + /** @var Module $deliveryModule */ foreach ($loopResult->getResultDataCollection() as $deliveryModule) { $loopResultRow = new LoopResultRow($deliveryModule); + /** @var DeliveryModuleInterface $moduleInstance */ $moduleInstance = $this->container->get(sprintf('module.%s', $deliveryModule->getCode())); if (false === $moduleInstance instanceof DeliveryModuleInterface) { @@ -72,28 +75,27 @@ class Delivery extends BaseSpecificModule } try { - $postage = $moduleInstance->getPostage($country); - } catch (OrderException $e) { - switch ($e->getCode()) { - case OrderException::DELIVERY_MODULE_UNAVAILABLE: - /* do not show this delivery module */ - continue(2); - break; - default: - throw $e; + // Check if module is valid, by calling isValidDelivery(), + // or catching a DeliveryException. + + if ($moduleInstance->isValidDelivery($country)) { + + $postage = $moduleInstance->getPostage($country); + + $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('POSTAGE', $postage) + ; + + $loopResult->addRow($loopResultRow); } + } catch (DeliveryException $ex) { + // Module is not available } - - $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('POSTAGE', $postage) - ; - - $loopResult->addRow($loopResultRow); } return $loopResult; @@ -103,4 +105,4 @@ class Delivery extends BaseSpecificModule { return BaseModule::DELIVERY_MODULE_TYPE; } -} +} \ No newline at end of file diff --git a/core/lib/Thelia/Form/BaseForm.php b/core/lib/Thelia/Form/BaseForm.php index 8dff18cfc..9fd287004 100644 --- a/core/lib/Thelia/Form/BaseForm.php +++ b/core/lib/Thelia/Form/BaseForm.php @@ -1,246 +1,246 @@ -. */ -/* */ -/*************************************************************************************/ -namespace Thelia\Form; - -use Symfony\Component\Form\Extension\Validator\ValidatorExtension; -use Symfony\Component\Form\Forms; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationExtension; -use Symfony\Component\Form\Extension\Csrf\CsrfExtension; -use Symfony\Component\Form\Extension\Csrf\CsrfProvider\SessionCsrfProvider; -use Symfony\Component\Validator\Validation; -use Thelia\Core\Translation\Translator; -use Thelia\Model\ConfigQuery; -use Thelia\Tools\URL; - -/** - * Base form class for creating form objects - * - * Class BaseForm - * @package Thelia\Form - * @author Manuel Raynaud - */ -abstract class BaseForm -{ - /** - * @var \Symfony\Component\Form\FormFactoryInterface - */ - protected $formBuilder; - - /** - * @var \Symfony\Component\Form\Form - */ - protected $form; - - protected $request; - - private $view = null; - - /** - * true if the form has an error, false otherwise. - * @var boolean - */ - private $has_error = false; - - /** - * The form error message. - * @var string - */ - private $error_message = ''; - - public function __construct(Request $request, $type= "form", $data = array(), $options = array()) - { - $this->request = $request; - - $validator = Validation::createValidatorBuilder(); - - if (!isset($options["attr"]["name"])) { - $options["attr"]["thelia_name"] = $this->getName(); - } - - $builder = Forms::createFormFactoryBuilder() - ->addExtension(new HttpFoundationExtension()); - if (!isset($options["csrf_protection"]) || $options["csrf_protection"] !== false) { - $builder->addExtension( - new CsrfExtension( - new SessionCsrfProvider( - $request->getSession(), - isset($options["secret"]) ? $options["secret"] : ConfigQuery::read("form.secret", md5(__DIR__)) - ) - ) - ); - } - - $translator = Translator::getInstance(); - - $validator - ->setTranslationDomain('validators') - ->setTranslator($translator); - $this->formBuilder = $builder - ->addExtension(new ValidatorExtension($validator->getValidator())) - ->getFormFactory() - ->createNamedBuilder($this->getName(), $type, $data, $this->cleanOptions($options)); - ; - - $this->buildForm(); - - // If not already set, define the success_url field - if (! $this->formBuilder->has('success_url')) { - $this->formBuilder->add("success_url", "text"); - } - - if (! $this->formBuilder->has('error_message')) { - $this->formBuilder->add("error_message", "text"); - } - - $this->form = $this->formBuilder->getForm(); - } - - public function getRequest() - { - return $this->request; - } - - protected function cleanOptions($options) - { - unset($options["csrf_protection"]); - - return $options; - } - - /** - * Returns the absolute URL to redirect the user to if the form is successfully processed. - * - * @param string $default the default URL. If not given, the configured base URL is used. - * - * @return string an absolute URL - */ - public function getSuccessUrl($default = null) - { - $successUrl = $this->form->get('success_url')->getData(); - - if (empty($successUrl)) { - - if ($default === null) $default = ConfigQuery::read('base_url', '/'); - - $successUrl = $default; - } - - return URL::getInstance()->absoluteUrl($successUrl); - } - - public function createView() - { - $this->view = $this->form->createView(); - - return $this; - } - - public function getView() - { - if ($this->view === null) throw new \LogicException("View was not created. Please call BaseForm::createView() first."); - return $this->view; - } - - // -- Error and errro message ---------------------------------------------- - - /** - * Set the error status of the form. - * - * @param boolean $has_error - */ - public function setError($has_error = true) - { - $this->has_error = $has_error; - - return $this; - } - - /** - * Get the cuirrent error status of the form. - * - * @return boolean - */ - public function hasError() - { - return $this->has_error; - } - - /** - * Set the error message related to global form error - * - * @param unknown $message - */ - public function setErrorMessage($message) - { - $this->setError(true); - $this->error_message = $message; - - return $this; - } - - /** - * Get the form error message. - * - * @return string - */ - public function getErrorMessage() - { - return $this->error_message; - } - - /** - * @return \Symfony\Component\Form\Form - */ - public function getForm() - { - return $this->form; - } - - /** - * - * in this function you add all the fields you need for your Form. - * Form this you have to call add method on $this->formBuilder attribute : - * - * $this->formBuilder->add("name", "text") - * ->add("email", "email", array( - * "attr" => array( - * "class" => "field" - * ), - * "label" => "email", - * "constraints" => array( - * new \Symfony\Component\Validator\Constraints\NotBlank() - * ) - * ) - * ) - * ->add('age', 'integer'); - * - * @return null - */ - abstract protected function buildForm(); - - /** - * @return string the name of you form. This name must be unique - */ - abstract public function getName(); -} +. */ +/* */ +/*************************************************************************************/ +namespace Thelia\Form; + +use Symfony\Component\Form\Extension\Validator\ValidatorExtension; +use Symfony\Component\Form\Forms; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationExtension; +use Symfony\Component\Form\Extension\Csrf\CsrfExtension; +use Symfony\Component\Form\Extension\Csrf\CsrfProvider\SessionCsrfProvider; +use Symfony\Component\Validator\Validation; +use Thelia\Core\Translation\Translator; +use Thelia\Model\ConfigQuery; +use Thelia\Tools\URL; + +/** + * Base form class for creating form objects + * + * Class BaseForm + * @package Thelia\Form + * @author Manuel Raynaud + */ +abstract class BaseForm +{ + /** + * @var \Symfony\Component\Form\FormFactoryInterface + */ + protected $formBuilder; + + /** + * @var \Symfony\Component\Form\Form + */ + protected $form; + + protected $request; + + private $view = null; + + /** + * true if the form has an error, false otherwise. + * @var boolean + */ + private $has_error = false; + + /** + * The form error message. + * @var string + */ + private $error_message = ''; + + public function __construct(Request $request, $type= "form", $data = array(), $options = array()) + { + $this->request = $request; + + $validator = Validation::createValidatorBuilder(); + + if (!isset($options["attr"]["name"])) { + $options["attr"]["thelia_name"] = $this->getName(); + } + + $builder = Forms::createFormFactoryBuilder() + ->addExtension(new HttpFoundationExtension()); + if (!isset($options["csrf_protection"]) || $options["csrf_protection"] !== false) { + $builder->addExtension( + new CsrfExtension( + new SessionCsrfProvider( + $request->getSession(), + isset($options["secret"]) ? $options["secret"] : ConfigQuery::read("form.secret", md5(__DIR__)) + ) + ) + ); + } + + $translator = Translator::getInstance(); + + $validator + ->setTranslationDomain('validators') + ->setTranslator($translator); + $this->formBuilder = $builder + ->addExtension(new ValidatorExtension($validator->getValidator())) + ->getFormFactory() + ->createNamedBuilder($this->getName(), $type, $data, $this->cleanOptions($options)); + ; + + $this->buildForm(); + + // If not already set, define the success_url field + if (! $this->formBuilder->has('success_url')) { + $this->formBuilder->add("success_url", "text"); + } + + if (! $this->formBuilder->has('error_message')) { + $this->formBuilder->add("error_message", "text"); + } + + $this->form = $this->formBuilder->getForm(); + } + + public function getRequest() + { + return $this->request; + } + + protected function cleanOptions($options) + { + unset($options["csrf_protection"]); + + return $options; + } + + /** + * Returns the absolute URL to redirect the user to if the form is successfully processed. + * + * @param string $default the default URL. If not given, the configured base URL is used. + * + * @return string an absolute URL + */ + public function getSuccessUrl($default = null) + { + $successUrl = $this->form->get('success_url')->getData(); + + if (empty($successUrl)) { + + if ($default === null) $default = ConfigQuery::read('base_url', '/'); + + $successUrl = $default; + } + + return URL::getInstance()->absoluteUrl($successUrl); + } + + public function createView() + { + $this->view = $this->form->createView(); + + return $this; + } + + public function getView() + { + if ($this->view === null) throw new \LogicException("View was not created. Please call BaseForm::createView() first."); + return $this->view; + } + + // -- Error and errro message ---------------------------------------------- + + /** + * Set the error status of the form. + * + * @param boolean $has_error + */ + public function setError($has_error = true) + { + $this->has_error = $has_error; + + return $this; + } + + /** + * Get the cuirrent error status of the form. + * + * @return boolean + */ + public function hasError() + { + return $this->has_error; + } + + /** + * Set the error message related to global form error + * + * @param string $message + */ + public function setErrorMessage($message) + { + $this->setError(true); + $this->error_message = $message; + + return $this; + } + + /** + * Get the form error message. + * + * @return string + */ + public function getErrorMessage() + { + return $this->error_message; + } + + /** + * @return \Symfony\Component\Form\Form + */ + public function getForm() + { + return $this->form; + } + + /** + * + * in this function you add all the fields you need for your Form. + * Form this you have to call add method on $this->formBuilder attribute : + * + * $this->formBuilder->add("name", "text") + * ->add("email", "email", array( + * "attr" => array( + * "class" => "field" + * ), + * "label" => "email", + * "constraints" => array( + * new \Symfony\Component\Validator\Constraints\NotBlank() + * ) + * ) + * ) + * ->add('age', 'integer'); + * + * @return null + */ + abstract protected function buildForm(); + + /** + * @return string the name of you form. This name must be unique + */ + abstract public function getName(); +} diff --git a/core/lib/Thelia/Module/AbstractDeliveryModule.php b/core/lib/Thelia/Module/AbstractDeliveryModule.php new file mode 100644 index 000000000..9e9710534 --- /dev/null +++ b/core/lib/Thelia/Module/AbstractDeliveryModule.php @@ -0,0 +1,53 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Module; + +use Thelia\Model\Country; +use Thelia\Module\Exception\DeliveryException; + +abstract class AbstractDeliveryModule extends BaseModule implements DeliveryModuleInterface +{ + /** + * This method is called by the Delivery loop, to check if the current module has to be displayed to the customer. + * Override it to implements your delivery rules/ + * + * If you return true, the delivery method will de displayed to the customer + * If you return false, the delivery method will not be displayed + * + * @param Country $country the country to deliver to. + * + * @return boolean + */ + public abstract function isValidDelivery(Country $country); + + /** + * Calculate and return delivery price in the shop's default currency + * + * @param Country $country the country to deliver to. + * + * @return float the delivery price + * @throws DeliveryException if the postage price cannot be calculated. + */ + public abstract function getPostage(Country $country); +} \ No newline at end of file diff --git a/core/lib/Thelia/Module/AbstractPaymentModule.php b/core/lib/Thelia/Module/AbstractPaymentModule.php index 7936dee16..5c2e4cec8 100644 --- a/core/lib/Thelia/Module/AbstractPaymentModule.php +++ b/core/lib/Thelia/Module/AbstractPaymentModule.php @@ -33,7 +33,7 @@ use Thelia\Tools\URL; abstract class AbstractPaymentModule extends BaseModule implements PaymentModuleInterface { /** - * This method is called when the payement gateway needs to be invoked. + * This method is called when the payment gateway needs to be invoked. * * If this method return a Response instance, this response is sent to the browser. Return null if you don't want to * send a response and process the payment yourself. @@ -91,9 +91,9 @@ abstract class AbstractPaymentModule extends BaseModule implements PaymentModule * @param int $order_id the order ID * @return string the order payment success page URL */ - public function getPayementSuccessPageUrl($order_id) + public function getPaymentSuccessPageUrl($order_id) { - $frontOfficeRouter = $this->container->get('router.front'); + $frontOfficeRouter = $this->getContainer()->get('router.front'); return URL::getInstance()->absoluteUrl( $frontOfficeRouter->generate( @@ -112,9 +112,9 @@ abstract class AbstractPaymentModule extends BaseModule implements PaymentModule * * @return string the order payment failure page URL */ - public function getPayementFailurePageUrl($order_id, $message) + public function getPaymentFailurePageUrl($order_id, $message) { - $frontOfficeRouter = $this->container->get('router.front'); + $frontOfficeRouter = $this->getContainer()->get('router.front'); return URL::getInstance()->absoluteUrl( $frontOfficeRouter->generate( @@ -127,4 +127,4 @@ abstract class AbstractPaymentModule extends BaseModule implements PaymentModule ) ); } -} +} \ No newline at end of file diff --git a/core/lib/Thelia/Module/BaseModule.php b/core/lib/Thelia/Module/BaseModule.php index 7fc3a16f7..6390785ec 100644 --- a/core/lib/Thelia/Module/BaseModule.php +++ b/core/lib/Thelia/Module/BaseModule.php @@ -30,19 +30,19 @@ use Symfony\Component\DependencyInjection\ContainerAware; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\HttpFoundation\Request; use Thelia\Core\HttpFoundation\Session\Session; +use Thelia\Exception\ModuleException; use Thelia\Model\Cart; use Thelia\Model\Country; -use Thelia\Model\Map\ModuleTableMap; -use Thelia\Model\ModuleI18nQuery; use Thelia\Model\Map\ModuleImageTableMap; +use Thelia\Model\Map\ModuleTableMap; +use Thelia\Model\Module; use Thelia\Model\ModuleI18n; +use Thelia\Model\ModuleI18nQuery; +use Thelia\Model\ModuleImage; +use Thelia\Model\ModuleQuery; use Thelia\Model\Order; use Thelia\TaxEngine\TaxEngine; use Thelia\Tools\Image; -use Thelia\Exception\ModuleException; -use Thelia\Model\Module; -use Thelia\Model\ModuleImage; -use Thelia\Model\ModuleQuery; class BaseModule extends ContainerAware implements BaseModuleInterface { @@ -138,7 +138,7 @@ class BaseModule extends ContainerAware implements BaseModuleInterface { if ($this->hasRequest() === false) { // Try to get request from container. - $this->setRequest($this->container->get('request')); + $this->setRequest($this->getContainer()->get('request')); } if ($this->hasRequest() === false) { @@ -171,7 +171,7 @@ class BaseModule extends ContainerAware implements BaseModuleInterface * Sets a module titles for various languages * * @param Module $module the module. - * @param $titles an associative array of locale => title_string + * @param array $titles an associative array of locale => title_string */ public function setTitle(Module $module, $titles) { @@ -197,8 +197,7 @@ class BaseModule extends ContainerAware implements BaseModuleInterface /** * Ensure the proper deployment of the module's images. * - * TODO : clarify the purpose of ModuleImage. How this table will be used elswhere in Thelia ? - * TODO : this method doesn't take care of internationalization. This is a bug. + * TODO : this method does not take care of internationalization. This is a bug. * * @param Module $module the module * @param string $folderPath the image folder path @@ -223,6 +222,7 @@ class BaseModule extends ContainerAware implements BaseModuleInterface /* browse the directory */ $imagePosition = 1; + /** @var \DirectoryIterator $directoryContent */ foreach ($directoryBrowser as $directoryContent) { /* is it a file ? */ if ($directoryContent->isFile()) { @@ -347,7 +347,7 @@ class BaseModule extends ContainerAware implements BaseModuleInterface $order = $session->getOrder(); /** @var TaxEngine $taxEngine */ - $taxEngine = $this->container->get("thelia.taxengine"); + $taxEngine = $this->getContainer()->get("thelia.taxengine"); /** @var Country $country */ $country = $taxEngine->getDeliveryCountry(); @@ -363,7 +363,7 @@ class BaseModule extends ContainerAware implements BaseModuleInterface /** * - * This method allow adding new compilers to Thelia container + * This method adds new compilers to Thelia container * * You must return an array. This array can contain : * - arrays @@ -409,7 +409,7 @@ class BaseModule extends ContainerAware implements BaseModuleInterface */ public function install(ConnectionInterface $con = null) { - // Implement this method to do something useful. + // Override this method to do something useful. } /** @@ -463,4 +463,4 @@ class BaseModule extends ContainerAware implements BaseModuleInterface { // Override this method to do something useful. } -} +} \ No newline at end of file diff --git a/core/lib/Thelia/Module/DeliveryModuleInterface.php b/core/lib/Thelia/Module/DeliveryModuleInterface.php index 17b000d4f..1f6bc5f70 100644 --- a/core/lib/Thelia/Module/DeliveryModuleInterface.php +++ b/core/lib/Thelia/Module/DeliveryModuleInterface.php @@ -24,15 +24,30 @@ namespace Thelia\Module; use Thelia\Model\Country; +use Thelia\Module\Exception\DeliveryException; interface DeliveryModuleInterface extends BaseModuleInterface { /** - * calculate and return delivery price + * This method is called by the Delivery loop, to check if the current module has to be displayed to the customer. + * Override it to implements your delivery rules/ * - * @param Country $country + * If you return true, the delivery method will de displayed to the customer + * If you return false, the delivery method will not be displayed * - * @return mixed + * @param Country $country the country to deliver to. + * + * @return boolean + */ + public function isValidDelivery(Country $country); + + /** + * Calculate and return delivery price in the shop's default currency + * + * @param Country $country the country to deliver to. + * + * @return float the delivery price + * @throws DeliveryException if the postage price cannot be calculated. */ public function getPostage(Country $country); } diff --git a/core/lib/Thelia/Module/Exception/DeliveryException.php b/core/lib/Thelia/Module/Exception/DeliveryException.php new file mode 100644 index 000000000..12a758d24 --- /dev/null +++ b/core/lib/Thelia/Module/Exception/DeliveryException.php @@ -0,0 +1,28 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Module\Exception; + +class DeliveryException extends \RuntimeException +{ +} diff --git a/local/modules/Colissimo/Colissimo.php b/local/modules/Colissimo/Colissimo.php index 90d32df35..eb6b53dda 100755 --- a/local/modules/Colissimo/Colissimo.php +++ b/local/modules/Colissimo/Colissimo.php @@ -25,15 +25,14 @@ namespace Colissimo; use Colissimo\Model\ColissimoFreeshippingQuery; use Propel\Runtime\Connection\ConnectionInterface; -use Symfony\Component\EventDispatcher\EventDispatcherInterface; -use Symfony\Component\HttpFoundation\Request; +use Thelia\Core\Translation\Translator; use Thelia\Exception\OrderException; use Thelia\Install\Database; use Thelia\Model\Country; -use Thelia\Module\BaseModule; -use Thelia\Module\DeliveryModuleInterface; +use Thelia\Module\AbstractDeliveryModule; +use Thelia\Module\Exception\DeliveryException; -class Colissimo extends BaseModule implements DeliveryModuleInterface +class Colissimo extends AbstractDeliveryModule { protected $request; protected $dispatcher; @@ -44,13 +43,38 @@ class Colissimo extends BaseModule implements DeliveryModuleInterface public static function getPrices() { - if(null === self::$prices) { + if (null === self::$prices) { self::$prices = json_decode(file_get_contents(sprintf('%s%s', __DIR__, self::JSON_PRICE_RESOURCE)), true); } return self::$prices; } + public function isValidDelivery(Country $country) { + + $areaId = $country->getAreaId(); + + $prices = self::getPrices(); + + /* Check if Colissimo delivers the area */ + if (isset($prices[$areaId]) && isset($prices[$areaId]["slices"])) { + + // Yes ! Check if the cart weight is below slice limit + $areaPrices = $prices[$areaId]["slices"]; + ksort($areaPrices); + + /* Check cart weight is below the maximum weight */ + end($areaPrices); + $maxWeight = key($areaPrices); + + $cartWeight = $this->getRequest()->getSession()->getCart()->getWeight(); + + if ($cartWeight <= $maxWeight) return true; + } + + return false; + } + /** * @param $areaId * @param $weight @@ -61,29 +85,36 @@ class Colissimo extends BaseModule implements DeliveryModuleInterface public static function getPostageAmount($areaId, $weight) { $freeshipping = ColissimoFreeshippingQuery::create()->getLast(); - $postage=0; - if(!$freeshipping) { + $postage = 0; + if (!$freeshipping) { $prices = self::getPrices(); /* check if Colissimo delivers the asked area */ - if(!isset($prices[$areaId]) || !isset($prices[$areaId]["slices"])) { - throw new OrderException("Colissimo delivery unavailable for the chosen delivery country", OrderException::DELIVERY_MODULE_UNAVAILABLE); + if (!isset($prices[$areaId]) || !isset($prices[$areaId]["slices"])) { + throw new DeliveryException( + Translator::getInstance()->trans("Colissimo delivery unavailable for the delivery country") + ); } $areaPrices = $prices[$areaId]["slices"]; ksort($areaPrices); - /* check this weight is not too much */ + /* Check cart weight is below the maximum weight */ end($areaPrices); $maxWeight = key($areaPrices); - if($weight > $maxWeight) { - throw new OrderException(sprintf("Colissimo delivery unavailable for this cart weight (%s kg)", $weight), OrderException::DELIVERY_MODULE_UNAVAILABLE); + if ($weight > $maxWeight) { + throw new DeliveryException( + Translator::getInstance()->trans( + "Colissimo delivery unavailable for this cart weight (%weight kg)", + array("%weight" => $weight) + ) + ); } $postage = current($areaPrices); - while(prev($areaPrices)) { - if($weight > key($areaPrices)) { + while (prev($areaPrices)) { + if ($weight > key($areaPrices)) { break; } @@ -94,29 +125,9 @@ class Colissimo extends BaseModule implements DeliveryModuleInterface } - 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; - } - public function postActivation(ConnectionInterface $con = null) { - $database = new Database($con->getWrappedConnection()); + $database = new Database($con); $database->insertSql(null, array(__DIR__ . '/Config/thelia.sql')); } @@ -131,7 +142,7 @@ class Colissimo extends BaseModule implements DeliveryModuleInterface */ public function getPostage(Country $country) { - $cartWeight = $this->getContainer()->get('request')->getSession()->getCart()->getWeight(); + $cartWeight = $this->getRequest()->getSession()->getCart()->getWeight(); $postage = self::getPostageAmount( $country->getAreaId(), @@ -140,10 +151,4 @@ class Colissimo extends BaseModule implements DeliveryModuleInterface return $postage; } - - public function getCode() - { - return 'Colissimo'; - } - -} +} \ No newline at end of file diff --git a/local/modules/Colissimo/Config/prices.json b/local/modules/Colissimo/Config/prices.json index 3fc2e0cd7..1b23c825c 100755 --- a/local/modules/Colissimo/Config/prices.json +++ b/local/modules/Colissimo/Config/prices.json @@ -1 +1,120 @@ -{"1":{"_info":"area 1 : France","slices":{"0.25":"5.23","0.5":5.8,"0.75":6.56,"1":7.13,"2":8.08,"3":9.22,"5":11.31,"7":13.4,"10":16.53,"15":19.14,"30":26.93}},"2":{"_info":"area 2 : A Zone - Union Europ\u00e9enne et Suisse","slices":{"1":15.34,"2":16.96,"3":20.47,"4":23.99,"5":27.5,"6":31.02,"7":34.53,"8":38.05,"9":41.56,"10":45.08,"15":51.92,"20":58.76,"25":65.6,"30":72.44}},"3":{"_info":"area 3 : B Zone - Pays de l\u2019Europe de l\u2019Est (hors Union Europ\u00e9enne), Norv\u00e8ge, Maghreb","slices":{"1":18.81,"2":20.62,"3":24.94,"4":29.26,"5":33.58,"6":37.91,"7":42.23,"8":46.55,"9":50.87,"10":55.2,"15":65.08,"20":74.96}},"4":{"_info":"area 4 : C Zone - Pays d\u2019Afrique hors Maghreb, Canada, Etats-Unis, Proche et Moyen Orient","slices":{"1":22.04,"2":29.55,"3":38.86,"4":48.17,"5":57.48,"6":66.79,"7":76.1,"8":85.41,"9":94.72,"10":104.03,"15":126.92,"20":149.82}},"5":{"_info":"area 5 : D Zone - Autres destinations","slices":{"1":25.08,"2":37.72,"3":50.26,"4":62.8,"5":75.34,"6":87.88,"7":100.42,"8":112.96,"9":125.5,"10":138.04,"15":162.74,"20":187.44}},"6":{"_info":"area 6 : France OM1","slices":{"0.5":8.27,"1":12.49,"2":17.05,"3":21.61,"4":26.17,"5":30.73,"6":35.29,"7":39.85,"8":44.41,"9":48.97,"10":53.53,"15":76.33,"20":99.13,"25":121.93,"30":144.73}},"7":{"_info":"area 7 : France OM2","slices":{"0.5":9.88,"1":14.92,"2":26.32,"3":37.72,"4":49.12,"5":60.52,"6":71.92,"7":83.32,"8":94.72,"9":106.12,"10":117.52,"15":174.52,"20":231.52,"25":288.52,"30":345.52}}} \ No newline at end of file +{"1": { + "_info": "area 1 : France", + "slices": { + "0.25": "5.23", + "0.5": 5.8, + "0.75": 6.56, + "1": 7.13, + "2": 8.08, + "3": 9.22, + "5": 11.31, + "7": 13.4, + "10": 16.53, + "15": 19.14, + "30": 26.93 + } +}, "2": { + "_info": "area 2 : A Zone - Union Europ\u00e9enne et Suisse", + "slices": { + "1": 15.34, + "2": 16.96, + "3": 20.47, + "4": 23.99, + "5": 27.5, + "6": 31.02, + "7": 34.53, + "8": 38.05, + "9": 41.56, + "10": 45.08, + "15": 51.92, + "20": 58.76, + "25": 65.6, + "30": 72.44 + } +}, "3": { + "_info": "area 3 : B Zone - Pays de l\u2019Europe de l\u2019Est (hors Union Europ\u00e9enne), Norv\u00e8ge, Maghreb", + "slices": { + "1": 18.81, + "2": 20.62, + "3": 24.94, + "4": 29.26, + "5": 33.58, + "6": 37.91, + "7": 42.23, + "8": 46.55, + "9": 50.87, + "10": 55.2, + "15": 65.08, + "20": 74.96 + } +}, "4": { + "_info": "area 4 : C Zone - Pays d\u2019Afrique hors Maghreb, Canada, Etats-Unis, Proche et Moyen Orient", + "slices": { + "1": 22.04, + "2": 29.55, + "3": 38.86, + "4": 48.17, + "5": 57.48, + "6": 66.79, + "7": 76.1, + "8": 85.41, + "9": 94.72, + "10": 104.03, + "15": 126.92, + "20": 149.82 + } +}, "5": { + "_info": "area 5 : D Zone - Autres destinations", + "slices": { + "1": 25.08, + "2": 37.72, + "3": 50.26, + "4": 62.8, + "5": 75.34, + "6": 87.88, + "7": 100.42, + "8": 112.96, + "9": 125.5, + "10": 138.04, + "15": 162.74, + "20": 187.44 + } +}, "6": { + "_info": "area 6 : France OM1", + "slices": { + "0.5": 8.27, + "1": 12.49, + "2": 17.05, + "3": 21.61, + "4": 26.17, + "5": 30.73, + "6": 35.29, + "7": 39.85, + "8": 44.41, + "9": 48.97, + "10": 53.53, + "15": 76.33, + "20": 99.13, + "25": 121.93, + "30": 144.73 + } +}, "7": { + "_info": "area 7 : France OM2", + "slices": { + "0.5": 9.88, + "1": 14.92, + "2": 26.32, + "3": 37.72, + "4": 49.12, + "5": 60.52, + "6": 71.92, + "7": 83.32, + "8": 94.72, + "9": 106.12, + "10": 117.52, + "15": 174.52, + "20": 231.52, + "25": 288.52, + "30": 345.52 + } +}} \ No newline at end of file diff --git a/local/modules/Front/Controller/CartController.php b/local/modules/Front/Controller/CartController.php index 59110d62a..ceda20751 100644 --- a/local/modules/Front/Controller/CartController.php +++ b/local/modules/Front/Controller/CartController.php @@ -23,14 +23,16 @@ namespace Front\Controller; use Propel\Runtime\Exception\PropelException; -use Thelia\Controller\Front\BaseFrontController; -use Thelia\Core\Event\Order\OrderEvent; -use Thelia\Form\Exception\FormValidationException; -use Thelia\Core\Event\Cart\CartEvent; -use Thelia\Core\Event\TheliaEvents; use Symfony\Component\HttpFoundation\Request; +use Thelia\Controller\Front\BaseFrontController; +use Thelia\Core\Event\Cart\CartEvent; +use Thelia\Core\Event\Order\OrderEvent; +use Thelia\Core\Event\TheliaEvents; use Thelia\Form\CartAdd; +use Thelia\Form\Exception\FormValidationException; +use Thelia\Log\Tlog; use Thelia\Model\AddressQuery; +use Thelia\Module\Exception\DeliveryException; class CartController extends BaseFrontController { @@ -60,7 +62,7 @@ class CartController extends BaseFrontController $this->redirectSuccess(); } catch (PropelException $e) { - \Thelia\Log\Tlog::getInstance()->error(sprintf("Failed to add item to cart with message : %s", $e->getMessage())); + Tlog::getInstance()->error(sprintf("Failed to add item to cart with message : %s", $e->getMessage())); $message = "Failed to add this article to your cart, please try again"; } catch (FormValidationException $e) { $message = $e->getMessage(); @@ -108,7 +110,7 @@ class CartController extends BaseFrontController $this->redirectSuccess(); } catch (PropelException $e) { - \Thelia\Log\Tlog::getInstance()->error(sprintf("error during deleting cartItem with message : %s", $e->getMessage())); + Tlog::getInstance()->error(sprintf("error during deleting cartItem with message : %s", $e->getMessage())); $this->getParserContext()->setGeneralError($e->getMessage()); } @@ -160,14 +162,24 @@ class CartController extends BaseFrontController if (null !== $deliveryModule && null !== $deliveryAddress) { $moduleInstance = $this->container->get(sprintf('module.%s', $deliveryModule->getCode())); - $postage = $moduleInstance->getPostage($deliveryAddress->getCountry()); $orderEvent = new OrderEvent($order); - $orderEvent->setPostage($postage); - $this->getDispatcher()->dispatch(TheliaEvents::ORDER_SET_POSTAGE, $orderEvent); + try { + $postage = $moduleInstance->getPostage($deliveryAddress->getCountry()); + + $orderEvent->setPostage($postage); + + $this->getDispatcher()->dispatch(TheliaEvents::ORDER_SET_POSTAGE, $orderEvent); + } + catch (DeliveryException $ex) { + // The postage has been chosen, but changes in the cart causes an exception. + // Reset the postage data in the order + $orderEvent->setDeliveryModule(0); + + $this->getDispatcher()->dispatch(TheliaEvents::ORDER_SET_DELIVERY_MODULE, $orderEvent); + } } } } - } diff --git a/local/modules/Front/Controller/CouponController.php b/local/modules/Front/Controller/CouponController.php index ba7433612..3c3c025ab 100644 --- a/local/modules/Front/Controller/CouponController.php +++ b/local/modules/Front/Controller/CouponController.php @@ -26,11 +26,12 @@ use Propel\Runtime\Exception\PropelException; use Thelia\Controller\Front\BaseFrontController; use Thelia\Core\Event\Coupon\CouponConsumeEvent; use Thelia\Core\Event\Order\OrderEvent; +use Thelia\Core\Event\TheliaEvents; use Thelia\Form\CouponCode; use Thelia\Form\Exception\FormValidationException; -use Thelia\Core\Event\TheliaEvents; use Thelia\Log\Tlog; use Thelia\Model\AddressQuery; +use Thelia\Module\Exception\DeliveryException; /** * Class CouponController @@ -74,12 +75,23 @@ class CouponController extends BaseFrontController if (null !== $deliveryModule && null !== $deliveryAddress) { $moduleInstance = $this->container->get(sprintf('module.%s', $deliveryModule->getCode())); - $postage = $moduleInstance->getPostage($deliveryAddress->getCountry()); $orderEvent = new OrderEvent($order); - $orderEvent->setPostage($postage); - $this->getDispatcher()->dispatch(TheliaEvents::ORDER_SET_POSTAGE, $orderEvent); + try { + $postage = $moduleInstance->getPostage($deliveryAddress->getCountry()); + + $orderEvent->setPostage($postage); + + $this->getDispatcher()->dispatch(TheliaEvents::ORDER_SET_POSTAGE, $orderEvent); + } + catch (DeliveryException $ex) { + // The postage has been chosen, but changes dues to coupon causes an exception. + // Reset the postage data in the order + $orderEvent->setDeliveryModule(0); + + $this->getDispatcher()->dispatch(TheliaEvents::ORDER_SET_DELIVERY_MODULE, $orderEvent); + } } } diff --git a/web/.htaccess b/web/.htaccess index dfe03bf51..5c957964e 100755 --- a/web/.htaccess +++ b/web/.htaccess @@ -1,4 +1,4 @@ -#Options +FollowSymlinks -Indexes +Options +FollowSymlinks -Indexes AddDefaultCharset UTF-8