Integration of Assetic in SmartyParser, extended it to Admin (we can now

use loops !), added the Thelia ControllerResolver and fixed config and
routing accordingly.²:wq
This commit is contained in:
franck
2013-06-19 02:07:43 +02:00
parent 7351edeb46
commit 89abfaad48
35 changed files with 763 additions and 244 deletions

View File

@@ -21,6 +21,8 @@
"symfony/routing" : "2.2.*",
"symfony/filesystem" : "2.2.*",
"symfony/yaml" : "2.2.*",
"symfony/translation" : "2.2.*",
"symfony-cmf/routing": "1.0.0",
"symfony/form": "2.2.*",
@@ -30,7 +32,8 @@
"smarty/smarty": "v3.1.13",
"kriswallsmith/assetic": "1.2.*@dev",
"leafo/lessphp": "0.3.*@dev"
"leafo/lessphp": "0.3.*@dev",
"ptachoire/cssembed": "dev-master"
},
"require-dev" : {
"fzaninotto/faker": "dev-master"

View File

@@ -4,7 +4,7 @@
/* Thelia */
/* */
/* Copyright (c) OpenStudio */
/* email : info@thelia.net */
/* email : info@thelia.net */
/* web : http://www.thelia.net */
/* */
/* This program is free software; you can redistribute it and/or modify */
@@ -17,7 +17,7 @@
/* 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/>. */
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* */
/*************************************************************************************/
namespace Thelia\Admin\Controller;
@@ -25,6 +25,9 @@ namespace Thelia\Admin\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Thelia\Admin\Templating\Template;
use Thelia\Core\Template\SmartyParser;
use Symfony\Component\Routing\RequestContext;
use Symfony\Component\DependencyInjection\ContainerAware;
/**
*
@@ -34,24 +37,23 @@ use Thelia\Admin\Templating\Template;
* @author Franck Allimant <franck@cqfdev.fr>
*/
class BaseAdminController
class BaseAdminController extends ContainerAware
{
protected function render($templateName, $args = array()) {
$tpl = new Template();
$parser = $this->container->get('thelia.admin.parser');
$data = $tpl->render($templateName, $args);
$args = array('lang' => 'fr');
return $data;
return $parser->render($templateName, $args);
}
public function indexAction()
{
$rep = new Response();
$resp = new Response();
$rep->setContent($this->render('login'));
$resp->setContent($this->render('login.html'));
return $rep;
return $resp;
}
}
?>
}

View File

@@ -0,0 +1,46 @@
<?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\Admin\Template;
use Thelia\Core\Template\SmartyParser;
use Symfony\Component\DependencyInjection\ContainerInterface;
// smarty configuration
class AdminSmartyParser extends SmartyParser
{
public function __construct(ContainerInterface $container, $template = false)
{
$this->template = $template == false ? 'admin/default' : $template;
parent::__construct($container, $template);
}
public function render($realTemplateName, $parameters) {
$this->assign($parameters);
return $this->fetch($realTemplateName);
}
}
?>

View File

@@ -18,6 +18,7 @@
</commands>
<services>
<service id="event_dispatcher" class="Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher">
<argument type="service" id="service_container" />
</service>
@@ -26,9 +27,23 @@
<tag name="kernel.event_subscriber"/>
</service>
<service id="controller_resolver" class="Symfony\Component\HttpKernel\Controller\ControllerResolver"/>
<!--
A ControllerResolver that supports "a:b:c", "service:method" and class::method" notations,
thus allowing the definition of controllers as service (see http://symfony.com/fr/doc/current/cookbook/controller/service.html)
We use it here to inject the servi ce container in the admin base controller.
-->
<service id="controller_resolver" class="Thelia\Core\Controller\ControllerResolver">
<argument type="service" id="service_container"/>
</service>
<service id="parser" class="Thelia\Core\Template\SmartyParser">
<service id="thelia.parser" class="Thelia\Core\Template\SmartyParser">
<argument type="service" id="service_container"/>
<call method="setLoopList">
<argument>%tpex.loop%</argument>
</call>
</service>
<service id="thelia.admin.parser" class="Thelia\Admin\Template\AdminSmartyParser">
<argument type="service" id="service_container"/>
<call method="setLoopList">
<argument>%tpex.loop%</argument>

View File

@@ -20,6 +20,10 @@
<service id="controller.default" class="Thelia\Controller\DefaultController"/>
<service id="thelia.admin.base_controller" class="Thelia\Admin\Controller\BaseAdminController">
<argument type="service" id="service_container"/>
</service>
<service id="matcher.default" class="Thelia\Routing\Matcher\DefaultMatcher">
<argument type="service" id="controller.default"/>
</service>

View File

@@ -5,6 +5,6 @@
xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd">
<route id="admin" path="/admin">
<default key="_controller">\Thelia\Admin\Controller\BaseAdminController::indexAction</default>
<default key="_controller">Thelia\Admin\Controller\BaseAdminController::indexAction</default>
</route>
</routes>

View File

@@ -0,0 +1,74 @@
<?php
namespace Thelia\Core\Controller;
use Symfony\Component\HttpKernel\Controller\ControllerResolver as BaseControllerResolver;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
/**
* ControllerResolver that supports "a:b:c", "service:method" and class::method" notations in routes definition
* thus allowing the definition of controllers as service (see http://symfony.com/fr/doc/current/cookbook/controller/service.html)
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Franck Allimant <franck@cqfdev.fr>
*/
class ControllerResolver extends BaseControllerResolver
{
protected $container;
/**
* Constructor.
*
* @param ContainerInterface $container A ContainerInterface instance
* @param LoggerInterface $logger A LoggerInterface instance
*/
public function __construct(ContainerInterface $container, LoggerInterface $logger = null)
{
$this->container = $container;
parent::__construct($logger);
}
/**
* Returns a callable for the given controller.
*
* @param string $controller A Controller string
*
* @return mixed A PHP callable
*
* @throws \LogicException When the name could not be parsed
* @throws \InvalidArgumentException When the controller class does not exist
*/
protected function createController($controller)
{
if (false === strpos($controller, '::')) {
$count = substr_count($controller, ':');
if (2 == $count) {
// controller in the a:b:c notation then
$controller = $this->parser->parse($controller);
} elseif (1 == $count) {
// controller in the service:method notation
list($service, $method) = explode(':', $controller, 2);
return array($this->container->get($service), $method);
} else {
throw new \LogicException(sprintf('Unable to parse the controller name "%s".', $controller));
}
}
list($class, $method) = explode('::', $controller, 2);
if (!class_exists($class)) {
throw new \InvalidArgumentException(sprintf('Class "%s" does not exist.', $class));
}
$controller = new $class();
if ($controller instanceof ContainerAwareInterface) {
$controller->setContainer($this->container);
}
return array($controller, $method);
}
}

View File

@@ -67,7 +67,7 @@ class ViewListener implements EventSubscriberInterface
*/
public function onKernelView(GetResponseForControllerResultEvent $event)
{
$parser = $this->container->get('parser');
$parser = $this->container->get('thelia.parser');
try {
$content = $parser->getContent();

View File

@@ -34,13 +34,6 @@ use Assetic\Cache\FilesystemCache;
class AsseticManager {
protected $options;
public function __construct($_options = array()) {
$this->options = $_options;
}
/**
* Generates assets from $asset_path in $output_path, using $filters.
*

View File

@@ -0,0 +1,85 @@
<?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\Assets;
use Thelia\Core\Template\Assets\AsseticManager;
class SmartyAssetsManager {
const ASSET_TYPE_AUTO = '';
private $assetic_manager;
private $web_root;
private $path_relative_to_web_root;
/**
*
* @param string $web_root the disk path to the web root
* @param string $path_relative_to_web_root the path (relative to web root) where the assets will be generated
*/
public function __construct($web_root, $path_relative_to_web_root) {
$this->web_root = $web_root;
$this->path_relative_to_web_root = $path_relative_to_web_root;
$this->assetic_manager = new AsseticManager();
}
public function processSmartyPluginCall($assetType, $params, $content, \Smarty_Internal_Template $template, &$repeat) {
// Opening tag (first call only)
if ($repeat) {
$file = $params['file'];
$filters = isset($params['filters']) ? $params['filters'] : '';
$debug = isset($params['debug']) ? trim(strtolower($params['debug'])) == 'true' : false;
// Get template base path
$tpl_path = $template->source->filepath;
// Get basedir
$tpl_dir = dirname($tpl_path);
// Create absolute dir path
$asset_dir = realpath($tpl_dir.'/'.dirname($file));
$asset_file = basename($file);
if ($asset_dir === false) throw new \Exception("Failed to get real path of '".$tpl_dir.'/'.dirname($file)."'");
$url = $this->assetic_manager->asseticize(
$asset_dir.'/'.$asset_file,
$this->web_root."/".$this->path_relative_to_web_root,
$this->path_relative_to_web_root,
$assetType,
$filters,
$debug
);
$template->assign('asset_url', $url);
}
else if (isset($content)) {
return $content;
}
}
}

View File

@@ -3,15 +3,20 @@
namespace Thelia\Core\Template;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Thelia\Core\Template\ParserInterface;
use \Smarty;
use Thelia\Core\Template\Loop\Category;
use \Smarty;
use Thelia\Core\Template\ParserInterface;
use Thelia\Core\Template\Loop\Category;
use Thelia\Tpex\Element\Loop\BaseLoop;
use Thelia\Core\Template\Assets\SmartyAssetsManager;
/**
*
* @author Franck Allimant <franck@cqfdev.fr>
*/
class SmartyParser extends Smarty implements ParserInterface {
/**
* @var Symfony\Component\DependencyInjection\ContainerInterface
*/
protected $container;
protected $template = "smarty-sample";
@@ -20,37 +25,271 @@ class SmartyParser extends Smarty implements ParserInterface {
protected $loopDefinition = array();
public function __construct(ContainerInterface $container)
protected $asset_manager = null; // Lazy loading
/**
* @var Symfony\Component\DependencyInjection\ContainerInterface
*/
public function __construct(ContainerInterface $container, $template = false)
{
parent::__construct();
$this->container = $container;
// Configure basic Smarty parameters
$compile_dir = THELIA_ROOT . 'cache/smarty/compile';
if (! is_dir($compile_dir)) @mkdir($compile_dir, 0777, true);
$cache_dir = THELIA_ROOT . 'cache/smarty/cache';
if (! is_dir($cache_dir)) @mkdir($cache_dir, 0777, true);
if ($template != false) $this->template = $template;
$this->setTemplateDir(THELIA_TEMPLATE_DIR.$this->template);
$this->setCompileDir($compile_dir);
$this->setCacheDir($cache_dir);
$this->registerPlugin('block', 'loop', array($this, 'theliaLoop'));
$this->registerPlugin('block', 'empty', array($this, 'theliaEmpty'));
$this->registerPlugin('block', 'notempty', array($this, 'theliaNotEmpty'));
// Prevent ErrorException: Notice: Undefined index
// Prevent smarty ErrorException: Notice: Undefined index bla bla bla...
$this->error_reporting = E_ALL ^ E_NOTICE;
// The default HTTP status
$this->status = 200;
// Register Thelia base block plugins
$this->registerPlugin('block', 'loop' , array($this, 'theliaLoop'));
$this->registerPlugin('block', 'elseloop' , array($this, 'theliaElseloop'));
$this->registerPlugin('block', 'ifloop' , array($this, 'theliaIfLoop'));
// Register translation function 'intl'
$this->registerPlugin('function', 'intl', array($this, 'theliaTranslate'));
// Register Thelia modules inclusion function 'thelia_module'
$this->registerPlugin('function', 'thelia_module', array($this, 'theliaModule'));
// Register asset management block plugins
$this->registerPlugin('block', 'stylesheets', array($this, 'theliaBlockStylesheets'));
$this->registerPlugin('block', 'javascripts', array($this, 'theliaBlockJavascripts'));
$this->registerPlugin('block', 'images' , array($this, 'theliaBlockImages'));
}
/**
* Process {loop name="loop name" type="loop type" ... } ... {/loop} block
*
* associative array containing information for loop execution
* @param unknown $params
* @param unknown $content
* @param unknown $template
* @param unknown $repeat
* @throws \InvalidArgumentException
* @return string
*/
public function theliaLoop($params, $content, $template, &$repeat) {
if (empty($params['name']))
throw new \InvalidArgumentException("Missing 'name' parameter in loop arguments");
if (empty($params['type']))
throw new \InvalidArgumentException("Missing 'type' parameter in loop arguments");
$name = $params['name'];
if ($content === null) {
$loop = $this->createLoopInstance(strtolower($params['type']));
$this->getLoopArgument($loop, $params);
$loopResults = $loop->exec();
$template->assignByRef($name, $loopResults);
}
else {
$loopResults = $template->getTemplateVars($name);
$loopResults->next();
}
if ($loopResults->valid()) {
$loopResultRow = $loopResults->current();
foreach($loopResultRow->getVarVal() as $var => $val) {
$template->assign(substr($var, 1), $val);
$template->assign('__COUNT__', 1 + $loopResults->key());
$template->assign('__TOTAL__', $loopResults->getCount());
}
$repeat = $loopResults->valid();
}
if ($content !== null) {
if ($loopResults->isEmpty()) $content = "";
return $content;
}
}
/**
* Process {elseloop rel="loopname"} ... {/elseloop} block
*
* @param unknown $params
* @param unknown $content
* @param unknown $template
* @param unknown $repeat
* @return Ambigous <string, unknown>
*/
public function theliaElseloop($params, $content, $template, &$repeat) {
// When encoutering close tag, check if loop has results.
if ($repeat === false) {
return $this->checkEmptyLoop($params, $template) ? $content : '';
}
}
/**
* Process {ifloop rel="loopname"} ... {/ifloop} block
*
* @param unknown $params
* @param unknown $content
* @param unknown $template
* @param unknown $repeat
* @return Ambigous <string, unknown>
*/
public function theliaIfLoop($params, $content, $template, &$repeat) {
// When encountering close tag, check if loop has results.
if ($repeat === false) {
return $this->checkEmptyLoop($params, $template) ? '' : $content;
}
}
/**
* Process translate function
*
* @param unknown $params
* @param unknown $smarty
* @return string
*/
public function theliaTranslate($params, &$smarty)
{
if (isset($params['l'])) {
$string = str_replace('\'', '\\\'', $params['l']);
}
else {
$string = '';
}
// TODO
return "[$string]";
}
/**
* Process theliaModule template inclusion function
*
* @param unknown $params
* @param unknown $smarty
* @return string
*/
public function theliaModule($params, &$smarty)
{
// TODO
return "";
}
public function theliaBlockJavascripts($params, $content, \Smarty_Internal_Template $template, &$repeat)
{
return $this->getAssetManager()->processSmartyPluginCall('js', $params, $content, $template, $repeat);
}
public function theliaBlockImages($params, $content, \Smarty_Internal_Template $template, &$repeat)
{
return $this->getAssetManager()->processSmartyPluginCall(SmartyAssetsManager::ASSET_TYPE_AUTO, $params, $content, $template, $repeat);
}
public function theliaBlockStylesheets($params, $content, \Smarty_Internal_Template $template, &$repeat)
{
return $this->getAssetManager()->processSmartyPluginCall('css', $params, $content, $template, $repeat);
}
/**
*
* This method must return a Symfony\Component\HttpFoudation\Response instance or the content of the response
*
*/
public function getContent()
{
return $this->fetch($this->getTemplateFilePath());
}
/**
*
* set $content with the body of the response or the Response object directly
*
* @param string|Symfony\Component\HttpFoundation\Response $content
*/
public function setContent($content)
{
$this->content = $content;
}
/**
*
* @return type the status of the response
*/
public function getStatus()
{
return $this->status;
}
/**
*
* status HTTP of the response
*
* @param int $status
*/
public function setStatus($status)
{
$this->status = $status;
}
/**
* Check if a loop has returned results. The loop shoud have been executed before, or an
* InvalidArgumentException is thrown
*
* @param unknown $params
* @param unknown $template
* @throws \InvalidArgumentException
*/
protected function checkEmptyLoop($params, $template) {
if (empty($params['rel']))
throw new \InvalidArgumentException("Missing 'rel' parameter in ifloop/elseloop arguments");
$loopName = $params['rel'];
// Find loop results in the current template vars
$loopResults = $template->getTemplateVars($loopName);
if (empty($loopResults)) {
throw new \InvalidArgumentException("Loop $loopName is not defined.");
}
return $loopResults->isEmpty();
}
/**
*
* Injects an associative array containing information for loop execution
*
* key is loop name
* value is the class implementing/extending base loop classes
@@ -77,16 +316,23 @@ class SmartyParser extends Smarty implements ParserInterface {
}
}
private function extractParam($loop, $smartyParam)
/**
* Returns the value of a loop argument.
*
* @param unknown $loop a BaseLoop instance
* @param unknown $smartyParam
* @throws \InvalidArgumentException
*/
protected function getLoopArgument(BaseLoop $loop, $smartyParam)
{
$defaultItemsParams = array('required' => true);
$shortcutItemParams = array(
'optional' => array('required' => false)
);
$shortcutItemParams = array('optional' => array('required' => false));
$errorCode = 0;
$faultActor = array();
$faultDetails = array();
foreach($loop->defineArgs() as $name => $param){
if(is_integer($name)){
$name = $param;
@@ -124,88 +370,6 @@ class SmartyParser extends Smarty implements ParserInterface {
}
}
public function theliaEmpty($params, $content, $template, &$repeat) {
// When encoutering close tag, check if loop has results.
if ($repeat === false) {
return $this->checkEmptyLoop($params, $template) ? $content : '';
}
}
public function theliaNotEmpty($params, $content, $template, &$repeat) {
// When encoutering close tag, check if loop has results.
if ($repeat === false) {
return $this->checkEmptyLoop($params, $template) ? '' : $content;
}
}
private function checkEmptyLoop($params, $template) {
if (empty($params['name']))
throw new \InvalidArgumentException("Missing 'name' parameter in conditional loop arguments");
$loopName = $params['name'];
// Find loop results in the current template vars
$loopResults = $template->getTemplateVars($loopName);
if (empty($loopResults)) {
throw new \InvalidArgumentException("Loop $loopName is not dfined.");
}
return $loopResults->isEmpty();
}
public function theliaLoop($params, $content, $template, &$repeat) {
if (empty($params['name']))
throw new \InvalidArgumentException("Missing 'name' parameter in loop arguments");
if (empty($params['type']))
throw new \InvalidArgumentException("Missing 'type' parameter in loop arguments");
$name = $params['name'];
if ($content === null) {
$loop = $this->createLoopInstance(strtolower($params['type']));
$this->extractParam($loop, $params);
$loopResults = $loop->exec();
$template->assignByRef($name, $loopResults);
}
else {
$loopResults = $template->getTemplateVars($name);
$loopResults->next();
}
if ($loopResults->valid()) {
$loopResultRow = $loopResults->current();
foreach($loopResultRow->getVarVal() as $var => $val) {
$template->assign(substr($var, 1), $val);
$template->assign('__COUNT__', 1 + $loopResults->key());
$template->assign('__TOTAL__', $loopResults->getCount());
}
$repeat = $loopResults->valid();
}
if ($content !== null) {
if ($loopResults->isEmpty()) $content = "";
return $content;
}
}
/**
*
* find the loop class with his name and construct an instance of this class
@@ -235,57 +399,6 @@ class SmartyParser extends Smarty implements ParserInterface {
);
}
/**
*
* This method must return a Symfony\Component\HttpFoudation\Response instance or the content of the response
*
*/
public function getContent()
{
return $this->fetch($this->getTemplateFilePath());
}
/**
*
* set $content with the body of the response or the Response object directly
*
* @param string|Symfony\Component\HttpFoundation\Response $content
*/
public function setContent($content)
{
$this->content = $content;
}
/**
*
* @return type the status of the response
*/
public function getStatus()
{
return $this->status;
}
/**
*
* status HTTP of the response
*
* @param int $status
*/
public function setStatus($status)
{
$this->status = $status;
}
/**
* Main parser function, load the parser
*/
public function loadParser()
{
$file = $this->getTemplateFilePath();
echo "f=$file";
}
protected function getTemplateFilePath()
{
$request = $this->container->get('request');
@@ -299,4 +412,11 @@ class SmartyParser extends Smarty implements ParserInterface {
throw new ResourceNotFoundException(sprintf("%s file not found in %s template", $file, $this->template));
}
}
protected function getAssetManager() {
if ($this->asset_manager == null)
$this->asset_manager = new SmartyAssetsManager(THELIA_WEB_DIR, "assets/$this->template");
return $this->asset_manager;
}
}

View File

@@ -4,7 +4,7 @@
/* Thelia */
/* */
/* Copyright (c) OpenStudio */
/* email : info@thelia.net */
/* email : info@thelia.net */
/* web : http://www.thelia.net */
/* */
/* This program is free software; you can redistribute it and/or modify */
@@ -17,7 +17,7 @@
/* 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/>. */
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* */
/*************************************************************************************/
namespace Thelia\Core;
@@ -121,32 +121,32 @@ class TheliaHttpKernel extends HttpKernel
{
}
protected function initSession(Request $request)
{
$storage = new Session\Storage\NativeSessionStorage();
if (Model\ConfigQuery::read("session_config.default")) {
$storage->setSaveHandler(new Session\Storage\Handler\NativeFileSessionHandler(Model\ConfigQuery::read("session_config.save_path", THELIA_ROOT . '/local/session/')));
} else {
$handlerString = Model\ConfigQuery::read("session_config.handlers");
$handler = new $handlerString;
$storage->setSaveHandler($handler);
}
if (Model\ConfigQuery::read("session_config.config", null)) {
$storage->setOptions(json_decode(Model\ConfigQuery::read("session_config.config")));
$storage->setOptions(json_decode(Model\ConfigQuery::read("session_config.config")));
}
$session = new Session\Session($storage);
$session->start();
$request->setSession($session);
return $request;
}
}
}

View File

@@ -54,12 +54,37 @@ a {
font-weight: bold;
}
// Bootstrap Adjustements ------------------------------------------------------
.btn-primary, .row h3 .btn-large, .row-fluid h3 .btn-large, .row-fluid h4 .btn-large {
background: -moz-linear-gradient(center bottom , #E3530B 0%, #F39922 100%) repeat scroll 0 0 #E9730F;
box-shadow: 0 0 2px rgba(250, 250, 250, 0.5) inset, 0 1px 3px rgba(0, 0, 0, 0.2);
color: white;
}
// -- Brandbar ----------------------------------------------------------------
/* --- BRAND BAR ---*/
.loginpage {
.brandbar {
width: 100%;
}
.hero-unit {
background-color: transparent !important;
}
.well {
background-color: #E4E3DE;
border: 1px solid rgba(0, 0, 0, 0.2);
box-shadow: 0 -4px 0 rgba(0, 0, 0, 0.05) inset;
}
}
.brandbar {
background: url("images/header.jpg") repeat-x;
background: url("img/header.jpg") repeat-x;
height: 90px;
a.brand {
@@ -67,7 +92,7 @@ a {
display: block;
float: left;
margin-right: 20px;
background: url("images/logo.png") 0px 12px no-repeat;
background: url("img/logo.png") 0px 12px no-repeat;
width: 124px;
height: 63px;
}
@@ -75,7 +100,7 @@ a {
.breadcrumb {
border-radius: 0px;
padding: 25px 0px 25px 30px;
background: url("images/logo-light.png") left center no-repeat;
background: url("img/logo-light.png") left center no-repeat;
float: left;
margin: 12px 0px 0px 0px;
@@ -114,7 +139,7 @@ a {
a {
text-indent: -13337px;
display: block;
background: url("images/deconnexion.png") no-repeat;
background: url("img/deconnexion.png") no-repeat;
width: 23px;
height: 24px;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

View File

View File

@@ -0,0 +1,13 @@
{* Include required JS files *}
{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>
</html>

View File

@@ -0,0 +1,24 @@
<!DOCTYPE html>
<html lang="{$lang}">
<head>
<title>{intl l='Thelia Back Office'}{if ! empty($page_title)} - {$page_title}{/if}</title>
{images file='../assets/img/favicon.ico'}<link rel="shortcut icon" href="{$asset_url}" />{/images}
<meta name="viewport" content="width=device-width, initial-scale=1.0">
{stylesheets file='../assets/css/*' filters='less,cssembed'}
<link rel="stylesheet" href="{$asset_url}">
{/stylesheets}
{stylesheets file='../assets/bootstrap/css/bootstrap.css' filters='cssembed'}
<link rel="stylesheet" href="{$asset_url}">
{/stylesheets}
{stylesheets file='../assets/bootstrap/css/bootstrap-responsive.css' filters='cssembed'}
<link rel="stylesheet" href="{$asset_url}">
{/stylesheets}
{* TODO allow modules to include CSS here *}
</head>
<body>

View File

@@ -0,0 +1,52 @@
{$page_title={intl l='Thelia'}}
{include file='includes/header.inc.html'}
<div class="loginpage">
<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">
{thelia_module action='index_top'}
<div class="hero-unit">
<h1>{intl l='Thelia Back Office'}</h1>
<form action="/admin/login" method="post" class="well form-inline">
<input type="text" class="input" placeholder="{intl l='E-mail address'}" name="username" />
<input type="password" class="input" placeholder="{intl l='Password'}" name="password" />
<label class="checkbox"> <input type="checkbox" name="remember" value="yes"> {intl l='Remember me'}</label>
<button type="submit" class="btn btn-primary">{intl l='Login'} <i class="icon-play"></i></button>
</form>
</div>
<div class="row-fluid">
</div>
<div>
<h2>We DO display loops in back-office !</h2>
<ul>
{loop type="category" name="catloop1"}
<li>{$__COUNT__}/{$__TOTAL__} : {$ID} {$TITLE}, children: {$NB_CHILD}
{ifloop rel="inner1"}
<ul>
{loop type="category" name="inner1" parent="{$ID}"}
<li>Sub cat {$ID} (parent is {$PARENT}): {$TITLE}</li>
{/loop}
</ul>
{/ifloop}
</li>
{/loop}
</ul>
</div>
</div>
{thelia_module action='index_bottom'}
</div>
{include file='includes/footer.inc.html'}

View File

@@ -0,0 +1,9 @@
body {
font-size: 12px;
font-family: Arial, helvetica, sans serif;
background-image: url("../img/test-background.jpg");
}
div {
margin: 10px 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

File diff suppressed because one or more lines are too long

View File

View File

@@ -0,0 +1 @@
<?php

View File

@@ -0,0 +1,18 @@
{* Include required JS files *}
{javascripts file='../assets/js/*'}
<script src="{$asset_url}"></script>
{/javascripts}
<script>
$(function() {
$('#jquery_block').html("Jquery is now loaded.").hover(function() {
$(this).css('font-weight', 'bold');
}, function() {
$(this).css('font-weight', 'normal');
});
});
</script>
</body>
</html>

View File

@@ -0,0 +1,11 @@
<!DOCTYPE html>
<html>
<head>
<title>{intl l='Hi, I\'m a Thelia TPex template'}</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
{stylesheets file='../assets/css/*' filters='less,cssembed'}
<link rel="stylesheet" href="{$asset_url}">
{/stylesheets}
</head>
<body>

View File

@@ -1,61 +1,77 @@
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<div>
<p>Category loop example</p>
{loop type="category" name="catloop1"}
{$__COUNT__}/{$__TOTAL__} : {$ID} {$TITLE} <br />
nb child : {$NB_CHILD} <br /><br />
{/loop}
</div>
{include file="includes/header.html"}
<div>
An image from asset directory :
{images file='assets/img/logo-thelia-34px.png'}<img src="{$asset_url}" alt="{intl l='Thelia, solution e-commerce libre'}" />{/images}
</div>
<div>
<p>Conditional example #1</p>
<div>
{intl l='An internationalized string'}
</div>
{notempty name="catloop2"}
Loop catloop2 is not empty: <ul>
{loop type="category" name="catloop2" parent="12"}
<li>{$__COUNT__}/{$__TOTAL__} : {$ID} {$TITLE}</li>
{/loop}
</ul>
{/notempty}
<div>
jQuery data: <span id="jquery_block"></span>
</div>
{empty name="catloop2"}
<p>Loop catloop2 is empty</p>
{/empty}
<div>
<p>Category loop example</p>
<ul>
{loop type="category" name="catloop1"}
<li>{$__COUNT__}/{$__TOTAL__} : {$ID} {$TITLE}, children: {$NB_CHILD}
{ifloop rel="inner1"}
<ul>
{loop type="category" name="inner1" parent="{$ID}"}
<li>Sub cat {$ID} (parent is {$PARENT}): {$TITLE}</li>
{/loop}
</ul>
{/ifloop}
</li>
{/loop}
</ul>
</div>
</div>
<div>
<p>Conditional example #1</p>
<div>
<p>Conditional example #2</p>
{ifloop rel="catloop2"}
Hey ! Loop catloop2 is not empty:
<ul>
{loop type="category" name="catloop2" parent="12"}
<li>{$__COUNT__}/{$__TOTAL__} : {$ID} {$TITLE}</li>
{/loop}
</ul>
{/ifloop}
{notempty name="catloop3"}
Loop catloop3 is not empty: <ul>
{loop type="category" name="catloop3" parent="0"}
<li>{$__COUNT__}/{$__TOTAL__} : {$ID} {$TITLE}</li>
{/loop}
</ul>
{/notempty}
{elseloop rel="catloop2"}
<p>Loop catloop2 is empty</p>
{/elseloop}
</div>
{empty name="catloop3"}
<p>Loop catloop3 is empty</p>
{/empty}
<div>
<p>Conditional example #2</p>
{empty name="catloop2"}
<p>... but catloop2 is still empty :-)</p>
{/empty}
{ifloop rel="catloop3"}
Loop catloop3 is not empty:
<ul>
{loop type="category" name="catloop3" parent="0"}
<li>{$__COUNT__}/{$__TOTAL__} : {$ID} {$TITLE}</li>
{/loop}
</ul>
{/ifloop}
</div>
{elseloop rel="catloop3"}
<p>Loop catloop3 is empty</p>
{/elseloop}
<div>
<p>Traditional for loop</p>
{for $index=5 to 12 step 1}
Compteur = {$index}<br />
{/for}
</div>
</body>
</html>
{elseloop rel="catloop2"}
<p>... but catloop2 is still empty :-)</p>
{/elseloop}
</div>
<div>
<p>Traditional for loop</p>
{for $index=5 to 12 step 1}
Compteur = {$index}<br />
{/for}
</div>
{include file="includes/footer.html"}

View File

@@ -8,5 +8,7 @@ AddDefaultCharset UTF-8
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteBase /thelia2
RewriteRule ^admin(/.*)?$ index_dev.php/admin/$1 [L,QSA]
</IfModule>