From 6867eae9b76ea43eedecd13270f80954742a3e4e Mon Sep 17 00:00:00 2001 From: franck Date: Fri, 30 Aug 2013 19:46:12 +0200 Subject: [PATCH 01/23] Fixed customer front controller, events, addec admion config. --- core/lib/Thelia/Action/Category.php | 8 +- core/lib/Thelia/Action/Customer.php | 15 +- core/lib/Thelia/Config/Resources/action.xml | 4 +- .../Thelia/Config/Resources/routing/front.xml | 6 +- .../Controller/Admin/BaseAdminController.php | 8 +- .../Controller/Admin/CategoryController.php | 28 +- .../Controller/Admin/SessionController.php | 11 +- core/lib/Thelia/Controller/BaseController.php | 27 +- .../Controller/Front/CustomerController.php | 175 +++++++---- .../Thelia/Core/Event/CategoryChangeEvent.php | 44 +++ .../Event/CategoryChangePositionEvent.php | 29 +- .../Thelia/Core/Event/CategoryCreateEvent.php | 1 - .../Thelia/Core/Event/CategoryDeleteEvent.php | 14 +- .../Event/CategoryToggleVisibilityEvent.php | 14 +- .../Thelia/Core/Event/CustomerLoginEvent.php | 2 +- .../Core/EventListener/ControllerListener.php | 7 +- .../UsernamePasswordFormAuthenticator.php | 2 - .../Thelia/Core/Security/SecurityContext.php | 20 ++ .../Thelia/Core/Template/Element/BaseLoop.php | 2 +- .../Thelia/Core/Template/Loop/Category.php | 10 +- core/lib/Thelia/Core/Template/Loop/Image.php | 16 +- .../Thelia/Core/Template/ParserContext.php | 4 + core/lib/Thelia/Model/Base/Category.php | 1 - core/lib/Thelia/Model/Lang.php | 29 ++ .../Thelia/Model/Tools/ModelCriteriaTools.php | 3 +- install/faker.php | 8 +- templates/admin/default/assets/css/admin.less | 48 ++- templates/admin/default/categories.html | 71 ++++- templates/admin/default/configuration.html | 174 +++++++++++ templates/admin/default/edit_category.html | 279 ++++++++++-------- templates/admin/default/general_error.html | 2 +- .../admin/default/includes/header.inc.html | 12 +- templates/admin/default/login.html | 3 - templates/default/includes/header.html | 4 +- templates/default/login.html | 13 +- 35 files changed, 810 insertions(+), 284 deletions(-) create mode 100644 core/lib/Thelia/Core/Event/CategoryChangeEvent.php create mode 100644 templates/admin/default/configuration.html diff --git a/core/lib/Thelia/Action/Category.php b/core/lib/Thelia/Action/Category.php index d411d2a51..b9bde8a07 100755 --- a/core/lib/Thelia/Action/Category.php +++ b/core/lib/Thelia/Action/Category.php @@ -75,7 +75,7 @@ class Category extends BaseAction implements EventSubscriberInterface { $this->checkAuth("ADMIN", "admin.category.delete"); - $category = CategoryQuery::create()->findPk($event->getId()); + $category = CategoryQuery::create()->findPk($event->getCategoryId()); if ($category !== null) { @@ -98,7 +98,7 @@ class Category extends BaseAction implements EventSubscriberInterface { $this->checkAuth("ADMIN", "admin.category.edit"); - $category = CategoryQuery::create()->findPk($event->getId()); + $category = CategoryQuery::create()->findPk($event->getCategoryId()); if ($category !== null) { @@ -136,7 +136,7 @@ class Category extends BaseAction implements EventSubscriberInterface */ protected function exchangePosition(CategoryChangePositionEvent $event) { - $category = CategoryQuery::create()->findPk($event->getId()); + $category = CategoryQuery::create()->findPk($event->getCategoryId()); if ($category !== null) { @@ -195,7 +195,7 @@ class Category extends BaseAction implements EventSubscriberInterface { $this->checkAuth("ADMIN", "admin.category.edit"); - $category = CategoryQuery::create()->findPk($event->getId()); + $category = CategoryQuery::create()->findPk($event->getCategoryId()); if ($category !== null) { diff --git a/core/lib/Thelia/Action/Customer.php b/core/lib/Thelia/Action/Customer.php index 4c7a71d5e..aed93d390 100755 --- a/core/lib/Thelia/Action/Customer.php +++ b/core/lib/Thelia/Action/Customer.php @@ -38,6 +38,7 @@ use Symfony\Component\Validator\Exception\ValidatorException; use Thelia\Core\Security\Exception\AuthenticationException; use Thelia\Core\Security\Exception\UsernameNotFoundException; use Propel\Runtime\Exception\PropelException; +use Thelia\Core\Event\CustomerLoginEvent; class Customer extends BaseAction implements EventSubscriberInterface { @@ -46,7 +47,6 @@ class Customer extends BaseAction implements EventSubscriberInterface { $customer = new CustomerModel(); - $customer->setDispatcher($this->getDispatcher()); $this->createOrUpdateCustomer($customer, $event); @@ -56,7 +56,6 @@ class Customer extends BaseAction implements EventSubscriberInterface { $customer = $event->getCustomer(); - $customer->setDispatcher($this->getDispatcher()); $this->createOrUpdateCustomer($customer, $event); @@ -64,6 +63,8 @@ class Customer extends BaseAction implements EventSubscriberInterface private function createOrUpdateCustomer(CustomerModel $customer, CustomerCreateOrUpdateEvent $event) { + $customer->setDispatcher($this->getDispatcher()); + $customer->createOrUpdate( $event->getTitle(), $event->getFirstname(), @@ -87,6 +88,12 @@ class Customer extends BaseAction implements EventSubscriberInterface $event->setCustomer($customer); } + + public function login(CustomerLoginEvent $event) + { + $this->getSecurityContext()->setCustomerUser($event->getCustomer()); + } + /** * Perform user logout. The user is redirected to the provided view, if any. * @@ -94,8 +101,6 @@ class Customer extends BaseAction implements EventSubscriberInterface */ public function logout(ActionEvent $event) { - $event->getDispatcher()->dispatch(TheliaEvents::CUSTOMER_LOGOUT, $event); - $this->getSecurityContext()->clearCustomerUser(); } @@ -129,6 +134,8 @@ class Customer extends BaseAction implements EventSubscriberInterface return array( TheliaEvents::CUSTOMER_CREATEACCOUNT => array("create", 128), TheliaEvents::CUSTOMER_UPDATEACCOUNT => array("modify", 128), + TheliaEvents::CUSTOMER_LOGOUT => array("logout", 128), + TheliaEvents::CUSTOMER_LOGIN => array("login" , 128), ); } } diff --git a/core/lib/Thelia/Config/Resources/action.xml b/core/lib/Thelia/Config/Resources/action.xml index 2bd31ce3e..7d21eadee 100755 --- a/core/lib/Thelia/Config/Resources/action.xml +++ b/core/lib/Thelia/Config/Resources/action.xml @@ -22,12 +22,12 @@ - + - + diff --git a/core/lib/Thelia/Config/Resources/routing/front.xml b/core/lib/Thelia/Config/Resources/routing/front.xml index c420e1550..9329b22ad 100755 --- a/core/lib/Thelia/Config/Resources/routing/front.xml +++ b/core/lib/Thelia/Config/Resources/routing/front.xml @@ -18,10 +18,14 @@ Thelia\Controller\Front\CustomerController::updateAction - + Thelia\Controller\Front\CustomerController::loginAction + + Thelia\Controller\Front\CustomerController::logoutAction + + Thelia\Controller\Front\CartController::addItem cart diff --git a/core/lib/Thelia/Controller/Admin/BaseAdminController.php b/core/lib/Thelia/Controller/Admin/BaseAdminController.php index 271ce3c05..989715de4 100755 --- a/core/lib/Thelia/Controller/Admin/BaseAdminController.php +++ b/core/lib/Thelia/Controller/Admin/BaseAdminController.php @@ -52,11 +52,13 @@ class BaseAdminController extends BaseController if (! empty($template)) { // If we have a view in the URL, render this view return $this->render($template); - } elseif (null != $view = $this->getRequest()->get('view')) { + } + elseif (null != $view = $this->getRequest()->get('view')) { return $this->render($view); } - } catch (\Exception $ex) { - // Nothing special + } + catch (\Exception $ex) { + return new Response($this->errorPage($ex->getMessage())); } return $this->pageNotFound(); diff --git a/core/lib/Thelia/Controller/Admin/CategoryController.php b/core/lib/Thelia/Controller/Admin/CategoryController.php index 4e798d683..f922f1b9d 100755 --- a/core/lib/Thelia/Controller/Admin/CategoryController.php +++ b/core/lib/Thelia/Controller/Admin/CategoryController.php @@ -33,6 +33,7 @@ use Thelia\Core\Event\CategoryDeleteEvent; use Thelia\Core\Event\CategoryToggleVisibilityEvent; use Thelia\Core\Event\CategoryChangePositionEvent; use Thelia\Form\CategoryDeletionForm; +use Thelia\Model\Lang; class CategoryController extends BaseAdminController { @@ -99,7 +100,7 @@ class CategoryController extends BaseAdminController $this->adminLogAppend(sprintf("Category %s (ID %s) deleted", $category->getTitle(), $category->getId())); // Substitute _ID_ in the URL with the ID of the created category - $successUrl = str_replace('_ID_', $categoryDeleteEvent->getDeletedCategory()->getId(), $categoryDeletionForm->getSuccessUrl()); + $successUrl = str_replace('_ID_', $categoryDeleteEvent->getDeletedCategory()->getParent(), $categoryDeletionForm->getSuccessUrl()); // Redirect to the success URL $this->redirect($successUrl); @@ -185,11 +186,34 @@ class CategoryController extends BaseAdminController // Get the category ID $id = $this->getRequest()->get('id', 0); + // Find the current order + $category_order = $this->getRequest()->get( + 'category_order', + $this->getSession()->get('admin.category_order', 'manual') + ); + + // Find the current edit language ID + $edition_language = $this->getRequest()->get( + 'edition_language', + $this->getSession()->get('admin.edition_language', Lang::getDefaultLanguage()->getId()) + ); + $args = array( 'action' => $action, - 'current_category_id' => $id + 'current_category_id' => $id, + 'category_order' => $category_order, + 'edition_language' => $edition_language, + 'date_format' => Lang::getDefaultLanguage()->getDateFormat(), + 'time_format' => Lang::getDefaultLanguage()->getTimeFormat(), + 'datetime_format' => Lang::getDefaultLanguage()->getDateTimeFormat(), ); + // Store the current sort order in session + $this->getSession()->set('admin.category_order', $category_order); + + // Store the current edition language in session + $this->getSession()->set('admin.edition_language', $edition_language); + try { switch ($action) { case 'browse' : // Browse categories diff --git a/core/lib/Thelia/Controller/Admin/SessionController.php b/core/lib/Thelia/Controller/Admin/SessionController.php index 39dbc1205..4e4e909e2 100755 --- a/core/lib/Thelia/Controller/Admin/SessionController.php +++ b/core/lib/Thelia/Controller/Admin/SessionController.php @@ -51,13 +51,16 @@ class SessionController extends BaseAdminController public function checkLoginAction() { - $adminLoginForm = new AdminLogin($this->getRequest()); - $request = $this->getRequest(); - $authenticator = new AdminUsernamePasswordFormAuthenticator($request, $adminLoginForm); + $adminLoginForm = new AdminLogin($request); try { + + $form = $this->validateForm($adminLoginForm, "post"); + + $authenticator = new AdminUsernamePasswordFormAuthenticator($request, $adminLoginForm); + $user = $authenticator->getAuthentifiedUser(); // Success -> store user in security context @@ -85,7 +88,7 @@ class SessionController extends BaseAdminController // Log authentication failure AdminLog::append(sprintf("Undefined error: %s", $ex->getMessage()), $request); - $message = "Unable to process your request. Please try again."; + $message = "Unable to process your request. Please try again.".$ex->getMessage(); } // Store error information in the form diff --git a/core/lib/Thelia/Controller/BaseController.php b/core/lib/Thelia/Controller/BaseController.php index 1a610768d..bede9f08c 100755 --- a/core/lib/Thelia/Controller/BaseController.php +++ b/core/lib/Thelia/Controller/BaseController.php @@ -35,6 +35,7 @@ use Thelia\Core\Factory\ActionEventFactory; use Thelia\Form\BaseForm; use Thelia\Form\Exception\FormValidationException; use Symfony\Component\EventDispatcher\Event; +use Thelia\Core\Event\DefaultActionEvent; /** * @@ -60,10 +61,12 @@ class BaseController extends ContainerAware * Dispatch a Thelia event * * @param string $eventName a TheliaEvent name, as defined in TheliaEvents class - * @param Event $event the event + * @param Event $event the action event, or null (a DefaultActionEvent will be dispatched) */ - protected function dispatch($eventName, Event $event = null) + protected function dispatch($eventName, ActionEvent $event = null) { + if ($event == null) $event = new DefaultActionEvent(); + $this->getDispatcher()->dispatch($eventName, $event); } @@ -145,7 +148,8 @@ class BaseController extends ContainerAware /** * - * redirect request to specify url + * redirect request to the specified url + * * @param string $url */ public function redirect($url) @@ -154,12 +158,21 @@ class BaseController extends ContainerAware } /** - * If success_url param is present in request, follow this link. + * If success_url param is present in request or in the provided form, redirect to this URL. + * + * @param BaseForm $form a base form, which may contains the success URL */ - protected function redirectSuccess() + protected function redirectSuccess(BaseForm $form = null) { - if (null !== $url = $this->getRequest()->get("success_url")) { - $this->redirect($url); + if ($form != null) { + $url = $form->getSuccessUrl(); } + else { + $url = $this->getRequest()->get("success_url"); + } + + echo "url=$url"; + + if (null !== $url) $this->redirect($url); } } diff --git a/core/lib/Thelia/Controller/Front/CustomerController.php b/core/lib/Thelia/Controller/Front/CustomerController.php index 698c69d70..de6d15129 100755 --- a/core/lib/Thelia/Controller/Front/CustomerController.php +++ b/core/lib/Thelia/Controller/Front/CustomerController.php @@ -22,8 +22,6 @@ /*************************************************************************************/ namespace Thelia\Controller\Front; -use Propel\Runtime\Exception\PropelException; -use Symfony\Component\Validator\Exception\ValidatorException; use Thelia\Core\Event\CustomerCreateOrUpdateEvent; use Thelia\Core\Event\CustomerLoginEvent; use Thelia\Core\Security\Authentication\CustomerUsernamePasswordFormAuthenticator; @@ -37,65 +35,101 @@ use Thelia\Form\Exception\FormValidationException; use Thelia\Model\Customer; use Thelia\Core\Event\TheliaEvents; use Thelia\Core\Event\CustomerEvent; +use Thelia\Core\Factory\ActionEventFactory; +use Thelia\Tools\URL; +use Thelia\Log\Tlog; +use Thelia\Core\Security\Exception\WrongPasswordException; class CustomerController extends BaseFrontController { /** - * create a new Customer. Retrieve data in form and dispatch a action.createCustomer event - * - * if error occurs, message is set in the parserContext + * Create a new customer. + * On success, redirect to success_url if exists, otherwise, display the same view again. */ public function createAction() { - $request = $this->getRequest(); - $customerCreation = new CustomerCreation($request); - try { - $form = $this->validateForm($customerCreation, "post"); + if (! $this->getSecurityContext()->hasCustomerUser()) { - $customerCreateEvent = $this->createEventInstance($form->getData()); + $message = false; - $this->getDispatcher()->dispatch(TheliaEvents::CUSTOMER_CREATEACCOUNT, $customerCreateEvent); + $customerCreation = new CustomerCreation($this->getRequest()); - $this->processLogin($customerCreateEvent->getCustomer()); + try { + $form = $this->validateForm($customerCreation, "post"); - $this->redirectSuccess(); + $customerCreateEvent = $this->createEventInstance($form->getData()); - } catch (FormValidationException $e) { - $customerCreation->setErrorMessage($e->getMessage()); - $this->getParserContext()->setErrorForm($customerCreation); - } catch (PropelException $e) { - \Thelia\Log\Tlog::getInstance()->error(sprintf("error during customer creation process in front context with message : %s", $e->getMessage())); - $this->getParserContext()->setGeneralError($e->getMessage()); + $this->dispatch(TheliaEvents::CUSTOMER_CREATEACCOUNT, $customerCreateEvent); + + $this->processLogin($customerCreateEvent->getCustomer()); + + $this->redirectSuccess($customerCreation); + } + catch (FormValidationException $e) { + $message = "Invalid or missing data. Please check your input"; + } + catch (\Exception $e) { + $message = "Sorry, an unknown error occured."; + } + + if ($message !== false) { + Tlog::getInstance()->error(sprintf("Error during customer creation process : %s. Exception was %s", $message, $e->getMessage())); + + $customerLoginForm->setErrorMessage($message); + + $this->getParserContext() + ->setErrorForm($customerLoginForm) + ->setGeneralError($message) + ; + } } - } + /** + * Update customer data. On success, redirect to success_url if exists. + * Otherwise, display the same view again. + */ public function updateAction() { - $request = $this->getRequest(); - $customerModification = new CustomerModification($request); + if ($this->getSecurityContext()->hasCustomerUser()) { - try { + $message = false; - $customer = $this->getSecurityContext()->getCustomerUser(); + $customerModification = new CustomerModification($this->getRequest()); - $form = $this->validateForm($customerModification, "post"); + try { - $customerChangeEvent = $this->createEventInstance($form->getData()); - $customerChangeEvent->setCustomer($customer); + $customer = $this->getSecurityContext()->getCustomerUser(); - $this->getDispatcher()->dispatch(TheliaEvents::CUSTOMER_UPDATEACCOUNT, $customerChangeEvent); + $form = $this->validateForm($customerModification, "post"); - $this->processLogin($customerChangeEvent->getCustomer()); + $customerChangeEvent = $this->createEventInstance($form->getData()); + $customerChangeEvent->setCustomer($customer); - $this->redirectSuccess(); + $this->dispatch(TheliaEvents::CUSTOMER_UPDATEACCOUNT, $customerChangeEvent); - } catch (FormValidationException $e) { - $customerModification->setErrorMessage($e->getMessage()); - $this->getParserContext()->setErrorForm($customerModification); - } catch (PropelException $e) { - \Thelia\Log\Tlog::getInstance()->error(sprintf("error during updating customer in front context with message : %s", $e->getMessage())); - $this->getParserContext()->setGeneralError($e->getMessage()); + $this->processLogin($customerChangeEvent->getCustomer()); + + $this->redirectSuccess($customerModification); + + } + catch (FormValidationException $e) { + $message = "Invalid or missing data. Please check your input"; + } + catch (\Exception $e) { + $message = "Sorry, an unknown error occured."; + } + + if ($message !== false) { + Tlog::getInstance()->error(sprintf("Error during customer modification process : %s. Exception was %s", $message, $e->getMessage())); + + $customerLoginForm->setErrorMessage($message); + + $this->getParserContext() + ->setErrorForm($customerLoginForm) + ->setGeneralError($message) + ; + } } } @@ -103,39 +137,75 @@ class CustomerController extends BaseFrontController * Perform user login. On a successful login, the user is redirected to the URL * found in the success_url form parameter, or / if none was found. * - * If login is not successfull, the same view is dispolyed again. + * If login is not successfull, the same view is displayed again. * */ public function loginAction() { - $request = $this->getRequest(); + if (! $this->getSecurityContext()->hasCustomerUser()) { + $message = false; - $customerLoginForm = new CustomerLogin($request); + $request = $this->getRequest(); - $authenticator = new CustomerUsernamePasswordFormAuthenticator($request, $customerLoginForm); + try { - try { - $customer = $authenticator->getAuthentifiedUser(); + $customerLoginForm = new CustomerLogin($request); - $this->processLogin($customer); + $form = $this->validateForm($customerLoginForm, "post"); - $this->redirectSuccess(); - } catch (ValidatorException $e) { + $authenticator = new CustomerUsernamePasswordFormAuthenticator($request, $customerLoginForm); - } catch(UsernameNotFoundException $e) { + $customer = $authenticator->getAuthentifiedUser(); - } catch(AuthenticationException $e) { + $this->processLogin($customer); - } catch (\Exception $e) { + $this->redirectSuccess($customerLoginForm); + } + catch (FormValidationException $e) { + $message = "Invalid or missing data. Please check your input"; + } + catch(UsernameNotFoundException $e) { + $message = "This customer email was not found."; + } + catch (WrongPasswordException $e) { + $message = "Wrong password. Please try again."; + } + catch(AuthenticationException $e) { + $message = "Sorry, we failed to authentify you. Please try again."; + } + catch (\Exception $e) { + $message = "Sorry, an unknown error occured."; + } + + if ($message !== false) { + Tlog::getInstance()->error(sprintf("Error during customer login process : %s. Exception was %s", $message, $e->getMessage())); + + $customerLoginForm->setErrorMessage($message); + + $this->getParserContext()->setErrorForm($customerLoginForm); + } } } - public function processLogin(Customer $customer) + /** + * Perform customer logout. + * + * @param Customer $customer + */ + public function logoutAction() { - $this->getSecurityContext()->setCustomerUser($customer); + if ($this->getSecurityContext()->hasCustomerUser()) { + $this->dispatch(TheliaEvents::CUSTOMER_LOGOUT); + } - if($event) $this->dispatch(TheliaEvents::CUSTOMER_LOGIN, new CustomerLoginEvent($customer)); + // Redirect to home page + $this->redirect(URL::getIndexPage()); + } + + protected function processLogin(Customer $customer) + { + $this->dispatch(TheliaEvents::CUSTOMER_LOGIN, new CustomerLoginEvent($customer)); } /** @@ -161,10 +231,9 @@ class CustomerController extends BaseFrontController $this->getRequest()->getSession()->getLang(), isset($data["reseller"])?$data["reseller"]:null, isset($data["sponsor"])?$data["sponsor"]:null, - isset($data["discount"])?$data["discount"]:nullsch + isset($data["discount"])?$data["discount"]:null ); return $customerCreateEvent; } - } diff --git a/core/lib/Thelia/Core/Event/CategoryChangeEvent.php b/core/lib/Thelia/Core/Event/CategoryChangeEvent.php new file mode 100644 index 000000000..e8e183b3f --- /dev/null +++ b/core/lib/Thelia/Core/Event/CategoryChangeEvent.php @@ -0,0 +1,44 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Core\Event; + +use Thelia\Model\Category; + +class CategoryCreateEvent extends ActionEvent +{ + protected $category_id; + protected $locale; + protected $title; + protected $chapo; + protected $description; + protected $postscriptum; + protected $url; + protected $visibility; + protected $parent; + + public function __construct($category_id) + { + $this->category_id = $category_id; + } +} diff --git a/core/lib/Thelia/Core/Event/CategoryChangePositionEvent.php b/core/lib/Thelia/Core/Event/CategoryChangePositionEvent.php index 141fc8182..94f131626 100644 --- a/core/lib/Thelia/Core/Event/CategoryChangePositionEvent.php +++ b/core/lib/Thelia/Core/Event/CategoryChangePositionEvent.php @@ -30,28 +30,18 @@ class CategoryChangePositionEvent extends ActionEvent const POSITION_DOWN = 2; const POSITION_ABSOLUTE = 3; - protected $id; + protected $category_id; protected $mode; protected $position; protected $category; - public function __construct($id, $mode, $position = null) + public function __construct($category_id, $mode, $position = null) { - $this->id = $id; + $this->category_id = $category_id; $this->mode = $mode; $this->position = $position; } - public function getId() - { - return $this->id; - } - - public function setId($id) - { - $this->id = $id; - } - public function getMode() { return $this->mode; @@ -81,4 +71,15 @@ class CategoryChangePositionEvent extends ActionEvent { $this->category = $category; } -} \ No newline at end of file + + public function getCategoryId() + { + return $this->category_id; + } + + public function setCategoryId($category_id) + { + $this->category_id = $category_id; + } + +} diff --git a/core/lib/Thelia/Core/Event/CategoryCreateEvent.php b/core/lib/Thelia/Core/Event/CategoryCreateEvent.php index 558b04277..f4d5a45ee 100644 --- a/core/lib/Thelia/Core/Event/CategoryCreateEvent.php +++ b/core/lib/Thelia/Core/Event/CategoryCreateEvent.php @@ -77,6 +77,5 @@ class CategoryCreateEvent extends ActionEvent public function setCreatedCategory(Category $created_category) { $this->created_category = $created_category; -var_dump($this->created_category); } } diff --git a/core/lib/Thelia/Core/Event/CategoryDeleteEvent.php b/core/lib/Thelia/Core/Event/CategoryDeleteEvent.php index c53cb7e10..3e863be8e 100644 --- a/core/lib/Thelia/Core/Event/CategoryDeleteEvent.php +++ b/core/lib/Thelia/Core/Event/CategoryDeleteEvent.php @@ -26,22 +26,22 @@ use Thelia\Model\Category; class CategoryDeleteEvent extends ActionEvent { - protected $id; + protected $category_id; protected $deleted_category; - public function __construct($id) + public function __construct($category_id) { - $this->id = $id; + $this->category_id = $category_id; } - public function getId() + public function getCategoryId() { - return $this->id; + return $this->category_id; } - public function setId($id) + public function setCategoryId($category_id) { - $this->id = $id; + $this->category_id = $category_id; } public function getDeletedCategory() diff --git a/core/lib/Thelia/Core/Event/CategoryToggleVisibilityEvent.php b/core/lib/Thelia/Core/Event/CategoryToggleVisibilityEvent.php index b7237924e..ef921a0de 100644 --- a/core/lib/Thelia/Core/Event/CategoryToggleVisibilityEvent.php +++ b/core/lib/Thelia/Core/Event/CategoryToggleVisibilityEvent.php @@ -26,22 +26,22 @@ use Thelia\Model\Category; class CategoryToggleVisibilityEvent extends ActionEvent { - protected $id; + protected $category_id; protected $category; - public function __construct($id) + public function __construct($category_id) { - $this->id = $id; + $this->category_id = $category_id; } - public function getId() + public function getCategoryId() { - return $this->id; + return $this->category_id; } - public function setId($id) + public function setCategoryId($category_id) { - $this->id = $id; + $this->category_id = $category_id; } public function getCategory() diff --git a/core/lib/Thelia/Core/Event/CustomerLoginEvent.php b/core/lib/Thelia/Core/Event/CustomerLoginEvent.php index cc363790d..9a26bba3f 100755 --- a/core/lib/Thelia/Core/Event/CustomerLoginEvent.php +++ b/core/lib/Thelia/Core/Event/CustomerLoginEvent.php @@ -26,7 +26,7 @@ namespace Thelia\Core\Event; use Thelia\Model\Customer; -class CustomerLoginEvent { +class CustomerLoginEvent extends ActionEvent { protected $customer; diff --git a/core/lib/Thelia/Core/EventListener/ControllerListener.php b/core/lib/Thelia/Core/EventListener/ControllerListener.php index 9bb432e6a..0585bbe81 100755 --- a/core/lib/Thelia/Core/EventListener/ControllerListener.php +++ b/core/lib/Thelia/Core/EventListener/ControllerListener.php @@ -59,12 +59,7 @@ class ControllerListener implements EventSubscriberInterface $event = new ActionEventFactory($request, $action, $event->getKernel()->getContainer()->getParameter("thelia.actionEvent")); $actionEvent = $event->createActionEvent(); $dispatcher->dispatch("action.".$action, $actionEvent); - - // Process form errors - if ($actionEvent->hasErrorForm()) { - $this->parserContext->setErrorForm($actionEvent->getErrorForm()); - } - } + } } public static function getSubscribedEvents() diff --git a/core/lib/Thelia/Core/Security/Authentication/UsernamePasswordFormAuthenticator.php b/core/lib/Thelia/Core/Security/Authentication/UsernamePasswordFormAuthenticator.php index 6dc938d88..d9a223430 100755 --- a/core/lib/Thelia/Core/Security/Authentication/UsernamePasswordFormAuthenticator.php +++ b/core/lib/Thelia/Core/Security/Authentication/UsernamePasswordFormAuthenticator.php @@ -55,8 +55,6 @@ class UsernamePasswordFormAuthenticator implements AuthenticatorInterface ); $this->options = array_merge($defaults, $options); - - $this->loginForm->bind($this->request); } /** diff --git a/core/lib/Thelia/Core/Security/SecurityContext.php b/core/lib/Thelia/Core/Security/SecurityContext.php index c09945f61..6ddb47f00 100755 --- a/core/lib/Thelia/Core/Security/SecurityContext.php +++ b/core/lib/Thelia/Core/Security/SecurityContext.php @@ -60,6 +60,16 @@ class SecurityContext return $this->getSession()->getAdminUser(); } + /** + * Check if an admin user is logged in. + * + * @return true if an admin user is logged in, false otherwise. + */ + public function hasAdminUser() + { + return $this->getSession()->getAdminUser() != null; + } + /** * Gets the currently authenticated customer, or null if none is defined * @@ -70,6 +80,16 @@ class SecurityContext return $this->getSession()->getCustomerUser(); } + /** + * Check if a customer user is logged in. + * + * @return true if a customer is logged in, false otherwise. + */ + public function hasCustomerUser() + { + return $this->getSession()->getCustomerUser() != null; + } + /** * Check if a user has at least one of the required roles * diff --git a/core/lib/Thelia/Core/Template/Element/BaseLoop.php b/core/lib/Thelia/Core/Template/Element/BaseLoop.php index 8861022e9..03956386d 100755 --- a/core/lib/Thelia/Core/Template/Element/BaseLoop.php +++ b/core/lib/Thelia/Core/Template/Element/BaseLoop.php @@ -138,7 +138,7 @@ abstract class BaseLoop } elseif ($value !== null && !$argument->type->isValid($value)) { /* check type */ $faultActor[] = $argument->name; - $faultDetails[] = sprintf('Invalid value for "%s" argument in loop type: %s, name: %s', $argument->name, $loopType, $loopName); + $faultDetails[] = sprintf('Invalid value "%s" for "%s" argument in loop type: %s, name: %s', $value, $argument->name, $loopType, $loopName); } else { /* set default */ /* did it as last checking for we consider default value is acceptable no matter type or empty restriction */ diff --git a/core/lib/Thelia/Core/Template/Loop/Category.php b/core/lib/Thelia/Core/Template/Loop/Category.php index e01ce3df4..d7ed1ddf9 100755 --- a/core/lib/Thelia/Core/Template/Loop/Category.php +++ b/core/lib/Thelia/Core/Template/Loop/Category.php @@ -79,7 +79,7 @@ class Category extends BaseLoop new Argument( 'order', new TypeCollection( - new Type\EnumListType(array('alpha', 'alpha_reverse', 'manual', 'manual_reverse', 'random')) + new Type\EnumListType(array('alpha', 'alpha_reverse', 'manual', 'manual_reverse', 'visible', 'visible_reverse', 'random')) ), 'manual' ), @@ -146,6 +146,12 @@ class Category extends BaseLoop case "manual": $search->orderByPosition(Criteria::ASC); break; + case "visible": + $search->orderByVisible(Criteria::ASC); + break; + case "visible_reverse": + $search->orderByVisible(Criteria::DESC); + break; case "random": $search->clearOrderByColumns(); $search->addAscendingOrderByColumn('RAND()'); @@ -173,7 +179,7 @@ class Category extends BaseLoop $loopResultRow ->set("ID", $category->getId()) ->set("IS_TRANSLATED",$category->getVirtualColumn('IS_TRANSLATED')) - ->set("TITLE",$category->getVirtualColumn('i18n_TITLE')) + ->set("TITLE", $category->getVirtualColumn('i18n_TITLE')) ->set("CHAPO", $category->getVirtualColumn('i18n_CHAPO')) ->set("DESCRIPTION", $category->getVirtualColumn('i18n_DESCRIPTION')) ->set("POSTSCRIPTUM", $category->getVirtualColumn('i18n_POSTSCRIPTUM')) diff --git a/core/lib/Thelia/Core/Template/Loop/Image.php b/core/lib/Thelia/Core/Template/Loop/Image.php index 638905dc2..e26bcc9fe 100755 --- a/core/lib/Thelia/Core/Template/Loop/Image.php +++ b/core/lib/Thelia/Core/Template/Loop/Image.php @@ -63,7 +63,6 @@ class Image extends BaseLoop $queryClass = sprintf("\Thelia\Model\%sImageQuery", $object); $filterMethod = sprintf("filterBy%sId", $object); - $mapClass = sprintf("\Thelia\Model\Map\%sI18nTableMap", $object); // xxxImageQuery::create() $method = new \ReflectionMethod($queryClass, 'create'); @@ -73,19 +72,16 @@ class Image extends BaseLoop $method = new \ReflectionMethod($queryClass, $filterMethod); $method->invoke($search, $object_id); - $map = new \ReflectionClass($mapClass); - $title_map = $map->getConstant('TITLE'); - $orders = $this->getOrder(); // Results ordering foreach ($orders as $order) { switch ($order) { case "alpha": - $search->addAscendingOrderByColumn($title_map); + $search->addAscendingOrderByColumn('i18n_TITLE'); break; case "alpha-reverse": - $search->addDescendingOrderByColumn($title_map); + $search->addDescendingOrderByColumn('i18n_TITLE'); break; case "manual-reverse": $search->orderByPosition(Criteria::DESC); @@ -122,7 +118,7 @@ class Image extends BaseLoop $source_id = $this->getSourceId(); - // echo "source = ".$this->getSource().", id=".$id."
"; + // echo "source = ".$this->getSource().", id=".$source_id." - ".$this->getArg('source_id')->getValue()."
"; if (is_null($source_id)) { throw new \InvalidArgumentException("'source_id' argument cannot be null if 'source' argument is specified."); @@ -167,6 +163,9 @@ class Image extends BaseLoop $search = $this->getSearchQuery($object_type, $object_id); + /* manage translations */ + $this->configureI18nProcessing($search); + $id = $this->getId(); if (! is_null($id)) { @@ -207,8 +206,7 @@ class Image extends BaseLoop } - /* manage translations */ - $this->configureI18nProcessing($search); + // echo "sql=".$search->toString(); $results = $this->search($search, $pagination); diff --git a/core/lib/Thelia/Core/Template/ParserContext.php b/core/lib/Thelia/Core/Template/ParserContext.php index 03c3cf45f..801b5a127 100755 --- a/core/lib/Thelia/Core/Template/ParserContext.php +++ b/core/lib/Thelia/Core/Template/ParserContext.php @@ -56,11 +56,15 @@ class ParserContext implements \IteratorAggregate public function setErrorForm(BaseForm $form) { $this->set('error_form', $form); + + return $this; } public function setGeneralError($error) { $this->set('general_error', $error); + + return $this; } public function getErrorForm() diff --git a/core/lib/Thelia/Model/Base/Category.php b/core/lib/Thelia/Model/Base/Category.php index 46a8876ef..d03fd04ad 100755 --- a/core/lib/Thelia/Model/Base/Category.php +++ b/core/lib/Thelia/Model/Base/Category.php @@ -474,7 +474,6 @@ abstract class Category implements ActiveRecordInterface if (!$this->hasVirtualColumn($name)) { throw new PropelException(sprintf('Cannot get value of inexistent virtual column %s.', $name)); } - return $this->virtualColumns[$name]; } diff --git a/core/lib/Thelia/Model/Lang.php b/core/lib/Thelia/Model/Lang.php index d63422680..3339dec64 100755 --- a/core/lib/Thelia/Model/Lang.php +++ b/core/lib/Thelia/Model/Lang.php @@ -6,4 +6,33 @@ use Thelia\Model\Base\Lang as BaseLang; class Lang extends BaseLang { + /** + * Return the default language object, using a local variable to cache it. + * + * @throws RuntimeException + */ + private static $default_lang = null; + + public static function getDefaultLanguage() { + + if (self::$default_lang == null) { + $default_lang = LangQuery::create()->findOneByByDefault(true); + + if ($default_lang == null) throw new RuntimeException("No default language is defined. Please define one."); + } + + return $default_lang; + } + + public function getDateFormat() { + return "d/m/Y"; + } + + public function getTimeFormat() { + return "H:i:s"; + } + + public function getDateTimeFormat() { + return "d/m/Y H:i:s"; + } } diff --git a/core/lib/Thelia/Model/Tools/ModelCriteriaTools.php b/core/lib/Thelia/Model/Tools/ModelCriteriaTools.php index 3913b2890..578b2c19d 100755 --- a/core/lib/Thelia/Model/Tools/ModelCriteriaTools.php +++ b/core/lib/Thelia/Model/Tools/ModelCriteriaTools.php @@ -7,6 +7,7 @@ use Propel\Runtime\ActiveQuery\Join; use Propel\Runtime\ActiveQuery\ModelCriteria; use Thelia\Model\Base\LangQuery; use Thelia\Model\ConfigQuery; +use Thelia\Model\Lang; /** * Class ModelCriteriaTools @@ -52,7 +53,7 @@ class ModelCriteriaTools $search->withColumn('`' . $requestedLocaleI18nAlias . '`.`' . $column . '`', $aliasPrefix . 'i18n_' . $column); } } else { - $defaultLocale = LangQuery::create()->findOneById($defaultLangWithoutTranslation)->getLocale(); + $defaultLocale = Lang::getDefaultLanguage()->getLocale(); $defaultLocaleJoin = new Join(); $defaultLocaleJoin->addExplicitCondition($search->getTableMap()->getName(), $foreignKey, null, $foreignTable . '_i18n', 'ID', $defaultLocaleI18nAlias); diff --git a/install/faker.php b/install/faker.php index 81edd767d..f1e7691d7 100755 --- a/install/faker.php +++ b/install/faker.php @@ -240,7 +240,7 @@ try { //categories and products $productIdList = array(); $categoryIdList = array(); - for($i=0; $i<4; $i++) { + for($i=1; $i<5; $i++) { $category = createCategory($faker, 0, $i, $categoryIdList, $contentIdList); for($j=1; $jsetProductId($productId); generate_image($image, 1, 'product', $productId); - + return $product; } @@ -415,7 +415,7 @@ function createCategory($faker, $parent, $position, &$categoryIdList, $contentId $image = new CategoryImage(); $image->setCategoryId($categoryId); generate_image($image, 1, 'category', $categoryId); - + return $category; } diff --git a/templates/admin/default/assets/css/admin.less b/templates/admin/default/assets/css/admin.less index 9d9f2c482..66a03ab37 100755 --- a/templates/admin/default/assets/css/admin.less +++ b/templates/admin/default/assets/css/admin.less @@ -216,6 +216,10 @@ hr { width: 23px; height: @top-bar-height; } + + a.profile { + color: #fff; + } } .view-shop { @@ -233,10 +237,6 @@ hr { .loginpage { - .brandbar { - width: 100%; - } - .hero-unit { background-color: transparent !important; @@ -316,6 +316,10 @@ hr { } } +.brandbar-wide { + width: 100%; +} + // -- Navigation bar ---------------------------------------------------------- .navbar { @@ -717,4 +721,40 @@ label { // Center the alert box (20px bottom margin) in the table cell padding: 20px 20px 0 20px; } + + th { + a { + color: inherit; + } + } + + td { + vertical-align: middle; + + img { + border: 2px solid white; + border-radius: 4px 4px 4px 4px; + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); + } + } +} + +.menu-list-table .table-striped { + td, th { + text-align: left; + } + + td:nth-child(2) { + text-align: right; + } + + caption { + background-color: #FFFFFF; + border-bottom: 2px solid #A5CED8; + color: #5A6876; + font-weight: bold; + line-height: 30px; + text-align: left; + text-transform: uppercase; + } } \ No newline at end of file diff --git a/templates/admin/default/categories.html b/templates/admin/default/categories.html index 7bf76988c..5d2ef5842 100755 --- a/templates/admin/default/categories.html +++ b/templates/admin/default/categories.html @@ -41,20 +41,72 @@ {ifloop rel="category_list"} - {intl l="Category title"} +   + + {if $category_order == 'alpha'} + + {$order_change = 'alpha_reverse'} + {elseif $category_order == 'alpha_reverse'} + + {$order_change = 'alpha'} + {else} + {$order_change = 'alpha'} + {/if} + + {intl l="Category title"} + + {module_include location='category_list_header'} - {intl l="Online"} - {intl l="Position"} + + {if $category_order == 'visible'} + + {$order_change = 'visible_reverse'} + {elseif $category_order == 'visible_reverse'} + + {$order_change = 'visible'} + {else} + {$order_change = 'visible'} + {/if} + + + {intl l="Online"} + + + + + {if $category_order == 'manual'} + + {$order_change = 'manual_reverse'} + {elseif $category_order == 'manual_reverse'} + + {$order_change = 'manual'} + {else} + {$order_change = 'manual'} + {/if} + + {intl l="Position"} + + {intl l="Actions"} - {loop name="category_list" type="category" visible="*" parent="{$current_category_id}" order="manual"} + {loop name="category_list" type="category" visible="*" parent="{$current_category_id}" order="$category_order"} - {$TITLE} + + {loop type="image" name="cat_image" source="category" source_id="$ID" limit="1" width="50" height="50" resize_mode="crop" backend_context="1"} + #TITLE + {/loop} + + + + + {$TITLE} + + {module_include location='category_list_row'} @@ -141,7 +193,7 @@ {ifloop rel="product_list"} - {intl l="Image"} +   {intl l="Product title"} @@ -156,7 +208,12 @@ {loop name="product_list" type="product" category="{$current_category_id}" order="manual"} - Image ! + + {loop type="image" name="cat_image" source="product" source_id="$ID" limit="1" width="50" height="50" resize_mode="crop" backend_context="1"} + + #TITLE + + {/loop} {$TITLE} diff --git a/templates/admin/default/configuration.html b/templates/admin/default/configuration.html new file mode 100644 index 000000000..6973807c7 --- /dev/null +++ b/templates/admin/default/configuration.html @@ -0,0 +1,174 @@ +{check_auth context="admin" roles="ADMIN" permissions="admin.configuration.view" login_tpl="/admin/login"} + +{$page_title={intl l='Configuration'}} + +{include file='includes/header.inc.html'} + +
+ +
+ + {module_include location='configuration_top'} + +

{intl l="Thelia configuration"}

+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ + {module_include location='configuration_bottom'} +
+
+
+ +{include file='includes/js.inc.html'} + +{include file='includes/footer.inc.html'} \ No newline at end of file diff --git a/templates/admin/default/edit_category.html b/templates/admin/default/edit_category.html index c1e19809f..dfd3b2b91 100755 --- a/templates/admin/default/edit_category.html +++ b/templates/admin/default/edit_category.html @@ -11,7 +11,7 @@
- + {loop name="category_edit" type="category" visible="*" id="{$current_category_id}" backend_context="1" lang="$edition_language"}
@@ -25,156 +25,187 @@
-
- -
+
-
- -
+
+
+
- {include file="includes/inner-form-toolbar.html"} + {include file="includes/inner-form-toolbar.html"} -
-
-
- +
+
+
+ -
- -
-
+
+ +
+
-
- +
+ -
- -
-
+
+ +
+
-
- +
+ -
- +
+ -
-
+
+
-
- +
+ -
- -
-
+
+ +
+
-
- +
+ -
-
- - {intl l='Use default'} +
+ +
{intl l="The rewritten URL to the category page. Click \"Use Default\" button to use the default URL. Use only digits, letters, - and _ characters."}
+
+
+ +
+
+ +
+
+
+   +
+

{intl l='Category created on %date_create. Last modification: %date_change' date_create=$CREATE_DATE->format($datetime_format) date_change=$UPDATE_DATE->format($datetime_format)}

+
+
+
+
+ +
+
+
+ +
+
+
+ {include file="includes/inner-form-toolbar.html"} + +
+
+
+ + +
+
-
{intl l="The rewritten URL to the category page. Click \"Use Default\" button to use the default URL. Use only digits, letters, - and _ characters."}
-
-
+
+
+ -
-
+
+ - + +
+
+
+
- {loop name="cat-parent" type="category-tree" visible="*" category="0" exclude="{$current_category_id}"} - - {/loop} +
+
+
+ - -
-
+
+ +
+
+
-
-
- +
+
+
-
- -
-
-
-
-

aff Date creation ?

-

aff date modif ?

- - -
+
+

Images

+
-
-

Détails divers

-
+
+

Documents

+
-
-

Images

-
+
+

Modules

+
-
-

Documents

-
- -
-

Modules

-
- - - + + + + {/loop} @@ -189,6 +220,12 @@ $(function() { e.preventDefault(); $(this).tab('show'); }); + + $('.use_default_rewriten_url').click(function(ev) { + alert("Not functionnal"); + + ev.preventDefault(); + }); }) diff --git a/templates/admin/default/general_error.html b/templates/admin/default/general_error.html index c41fee7a4..b8f9e8661 100755 --- a/templates/admin/default/general_error.html +++ b/templates/admin/default/general_error.html @@ -1,4 +1,4 @@ -{$page_title={intl l='AN error occured'}} +{$page_title={intl l='An error occured'}} {include file='includes/header.inc.html'} diff --git a/templates/admin/default/includes/header.inc.html b/templates/admin/default/includes/header.inc.html index 65500f05a..9b8d4b18a 100755 --- a/templates/admin/default/includes/header.inc.html +++ b/templates/admin/default/includes/header.inc.html @@ -54,7 +54,9 @@ {module_include location='inside_topbar'} - + {loop name="top-bar-search" type="auth" context="admin" roles="ADMIN" permissions="admin.search"}