diff --git a/composer.lock b/composer.lock index b49c21e6f..88c9d3b5a 100755 --- a/composer.lock +++ b/composer.lock @@ -11,12 +11,12 @@ "source": { "type": "git", "url": "https://github.com/ezyang/htmlpurifier.git", - "reference": "107b3055a10eb824701463602f77fbc8129180a2" + "reference": "af7107e8304e0ac0ad6fc2dfbecc9062d90e0b17" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/107b3055a10eb824701463602f77fbc8129180a2", - "reference": "107b3055a10eb824701463602f77fbc8129180a2", + "url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/af7107e8304e0ac0ad6fc2dfbecc9062d90e0b17", + "reference": "af7107e8304e0ac0ad6fc2dfbecc9062d90e0b17", "shasum": "" }, "require": { @@ -47,7 +47,7 @@ "keywords": [ "html" ], - "time": "2013-07-17 04:56:29" + "time": "2013-07-18 17:22:45" }, { "name": "ircmaxell/password-compat", @@ -304,12 +304,12 @@ "source": { "type": "git", "url": "https://github.com/krichprollsch/phpCssEmbed.git", - "reference": "v1.0.1" + "reference": "v1.0.2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/krichprollsch/phpCssEmbed/zipball/v1.0.1", - "reference": "v1.0.1", + "url": "https://api.github.com/repos/krichprollsch/phpCssEmbed/zipball/v1.0.2", + "reference": "v1.0.2", "shasum": "" }, "require": { @@ -337,7 +337,7 @@ "css", "url" ], - "time": "2013-04-29 19:58:29" + "time": "2013-07-22 20:01:48" }, { "name": "simplepie/simplepie", diff --git a/core/lib/Thelia/Action/Cart.php b/core/lib/Thelia/Action/Cart.php index c06ade935..61629bde8 100755 --- a/core/lib/Thelia/Action/Cart.php +++ b/core/lib/Thelia/Action/Cart.php @@ -26,6 +26,10 @@ namespace Thelia\Action; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Thelia\Core\Event\ActionEvent; +use Thelia\Core\HttpFoundation\Session\Session; +use Thelia\Model\CartQuery; +use Thelia\Model\Cart as CartModel; +use Thelia\Model\Customer; class Cart implements EventSubscriberInterface @@ -91,4 +95,87 @@ class Cart implements EventSubscriberInterface "action.modifyArticle" => array("modifyArticle", 128), ); } + + public function getCart(Request $request) + { + + if(null !== $cart = $request->getSession()->getCart()){ + return $cart; + } + + if ($request->cookies->has("thelia_cart")) { + //le cookie de panier existe, on le récupère + $token = $request->cookies->get("thelia_cart"); + + $cart = CartQuery::create()->findOneByToken($token); + + if ($cart) { + //le panier existe en base + $customer = $request->getSession()->getCustomerUser(); + + if ($customer) { + if($cart->getCustomerId() != $customer->getId()) { + //le customer du panier n'est pas le mm que celui connecté, il faut cloner le panier sans le customer_id + $cart = $this->duplicateCart($cart, $request->getSession(), $customer); + } + } else { + if ($cart->getCustomerId() != null) { + //il faut dupliquer le panier sans le customer_id + $cart = $this->duplicateCart($cart, $request->getSession()); + } + } + + } else { + $cart = $this->createCart($request->getSession()); + } + } else { + //le cookie de panier n'existe pas, il va falloir le créer et faire un enregistrement en base. + $cart = $this->createCart($request->getSession()); + } + + return $cart; + } + + /** + * @param Session $session + * @return CartModel + */ + protected function createCart(Session $session) + { + $cart = new CartModel(); + $cart->setToken($this->generateCookie()); + + if(null !== $customer = $session->getCustomerUser()) { + $cart->setCustomer($customer); + } + + $cart->save(); + + $session->setCart($cart->getId()); + + return $cart; + } + + + /** + * @param CartModel $cart + * @param Session $session + * @param Customer $customer + * @return CartModel + */ + protected function duplicateCart(CartModel $cart, Session $session, Customer $customer = null) + { + $newCart = $cart->duplicate($this->generateCookie(), $customer); + $session->setCart($newCart->getId()); + + return $newCart; + } + + protected function generateCookie() + { + $id = uniqid('', true); + setcookie("thelia_cart", $id, time()+(60*60*24*365)); + + return $id; + } } diff --git a/core/lib/Thelia/Action/Customer.php b/core/lib/Thelia/Action/Customer.php index fe1379aed..3a39a4bf2 100755 --- a/core/lib/Thelia/Action/Customer.php +++ b/core/lib/Thelia/Action/Customer.php @@ -56,8 +56,6 @@ class Customer implements EventSubscriberInterface public function create(ActionEvent $event) { - $event->getDispatcher()->dispatch(TheliaEvents::BEFORE_CREATECUSTOMER, $event); - $request = $event->getRequest(); $customerCreationForm = new CustomerCreation($request); @@ -71,8 +69,11 @@ class Customer implements EventSubscriberInterface if ($form->isValid()) { $data = $form->getData(); $customer = new CustomerModel(); + try { - $customer->createOrUpdate( + $event->getDispatcher()->dispatch(TheliaEvents::BEFORE_CREATECUSTOMER, $event); + + $customer->createOrUpdate( $data["title"], $data["firstname"], $data["lastname"], @@ -120,8 +121,6 @@ class Customer implements EventSubscriberInterface public function modify(ActionEvent $event) { - $event->getDispatcher()->dispatch(TheliaEvents::BEFORE_CHANGECUSTOMER, $event); - $request = $event->getRequest(); $customerModification = new CustomerModification($request); @@ -137,7 +136,10 @@ class Customer implements EventSubscriberInterface $customer = CustomerQuery::create()->findPk(1); try { - $data = $form->getData(); + $event->getDispatcher()->dispatch(TheliaEvents::BEFORE_CHANGECUSTOMER, $event); + + $data = $form->getData(); + $customer->createOrUpdate( $data["title"], $data["firstname"], diff --git a/core/lib/Thelia/Admin/Controller/BaseAdminController.php b/core/lib/Thelia/Admin/Controller/BaseAdminController.php index b5fe2a71b..742db4304 100755 --- a/core/lib/Thelia/Admin/Controller/BaseAdminController.php +++ b/core/lib/Thelia/Admin/Controller/BaseAdminController.php @@ -37,6 +37,7 @@ use Thelia\Core\Security\SecurityContext; use Thelia\Tools\URL; use Thelia\Tools\Redirect; use Thelia\Core\Template\ParserContext; +use Thelia\Core\Event\ActionEvent; /** * @@ -133,10 +134,21 @@ class BaseAdminController extends ContainerAware return $this->container->get('request'); } + /** + * Dispatch a Thelia event to modules + * + * @param string $eventName a TheliaEvent name, as defined in TheliaEvents class + * @param ActionEvent $event the event + */ + protected function dispatch($eventName, ActionEvent $event = null) { + + $this->container->get("event_dispatcher")->dispatch($eventName, $event); + } + /** * Returns the session from the current request * - * @return Ambigous + * @return \Symfony\Component\HttpFoundation\Session\SessionInterface */ protected function getSession() { @@ -146,8 +158,7 @@ class BaseAdminController extends ContainerAware } /** - * - * @return a ParserInterface instance parser, as configured. + * @return a ParserInterface instance parser */ protected function getParser() { @@ -159,16 +170,6 @@ class BaseAdminController extends ContainerAware return $parser; } - protected function getFormFactory() - { - return BaseForm::getFormFactory($this->getRequest(), ConfigQuery::read("form.secret.admin", md5(__DIR__))); - } - - protected function getFormBuilder() - { - return $this->getFormFactory()->createBuilder("form"); - } - /** * Forwards the request to another controller. * diff --git a/core/lib/Thelia/Admin/Controller/SessionController.php b/core/lib/Thelia/Admin/Controller/SessionController.php index 71a3c0106..9928a5a01 100755 --- a/core/lib/Thelia/Admin/Controller/SessionController.php +++ b/core/lib/Thelia/Admin/Controller/SessionController.php @@ -31,6 +31,7 @@ use Thelia\Core\Security\Exception\AuthenticationException; use Symfony\Component\Validator\Exception\ValidatorException; use Thelia\Tools\URL; use Thelia\Tools\Redirect; +use Thelia\Core\Event\TheliaEvents; class SessionController extends BaseAdminController { @@ -41,6 +42,8 @@ class SessionController extends BaseAdminController { public function checkLogoutAction() { + $this->dispatch(TheliaEvents::ADMIN_LOGOUT); + $this->getSecurityContext()->clear(); // Go back to login page. @@ -64,6 +67,8 @@ class SessionController extends BaseAdminController { // Log authentication success AdminLog::append("Authentication successuful", $request, $user); + $this->dispatch(TheliaEvents::ADMIN_LOGIN); + // Redirect to the success URL return Redirect::exec($adminLoginForm->getSuccessUrl()); } diff --git a/core/lib/Thelia/Config/Resources/config.xml b/core/lib/Thelia/Config/Resources/config.xml index 73dc56e88..cde8350a6 100755 --- a/core/lib/Thelia/Config/Resources/config.xml +++ b/core/lib/Thelia/Config/Resources/config.xml @@ -14,6 +14,8 @@ + + @@ -137,6 +139,12 @@ + + + + + + diff --git a/core/lib/Thelia/Core/Event/TheliaEvents.php b/core/lib/Thelia/Core/Event/TheliaEvents.php index d570c22a1..c086f4fa9 100755 --- a/core/lib/Thelia/Core/Event/TheliaEvents.php +++ b/core/lib/Thelia/Core/Event/TheliaEvents.php @@ -25,8 +25,7 @@ namespace Thelia\Core\Event; /** * - * Class containing all Thelia events name using in Thelia Core - * + * This class contains all Thelia events identifiers used by Thelia Core * * @author Manuel Raynaud */ @@ -37,25 +36,56 @@ final class TheliaEvents /** * ACTION event * - * Send if no action are already present in Thelia action process ( see Thelia\Routing\Matcher\ActionMatcher) + * Sent if no action are already present in Thelia action process ( see Thelia\Routing\Matcher\ActionMatcher) */ const ACTION = "thelia.action"; /** * INCLUDE event * - * Send before starting thelia inclusion + * Sent before starting thelia inclusion */ const INCLUSION = "thelia.include"; + /** + * Sent before the logout of the customer. + */ const CUSTOMER_LOGOUT = "action.customer_logout"; + /** + * Sent once the customer is successfully logged in. + */ const CUSTOMER_LOGIN = "action.customer_login"; + /** + * Sent before the logout of the administrator. + */ + const ADMIN_LOGOUT = "action.admin_logout"; + /** + * Sent once the administrator is successfully logged in. + */ + const ADMIN_LOGIN = "action.admin_login"; + + /** + * Sent once the customer creation form has been successfully validated, and before customer insertion in the database. + */ const BEFORE_CREATECUSTOMER = "action.before_createcustomer"; + + /** + * Sent just after a successful insert of a new customer in the database. + */ const AFTER_CREATECUSTOMER = "action.after_createcustomer"; + /** + * Sent once the customer change form has been successfully validated, and before customer update in the database. + */ const BEFORE_CHANGECUSTOMER = "action.before_changecustomer"; + /** + * Sent just after a successful update of a customer in the database. + */ const AFTER_CHANGECUSTOMER = "action.after_changecustomer"; + /** + * Sent before customer insertion, to allow modules to create a custom customer reference. + */ const CREATECUSTOMER_CUSTOMREF = "customer.creation.customref"; -} +} \ No newline at end of file diff --git a/core/lib/Thelia/Core/HttpFoundation/Session/Session.php b/core/lib/Thelia/Core/HttpFoundation/Session/Session.php index a57428c73..cde686ee4 100755 --- a/core/lib/Thelia/Core/HttpFoundation/Session/Session.php +++ b/core/lib/Thelia/Core/HttpFoundation/Session/Session.php @@ -25,13 +25,14 @@ namespace Thelia\Core\HttpFoundation\Session; use Symfony\Component\HttpFoundation\Session\Session as BaseSession; use Thelia\Core\Security\User\UserInterface; -use Thelia\Form\BaseForm; -use Thelia\Model\ConfigQuery; +use Thelia\Exception\InvalidCartException; +use Thelia\Model\CartQuery; +use Thelia\Model\Cart; use Thelia\Tools\URL; -class Session extends BaseSession { - - // -- Language ------------------------------------------------------------ +class Session extends BaseSession +{ + // -- Language ------------------------------------------------------------ public function getLocale() { @@ -47,41 +48,61 @@ class Session extends BaseSession { public function setCustomerUser(UserInterface $user) { - $this->set('customer_user', $user); + $this->set('customer_user', $user); } public function getCustomerUser() { - return $this->get('customer_user'); + return $this->get('customer_user'); } public function clearCustomerUser() { - return $this->remove('customer_user'); + return $this->remove('customer_user'); } // -- Admin user ----------------------------------------------------------- public function setAdminUser(UserInterface $user) { - $this->set('admin_user', $user); + $this->set('admin_user', $user); } public function getAdminUser() { - return $this->get('admin_user'); + return $this->get('admin_user'); } public function clearAdminUser() { - return $this->remove('admin_user'); + return $this->remove('admin_user'); + } + + // -- Error form ----------------------------------------------------------- + + /** + * @param string $formName the form name + */ + public function setErrorFormName($formName) + { + $this->set('error_form', $formName); + } + + public function getErrorFormName() + { + return $this->get('error_form', null); + } + + public function clearErrorFormName() + { + return $this->remove('error_form'); } // -- Return page ---------------------------------------------------------- public function setReturnToUrl($url) { - $this->set('return_to_url', $url); + $this->set('return_to_url', $url); } /** @@ -90,7 +111,56 @@ class Session extends BaseSession { */ public function getReturnToUrl() { - return $this->get('return_to_url', URL::getIndexPage()); + return $this->get('return_to_url', URL::getIndexPage()); + } + + // -- Cart ------------------------------------------------------------------ + + /** + * return cart if exists and is valid (checking customer) + * + * @return \Thelia\Model\Cart|null + */ + public function getCart() + { + $cart_id = $this->get("cart_id"); + $cart = null; + if ($cart_id) { + $cart = CartQuery::create()->findPk($cart_id); + try { + $this->verifyValidCart($cart); + } catch (InvalidCartException $e) { + $cart = null; + } + } + + return $cart; + } + + /** + * + * + * @param \Thelia\Model\Cart $cart + * @throws \Thelia\Exception\InvalidCartException + */ + protected function verifyValidCart(Cart $cart) + { + $customer = $this->getCustomerUser(); + if ($customer && $cart->getCustomerId() != $customer->getId()) { + throw new InvalidCartException("customer in session and customer_id in cart are not the same"); + } else if($customer === null && $cart->getCustomerId() !== null) { + throw new InvalidCartException("Customer exists in cart and not in session"); + } + } + + /** + * assign cart id in session + * + * @param $cart_id + */ + public function setCart($cart_id) + { + $this->set("cart_id", $cart_id); } } diff --git a/core/lib/Thelia/Core/Security/SecurityContext.php b/core/lib/Thelia/Core/Security/SecurityContext.php index a4409afd8..b881282b9 100755 --- a/core/lib/Thelia/Core/Security/SecurityContext.php +++ b/core/lib/Thelia/Core/Security/SecurityContext.php @@ -55,6 +55,8 @@ class SecurityContext { } $this->context = $context; + + return $this; } public function getContext($exception_if_context_undefined = false) { @@ -133,7 +135,7 @@ class SecurityContext { // Get permissions from profile // $userPermissions = $user->getPermissions(); - echo "TODO: Finalize permissions system !"; + // TODO: Finalize permissions system !; $userPermissions = array('*'); // FIXME ! diff --git a/core/lib/Thelia/Core/Template/Loop/Order.php b/core/lib/Thelia/Core/Template/Loop/Order.php new file mode 100644 index 000000000..112a1b0f3 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/Order.php @@ -0,0 +1,59 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Core\Template\Loop; + +use Thelia\Core\Template\Element\BaseLoop; +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\Type\TypeCollection; +use Thelia\Type; + +/** + * + * @package Thelia\Core\Template\Loop + * + * @author Franck Allimant + */ +class Order extends BaseLoop +{ + public function getArgDefinitions() + { + return new ArgumentCollection(); + } + + /** + * + * + * @return \Thelia\Core\Template\Element\LoopResult + */ + public function exec(&$pagination) + { + // TODO : a coder ! + return new LoopResult(); + } +} \ No newline at end of file diff --git a/core/lib/Thelia/Core/Template/Loop/OrderStatus.php b/core/lib/Thelia/Core/Template/Loop/OrderStatus.php new file mode 100644 index 000000000..e6787f003 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/OrderStatus.php @@ -0,0 +1,59 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Core\Template\Loop; + +use Thelia\Core\Template\Element\BaseLoop; +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\Type\TypeCollection; +use Thelia\Type; + +/** + * + * @package Thelia\Core\Template\Loop + * + * @author Franck Allimant + */ +class OrderStatus extends BaseLoop +{ + public function getArgDefinitions() + { + return new ArgumentCollection(); + } + + /** + * + * + * @return \Thelia\Core\Template\Element\LoopResult + */ + public function exec(&$pagination) + { + // TODO : a coder ! + return new LoopResult(); + } +} \ No newline at end of file diff --git a/core/lib/Thelia/Core/Template/ParserContext.php b/core/lib/Thelia/Core/Template/ParserContext.php index e5c682e37..85b2b73b9 100644 --- a/core/lib/Thelia/Core/Template/ParserContext.php +++ b/core/lib/Thelia/Core/Template/ParserContext.php @@ -44,6 +44,7 @@ class ParserContext implements \IteratorAggregate ->set('BASE_URL' , ConfigQuery::read('base_url', '/')) ->set('INDEX_PAGE' , URL::getIndexPage()) ->set('RETURN_TO_URL' , URL::absoluteUrl($request->getSession()->getReturnToUrl())) + ->set('THELIA_VERSION' , ConfigQuery::read('thelia_version', 'undefined')) ; } diff --git a/core/lib/Thelia/Core/Template/Smarty/AbstractSmartyPlugin.php b/core/lib/Thelia/Core/Template/Smarty/AbstractSmartyPlugin.php new file mode 100755 index 000000000..0015dbb0b --- /dev/null +++ b/core/lib/Thelia/Core/Template/Smarty/AbstractSmartyPlugin.php @@ -0,0 +1,58 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Core\Template\Smarty; + +/** + * + * The class all Smarty Thelia plugin shoud extend + * + * Class AbstractSmartyPlugin + * @package Thelia\Core\Template\Smarty + */ +abstract class AbstractSmartyPlugin +{ + /** + * Explode a comma separated list in a array, trimming all array elements + * + * @param unknown $commaSeparatedValues + * @return multitype: + */ + protected function _explode($commaSeparatedValues) + { + $array = explode(',', $commaSeparatedValues); + + if (array_walk($array, function(&$item) { + $item = strtoupper(trim($item)); + })) { + return $array; + } + + return array(); + } + + /** + * @return an array of SmartyPluginDescriptor + */ + public abstract function getPluginDescriptors(); +} diff --git a/core/lib/Thelia/Core/Template/Smarty/Assets/SmartyAssetsManager.php b/core/lib/Thelia/Core/Template/Smarty/Assets/SmartyAssetsManager.php index 1f8a3cb2e..1e594ae32 100755 --- a/core/lib/Thelia/Core/Template/Smarty/Assets/SmartyAssetsManager.php +++ b/core/lib/Thelia/Core/Template/Smarty/Assets/SmartyAssetsManager.php @@ -50,10 +50,7 @@ class SmartyAssetsManager $this->assetic_manager = new AsseticHelper(); } - public function processSmartyPluginCall($assetType, $params, $content, \Smarty_Internal_Template $template, &$repeat) - { - // Opening tag (first call only) - if ($repeat) { + public function computeAssetUrl($assetType, $params, \Smarty_Internal_Template $template) { $file = $params['file']; $filters = isset($params['filters']) ? $params['filters'] : ''; $debug = isset($params['debug']) ? trim(strtolower($params['debug'])) == 'true' : false; @@ -79,7 +76,17 @@ class SmartyAssetsManager $debug ); + return $url; + } + + public function processSmartyPluginCall($assetType, $params, $content, \Smarty_Internal_Template $template, &$repeat) + { + // Opening tag (first call only) + if ($repeat) { + $url = $this->computeAssetUrl($assetType, $params, $template); + $template->assign('asset_url', $url); + } elseif (isset($content)) { return $content; } diff --git a/core/lib/Thelia/Core/Template/Smarty/Plugins/Assetic.php b/core/lib/Thelia/Core/Template/Smarty/Plugins/Assetic.php index 4418bd50c..7fca50151 100755 --- a/core/lib/Thelia/Core/Template/Smarty/Plugins/Assetic.php +++ b/core/lib/Thelia/Core/Template/Smarty/Plugins/Assetic.php @@ -24,12 +24,12 @@ namespace Thelia\Core\Template\Smarty\Plugins; use Thelia\Core\Template\Smarty\SmartyPluginDescriptor; -use Thelia\Core\Template\Smarty\SmartyPluginInterface; +use Thelia\Core\Template\Smarty\AbstractSmartyPlugin; use Thelia\Core\Template\Smarty\Assets\SmartyAssetsManager; -class Assetic implements SmartyPluginInterface +class Assetic extends AbstractSmartyPlugin { - public $asset_manager; + public $assetManager; public function __construct() { @@ -37,22 +37,27 @@ class Assetic implements SmartyPluginInterface $asset_dir_from_web_root = 'assets/admin/default'; // FIXME - $this->asset_manager = new SmartyAssetsManager($web_root, $asset_dir_from_web_root); + $this->assetManager = new SmartyAssetsManager($web_root, $asset_dir_from_web_root); } - public function theliaBlockJavascripts($params, $content, \Smarty_Internal_Template $template, &$repeat) + public function blockJavascripts($params, $content, \Smarty_Internal_Template $template, &$repeat) { - return $this->asset_manager->processSmartyPluginCall('js', $params, $content, $template, $repeat); + return $this->assetManager->processSmartyPluginCall('js', $params, $content, $template, $repeat); } - public function theliaBlockImages($params, $content, \Smarty_Internal_Template $template, &$repeat) + public function blockImages($params, $content, \Smarty_Internal_Template $template, &$repeat) { - return $this->asset_manager->processSmartyPluginCall(SmartyAssetsManager::ASSET_TYPE_AUTO, $params, $content, $template, $repeat); + return $this->assetManager->processSmartyPluginCall(SmartyAssetsManager::ASSET_TYPE_AUTO, $params, $content, $template, $repeat); } - public function theliaBlockStylesheets($params, $content, \Smarty_Internal_Template $template, &$repeat) + public function blockStylesheets($params, $content, \Smarty_Internal_Template $template, &$repeat) { - return $this->asset_manager->processSmartyPluginCall('css', $params, $content, $template, $repeat); + return $this->assetManager->processSmartyPluginCall('css', $params, $content, $template, $repeat); + } + + public function functionImage($params, \Smarty_Internal_Template $template) + { + return $this->assetManager->computeAssetUrl(SmartyAssetsManager::ASSET_TYPE_AUTO, $params, $template); } /** @@ -63,9 +68,10 @@ class Assetic implements SmartyPluginInterface public function getPluginDescriptors() { return array( - new SmartyPluginDescriptor('block', 'stylesheets', $this, 'theliaBlockStylesheets'), - new SmartyPluginDescriptor('block', 'javascripts', $this, 'theliaBlockJavascripts'), - new SmartyPluginDescriptor('block', 'images' , $this, 'theliaBlockImages') + new SmartyPluginDescriptor('block' , 'stylesheets', $this, 'blockStylesheets'), + new SmartyPluginDescriptor('block' , 'javascripts', $this, 'blockJavascripts'), + new SmartyPluginDescriptor('block' , 'images' , $this, 'blockImages'), + new SmartyPluginDescriptor('function', 'image' , $this, 'functionImage') ); } } diff --git a/core/lib/Thelia/Core/Template/Smarty/Plugins/DataAccessFunctions.php b/core/lib/Thelia/Core/Template/Smarty/Plugins/DataAccessFunctions.php new file mode 100644 index 000000000..7fcbdfbc7 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Smarty/Plugins/DataAccessFunctions.php @@ -0,0 +1,112 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Core\Template\Smarty\Plugins; + +use Thelia\Core\Template\Smarty\AbstractSmartyPlugin; +use Thelia\Core\Security\SecurityContext; +use Thelia\Core\Template\ParserContext; +use Thelia\Core\Template\Smarty\SmartyPluginDescriptor; +/** + * Implementation of data access to main Thelia objects (users, cart, etc.) + * + * @author Franck Allimant + * + */ +class DataAccessFunctions extends AbstractSmartyPlugin +{ + private $securityContext; + protected $parserContext; + + public function __construct(SecurityContext $securityContext, ParserContext $parserContext) + { + $this->securityContext = $securityContext; + } + + /** + * Provides access to the current logged administrator attributes using the accessors. + * + * @param array $params + * @param unknown $smarty + * @return string the value of the requested attribute + */ + public function adminDataAccess($params, &$smarty) + { + return $this->userDataAccess("Admin User", SecurityContext::CONTEXT_BACK_OFFICE, $params); + } + + /** + * Provides access to the current logged customer attributes throught the accessor + * + * @param array $params + * @param unknown $smarty + * @return string the value of the requested attribute + */ + public function customerDataAccess($params, &$smarty) + { + return $this->userDataAccess("Customer User", SecurityContext::CONTEXT_FRONT_OFFICE, $params); + } + + + /** + * Provides access to user attributes using the accessors. + * + * @param array $params + * @param unknown $smarty + * @return string the value of the requested attribute + * @throws InvalidArgumentException if the object does not have the requested attribute. + */ + protected function userDataAccess($objectLabel, $context, $params) + { + $attribute = $params['attr']; + + if (! empty($attribute)) { + $user = $this->securityContext->setContext($context)->getUser(); + + if (null != $user) { + $getter = sprintf("get%s", ucfirst(strtolower($attribute))); + + if (method_exists($user, $getter)) { + return $user->$getter(); + } + + throw new \InvalidArgumentException(sprintf("%s has no '%s' attribute", $objectLabel, $attribute)); + + } + } + + return ''; + } + /** + * Define the various smarty plugins hendled by this class + * + * @return an array of smarty plugin descriptors + */ + public function getPluginDescriptors() + { + return array( + new SmartyPluginDescriptor('function', 'admin', $this, 'adminDataAccess'), + new SmartyPluginDescriptor('function', 'customer', $this, 'customerDataAccess') + ); + } +} diff --git a/core/lib/Thelia/Core/Template/Smarty/Plugins/Form.php b/core/lib/Thelia/Core/Template/Smarty/Plugins/Form.php index cdabebb13..7ddb96104 100755 --- a/core/lib/Thelia/Core/Template/Smarty/Plugins/Form.php +++ b/core/lib/Thelia/Core/Template/Smarty/Plugins/Form.php @@ -27,7 +27,7 @@ use Thelia\Form\BaseForm; use Thelia\Core\Template\Element\Exception\ElementNotFoundException; use Symfony\Component\HttpFoundation\Request; use Thelia\Core\Template\Smarty\SmartyPluginDescriptor; -use Thelia\Core\Template\Smarty\SmartyPluginInterface; +use Thelia\Core\Template\Smarty\AbstractSmartyPlugin; use Thelia\Log\Tlog; use Thelia\Core\Template\ParserContext; @@ -55,7 +55,7 @@ use Thelia\Core\Template\ParserContext; * Class Form * @package Thelia\Core\Template\Smarty\Plugins */ -class Form implements SmartyPluginInterface +class Form extends AbstractSmartyPlugin { protected $request; diff --git a/core/lib/Thelia/Core/Template/Smarty/Plugins/Module.php b/core/lib/Thelia/Core/Template/Smarty/Plugins/Module.php index 99080ce70..52feae096 100755 --- a/core/lib/Thelia/Core/Template/Smarty/Plugins/Module.php +++ b/core/lib/Thelia/Core/Template/Smarty/Plugins/Module.php @@ -24,9 +24,9 @@ namespace Thelia\Core\Template\Smarty\Plugins; use Thelia\Core\Template\Smarty\SmartyPluginDescriptor; -use Thelia\Core\Template\Smarty\SmartyPluginInterface; +use Thelia\Core\Template\Smarty\AbstractSmartyPlugin; -class Module implements SmartyPluginInterface +class Module extends AbstractSmartyPlugin { /** * Process theliaModule template inclusion function diff --git a/core/lib/Thelia/Core/Template/Smarty/Plugins/Security.php b/core/lib/Thelia/Core/Template/Smarty/Plugins/Security.php index cd19576b1..51bb0d1ef 100755 --- a/core/lib/Thelia/Core/Template/Smarty/Plugins/Security.php +++ b/core/lib/Thelia/Core/Template/Smarty/Plugins/Security.php @@ -24,12 +24,12 @@ namespace Thelia\Core\Template\Smarty\Plugins; use Thelia\Core\Template\Smarty\SmartyPluginDescriptor; -use Thelia\Core\Template\Smarty\SmartyPluginInterface; +use Thelia\Core\Template\Smarty\AbstractSmartyPlugin; use Thelia\Core\Template\Smarty\Assets\SmartyAssetsManager; use Thelia\Core\Security\SecurityContext; use Thelia\Core\Security\Exception\AuthenticationException; -class Security implements SmartyPluginInterface +class Security extends AbstractSmartyPlugin { private $securityContext; @@ -38,19 +38,6 @@ class Security implements SmartyPluginInterface $this->securityContext = $securityContext; } - private function _explode($commaSeparatedValues) - { - $array = explode(',', $commaSeparatedValues); - - if (array_walk($array, function(&$item) { - $item = strtoupper(trim($item)); - })) { - return $array; - } - - return array(); - } - /** * Process security check function * diff --git a/core/lib/Thelia/Core/Template/Smarty/Plugins/TheliaLoop.php b/core/lib/Thelia/Core/Template/Smarty/Plugins/TheliaLoop.php index 3d5496741..ddb0eca4a 100755 --- a/core/lib/Thelia/Core/Template/Smarty/Plugins/TheliaLoop.php +++ b/core/lib/Thelia/Core/Template/Smarty/Plugins/TheliaLoop.php @@ -24,7 +24,7 @@ namespace Thelia\Core\Template\Smarty\Plugins; use Thelia\Core\Template\Element\BaseLoop; -use Thelia\Core\Template\Smarty\SmartyPluginInterface; +use Thelia\Core\Template\Smarty\AbstractSmartyPlugin; use Thelia\Core\Template\Smarty\SmartyPluginDescriptor; use Thelia\Core\Template\Element\Exception\ElementNotFoundException; @@ -34,7 +34,7 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Thelia\Core\Security\SecurityContext; -class TheliaLoop implements SmartyPluginInterface +class TheliaLoop extends AbstractSmartyPlugin { protected static $pagination = null; @@ -68,6 +68,23 @@ class TheliaLoop implements SmartyPluginInterface } } + /** + * Process the count function: executes a loop and return the number of items found + */ + public function theliaCount($params, $template) { + + if (empty($params['type'])) + throw new \InvalidArgumentException("Missing 'type' parameter in count arguments"); + + $loop = $this->createLoopInstance($params); + + $dummy = null; + + $loopResults = $loop->exec($dummy); + + return $loopResults->valid() ? $loopResults->getCount() : 0; + } + /** * Process {loop name="loop name" type="loop type" ... } ... {/loop} block * @@ -343,10 +360,11 @@ class TheliaLoop implements SmartyPluginInterface { return array( - new SmartyPluginDescriptor('block', 'loop' , $this, 'theliaLoop'), - new SmartyPluginDescriptor('block', 'elseloop' , $this, 'theliaElseloop'), - new SmartyPluginDescriptor('block', 'ifloop' , $this, 'theliaIfLoop'), - new SmartyPluginDescriptor('block', 'pageloop' , $this, 'theliaPageLoop'), + new SmartyPluginDescriptor('function', 'count' , $this, 'theliaCount'), + new SmartyPluginDescriptor('block' , 'loop' , $this, 'theliaLoop'), + new SmartyPluginDescriptor('block' , 'elseloop' , $this, 'theliaElseloop'), + new SmartyPluginDescriptor('block' , 'ifloop' , $this, 'theliaIfLoop'), + new SmartyPluginDescriptor('block' , 'pageloop' , $this, 'theliaPageLoop'), ); } } diff --git a/core/lib/Thelia/Core/Template/Smarty/Plugins/TheliaSyntax.php b/core/lib/Thelia/Core/Template/Smarty/Plugins/TheliaSyntax.php index 9b508cf3e..7881941ac 100755 --- a/core/lib/Thelia/Core/Template/Smarty/Plugins/TheliaSyntax.php +++ b/core/lib/Thelia/Core/Template/Smarty/Plugins/TheliaSyntax.php @@ -23,7 +23,7 @@ namespace Thelia\Core\Template\Smarty\Plugins; use Thelia\Core\Template\Smarty\SmartyPluginDescriptor; -use Thelia\Core\Template\Smarty\SmartyPluginInterface; +use Thelia\Core\Template\Smarty\AbstractSmartyPlugin; /** * Class TheliaSyntax @@ -31,7 +31,7 @@ use Thelia\Core\Template\Smarty\SmartyPluginInterface; * * @author Etienne Roudeix */ -class TheliaSyntax implements SmartyPluginInterface +class TheliaSyntax extends AbstractSmartyPlugin { public function dieseCancel($value, $diese) { diff --git a/core/lib/Thelia/Core/Template/Smarty/Plugins/Translation.php b/core/lib/Thelia/Core/Template/Smarty/Plugins/Translation.php index f03c34a7e..6015ca618 100755 --- a/core/lib/Thelia/Core/Template/Smarty/Plugins/Translation.php +++ b/core/lib/Thelia/Core/Template/Smarty/Plugins/Translation.php @@ -24,10 +24,10 @@ namespace Thelia\Core\Template\Smarty\Plugins; use Thelia\Core\Template\Smarty\SmartyPluginDescriptor; -use Thelia\Core\Template\Smarty\SmartyPluginInterface; +use Thelia\Core\Template\Smarty\AbstractSmartyPlugin; use Symfony\Component\Translation\TranslatorInterface; -class Translation implements SmartyPluginInterface +class Translation extends AbstractSmartyPlugin { protected $translator; @@ -44,7 +44,15 @@ class Translation implements SmartyPluginInterface */ public function translate($params, &$smarty) { - return $this->translator->trans($params['l'], isset($params['p']) ? $params['p'] : array()); + // All parameters other than 'l' are supposed to be variables. Build an array of var => value pairs + // and pass it to the translator + $vars = array(); + + foreach($params as $name => $value) { + $vars["%$name"] = $value; + } + + return $this->translator->trans($params['l'], $vars); } /** diff --git a/core/lib/Thelia/Core/Template/Smarty/Plugins/UrlGenerator.php b/core/lib/Thelia/Core/Template/Smarty/Plugins/UrlGenerator.php index c2c75dffc..9d63080be 100644 --- a/core/lib/Thelia/Core/Template/Smarty/Plugins/UrlGenerator.php +++ b/core/lib/Thelia/Core/Template/Smarty/Plugins/UrlGenerator.php @@ -24,11 +24,11 @@ namespace Thelia\Core\Template\Smarty\Plugins; use Thelia\Core\Template\Smarty\SmartyPluginDescriptor; -use Thelia\Core\Template\Smarty\SmartyPluginInterface; +use Thelia\Core\Template\Smarty\AbstractSmartyPlugin; use Thelia\Tools\URL; use Thelia\Core\HttpFoundation\Request; -class UrlGenerator implements SmartyPluginInterface +class UrlGenerator extends AbstractSmartyPlugin { protected $request; diff --git a/core/lib/Thelia/Core/Template/Smarty/SmartyParser.php b/core/lib/Thelia/Core/Template/Smarty/SmartyParser.php index a1e63dbf8..65b82d88f 100755 --- a/core/lib/Thelia/Core/Template/Smarty/SmartyParser.php +++ b/core/lib/Thelia/Core/Template/Smarty/SmartyParser.php @@ -10,7 +10,7 @@ use \Smarty; use Symfony\Component\HttpFoundation\Response; use Thelia\Core\Template\ParserInterface; -use Thelia\Core\Template\Smarty\SmartyPluginInterface; +use Thelia\Core\Template\Smarty\AbstractSmartyPlugin; use Thelia\Core\Template\Exception\ResourceNotFoundException; use Thelia\Core\Template\ParserContext; use Thelia\Model\ConfigQuery; @@ -177,7 +177,7 @@ class SmartyParser extends Smarty implements ParserInterface $this->status = $status; } - public function addPlugins(SmartyPluginInterface $plugin) + public function addPlugins(AbstractSmartyPlugin $plugin) { $this->plugins[] = $plugin; } diff --git a/core/lib/Thelia/Core/Template/Smarty/SmartyPluginDescriptor.php b/core/lib/Thelia/Core/Template/Smarty/SmartyPluginDescriptor.php index b22f99577..f3bdbb203 100755 --- a/core/lib/Thelia/Core/Template/Smarty/SmartyPluginDescriptor.php +++ b/core/lib/Thelia/Core/Template/Smarty/SmartyPluginDescriptor.php @@ -42,7 +42,7 @@ class SmartyPluginDescriptor protected $name; /** - * @var SmartyPluginInterface plugin implmentation class + * @var AbstractSmartyPlugin plugin implmentation class */ protected $class; diff --git a/core/lib/Thelia/Core/Template/Smarty/SmartyPluginInterface.php b/core/lib/Thelia/Exception/InvalidCartException.php old mode 100755 new mode 100644 similarity index 79% rename from core/lib/Thelia/Core/Template/Smarty/SmartyPluginInterface.php rename to core/lib/Thelia/Exception/InvalidCartException.php index e1228c7b1..7eceb47d0 --- a/core/lib/Thelia/Core/Template/Smarty/SmartyPluginInterface.php +++ b/core/lib/Thelia/Exception/InvalidCartException.php @@ -4,7 +4,7 @@ /* Thelia */ /* */ /* Copyright (c) OpenStudio */ -/* email : info@thelia.net */ +/* email : info@thelia.net */ /* web : http://www.thelia.net */ /* */ /* This program is free software; you can redistribute it and/or modify */ @@ -21,19 +21,10 @@ /* */ /*************************************************************************************/ -namespace Thelia\Core\Template\Smarty; -/** - * - * this interface must be implements when you want to add plugin to smarty using config process - * - * Interface SmartyPluginInterface - * @package Thelia\Core\Template\Smarty - */ -interface SmartyPluginInterface -{ - /** - * @return an array of SmartyPluginDescriptor - */ - public function getPluginDescriptors(); -} +namespace Thelia\Exception; + + +class InvalidCartException extends \RuntimeException { + +} \ No newline at end of file diff --git a/core/lib/Thelia/Model/Cart.php b/core/lib/Thelia/Model/Cart.php index 32f51484e..cf9b083c5 100644 --- a/core/lib/Thelia/Model/Cart.php +++ b/core/lib/Thelia/Model/Cart.php @@ -7,4 +7,30 @@ use Thelia\Model\Base\Cart as BaseCart; class Cart extends BaseCart { + public function duplicate($token, Customer $customer = null) + { + $cartItems = $this->getCartItems(); + + $cart = new Cart(); + $cart->setAddressDeliveryId($this->getAddressDeliveryId()); + $cart->setAddressInvoiceId($this->getAddressInvoiceId()); + $cart->setToken($token); + + if ($customer){ + $cart->setCustomer($customer); + } + // TODO : set current Currency + //$cart->setCurrency() + $cart->save(); + + foreach ($cartItems as $cartItem){ + $item = new CartItem(); + $item->setCart($cart); + $item->setProductId($cartItem->getProductId()); + $item->setQuantity($cartItem->getQuantity()); + $item->save(); + } + + return $cart; + } } diff --git a/core/lib/Thelia/Model/CartQuery.php b/core/lib/Thelia/Model/CartQuery.php index f0b9c48ce..1d51262d2 100644 --- a/core/lib/Thelia/Model/CartQuery.php +++ b/core/lib/Thelia/Model/CartQuery.php @@ -3,7 +3,7 @@ namespace Thelia\Model; use Thelia\Model\Base\CartQuery as BaseCartQuery; - +use Symfony\Component\HttpFoundation\Request; /** * Skeleton subclass for performing query and update operations on the 'cart' table. @@ -18,4 +18,5 @@ use Thelia\Model\Base\CartQuery as BaseCartQuery; class CartQuery extends BaseCartQuery { + } // CartQuery diff --git a/core/lib/Thelia/Model/Customer.php b/core/lib/Thelia/Model/Customer.php index 4d9a78ea0..b6379380b 100755 --- a/core/lib/Thelia/Model/Customer.php +++ b/core/lib/Thelia/Model/Customer.php @@ -116,7 +116,7 @@ class Customer extends BaseCustomer implements UserInterface protected function generateRef() { - return date("YmdHisu"); + return uniqid(substr($this->getLastname(), 0, (strlen($this->getLastname()) >= 3) ? 3 : strlen($this->getLastname())), true); } public function setPassword($password) diff --git a/core/lib/Thelia/Tests/Action/CartTest.php b/core/lib/Thelia/Tests/Action/CartTest.php new file mode 100644 index 000000000..4b9712efc --- /dev/null +++ b/core/lib/Thelia/Tests/Action/CartTest.php @@ -0,0 +1,239 @@ +. */ +/* */ +/*************************************************************************************/ +namespace Thelia\Tests\Action; + +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; +use Thelia\Core\HttpFoundation\Request; +use Thelia\Core\HttpFoundation\Session\Session; +use Thelia\Model\Cart; +use Thelia\Model\Customer; + +class CartTest extends \PHPUnit_Framework_TestCase +{ + + protected $session; + + protected $request; + + protected $actionCart; + + protected $uniqid; + + + + public function setUp() + { + $this->session = new Session(new MockArraySessionStorage()); + $this->request = new Request(); + + $this->request->setSession($this->session); + + $this->uniqid = uniqid('', true); + + $this->actionCart = $this->getMock( + "\Thelia\Action\Cart", + array("generateCookie") + ); + + $this->actionCart + ->expects($this->any()) + ->method("generateCookie") + ->will($this->returnValue($this->uniqid)); + } + + /** + * no cart present in session and cart_id no yet exists in cookies. + * + * In this case, a new cart instance must be create + */ + public function testGetCartWithoutCustomerAndWithoutExistingCart() + { + $actionCart = $this->actionCart; + + $cart = $actionCart->getCart($this->request); + + $this->assertInstanceOf("Thelia\Model\Cart", $cart, '$cart must be an instance of cart model Thelia\Model\Cart'); + $this->assertNull($cart->getCustomerId()); + $this->assertNull($cart->getAddressDeliveryId()); + $this->assertNull($cart->getAddressInvoiceId()); + $this->assertEquals($this->uniqid, $cart->getToken()); + + } + + /** + * Customer is connected but his cart does not exists yet + * + * Cart must be created and associated to the current connected Customer + */ + public function testGetCartWithCustomerAndWithoutExistingCart() + { + $actionCart = $this->actionCart; + + $request = $this->request; + + //create a fake customer just for test. If not persists test fails ! + $customer = new Customer(); + $customer->setFirstname("john"); + $customer->setLastname("doe"); + $customer->setTitleId(1); + $customer->save(); + + $request->getSession()->setCustomerUser($customer); + + $cart = $actionCart->getCart($request); + $this->assertInstanceOf("Thelia\Model\Cart", $cart, '$cart must be an instance of cart model Thelia\Model\Cart'); + $this->assertNotNull($cart->getCustomerId()); + $this->assertEquals($customer->getId(), $cart->getCustomerId()); + $this->assertNull($cart->getAddressDeliveryId()); + $this->assertNull($cart->getAddressInvoiceId()); + $this->assertEquals($this->uniqid, $cart->getToken()); + + } + + /** + * Cart exists and his id put in cookies. + * + * Must return the same cart instance + */ + public function testGetCartWithoutCustomerAndWithExistingCart() + { + $actionCart = $this->actionCart; + + $request = $this->request; + $uniqid = uniqid("test1", true); + //create a fake cart in database; + $cart = new Cart(); + $cart->setToken($uniqid); + $cart->save(); + + $request->cookies->set("thelia_cart", $uniqid); + + $getCart = $actionCart->getCart($request); + $this->assertInstanceOf("Thelia\Model\Cart", $getCart, '$cart must be an instance of cart model Thelia\Model\Cart'); + $this->assertNull($getCart->getCustomerId()); + $this->assertNull($getCart->getAddressDeliveryId()); + $this->assertNull($getCart->getAddressInvoiceId()); + $this->assertEquals($cart->getToken(), $getCart->getToken()); + } + + /** + * a cart id exists in cookies but this id does not exists yet in databases + * + * a new cart must be created (different token) + */ + public function testGetCartWithExistingCartButNotGoodCookies() + { + $actionCart = $this->actionCart; + + $request = $this->request; + + $token = "WrongToken"; + $request->cookies->set("thelia_cart", $token); + + $cart = $actionCart->getCart($request); + $this->assertInstanceOf("Thelia\Model\Cart", $cart, '$cart must be an instance of cart model Thelia\Model\Cart'); + $this->assertNull($cart->getCustomerId()); + $this->assertNull($cart->getAddressDeliveryId()); + $this->assertNull($cart->getAddressInvoiceId()); + $this->assertNotEquals($token, $cart->getToken()); + } + + /** + * cart and customer already exists. Cart and customer are linked. + * + * cart in session must be return + */ + public function testGetCartWithExistingCartAndCustomer() + { + $actionCart = $this->actionCart; + + $request = $this->request; + + + //create a fake customer just for test. If not persists test fails ! + $customer = new Customer(); + $customer->setFirstname("john"); + $customer->setLastname("doe"); + $customer->setTitleId(1); + $customer->save(); + + $uniqid = uniqid("test2", true); + //create a fake cart in database; + $cart = new Cart(); + $cart->setToken($uniqid); + $cart->setCustomer($customer); + $cart->save(); + + $request->cookies->set("thelia_cart", $uniqid); + + $request->getSession()->setCustomerUser($customer); + + $getCart = $actionCart->getCart($request); + $this->assertInstanceOf("Thelia\Model\Cart", $getCart, '$cart must be an instance of cart model Thelia\Model\Cart'); + $this->assertNotNull($getCart->getCustomerId()); + $this->assertNull($getCart->getAddressDeliveryId()); + $this->assertNull($getCart->getAddressInvoiceId()); + $this->assertEquals($cart->getToken(), $getCart->getToken(), "token must be the same"); + $this->assertEquals($customer->getId(), $getCart->getCustomerId()); + } + + /** + * Customer is connected but cart not associated to him + * + * A new cart must be created (duplicated) containing customer id + */ + public function testGetCartWithExistinsCartAndCustomerButNotSameCustomerId() + { + $actionCart = $this->actionCart; + + $request = $this->request; + + + //create a fake customer just for test. If not persists test fails ! + $customer = new Customer(); + $customer->setFirstname("john"); + $customer->setLastname("doe"); + $customer->setTitleId(1); + $customer->save(); + + $uniqid = uniqid("test3", true); + //create a fake cart in database; + $cart = new Cart(); + $cart->setToken($uniqid); + + $cart->save(); + + $request->cookies->set("thelia_cart", $uniqid); + + $request->getSession()->setCustomerUser($customer); + + $getCart = $actionCart->getCart($request); + $this->assertInstanceOf("Thelia\Model\Cart", $getCart, '$cart must be an instance of cart model Thelia\Model\Cart'); + $this->assertNotNull($getCart->getCustomerId()); + $this->assertNull($getCart->getAddressDeliveryId()); + $this->assertNull($getCart->getAddressInvoiceId()); + $this->assertNotEquals($cart->getToken(), $getCart->getToken(), "token must be different"); + $this->assertEquals($customer->getId(), $getCart->getCustomerId()); + } + +} \ No newline at end of file diff --git a/core/lib/Thelia/Tests/Command/BaseCommandTest.php b/core/lib/Thelia/Tests/Command/BaseCommandTest.php index ca9d0a632..356478ab9 100644 --- a/core/lib/Thelia/Tests/Command/BaseCommandTest.php +++ b/core/lib/Thelia/Tests/Command/BaseCommandTest.php @@ -1,12 +1,25 @@ . */ +/* */ +/*************************************************************************************/ namespace Thelia\Tests\Command; diff --git a/core/lib/Thelia/Tests/Core/HttpFoundation/Session/SessionTest.php b/core/lib/Thelia/Tests/Core/HttpFoundation/Session/SessionTest.php new file mode 100644 index 000000000..67fbfd1c2 --- /dev/null +++ b/core/lib/Thelia/Tests/Core/HttpFoundation/Session/SessionTest.php @@ -0,0 +1,136 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Tests\Core\HttpFoundation\Session; + +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; +use Thelia\Core\HttpFoundation\Session\Session; +use Thelia\Model\Cart; +use Thelia\Model\Customer; + +class SessionTest extends \PHPUnit_Framework_TestCase +{ + + protected $session; + + public function setUp() + { + $this->session = new Session(new MockArraySessionStorage()); + } + + public function testGetCartWithoutExistingCart() + { + $session = $this->session; + + $cart = $session->getCart(); + + $this->assertNull($cart); + } + + public function testGetCartWithExistingCartWithoutCustomerConnected() + { + $session = $this->session; + + $testCart = new Cart(); + $testCart->setToken(uniqid("testSessionGetCart1", true)); + $testCart->save(); + + $session->setCart($testCart->getId()); + + $cart = $session->getCart(); + + $this->assertNotNull($cart); + $this->assertInstanceOf("\Thelia\Model\Cart", $cart, '$cart must be an instance of Thelia\Model\Cart'); + $this->assertEquals($testCart->getToken(), $cart->getToken()); + + } + + public function testGetCartWithExistingCustomerButNoCart() + { + $session = $this->session; + + //create a fake customer just for test. If not persists test fails ! + $customer = new Customer(); + $customer->setFirstname("john test session"); + $customer->setLastname("doe"); + $customer->setTitleId(1); + $customer->save(); + + $session->setCustomerUser($customer); + + $cart = $session->getCart(); + + $this->assertNull($cart); + } + + public function testGetCartWithExistingCartAndCustomerButWithoutReferenceToCustomerInCart() + { + $session = $this->session; + + //create a fake customer just for test. If not persists test fails ! + $customer = new Customer(); + $customer->setFirstname("john test session"); + $customer->setLastname("doe"); + $customer->setTitleId(1); + $customer->save(); + + $session->setCustomerUser($customer); + + $testCart = new Cart(); + $testCart->setToken(uniqid("testSessionGetCart2", true)); + $testCart->save(); + + $session->setCart($testCart->getId()); + + $cart = $session->getCart(); + + $this->assertNull($cart); + } + + public function testGetCartWithExistingCartAndCustomerAndReferencesEachOther() + { + $session = $this->session; + + //create a fake customer just for test. If not persists test fails ! + $customer = new Customer(); + $customer->setFirstname("john test session"); + $customer->setLastname("doe"); + $customer->setTitleId(1); + $customer->save(); + + $session->setCustomerUser($customer); + + $testCart = new Cart(); + $testCart->setToken(uniqid("testSessionGetCart3", true)); + $testCart->setCustomerId($customer->getId()); + $testCart->save(); + + $session->setCart($testCart->getId()); + + $cart = $session->getCart(); + + $this->assertNotNull($cart); + $this->assertInstanceOf("\Thelia\Model\Cart", $cart, '$cart must be an instance of Thelia\Model\Cart'); + } + +} \ No newline at end of file diff --git a/install/INSTALL-TODO.txt b/install/INSTALL-TODO.txt index 772946a7c..748a1788c 100644 --- a/install/INSTALL-TODO.txt +++ b/install/INSTALL-TODO.txt @@ -8,3 +8,4 @@ Variables Config à initialiser: - default_locale : la locale par défaut (ex. en_US), à utiliser pour les fichiers de traduction - asset_dir_from_web_root : le chemin relatif à /web du repertoires des assets (ex. assets) - active_template: chemin du template front relatif au repertoire template (ex. default) +- thelia_version: la version de Thelia (ex. 2.0.0 alpha) diff --git a/templates/admin/default/assets/css/admin.less b/templates/admin/default/assets/css/admin.less index c19e623f6..0489c9348 100755 --- a/templates/admin/default/assets/css/admin.less +++ b/templates/admin/default/assets/css/admin.less @@ -112,6 +112,87 @@ hr { text-align: left; } +// -- Top bar ----------------------------------------------------------------- + +.topbar { + + @top-bar-height: 50px; + + background: url("img/top.jpg") repeat-x; + color: #6d737b; + font-size: 13px; + font-weight: bold; + text-shadow: 0px 1px 1px black; + + .form-search { + + position: relative; + float: right; + margin: 0px; + + input.search-query { + background: url("img/search.png") no-repeat; + width: 212px; + height: 20px; + outline: none; + border: none; + padding: 5px 20px 5px 20px; + border-radius: 0px; + font-size: 12px; + color: #eee; + + &:focus { + box-shadow: none; + color: white; + } + } + + button.btn { + position: absolute; + right: 5px; + text-indent: -13337px; + background: url("img/search-icon.png") no-repeat; + width: 16px; + height: 15px; + display: block; + cursor: pointer; + outline: none; + border: none; + top: 17px; + box-shadow: none; + border-radius: 0px; + z-index: 1337; + } + } + + .container { + line-height: @top-bar-height; + } + + .version-info { + float: left; + line-height: @top-bar-height; + background: url("img/top-bar-logo.png") left -3px no-repeat; + padding-left: 100px; + + } + + .user-info { + float: right; + line-height: @top-bar-height; + margin-left: 20px; + color: #fff; + + a.logout { + text-indent: -13337px; + display: inline-block; + background: url("img/logout.png") left center no-repeat; + width: 23px; + height: @top-bar-height; + } + } +} + // -- Brandbar ---------------------------------------------------------------- .loginpage { diff --git a/templates/admin/default/assets/css/img/search-icon.png b/templates/admin/default/assets/css/img/search-icon.png new file mode 100644 index 000000000..66178cb8f Binary files /dev/null and b/templates/admin/default/assets/css/img/search-icon.png differ diff --git a/templates/admin/default/assets/css/img/search.png b/templates/admin/default/assets/css/img/search.png new file mode 100644 index 000000000..417c73dbb Binary files /dev/null and b/templates/admin/default/assets/css/img/search.png differ diff --git a/templates/admin/default/assets/css/img/top-bar-logo.png b/templates/admin/default/assets/css/img/top-bar-logo.png new file mode 100644 index 000000000..e1f3b8786 Binary files /dev/null and b/templates/admin/default/assets/css/img/top-bar-logo.png differ diff --git a/templates/admin/default/assets/css/img/top.jpg b/templates/admin/default/assets/css/img/top.jpg new file mode 100644 index 000000000..20ea5dd18 Binary files /dev/null and b/templates/admin/default/assets/css/img/top.jpg differ diff --git a/templates/admin/default/home.html b/templates/admin/default/home.html index 1f1e7b4e5..83ae4fc68 100755 --- a/templates/admin/default/home.html +++ b/templates/admin/default/home.html @@ -3,13 +3,9 @@ {include file='includes/header.inc.html'}
- +
-
- - {module_include location='index_top'} + {module_include location='home_top'} welcome home ! diff --git a/templates/admin/default/includes/header.inc.html b/templates/admin/default/includes/header.inc.html index 712a0a600..e0dd1997c 100755 --- a/templates/admin/default/includes/header.inc.html +++ b/templates/admin/default/includes/header.inc.html @@ -19,6 +19,127 @@ {/stylesheets} - {* TODO allow modules to include CSS here *} + {module_include location='head_css'} - \ No newline at end of file + + +{* display top bar once admin is connected *} + +{loop name="top-bar-auth" type="auth" context="admin" roles="ADMIN"} + +{module_include location='before_topbar'} + +
+
+ +
{intl l='Version %ver' ver="{$THELIA_VERSION}"}
+ + {module_include location='inside_topbar'} + + + + {loop name="top-bar-search" type="auth" context="admin" roles="ADMIN" permissions="admin.search"} + + {/loop} +
+
+ +{module_include location='after_topbar'} + + +{module_include location='before_top_menu'} + + + +{module_include location='after_top_menu'} + +{/loop} \ No newline at end of file