Merge pull request #310 from roadster31/modulesfix

Modulesfix
This commit is contained in:
Manuel Raynaud
2014-04-18 09:19:06 +02:00
13 changed files with 606 additions and 353 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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