From ac51ab21e4482cce29d16e0dd5999080c5f8a9ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Chans=C3=A9aume?= Date: Fri, 25 Apr 2014 09:43:22 +0200 Subject: [PATCH] add estimated shipping functionnality in cart --- .../Thelia/Config/Resources/smarty-plugin.xml | 5 + .../Template/Smarty/Plugins/CartPostage.php | 250 ++++++++++++++++++ core/lib/Thelia/Tools/Redirect.php | 12 +- local/modules/Front/Config/front.xml | 5 + .../Front/Controller/CartController.php | 16 ++ templates/frontOffice/default/I18n/fr_FR.php | 6 + templates/frontOffice/default/cart.html | 53 +++- 7 files changed, 341 insertions(+), 6 deletions(-) create mode 100644 core/lib/Thelia/Core/Template/Smarty/Plugins/CartPostage.php diff --git a/core/lib/Thelia/Config/Resources/smarty-plugin.xml b/core/lib/Thelia/Config/Resources/smarty-plugin.xml index 903bb114e..222874903 100644 --- a/core/lib/Thelia/Config/Resources/smarty-plugin.xml +++ b/core/lib/Thelia/Config/Resources/smarty-plugin.xml @@ -38,6 +38,11 @@ + + + + + diff --git a/core/lib/Thelia/Core/Template/Smarty/Plugins/CartPostage.php b/core/lib/Thelia/Core/Template/Smarty/Plugins/CartPostage.php new file mode 100644 index 000000000..72f6947cf --- /dev/null +++ b/core/lib/Thelia/Core/Template/Smarty/Plugins/CartPostage.php @@ -0,0 +1,250 @@ +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') + ); + } +} diff --git a/core/lib/Thelia/Tools/Redirect.php b/core/lib/Thelia/Tools/Redirect.php index e183079d5..2411924bf 100644 --- a/core/lib/Thelia/Tools/Redirect.php +++ b/core/lib/Thelia/Tools/Redirect.php @@ -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(); } } diff --git a/local/modules/Front/Config/front.xml b/local/modules/Front/Config/front.xml index 7d78aa46d..319d9b4c2 100644 --- a/local/modules/Front/Config/front.xml +++ b/local/modules/Front/Config/front.xml @@ -123,6 +123,11 @@ Front\Controller\CartController::changeItem cart + + + Front\Controller\CartController::changeCountry + cart + diff --git a/local/modules/Front/Controller/CartController.php b/local/modules/Front/Controller/CartController.php index ceda20751..587866950 100644 --- a/local/modules/Front/Controller/CartController.php +++ b/local/modules/Front/Controller/CartController.php @@ -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 * diff --git a/templates/frontOffice/default/I18n/fr_FR.php b/templates/frontOffice/default/I18n/fr_FR.php index fef729162..ab8754e16 100644 --- a/templates/frontOffice/default/I18n/fr_FR.php +++ b/templates/frontOffice/default/I18n/fr_FR.php @@ -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 :', ); diff --git a/templates/frontOffice/default/cart.html b/templates/frontOffice/default/cart.html index bb5f644be..a38877d01 100644 --- a/templates/frontOffice/default/cart.html +++ b/templates/frontOffice/default/cart.html @@ -115,17 +115,57 @@ {$real_price * $QUANTITY} {currency attr="symbol"} - {/loop} + {postage} + {assign var="postageAmount" value=$postage } + + +
+

+ {intl l="Estimated shipping "} + {if $is_customizable == false} + {loop type="country" name="countryLoop" id="$country_id"} + {intl l="for"} {$TITLE} + {/loop} + {/if} +

+ {if $is_customizable} +
+ + + {intl l="update"} +
+ {/if} + {if $delivery_id != 0 } +
+ {intl l="with:"} {loop type="delivery" name="deliveryLoop" id=$delivery_id}{$TITLE} {/loop} +
+ {else} +
+ {intl l="No deliveries available for this cart and this country"} +
+ {/if} +
+ + {$postage} {currency attr="symbol"} + - + {$postage} {currency attr="symbol"} + + {/postage} - +   {intl l="Total"}
- {cart attr="total_taxed_price_without_discount"} {currency attr="symbol"} -
+ {assign var="totalAmount" value={cart attr='total_taxed_price_without_discount'} + $postageAmount } + {$totalAmount} {currency attr="symbol"} + cart @@ -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(); + }) }); {/block}