Merge branch 'master' into cart

This commit is contained in:
Manuel Raynaud
2013-08-07 09:44:34 +02:00
40 changed files with 1023 additions and 127 deletions

View File

@@ -6,11 +6,11 @@
* Functions needed for Thelia bootstrap * Functions needed for Thelia bootstrap
*/ */
define('THELIA_ROOT' , rtrim(realpath(__DIR__ .'/../'),'/') . "/"); define('THELIA_ROOT' , rtrim(realpath(__DIR__ .'/../'),'/') . "/");
define('THELIA_LOCAL_DIR' , THELIA_ROOT . '/local/'); define('THELIA_LOCAL_DIR' , THELIA_ROOT . 'local/');
define('THELIA_CONF_DIR' , THELIA_LOCAL_DIR . 'config/'); define('THELIA_CONF_DIR' , THELIA_LOCAL_DIR . 'config/');
define('THELIA_MODULE_DIR' , THELIA_LOCAL_DIR . 'modules/'); define('THELIA_MODULE_DIR' , THELIA_LOCAL_DIR . 'modules/');
define('THELIA_WEB_DIR' , THELIA_ROOT . '/web/'); define('THELIA_WEB_DIR' , THELIA_ROOT . 'web/');
define('THELIA_TEMPLATE_DIR' , THELIA_ROOT . '/templates/'); define('THELIA_TEMPLATE_DIR' , THELIA_ROOT . 'templates/');
define('DS', DIRECTORY_SEPARATOR); define('DS', DIRECTORY_SEPARATOR);
$loader = require __DIR__ . "/vendor/autoload.php"; $loader = require __DIR__ . "/vendor/autoload.php";

View File

@@ -25,6 +25,7 @@ namespace Thelia\Action;
use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Thelia\Core\Event\ActionEvent; use Thelia\Core\Event\ActionEvent;
use Thelia\Core\Event\CustomerEvent;
use Thelia\Core\Event\TheliaEvents; use Thelia\Core\Event\TheliaEvents;
use Thelia\Form\BaseForm; use Thelia\Form\BaseForm;
use Thelia\Form\CustomerCreation; use Thelia\Form\CustomerCreation;
@@ -88,8 +89,8 @@ class Customer implements EventSubscriberInterface
$data["password"], $data["password"],
$request->getSession()->getLang() $request->getSession()->getLang()
); );
$customerEvent = new CustomerEvent($customer);
$event->getDispatcher()->dispatch(TheliaEvents::AFTER_CREATECUSTOMER, $event); $event->getDispatcher()->dispatch(TheliaEvents::AFTER_CREATECUSTOMER, $customerEvent);
// Connect the newly created user,and redirect to the success URL // Connect the newly created user,and redirect to the success URL
$this->processSuccessfulLogin($event, $customer, $customerCreationForm, true); $this->processSuccessfulLogin($event, $customer, $customerCreationForm, true);
@@ -136,7 +137,8 @@ class Customer implements EventSubscriberInterface
$customer = CustomerQuery::create()->findPk(1); $customer = CustomerQuery::create()->findPk(1);
try { try {
$event->getDispatcher()->dispatch(TheliaEvents::BEFORE_CHANGECUSTOMER, $event); $customerEvent = new CustomerEvent($customer);
$event->getDispatcher()->dispatch(TheliaEvents::BEFORE_CHANGECUSTOMER, $customerEvent);
$data = $form->getData(); $data = $form->getData();
@@ -153,7 +155,8 @@ class Customer implements EventSubscriberInterface
$data["country"] $data["country"]
); );
$event->getDispatcher()->dispatch(TheliaEvents::AFTER_CHANGECUSTOMER, $event); $customerEvent->customer = $customer;
$event->getDispatcher()->dispatch(TheliaEvents::AFTER_CHANGECUSTOMER, $customerEvent);
// Update the logged-in user, and redirect to the success URL (exits) // 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. // We don-t send the login event, as the customer si already logged.

View File

@@ -27,6 +27,12 @@ class AdminController extends BaseAdminController {
public function indexAction() public function indexAction()
{ {
return $this->render("home.html"); return $this->render("home");
}
public function processAction()
{
echo "not yet coded !";
exit();
} }
} }

View File

@@ -50,10 +50,23 @@ use Thelia\Core\Event\ActionEvent;
class BaseAdminController extends ContainerAware class BaseAdminController extends ContainerAware
{ {
const TEMPLATE_404 = "404.html"; const TEMPLATE_404 = "404";
protected function undefinedAction() public function processTemplateAction($template)
{ {
try {
if (! empty($template)) {
// If we have a view in the URL, render this view
return $this->render($template);
}
else if (null != $view = $this->getRequest()->get('view')) {
return $this->render($view);
}
}
catch (\Exception $ex) {
// Nothing special
}
return new Response($this->renderRaw(self::TEMPLATE_404), 404); return new Response($this->renderRaw(self::TEMPLATE_404), 404);
} }
@@ -81,6 +94,9 @@ class BaseAdminController extends ContainerAware
*/ */
protected function renderRaw($templateName, $args = array()) protected function renderRaw($templateName, $args = array())
{ {
// Add the template standard extension
$templateName .= '.html';
$session = $this->getSession(); $session = $this->getSession();
$args = array_merge($args, array( $args = array_merge($args, array(
@@ -158,7 +174,7 @@ class BaseAdminController extends ContainerAware
} }
/** /**
* @return a ParserInterface instance parser * @return a ParserInterfac instance parser
*/ */
protected function getParser() protected function getParser()
{ {

View File

@@ -37,7 +37,7 @@ class SessionController extends BaseAdminController {
public function showLoginAction() public function showLoginAction()
{ {
return $this->render("login.html"); return $this->render("login");
} }
public function checkLogoutAction() public function checkLogoutAction()
@@ -100,6 +100,6 @@ class SessionController extends BaseAdminController {
$this->getParserContext()->setErrorForm($adminLoginForm); $this->getParserContext()->setErrorForm($adminLoginForm);
// Display the login form again // Display the login form again
return $this->render("login.html"); return $this->render("login");
} }
} }

View File

@@ -16,6 +16,7 @@
<loop class="Thelia\Core\Template\Loop\FeatureValue" name="feature_value"/> <loop class="Thelia\Core\Template\Loop\FeatureValue" name="feature_value"/>
<loop class="Thelia\Core\Template\Loop\Order" name="order"/> <loop class="Thelia\Core\Template\Loop\Order" name="order"/>
<loop class="Thelia\Core\Template\Loop\OrderStatus" name="order-status"/> <loop class="Thelia\Core\Template\Loop\OrderStatus" name="order-status"/>
<loop class="Thelia\Core\Template\Loop\CategoryPath" name="category-path"/>
<loop class="Thelia\Core\Template\Loop\Product" name="product"/> <loop class="Thelia\Core\Template\Loop\Product" name="product"/>
<loop class="Thelia\Core\Template\Loop\Feed" name="feed"/> <loop class="Thelia\Core\Template\Loop\Feed" name="feed"/>
<loop class="Thelia\Core\Template\Loop\Title" name="title"/> <loop class="Thelia\Core\Template\Loop\Title" name="title"/>

View File

@@ -24,8 +24,22 @@
<default key="_controller">Thelia\Admin\Controller\SessionController::checkLoginAction</default> <default key="_controller">Thelia\Admin\Controller\SessionController::checkLoginAction</default>
</route> </route>
<route id="admin.undefined" path="/admin/{everything}">
<default key="_controller">Thelia\Admin\Controller\AdminController::undefinedAction</default> <!-- Route to the catalog controller (process category browsing) -->
<requirement key="everything">.*</requirement>
<route id="admin.catalog" path="/admin/catalog">
<default key="_controller">Thelia\Admin\Controller\CategoryController::indexAction</default>
</route>
<route id="admin.category" path="/admin/catalog/category/{action}">
<default key="_controller">Thelia\Admin\Controller\CategoryController::processAction</default>
<requirement key="action">.*</requirement>
</route>
<!-- The default route, to display a template -->
<route id="admin.processTemplate" path="/admin/{template}">
<default key="_controller">Thelia\Admin\Controller\AdminController::processTemplateAction</default>
<requirement key="template">.*</requirement>
</route> </route>
</routes> </routes>

View File

@@ -0,0 +1,38 @@
<?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\Customer;
class CustomerEvent extends InternalEvent {
public $customer;
public function __construct(Customer $customer)
{
$this->customer = $customer;
}
}

View File

@@ -117,6 +117,9 @@ abstract class BaseLoop
$faultActor = array(); $faultActor = array();
$faultDetails = array(); $faultDetails = array();
$loopType = isset($nameValuePairs['type']) ? $nameValuePairs['type'] : "undefined";
$loopName = isset($nameValuePairs['name']) ? $nameValuePairs['name'] : "undefined";
while (($argument = $this->args->current()) !== false) { while (($argument = $this->args->current()) !== false) {
$this->args->next(); $this->args->next();
@@ -125,17 +128,17 @@ abstract class BaseLoop
/* check if mandatory */ /* check if mandatory */
if($value === null && $argument->mandatory) { if($value === null && $argument->mandatory) {
$faultActor[] = $argument->name; $faultActor[] = $argument->name;
$faultDetails[] = sprintf('"%s" parameter is missing', $argument->name); $faultDetails[] = sprintf('"%s" parameter is missing in loop type: %s, name: %s', $argument->name, $loopType, $loopName);
} }
else if($value === '' && !$argument->empty) { else if($value === '' && !$argument->empty) {
/* check if empty */ /* check if empty */
$faultActor[] = $argument->name; $faultActor[] = $argument->name;
$faultDetails[] = sprintf('"%s" parameter cannot be empty', $argument->name); $faultDetails[] = sprintf('"%s" parameter cannot be empty in loop type: %s, name: %s', $argument->name, $loopType, $loopName);
} }
else if($value !== null && !$argument->type->isValid($value)) { else if($value !== null && !$argument->type->isValid($value)) {
/* check type */ /* check type */
$faultActor[] = $argument->name; $faultActor[] = $argument->name;
$faultDetails[] = sprintf('Invalid value for "%s" argument', $argument->name); $faultDetails[] = sprintf('Invalid value for "%s" argument in loop type: %s, name: %s', $argument->name, $loopType, $loopName);
} }
else { else {
/* set default */ /* set default */

View File

@@ -30,6 +30,8 @@ class LoopResultRow
public function set($key, $value) public function set($key, $value)
{ {
$this->substitution[$key] = $value === null ? '' : $value; $this->substitution[$key] = $value === null ? '' : $value;
return $this;
} }
public function get($key) public function get($key)

View File

@@ -168,14 +168,25 @@ class Category extends BaseLoop
if ($this->not_empty && $category->countAllProducts() == 0) continue; if ($this->not_empty && $category->countAllProducts() == 0) continue;
$loopResultRow = new LoopResultRow(); $loopResultRow = new LoopResultRow();
$loopResultRow->set("TITLE",$category->getTitle());
$loopResultRow->set("CHAPO", $category->getChapo()); $loopResultRow
$loopResultRow->set("DESCRIPTION", $category->getDescription()); ->set("ID", $category->getId())
$loopResultRow->set("POSTSCRIPTUM", $category->getPostscriptum()); ->set("TITLE",$category->getTitle())
$loopResultRow->set("PARENT", $category->getParent()); ->set("CHAPO", $category->getChapo())
$loopResultRow->set("ID", $category->getId()); ->set("DESCRIPTION", $category->getDescription())
$loopResultRow->set("URL", $category->getUrl()); ->set("POSTSCRIPTUM", $category->getPostscriptum())
$loopResultRow->set("PRODUCT_COUNT", $category->countChild()); ->set("PARENT", $category->getParent())
->set("URL", $category->getUrl())
->set("PRODUCT_COUNT", $category->countChild())
->set("VISIBLE", $category->getVisible() ? "1" : "0")
->set("POSITION", $category->getPosition())
->set("CREATE_DATE", $category->getCreatedAt())
->set("UPDATE_DATE", $category->getUpdatedAt())
->set("VERSION", $category->getVersion())
->set("VERSION_DATE", $category->getVersionCreatedAt())
->set("VERSION_AUTHOR", $category->getVersionCreatedBy())
;
$loopResult->addRow($loopResultRow); $loopResult->addRow($loopResultRow);
} }

View File

@@ -87,7 +87,7 @@ class FeatureValue extends BaseLoop
$search->filterByProductId($product, Criteria::EQUAL); $search->filterByProductId($product, Criteria::EQUAL);
$featureAvailable = $this->geFeature_available(); $featureAvailable = $this->getFeature_available();
if (null !== $featureAvailable) { if (null !== $featureAvailable) {
$search->filterByFeatureAvId($featureAvailable, Criteria::IN); $search->filterByFeatureAvId($featureAvailable, Criteria::IN);

View File

@@ -86,7 +86,7 @@ class Product extends BaseLoop
new TypeCollection( new TypeCollection(
new Type\EnumListType(array('alpha', 'alpha_reverse', /*'min_price', 'max_price',*/ 'manual', 'manual_reverse', 'ref', /*'promo', 'new',*/ 'random', 'given_id')) new Type\EnumListType(array('alpha', 'alpha_reverse', /*'min_price', 'max_price',*/ 'manual', 'manual_reverse', 'ref', /*'promo', 'new',*/ 'random', 'given_id'))
), ),
'manual' 'alpha'
), ),
Argument::createIntListTypeArgument('exclude'), Argument::createIntListTypeArgument('exclude'),
Argument::createIntListTypeArgument('exclude_category'), Argument::createIntListTypeArgument('exclude_category'),
@@ -271,12 +271,12 @@ class Product extends BaseLoop
$search->orderBy('real_price', Criteria::DESC); $search->orderBy('real_price', Criteria::DESC);
break;*/ break;*/
case "manual": case "manual":
if(null === $this->category || count($this->category) != 1) if(null === $category || count($category) != 1)
throw new \InvalidArgumentException('Manual order cannot be set without single category argument'); throw new \InvalidArgumentException('Manual order cannot be set without single category argument');
$search->orderByPosition(Criteria::ASC); $search->orderByPosition(Criteria::ASC);
break; break;
case "manual_reverse": case "manual_reverse":
if(null === $this->category || count($this->category) != 1) if(null === $category || count($category) != 1)
throw new \InvalidArgumentException('Manual order cannot be set without single category argument'); throw new \InvalidArgumentException('Manual order cannot be set without single category argument');
$search->orderByPosition(Criteria::DESC); $search->orderByPosition(Criteria::DESC);
break; break;
@@ -395,17 +395,20 @@ class Product extends BaseLoop
foreach ($products as $product) { foreach ($products as $product) {
$loopResultRow = new LoopResultRow(); $loopResultRow = new LoopResultRow();
$loopResultRow->set("ID", $product->getId());
$loopResultRow->set("REF",$product->getRef()); $loopResultRow->set("ID", $product->getId())
$loopResultRow->set("TITLE",$product->getTitle()); ->set("REF",$product->getRef())
$loopResultRow->set("CHAPO", $product->getChapo()); ->set("TITLE",$product->getTitle())
$loopResultRow->set("DESCRIPTION", $product->getDescription()); ->set("CHAPO", $product->getChapo())
$loopResultRow->set("POSTSCRIPTUM", $product->getPostscriptum()); ->set("DESCRIPTION", $product->getDescription())
//$loopResultRow->set("PRICE", $product->getPrice()); ->set("POSTSCRIPTUM", $product->getPostscriptum())
//$loopResultRow->set("PROMO_PRICE", $product->getPrice2()); ->set("PRICE", $product->getPrice())
//$loopResultRow->set("WEIGHT", $product->getWeight()); ->set("PROMO_PRICE", $product->getPrice2())
//$loopResultRow->set("PROMO", $product->getPromo()); ->set("WEIGHT", $product->getWeight())
//$loopResultRow->set("NEW", $product->getNewness()); ->set("PROMO", $product->getPromo())
->set("NEW", $product->getNewness())
->set("POSITION", $product->getPosition())
;
$loopResult->addRow($loopResultRow); $loopResult->addRow($loopResultRow);
} }

View File

@@ -51,6 +51,48 @@ abstract class AbstractSmartyPlugin
return array(); return array();
} }
/**
* Get a function or block parameter value, and normalize it, trimming balnks and
* making it lowercase
*
* @param array $params the parameters array
* @param mixed $name as single parameter name, or an array of names. In this case, the first defined parameter is returned. Use this for aliases (context, ctx, c)
* @param mixed $default the defaut value if parameter is missing (default to null)
* @return mixed the parameter value, or the default value if it is not found.
*/
public function getNormalizedParam($params, $name, $default = null)
{
$value = $this->getParam($params, $name, $default);
if (is_string($value)) $value = strtolower(trim($value));
return $value;
}
/**
* Get a function or block parameter value
*
* @param array $params the parameters array
* @param mixed $name as single parameter name, or an array of names. In this case, the first defined parameter is returned. Use this for aliases (context, ctx, c)
* @param mixed $default the defaut value if parameter is missing (default to null)
* @return mixed the parameter value, or the default value if it is not found.
*/
public function getParam($params, $name, $default = null)
{
if (is_array($name)) {
foreach($name as $test) {
if (isset($params[$test])) {
return $params[$test];
}
}
}
else if (isset($params[$name])) {
return $params[$name];
}
return $default;
}
/** /**
* @return an array of SmartyPluginDescriptor * @return an array of SmartyPluginDescriptor
*/ */

View File

@@ -78,13 +78,13 @@ class DataAccessFunctions extends AbstractSmartyPlugin
*/ */
protected function userDataAccess($objectLabel, $context, $params) protected function userDataAccess($objectLabel, $context, $params)
{ {
$attribute = $params['attr']; $attribute = $this->getNormalizedParam($params, array('attribute', 'attrib', 'attr'));
if (! empty($attribute)) { if (! empty($attribute)) {
$user = $this->securityContext->setContext($context)->getUser(); $user = $this->securityContext->setContext($context)->getUser();
if (null != $user) { if (null != $user) {
$getter = sprintf("get%s", ucfirst(strtolower($attribute))); $getter = sprintf("get%s", ucfirst($attribute));
if (method_exists($user, $getter)) { if (method_exists($user, $getter)) {
return $user->$getter(); return $user->$getter();

View File

@@ -85,11 +85,13 @@ class Form extends AbstractSmartyPlugin
{ {
if ($repeat) { if ($repeat) {
if (empty($params['name'])) { $name = $this->getParam($params, 'name');
if (null == $name) {
throw new \InvalidArgumentException("Missing 'name' parameter in form arguments"); throw new \InvalidArgumentException("Missing 'name' parameter in form arguments");
} }
$instance = $this->createInstance($params['name']); $instance = $this->createInstance($name);
// Check if parser context contains our form // Check if parser context contains our form
$errorForm = $this->parserContext->getErrorForm(); $errorForm = $this->parserContext->getErrorForm();
@@ -212,10 +214,11 @@ class Form extends AbstractSmartyPlugin
protected function getFormFieldView($params) { protected function getFormFieldView($params) {
$instance = $this->getInstanceFromParams($params); $instance = $this->getInstanceFromParams($params);
if (! isset($params['field'])) $fieldName = $this->getParam($params, 'field');
if (null == $fieldName)
throw new \InvalidArgumentException("'field' parameter is missing"); throw new \InvalidArgumentException("'field' parameter is missing");
$fieldName = $params['field'];
if (empty($instance->getView()[$fieldName])) if (empty($instance->getView()[$fieldName]))
throw new \InvalidArgumentException(sprintf("Field name '%s' not found in form %s", $fieldName, $instance->getName())); throw new \InvalidArgumentException(sprintf("Field name '%s' not found in form %s", $fieldName, $instance->getName()));
@@ -225,12 +228,12 @@ class Form extends AbstractSmartyPlugin
protected function getInstanceFromParams($params) { protected function getInstanceFromParams($params) {
if (empty($params['form'])) { $instance = $this->getParam($params, 'form');
if (null == $instance) {
throw new \InvalidArgumentException("Missing 'form' parameter in form arguments"); throw new \InvalidArgumentException("Missing 'form' parameter in form arguments");
} }
$instance = $params["form"];
if (! $instance instanceof \Thelia\Form\BaseForm) { if (! $instance instanceof \Thelia\Form\BaseForm) {
throw new \InvalidArgumentException(sprintf("form parameter in form_field block must be an instance of throw new \InvalidArgumentException(sprintf("form parameter in form_field block must be an instance of
\Thelia\Form\BaseForm, instance of %s found", get_class($instance))); \Thelia\Form\BaseForm, instance of %s found", get_class($instance)));

View File

@@ -48,22 +48,25 @@ class Security extends AbstractSmartyPlugin
public function checkAuthFunction($params, &$smarty) public function checkAuthFunction($params, &$smarty)
{ {
// Context: 'front' or 'admin' // Context: 'front' or 'admin'
$context = strtolower(trim($params['context'])); $context = $this->getNormalizedParam($params, 'context');
$this->securityContext->setContext($context); $this->securityContext->setContext($context);
$roles = $this->_explode($params['roles']); $roles = $this->_explode($this->getParam($params, 'roles'));
$permissions = $this->_explode($params['permissions']); $permissions = $this->_explode($this->getParam($params, 'permissions'));
if (! $this->securityContext->isGranted($roles, $permissions)) { if (! $this->securityContext->isGranted($roles, $permissions)) {
$ex = new AuthenticationException( $ex = new AuthenticationException(
sprintf("User not granted for roles '%s', permissions '%s' in context '%s'.", sprintf("User not granted for roles '%s', permissions '%s' in context '%s'.",
implode(',', $roles), implode(',', $permissions), $context implode(',', $roles), implode(',', $permissions), $context
) )
); );
if (! empty($params['login_tpl'])) { $loginTpl = $this->getParam($params, 'login_tpl');
$ex->setLoginTemplate($params['login_tpl']);
if (null != $loginTpl) {
$ex->setLoginTemplate($loginTpl);
} }
throw $ex; throw $ex;
@@ -73,7 +76,7 @@ class Security extends AbstractSmartyPlugin
} }
/** /**
* Define the various smarty plugins hendled by this class * Define the various smarty plugins handled by this class
* *
* @return an array of smarty plugin descriptors * @return an array of smarty plugin descriptors
*/ */

View File

@@ -71,9 +71,11 @@ class TheliaLoop extends AbstractSmartyPlugin
/** /**
* Process the count function: executes a loop and return the number of items found * Process the count function: executes a loop and return the number of items found
*/ */
public function theliaCount($params, $template) { public function theliaCount($params, $template)
{
$type = $this->getParam($params, 'type');
if (empty($params['type'])) if (null == $type)
throw new \InvalidArgumentException("Missing 'type' parameter in count arguments"); throw new \InvalidArgumentException("Missing 'type' parameter in count arguments");
$loop = $this->createLoopInstance($params); $loop = $this->createLoopInstance($params);
@@ -97,13 +99,15 @@ class TheliaLoop extends AbstractSmartyPlugin
*/ */
public function theliaLoop($params, $content, $template, &$repeat) public function theliaLoop($params, $content, $template, &$repeat)
{ {
if (empty($params['name'])) $name = $this->getParam($params, 'name');
if (null == $name)
throw new \InvalidArgumentException("Missing 'name' parameter in loop arguments"); throw new \InvalidArgumentException("Missing 'name' parameter in loop arguments");
if (empty($params['type'])) $type = $this->getParam($params, 'type');
throw new \InvalidArgumentException("Missing 'type' parameter in loop arguments");
$name = $params['name']; if (null == $type)
throw new \InvalidArgumentException("Missing 'type' parameter in loop arguments");
if ($content === null) { if ($content === null) {
// Check if a loop with the same name exists in the current scope, and abort if it's the case. // Check if a loop with the same name exists in the current scope, and abort if it's the case.
@@ -116,8 +120,12 @@ class TheliaLoop extends AbstractSmartyPlugin
self::$pagination[$name] = null; self::$pagination[$name] = null;
$loopResults = $loop->exec(self::$pagination[$name]); $loopResults = $loop->exec(self::$pagination[$name]);
$this->loopstack[$name] = $loopResults; $this->loopstack[$name] = $loopResults;
// Pas de résultat ? la boucle est terminée, ne pas évaluer le contenu.
if ($loopResults->isEmpty()) $repeat = false;
} else { } else {
$loopResults = $this->loopstack[$name]; $loopResults = $this->loopstack[$name];
@@ -223,10 +231,10 @@ class TheliaLoop extends AbstractSmartyPlugin
*/ */
public function theliaPageLoop($params, $content, $template, &$repeat) public function theliaPageLoop($params, $content, $template, &$repeat)
{ {
if (empty($params['rel'])) $loopName = $this->getParam($params, 'rel');
throw new \InvalidArgumentException("Missing 'rel' parameter in page loop");
$loopName = $params['rel']; if (null == $loopName)
throw new \InvalidArgumentException("Missing 'rel' parameter in page loop");
// Find loop results in the current template vars // Find loop results in the current template vars
/* $loopResults = $template->getTemplateVars($loopName); /* $loopResults = $template->getTemplateVars($loopName);
@@ -274,11 +282,10 @@ class TheliaLoop extends AbstractSmartyPlugin
*/ */
protected function checkEmptyLoop($params, $template) protected function checkEmptyLoop($params, $template)
{ {
$loopName = $this->getParam($params, 'rel');
if (empty($params['rel'])) if (null == $loopName)
throw new \InvalidArgumentException("Missing 'rel' parameter in ifloop/elseloop arguments"); throw new \InvalidArgumentException("Missing 'rel' parameter in ifloop/elseloop arguments");
$loopName = $params['rel'];
if (! isset($this->loopstack[$loopName])) { if (! isset($this->loopstack[$loopName])) {
throw new \InvalidArgumentException("Loop $loopName is not defined."); throw new \InvalidArgumentException("Loop $loopName is not defined.");

View File

@@ -49,10 +49,10 @@ class Translation extends AbstractSmartyPlugin
$vars = array(); $vars = array();
foreach($params as $name => $value) { foreach($params as $name => $value) {
$vars["%$name"] = $value; if ($name != 'l') $vars["%$name"] = $value;
} }
return $this->translator->trans($params['l'], $vars); return $this->translator->trans($this->getParam($params, 'l'), $vars);
} }
/** /**

View File

@@ -47,7 +47,7 @@ class UrlGenerator extends AbstractSmartyPlugin
public function generateUrlFunction($params, &$smarty) public function generateUrlFunction($params, &$smarty)
{ {
// the path to process // the path to process
$path = trim($params['path']); $path = $this->getParam($params, 'path');
return URL::absoluteUrl($path, $this->getArgsFromParam($params)); return URL::absoluteUrl($path, $this->getArgsFromParam($params));
} }
@@ -59,19 +59,36 @@ class UrlGenerator extends AbstractSmartyPlugin
* @param unknown $smarty * @param unknown $smarty
* @return string no text is returned. * @return string no text is returned.
*/ */
public function generateViewUrlFunction($params, &$smarty) public function generateFrontViewUrlFunction($params, &$smarty)
{
return $this->generateViewUrlFunction($params, false);
}
/**
* Process administration view url generator function
*
* @param array $params
* @param unknown $smarty
* @return string no text is returned.
*/
public function generateAdminViewUrlFunction($params, &$smarty)
{
return $this->generateViewUrlFunction($params, true);
}
protected function generateViewUrlFunction($params, $forAdmin)
{ {
// the view name (without .html) // the view name (without .html)
$view = trim($params['view']); $view = $this->getParam($params,'view');
// the related action (optionale) // the related action (optionale)
$action = trim($params['action']); $action = $this->getParam($params, 'action');
$args = $this->getArgsFromParam($params); $args = $this->getArgsFromParam($params);
if (! empty($action)) $args['action'] = $action; if (! empty($action)) $args['action'] = $action;
return URL::viewUrl($view, $args); return $forAdmin ? URL::adminViewUrl($view, $args) : URL::viewUrl($view, $args);
} }
/** /**
@@ -83,14 +100,13 @@ class UrlGenerator extends AbstractSmartyPlugin
*/ */
private function getArgsFromParam($params) { private function getArgsFromParam($params) {
if (isset($params['args'])) $args = $this->getParam($params, array('arguments', 'args'));
return explode($params['args'], ',');
return array(); return $args !== null ? explode($args, ',') : array();
} }
/** /**
* Define the various smarty plugins hendled by this class * Define the various smarty plugins handled by this class
* *
* @return an array of smarty plugin descriptors * @return an array of smarty plugin descriptors
*/ */
@@ -98,7 +114,8 @@ class UrlGenerator extends AbstractSmartyPlugin
{ {
return array( return array(
new SmartyPluginDescriptor('function', 'url', $this, 'generateUrlFunction'), new SmartyPluginDescriptor('function', 'url', $this, 'generateUrlFunction'),
new SmartyPluginDescriptor('function', 'viewurl', $this, 'generateViewUrlFunction') new SmartyPluginDescriptor('function', 'viewurl', $this, 'generateFrontViewUrlFunction'),
new SmartyPluginDescriptor('function', 'admin_viewurl', $this, 'generateAdminViewUrlFunction')
); );
} }
} }

View File

@@ -0,0 +1,86 @@
<?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\Tests\Core\Template\Element;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Thelia\Core\HttpFoundation\Request;
use Thelia\Core\Security\SecurityContext;
use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage;
use Thelia\Core\HttpFoundation\Session\Session;
/**
*
* @author Etienne Roudeix <eroudeix@openstudio.fr>
*
*/
abstract class BaseLoopTestor extends \PHPUnit_Framework_TestCase
{
protected $request;
protected $dispatcher;
protected $securityContext;
protected $instance;
abstract public function getTestedClassName();
abstract public function getTestedInstance();
abstract public function getMandatoryArguments();
protected function getMethod($name) {
$class = new \ReflectionClass($this->getTestedClassName());
$method = $class->getMethod($name);
$method->setAccessible(true);
return $method;
}
public function setUp()
{
$this->request = new Request();
$this->request->setSession(new Session(new MockArraySessionStorage()));
$this->dispatcher = new EventDispatcher();
$this->securityContext = new SecurityContext($this->request);
$this->instance = $this->getTestedInstance();
$this->instance->initializeArgs($this->getMandatoryArguments());
}
public function testGetArgDefinitions()
{
$method = $this->getMethod('getArgDefinitions');
$methodReturn = $method->invoke($this->instance);
$this->assertInstanceOf('Thelia\Core\Template\Loop\Argument\ArgumentCollection', $methodReturn);
}
public function testExec()
{
$method = $this->getMethod('exec');
$methodReturn = $method->invokeArgs($this->instance, array(null));
$this->assertInstanceOf('\Thelia\Core\Template\Element\LoopResult', $methodReturn);
}
}

View File

@@ -0,0 +1,51 @@
<?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\Tests\Core\Template\Loop;
use Thelia\Tests\Core\Template\Element\BaseLoopTestor;
use Thelia\Core\Template\Loop\Accessory;
/**
*
* @author Etienne Roudeix <eroudeix@openstudio.fr>
*
*/
class AccessoryTest extends BaseLoopTestor
{
public function getTestedClassName()
{
return 'Thelia\Core\Template\Loop\Accessory';
}
public function getTestedInstance()
{
return new Accessory($this->request, $this->dispatcher, $this->securityContext);
}
public function getMandatoryArguments()
{
return array('product' => 1);
}
}

View File

@@ -0,0 +1,51 @@
<?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\Tests\Core\Template\Loop;
use Thelia\Tests\Core\Template\Element\BaseLoopTestor;
use Thelia\Core\Template\Loop\Address;
/**
*
* @author Etienne Roudeix <eroudeix@openstudio.fr>
*
*/
class AddressTest extends BaseLoopTestor
{
public function getTestedClassName()
{
return 'Thelia\Core\Template\Loop\Address';
}
public function getTestedInstance()
{
return new Address($this->request, $this->dispatcher, $this->securityContext);
}
public function getMandatoryArguments()
{
return array();
}
}

View File

@@ -0,0 +1,51 @@
<?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\Tests\Core\Template\Loop;
use Thelia\Tests\Core\Template\Element\BaseLoopTestor;
use Thelia\Core\Template\Loop\Category;
/**
*
* @author Etienne Roudeix <eroudeix@openstudio.fr>
*
*/
class CategoryTest extends BaseLoopTestor
{
public function getTestedClassName()
{
return 'Thelia\Core\Template\Loop\Category';
}
public function getTestedInstance()
{
return new Category($this->request, $this->dispatcher, $this->securityContext);
}
public function getMandatoryArguments()
{
return array();
}
}

View File

@@ -0,0 +1,51 @@
<?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\Tests\Core\Template\Loop;
use Thelia\Tests\Core\Template\Element\BaseLoopTestor;
use Thelia\Core\Template\Loop\Country;
/**
*
* @author Etienne Roudeix <eroudeix@openstudio.fr>
*
*/
class CountryTest extends BaseLoopTestor
{
public function getTestedClassName()
{
return 'Thelia\Core\Template\Loop\Country';
}
public function getTestedInstance()
{
return new Country($this->request, $this->dispatcher, $this->securityContext);
}
public function getMandatoryArguments()
{
return array();
}
}

View File

@@ -0,0 +1,51 @@
<?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\Tests\Core\Template\Loop;
use Thelia\Tests\Core\Template\Element\BaseLoopTestor;
use Thelia\Core\Template\Loop\Customer;
/**
*
* @author Etienne Roudeix <eroudeix@openstudio.fr>
*
*/
class CustomerTest extends BaseLoopTestor
{
public function getTestedClassName()
{
return 'Thelia\Core\Template\Loop\Customer';
}
public function getTestedInstance()
{
return new Customer($this->request, $this->dispatcher, $this->securityContext);
}
public function getMandatoryArguments()
{
return array();
}
}

View File

@@ -0,0 +1,51 @@
<?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\Tests\Core\Template\Loop;
use Thelia\Tests\Core\Template\Element\BaseLoopTestor;
use Thelia\Core\Template\Loop\FeatureAvailable;
/**
*
* @author Etienne Roudeix <eroudeix@openstudio.fr>
*
*/
class FeatureAvailableTest extends BaseLoopTestor
{
public function getTestedClassName()
{
return 'Thelia\Core\Template\Loop\FeatureAvailable';
}
public function getTestedInstance()
{
return new FeatureAvailable($this->request, $this->dispatcher, $this->securityContext);
}
public function getMandatoryArguments()
{
return array();
}
}

View File

@@ -0,0 +1,51 @@
<?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\Tests\Core\Template\Loop;
use Thelia\Tests\Core\Template\Element\BaseLoopTestor;
use Thelia\Core\Template\Loop\Feature;
/**
*
* @author Etienne Roudeix <eroudeix@openstudio.fr>
*
*/
class FeatureTest extends BaseLoopTestor
{
public function getTestedClassName()
{
return 'Thelia\Core\Template\Loop\Feature';
}
public function getTestedInstance()
{
return new Feature($this->request, $this->dispatcher, $this->securityContext);
}
public function getMandatoryArguments()
{
return array();
}
}

View File

@@ -0,0 +1,51 @@
<?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\Tests\Core\Template\Loop;
use Thelia\Tests\Core\Template\Element\BaseLoopTestor;
use Thelia\Core\Template\Loop\FeatureValue;
/**
*
* @author Etienne Roudeix <eroudeix@openstudio.fr>
*
*/
class FeatureValueTest extends BaseLoopTestor
{
public function getTestedClassName()
{
return 'Thelia\Core\Template\Loop\FeatureValue';
}
public function getTestedInstance()
{
return new FeatureValue($this->request, $this->dispatcher, $this->securityContext);
}
public function getMandatoryArguments()
{
return array('product' => 1, 'feature' => 1);
}
}

View File

@@ -0,0 +1,51 @@
<?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\Tests\Core\Template\Loop;
use Thelia\Tests\Core\Template\Element\BaseLoopTestor;
use Thelia\Core\Template\Loop\Product;
/**
*
* @author Etienne Roudeix <eroudeix@openstudio.fr>
*
*/
class ProductTest extends BaseLoopTestor
{
public function getTestedClassName()
{
return 'Thelia\Core\Template\Loop\Product';
}
public function getTestedInstance()
{
return new Product($this->request, $this->dispatcher, $this->securityContext);
}
public function getMandatoryArguments()
{
return array();
}
}

View File

@@ -0,0 +1,51 @@
<?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\Tests\Core\Template\Loop;
use Thelia\Tests\Core\Template\Element\BaseLoopTestor;
use Thelia\Core\Template\Loop\Title;
/**
*
* @author Etienne Roudeix <eroudeix@openstudio.fr>
*
*/
class TitleTest extends BaseLoopTestor
{
public function getTestedClassName()
{
return 'Thelia\Core\Template\Loop\Title';
}
public function getTestedInstance()
{
return new Title($this->request, $this->dispatcher, $this->securityContext);
}
public function getMandatoryArguments()
{
return array();
}
}

View File

@@ -49,7 +49,7 @@ class URL
$root = $path_only ? ConfigQuery::read('base_url', '/') : self::getIndexPage(); $root = $path_only ? ConfigQuery::read('base_url', '/') : self::getIndexPage();
$base = $root . $path; $base = $root . '/' . ltrim($path, '/');
} }
else else
$base = $path; $base = $path;
@@ -67,11 +67,26 @@ class URL
return $base . $queryString; return $base . $queryString;
} }
/**
* Returns the Absolute URL to a administration view
*
* @param string $viewName the view name (e.g. login for login.html)
* @param mixed $parameters An array of parameters
*
* @return string The generated 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
return self::absoluteUrl($path, $parameters);
}
/** /**
* Returns the Absolute URL to a view * Returns the Absolute URL to a view
* *
* @param string $viewName the view name (e.g. login for login.html) * @param string $viewName the view name (e.g. login for login.html)
* @param mixed $parameters An array of parameters * @param mixed $parameters An array of parameters
* *
* @return string The generated URL * @return string The generated URL
*/ */

View File

@@ -1,14 +1,11 @@
{$page_title={intl l='Thelia'}} {$page_title={intl l='Page not found'}}
{include file='includes/header.inc.html'} {include file='includes/header.inc.html'}
<div class="brandbar container">
<a class="brand" href="index.php">{images file='assets/img/logo-thelia-34px.png'}<img src="{$asset_url}" alt="{intl l='Thelia, solution e-commerce libre'}" />{/images}</a>
</div>
<div id="wrapper" class="container"> <div id="wrapper" class="container">
<h1>Oops! An Error Occurred</h1> <h1>{intl l="Oops! An Error Occurred"}</h1>
<h2>The server returned a "404 Not Found".</h2> <h2>{intl l='The server returned a "404 Not Found"'}</h2>
<p>{intl l='The page you\'ve requested was not found. Please check the page address, and try again.'}</p>
</div> </div>
{include file='includes/footer.inc.html'} {include file='includes/footer.inc.html'}

View File

@@ -1,9 +1,31 @@
// -- Tools -------------------------------------------------------------------- // -- Tools --------------------------------------------------------------------
.border-radius(@radius: 5px) { .rounded(@radius: 2px) {
-webkit-border-radius: @radius; -webkit-border-radius: @radius;
-moz-border-radius: @radius; -moz-border-radius: @radius;
border-radius: @radius; border-radius: @radius;
}
.border-radius(@topright: 0, @bottomright: 0, @bottomleft: 0, @topleft: 0) {
-webkit-border-top-right-radius: @topright;
-webkit-border-bottom-right-radius: @bottomright;
-webkit-border-bottom-left-radius: @bottomleft;
-webkit-border-top-left-radius: @topleft;
-moz-border-radius-topright: @topright;
-moz-border-radius-bottomright: @bottomright;
-moz-border-radius-bottomleft: @bottomleft;
-moz-border-radius-topleft: @topleft;
border-top-right-radius: @topright;
border-bottom-right-radius: @bottomright;
border-bottom-left-radius: @bottomleft;
border-top-left-radius: @topleft;
.background-clip(padding-box);
}
.background-clip(@argument: padding-box) {
-moz-background-clip: @argument;
-webkit-background-clip: @argument;
background-clip: @argument;
} }
.box-shadow(@shadow: 0 1px 2px rgba(0,0,0,.05)) { .box-shadow(@shadow: 0 1px 2px rgba(0,0,0,.05)) {
@@ -130,6 +152,10 @@ hr {
float: right; float: right;
margin: 0px; margin: 0px;
.control-group {
margin-bottom: 0px;
}
input.search-query { input.search-query {
background: url("img/search.png") no-repeat; background: url("img/search.png") no-repeat;
width: 212px; width: 212px;
@@ -137,7 +163,7 @@ hr {
outline: none; outline: none;
border: none; border: none;
padding: 5px 20px 5px 20px; padding: 5px 20px 5px 20px;
border-radius: 0px; .rounded(0px);
font-size: 12px; font-size: 12px;
color: #eee; color: #eee;
@@ -160,7 +186,7 @@ hr {
border: none; border: none;
top: 17px; top: 17px;
box-shadow: none; box-shadow: none;
border-radius: 0px; .rounded(0px);
z-index: 1337; z-index: 1337;
} }
} }
@@ -196,6 +222,7 @@ hr {
// -- Brandbar ---------------------------------------------------------------- // -- Brandbar ----------------------------------------------------------------
.loginpage { .loginpage {
.brandbar { .brandbar {
width: 100%; width: 100%;
} }
@@ -231,7 +258,7 @@ hr {
} }
.breadcrumb { .breadcrumb {
border-radius: 0px; .rounded(0px);
padding: 25px 0px 25px 30px; padding: 25px 0px 25px 30px;
background: url("img/logo-light.png") left center no-repeat; background: url("img/logo-light.png") left center no-repeat;
float: left; float: left;
@@ -279,6 +306,38 @@ hr {
} }
} }
// -- Navigation bar ----------------------------------------------------------
.navbar {
margin-bottom: 0px;
}
.navbar-inner {
border-top: none;
.border-radius(0, 4px, 4px, 0);
.container{
width: 1170px;
}
}
// -- Breadcrumb --------------------------------------------------------------
.breadcrumb {
margin-top: 0;
background-color: transparent;
padding: 0 15px;
> li > .divider {
color: inherit;
}
> .active {
color: inherit;
}
}
// -- Feed list on home page -------------------------------------------------- // -- Feed list on home page --------------------------------------------------
.feed-list { .feed-list {
@@ -314,10 +373,15 @@ hr {
margin: 0 auto 20px; margin: 0 auto 20px;
background-color: #fff; background-color: #fff;
border: 1px solid #e5e5e5; border: 1px solid #e5e5e5;
.border-radius; .rounded(5px);
.box-shadow; .box-shadow;
} }
textarea:focus, input[type="text"]:focus, input[type="password"]:focus, input[type="datetime"]:focus, input[type="datetime-local"]:focus, input[type="date"]:focus, input[type="month"]:focus, input[type="time"]:focus, input[type="week"]:focus, input[type="number"]:focus, input[type="email"]:focus, input[type="url"]:focus, input[type="search"]:focus, input[type="tel"]:focus, input[type="color"]:focus, .uneditable-input:focus {
border: 1px solid #E9730F;
box-shadow: 0px 0px 8px #FFA65A;
}
// -- Allow inline forms validation states ------------------------------------ // -- Allow inline forms validation states ------------------------------------
.form-inline .warning .control-label, .form-inline .warning .control-label,
@@ -474,4 +538,51 @@ hr {
color: #3a87ad; color: #3a87ad;
background-color: #d9edf7; background-color: #d9edf7;
border-color: #3a87ad; border-color: #3a87ad;
}
// -- Catalog Tables ----------------------------------------------------------
.table-striped {
background: white;
caption {
text-align: left;
color: #5A6876;
text-transform: uppercase;
font-weight: bold;
background-color: #fff;
padding: 0.5em 0.5em 0.5em 1em;
border-bottom: 2px solid #A5CED8;
line-height: 30px;
.btn-add-item {
display: block;
float: right;
}
}
td, th {
text-align: center;
}
td.object-title, th.object-title {
text-align: left;
}
td.message {
// Center the alert box (20px bottom margin) in the table cell
padding: 20px 20px 0 20px;
// No border, nor background in alert blocks
.alert {
border: none;
background-color: transparent;
&-info {
background-color: transparent;
}
}
}
} }

View File

@@ -7,7 +7,9 @@
{module_include location='home_top'} {module_include location='home_top'}
welcome home ! <div class="span12">
This is the administration home page. Put some interesting statistics here, and display useful information :)
</div>
{module_include location='home_bottom'} {module_include location='home_bottom'}
</div> </div>

View File

@@ -1,3 +1,5 @@
{module_include location='before_footer'}
<hr /> <hr />
<footer class="modal-footer"> <footer class="modal-footer">
<div class="container"> <div class="container">
@@ -7,19 +9,12 @@
- <a href="http://contrib.thelia.net/" target="_blank">{intl l='Contributions Thelia'}</a> - <a href="http://contrib.thelia.net/" target="_blank">{intl l='Contributions Thelia'}</a>
<span class="pull-right">{intl l='interface par <a target="_blank" href="http://www.steaw-webdesign.com/">Steaw-Webdesign</a>'}</span> <span class="pull-right">{intl l='interface par <a target="_blank" href="http://www.steaw-webdesign.com/">Steaw-Webdesign</a>'}</span>
</p> </p>
{module_include location='in_footer'}
</div> </div>
</footer> </footer>
{* Include required JS files *} {module_include location='after_footer'}
{javascripts file='../assets/js/jquery.min.js'}
<link rel="stylesheet" href="{$asset_url}" target="screen">
{/javascripts}
{javascripts file='../assets/bootstrap/js/bootstrap.min.js'}
<link rel="stylesheet" href="{$asset_url}" target="screen">
{/javascripts}
{* TODO allow modules to include JS here *}
</body> </body>
</html> </html>

View File

@@ -19,6 +19,16 @@
<link rel="stylesheet" href="{$asset_url}"> <link rel="stylesheet" href="{$asset_url}">
{/stylesheets} {/stylesheets}
{* Include here page specifc CSS file, if any *}
{if ! empty($thelia_page_css_file)}
{stylesheets file='../assets/css/$thelia_page_css_file' filters='less,cssembed'}
<link rel="stylesheet" href="{$asset_url}" target="screen">
{/stylesheets}
{/if}
{* Modules css are included here *}
{module_include location='head_css'} {module_include location='head_css'}
</head> </head>
<body> <body>
@@ -59,12 +69,6 @@
<div class="navbar"> <div class="navbar">
<div class="navbar-inner"> <div class="navbar-inner">
<div class="container"> <div class="container">
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</a>
<div class="nav-collapse"> <div class="nav-collapse">
<ul class="nav"> <ul class="nav">

View File

@@ -48,14 +48,9 @@
{module_include location='index_middle'} {module_include location='index_middle'}
<div class="row-fluid feed-list"> <div class="row-fluid feed-list">
{loop type="feed" name="thelia_feeds" url="http://thelia.net/Flux-rss.html?id_rubrique=8" limit="3"} <div class="span4 offset4">
<div class="span4 feed-list-item"> <div class="well">{intl l="Loading Thelia lastest news..."}</div>
<h3>{$DATE}</h3> </div>
<h2><a href="#URL" target="_blank" title="{intl l='Lire la suite'}">{$TITLE|strip_tags}</a></h2>
<p>{$DESCRIPTION|strip_tags|truncate:250:"...":true}</p>
<p><a class="btn" href="#URL" target="_blank">{intl l='Lire la suite »'}</a></p>
</div>
{/loop}
</div> </div>
</div> </div>
@@ -63,4 +58,12 @@
</div> </div>
{include file='includes/js.inc.html'}
<script>
$(function () {
$(".feed-list").load("{admin_viewurl view='includes/thelia_news_feed'}");
})
</script>
{include file='includes/footer.inc.html'} {include file='includes/footer.inc.html'}

View File

@@ -0,0 +1,4 @@
{loop name="cat" type="category" id="99999"}
{loop name="prod" type="product" category="#ID"}
{/loop}
{/loop}