Added category creation and deletion

This commit is contained in:
franck
2013-08-08 02:39:42 +02:00
parent eb93049897
commit 64031a1883
55 changed files with 1569 additions and 255 deletions

View File

@@ -0,0 +1,266 @@
<?php
/*************************************************************************************/
/* */
/* Thelia */
/* */
/* Copyright (c) OpenStudio */
/* email : info@thelia.net */
/* web : http://www.thelia.net */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 3 of the License */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* */
/*************************************************************************************/
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),
);
}
}

View File

@@ -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
*

View File

@@ -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");
}
}

View File

@@ -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);

View File

@@ -22,6 +22,10 @@
<argument type="service" id="thelia.securityContext"/>
</service>
<service id="thelia.action.category" class="Thelia\Action\Category">
<tag name="kernel.event_subscriber"/>
</service>
</services>
</config>

View File

@@ -22,13 +22,21 @@
<loop class="Thelia\Core\Template\Loop\Product" name="product"/>
<loop class="Thelia\Core\Template\Loop\Feed" name="feed"/>
<loop class="Thelia\Core\Template\Loop\Title" name="title"/>
<loop class="Thelia\Core\Template\Loop\Lang" name="lang"/>
<loop class="Thelia\Core\Template\Loop\CategoryTree" name="category-tree"/>
</loops>
<forms>
<form name="thelia.customer.creation" class="Thelia\Form\CustomerCreation"/>
<form name="thelia.customer.modification" class="Thelia\Form\CustomerModification"/>
<form name="thelia.customer.login" class="Thelia\Form\CustomerLogin"/>
<form name="thelia.admin.login" class="Thelia\Form\AdminLogin"/>
<form name="thelia.admin.category.creation" class="Thelia\Form\CategoryCreationForm"/>
<form name="thelia.admin.category.deletion" class="Thelia\Form\CategoryDeletionForm"/>
</forms>
@@ -84,7 +92,7 @@
<argument type="service" id="request" />
<argument type="service" id="event_dispatcher"/>
<argument type="service" id="thelia.parser.context"/>
<argument >true</argument> <!-- debug mode -->
<argument >false</argument> <!-- Template name, or false -->
<argument >%kernel.environment%</argument>
<argument >%kernel.debug%</argument>
</service>

View File

@@ -31,9 +31,8 @@
<default key="_controller">Thelia\Admin\Controller\CategoryController::indexAction</default>
</route>
<route id="admin.category" path="/admin/catalog/category/{action}">
<route id="admin.category" path="/admin/catalog/category">
<default key="_controller">Thelia\Admin\Controller\CategoryController::processAction</default>
<requirement key="action">.*</requirement>
</route>
<!-- The default route, to display a template -->

View File

@@ -59,7 +59,7 @@ abstract class ActionEvent extends Event
public function __construct(Request $request, $action)
{
$this->request = $request;
$this->action = $action;
$this->action = $action;
}
/**

View File

@@ -0,0 +1,37 @@
<?php
/*************************************************************************************/
/* */
/* Thelia */
/* */
/* Copyright (c) OpenStudio */
/* email : info@thelia.net */
/* web : http://www.thelia.net */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 3 of the License */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* */
/*************************************************************************************/
namespace Thelia\Core\Event;
use Thelia\Model\Category;
class CategoryEvent extends InternalEvent {
public $category;
public function __construct(Category $category)
{
$this->category = $category;
}
}

View File

@@ -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";
}

View File

@@ -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);

View File

@@ -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)

View File

@@ -0,0 +1,28 @@
<?php
/*************************************************************************************/
/* */
/* Thelia */
/* */
/* Copyright (c) OpenStudio */
/* email : info@thelia.net */
/* web : http://www.thelia.net */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 3 of the License */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* */
/*************************************************************************************/
namespace Thelia\Core\Security\Exception;
class AuthorizationException extends \Exception
{
}

View File

@@ -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) {

View File

@@ -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),
);
}

View File

@@ -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(

View File

@@ -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();

View File

@@ -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);

View File

@@ -0,0 +1,123 @@
<?php
/*************************************************************************************/
/* */
/* Thelia */
/* */
/* Copyright (c) OpenStudio */
/* email : info@thelia.net */
/* web : http://www.thelia.net */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 3 of the License */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* */
/*************************************************************************************/
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 <franck@cqfdev.fr>
*/
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;
}
}

View File

@@ -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();

View File

@@ -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();

View File

@@ -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();

View File

@@ -0,0 +1,114 @@
<?php
/*************************************************************************************/
/* */
/* Thelia */
/* */
/* Copyright (c) OpenStudio */
/* email : info@thelia.net */
/* web : http://www.thelia.net */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 3 of the License */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* */
/*************************************************************************************/
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 <franck@cqfdev.fr>
*/
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;
}
}

View File

@@ -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":

View File

@@ -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);
}

View File

@@ -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();

View File

@@ -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;
}
/**

View File

@@ -0,0 +1,55 @@
<?php
/*************************************************************************************/
/* */
/* Thelia */
/* */
/* Copyright (c) OpenStudio */
/* email : info@thelia.net */
/* web : http://www.thelia.net */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 3 of the License */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* */
/*************************************************************************************/
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";
}
}

View File

@@ -0,0 +1,45 @@
<?php
/*************************************************************************************/
/* */
/* Thelia */
/* */
/* Copyright (c) OpenStudio */
/* email : info@thelia.net */
/* web : http://www.thelia.net */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 3 of the License */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* */
/*************************************************************************************/
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";
}
}

View File

@@ -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;

View File

@@ -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:
* <code>
* $query->filterByPosition(1234); // WHERE position = 1234
* $query->filterByPosition(array(12, 34)); // WHERE position IN (12, 34)
* $query->filterByPosition(array('min' => 12)); // WHERE position > 12
* </code>
*
* @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
*

View File

@@ -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;

View File

@@ -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:
* <code>
* $query->filterByPosition(1234); // WHERE position = 1234
* $query->filterByPosition(array(12, 34)); // WHERE position IN (12, 34)
* $query->filterByPosition(array('min' => 12)); // WHERE position > 12
* </code>
*
* @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
*

View File

@@ -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;
}
/**
*

View File

@@ -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');
}

View File

@@ -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');
}

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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`)

View File

@@ -589,7 +589,8 @@
<column name="code" size="45" type="VARCHAR" />
<column name="symbol" size="45" type="VARCHAR" />
<column name="rate" type="FLOAT" />
<column name="by_default" type="TINYINT" />
<column name="by_default" type="TINYINT" />
<column name="position" type="INTEGER" />
<behavior name="timestampable" />
<behavior name="i18n">
<parameter name="i18n_columns" value="name" />

View File

@@ -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);

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -16,10 +16,10 @@
<div class="row-fluid">
<div class="span12">
<div class="general-block-decorator">
<table class="table table-striped">
<table class="table table-striped table-condensed">
<caption>
{* 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'}
<a class="btn btn-primary btn-add-item" title="{intl l='Add a new category'}" href="{url path="admin/catalog/category/create/{$cat_id|default:0}"}">
{loop type="auth" name="can_create" context="admin" roles="ADMIN" permissions="admin.category.create"}
<a class="btn btn-primary btn-add-item" title="{intl l='Add a new category'}" href="#add_category_dialog" data-toggle="modal">
<i class="icon-plus-sign icon-white"></i>
</a>
{/loop}
</caption>
{ifloop rel="category_list"}
@@ -48,9 +50,9 @@
</thead>
<tbody>
{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"}
<tr>
<td class="object-title"><a href="{url path="admin/catalog/category/browse/$ID"}" title="{intl l='Browse this category'}">{$TITLE}</a></td>
<td class="object-title"><a href="{url path='admin/catalog/category' id="$ID" action='browse'}" title="{intl l='Browse this category'}">{$TITLE}</a></td>
{module_include location='category_list_row'}
@@ -59,15 +61,27 @@
</td>
<td>
<a href="{url path='admin/catalog/category/positionUp/{$ID}'}"><i class="icon-arrow-up"></i></a>
<span class="object_classement_editable" data-action="changeCategoryPosition" data-name="category_id" data-id="{$ID}">{$POSITION}</span>
<a href="{url path='admin/catalog/category/positionDown/{$ID}'}"><i class="icon-arrow-down"></i></a>
{loop type="auth" name="can_change" context="admin" roles="ADMIN" permissions="admin.category.edit"}
<a href="{url path='admin/catalog/category' id="{$ID}" action='positionUp'}"><i class="icon-arrow-up"></i></a>
<span class="object_classement_editable" data-action="changeCategoryPosition" data-name="category_id" data-id="{$ID}">{$POSITION}</span>
<a href="{url path='admin/catalog/category' id="{$ID}" action='positionDown'}"><i class="icon-arrow-down"></i></a>
{/loop}
{elseloop rel="can_change"}
{$POSITION}
{/elseloop}
</td>
<td>
<a class="btn btn-mini" title="{intl l='Browse this category'}" href="{url path="admin/catalog/category/browse/{$ID}"}"><i class="icon-folder-open"></i></a>
<a class="btn btn-mini" title="{intl l='Edit this category'}" href="{url path="admin/catalog/category/edit/{$ID}"}"><i class="icon-edit"></i></a>
<a class="btn btn-mini category-delete" title="{intl l='Delete this category and all its contents'}" href="{url path='admin/catalog/category/delete/{$ID}'}"><i class="icon-trash"></i></a>
<a class="btn btn-mini" title="{intl l='Browse this category'}" href="{url path='admin/catalog/category' id="$ID" action='browse'}"><i class="icon-folder-open"></i></a>
{loop type="auth" name="can_change" context="admin" roles="ADMIN" permissions="admin.category.edit"}
<a class="btn btn-mini" title="{intl l='Edit this category'}" href="{url path='admin/catalog/category' id="$ID" action='edit'}"><i class="icon-edit"></i></a>
{/loop}
{loop type="auth" name="can_delete" context="admin" roles="ADMIN" permissions="admin.category.delete"}
<a class="btn btn-mini category-delete" title="{intl l='Delete this category and all its contents'}" href="#delete_category_dialog" data-id="{$ID}" data-toggle="modal"><i class="icon-trash"></i></a>
{/loop}
</td>
</tr>
{/loop}
@@ -77,7 +91,17 @@
{elseloop rel="category_list"}
<thead>
<tr>
<td class="message"><div class="alert alert-info">{intl l="This category has no sub-categories. To create a new one, click the + button above."}</div></td>
<td class="message">
<div class="alert alert-info">
{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}
</div>
</td>
</tr>
</thead>
{/elseloop}
@@ -89,10 +113,10 @@
<div class="row-fluid">
<div class="span12">
<div class="general-block-decorator">
<table class="table table-striped">
<table class="table table-striped table-condensed">
<caption>
{* 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 @@
<tbody>
{loop name="product_list" type="product" category="{$current_category_id}" order="manual"}
<tr>
<td><a href="{url path="admin/catalog/product/edit/$ID"}" title="{intl l='Edit this product'}">Image !</a></td>
<td><a href="{url path='admin/catalog/product' id="$ID" action='edit'}" title="{intl l='Edit this product'}">Image !</a></td>
<td class="object-title"><a href="{url path="admin/catalog/product/edit/$ID"}" title="{intl l='Edit this product'}">{$TITLE}</a></td>
<td class="object-title"><a href="{url path='admin/catalog/product' id="$ID" action='edit'}" title="{intl l='Edit this product'}">{$TITLE}</a></td>
{module_include location='product_list_row'}
@@ -135,14 +159,14 @@
</td>
<td>
<a href="{url path='admin/catalog/product/positionUp/{$ID}'}"><i class="icon-arrow-up"></i></a>
<a href="{url path='admin/catalog/product' id="$ID" action='positionUn'}"><i class="icon-arrow-up"></i></a>
<span class="object_classement_editable" data-action="changeProductPosition" data-name="product_id" data-id="{$ID}">{$POSITION}</span>
<a href="{url path='admin/catalog/product/positionDown/{$ID}'}"><i class="icon-arrow-down"></i></a>
<a href="{url path='admin/catalog/product' id="$ID" action='positionDown'}"><i class="icon-arrow-down"></i></a>
</td>
<td>
<a class="btn btn-mini" title="{intl l='Edit this category'}" href="{url path="admin/catalog/product/edit/{$ID}"}"><i class="icon-edit"></i></a>
<a class="btn btn-mini product-delete" title="{intl l='Delete this product'}" href="{url path='admin/catalog/product/delete/{$ID}'}"><i class="icon-trash"></i></a>
<a class="btn btn-mini" title="{intl l='Edit this category'}" href="{url path='admin/catalog/product' id="$ID" action='edit'}"><i class="icon-edit"></i></a>
<a class="btn btn-mini product-delete" title="{intl l='Delete this product'}" href="{url path='admin/catalog/product' id="$ID" action='delete'}"><i class="icon-trash"></i></a>
</td>
</tr>
{/loop}
@@ -165,6 +189,40 @@
</div>
</div>
{include file="includes/add-category-dialog.html"}
{include file="includes/delete-category-dialog.html"}
{include file='includes/js.inc.html'}
<script>
$(function() {
{* display the form creation dialog if it contains errors *}
{form name="thelia.admin.category.creation"}
{if #form_error}
$('#add_category_dialog').modal();
{/if}
{/form}
{* Always reset dialog on close *}
$('#add_category_dialog').on('hidden',function() {
// Hide error message
$('#add_category_dialog_error').remove();
// Clear error status
$("#add_category_dialog .error").removeClass('error');
// Empty field values
$("#add_category_dialog input[type=text]").val('');
});
{* Set the proper category ID in the delete confirmation dialog *}
$(document).on("click", ".category-delete", function () {
$('#'+'delete-category-id').val($(this).data('id'));
});
})
</script>
{include file='includes/footer.inc.html'}

View File

@@ -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 @@
<div class="span12 general-block-decorator">
<div class="row-fluid">
<div class="span7 title">
{if $action == 'create'}
{intl l='Create a new category'}
{else}
{intl l='Edit category'}
{/if}
{intl l='Edit category'}
</div>
<div class="span5 actions">
<button class="btn btn-primary" title="{intl l='Save and stay on this page'}">{intl l='Save'} <i class="icon icon-white icon-ok"></i></button>
<button class="btn btn-info" title="{intl l='Save and close'}">{intl l='Save'} <i class="icon icon-remove icon-white"></i></button>
{if $action != 'create'}
<button class="btn" title="{intl l='Edit previous category'}"><i class="icon icon-arrow-left"></i></button>
<button class="btn" title="{intl l='Preview category page'}"><i class="icon icon-eye-open"></i></button>
<button class="btn" title="{intl l='Edit next category'}"><i class="icon icon-arrow-right"></i></button>
{/if}
<button class="btn" title="{intl l='Edit previous category'}"><i class="icon icon-arrow-left"></i></button>
<button class="btn" title="{intl l='Preview category page'}"><i class="icon icon-eye-open"></i></button>
<button class="btn" title="{intl l='Edit next category'}"><i class="icon icon-arrow-right"></i></button>
</div>
</div>
<div class="tabbable">
<ul class="nav nav-tabs" id="tabbed_menu">
<ul class="nav nav-tabs admin-tabs" id="tabbed_menu">
<li class="active">
<a href="#general_description">{intl l="General description"}</a>
</li>
<li>
<a href="#details">{intl l="Details"}</a>
</li>
@@ -57,9 +46,13 @@
</ul>
<div class="tab-content">
<div class="tab-pane active" id="general_description">
<div class="tab-pane active form-container" id="general_description">
<form class="form-horizontal span12">
<fieldset>
{include file="includes/inner-form-toolbar.html"}
<div class="row-fluid">
<div class="span12">
<div class="control-group">
@@ -133,7 +126,12 @@
<div class="controls">
<select required="required" name="parent" class="input-block-level">
<option value="">{intl l="Choose a category"}</option>
<option value="0">{intl l="Top level"}</option>
{loop name="cat-parent" type="category-tree" visible="*" category="0" exclude="{$current_category_id}"}
<option value="#ID" style="padding-left: {3 + $LEVEL * 20}px" {if $parent_category_id == $ID}selected="selected"{/if}>{$TITLE}</option>
{/loop}
</select>
</div>
</div>
@@ -160,19 +158,22 @@
</div>
<div class="tab-pane" id="details">
<p>Infos générales</p>
<p>Détails divers</p>
</div>
<div class="tab-pane" id="images">
<p>Images</p>
</div>
<div class="tab-pane" id="documents">
<p>Documents</p>
</div>
<div class="tab-pane" id="modules">
<p>Modules</p>
</div>
</div>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,10 @@
{$page_title={intl l='AN error occured'}}
{include file='includes/header.inc.html'}
<div id="wrapper" class="container">
<h1>{intl l="Oops! An Error Occurred"}</h1>
<p>{$error_message}</p>
</div>
{include file='includes/footer.inc.html'}

View File

@@ -0,0 +1,66 @@
{* Adding a new Category *}
<div class="modal hide fade" id="add_category_dialog" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h3>{intl l="Create a new category"}</h3>
</div>
{form name="thelia.admin.category.creation"}
<form method="POST" action="{url path='/admin/catalog/category'}" {form_enctype form=$form}>
{* the action processed by the controller *}
<input type="hidden" name="action" value="create" />
{form_hidden_fields form=$form}
{form_field form=$form field='parent'}
<input type="hidden" name="{$name}" value="{$current_category_id}" />
{/form_field}
{form_field form=$form field='success_url'}
{* on success, redirect to category change page. _ID_ is replaced with the ID of the created category (see Thelia\Action\Category.php) *}
<input type="hidden" name="{$name}" value="{url path='admin/catalog/category' id="_ID_" action='edit'}" />
{/form_field}
<div class="modal-body">
{if #form_error}<div class="alert alert-block alert-error" id="add_category_dialog_error">#form_error_message</div>{/if}
<div class="control-group">
<label class="control-label">
{intl l='Category Title *'}
</label>
<div class="controls">
{loop type="lang" name="default-lang" default_only="1"}
{form_field form=$form field='locale'}
<input type="hidden" name="{$name}" value="{$LOCALE}" />
{/form_field}
<div class="input-append input-block-level">
{form_field form=$form field='title'}
<span {if $error}class="error"{/if}>
<input type="text" required="required" name="{$name}" value="{$value}" title="{intl l='Category title'}" placeholder="{intl l='Category title'}" class="input-block-level">
</span>
{/form_field}
<span class="add-on"><img src="{image file="../assets/img/flags/{$CODE}.gif"}" alt="{intl l=$TITLE}" /></span>
</div>
<div class="help-block">{intl l="Enter here the category title in the default language ($TITLE)"}</div>
{/loop}
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn" data-dismiss="modal" aria-hidden="true">{intl l="Cancel"}</button>
<button type="submit" class="btn btn-primary">{intl l="Create this category"}</button>
</div>
</form>
{/form}
</div>

View File

@@ -1,16 +1,18 @@
{* Breadcrumb for categories browsing and editing *}
<li><a href="{url path='admin/home'}">Home</a> <span class="divider">/</span></li>
<li><a href="{url path='admin/catalog'}">Catalog</a>
{ifloop rel="category_path"}
<span class="divider">/</span></li>
{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}
<li class="active">
{if $action == 'edit'}
{intl l='Editing %cat' cat="{$TITLE}"}
{else}
{$TITLE} <a href="{url path="admin/catalog/category/edit/$ID"}" title="{intl l='Edit this category'}">{intl l="(edit)"}</a>
{$TITLE} <a href="{url path="admin/catalog/category/edit/$ID"}" title="{intl l='Edit this category'}">{intl l="(edit)"}</a>
{/if}
</li>
{else}
@@ -18,11 +20,7 @@
{/if}
{/loop}
{/ifloop}
{elseloop rel="category_path"}
{if $action == 'create'}<span class="divider">/</span>{/if}</li>
{/elseloop}
{if $action == 'create'}
<li class="active">{intl l='Create a new category'}</li>
{/if}
</li>
{/elseloop}

View File

@@ -0,0 +1,42 @@
{* Adding a new Category *}
<div class="modal hide fade" id="delete_category_dialog" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h3>{intl l="Delete a category"}</h3>
</div>
{form name="thelia.admin.category.deletion"}
<form method="POST" action="{url path='/admin/catalog/category'}" {form_enctype form=$form}>
{* the action processed by the controller *}
<input type="hidden" name="action" value="delete" />
{form_hidden_fields form=$form}
{form_field form=$form field='id'}
<input type="hidden" name="{$name}" id="delete-category-id" value="" />
{/form_field}
{form_field form=$form field='success_url'}
{* on success, redirect to catalog. _ID_ is replaced with the ID of the deleted category parent id (see Thelia\Action\Category.php) *}
<input type="hidden" name="{$name}" value="{url path='admin/catalog/category' id="_ID_" action='browse'}" />
{/form_field}
<div class="modal-body">
{if #form_error}<div class="alert alert-block alert-error" id="add_category_dialog_error">#form_error_message</div>{/if}
<p>{intl l="Delete this category and all its contents ?"}</p>
</div>
<div class="modal-footer">
<button type="button" class="btn" data-dismiss="modal" aria-hidden="true">{intl l="No"}</button>
<button type="submit" class="btn btn-primary">{intl l="Yes"}</button>
</div>
</form>
{/form}
</div>

View File

@@ -1,7 +1,7 @@
{module_include location='before_footer'}
<hr />
<footer class="modal-footer">
<footer class="footer">
<div class="container">
<p>{intl l='&copy; Thelia 2013'}
- <a href="http://www.openstudio.fr/" target="_blank">{intl l='Édité par OpenStudio'}</a>

View File

@@ -0,0 +1,27 @@
<div class="row-fluid inner-toolbar">
<div class="span6 inner-actions">
{* 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}
<ul class="nav nav-pills">
{loop name="lang_list" type="lang" default_only={$default_only}}
<li {if $IS_DEFAULT}class="active"{/if}>
<a href="#" title="{intl l="Edit information for %lng" lng=$TITLE}">
<img src="{image file="../assets/img/flags/{$CODE}.gif"}" alt="{intl l=$TITLE}" />
</a>
</li>
{/loop}
</ul>
</div>
<div class="span6 inner-actions">
<button class="btn btn-primary" title="{intl l='Save'}">{intl l='Save'} <i class="icon icon-white icon-ok"></i></button>
<button class="btn btn-info" title="{intl l='Save and close'}">{intl l='Save and close'} <i class="icon icon-remove icon-white"></i></button>
</div>
</div>

View File

@@ -13,7 +13,7 @@
<div class="hero-unit">
<h1>{intl l='Thelia Back Office'}</h1>
{form name="thelia.admin.login" success_url="home" error_url="login"}
{form name="thelia.admin.login"}
<form action="{url path='/admin/checklogin'}" method="post" class="well form-inline" {form_enctype form=$form}>
{if #form_error}<div class="alert alert-error">#form_error_message</div>{/if}

View File

@@ -4,7 +4,7 @@
{* We use $INDEX_PAGE as form action to avoid mixing post and get data *}
<form action="{$INDEX_PAGE}" method="post" {form_enctype form=$form}>
{*
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
*}
<input type="hidden" name="action" value="createCustomer" /> {* the action triggered by this form *}