From 64031a1883af3844e25d4c4a5b2220292c597ca7 Mon Sep 17 00:00:00 2001 From: franck Date: Thu, 8 Aug 2013 02:39:42 +0200 Subject: [PATCH] Added category creation and deletion --- core/lib/Thelia/Action/Category.php | 266 ++++++++++++++++++ .../Admin/Controller/BaseAdminController.php | 60 +++- .../Admin/Controller/CategoryController.php | 82 +++++- .../Admin/Controller/SessionController.php | 2 +- core/lib/Thelia/Config/Resources/action.xml | 4 + core/lib/Thelia/Config/Resources/config.xml | 10 +- .../Thelia/Config/Resources/routing/admin.xml | 3 +- core/lib/Thelia/Core/Event/ActionEvent.php | 2 +- core/lib/Thelia/Core/Event/CategoryEvent.php | 37 +++ core/lib/Thelia/Core/Event/TheliaEvents.php | 21 ++ .../Core/Factory/ActionEventFactory.php | 1 - .../Core/HttpFoundation/Session/Session.php | 20 -- .../Exception/AuthorizationException.php | 28 ++ .../Thelia/Core/Security/SecurityContext.php | 2 +- .../Thelia/Core/Template/Element/BaseLoop.php | 2 +- .../Core/Template/Loop/Argument/Argument.php | 13 + .../Thelia/Core/Template/Loop/Category.php | 3 +- .../Core/Template/Loop/CategoryPath.php | 15 +- .../Core/Template/Loop/CategoryTree.php | 123 ++++++++ .../lib/Thelia/Core/Template/Loop/Content.php | 5 +- .../lib/Thelia/Core/Template/Loop/Feature.php | 5 +- core/lib/Thelia/Core/Template/Loop/Folder.php | 7 +- core/lib/Thelia/Core/Template/Loop/Lang.php | 114 ++++++++ .../lib/Thelia/Core/Template/Loop/Product.php | 6 +- .../Core/Template/Smarty/Plugins/Assetic.php | 3 +- .../Core/Template/Smarty/Plugins/Form.php | 3 +- .../Template/Smarty/Plugins/UrlGenerator.php | 20 +- core/lib/Thelia/Form/CategoryCreationForm.php | 55 ++++ core/lib/Thelia/Form/CategoryDeletionForm.php | 45 +++ core/lib/Thelia/Model/Base/Currency.php | 76 ++++- core/lib/Thelia/Model/Base/CurrencyQuery.php | 47 +++- core/lib/Thelia/Model/Base/Lang.php | 76 ++++- core/lib/Thelia/Model/Base/LangQuery.php | 47 +++- core/lib/Thelia/Model/Category.php | 32 +++ .../lib/Thelia/Model/Map/CurrencyTableMap.php | 36 ++- core/lib/Thelia/Model/Map/LangTableMap.php | 36 ++- core/lib/Thelia/Tools/URL.php | 6 +- install/insert.sql | 18 +- install/thelia.sql | 2 + local/config/schema.xml | 3 +- templates/admin/default/assets/css/admin.less | 178 +++++++----- .../admin/default/assets/img/flags/en.gif | Bin 0 -> 1256 bytes .../admin/default/assets/img/flags/es.gif | Bin 0 -> 1262 bytes .../admin/default/assets/img/flags/fr.gif | Bin 0 -> 1277 bytes .../admin/default/assets/img/flags/it.gif | Bin 0 -> 1269 bytes templates/admin/default/categories.html | 98 +++++-- templates/admin/default/edit_category.html | 45 +-- templates/admin/default/general_error.html | 10 + .../default/includes/add-category-dialog.html | 66 +++++ .../default/includes/category_breadcrumb.html | 16 +- .../includes/delete-category-dialog.html | 42 +++ .../admin/default/includes/footer.inc.html | 2 +- .../default/includes/inner-form-toolbar.html | 27 ++ templates/admin/default/login.html | 2 +- templates/default/connexion.html | 2 +- 55 files changed, 1569 insertions(+), 255 deletions(-) create mode 100644 core/lib/Thelia/Action/Category.php create mode 100644 core/lib/Thelia/Core/Event/CategoryEvent.php create mode 100644 core/lib/Thelia/Core/Security/Exception/AuthorizationException.php create mode 100644 core/lib/Thelia/Core/Template/Loop/CategoryTree.php create mode 100644 core/lib/Thelia/Core/Template/Loop/Lang.php create mode 100644 core/lib/Thelia/Form/CategoryCreationForm.php create mode 100644 core/lib/Thelia/Form/CategoryDeletionForm.php create mode 100644 templates/admin/default/assets/img/flags/en.gif create mode 100644 templates/admin/default/assets/img/flags/es.gif create mode 100644 templates/admin/default/assets/img/flags/fr.gif create mode 100644 templates/admin/default/assets/img/flags/it.gif create mode 100644 templates/admin/default/general_error.html create mode 100644 templates/admin/default/includes/add-category-dialog.html create mode 100644 templates/admin/default/includes/delete-category-dialog.html create mode 100644 templates/admin/default/includes/inner-form-toolbar.html diff --git a/core/lib/Thelia/Action/Category.php b/core/lib/Thelia/Action/Category.php new file mode 100644 index 000000000..f77d6c964 --- /dev/null +++ b/core/lib/Thelia/Action/Category.php @@ -0,0 +1,266 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Action; + +use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Thelia\Core\Event\ActionEvent; +use Thelia\Core\Event\TheliaEvents; +use Thelia\Model\Category as CategoryModel; +use Thelia\Form\CategoryCreationForm; +use Thelia\Core\Event\CategoryEvent; +use Thelia\Tools\Redirect; +use Thelia\Model\CategoryQuery; +use Thelia\Model\AdminLog; +use Thelia\Form\CategoryDeletionForm; + +class Category implements EventSubscriberInterface +{ + public function create(ActionEvent $event) + { + $request = $event->getRequest(); + + $categoryCreationForm = new CategoryCreationForm($request); + + $form = $categoryCreationForm->getForm(); + + if ($request->isMethod("post")) { + + $form->bind($request); + + if ($form->isValid()) { + + $data = $form->getData(); + + $category = new CategoryModel(); + + try { + $event->getDispatcher()->dispatch(TheliaEvents::BEFORE_CREATECATEGORY, $event); + + $category->create( + $data["title"], + $data["parent"], + $data["locale"] + ); + + AdminLog::append(sprintf("Category %s (ID %s) created", $category->getTitle(), $category->getId()), $request, $request->getSession()->getAdminUser()); + + $categoryEvent = new CategoryEvent($category); + + $event->getDispatcher()->dispatch(TheliaEvents::AFTER_CREATECATEGORY, $categoryEvent); + + // Substitute _ID_ in the URL with the ID of the created category + $successUrl = str_replace('_ID_', $category->getId(), $categoryCreationForm->getSuccessUrl()); + + // Redirect to the success URL + Redirect::exec($successUrl); + + } catch (Exception $e) { + Tlog::getInstance()->error(sprintf('error during creating customer on action/createCustomer with message "%s"', $e->getMessage())); + + $message = "Failed to create this category, please try again."; + } + } + else { + $message = "Missing or invalid data"; + } + } + else { + $message = "Wrong form method !"; + } + + // The form has an error + $categoryCreationForm->setError(true); + $categoryCreationForm->setErrorMessage($message); + + // Store the form in the parser context + $event->setErrorForm($categoryCreationForm); + + // Stop event propagation + $event->stopPropagation(); + } + + public function modify(ActionEvent $event) + { + /* + $request = $event->getRequest(); + + $customerModification = new CustomerModification($request); + + $form = $customerModification->getForm(); + + if ($request->isMethod("post")) { + + $form->bind($request); + + if ($form->isValid()) { + $data = $form->getData(); + + $customer = CustomerQuery::create()->findPk(1); + try { + $customerEvent = new CustomerEvent($customer); + $event->getDispatcher()->dispatch(TheliaEvents::BEFORE_CHANGECUSTOMER, $customerEvent); + + $data = $form->getData(); + + $customer->createOrUpdate( + $data["title"], + $data["firstname"], + $data["lastname"], + $data["address1"], + $data["address2"], + $data["address3"], + $data["phone"], + $data["cellphone"], + $data["zipcode"], + $data["country"] + ); + + $customerEvent->customer = $customer; + $event->getDispatcher()->dispatch(TheliaEvents::AFTER_CHANGECUSTOMER, $customerEvent); + + // Update the logged-in user, and redirect to the success URL (exits) + // We don-t send the login event, as the customer si already logged. + $this->processSuccessfulLogin($event, $customer, $customerModification); + } + catch(PropelException $e) { + + Tlog::getInstance()->error(sprintf('error during modifying customer on action/modifyCustomer with message "%s"', $e->getMessage())); + + $message = "Failed to change your account, please try again."; + } + } + else { + $message = "Missing or invalid data"; + } + } + else { + $message = "Wrong form method !"; + } + + // The form has an error + $customerModification->setError(true); + $customerModification->setErrorMessage($message); + + // Dispatch the errored form + $event->setErrorForm($customerModification); + */ + } + + /** + * Delete a category + * + * @param ActionEvent $event + */ + public function delete(ActionEvent $event) + { + $request = $event->getRequest(); + + $categoryDeletionForm = new CategoryDeletionForm($request); + + $form = $categoryDeletionForm->getForm(); + + if ($request->isMethod("post")) { + + $form->bind($request); + + if ($form->isValid()) { + + $data = $form->getData(); + + try { + $category = CategoryQuery::create()->findPk($data['id']); + + $categoryEvent = new CategoryEvent($category); + + $event->getDispatcher()->dispatch(TheliaEvents::BEFORE_DELETECATEGORY, $categoryEvent); + + $category->delete(); + + AdminLog::append(sprintf("Category %s (ID %s) deleted", $category->getTitle(), $category->getId()), $request, $request->getSession()->getAdminUser()); + + $categoryEvent->category = $category; + + $event->getDispatcher()->dispatch(TheliaEvents::AFTER_DELETECATEGORY, $categoryEvent); + + // Substitute _ID_ in the URL with the ID of the created category + $successUrl = str_replace('_ID_', $category->getParent(), $categoryDeletionForm->getSuccessUrl()); + + // Redirect to the success URL + Redirect::exec($successUrl); + } + catch(PropelException $e) { + + Tlog::getInstance()->error(sprintf('error during deleting category ID=%s on action/modifyCustomer with message "%s"', $data['id'], $e->getMessage())); + + $message = "Failed to change your account, please try again."; + } + } + else { + $message = "Missing or invalid data"; + } + } + else { + $message = "Wrong form method !"; + } + + // The form has an error + $categoryDeletionForm->setError(true); + $categoryDeletionForm->setErrorMessage($message); + + // Store the form in the parser context + $event->setErrorForm($categoryDeletionForm); + + // Stop event propagation + $event->stopPropagation(); + } + + /** + * Returns an array of event names this subscriber listens to. + * + * The array keys are event names and the value can be: + * + * * The method name to call (priority defaults to 0) + * * An array composed of the method name to call and the priority + * * An array of arrays composed of the method names to call and respective + * priorities, or 0 if unset + * + * For instance: + * + * * array('eventName' => 'methodName') + * * array('eventName' => array('methodName', $priority)) + * * array('eventName' => array(array('methodName1', $priority), array('methodName2')) + * + * @return array The event names to listen to + * + * @api + */ + public static function getSubscribedEvents() + { + return array( + "action.createCategory" => array("create", 128), + "action.modifyCategory" => array("modify", 128), + "action.deleteCategory" => array("delete", 128), + ); + } +} diff --git a/core/lib/Thelia/Admin/Controller/BaseAdminController.php b/core/lib/Thelia/Admin/Controller/BaseAdminController.php index 17010a69e..6aa15c001 100755 --- a/core/lib/Thelia/Admin/Controller/BaseAdminController.php +++ b/core/lib/Thelia/Admin/Controller/BaseAdminController.php @@ -38,6 +38,9 @@ use Thelia\Tools\URL; use Thelia\Tools\Redirect; use Thelia\Core\Template\ParserContext; use Thelia\Core\Event\ActionEvent; +use Symfony\Component\EventDispatcher\EventDispatcher; +use Thelia\Core\Factory\ActionEventFactory; +use Thelia\Core\Security\Exception\AuthorizationException; /** * @@ -70,6 +73,19 @@ class BaseAdminController extends ContainerAware return new Response($this->renderRaw(self::TEMPLATE_404), 404); } + /** + * Check current admin user authorisations. An ADMIN role is assumed. + * + * @param unknown $permissions a single permission or an array of permissions. + * + * @throws AuthenticationException if permissions are not granted ti the current user. + */ + protected function checkAuth($permissions) { + + if (! $this->getSecurityContext()->isGranted(array("ADMIN"), is_array($permissions) ? $permissions : array($permissions))) { + throw new AuthorizationException("Sorry, you're not allowed to perform this action"); + } + } /** * Render the givent template, and returns the result as an Http Response. @@ -118,12 +134,43 @@ class BaseAdminController extends ContainerAware } } + /** + * Create an action event, + * + * @return EventDispatcher + */ + protected function dispatchEvent($action) + { + // Create the + $eventFactory = new ActionEventFactory($this->getRequest(), $action, $this->container->getParameter("thelia.actionEvent")); + + $actionEvent = $eventFactory->createActionEvent(); + + $this->getDispatcher()->dispatch("action.$action", $actionEvent); + + if ($actionEvent->hasErrorForm()) { + $this->getParserContext()->setErrorForm($actionEvent->getErrorForm()); + } + + return $actionEvent; + } + + /** + * Return the event dispatcher, + * + * @return EventDispatcherInterface + */ + protected function getDispatcher() + { + return $this->container->get('event_dispatcher'); + } + /** * Return the parser context, * * @return ParserContext */ - protected function getParserContext($context = false) + protected function getParserContext() { return $this->container->get('thelia.parser.context'); } @@ -150,17 +197,6 @@ 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 * diff --git a/core/lib/Thelia/Admin/Controller/CategoryController.php b/core/lib/Thelia/Admin/Controller/CategoryController.php index 6f64d2a1d..2ce94c954 100644 --- a/core/lib/Thelia/Admin/Controller/CategoryController.php +++ b/core/lib/Thelia/Admin/Controller/CategoryController.php @@ -23,6 +23,8 @@ namespace Thelia\Admin\Controller; +use Thelia\Model\CategoryQuery; +use Thelia\Core\Security\Exception\AuthenticationException; class CategoryController extends BaseAdminController { public function indexAction() @@ -33,31 +35,83 @@ class CategoryController extends BaseAdminController { 'current_category_id' => 0 ); + return $this->browseCategory($args); + } + + public function createNewCategory($args) { + + $this->checkAuth("ADMIN", "admin.category.create"); + + $this->dispatchEvent("createCategory"); + + // At this point, the form has error, and should be redisplayed. return $this->render('categories', $args); } - public function processAction($action) + public function editCategory($args) { + + $this->checkAuth("AMIN", "admin.category.edit"); + + return $this->render('edit_category', $args); + } + + public function deleteCategory($category_id) { + + $this->checkAuth("AMIN", "admin.category.delete"); + + $category = CategoryQuery::create()->findPk($category_id); + + $this->dispatchEvent("deleteCategory"); + + // Something was wrong, category was not deleted. Display parent category list + return $this->render( + 'categories', + array('current_category_id' => $category->getParent()) + ); + } + + public function browseCategory($args) { + + $this->checkAuth("AMIN", "admin.catalog.view"); + + return $this->render('categories', $args); + } + + public function processAction() { - list($action, $id) = explode('/', $action); + // Get the current action + $action = $this->getRequest()->get('action', 'browse'); + + // Get the category ID + $id = $this->getRequest()->get('id', 0); $args = array( 'action' => $action, 'current_category_id' => $id ); - // Browe categories - if ($action == 'browse') { - return $this->render('categories', $args); + try { + // Browse categories + if ($action == 'browse') { + return $this->browseCategory($args); + } + // Create a new category + else if ($action == 'create') { + return $this->createNewCategory($args); + } + // Edit an existing category + else if ($action == 'edit') { + return $this->editCategory($args); + } + // Delete an existing category + else if ($action == 'delete') { + return $this->deleteCategory($id); + } } - // Create a new category - else if ($action = 'create') { - return $this->render('edit_category', $args); + catch(AuthenticationException $ex) { + return $this->render('general_error', array( + "error_message" => $ex->getMessage()) + ); } - // Edit an existing category - else if ($action = 'edit') { - return $this->render('edit_category', $args); - } - - //return $this->render("categories"); } } \ No newline at end of file diff --git a/core/lib/Thelia/Admin/Controller/SessionController.php b/core/lib/Thelia/Admin/Controller/SessionController.php index 7d1b6365d..75d102bdb 100755 --- a/core/lib/Thelia/Admin/Controller/SessionController.php +++ b/core/lib/Thelia/Admin/Controller/SessionController.php @@ -65,7 +65,7 @@ class SessionController extends BaseAdminController { $this->getSecurityContext()->setUser($user); // Log authentication success - AdminLog::append("Authentication successuful", $request, $user); + AdminLog::append("Authentication successful", $request, $user); $this->dispatch(TheliaEvents::ADMIN_LOGIN); diff --git a/core/lib/Thelia/Config/Resources/action.xml b/core/lib/Thelia/Config/Resources/action.xml index 0816f9958..975baab47 100755 --- a/core/lib/Thelia/Config/Resources/action.xml +++ b/core/lib/Thelia/Config/Resources/action.xml @@ -22,6 +22,10 @@ + + + + \ No newline at end of file diff --git a/core/lib/Thelia/Config/Resources/config.xml b/core/lib/Thelia/Config/Resources/config.xml index c4b517c38..19c263cda 100755 --- a/core/lib/Thelia/Config/Resources/config.xml +++ b/core/lib/Thelia/Config/Resources/config.xml @@ -22,13 +22,21 @@ + + +
+ + + + + @@ -84,7 +92,7 @@ - true + false %kernel.environment% %kernel.debug% diff --git a/core/lib/Thelia/Config/Resources/routing/admin.xml b/core/lib/Thelia/Config/Resources/routing/admin.xml index 4f053b76e..adfff289b 100755 --- a/core/lib/Thelia/Config/Resources/routing/admin.xml +++ b/core/lib/Thelia/Config/Resources/routing/admin.xml @@ -31,9 +31,8 @@ Thelia\Admin\Controller\CategoryController::indexAction - + Thelia\Admin\Controller\CategoryController::processAction - .* diff --git a/core/lib/Thelia/Core/Event/ActionEvent.php b/core/lib/Thelia/Core/Event/ActionEvent.php index 3dbbb106e..f2a618e8a 100755 --- a/core/lib/Thelia/Core/Event/ActionEvent.php +++ b/core/lib/Thelia/Core/Event/ActionEvent.php @@ -59,7 +59,7 @@ abstract class ActionEvent extends Event public function __construct(Request $request, $action) { $this->request = $request; - $this->action = $action; + $this->action = $action; } /** diff --git a/core/lib/Thelia/Core/Event/CategoryEvent.php b/core/lib/Thelia/Core/Event/CategoryEvent.php new file mode 100644 index 000000000..6542197e5 --- /dev/null +++ b/core/lib/Thelia/Core/Event/CategoryEvent.php @@ -0,0 +1,37 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Core\Event; + + +use Thelia\Model\Category; + +class CategoryEvent extends InternalEvent { + + public $category; + + public function __construct(Category $category) + { + $this->category = $category; + } +} \ No newline at end of file diff --git a/core/lib/Thelia/Core/Event/TheliaEvents.php b/core/lib/Thelia/Core/Event/TheliaEvents.php index c086f4fa9..138f7cb97 100755 --- a/core/lib/Thelia/Core/Event/TheliaEvents.php +++ b/core/lib/Thelia/Core/Event/TheliaEvents.php @@ -88,4 +88,25 @@ final class TheliaEvents * Sent before customer insertion, to allow modules to create a custom customer reference. */ const CREATECUSTOMER_CUSTOMREF = "customer.creation.customref"; + + + /** + * Sent once the category creation form has been successfully validated, and before category insertion in the database. + */ + const BEFORE_CREATECATEGORY = "action.before_createcategory"; + + /** + * Sent just after a successful insert of a new category in the database. + */ + const AFTER_CREATECATEGORY = "action.after_createcategory"; + /** + * Sent befonre deleting a category + */ + const BEFORE_DELETECATEGORY = "action.before_deletecategory"; + + /** + * Sent just after a successful delete of a category from the database. + */ + const AFTER_DELETECATEGORY = "action.after_deletecategory"; + } \ No newline at end of file diff --git a/core/lib/Thelia/Core/Factory/ActionEventFactory.php b/core/lib/Thelia/Core/Factory/ActionEventFactory.php index af41edecd..9ef0644ff 100755 --- a/core/lib/Thelia/Core/Factory/ActionEventFactory.php +++ b/core/lib/Thelia/Core/Factory/ActionEventFactory.php @@ -60,7 +60,6 @@ class ActionEventFactory { if (array_key_exists($this->action, $this->className)) { $class = new \ReflectionClass($this->className[$this->action]); - // return $class->newInstance($this->request, $this->action); } else { $class = new \ReflectionClass($this->defaultClassName); diff --git a/core/lib/Thelia/Core/HttpFoundation/Session/Session.php b/core/lib/Thelia/Core/HttpFoundation/Session/Session.php index cde686ee4..578d681e3 100755 --- a/core/lib/Thelia/Core/HttpFoundation/Session/Session.php +++ b/core/lib/Thelia/Core/HttpFoundation/Session/Session.php @@ -78,26 +78,6 @@ class Session extends BaseSession 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) diff --git a/core/lib/Thelia/Core/Security/Exception/AuthorizationException.php b/core/lib/Thelia/Core/Security/Exception/AuthorizationException.php new file mode 100644 index 000000000..60bd0a2d6 --- /dev/null +++ b/core/lib/Thelia/Core/Security/Exception/AuthorizationException.php @@ -0,0 +1,28 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Core\Security\Exception; + +class AuthorizationException extends \Exception +{ +} diff --git a/core/lib/Thelia/Core/Security/SecurityContext.php b/core/lib/Thelia/Core/Security/SecurityContext.php index b881282b9..9991006c1 100755 --- a/core/lib/Thelia/Core/Security/SecurityContext.php +++ b/core/lib/Thelia/Core/Security/SecurityContext.php @@ -107,7 +107,7 @@ class SecurityContext { * * @return Boolean */ - final public function isGranted($roles, $permissions) + final public function isGranted(array $roles, array $permissions) { if ($this->isAuthenticated() === true) { diff --git a/core/lib/Thelia/Core/Template/Element/BaseLoop.php b/core/lib/Thelia/Core/Template/Element/BaseLoop.php index 1f26e86fb..bff6ea54d 100755 --- a/core/lib/Thelia/Core/Template/Element/BaseLoop.php +++ b/core/lib/Thelia/Core/Template/Element/BaseLoop.php @@ -80,7 +80,7 @@ abstract class BaseLoop return array( Argument::createIntTypeArgument('offset', 0), Argument::createIntTypeArgument('page'), - Argument::createIntTypeArgument('limit', 10), + Argument::createIntTypeArgument('limit', PHP_INT_MAX), ); } diff --git a/core/lib/Thelia/Core/Template/Loop/Argument/Argument.php b/core/lib/Thelia/Core/Template/Loop/Argument/Argument.php index 265fdbdf2..f927a4222 100755 --- a/core/lib/Thelia/Core/Template/Loop/Argument/Argument.php +++ b/core/lib/Thelia/Core/Template/Loop/Argument/Argument.php @@ -111,6 +111,19 @@ class Argument ); } + public static function createBooleanOrBothTypeArgument($name, $default=null, $mandatory=false, $empty=true) + { + return new Argument( + $name, + new TypeCollection( + new Type\BooleanOrBothType() + ), + $default, + $mandatory, + $empty + ); + } + public static function createIntListTypeArgument($name, $default=null, $mandatory=false, $empty=true) { return new Argument( diff --git a/core/lib/Thelia/Core/Template/Loop/Category.php b/core/lib/Thelia/Core/Template/Loop/Category.php index b3492a7ab..ac74b2824 100755 --- a/core/lib/Thelia/Core/Template/Loop/Category.php +++ b/core/lib/Thelia/Core/Template/Loop/Category.php @@ -36,6 +36,7 @@ use Thelia\Model\CategoryQuery; use Thelia\Model\ConfigQuery; use Thelia\Type\TypeCollection; use Thelia\Type; +use Thelia\Type\BooleanOrBothType; /** * @@ -122,7 +123,7 @@ class Category extends BaseLoop $search->filterById($exclude, Criteria::NOT_IN); } - if ($this->getVisible() != '*') + if ($this->getVisible() != BooleanOrBothType::ANY) $search->filterByVisible($this->getVisible() ? 1 : 0); $orders = $this->getOrder(); diff --git a/core/lib/Thelia/Core/Template/Loop/CategoryPath.php b/core/lib/Thelia/Core/Template/Loop/CategoryPath.php index e1fa1fd30..bfcfa42ce 100644 --- a/core/lib/Thelia/Core/Template/Loop/CategoryPath.php +++ b/core/lib/Thelia/Core/Template/Loop/CategoryPath.php @@ -36,6 +36,7 @@ use Thelia\Model\CategoryQuery; use Thelia\Model\ConfigQuery; use Thelia\Type\TypeCollection; use Thelia\Type; +use Thelia\Type\BooleanOrBothType; /** * @@ -68,7 +69,7 @@ class CategoryPath extends BaseLoop Argument::createIntTypeArgument('category', null, true), Argument::createIntTypeArgument('depth'), Argument::createIntTypeArgument('level'), - Argument::createBooleanTypeArgument('visible', true, false) + Argument::createBooleanOrBothTypeArgument('visible', true, false) ); } @@ -84,10 +85,12 @@ class CategoryPath extends BaseLoop $search = CategoryQuery::create(); $search->filterById($id); - if ($visible == true) $search->filterByVisible($visible); + if ($visible != BooleanOrBothType::ANY) $search->filterByVisible($visible); $results = array(); + $ids = array(); + do { $category = $search->findOne(); @@ -106,6 +109,14 @@ class CategoryPath extends BaseLoop $parent = $category->getParent(); if ($parent > 0) { + + // Prevent circular refererences + if (in_array($parent, $ids)) { + throw new \LogicException(sprintf("Circular reference detected in category ID=%d hierarchy (category ID=%d appears more than one times in path)", $id, $parent)); + } + + $ids[] = $parent; + $search = CategoryQuery::create(); $search->filterById($parent); if ($visible == true) $search->filterByVisible($visible); diff --git a/core/lib/Thelia/Core/Template/Loop/CategoryTree.php b/core/lib/Thelia/Core/Template/Loop/CategoryTree.php new file mode 100644 index 000000000..f452d61bc --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/CategoryTree.php @@ -0,0 +1,123 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Core\Template\Loop; + +use Propel\Runtime\ActiveQuery\Criteria; +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\Log\Tlog; + +use Thelia\Model\CategoryQuery; +use Thelia\Model\ConfigQuery; +use Thelia\Type\TypeCollection; +use Thelia\Type; +use Thelia\Type\BooleanOrBothType; + +/** + * + * Category tree loop, to get a category tree from a given category to a given depth. + * + * - category is the category id + * - depth is the maximum depth to go, default unlimited + * - visible if true or missing, only visible categories will be displayed. If false, all categories (visible or not) are returned. + * + * @package Thelia\Core\Template\Loop + * @author Franck Allimant + */ +class CategoryTree extends BaseLoop +{ + /** + * @return ArgumentCollection + */ + protected function getArgDefinitions() + { + return new ArgumentCollection( + Argument::createIntTypeArgument('category', null, true), + Argument::createIntTypeArgument('depth', PHP_INT_MAX), + Argument::createBooleanOrBothTypeArgument('visible', true, false), + Argument::createIntListTypeArgument('exclude', array()) + ); + } + + // changement de rubrique + protected function buildCategoryTree($parent, $visible, $level, $max_level, array $exclude, LoopResult &$loopResult) { + + if ($level > $max_level) return; + + $search = CategoryQuery::create(); + + $search->filterByParent($parent); + + if ($visible != BooleanOrBothType::ANY) $search->filterByVisible($visible); + + $search->filterById($exclude, Criteria::NOT_IN); + + $search->orderByPosition(Criteria::ASC); + + $results = $search->find(); + + foreach($results as $result) { + + $loopResultRow = new LoopResultRow(); + + $loopResultRow + ->set("ID", $result->getId()) + ->set("TITLE",$result->getTitle()) + ->set("PARENT", $result->getParent()) + ->set("URL", $result->getUrl()) + ->set("VISIBLE", $result->getVisible() ? "1" : "0") + ->set("LEVEL", $level) + ; + + $loopResult->addRow($loopResultRow); + + $this->buildCategoryTree($result->getId(), $visible, 1 + $level, $max_level, $exclude, $loopResult); + } + } + + /** + * @param $pagination (ignored) + * + * @return \Thelia\Core\Template\Element\LoopResult + */ + public function exec(&$pagination) + { + $id = $this->getCategory(); + $depth = $this->getDepth(); + $visible = $this->getVisible(); + $exclude = $this->getExclude(); + + //echo "exclude=".print_r($exclude); + + $loopResult = new LoopResult(); + + $this->buildCategoryTree($id, $visible, 0, $depth, $exclude, $loopResult); + + return $loopResult; + } +} \ No newline at end of file diff --git a/core/lib/Thelia/Core/Template/Loop/Content.php b/core/lib/Thelia/Core/Template/Loop/Content.php index f0606755d..e58e98625 100755 --- a/core/lib/Thelia/Core/Template/Loop/Content.php +++ b/core/lib/Thelia/Core/Template/Loop/Content.php @@ -41,6 +41,7 @@ use Thelia\Model\ContentQuery; use Thelia\Model\ConfigQuery; use Thelia\Type\TypeCollection; use Thelia\Type; +use Thelia\Type\BooleanOrBothType; /** * @@ -64,7 +65,7 @@ class Content extends BaseLoop Argument::createBooleanTypeArgument('current'), Argument::createBooleanTypeArgument('current_folder'), Argument::createIntTypeArgument('depth', 1), - Argument::createBooleanTypeArgument('visible', 1), + Argument::createBooleanOrBothTypeArgument('visible', 1), new Argument( 'order', new TypeCollection( @@ -148,7 +149,7 @@ class Content extends BaseLoop $visible = $this->getVisible(); - $search->filterByVisible($visible); + if ($visible != BooleanOrBothType::ANY) $search->filterByVisible($visible); $orders = $this->getOrder(); diff --git a/core/lib/Thelia/Core/Template/Loop/Feature.php b/core/lib/Thelia/Core/Template/Loop/Feature.php index ab420def2..d35224384 100755 --- a/core/lib/Thelia/Core/Template/Loop/Feature.php +++ b/core/lib/Thelia/Core/Template/Loop/Feature.php @@ -40,6 +40,7 @@ use Thelia\Model\ConfigQuery; use Thelia\Model\Map\ProductCategoryTableMap; use Thelia\Type\TypeCollection; use Thelia\Type; +use Thelia\Type\BooleanOrBothType; /** * @@ -61,7 +62,7 @@ class Feature extends BaseLoop Argument::createIntListTypeArgument('id'), Argument::createIntListTypeArgument('product'), Argument::createIntListTypeArgument('category'), - Argument::createBooleanTypeArgument('visible', 1), + Argument::createBooleanOrBothTypeArgument('visible', 1), Argument::createIntListTypeArgument('exclude'), new Argument( 'order', @@ -96,7 +97,7 @@ class Feature extends BaseLoop $visible = $this->getVisible(); - $search->filterByVisible($visible); + if ($visible != BooleanOrBothType::ANY) $search->filterByVisible($visible); $product = $this->getProduct(); $category = $this->getCategory(); diff --git a/core/lib/Thelia/Core/Template/Loop/Folder.php b/core/lib/Thelia/Core/Template/Loop/Folder.php index b6b5768fd..13d0409a6 100755 --- a/core/lib/Thelia/Core/Template/Loop/Folder.php +++ b/core/lib/Thelia/Core/Template/Loop/Folder.php @@ -36,6 +36,7 @@ use Thelia\Model\FolderQuery; use Thelia\Model\ConfigQuery; use Thelia\Type\TypeCollection; use Thelia\Type; +use Thelia\Type\BooleanOrBothType; /** * Class Folder @@ -55,7 +56,7 @@ class Folder extends BaseLoop Argument::createIntTypeArgument('parent'), Argument::createBooleanTypeArgument('current'), Argument::createBooleanTypeArgument('not_empty', 0), - Argument::createBooleanTypeArgument('visible', 1), + Argument::createBooleanOrBothTypeArgument('visible', 1), new Argument( 'order', new TypeCollection( @@ -104,7 +105,9 @@ class Folder extends BaseLoop $search->filterById($exclude, Criteria::NOT_IN); } - $search->filterByVisible($this->getVisible() ? 1 : 0); + $visible = $this->getVisible(); + + if ($visible != BooleanOrBothType::ANY) $search->filterByVisible($visible ? 1 : 0); $orders = $this->getOrder(); diff --git a/core/lib/Thelia/Core/Template/Loop/Lang.php b/core/lib/Thelia/Core/Template/Loop/Lang.php new file mode 100644 index 000000000..2e7d2ce16 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/Lang.php @@ -0,0 +1,114 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Core\Template\Loop; + +use Propel\Runtime\ActiveQuery\Criteria; +use Thelia\Core\Template\Element\BaseLoop; +use Thelia\Core\Template\Element\LoopResult; +use Thelia\Core\Template\Element\LoopResultRow; + +use Thelia\Core\Template\Loop\Argument\Argument; + +use Thelia\Type\TypeCollection; +use Thelia\Type; +use Thelia\Model\LangQuery; +use Thelia\Core\Template\Loop\Argument\ArgumentCollection; + +/** + * Language loop, to get a list of available languages + * + * - id is the language id + * - exclude is a comma separated list of lang IDs that will be excluded from output + * - default if 1, the loop return only default lang. If 0, return all but the default language + * + * @package Thelia\Core\Template\Loop + * @author Franck Allimant + */ +class Lang extends BaseLoop +{ + /** + * @return ArgumentCollection + */ + protected function getArgDefinitions() + { + return new ArgumentCollection( + Argument::createIntTypeArgument('id', null), + Argument::createIntListTypeArgument('exclude'), + Argument::createBooleanTypeArgument('default_only', false) + ); + } + + /** + * @param $pagination (ignored) + * + * @return \Thelia\Core\Template\Element\LoopResult + */ + public function exec(&$pagination) + { + $id = $this->getId(); + $exclude = $this->getExclude(); + $default_only = $this->getDefaultOnly(); + + $search = LangQuery::create(); + + if (! is_null($id)) + $search->filterById($id); + + if ($default_only) + $search->filterByByDefault(true); + + if (! is_null($exclude)) { + $search->filterById($exclude, Criteria::NOT_IN); + } + + $search->orderByPosition(Criteria::ASC); + + $results = $this->search($search, $pagination); + + $loopResult = new LoopResult(); + + foreach ($results as $result) { + + $loopResultRow = new LoopResultRow(); + + $loopResultRow + ->set("ID", $result->getId()) + ->set("TITLE",$result->getTitle()) + ->set("CODE", $result->getCode()) + ->set("LOCALE", $result->getLocale()) + ->set("URL", $result->getUrl()) + ->set("IS_DEFAULT", $result->getByDefault()) + ->set("URL", $result->getUrl()) + ->set("POSITION", $result->getPosition()) + + ->set("CREATE_DATE", $result->getCreatedAt()) + ->set("UPDATE_DATE", $result->getUpdatedAt()) + ; + + $loopResult->addRow($loopResultRow); + } + + return $loopResult; + } +} \ No newline at end of file diff --git a/core/lib/Thelia/Core/Template/Loop/Product.php b/core/lib/Thelia/Core/Template/Loop/Product.php index d50bfc495..8d892a446 100755 --- a/core/lib/Thelia/Core/Template/Loop/Product.php +++ b/core/lib/Thelia/Core/Template/Loop/Product.php @@ -44,6 +44,7 @@ use Thelia\Model\ProductQuery; use Thelia\Model\ConfigQuery; use Thelia\Type\TypeCollection; use Thelia\Type; +use Thelia\Type\BooleanOrBothType; /** * @@ -80,7 +81,7 @@ class Product extends BaseLoop Argument::createBooleanTypeArgument('current'), Argument::createBooleanTypeArgument('current_category'), Argument::createIntTypeArgument('depth', 1), - Argument::createBooleanTypeArgument('visible', 1), + Argument::createBooleanOrBothTypeArgument('visible', 1), new Argument( 'order', new TypeCollection( @@ -252,11 +253,10 @@ class Product extends BaseLoop $visible = $this->getVisible(); - $search->filterByVisible($visible); + if ($visible != BooleanOrBothType::ANY) $search->filterByVisible($visible ? 1 : 0); $orders = $this->getOrder(); - foreach($orders as $order) { switch ($order) { case "alpha": diff --git a/core/lib/Thelia/Core/Template/Smarty/Plugins/Assetic.php b/core/lib/Thelia/Core/Template/Smarty/Plugins/Assetic.php index 7fca50151..954bb58da 100755 --- a/core/lib/Thelia/Core/Template/Smarty/Plugins/Assetic.php +++ b/core/lib/Thelia/Core/Template/Smarty/Plugins/Assetic.php @@ -26,6 +26,7 @@ namespace Thelia\Core\Template\Smarty\Plugins; use Thelia\Core\Template\Smarty\SmartyPluginDescriptor; use Thelia\Core\Template\Smarty\AbstractSmartyPlugin; use Thelia\Core\Template\Smarty\Assets\SmartyAssetsManager; +use Thelia\Model\ConfigQuery; class Assetic extends AbstractSmartyPlugin { @@ -35,7 +36,7 @@ class Assetic extends AbstractSmartyPlugin { $web_root = THELIA_WEB_DIR; - $asset_dir_from_web_root = 'assets/admin/default'; // FIXME + $asset_dir_from_web_root = ConfigQuery::read('asset_dir_from_web_root', 'assets'); $this->assetManager = new SmartyAssetsManager($web_root, $asset_dir_from_web_root); } diff --git a/core/lib/Thelia/Core/Template/Smarty/Plugins/Form.php b/core/lib/Thelia/Core/Template/Smarty/Plugins/Form.php index afb164604..24d58a7da 100755 --- a/core/lib/Thelia/Core/Template/Smarty/Plugins/Form.php +++ b/core/lib/Thelia/Core/Template/Smarty/Plugins/Form.php @@ -101,7 +101,8 @@ class Form extends AbstractSmartyPlugin // Re-use the errored form $instance = $errorForm; - $this->parserContext->clearErrorForm(); + // Don't do that, as we may want to use this form firther in the template code + //$this->parserContext->clearErrorForm(); } $instance->createView(); diff --git a/core/lib/Thelia/Core/Template/Smarty/Plugins/UrlGenerator.php b/core/lib/Thelia/Core/Template/Smarty/Plugins/UrlGenerator.php index 8bc0ad991..835f02d31 100644 --- a/core/lib/Thelia/Core/Template/Smarty/Plugins/UrlGenerator.php +++ b/core/lib/Thelia/Core/Template/Smarty/Plugins/UrlGenerator.php @@ -49,7 +49,7 @@ class UrlGenerator extends AbstractSmartyPlugin // the path to process $path = $this->getParam($params, 'path'); - return URL::absoluteUrl($path, $this->getArgsFromParam($params)); + return URL::absoluteUrl($path, $this->getArgsFromParam($params, array('path'))); } /** @@ -84,7 +84,7 @@ class UrlGenerator extends AbstractSmartyPlugin // the related action (optionale) $action = $this->getParam($params, 'action'); - $args = $this->getArgsFromParam($params); + $args = $this->getArgsFromParam($params, array('view', 'action')); if (! empty($action)) $args['action'] = $action; @@ -92,17 +92,23 @@ class UrlGenerator extends AbstractSmartyPlugin } /** - * Get URL parameters array from a comma separated list or arguments in the - * parameters. + * Get URL parameters array from parameters. * * @param array $params Smarty function params * @return array the parameters array (either emply, of valued) */ - private function getArgsFromParam($params) { + private function getArgsFromParam($params, $exclude = array()) { - $args = $this->getParam($params, array('arguments', 'args')); + $pairs = array(); - return $args !== null ? explode($args, ',') : array(); + foreach($params as $name => $value) { + + if (in_array($name, $exclude)) continue; + + $pairs[$name] = $value; + } + + return $pairs; } /** diff --git a/core/lib/Thelia/Form/CategoryCreationForm.php b/core/lib/Thelia/Form/CategoryCreationForm.php new file mode 100644 index 000000000..11d2851d7 --- /dev/null +++ b/core/lib/Thelia/Form/CategoryCreationForm.php @@ -0,0 +1,55 @@ +. */ +/* */ +/*************************************************************************************/ +namespace Thelia\Form; + +use Symfony\Component\Form\FormBuilderInterface; +use Symfony\Component\Validator\Constraints\NotBlank; + +class CategoryCreationForm extends BaseForm { + + protected function buildForm() + { + $this->formBuilder + ->add("title", "text", array( + "constraints" => array( + new NotBlank() + ) + )) + ->add("parent", "integer", array( + "constraints" => array( + new NotBlank() + ) + )) + ->add("locale", "text", array( + "constraints" => array( + new NotBlank() + ) + )) + ; + } + + public function getName() + { + return "thelia_category_creation"; + } +} diff --git a/core/lib/Thelia/Form/CategoryDeletionForm.php b/core/lib/Thelia/Form/CategoryDeletionForm.php new file mode 100644 index 000000000..06d5c6969 --- /dev/null +++ b/core/lib/Thelia/Form/CategoryDeletionForm.php @@ -0,0 +1,45 @@ +. */ +/* */ +/*************************************************************************************/ +namespace Thelia\Form; + +use Symfony\Component\Form\FormBuilderInterface; +use Symfony\Component\Validator\Constraints\NotBlank; + +class CategoryDeletionForm extends BaseForm { + + protected function buildForm() + { + $this->formBuilder + ->add("id", "integer", array( + "constraints" => array( + new NotBlank() + ) + )) + ; + } + + public function getName() + { + return "thelia_category_deletion"; + } +} \ No newline at end of file diff --git a/core/lib/Thelia/Model/Base/Currency.php b/core/lib/Thelia/Model/Base/Currency.php index 5ab40a742..bbb83bb92 100644 --- a/core/lib/Thelia/Model/Base/Currency.php +++ b/core/lib/Thelia/Model/Base/Currency.php @@ -93,6 +93,12 @@ abstract class Currency implements ActiveRecordInterface */ protected $by_default; + /** + * The value for the position field. + * @var int + */ + protected $position; + /** * The value for the created_at field. * @var string @@ -484,6 +490,17 @@ abstract class Currency implements ActiveRecordInterface return $this->by_default; } + /** + * Get the [position] column value. + * + * @return int + */ + public function getPosition() + { + + return $this->position; + } + /** * Get the [optionally formatted] temporal [created_at] column value. * @@ -629,6 +646,27 @@ abstract class Currency implements ActiveRecordInterface return $this; } // setByDefault() + /** + * Set the value of [position] column. + * + * @param int $v new value + * @return \Thelia\Model\Currency The current object (for fluent API support) + */ + public function setPosition($v) + { + if ($v !== null) { + $v = (int) $v; + } + + if ($this->position !== $v) { + $this->position = $v; + $this->modifiedColumns[] = CurrencyTableMap::POSITION; + } + + + return $this; + } // setPosition() + /** * Sets the value of [created_at] column to a normalized version of the date/time value specified. * @@ -723,13 +761,16 @@ abstract class Currency implements ActiveRecordInterface $col = $row[TableMap::TYPE_NUM == $indexType ? 4 + $startcol : CurrencyTableMap::translateFieldName('ByDefault', TableMap::TYPE_PHPNAME, $indexType)]; $this->by_default = (null !== $col) ? (int) $col : null; - $col = $row[TableMap::TYPE_NUM == $indexType ? 5 + $startcol : CurrencyTableMap::translateFieldName('CreatedAt', TableMap::TYPE_PHPNAME, $indexType)]; + $col = $row[TableMap::TYPE_NUM == $indexType ? 5 + $startcol : CurrencyTableMap::translateFieldName('Position', TableMap::TYPE_PHPNAME, $indexType)]; + $this->position = (null !== $col) ? (int) $col : null; + + $col = $row[TableMap::TYPE_NUM == $indexType ? 6 + $startcol : CurrencyTableMap::translateFieldName('CreatedAt', TableMap::TYPE_PHPNAME, $indexType)]; if ($col === '0000-00-00 00:00:00') { $col = null; } $this->created_at = (null !== $col) ? PropelDateTime::newInstance($col, null, '\DateTime') : null; - $col = $row[TableMap::TYPE_NUM == $indexType ? 6 + $startcol : CurrencyTableMap::translateFieldName('UpdatedAt', TableMap::TYPE_PHPNAME, $indexType)]; + $col = $row[TableMap::TYPE_NUM == $indexType ? 7 + $startcol : CurrencyTableMap::translateFieldName('UpdatedAt', TableMap::TYPE_PHPNAME, $indexType)]; if ($col === '0000-00-00 00:00:00') { $col = null; } @@ -742,7 +783,7 @@ abstract class Currency implements ActiveRecordInterface $this->ensureConsistency(); } - return $startcol + 7; // 7 = CurrencyTableMap::NUM_HYDRATE_COLUMNS. + return $startcol + 8; // 8 = CurrencyTableMap::NUM_HYDRATE_COLUMNS. } catch (Exception $e) { throw new PropelException("Error populating \Thelia\Model\Currency object", 0, $e); @@ -1055,6 +1096,9 @@ abstract class Currency implements ActiveRecordInterface if ($this->isColumnModified(CurrencyTableMap::BY_DEFAULT)) { $modifiedColumns[':p' . $index++] = 'BY_DEFAULT'; } + if ($this->isColumnModified(CurrencyTableMap::POSITION)) { + $modifiedColumns[':p' . $index++] = 'POSITION'; + } if ($this->isColumnModified(CurrencyTableMap::CREATED_AT)) { $modifiedColumns[':p' . $index++] = 'CREATED_AT'; } @@ -1087,6 +1131,9 @@ abstract class Currency implements ActiveRecordInterface case 'BY_DEFAULT': $stmt->bindValue($identifier, $this->by_default, PDO::PARAM_INT); break; + case 'POSITION': + $stmt->bindValue($identifier, $this->position, PDO::PARAM_INT); + break; case 'CREATED_AT': $stmt->bindValue($identifier, $this->created_at ? $this->created_at->format("Y-m-d H:i:s") : null, PDO::PARAM_STR); break; @@ -1171,9 +1218,12 @@ abstract class Currency implements ActiveRecordInterface return $this->getByDefault(); break; case 5: - return $this->getCreatedAt(); + return $this->getPosition(); break; case 6: + return $this->getCreatedAt(); + break; + case 7: return $this->getUpdatedAt(); break; default: @@ -1210,8 +1260,9 @@ abstract class Currency implements ActiveRecordInterface $keys[2] => $this->getSymbol(), $keys[3] => $this->getRate(), $keys[4] => $this->getByDefault(), - $keys[5] => $this->getCreatedAt(), - $keys[6] => $this->getUpdatedAt(), + $keys[5] => $this->getPosition(), + $keys[6] => $this->getCreatedAt(), + $keys[7] => $this->getUpdatedAt(), ); $virtualColumns = $this->virtualColumns; foreach($virtualColumns as $key => $virtualColumn) @@ -1282,9 +1333,12 @@ abstract class Currency implements ActiveRecordInterface $this->setByDefault($value); break; case 5: - $this->setCreatedAt($value); + $this->setPosition($value); break; case 6: + $this->setCreatedAt($value); + break; + case 7: $this->setUpdatedAt($value); break; } // switch() @@ -1316,8 +1370,9 @@ abstract class Currency implements ActiveRecordInterface if (array_key_exists($keys[2], $arr)) $this->setSymbol($arr[$keys[2]]); if (array_key_exists($keys[3], $arr)) $this->setRate($arr[$keys[3]]); if (array_key_exists($keys[4], $arr)) $this->setByDefault($arr[$keys[4]]); - if (array_key_exists($keys[5], $arr)) $this->setCreatedAt($arr[$keys[5]]); - if (array_key_exists($keys[6], $arr)) $this->setUpdatedAt($arr[$keys[6]]); + if (array_key_exists($keys[5], $arr)) $this->setPosition($arr[$keys[5]]); + if (array_key_exists($keys[6], $arr)) $this->setCreatedAt($arr[$keys[6]]); + if (array_key_exists($keys[7], $arr)) $this->setUpdatedAt($arr[$keys[7]]); } /** @@ -1334,6 +1389,7 @@ abstract class Currency implements ActiveRecordInterface if ($this->isColumnModified(CurrencyTableMap::SYMBOL)) $criteria->add(CurrencyTableMap::SYMBOL, $this->symbol); if ($this->isColumnModified(CurrencyTableMap::RATE)) $criteria->add(CurrencyTableMap::RATE, $this->rate); if ($this->isColumnModified(CurrencyTableMap::BY_DEFAULT)) $criteria->add(CurrencyTableMap::BY_DEFAULT, $this->by_default); + if ($this->isColumnModified(CurrencyTableMap::POSITION)) $criteria->add(CurrencyTableMap::POSITION, $this->position); if ($this->isColumnModified(CurrencyTableMap::CREATED_AT)) $criteria->add(CurrencyTableMap::CREATED_AT, $this->created_at); if ($this->isColumnModified(CurrencyTableMap::UPDATED_AT)) $criteria->add(CurrencyTableMap::UPDATED_AT, $this->updated_at); @@ -1403,6 +1459,7 @@ abstract class Currency implements ActiveRecordInterface $copyObj->setSymbol($this->getSymbol()); $copyObj->setRate($this->getRate()); $copyObj->setByDefault($this->getByDefault()); + $copyObj->setPosition($this->getPosition()); $copyObj->setCreatedAt($this->getCreatedAt()); $copyObj->setUpdatedAt($this->getUpdatedAt()); @@ -2579,6 +2636,7 @@ abstract class Currency implements ActiveRecordInterface $this->symbol = null; $this->rate = null; $this->by_default = null; + $this->position = null; $this->created_at = null; $this->updated_at = null; $this->alreadyInSave = false; diff --git a/core/lib/Thelia/Model/Base/CurrencyQuery.php b/core/lib/Thelia/Model/Base/CurrencyQuery.php index 140b70463..7aba3317e 100644 --- a/core/lib/Thelia/Model/Base/CurrencyQuery.php +++ b/core/lib/Thelia/Model/Base/CurrencyQuery.php @@ -27,6 +27,7 @@ use Thelia\Model\Map\CurrencyTableMap; * @method ChildCurrencyQuery orderBySymbol($order = Criteria::ASC) Order by the symbol column * @method ChildCurrencyQuery orderByRate($order = Criteria::ASC) Order by the rate column * @method ChildCurrencyQuery orderByByDefault($order = Criteria::ASC) Order by the by_default column + * @method ChildCurrencyQuery orderByPosition($order = Criteria::ASC) Order by the position column * @method ChildCurrencyQuery orderByCreatedAt($order = Criteria::ASC) Order by the created_at column * @method ChildCurrencyQuery orderByUpdatedAt($order = Criteria::ASC) Order by the updated_at column * @@ -35,6 +36,7 @@ use Thelia\Model\Map\CurrencyTableMap; * @method ChildCurrencyQuery groupBySymbol() Group by the symbol column * @method ChildCurrencyQuery groupByRate() Group by the rate column * @method ChildCurrencyQuery groupByByDefault() Group by the by_default column + * @method ChildCurrencyQuery groupByPosition() Group by the position column * @method ChildCurrencyQuery groupByCreatedAt() Group by the created_at column * @method ChildCurrencyQuery groupByUpdatedAt() Group by the updated_at column * @@ -66,6 +68,7 @@ use Thelia\Model\Map\CurrencyTableMap; * @method ChildCurrency findOneBySymbol(string $symbol) Return the first ChildCurrency filtered by the symbol column * @method ChildCurrency findOneByRate(double $rate) Return the first ChildCurrency filtered by the rate column * @method ChildCurrency findOneByByDefault(int $by_default) Return the first ChildCurrency filtered by the by_default column + * @method ChildCurrency findOneByPosition(int $position) Return the first ChildCurrency filtered by the position column * @method ChildCurrency findOneByCreatedAt(string $created_at) Return the first ChildCurrency filtered by the created_at column * @method ChildCurrency findOneByUpdatedAt(string $updated_at) Return the first ChildCurrency filtered by the updated_at column * @@ -74,6 +77,7 @@ use Thelia\Model\Map\CurrencyTableMap; * @method array findBySymbol(string $symbol) Return ChildCurrency objects filtered by the symbol column * @method array findByRate(double $rate) Return ChildCurrency objects filtered by the rate column * @method array findByByDefault(int $by_default) Return ChildCurrency objects filtered by the by_default column + * @method array findByPosition(int $position) Return ChildCurrency objects filtered by the position column * @method array findByCreatedAt(string $created_at) Return ChildCurrency objects filtered by the created_at column * @method array findByUpdatedAt(string $updated_at) Return ChildCurrency objects filtered by the updated_at column * @@ -164,7 +168,7 @@ abstract class CurrencyQuery extends ModelCriteria */ protected function findPkSimple($key, $con) { - $sql = 'SELECT ID, CODE, SYMBOL, RATE, BY_DEFAULT, CREATED_AT, UPDATED_AT FROM currency WHERE ID = :p0'; + $sql = 'SELECT ID, CODE, SYMBOL, RATE, BY_DEFAULT, POSITION, CREATED_AT, UPDATED_AT FROM currency WHERE ID = :p0'; try { $stmt = $con->prepare($sql); $stmt->bindValue(':p0', $key, PDO::PARAM_INT); @@ -434,6 +438,47 @@ abstract class CurrencyQuery extends ModelCriteria return $this->addUsingAlias(CurrencyTableMap::BY_DEFAULT, $byDefault, $comparison); } + /** + * Filter the query on the position column + * + * Example usage: + * + * $query->filterByPosition(1234); // WHERE position = 1234 + * $query->filterByPosition(array(12, 34)); // WHERE position IN (12, 34) + * $query->filterByPosition(array('min' => 12)); // WHERE position > 12 + * + * + * @param mixed $position The value to use as filter. + * Use scalar values for equality. + * Use array values for in_array() equivalent. + * Use associative array('min' => $minValue, 'max' => $maxValue) for intervals. + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildCurrencyQuery The current query, for fluid interface + */ + public function filterByPosition($position = null, $comparison = null) + { + if (is_array($position)) { + $useMinMax = false; + if (isset($position['min'])) { + $this->addUsingAlias(CurrencyTableMap::POSITION, $position['min'], Criteria::GREATER_EQUAL); + $useMinMax = true; + } + if (isset($position['max'])) { + $this->addUsingAlias(CurrencyTableMap::POSITION, $position['max'], Criteria::LESS_EQUAL); + $useMinMax = true; + } + if ($useMinMax) { + return $this; + } + if (null === $comparison) { + $comparison = Criteria::IN; + } + } + + return $this->addUsingAlias(CurrencyTableMap::POSITION, $position, $comparison); + } + /** * Filter the query on the created_at column * diff --git a/core/lib/Thelia/Model/Base/Lang.php b/core/lib/Thelia/Model/Base/Lang.php index 694f86bc5..63a3c1b8d 100644 --- a/core/lib/Thelia/Model/Base/Lang.php +++ b/core/lib/Thelia/Model/Base/Lang.php @@ -90,6 +90,12 @@ abstract class Lang implements ActiveRecordInterface */ protected $by_default; + /** + * The value for the position field. + * @var int + */ + protected $position; + /** * The value for the created_at field. * @var string @@ -430,6 +436,17 @@ abstract class Lang implements ActiveRecordInterface return $this->by_default; } + /** + * Get the [position] column value. + * + * @return int + */ + public function getPosition() + { + + return $this->position; + } + /** * Get the [optionally formatted] temporal [created_at] column value. * @@ -596,6 +613,27 @@ abstract class Lang implements ActiveRecordInterface return $this; } // setByDefault() + /** + * Set the value of [position] column. + * + * @param int $v new value + * @return \Thelia\Model\Lang The current object (for fluent API support) + */ + public function setPosition($v) + { + if ($v !== null) { + $v = (int) $v; + } + + if ($this->position !== $v) { + $this->position = $v; + $this->modifiedColumns[] = LangTableMap::POSITION; + } + + + return $this; + } // setPosition() + /** * Sets the value of [created_at] column to a normalized version of the date/time value specified. * @@ -693,13 +731,16 @@ abstract class Lang implements ActiveRecordInterface $col = $row[TableMap::TYPE_NUM == $indexType ? 5 + $startcol : LangTableMap::translateFieldName('ByDefault', TableMap::TYPE_PHPNAME, $indexType)]; $this->by_default = (null !== $col) ? (int) $col : null; - $col = $row[TableMap::TYPE_NUM == $indexType ? 6 + $startcol : LangTableMap::translateFieldName('CreatedAt', TableMap::TYPE_PHPNAME, $indexType)]; + $col = $row[TableMap::TYPE_NUM == $indexType ? 6 + $startcol : LangTableMap::translateFieldName('Position', TableMap::TYPE_PHPNAME, $indexType)]; + $this->position = (null !== $col) ? (int) $col : null; + + $col = $row[TableMap::TYPE_NUM == $indexType ? 7 + $startcol : LangTableMap::translateFieldName('CreatedAt', TableMap::TYPE_PHPNAME, $indexType)]; if ($col === '0000-00-00 00:00:00') { $col = null; } $this->created_at = (null !== $col) ? PropelDateTime::newInstance($col, null, '\DateTime') : null; - $col = $row[TableMap::TYPE_NUM == $indexType ? 7 + $startcol : LangTableMap::translateFieldName('UpdatedAt', TableMap::TYPE_PHPNAME, $indexType)]; + $col = $row[TableMap::TYPE_NUM == $indexType ? 8 + $startcol : LangTableMap::translateFieldName('UpdatedAt', TableMap::TYPE_PHPNAME, $indexType)]; if ($col === '0000-00-00 00:00:00') { $col = null; } @@ -712,7 +753,7 @@ abstract class Lang implements ActiveRecordInterface $this->ensureConsistency(); } - return $startcol + 8; // 8 = LangTableMap::NUM_HYDRATE_COLUMNS. + return $startcol + 9; // 9 = LangTableMap::NUM_HYDRATE_COLUMNS. } catch (Exception $e) { throw new PropelException("Error populating \Thelia\Model\Lang object", 0, $e); @@ -950,6 +991,9 @@ abstract class Lang implements ActiveRecordInterface if ($this->isColumnModified(LangTableMap::BY_DEFAULT)) { $modifiedColumns[':p' . $index++] = 'BY_DEFAULT'; } + if ($this->isColumnModified(LangTableMap::POSITION)) { + $modifiedColumns[':p' . $index++] = 'POSITION'; + } if ($this->isColumnModified(LangTableMap::CREATED_AT)) { $modifiedColumns[':p' . $index++] = 'CREATED_AT'; } @@ -985,6 +1029,9 @@ abstract class Lang implements ActiveRecordInterface case 'BY_DEFAULT': $stmt->bindValue($identifier, $this->by_default, PDO::PARAM_INT); break; + case 'POSITION': + $stmt->bindValue($identifier, $this->position, PDO::PARAM_INT); + break; case 'CREATED_AT': $stmt->bindValue($identifier, $this->created_at ? $this->created_at->format("Y-m-d H:i:s") : null, PDO::PARAM_STR); break; @@ -1072,9 +1119,12 @@ abstract class Lang implements ActiveRecordInterface return $this->getByDefault(); break; case 6: - return $this->getCreatedAt(); + return $this->getPosition(); break; case 7: + return $this->getCreatedAt(); + break; + case 8: return $this->getUpdatedAt(); break; default: @@ -1111,8 +1161,9 @@ abstract class Lang implements ActiveRecordInterface $keys[3] => $this->getLocale(), $keys[4] => $this->getUrl(), $keys[5] => $this->getByDefault(), - $keys[6] => $this->getCreatedAt(), - $keys[7] => $this->getUpdatedAt(), + $keys[6] => $this->getPosition(), + $keys[7] => $this->getCreatedAt(), + $keys[8] => $this->getUpdatedAt(), ); $virtualColumns = $this->virtualColumns; foreach($virtualColumns as $key => $virtualColumn) @@ -1172,9 +1223,12 @@ abstract class Lang implements ActiveRecordInterface $this->setByDefault($value); break; case 6: - $this->setCreatedAt($value); + $this->setPosition($value); break; case 7: + $this->setCreatedAt($value); + break; + case 8: $this->setUpdatedAt($value); break; } // switch() @@ -1207,8 +1261,9 @@ abstract class Lang implements ActiveRecordInterface if (array_key_exists($keys[3], $arr)) $this->setLocale($arr[$keys[3]]); if (array_key_exists($keys[4], $arr)) $this->setUrl($arr[$keys[4]]); if (array_key_exists($keys[5], $arr)) $this->setByDefault($arr[$keys[5]]); - if (array_key_exists($keys[6], $arr)) $this->setCreatedAt($arr[$keys[6]]); - if (array_key_exists($keys[7], $arr)) $this->setUpdatedAt($arr[$keys[7]]); + if (array_key_exists($keys[6], $arr)) $this->setPosition($arr[$keys[6]]); + if (array_key_exists($keys[7], $arr)) $this->setCreatedAt($arr[$keys[7]]); + if (array_key_exists($keys[8], $arr)) $this->setUpdatedAt($arr[$keys[8]]); } /** @@ -1226,6 +1281,7 @@ abstract class Lang implements ActiveRecordInterface if ($this->isColumnModified(LangTableMap::LOCALE)) $criteria->add(LangTableMap::LOCALE, $this->locale); if ($this->isColumnModified(LangTableMap::URL)) $criteria->add(LangTableMap::URL, $this->url); if ($this->isColumnModified(LangTableMap::BY_DEFAULT)) $criteria->add(LangTableMap::BY_DEFAULT, $this->by_default); + if ($this->isColumnModified(LangTableMap::POSITION)) $criteria->add(LangTableMap::POSITION, $this->position); if ($this->isColumnModified(LangTableMap::CREATED_AT)) $criteria->add(LangTableMap::CREATED_AT, $this->created_at); if ($this->isColumnModified(LangTableMap::UPDATED_AT)) $criteria->add(LangTableMap::UPDATED_AT, $this->updated_at); @@ -1296,6 +1352,7 @@ abstract class Lang implements ActiveRecordInterface $copyObj->setLocale($this->getLocale()); $copyObj->setUrl($this->getUrl()); $copyObj->setByDefault($this->getByDefault()); + $copyObj->setPosition($this->getPosition()); $copyObj->setCreatedAt($this->getCreatedAt()); $copyObj->setUpdatedAt($this->getUpdatedAt()); if ($makeNew) { @@ -1337,6 +1394,7 @@ abstract class Lang implements ActiveRecordInterface $this->locale = null; $this->url = null; $this->by_default = null; + $this->position = null; $this->created_at = null; $this->updated_at = null; $this->alreadyInSave = false; diff --git a/core/lib/Thelia/Model/Base/LangQuery.php b/core/lib/Thelia/Model/Base/LangQuery.php index 1a99ff28a..6223bea61 100644 --- a/core/lib/Thelia/Model/Base/LangQuery.php +++ b/core/lib/Thelia/Model/Base/LangQuery.php @@ -24,6 +24,7 @@ use Thelia\Model\Map\LangTableMap; * @method ChildLangQuery orderByLocale($order = Criteria::ASC) Order by the locale column * @method ChildLangQuery orderByUrl($order = Criteria::ASC) Order by the url column * @method ChildLangQuery orderByByDefault($order = Criteria::ASC) Order by the by_default column + * @method ChildLangQuery orderByPosition($order = Criteria::ASC) Order by the position column * @method ChildLangQuery orderByCreatedAt($order = Criteria::ASC) Order by the created_at column * @method ChildLangQuery orderByUpdatedAt($order = Criteria::ASC) Order by the updated_at column * @@ -33,6 +34,7 @@ use Thelia\Model\Map\LangTableMap; * @method ChildLangQuery groupByLocale() Group by the locale column * @method ChildLangQuery groupByUrl() Group by the url column * @method ChildLangQuery groupByByDefault() Group by the by_default column + * @method ChildLangQuery groupByPosition() Group by the position column * @method ChildLangQuery groupByCreatedAt() Group by the created_at column * @method ChildLangQuery groupByUpdatedAt() Group by the updated_at column * @@ -49,6 +51,7 @@ use Thelia\Model\Map\LangTableMap; * @method ChildLang findOneByLocale(string $locale) Return the first ChildLang filtered by the locale column * @method ChildLang findOneByUrl(string $url) Return the first ChildLang filtered by the url column * @method ChildLang findOneByByDefault(int $by_default) Return the first ChildLang filtered by the by_default column + * @method ChildLang findOneByPosition(int $position) Return the first ChildLang filtered by the position column * @method ChildLang findOneByCreatedAt(string $created_at) Return the first ChildLang filtered by the created_at column * @method ChildLang findOneByUpdatedAt(string $updated_at) Return the first ChildLang filtered by the updated_at column * @@ -58,6 +61,7 @@ use Thelia\Model\Map\LangTableMap; * @method array findByLocale(string $locale) Return ChildLang objects filtered by the locale column * @method array findByUrl(string $url) Return ChildLang objects filtered by the url column * @method array findByByDefault(int $by_default) Return ChildLang objects filtered by the by_default column + * @method array findByPosition(int $position) Return ChildLang objects filtered by the position column * @method array findByCreatedAt(string $created_at) Return ChildLang objects filtered by the created_at column * @method array findByUpdatedAt(string $updated_at) Return ChildLang objects filtered by the updated_at column * @@ -148,7 +152,7 @@ abstract class LangQuery extends ModelCriteria */ protected function findPkSimple($key, $con) { - $sql = 'SELECT ID, TITLE, CODE, LOCALE, URL, BY_DEFAULT, CREATED_AT, UPDATED_AT FROM lang WHERE ID = :p0'; + $sql = 'SELECT ID, TITLE, CODE, LOCALE, URL, BY_DEFAULT, POSITION, CREATED_AT, UPDATED_AT FROM lang WHERE ID = :p0'; try { $stmt = $con->prepare($sql); $stmt->bindValue(':p0', $key, PDO::PARAM_INT); @@ -435,6 +439,47 @@ abstract class LangQuery extends ModelCriteria return $this->addUsingAlias(LangTableMap::BY_DEFAULT, $byDefault, $comparison); } + /** + * Filter the query on the position column + * + * Example usage: + * + * $query->filterByPosition(1234); // WHERE position = 1234 + * $query->filterByPosition(array(12, 34)); // WHERE position IN (12, 34) + * $query->filterByPosition(array('min' => 12)); // WHERE position > 12 + * + * + * @param mixed $position The value to use as filter. + * Use scalar values for equality. + * Use array values for in_array() equivalent. + * Use associative array('min' => $minValue, 'max' => $maxValue) for intervals. + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildLangQuery The current query, for fluid interface + */ + public function filterByPosition($position = null, $comparison = null) + { + if (is_array($position)) { + $useMinMax = false; + if (isset($position['min'])) { + $this->addUsingAlias(LangTableMap::POSITION, $position['min'], Criteria::GREATER_EQUAL); + $useMinMax = true; + } + if (isset($position['max'])) { + $this->addUsingAlias(LangTableMap::POSITION, $position['max'], Criteria::LESS_EQUAL); + $useMinMax = true; + } + if ($useMinMax) { + return $this; + } + if (null === $comparison) { + $comparison = Criteria::IN; + } + } + + return $this->addUsingAlias(LangTableMap::POSITION, $position, $comparison); + } + /** * Filter the query on the created_at column * diff --git a/core/lib/Thelia/Model/Category.php b/core/lib/Thelia/Model/Category.php index 25a2ebe48..35ac49e0e 100755 --- a/core/lib/Thelia/Model/Category.php +++ b/core/lib/Thelia/Model/Category.php @@ -3,6 +3,7 @@ namespace Thelia\Model; use Thelia\Model\Base\Category as BaseCategory; +use Propel\Runtime\ActiveQuery\Criteria; class Category extends BaseCategory { /** @@ -17,6 +18,37 @@ class Category extends BaseCategory { { } + /** + * Create a new category. + * + * @param string $title the category title + * @param int $parent the ID of the parent category + * @param string $locale the locale of the title + */ + public function create($title, $parent, $locale) + { + $this + ->setLocale($locale) + ->setTitle($title) + ->setParent($parent) + ->setVisible(1) + ->setPosition($this->getNextPosition($parent)) + ; + + $this->save(); + } + + public function getNextPosition($parent) { + + $last = CategoryQuery::create() + ->filterByParent($parent) + ->orderByPosition(Criteria::DESC) + ->limit(1) + ->findOne() + ; + + return $last->getPosition() + 1; + } /** * diff --git a/core/lib/Thelia/Model/Map/CurrencyTableMap.php b/core/lib/Thelia/Model/Map/CurrencyTableMap.php index b1251801a..341a0cb45 100644 --- a/core/lib/Thelia/Model/Map/CurrencyTableMap.php +++ b/core/lib/Thelia/Model/Map/CurrencyTableMap.php @@ -57,7 +57,7 @@ class CurrencyTableMap extends TableMap /** * The total number of columns */ - const NUM_COLUMNS = 7; + const NUM_COLUMNS = 8; /** * The number of lazy-loaded columns @@ -67,7 +67,7 @@ class CurrencyTableMap extends TableMap /** * The number of columns to hydrate (NUM_COLUMNS - NUM_LAZY_LOAD_COLUMNS) */ - const NUM_HYDRATE_COLUMNS = 7; + const NUM_HYDRATE_COLUMNS = 8; /** * the column name for the ID field @@ -94,6 +94,11 @@ class CurrencyTableMap extends TableMap */ const BY_DEFAULT = 'currency.BY_DEFAULT'; + /** + * the column name for the POSITION field + */ + const POSITION = 'currency.POSITION'; + /** * the column name for the CREATED_AT field */ @@ -125,12 +130,12 @@ class CurrencyTableMap extends TableMap * e.g. self::$fieldNames[self::TYPE_PHPNAME][0] = 'Id' */ protected static $fieldNames = array ( - self::TYPE_PHPNAME => array('Id', 'Code', 'Symbol', 'Rate', 'ByDefault', 'CreatedAt', 'UpdatedAt', ), - self::TYPE_STUDLYPHPNAME => array('id', 'code', 'symbol', 'rate', 'byDefault', 'createdAt', 'updatedAt', ), - self::TYPE_COLNAME => array(CurrencyTableMap::ID, CurrencyTableMap::CODE, CurrencyTableMap::SYMBOL, CurrencyTableMap::RATE, CurrencyTableMap::BY_DEFAULT, CurrencyTableMap::CREATED_AT, CurrencyTableMap::UPDATED_AT, ), - self::TYPE_RAW_COLNAME => array('ID', 'CODE', 'SYMBOL', 'RATE', 'BY_DEFAULT', 'CREATED_AT', 'UPDATED_AT', ), - self::TYPE_FIELDNAME => array('id', 'code', 'symbol', 'rate', 'by_default', 'created_at', 'updated_at', ), - self::TYPE_NUM => array(0, 1, 2, 3, 4, 5, 6, ) + self::TYPE_PHPNAME => array('Id', 'Code', 'Symbol', 'Rate', 'ByDefault', 'Position', 'CreatedAt', 'UpdatedAt', ), + self::TYPE_STUDLYPHPNAME => array('id', 'code', 'symbol', 'rate', 'byDefault', 'position', 'createdAt', 'updatedAt', ), + self::TYPE_COLNAME => array(CurrencyTableMap::ID, CurrencyTableMap::CODE, CurrencyTableMap::SYMBOL, CurrencyTableMap::RATE, CurrencyTableMap::BY_DEFAULT, CurrencyTableMap::POSITION, CurrencyTableMap::CREATED_AT, CurrencyTableMap::UPDATED_AT, ), + self::TYPE_RAW_COLNAME => array('ID', 'CODE', 'SYMBOL', 'RATE', 'BY_DEFAULT', 'POSITION', 'CREATED_AT', 'UPDATED_AT', ), + self::TYPE_FIELDNAME => array('id', 'code', 'symbol', 'rate', 'by_default', 'position', 'created_at', 'updated_at', ), + self::TYPE_NUM => array(0, 1, 2, 3, 4, 5, 6, 7, ) ); /** @@ -140,12 +145,12 @@ class CurrencyTableMap extends TableMap * e.g. self::$fieldKeys[self::TYPE_PHPNAME]['Id'] = 0 */ protected static $fieldKeys = array ( - self::TYPE_PHPNAME => array('Id' => 0, 'Code' => 1, 'Symbol' => 2, 'Rate' => 3, 'ByDefault' => 4, 'CreatedAt' => 5, 'UpdatedAt' => 6, ), - self::TYPE_STUDLYPHPNAME => array('id' => 0, 'code' => 1, 'symbol' => 2, 'rate' => 3, 'byDefault' => 4, 'createdAt' => 5, 'updatedAt' => 6, ), - self::TYPE_COLNAME => array(CurrencyTableMap::ID => 0, CurrencyTableMap::CODE => 1, CurrencyTableMap::SYMBOL => 2, CurrencyTableMap::RATE => 3, CurrencyTableMap::BY_DEFAULT => 4, CurrencyTableMap::CREATED_AT => 5, CurrencyTableMap::UPDATED_AT => 6, ), - self::TYPE_RAW_COLNAME => array('ID' => 0, 'CODE' => 1, 'SYMBOL' => 2, 'RATE' => 3, 'BY_DEFAULT' => 4, 'CREATED_AT' => 5, 'UPDATED_AT' => 6, ), - self::TYPE_FIELDNAME => array('id' => 0, 'code' => 1, 'symbol' => 2, 'rate' => 3, 'by_default' => 4, 'created_at' => 5, 'updated_at' => 6, ), - self::TYPE_NUM => array(0, 1, 2, 3, 4, 5, 6, ) + self::TYPE_PHPNAME => array('Id' => 0, 'Code' => 1, 'Symbol' => 2, 'Rate' => 3, 'ByDefault' => 4, 'Position' => 5, 'CreatedAt' => 6, 'UpdatedAt' => 7, ), + self::TYPE_STUDLYPHPNAME => array('id' => 0, 'code' => 1, 'symbol' => 2, 'rate' => 3, 'byDefault' => 4, 'position' => 5, 'createdAt' => 6, 'updatedAt' => 7, ), + self::TYPE_COLNAME => array(CurrencyTableMap::ID => 0, CurrencyTableMap::CODE => 1, CurrencyTableMap::SYMBOL => 2, CurrencyTableMap::RATE => 3, CurrencyTableMap::BY_DEFAULT => 4, CurrencyTableMap::POSITION => 5, CurrencyTableMap::CREATED_AT => 6, CurrencyTableMap::UPDATED_AT => 7, ), + self::TYPE_RAW_COLNAME => array('ID' => 0, 'CODE' => 1, 'SYMBOL' => 2, 'RATE' => 3, 'BY_DEFAULT' => 4, 'POSITION' => 5, 'CREATED_AT' => 6, 'UPDATED_AT' => 7, ), + self::TYPE_FIELDNAME => array('id' => 0, 'code' => 1, 'symbol' => 2, 'rate' => 3, 'by_default' => 4, 'position' => 5, 'created_at' => 6, 'updated_at' => 7, ), + self::TYPE_NUM => array(0, 1, 2, 3, 4, 5, 6, 7, ) ); /** @@ -169,6 +174,7 @@ class CurrencyTableMap extends TableMap $this->addColumn('SYMBOL', 'Symbol', 'VARCHAR', false, 45, null); $this->addColumn('RATE', 'Rate', 'FLOAT', false, null, null); $this->addColumn('BY_DEFAULT', 'ByDefault', 'TINYINT', false, null, null); + $this->addColumn('POSITION', 'Position', 'INTEGER', false, null, null); $this->addColumn('CREATED_AT', 'CreatedAt', 'TIMESTAMP', false, null, null); $this->addColumn('UPDATED_AT', 'UpdatedAt', 'TIMESTAMP', false, null, null); } // initialize() @@ -352,6 +358,7 @@ class CurrencyTableMap extends TableMap $criteria->addSelectColumn(CurrencyTableMap::SYMBOL); $criteria->addSelectColumn(CurrencyTableMap::RATE); $criteria->addSelectColumn(CurrencyTableMap::BY_DEFAULT); + $criteria->addSelectColumn(CurrencyTableMap::POSITION); $criteria->addSelectColumn(CurrencyTableMap::CREATED_AT); $criteria->addSelectColumn(CurrencyTableMap::UPDATED_AT); } else { @@ -360,6 +367,7 @@ class CurrencyTableMap extends TableMap $criteria->addSelectColumn($alias . '.SYMBOL'); $criteria->addSelectColumn($alias . '.RATE'); $criteria->addSelectColumn($alias . '.BY_DEFAULT'); + $criteria->addSelectColumn($alias . '.POSITION'); $criteria->addSelectColumn($alias . '.CREATED_AT'); $criteria->addSelectColumn($alias . '.UPDATED_AT'); } diff --git a/core/lib/Thelia/Model/Map/LangTableMap.php b/core/lib/Thelia/Model/Map/LangTableMap.php index 86e3ebe16..c057cb315 100644 --- a/core/lib/Thelia/Model/Map/LangTableMap.php +++ b/core/lib/Thelia/Model/Map/LangTableMap.php @@ -57,7 +57,7 @@ class LangTableMap extends TableMap /** * The total number of columns */ - const NUM_COLUMNS = 8; + const NUM_COLUMNS = 9; /** * The number of lazy-loaded columns @@ -67,7 +67,7 @@ class LangTableMap extends TableMap /** * The number of columns to hydrate (NUM_COLUMNS - NUM_LAZY_LOAD_COLUMNS) */ - const NUM_HYDRATE_COLUMNS = 8; + const NUM_HYDRATE_COLUMNS = 9; /** * the column name for the ID field @@ -99,6 +99,11 @@ class LangTableMap extends TableMap */ const BY_DEFAULT = 'lang.BY_DEFAULT'; + /** + * the column name for the POSITION field + */ + const POSITION = 'lang.POSITION'; + /** * the column name for the CREATED_AT field */ @@ -121,12 +126,12 @@ class LangTableMap extends TableMap * e.g. self::$fieldNames[self::TYPE_PHPNAME][0] = 'Id' */ protected static $fieldNames = array ( - self::TYPE_PHPNAME => array('Id', 'Title', 'Code', 'Locale', 'Url', 'ByDefault', 'CreatedAt', 'UpdatedAt', ), - self::TYPE_STUDLYPHPNAME => array('id', 'title', 'code', 'locale', 'url', 'byDefault', 'createdAt', 'updatedAt', ), - self::TYPE_COLNAME => array(LangTableMap::ID, LangTableMap::TITLE, LangTableMap::CODE, LangTableMap::LOCALE, LangTableMap::URL, LangTableMap::BY_DEFAULT, LangTableMap::CREATED_AT, LangTableMap::UPDATED_AT, ), - self::TYPE_RAW_COLNAME => array('ID', 'TITLE', 'CODE', 'LOCALE', 'URL', 'BY_DEFAULT', 'CREATED_AT', 'UPDATED_AT', ), - self::TYPE_FIELDNAME => array('id', 'title', 'code', 'locale', 'url', 'by_default', 'created_at', 'updated_at', ), - self::TYPE_NUM => array(0, 1, 2, 3, 4, 5, 6, 7, ) + self::TYPE_PHPNAME => array('Id', 'Title', 'Code', 'Locale', 'Url', 'ByDefault', 'Position', 'CreatedAt', 'UpdatedAt', ), + self::TYPE_STUDLYPHPNAME => array('id', 'title', 'code', 'locale', 'url', 'byDefault', 'position', 'createdAt', 'updatedAt', ), + self::TYPE_COLNAME => array(LangTableMap::ID, LangTableMap::TITLE, LangTableMap::CODE, LangTableMap::LOCALE, LangTableMap::URL, LangTableMap::BY_DEFAULT, LangTableMap::POSITION, LangTableMap::CREATED_AT, LangTableMap::UPDATED_AT, ), + self::TYPE_RAW_COLNAME => array('ID', 'TITLE', 'CODE', 'LOCALE', 'URL', 'BY_DEFAULT', 'POSITION', 'CREATED_AT', 'UPDATED_AT', ), + self::TYPE_FIELDNAME => array('id', 'title', 'code', 'locale', 'url', 'by_default', 'position', 'created_at', 'updated_at', ), + self::TYPE_NUM => array(0, 1, 2, 3, 4, 5, 6, 7, 8, ) ); /** @@ -136,12 +141,12 @@ class LangTableMap extends TableMap * e.g. self::$fieldKeys[self::TYPE_PHPNAME]['Id'] = 0 */ protected static $fieldKeys = array ( - self::TYPE_PHPNAME => array('Id' => 0, 'Title' => 1, 'Code' => 2, 'Locale' => 3, 'Url' => 4, 'ByDefault' => 5, 'CreatedAt' => 6, 'UpdatedAt' => 7, ), - self::TYPE_STUDLYPHPNAME => array('id' => 0, 'title' => 1, 'code' => 2, 'locale' => 3, 'url' => 4, 'byDefault' => 5, 'createdAt' => 6, 'updatedAt' => 7, ), - self::TYPE_COLNAME => array(LangTableMap::ID => 0, LangTableMap::TITLE => 1, LangTableMap::CODE => 2, LangTableMap::LOCALE => 3, LangTableMap::URL => 4, LangTableMap::BY_DEFAULT => 5, LangTableMap::CREATED_AT => 6, LangTableMap::UPDATED_AT => 7, ), - self::TYPE_RAW_COLNAME => array('ID' => 0, 'TITLE' => 1, 'CODE' => 2, 'LOCALE' => 3, 'URL' => 4, 'BY_DEFAULT' => 5, 'CREATED_AT' => 6, 'UPDATED_AT' => 7, ), - self::TYPE_FIELDNAME => array('id' => 0, 'title' => 1, 'code' => 2, 'locale' => 3, 'url' => 4, 'by_default' => 5, 'created_at' => 6, 'updated_at' => 7, ), - self::TYPE_NUM => array(0, 1, 2, 3, 4, 5, 6, 7, ) + self::TYPE_PHPNAME => array('Id' => 0, 'Title' => 1, 'Code' => 2, 'Locale' => 3, 'Url' => 4, 'ByDefault' => 5, 'Position' => 6, 'CreatedAt' => 7, 'UpdatedAt' => 8, ), + self::TYPE_STUDLYPHPNAME => array('id' => 0, 'title' => 1, 'code' => 2, 'locale' => 3, 'url' => 4, 'byDefault' => 5, 'position' => 6, 'createdAt' => 7, 'updatedAt' => 8, ), + self::TYPE_COLNAME => array(LangTableMap::ID => 0, LangTableMap::TITLE => 1, LangTableMap::CODE => 2, LangTableMap::LOCALE => 3, LangTableMap::URL => 4, LangTableMap::BY_DEFAULT => 5, LangTableMap::POSITION => 6, LangTableMap::CREATED_AT => 7, LangTableMap::UPDATED_AT => 8, ), + self::TYPE_RAW_COLNAME => array('ID' => 0, 'TITLE' => 1, 'CODE' => 2, 'LOCALE' => 3, 'URL' => 4, 'BY_DEFAULT' => 5, 'POSITION' => 6, 'CREATED_AT' => 7, 'UPDATED_AT' => 8, ), + self::TYPE_FIELDNAME => array('id' => 0, 'title' => 1, 'code' => 2, 'locale' => 3, 'url' => 4, 'by_default' => 5, 'position' => 6, 'created_at' => 7, 'updated_at' => 8, ), + self::TYPE_NUM => array(0, 1, 2, 3, 4, 5, 6, 7, 8, ) ); /** @@ -166,6 +171,7 @@ class LangTableMap extends TableMap $this->addColumn('LOCALE', 'Locale', 'VARCHAR', false, 45, null); $this->addColumn('URL', 'Url', 'VARCHAR', false, 255, null); $this->addColumn('BY_DEFAULT', 'ByDefault', 'TINYINT', false, null, null); + $this->addColumn('POSITION', 'Position', 'INTEGER', false, null, null); $this->addColumn('CREATED_AT', 'CreatedAt', 'TIMESTAMP', false, null, null); $this->addColumn('UPDATED_AT', 'UpdatedAt', 'TIMESTAMP', false, null, null); } // initialize() @@ -334,6 +340,7 @@ class LangTableMap extends TableMap $criteria->addSelectColumn(LangTableMap::LOCALE); $criteria->addSelectColumn(LangTableMap::URL); $criteria->addSelectColumn(LangTableMap::BY_DEFAULT); + $criteria->addSelectColumn(LangTableMap::POSITION); $criteria->addSelectColumn(LangTableMap::CREATED_AT); $criteria->addSelectColumn(LangTableMap::UPDATED_AT); } else { @@ -343,6 +350,7 @@ class LangTableMap extends TableMap $criteria->addSelectColumn($alias . '.LOCALE'); $criteria->addSelectColumn($alias . '.URL'); $criteria->addSelectColumn($alias . '.BY_DEFAULT'); + $criteria->addSelectColumn($alias . '.POSITION'); $criteria->addSelectColumn($alias . '.CREATED_AT'); $criteria->addSelectColumn($alias . '.UPDATED_AT'); } diff --git a/core/lib/Thelia/Tools/URL.php b/core/lib/Thelia/Tools/URL.php index 460703199..cf0800e07 100644 --- a/core/lib/Thelia/Tools/URL.php +++ b/core/lib/Thelia/Tools/URL.php @@ -44,7 +44,7 @@ class URL */ public static function absoluteUrl($path, array $parameters = array(), $path_only = false) { - // Already absolute ? + // Already absolute ? if (substr($path, 0, 4) != 'http') { $root = $path_only ? ConfigQuery::read('base_url', '/') : self::getIndexPage(); @@ -57,7 +57,7 @@ class URL $queryString = ''; foreach($parameters as $name => $value) { - $queryString = sprintf("%s=%s&", urlencode($name), urlencode($value)); + $queryString .= sprintf("%s=%s&", urlencode($name), urlencode($value)); } $sepChar = strstr($base, '?') === false ? '?' : '&'; @@ -77,7 +77,7 @@ class URL */ public static function adminViewUrl($viewName, array $parameters = array()) { - $path = sprintf("%s/admin/%s", self::getIndexPage(), $viewName); // FIXME ! view= should not be necessaray, check routing parameters + $path = sprintf("%s/admin/%s", self::getIndexPage(), $viewName); // FIXME ! view= should not be required, check routing parameters return self::absoluteUrl($path, $parameters); } diff --git a/install/insert.sql b/install/insert.sql index 6518462c4..d4697f94b 100755 --- a/install/insert.sql +++ b/install/insert.sql @@ -1,8 +1,8 @@ -INSERT INTO `lang`(`id`,`title`,`code`,`locale`,`url`,`by_default`,`created_at`,`updated_at`)VALUES -(1, 'Français', 'fr', 'fr_FR', '','1', NOW(), NOW()), -(2, 'English', 'en', 'en_EN', '', '0', NOW(), NOW()), -(3, 'Espanol', 'es', 'es_ES', '', '0', NOW(), NOW()), -(4, 'Italiano', 'it', 'it_IT', '','0', NOW(), NOW()); +INSERT INTO `lang`(`id`,`title`,`code`,`locale`,`url`,`by_default`,`position`,`created_at`,`updated_at`)VALUES +(1, 'Français', 'fr', 'fr_FR', '','1', '1', NOW(), NOW()), +(2, 'English', 'en', 'en_EN', '', '0', '2', NOW(), NOW()), +(3, 'Espanol', 'es', 'es_ES', '', '0', '3', NOW(), NOW()), +(4, 'Italiano', 'it', 'it_IT', '','0', '4', NOW(), NOW()); INSERT INTO `config` (`name`, `value`, `secured`, `hidden`, `created_at`, `updated_at`) VALUES ('session_config.default', '1', 1, 1, NOW(), NOW()), @@ -23,11 +23,11 @@ INSERT INTO `customer_title_i18n` (`id`, `locale`, `short`, `long`) VALUES (3, 'en_US', 'Miss', 'Miss'), (3, 'fr_FR', 'Mlle', 'Madamemoiselle'); -INSERT INTO `currency` (`id` ,`code` ,`symbol` ,`rate` ,`by_default` ,`created_at` ,`updated_at`) +INSERT INTO `currency` (`id` ,`code` ,`symbol` ,`rate` ,`by_default`, `position` ,`created_at` ,`updated_at`) VALUES -(1, 'EUR', '€', '1', '1', NOW() , NOW()), -(2, 'USD', '$', '1.26', '0', NOW(), NOW()), -(3, 'GBP', '£', '0.89', '0', NOW(), NOW()); +(1, 'EUR', '€', '1', '1', '1', NOW() , NOW()), +(2, 'USD', '$', '1.26', '0', '2', NOW(), NOW()), +(3, 'GBP', '£', '0.89', '0', '3', NOW(), NOW()); INSERT INTO `currency_i18n` (`id` ,`locale` ,`name`) VALUES diff --git a/install/thelia.sql b/install/thelia.sql index 0cf0efe7f..a2797af33 100755 --- a/install/thelia.sql +++ b/install/thelia.sql @@ -522,6 +522,7 @@ CREATE TABLE `lang` `locale` VARCHAR(45), `url` VARCHAR(255), `by_default` TINYINT, + `position` INTEGER, `created_at` DATETIME, `updated_at` DATETIME, PRIMARY KEY (`id`) @@ -763,6 +764,7 @@ CREATE TABLE `currency` `symbol` VARCHAR(45), `rate` FLOAT, `by_default` TINYINT, + `position` INTEGER, `created_at` DATETIME, `updated_at` DATETIME, PRIMARY KEY (`id`) diff --git a/local/config/schema.xml b/local/config/schema.xml index 533bf2d37..744e1746c 100755 --- a/local/config/schema.xml +++ b/local/config/schema.xml @@ -589,7 +589,8 @@ - + + diff --git a/templates/admin/default/assets/css/admin.less b/templates/admin/default/assets/css/admin.less index 0c6019d78..9d9f2c482 100755 --- a/templates/admin/default/assets/css/admin.less +++ b/templates/admin/default/assets/css/admin.less @@ -124,7 +124,7 @@ hr { color: white; } -.modal-footer { +.footer { background: none repeat scroll 0 0 transparent; border: medium none; box-shadow: none; @@ -375,6 +375,7 @@ hr { padding: 10px 20px; } } + // -- Login form -------------------------------------------------------------- .form-signin { @@ -394,157 +395,157 @@ textarea:focus, input[type="text"]:focus, input[type="password"]:focus, input[ty // -- Allow inline forms validation states ------------------------------------ -.form-inline .warning .control-label, -.form-inline .warning .help-block, -.form-inline .warning .help-inline { +form .warning .control-label, +form .warning .help-block, +form .warning .help-inline { color: #c09853; } -.form-inline .warning .checkbox, -.form-inline .warning .radio, -.form-inline .warning input, -.form-inline .warning select, -.form-inline .warning textarea { +form .warning .checkbox, +form .warning .radio, +form .warning input, +form .warning select, +form .warning textarea { color: #c09853; } -.form-inline .warning input, -.form-inline .warning select, -.form-inline .warning textarea { +form .warning input, +form .warning select, +form .warning textarea { border-color: #c09853; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); } -.form-inline .warning input:focus, -.form-inline .warning select:focus, -.form-inline .warning textarea:focus { +form .warning input:focus, +form .warning select:focus, +form .warning textarea:focus { border-color: #a47e3c; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e; -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e; box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e; } -.form-inline .warning .input-prepend .add-on, -.form-inline .warning .input-append .add-on { +form .warning .input-prepend .add-on, +form .warning .input-append .add-on { color: #c09853; background-color: #fcf8e3; border-color: #c09853; } -.form-inline .error .control-label, -.form-inline .error .help-block, -.form-inline .error .help-inline { +form .error .control-label, +form .error .help-block, +form .error .help-inline { color: #b94a48; } -.form-inline .error .checkbox, -.form-inline .error .radio, -.form-inline .error input, -.form-inline .error select, -.form-inline .error textarea { +form .error .checkbox, +form .error .radio, +form .error input, +form .error select, +form .error textarea { color: #b94a48; } -.form-inline .error input, -.form-inline .error select, -.form-inline .error textarea { +form .error input, +form .error select, +form .error textarea { border-color: #b94a48; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); } -.form-inline .error input:focus, -.form-inline .error select:focus, -.form-inline .error textarea:focus { +form .error input:focus, +form .error select:focus, +form .error textarea:focus { border-color: #953b39; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392; -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392; box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392; } -.form-inline .error .input-prepend .add-on, -.form-inline .error .input-append .add-on { +form .error .input-prepend .add-on, +form .error .input-append .add-on { color: #b94a48; background-color: #f2dede; border-color: #b94a48; } -.form-inline .success .control-label, -.form-inline .success .help-block, -.form-inline .success .help-inline { +form .success .control-label, +form .success .help-block, +form .success .help-inline { color: #468847; } -.form-inline .success .checkbox, -.form-inline .success .radio, -.form-inline .success input, -.form-inline .success select, -.form-inline .success textarea { +form .success .checkbox, +form .success .radio, +form .success input, +form .success select, +form .success textarea { color: #468847; } -.form-inline .success input, -.form-inline .success select, -.form-inline .success textarea { +form .success input, +form .success select, +form .success textarea { border-color: #468847; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); } -.form-inline .success input:focus, -.form-inline .success select:focus, -.form-inline .success textarea:focus { +form .success input:focus, +form .success select:focus, +form .success textarea:focus { border-color: #356635; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b; -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b; box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b; } -.form-inline .success .input-prepend .add-on, -.form-inline .success .input-append .add-on { +form .success .input-prepend .add-on, +form .success .input-append .add-on { color: #468847; background-color: #dff0d8; border-color: #468847; } -.form-inline .info .control-label, -.form-inline .info .help-block, -.form-inline .info .help-inline { +form .info .control-label, +form .info .help-block, +form .info .help-inline { color: #3a87ad; } -.form-inline .info .checkbox, -.form-inline .info .radio, -.form-inline .info input, -.form-inline .info select, -.form-inline .info textarea { +form .info .checkbox, +form .info .radio, +form .info input, +form .info select, +form .info textarea { color: #3a87ad; } -.form-inline .info input, -.form-inline .info select, -.form-inline .info textarea { +form .info input, +form .info select, +form .info textarea { border-color: #3a87ad; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); } -.form-inline .info input:focus, -.form-inline .info select:focus, -.form-inline .info textarea:focus { +form .info input:focus, +form .info select:focus, +form .info textarea:focus { border-color: #2d6987; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3; -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3; box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3; } -.form-inline .info .input-prepend .add-on, -.form-inline .info .input-append .add-on { +form .info .input-prepend .add-on, +form .info .input-append .add-on { color: #3a87ad; background-color: #d9edf7; border-color: #3a87ad; @@ -560,6 +561,7 @@ textarea:focus, input[type="text"]:focus, input[type="password"]:focus, input[ty padding: 1em; margin-bottom: 20px; + // The block title .title { color: #5A6876; text-transform: uppercase; @@ -569,11 +571,53 @@ textarea:focus, input[type="text"]:focus, input[type="password"]:focus, input[ty line-height: 30px; } + // The action bar on the right .actions { text-align: right; } } +// Reduce bottom margin of admin tabs. +.admin-tabs { + margin-bottom: 1em; +} + +// The overall form container +.form-container { + + // The inner toolbar (flags & save buttons) + .inner-toolbar { + + line-height: 30px; + margin-bottom: 1em; + + .inner-actions { + text-align: right; + } + + .nav-pills { + margin-bottom: 0; + + li a { + padding: 4px; + opacity: 0.3; + } + + li.active a { + opacity: 1; + background-color: #E7E7E7; + } + } + } +} + +// Modal dialog tweaking ------------------------------------------------------ + +.modal { + form { + margin-bottom: 0; + } +} // -- Admin forms tweaking ---------------------------------------------------- label { @@ -584,6 +628,10 @@ label { } } +.input-append.input-block-level .add-on img { + max-height: 18px; +} + // Information in field label .label-help-block, .help-block { color: lighten(#595959, 20); diff --git a/templates/admin/default/assets/img/flags/en.gif b/templates/admin/default/assets/img/flags/en.gif new file mode 100644 index 0000000000000000000000000000000000000000..3a7661fdbc59f3153a66a613a8c95ccf4dd6c2fe GIT binary patch literal 1256 zcmVu>ePrI=-_(8xNO_QIwy~5Grzq0DF zn`CyG*t4YP<>b$-otH&4sEma`XNZhHIBtBKs7*S3hn~GQE6lX3v0+(%IxCSgCfnTK zKxm4lIxOqg)u}ryXM3R9tC_Brjoho5ud%nPg?KAZdgIvB;MmpV)XcNBxc&3;{QUfp zm!^VGK(>;HouaP4m4?E+yW!s6n4PJrtFP9cihzQKt*EEDfp3A2uCQxYzrn`lu9@hn zl&6=G;mN?Ro|yFK;gyz{iHncb*4OIg9(Tfx21lEp02O4%*e;t zzO&Q5wbHw>KxKx`Q9a46qPVA_z{1DG#m3^Xo|KS}YP`kOss0W6 zMJJIkZZnMdAW@1Q0aBX$#mI;2(?2InHpP-wtj!J^?wU0SXA7T+LszI+_*a654p_5@ zt>_`+8wd~xzCh@=3)4Id|BwuUGGojNRV;{b;DEwF0AR{)1cSHk-v|*fjO^&a!qf>5 z9soRe!OKO90yKpD+Ymy74;wOwocPh9g9-o~k~9F4V?mMCA2g7VqYnju4ha&}SaL)_ z69`Hc-~cZC3=*cnK0rAU~qJDN+Dv{ zQ;P!(G@xQHtynR^0*!>R);Vklf(;)7JmHKu5k%kz0nkJ9m{dww>_ly4pih79l0(Zp*1MiGa>2LI;|@leo8m(P``0I{ESO+{-w&Egj&lmHGGV?Abfs(rNVI zJLa;Pw=EsGE*|sjz4h(B=(L*W)jGm2AI2~r_TfDI=RC3${EGa=xumBcU~?8r3UySLu5a?!hbYyIDa3&%oW z*s=K8viR}w;Jml?>g4_P#QgdAz`9HF*vt0mX!__hzb_u1DH{6p@%ZSh^3<-*c2)oD zNaopo$$2-gGa#ovEXheNsWvI|cT-OM@n@aX2lwZJbQ=+!#*xj3^e9qHX& z?a-_H@}$(nH_EJa@7Bur@9O8&I?cT{{PLdi<#6n+N$b|s`th^y*2?hGt?A9E&@v$Z z>^S1kIoHc*vn(CGE*|Hynd#xM+ODaoD;&p$f9I_ts45)5FCPEwIs5UY-_vQTLpSZ( zJJWA&2$2k4+@#mLR?%hS~xrgi8EdJ>|(Z*-xmMgh>Cc$RNu^1ZhXxZpFUCCe6DhjtY6Af#G2T=&fM+Lk21f)p}r zT-Y#-){JBl=;?tpst_YN`vMnGfJ6o$7KScm@LqGM5)$yIe=?LIBF~w z0;}0OS!<-i3IGJ|Q$Pdo@GzGOGdMHH1vVt$KmZy9w$ChsrSKXB!5p*0CePr&3=at) z(LewwDzJbL2+&|jD~nuF#w{W^p^6e1EE9zbC6wR-Hz2^kKqx?*kj)Ktbb^T!MlkRK z29$sRLOd`i!44ZiJkbOv{7lmZC?bqNfDuP9&_W9gOi|AgIgrByFA`Nz$_gh462uY& YZ>s)@9*%OEhOyi?eOvO;Njx_{{FVP&hql} z?(XiOrNX#0D!?`?;^O0&ow@t_`|9fJpQOR_^z@P|A)cbYrmD$@C?E6l^QWxJ`1$$g z=jf-a%Auyi(Yd$o@9)YvErcf?l`J9vK6$n@DWEPT054yeEhFXT=j-e2`1ttw`T4Ih zDEj*P_V)JQ;Nj@#>6a`c07Qe!IWC2GNu(Qa*!^Nzx#qHzb03=RLVwT$5+`+=csWB(Cx6ZG#$HTFMe5^7XT}%+=P{;K|3?+S`659o%nK04-erJ$S##)s&gEt*@})aaOgs&a<}5 zsjkh`Yf{$N*kf*%oua?O#nh}XfC05oUFWliGA z#~L?hgpH=y+1lyp>U$&{yuH8LZd9c(CZVRpqNl~r(9)ZqytOnbf-)($G%CN!*0Qs; znk^%(GANaqwY0a*xiu=#(bA|eCf;yWx4O|)YooQf&a$@4(4qwd9j0nMNtR@o#zgKyEIHAk%ZMEoEJ!evO5Tkj29hZF z=S60-7Y^ugpm4#0mPK(0Okm*8fS!MvR-HhK;@5@}6eeLfl5N1N2~23D_%~=@2L~u{ z0eisjrUVFS5DXwtszRH8?@o-q@B6&fCmd% zD)t0`f`-799RD=DbwNl?y*WK1L=d55-T@iaZ1k&;T8e`eq{c)6A|gYE2rL2#DQa5&%F0&LdTPvBf8fFu_ii-xwp17-l5E$2FJ$5(_n< ntOH6fPZ%&mF|ZJnNiKei>g%U4CZR7S)H^Q#Xd>zA>Xfva)e z-{4S!NX9rU&^j*1$jQYwETb+`l^Yin(y}zfuoSwRoSeZ?<%&6_{ z?yt$A=I7|MUrE!dn*entw6(X@J1@D(vghdOai?JbU?6@a9DXGo`1$$L)78AqwP2HQ zz0S1(hbzCo!N%9Tz|ps@GAN2DAH&qTV3dIvzOmZk*V8*M0C*>|$)*E}EcyBQ!Z$3xHY);&D*%5f=jZ6i z$;!Xd#kkL_V2^LC!lBsN+5l-IsC96LCmyRYCjeR=vB;%2b2hxqw78Irk18SGy|9Hd zDp!k4K!H{OeksQ|Evzyp-QM43p;))Ly88P1xX7^1IWBUOZj31)?CtHiG%BbuCa=J! z#?!&UHY*)}E`+6b($mz$#>b&ySxkpS&(PAr)wYEv9@wOipS-BKH7fuA{{R3000000 z0000000000A^8LW008;`EC2ui02Kfg000R80QCtRNU)&6fxd?5>A;T89uN?b^~z>P z-ZcyZ*QFrA;s?1BOH`;>LgZc@Y|%u#!iXkCtyDZ3Si7L*$dM}Ga-EqWVUj6a`i78j zv%$a!L~;_CFfpaZ15H)}Xz(IJpAi;348V}J2nqxUKyq9vmXCnC0Hapv>+qx5h+uIJ zy2)6XT}NNEtL(R$}Eb{2L=wh3>(lwN`(av3Q*B!BMJotb3i>A-~a&v4h(wy!f_yi zk088#D}Wu1+|UOmtW?s-3M+_%M*v%t;)NfO fU?h+-gK(3HIk#9MgA9hW5eq4iP|}G&0RaFzgC=ei literal 0 HcmV?d00001 diff --git a/templates/admin/default/categories.html b/templates/admin/default/categories.html index 2a43dd426..0abc9e10a 100644 --- a/templates/admin/default/categories.html +++ b/templates/admin/default/categories.html @@ -16,10 +16,10 @@
- +
{ifloop rel="category_list"} @@ -48,9 +50,9 @@ - {loop name="category_list" type="category" parent="{$current_category_id}" order="manual"} + {loop name="category_list" type="category" visible="*" parent="{$current_category_id}" order="manual"} - + {module_include location='category_list_row'} @@ -59,15 +61,27 @@ {/loop} @@ -77,7 +91,17 @@ {elseloop rel="category_list"} - + {/elseloop} @@ -89,10 +113,10 @@
-
{* display parent category name, and get current cat ID *} - {loop name="category_title" type="category" id="{$current_category_id}"} + {loop name="category_title" type="category" visible="*" id="{$current_category_id}"} {intl l="Categories in %cat" cat=$TITLE} {$cat_id = $ID} {/loop} @@ -29,9 +29,11 @@ {module_include location='category_list_caption'} - + {loop type="auth" name="can_create" context="admin" roles="ADMIN" permissions="admin.category.create"} + + {/loop}
{$TITLE}{$TITLE} - - {$POSITION} - + {loop type="auth" name="can_change" context="admin" roles="ADMIN" permissions="admin.category.edit"} + + {$POSITION} + + {/loop} + + {elseloop rel="can_change"} + {$POSITION} + {/elseloop} - - - + + + {loop type="auth" name="can_change" context="admin" roles="ADMIN" permissions="admin.category.edit"} + + {/loop} + + {loop type="auth" name="can_delete" context="admin" roles="ADMIN" permissions="admin.category.delete"} + + {/loop}
{intl l="This category has no sub-categories. To create a new one, click the + button above."}
+
+ {loop type="auth" name="can_create" context="admin" roles="ADMIN" permissions="admin.category.create"} + {intl l="This category has no sub-categories. To create a new one, click the + button above."} + {/loop} + + {elseloop rel="can_create"} + {intl l="This category has no sub-categories."} + {/elseloop} +
+
+
{loop name="product_list" type="product" category="{$current_category_id}" order="manual"} - + - + {module_include location='product_list_row'} @@ -135,14 +159,14 @@ {/loop} @@ -165,6 +189,40 @@ +{include file="includes/add-category-dialog.html"} +{include file="includes/delete-category-dialog.html"} + {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 5ad547fa0..c1e19809f 100644 --- a/templates/admin/default/edit_category.html +++ b/templates/admin/default/edit_category.html @@ -1,10 +1,6 @@ {check_auth context="admin" roles="ADMIN" permissions="admin.catalog.view" login_tpl="/admin/login"} -{if $action == 'create'} - {$page_title={intl l='Create a new category'}} -{else} - {$page_title={intl l='Edit category'}} -{/if} +{$page_title={intl l='Edit category'}} {include file='includes/header.inc.html'} @@ -19,29 +15,22 @@
- {if $action == 'create'} - {intl l='Create a new category'} - {else} - {intl l='Edit category'} - {/if} + {intl l='Edit category'}
- - - {if $action != 'create'} - - - - {/if} + + +
-
diff --git a/templates/admin/default/general_error.html b/templates/admin/default/general_error.html new file mode 100644 index 000000000..c41fee7a4 --- /dev/null +++ b/templates/admin/default/general_error.html @@ -0,0 +1,10 @@ +{$page_title={intl l='AN error occured'}} + +{include file='includes/header.inc.html'} + +
+

{intl l="Oops! An Error Occurred"}

+

{$error_message}

+
+ +{include file='includes/footer.inc.html'} \ No newline at end of file diff --git a/templates/admin/default/includes/add-category-dialog.html b/templates/admin/default/includes/add-category-dialog.html new file mode 100644 index 000000000..3f7c19b4a --- /dev/null +++ b/templates/admin/default/includes/add-category-dialog.html @@ -0,0 +1,66 @@ + +{* Adding a new Category *} + + diff --git a/templates/admin/default/includes/category_breadcrumb.html b/templates/admin/default/includes/category_breadcrumb.html index 8bb6aa6ff..0870a4c2e 100644 --- a/templates/admin/default/includes/category_breadcrumb.html +++ b/templates/admin/default/includes/category_breadcrumb.html @@ -1,16 +1,18 @@ +{* Breadcrumb for categories browsing and editing *}
  • Home /
  • Catalog + {ifloop rel="category_path"} /
  • - {loop name="category_path" type="category-path" category="{$current_category_id}"} + {loop name="category_path" type="category-path" visible="*" category="{$current_category_id}"} {if $ID == $current_category_id}
  • {if $action == 'edit'} {intl l='Editing %cat' cat="{$TITLE}"} {else} - {$TITLE} {intl l="(edit)"} + {$TITLE} {intl l="(edit)"} {/if}
  • {else} @@ -18,11 +20,7 @@ {/if} {/loop} {/ifloop} + {elseloop rel="category_path"} - {if $action == 'create'}/{/if} -{/elseloop} - -{if $action == 'create'} -
  • {intl l='Create a new category'}
  • -{/if} - + +{/elseloop} \ No newline at end of file diff --git a/templates/admin/default/includes/delete-category-dialog.html b/templates/admin/default/includes/delete-category-dialog.html new file mode 100644 index 000000000..f23829951 --- /dev/null +++ b/templates/admin/default/includes/delete-category-dialog.html @@ -0,0 +1,42 @@ + +{* Adding a new Category *} + + diff --git a/templates/admin/default/includes/footer.inc.html b/templates/admin/default/includes/footer.inc.html index 9611586b0..c69b253ad 100755 --- a/templates/admin/default/includes/footer.inc.html +++ b/templates/admin/default/includes/footer.inc.html @@ -1,7 +1,7 @@ {module_include location='before_footer'}
    -
    +

    {intl l='© Thelia 2013'} - {intl l='Édité par OpenStudio'} diff --git a/templates/admin/default/includes/inner-form-toolbar.html b/templates/admin/default/includes/inner-form-toolbar.html new file mode 100644 index 000000000..8d6f65cc8 --- /dev/null +++ b/templates/admin/default/includes/inner-form-toolbar.html @@ -0,0 +1,27 @@ +

    +
    + {* Display the top form toolbar, with edition flags, and save buttons *} + + {* When creating a new object, only default language is displayed *} + {if $action == 'create'} + {$default_only = 1} + {else} + {$default_only = 0} + {/if} + + +
    + +
    + + +
    +
    diff --git a/templates/admin/default/login.html b/templates/admin/default/login.html index 246801e3f..77195cf18 100755 --- a/templates/admin/default/login.html +++ b/templates/admin/default/login.html @@ -13,7 +13,7 @@

    {intl l='Thelia Back Office'}

    - {form name="thelia.admin.login" success_url="home" error_url="login"} + {form name="thelia.admin.login"}
    {if #form_error}
    #form_error_message
    {/if} diff --git a/templates/default/connexion.html b/templates/default/connexion.html index b4c391825..b6b377031 100755 --- a/templates/default/connexion.html +++ b/templates/default/connexion.html @@ -4,7 +4,7 @@ {* We use $INDEX_PAGE as form action to avoid mixing post and get data *} {* - The two fields below are not par of the Login form, they are here to defines + The two fields below are not par of the form, they are here to defines the action to process, and the view to render once the form is submited *} {* the action triggered by this form *}
    {* display parent category name *} - {loop name="category_title" type="category" id="{$current_category_id}"} + {loop name="category_title" type="category" visible="*" id="{$current_category_id}"} {intl l="Products in %cat" cat=$TITLE} {/loop} {elseloop rel="category_title"} @@ -124,9 +148,9 @@
    Image !Image !{$TITLE}{$TITLE} - + {$POSITION} - + - - + +