add estimated shipping functionnality in cart
This commit is contained in:
@@ -38,6 +38,11 @@
|
||||
</call>
|
||||
</service>
|
||||
|
||||
<service id="smarty.plugin.cartpostage" class="Thelia\Core\Template\Smarty\Plugins\CartPostage" scope="request">
|
||||
<tag name="thelia.parser.register_plugin"/>
|
||||
<argument type="service" id="service_container" />
|
||||
</service>
|
||||
|
||||
<service id="smarty.plugin.type" class="Thelia\Core\Template\Smarty\Plugins\Type" scope="request">
|
||||
<tag name="thelia.parser.register_plugin"/>
|
||||
</service>
|
||||
|
||||
250
core/lib/Thelia/Core/Template/Smarty/Plugins/CartPostage.php
Normal file
250
core/lib/Thelia/Core/Template/Smarty/Plugins/CartPostage.php
Normal file
@@ -0,0 +1,250 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Core\Template\Smarty\Plugins;
|
||||
|
||||
use Propel\Runtime\ActiveQuery\Criteria;
|
||||
use Propel\Runtime\Util\PropelModelPager;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Thelia\Core\Template\Element\BaseLoop;
|
||||
use Thelia\Core\Template\Element\LoopResult;
|
||||
use Thelia\Core\Template\Smarty\AbstractSmartyPlugin;
|
||||
use Thelia\Core\Template\Smarty\SmartyPluginDescriptor;
|
||||
|
||||
use Thelia\Core\Template\Element\Exception\ElementNotFoundException;
|
||||
use Thelia\Core\Template\Element\Exception\InvalidElementException;
|
||||
use Thelia\Core\Translation\Translator;
|
||||
use Thelia\Log\Tlog;
|
||||
use Thelia\Model\AddressQuery;
|
||||
use Thelia\Model\ConfigQuery;
|
||||
use Thelia\Model\Country;
|
||||
use Thelia\Model\CountryQuery;
|
||||
use Thelia\Model\Customer;
|
||||
use Thelia\Model\ModuleQuery;
|
||||
use Thelia\Module\BaseModule;
|
||||
use Thelia\Module\DeliveryModuleInterface;
|
||||
use Thelia\Module\Exception\DeliveryException;
|
||||
|
||||
/**
|
||||
* Class CartPostage
|
||||
* @package Thelia\Core\Template\Smarty\Plugins
|
||||
*/
|
||||
class CartPostage extends AbstractSmartyPlugin
|
||||
{
|
||||
/** @var PropelModelPager[] */
|
||||
protected static $pagination = null;
|
||||
|
||||
protected $loopDefinition = array();
|
||||
|
||||
|
||||
/** @var \Thelia\Core\HttpFoundation\Request The Request */
|
||||
protected $request;
|
||||
|
||||
/** @var \Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher The Dispatcher */
|
||||
protected $dispatcher;
|
||||
|
||||
|
||||
/** @var \Thelia\Core\Security\SecurityContext The Security Context */
|
||||
protected $securityContext;
|
||||
|
||||
/** @var Translator */
|
||||
protected $translator;
|
||||
|
||||
/** @var ContainerInterface Service Container */
|
||||
protected $container = null;
|
||||
|
||||
/** @var integer $countryId the id of country */
|
||||
protected $countryId = null;
|
||||
|
||||
/** @var integer $deliveryId the id of the cheapest delivery */
|
||||
protected $deliveryId = null;
|
||||
|
||||
/** @var float $postage the postage amount */
|
||||
protected $postage = null;
|
||||
|
||||
/** @var boolean $isCustomizable indicate if customer can change the country */
|
||||
protected $isCustomizable = true;
|
||||
|
||||
|
||||
/**
|
||||
* @param ContainerInterface $container
|
||||
*/
|
||||
public function __construct(ContainerInterface $container)
|
||||
{
|
||||
$this->container = $container;
|
||||
|
||||
$this->request = $container->get('request');
|
||||
//$this->dispatcher = $container->get('event_dispatcher');
|
||||
//$this->securityContext = $container->get('thelia.securityContext');
|
||||
$this->translator = $container->get("thelia.translator");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get postage amount for cart
|
||||
*
|
||||
* @param array $params Block parameters
|
||||
* @param mixed $content Block content
|
||||
* @param \Smarty_Internal_Template $template Template
|
||||
* @param bool $repeat Control how many times
|
||||
* the block is displayed
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function postage($params, $content, $template, &$repeat)
|
||||
{
|
||||
|
||||
if ( ! $repeat) {
|
||||
return $content;
|
||||
}
|
||||
|
||||
$customer = $this->request->getSession()->getCustomerUser();
|
||||
$country = $this->getDeliveryCountry($customer);
|
||||
|
||||
if (null !== $country) {
|
||||
$this->countryId = $country->getId();
|
||||
// try to get the cheapest delivery for this country
|
||||
$this->getCheapestDelivery($country);
|
||||
}
|
||||
|
||||
$template->assign('country_id', $this->countryId);
|
||||
$template->assign('delivery_id', $this->deliveryId);
|
||||
$template->assign('postage', $this->postage ?: 0.0);
|
||||
$template->assign('is_customizable', $this->isCustomizable);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve the delivery country for a customer
|
||||
*
|
||||
* The rules :
|
||||
* - the country of the delivery address of the customer related to the
|
||||
* cart if it exists
|
||||
* - the country saved in cookie if customer have changed
|
||||
* the default country
|
||||
* - the default country for the shop if exists
|
||||
* - the country related to the customer based on browser preferences
|
||||
* - default country
|
||||
*
|
||||
*
|
||||
* @param \Thelia\Model\Customer $customer
|
||||
* @return \Thelia\Model\Country
|
||||
*/
|
||||
protected function getDeliveryCountry(Customer $customer = null)
|
||||
{
|
||||
|
||||
// get country from customer addresses
|
||||
if (null !== $customer){
|
||||
$address = AddressQuery::create()
|
||||
->filterByCustomerId($customer->getId())
|
||||
->filterByIsDefault(1)
|
||||
->findOne()
|
||||
;
|
||||
|
||||
if (null !== $address) {
|
||||
$this->isCustomizable = false;
|
||||
return $address->getCountry();
|
||||
}
|
||||
}
|
||||
|
||||
// get country from cookie
|
||||
$cookieName = ConfigQuery::read('front_cart_country_cookie_name', 'fcccn');
|
||||
if ($this->request->cookies->has($cookieName)) {
|
||||
$cookieVal = $this->request->cookies->getInt($cookieName, 0);
|
||||
if (0 !== $cookieVal){
|
||||
$country = CountryQuery::create()->findPk($cookieVal);
|
||||
if (null !== $country){
|
||||
return $country;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// get default country for store.
|
||||
try{
|
||||
$country = Country::getDefaultCountry();
|
||||
return $country;
|
||||
}
|
||||
catch (\LogicException $e) {
|
||||
;
|
||||
}
|
||||
|
||||
// get browser lang
|
||||
$lang_code= $this->request->getSession()->getLang()->getCode();
|
||||
if ($lang_code) {
|
||||
$country = CountryQuery::create()
|
||||
->findOneByIsoalpha2(strtoupper($lang_code));
|
||||
if (null !== $country) {
|
||||
return $country;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve the cheapest delivery for country
|
||||
*
|
||||
* @param \Thelia\Model\Country $country
|
||||
* @return DeliveryModuleInterface
|
||||
*/
|
||||
protected function getCheapestDelivery(Country $country)
|
||||
{
|
||||
|
||||
$deliveryModules = ModuleQuery::create()
|
||||
->filterByActivate(1)
|
||||
->filterByType(BaseModule::DELIVERY_MODULE_TYPE, Criteria::EQUAL)
|
||||
->find();
|
||||
;
|
||||
|
||||
foreach ($deliveryModules as $deliveryModule){
|
||||
|
||||
/** @var DeliveryModuleInterface $moduleInstance */
|
||||
$moduleInstance = $this->container->get(sprintf('module.%s', $deliveryModule->getCode()));
|
||||
|
||||
if (false === $moduleInstance instanceof DeliveryModuleInterface) {
|
||||
throw new \RuntimeException(sprintf("delivery module %s is not a Thelia\Module\DeliveryModuleInterface", $deliveryModule->getCode()));
|
||||
}
|
||||
|
||||
try {
|
||||
// Check if module is valid, by calling isValidDelivery(),
|
||||
// or catching a DeliveryException.
|
||||
if ($moduleInstance->isValidDelivery($country)) {
|
||||
|
||||
$postage = $moduleInstance->getPostage($country);
|
||||
if ( null === $this->postage || $this->postage > $postage) {
|
||||
$this->postage = $postage;
|
||||
$this->deliveryId = $deliveryModule->getId();
|
||||
}
|
||||
}
|
||||
} catch (DeliveryException $ex) {
|
||||
// Module is not available
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Defines the various smarty plugins handled by this class
|
||||
*
|
||||
* @return SmartyPluginDescriptor[] smarty plugin descriptors
|
||||
*/
|
||||
public function getPluginDescriptors()
|
||||
{
|
||||
return array(
|
||||
new SmartyPluginDescriptor('block', 'postage', $this, 'postage')
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -12,16 +12,24 @@
|
||||
|
||||
namespace Thelia\Tools;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Cookie;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Thelia\Log\Tlog;
|
||||
|
||||
class Redirect
|
||||
{
|
||||
public static function exec($url, $status = 302)
|
||||
public static function exec($url, $status = 302, $cookies = array())
|
||||
{
|
||||
if (false == Tlog::getInstance()->showRedirect($url)) {
|
||||
$response = new RedirectResponse($url, $status);
|
||||
|
||||
foreach ($cookies as $cookie)
|
||||
{
|
||||
if (!$cookie instanceof Cookie)
|
||||
{
|
||||
throw new \InvalidArgumentException(sprintf('Third parameter is not a valid Cookie object.'));
|
||||
}
|
||||
$response->headers->setCookie($cookie);
|
||||
}
|
||||
$response->send();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,6 +123,11 @@
|
||||
<default key="_controller">Front\Controller\CartController::changeItem</default>
|
||||
<default key="_view">cart</default>
|
||||
</route>
|
||||
|
||||
<route id="cart.update.country" path="/cart/country">
|
||||
<default key="_controller">Front\Controller\CartController::changeCountry</default>
|
||||
<default key="_view">cart</default>
|
||||
</route>
|
||||
<!-- end cart routes -->
|
||||
|
||||
<!-- order management process -->
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
namespace Front\Controller;
|
||||
|
||||
use Propel\Runtime\Exception\PropelException;
|
||||
use Symfony\Component\HttpFoundation\Cookie;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Thelia\Controller\Front\BaseFrontController;
|
||||
use Thelia\Core\Event\Cart\CartEvent;
|
||||
@@ -32,7 +33,9 @@ use Thelia\Form\CartAdd;
|
||||
use Thelia\Form\Exception\FormValidationException;
|
||||
use Thelia\Log\Tlog;
|
||||
use Thelia\Model\AddressQuery;
|
||||
use Thelia\Model\ConfigQuery;
|
||||
use Thelia\Module\Exception\DeliveryException;
|
||||
use Thelia\Tools\URL;
|
||||
|
||||
class CartController extends BaseFrontController
|
||||
{
|
||||
@@ -116,6 +119,19 @@ class CartController extends BaseFrontController
|
||||
|
||||
}
|
||||
|
||||
public function changeCountry()
|
||||
{
|
||||
$redirectUrl = URL::getInstance()->absoluteUrl("/cart");
|
||||
$deliveryId = $this->getRequest()->get("country");
|
||||
$cookieName = ConfigQuery::read('front_cart_country_cookie_name', 'fcccn');
|
||||
$cookieExpires = ConfigQuery::read('front_cart_country_cookie_expires', 2592000);
|
||||
$cookieExpires = intval($cookieExpires) ?: 2592000;
|
||||
|
||||
$cookie = new Cookie($cookieName, $deliveryId, time() + $cookieExpires, '/');
|
||||
|
||||
$this->redirect($redirectUrl, 302, array($cookie));
|
||||
}
|
||||
|
||||
/**
|
||||
* use Thelia\Cart\CartTrait for searching current cart or create a new one
|
||||
*
|
||||
|
||||
@@ -57,6 +57,7 @@ return array(
|
||||
'Edit' => 'Editer',
|
||||
'Edit this address' => 'Editer cette adresse',
|
||||
'Email address' => 'Adresse e-mail',
|
||||
'Estimated shipping ' => 'Estimation des frais de port',
|
||||
'Facebook' => 'Facebook',
|
||||
'Follow us' => 'Suivez-nous',
|
||||
'Follow us introduction' => 'Abonnez vous à nos pages',
|
||||
@@ -100,6 +101,7 @@ return array(
|
||||
'Next product' => 'Produit suivant.',
|
||||
'No Content in this folder.' => 'Aucun contenu dans ce dossier.',
|
||||
'No articles currently' => 'Aucun article en ce moment',
|
||||
'No deliveries available for this cart and this country' => 'Aucun mode de livraison disponible pour ce panier et ce pays',
|
||||
'No products available in this category' => 'Aucun produit dans cette catégorie.',
|
||||
'No results found' => 'Aucun résultat',
|
||||
'No.' => 'N°',
|
||||
@@ -166,6 +168,7 @@ return array(
|
||||
'Secure payment' => 'Paiement sécurisé',
|
||||
'Select Country' => 'Choisissez un pays',
|
||||
'Select Title' => 'Civilité',
|
||||
'Select your country:' => 'Sélectionnez votre pays :',
|
||||
'Send' => 'Envoyer',
|
||||
'Send us a message' => 'Envoyez nous un message.',
|
||||
'Shipping Tax' => 'Frais de livraison',
|
||||
@@ -214,7 +217,10 @@ return array(
|
||||
'Your order will be confirmed by us upon receipt of your payment.' => 'Votre commande sera confirmée à réception de votre paiement.',
|
||||
'Youtube' => 'Youtube',
|
||||
'deliveries' => 'Livraisons',
|
||||
'for' => 'pour',
|
||||
'instead of' => 'au lieu de',
|
||||
'missing or invalid data' => 'Information érronée ou incomplète',
|
||||
'per page' => 'par page',
|
||||
'update' => 'mettre à jour',
|
||||
'with:' => 'avec :',
|
||||
);
|
||||
|
||||
@@ -115,17 +115,57 @@
|
||||
<span class="price">{$real_price * $QUANTITY} {currency attr="symbol"}</span>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
{/loop}
|
||||
{postage}
|
||||
{assign var="postageAmount" value=$postage }
|
||||
<tr>
|
||||
<td class="product" colspan="2">
|
||||
<form action="{url path="/cart/country"}" class="form-inline" method="post">
|
||||
<h3>
|
||||
{intl l="Estimated shipping "}
|
||||
{if $is_customizable == false}
|
||||
{loop type="country" name="countryLoop" id="$country_id"}
|
||||
{intl l="for"} {$TITLE}
|
||||
{/loop}
|
||||
{/if}
|
||||
</h3>
|
||||
{if $is_customizable}
|
||||
<div>
|
||||
<label for="cart-country">{intl l="Select your country:"}</label>
|
||||
<select id="cart-country" name="country">
|
||||
{loop type="country" name="countryLoop" with_area="true"}
|
||||
<option value="{$ID}" {if $ID == $country_id }selected="selected" {/if}>{$TITLE}</option>
|
||||
{/loop}
|
||||
</select>
|
||||
<a class="btn btn-change-country" href="#"><i class="icon-refresh"></i> {intl l="update"}</a>
|
||||
</div>
|
||||
{/if}
|
||||
{if $delivery_id != 0 }
|
||||
<div>
|
||||
{intl l="with:"} {loop type="delivery" name="deliveryLoop" id=$delivery_id}{$TITLE} {/loop}
|
||||
</div>
|
||||
{else}
|
||||
<div class="alert alert-danger">
|
||||
{intl l="No deliveries available for this cart and this country"}
|
||||
</div>
|
||||
{/if}
|
||||
</form>
|
||||
</td>
|
||||
<td class="unitprice">{$postage} {currency attr="symbol"}</td>
|
||||
<td class="qty">-</td>
|
||||
<td class="subprice">{$postage} {currency attr="symbol"}</td>
|
||||
</tr>
|
||||
{/postage}
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr >
|
||||
<tr>
|
||||
<td colspan="3" class="empty"> </td>
|
||||
<th class="total">{intl l="Total"}</th>
|
||||
<td class="total">
|
||||
<div class="total-price">
|
||||
<span class="price">{cart attr="total_taxed_price_without_discount"} {currency attr="symbol"}</span>
|
||||
</div>
|
||||
{assign var="totalAmount" value={cart attr='total_taxed_price_without_discount'} + $postageAmount }
|
||||
<span class="price">{$totalAmount} {currency attr="symbol"}</span>
|
||||
</div>cart
|
||||
</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
@@ -169,6 +209,11 @@
|
||||
$("select[name=quantity]").change(function(){
|
||||
$(this).parents('form').submit();
|
||||
});
|
||||
$(".btn-change-country").click(function(e){
|
||||
e.preventDefault();
|
||||
var $form = $(this).parents('form');
|
||||
$form.submit();
|
||||
})
|
||||
});
|
||||
</script>
|
||||
{/block}
|
||||
|
||||
Reference in New Issue
Block a user