diff --git a/core/lib/Thelia/Config/Resources/config.xml b/core/lib/Thelia/Config/Resources/config.xml
index bd17daa8d..4199ce349 100644
--- a/core/lib/Thelia/Config/Resources/config.xml
+++ b/core/lib/Thelia/Config/Resources/config.xml
@@ -36,17 +36,29 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
%tpex.loop%
-
+
-
-
-
diff --git a/core/lib/Thelia/Core/Bundle/TheliaBundle.php b/core/lib/Thelia/Core/Bundle/TheliaBundle.php
index 76c3cabaa..a016dc193 100644
--- a/core/lib/Thelia/Core/Bundle/TheliaBundle.php
+++ b/core/lib/Thelia/Core/Bundle/TheliaBundle.php
@@ -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 . */
+/* along with this program. If not, see . */
/* */
/*************************************************************************************/
namespace Thelia\Core\Bundle;
@@ -28,7 +28,7 @@ use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\Scope;
use Thelia\Core\DependencyInjection\Compiler\RegisterListenersPass;
-use Thelia\Core\DependencyInjection\Compiler\RegisterSmartyPluginPass;
+use Thelia\Core\DependencyInjection\Compiler\RegisterParserPluginPass;
/**
* First Bundle use in Thelia
@@ -57,6 +57,6 @@ class TheliaBundle extends Bundle
$container->addScope(new Scope('request'));
$container->addCompilerPass(new RegisterListenersPass());
- $container->addCompilerPass(new RegisterSmartyPluginPass());
+ $container->addCompilerPass(new RegisterParserPluginPass());
}
}
diff --git a/core/lib/Thelia/Core/DependencyInjection/Compiler/RegisterSmartyPluginPass.php b/core/lib/Thelia/Core/DependencyInjection/Compiler/RegisterParserPluginPass.php
similarity index 89%
rename from core/lib/Thelia/Core/DependencyInjection/Compiler/RegisterSmartyPluginPass.php
rename to core/lib/Thelia/Core/DependencyInjection/Compiler/RegisterParserPluginPass.php
index 0de6ab1bb..3c1d0f35f 100644
--- a/core/lib/Thelia/Core/DependencyInjection/Compiler/RegisterSmartyPluginPass.php
+++ b/core/lib/Thelia/Core/DependencyInjection/Compiler/RegisterParserPluginPass.php
@@ -29,14 +29,12 @@ use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
/**
+ * Register parser plugins. These plugins shouild be tagged thelia.parser.register_plugin
+ * in the configuration.
*
- * This compiler allow adding plugins in smarty parser using config files
*
- * Class RegisterSmartyPluginPass
- * @package Thelia\Core\DependencyInjection\Compiler
*/
-
-class RegisterSmartyPluginPass implements CompilerPassInterface {
+class RegisterParserPluginPass implements CompilerPassInterface {
/**
* You can modify the container here before it is dumped to PHP code.
@@ -53,10 +51,8 @@ class RegisterSmartyPluginPass implements CompilerPassInterface {
$smarty = $container->getDefinition("thelia.parser");
- foreach ($container->findTaggedServiceIds("smarty.register_plugin") as $id => $plugin) {
-
+ foreach ($container->findTaggedServiceIds("thelia.parser.register_plugin") as $id => $plugin) {
$smarty->addMethodCall("addPlugins", array(new Reference($id)));
-
}
$smarty->addMethodCall("registerPlugins");
diff --git a/core/lib/Thelia/Core/Template/Assets/AsseticManager.php b/core/lib/Thelia/Core/Template/Assets/AsseticHelper.php
similarity index 93%
rename from core/lib/Thelia/Core/Template/Assets/AsseticManager.php
rename to core/lib/Thelia/Core/Template/Assets/AsseticHelper.php
index 8f8df9698..6826e373d 100644
--- a/core/lib/Thelia/Core/Template/Assets/AsseticManager.php
+++ b/core/lib/Thelia/Core/Template/Assets/AsseticHelper.php
@@ -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 . */
+/* along with this program. If not, see . */
/* */
/*************************************************************************************/
@@ -32,14 +32,12 @@ use Assetic\AssetWriter;
use Assetic\Asset\AssetCache;
use Assetic\Cache\FilesystemCache;
-class AsseticManager {
-
- protected $options;
-
- public function __construct($_options = array()) {
-
- $this->options = $_options;
- }
+/**
+ * This class is a simple helper for generating assets using Assetic.
+ *
+ * @author Franck Allimant
+ */
+class AsseticHelper {
/**
* Generates assets from $asset_path in $output_path, using $filters.
@@ -50,7 +48,7 @@ class AsseticManager {
* @param unknown $asset_type the asset type: css, js, ... The generated files will have this extension. Pass an empty string to use the asset source extension.
* @param unknown $filters a list of filters, as defined below (see switch($filter_name) ...)
* @param unknown $debug true / false
- * @throws \Exception
+ * @throws \InvalidArgumentException if an invalid filter name is found
* @return string The URL to the generated asset file.
*/
public function asseticize($asset_path, $output_path, $output_url, $asset_type, $filters, $debug) {
@@ -90,7 +88,7 @@ class AsseticManager {
break;
default :
- throw new \Exception("Unsupported Assetic filter: '$filter_name'");
+ throw new \InvalidArgumentException("Unsupported Assetic filter: '$filter_name'");
break;
}
}
diff --git a/core/lib/Thelia/Core/Template/Parser.php b/core/lib/Thelia/Core/Template/Parser.php
deleted file mode 100644
index bf47caa40..000000000
--- a/core/lib/Thelia/Core/Template/Parser.php
+++ /dev/null
@@ -1,171 +0,0 @@
-. */
-/* */
-/*************************************************************************************/
-namespace Thelia\Core\Template;
-
-use Symfony\Component\HttpFoundation\Response;
-use Thelia\Core\Template\ParserInterface;
-use Symfony\Component\DependencyInjection\ContainerInterface;
-use Symfony\Component\HttpFoundation\Request;
-use Symfony\Component\Routing\Exception\ResourceNotFoundException;
-use Symfony\Component\Config\ConfigCache;
-
-use Thelia\Tpex\Tpex;
-use Thelia\Log\Tlog;
-
-/**
- *
- * Master class of Thelia's parser. The loop mechanism depends of this parser
- *
- * From this class all the parser is lunch
- *
- *
- * @author Manuel Raynaud
- */
-
-
-class Parser implements ParserInterface
-{
- const PREFIXE = 'prx';
-
- const SHOW_TIME = true;
- const ALLOW_DEBUG = true;
- const USE_CACHE = true;
-
-
- /**
- *
- * @var Symfony\Component\DependencyInjection\ContainerInterface
- */
- protected $container;
-
- protected $content;
- protected $status = 200;
-
- /**
- *
- * @var Thelia\Tpex\Tpex
- */
- protected $tpex;
-
- protected $template = "default";
-
- /**
- *
- * @param type $container
- *
- * public function __construct(ContainerBuilder $container)
- */
- public function __construct(ContainerInterface $container)
- {
- $this->container = $container;
- }
-
- /**
- *
- * @return Symfony\Component\HttpFoundation\Request
- */
- public function getRequest()
- {
- return $this->container->get('request');
- }
-
- /**
- *
- * @return Symfony\Component\EventDispatcher\EventDispatcher
- */
- public function getDispatcher()
- {
- return $this->container->get('dispatcher');
- }
-
- /**
- *
- * This method must return a Symfony\Component\HttpFoudation\Response instance or the content of the response
- *
- */
- public function getContent()
- {
- $this->loadParser();
-
- return $this->content;
- }
-
- /**
- *
- * 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()
- {
- $content = $this->openFile($this->getRequest());
-
- $tpex = $this->container->get("template");
-
- $tpex->setBaseDir(THELIA_TEMPLATE_DIR . rtrim($this->template, "/") . "/");
- $tpex->setContent($content);
-
- $this->setContent($tpex->execute());
- }
-
- protected function openFile(Request $request)
- {
- $file = $request->attributes->get('_view');
- $fileName = THELIA_TEMPLATE_DIR . rtrim($this->template, "/") . "/" . $file . ".html";
- if (file_exists($fileName)) {
- $content = file_get_contents($fileName);
- } else {
- throw new ResourceNotFoundException(sprintf("%s file not found in %s template", $file, $this->template));
- }
-
- return $content;
- }
-}
diff --git a/core/lib/Thelia/Core/Template/ParserInterface.php b/core/lib/Thelia/Core/Template/ParserInterface.php
index 4b3102fbf..08308659c 100644
--- a/core/lib/Thelia/Core/Template/ParserInterface.php
+++ b/core/lib/Thelia/Core/Template/ParserInterface.php
@@ -23,8 +23,6 @@
namespace Thelia\Core\Template;
/**
- *
- *
*
* @author Manuel Raynaud
*
diff --git a/core/lib/Thelia/Core/Template/Assets/SmartyAssetsManager.php b/core/lib/Thelia/Core/Template/Smarty/Assets/SmartyAssetsManager.php
similarity index 94%
rename from core/lib/Thelia/Core/Template/Assets/SmartyAssetsManager.php
rename to core/lib/Thelia/Core/Template/Smarty/Assets/SmartyAssetsManager.php
index 50a5e3ae2..69a611b3e 100644
--- a/core/lib/Thelia/Core/Template/Assets/SmartyAssetsManager.php
+++ b/core/lib/Thelia/Core/Template/Smarty/Assets/SmartyAssetsManager.php
@@ -17,13 +17,13 @@
/* 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 . */
+/* along with this program. If not, see . */
/* */
/*************************************************************************************/
-namespace Thelia\Core\Template\Assets;
+namespace Thelia\Core\Template\Smarty\Assets;
-use Thelia\Core\Template\Assets\AsseticManager;
+use Thelia\Core\Template\Assets\AsseticHelper;
class SmartyAssetsManager {
@@ -35,6 +35,7 @@ class SmartyAssetsManager {
private $path_relative_to_web_root;
/**
+ * Creates a new SmartyAssetsManager instance
*
* @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
@@ -44,7 +45,7 @@ class SmartyAssetsManager {
$this->web_root = $web_root;
$this->path_relative_to_web_root = $path_relative_to_web_root;
- $this->assetic_manager = new AsseticManager();
+ $this->assetic_manager = new AsseticHelper();
}
public function processSmartyPluginCall($assetType, $params, $content, \Smarty_Internal_Template $template, &$repeat) {
diff --git a/core/lib/Thelia/Core/Template/Smarty/Plugins/Assetic.php b/core/lib/Thelia/Core/Template/Smarty/Plugins/Assetic.php
index d083e083b..7b24b78be 100644
--- a/core/lib/Thelia/Core/Template/Smarty/Plugins/Assetic.php
+++ b/core/lib/Thelia/Core/Template/Smarty/Plugins/Assetic.php
@@ -1,18 +1,32 @@
. */
+/* */
+/*************************************************************************************/
namespace Thelia\Core\Template\Smarty\Plugins;
-use Thelia\Core\Template\Smarty\RegisterSmartyPlugin;
+use Thelia\Core\Template\Smarty\SmartyPluginDescriptor;
use Thelia\Core\Template\Smarty\SmartyPluginInterface;
-use Thelia\Core\Template\Assets\SmartyAssetsManager;
+use Thelia\Core\Template\Smarty\Assets\SmartyAssetsManager;
class Assetic implements SmartyPluginInterface {
@@ -45,14 +59,16 @@ class Assetic implements SmartyPluginInterface {
}
/**
- * @return mixed
+ * Define the various smarty plugins hendled by this class
+ *
+ * @return an array of smarty plugin descriptors
*/
- public function registerPlugins()
+ public function getPluginDescriptors()
{
return array(
- new RegisterSmartyPlugin('block', 'stylesheets', $this, 'theliaBlockStylesheets'),
- new RegisterSmartyPlugin('block', 'javascripts', $this, 'theliaBlockJavascripts'),
- new RegisterSmartyPlugin('block', 'images', $this, 'theliaBlockImages')
+ new SmartyPluginDescriptor('block', 'stylesheets', $this, 'theliaBlockStylesheets'),
+ new SmartyPluginDescriptor('block', 'javascripts', $this, 'theliaBlockJavascripts'),
+ new SmartyPluginDescriptor('block', 'images' , $this, 'theliaBlockImages')
);
}
}
\ No newline at end of file
diff --git a/core/lib/Thelia/Core/Template/Smarty/Plugins/TheliaLoop.php b/core/lib/Thelia/Core/Template/Smarty/Plugins/TheliaLoop.php
new file mode 100644
index 000000000..162f261b5
--- /dev/null
+++ b/core/lib/Thelia/Core/Template/Smarty/Plugins/TheliaLoop.php
@@ -0,0 +1,291 @@
+. */
+/* */
+/*************************************************************************************/
+
+namespace Thelia\Core\Template\Smarty\Plugins;
+
+use Thelia\Core\Template\Smarty\SmartyPluginInterface;
+use Thelia\Core\Template\Smarty\SmartyPluginDescriptor;
+
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\EventDispatcher\EventDispatcherInterface;
+
+class TheliaLoop implements SmartyPluginInterface {
+
+ protected $loopDefinition = array();
+
+ protected $request;
+
+ protected $dispatcher;
+
+ public function __construct(Request $request, EventDispatcherInterface $dispatcher) {
+ $this->request = $request;
+ $this->dispatcher = $dispatcher;
+ }
+
+ /**
+ * Process {loop name="loop name" type="loop type" ... } ... {/loop} block
+ *
+ * @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
+ */
+ 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
+ */
+ 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;
+ }
+ }
+
+ /**
+ * 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();
+ }
+
+ /**
+ *
+ * find the loop class with his name and construct an instance of this class
+ *
+ * @param string $name
+ * @return \Thelia\Tpex\Element\Loop\BaseLoop
+ * @throws \Thelia\Tpex\Exception\InvalidElementException
+ * @throws \Thelia\Tpex\Exception\ElementNotFoundException
+ */
+ protected function createLoopInstance($name)
+ {
+
+ if (! isset($this->loopDefinition[$name])) {
+ throw new ElementNotFoundException(sprintf("%s loop does not exists", $name));
+ }
+
+ $class = new \ReflectionClass($this->loopDefinition[$name]);
+
+ if ($class->isSubclassOf("Thelia\Tpex\Element\Loop\BaseLoop") === false) {
+ throw new InvalidElementException(sprintf("%s Loop class have to extends Thelia\Tpex\Element\Loop\BaseLoop",
+ $name));
+ }
+
+ return $class->newInstance(
+ $this->request,
+ $this->dispatcher
+ );
+ }
+
+
+ /**
+ * Returns the value of a loop argument.
+ *
+ * @param unknown $loop a BaseLoop instance
+ * @param unknown $smartyParam
+ * @throws \InvalidArgumentException
+ */
+ protected function getLoopArgument($loop, $smartyParam)
+ {
+ $defaultItemsParams = array('required' => true);
+
+ $shortcutItemParams = array('optional' => array('required' => false));
+
+ $errorCode = 0;
+ $faultActor = array();
+ $faultDetails = array();
+
+ foreach($loop->defineArgs() as $name => $param){
+ if(is_integer($name)){
+ $name = $param;
+ $param = $defaultItemsParams;
+ }
+
+ if(is_string($param) && array_key_exists($param, $shortcutItemParams)){
+ $param = $shortcutItemParams[$param];
+ }
+
+ if(!is_array($param)){
+ $param = array('default' => $param);
+ }
+
+ $value = isset($smartyParam[$name]) ? $smartyParam[$name] : null;
+
+ if($value == null){
+ if(isset($param['default'])){
+ $value = $param['default'];
+ }
+ else if($param['required'] === true){
+ $faultActor[] = $name;
+ $faultDetails[] = sprintf('"%s" parameter is missing', $name);
+ continue;
+ }
+ }
+
+ $loop->{$name} = $value;
+ }
+
+ if(!empty($faultActor)){
+
+ $complement = sprintf('[%s]', implode(', ', $faultDetails));
+ throw new \InvalidArgumentException($complement);
+ }
+ }
+
+ /**
+ *
+ * Injects an associative array containing information for loop execution
+ *
+ * key is loop name
+ * value is the class implementing/extending base loop classes
+ *
+ * ex :
+ *
+ * $loop = array(
+ * "product" => "Thelia\Loop\Product",
+ * "category" => "Thelia\Loop\Category",
+ * "myLoop" => "My\Own\Loop"
+ * );
+ *
+ * @param array $loops
+ * @throws \InvalidArgumentException if loop name already exists
+ */
+ public function setLoopList(array $loopDefinition)
+ {
+ foreach ($loopDefinition as $name => $className) {
+ if (array_key_exists($name, $this->loopDefinition)) {
+ throw new \InvalidArgumentException(sprintf("%s loop name already exists for %s class name", $name, $className));
+ }
+
+ $this->loopDefinition[$name] = $className;
+ }
+ }
+
+ /**
+ * Defines the various smarty plugins hendled by this class
+ *
+ * @return an array of smarty plugin descriptors
+ */
+ public function getPluginDescriptors()
+ {
+ return array(
+ new SmartyPluginDescriptor('block', 'loop' , $this, 'theliaLoop'),
+ new SmartyPluginDescriptor('block', 'elseloop' , $this, 'theliaElseloop'),
+ new SmartyPluginDescriptor('block', 'ifloop' , $this, 'theliaIfLoop')
+ );
+ }
+}
\ No newline at end of file
diff --git a/core/lib/Thelia/Core/Template/Smarty/RegisterSmartyPlugin.php b/core/lib/Thelia/Core/Template/Smarty/RegisterSmartyPlugin.php
deleted file mode 100644
index f48d05cd9..000000000
--- a/core/lib/Thelia/Core/Template/Smarty/RegisterSmartyPlugin.php
+++ /dev/null
@@ -1,26 +0,0 @@
-type = $type;
- $this->name = $name;
- $this->class = $class;
- $this->method = $method;
- }
-}
\ No newline at end of file
diff --git a/core/lib/Thelia/Core/Template/Smarty/SmartyParser.php b/core/lib/Thelia/Core/Template/Smarty/SmartyParser.php
new file mode 100644
index 000000000..ecf5b352c
--- /dev/null
+++ b/core/lib/Thelia/Core/Template/Smarty/SmartyParser.php
@@ -0,0 +1,210 @@
+
+ */
+class SmartyParser extends Smarty implements ParserInterface {
+
+ public $plugins = array();
+
+ protected $request, $dispatcher;
+
+ protected $template = "";
+
+ protected $status = 200;
+
+ /**
+ * @param \Symfony\Component\HttpFoundation\Request $request
+ * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $dispatcher
+ */
+ public function __construct(Request $request, EventDispatcherInterface $dispatcher, $template = false)
+ {
+ parent::__construct();
+
+ $this->request = $request;
+ $this->dispatcher = $dispatcher;
+
+ // 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);
+
+ $this->setTemplate($template != false ? $template : 'smarty-sample');
+
+ $this->setCompileDir($compile_dir);
+ $this->setCacheDir($cache_dir);
+
+ // Prevent smarty ErrorException: Notice: Undefined index bla bla bla...
+ $this->error_reporting = E_ALL ^ E_NOTICE;
+
+ // Activer le cache, avec une lifetime de 15mn, et en vérifiant que les templates sources n'ont pas été modifiés.
+ $this->caching = 1;
+ $this->cache_lifetime = 300;
+ $this->compile_check = true;
+
+ // The default HTTP status
+ $this->status = 200;
+
+ // 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'));
+ }
+
+ public function setTemplate($template_path_from_template_base) {
+
+ $this->template = $template_path_from_template_base;
+
+ $this->setTemplateDir(THELIA_TEMPLATE_DIR.$this->template);
+ }
+
+ public function getTemplate() {
+ return $this->template;
+ }
+
+ /**
+ * Return a rendered template file
+ *
+ * @param string $realTemplateName the template name (from the template directory)
+ * @param array $parameters an associative array of names / value pairs
+ * @return string the rendered template text
+ */
+ public function render($realTemplateName, array $parameters) {
+
+ $this->assign($parameters);
+
+ return $this->fetch($realTemplateName);
+ }
+
+ /**
+ * 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 "";
+ }
+
+ /**
+ *
+ * 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;
+ }
+
+ public function addPlugins(SmartyPluginInterface $plugin)
+ {
+ $this->plugins[] = $plugin;
+ }
+
+ public function registerPlugins()
+ {
+ foreach ($this->plugins as $register_plugin) {
+ $plugins = $register_plugin->getPluginDescriptors();
+
+ if(!is_array($plugins)) {
+ $plugins = array($plugins);
+ }
+
+ foreach ($plugins as $plugin) {
+ $this->registerPlugin(
+ $plugin->getType(),
+ $plugin->getName(),
+ array(
+ $plugin->getClass(),
+ $plugin->getMethod()
+ )
+ );
+ }
+ }
+ }
+
+ protected function getTemplateFilePath()
+ {
+ $file = $this->request->attributes->get('_view');
+
+ $fileName = THELIA_TEMPLATE_DIR . rtrim($this->template, "/") . "/" . $file . ".html";
+
+ if (file_exists($fileName)) return $fileName;
+
+ throw new ResourceNotFoundException(sprintf("%s file not found in %s template", $file, $this->template));
+ }
+}
\ No newline at end of file
diff --git a/core/lib/Thelia/Core/Template/Smarty/SmartyPluginDescriptor.php b/core/lib/Thelia/Core/Template/Smarty/SmartyPluginDescriptor.php
new file mode 100644
index 000000000..3e8fec8ad
--- /dev/null
+++ b/core/lib/Thelia/Core/Template/Smarty/SmartyPluginDescriptor.php
@@ -0,0 +1,87 @@
+. */
+/* */
+/*************************************************************************************/
+
+namespace Thelia\Core\Template\Smarty;
+
+class SmartyPluginDescriptor {
+
+ /**
+ * @var string Smarty plugin type (block, function, etc.)
+ */
+ protected $type;
+
+ /**
+ * @var string Smarty plugin name. This name will be used in Smarty templates.
+ */
+ protected $name;
+
+ /**
+ * @var SmartyPluginInterface plugin implmentation class
+ */
+ protected $class;
+
+ /**
+ * @var string plugin implmentation method in $class
+ */
+ protected $method;
+
+ public function __construct($type, $name, $class, $method)
+ {
+ $this->type = $type;
+ $this->name = $name;
+ $this->class = $class;
+ $this->method = $method;
+ }
+
+ public function setType($type) {
+ $this->type = $type;
+ }
+
+ public function getType() {
+ return $this->type;
+ }
+
+ public function setName($name) {
+ $this->name = $name;
+ }
+
+ public function getName() {
+ return $this->name;
+ }
+
+ public function setClass($class) {
+ $this->class = $class;
+ }
+
+ public function getClass() {
+ return $this->class;
+ }
+
+ public function setMethod($method) {
+ $this->method = $method;
+ }
+
+ public function getMethod() {
+ return $this->method;
+ }
+}
\ No newline at end of file
diff --git a/core/lib/Thelia/Core/Template/Smarty/SmartyPluginInterface.php b/core/lib/Thelia/Core/Template/Smarty/SmartyPluginInterface.php
index 3c6c55a14..87705c467 100644
--- a/core/lib/Thelia/Core/Template/Smarty/SmartyPluginInterface.php
+++ b/core/lib/Thelia/Core/Template/Smarty/SmartyPluginInterface.php
@@ -1,19 +1,31 @@
. */
+/* */
+/*************************************************************************************/
namespace Thelia\Core\Template\Smarty;
-
interface SmartyPluginInterface {
/**
- * @return mixed
+ * @return an array of SmartyPluginDescriptor
*/
- public function registerPlugins();
-
+ public function getPluginDescriptors();
}
\ No newline at end of file
diff --git a/core/lib/Thelia/Core/Template/SmartyParser.php b/core/lib/Thelia/Core/Template/SmartyParser.php
deleted file mode 100644
index d0dcab7d0..000000000
--- a/core/lib/Thelia/Core/Template/SmartyParser.php
+++ /dev/null
@@ -1,455 +0,0 @@
-
- */
-class SmartyParser extends Smarty implements ParserInterface {
-
- public $plugins = array();
-
- protected $request, $dispatcher;
-
- protected $template = "";
-
- protected $status = 200;
-
- protected $loopDefinition = array();
-
- protected $asset_manager = null; // Lazy loading
-
- /**
- * @param \Symfony\Component\HttpFoundation\Request $request
- * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $dispatcher
- */
- public function __construct(Request $request, EventDispatcherInterface $dispatcher, $template = false)
- {
- parent::__construct();
-
- $this->request = $request;
- $this->dispatcher = $dispatcher;
-
- // 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);
-
- $this->setTemplate($template != false ? $template : 'smarty-sample');
-
- $this->setCompileDir($compile_dir);
- $this->setCacheDir($cache_dir);
-
- // 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'));
- }
-
- public function setTemplate($template_path_from_template_base) {
-
- $this->template = $template_path_from_template_base;
-
- $this->setTemplateDir(THELIA_TEMPLATE_DIR.$this->template);
- }
-
- public function getTemplate() {
- return $this->template;
- }
-
- /**
- * Return a rendered template file
- *
- * @param string $realTemplateName the template name (from the template directory)
- * @param array $parameters an associative array of names / value pairs
- * @return string the rendered template text
- */
- public function render($realTemplateName, array $parameters) {
-
- $this->assign($parameters);
-
- return $this->fetch($realTemplateName);
- }
-
- /**
- * Process {loop name="loop name" type="loop type" ... } ... {/loop} block
- *
- * @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
- */
- 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
- */
- 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 "";
- }
-
- /**
- *
- * 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
- *
- * ex :
- *
- * $loop = array(
- * "product" => "Thelia\Loop\Product",
- * "category" => "Thelia\Loop\Category",
- * "myLoop" => "My\Own\Loop"
- * );
- *
- * @param array $loops
- * @throws \InvalidArgumentException if loop name already exists
- */
- public function setLoopList(array $loopDefinition)
- {
- foreach ($loopDefinition as $name => $className) {
- if (array_key_exists($name, $this->loopDefinition)) {
- throw new \InvalidArgumentException(sprintf("%s loop name already exists for %s class name", $name, $className));
- }
-
- $this->loopDefinition[$name] = $className;
- }
- }
-
- public function addPlugins(SmartyPluginInterface $plugin)
- {
- $this->plugins[] = $plugin;
- }
-
- public function registerPlugins()
- {
- foreach ($this->plugins as $register_plugin) {
- $plugins = $register_plugin->registerPlugins();
-
- if(!is_array($plugins)) {
- $plugins = array($plugins);
- }
-
- foreach ($plugins as $plugin) {
- $this->registerPlugin(
- $plugin->type,
- $plugin->name,
- array(
- $plugin->class,
- $plugin->method
- )
- );
- }
- }
- }
-
-
- /**
- * Returns the value of a loop argument.
- *
- * @param unknown $loop a BaseLoop instance
- * @param unknown $smartyParam
- * @throws \InvalidArgumentException
- */
- protected function getLoopArgument($loop, $smartyParam)
- {
- $defaultItemsParams = array('required' => true);
-
- $shortcutItemParams = array('optional' => array('required' => false));
-
- $errorCode = 0;
- $faultActor = array();
- $faultDetails = array();
-
- foreach($loop->defineArgs() as $name => $param){
- if(is_integer($name)){
- $name = $param;
- $param = $defaultItemsParams;
- }
-
- if(is_string($param) && array_key_exists($param, $shortcutItemParams)){
- $param = $shortcutItemParams[$param];
- }
-
- if(!is_array($param)){
- $param = array('default' => $param);
- }
-
- $value = isset($smartyParam[$name]) ? $smartyParam[$name] : null;
-
- if($value == null){
- if(isset($param['default'])){
- $value = $param['default'];
- }
- else if($param['required'] === true){
- $faultActor[] = $name;
- $faultDetails[] = sprintf('"%s" parameter is missing', $name);
- continue;
- }
- }
-
- $loop->{$name} = $value;
- }
-
- if(!empty($faultActor)){
-
- $complement = sprintf('[%s]', implode(', ', $faultDetails));
- throw new \InvalidArgumentException($complement);
- }
- }
-
- /**
- *
- * find the loop class with his name and construct an instance of this class
- *
- * @param string $name
- * @return \Thelia\Tpex\Element\Loop\BaseLoop
- * @throws \Thelia\Tpex\Exception\InvalidElementException
- * @throws \Thelia\Tpex\Exception\ElementNotFoundException
- */
- protected function createLoopInstance($name)
- {
-
- if (! isset($this->loopDefinition[$name])) {
- throw new ElementNotFoundException(sprintf("%s loop does not exists", $name));
- }
-
- $class = new \ReflectionClass($this->loopDefinition[$name]);
-
- if ($class->isSubclassOf("Thelia\Tpex\Element\Loop\BaseLoop") === false) {
- throw new InvalidElementException(sprintf("%s Loop class have to extends Thelia\Tpex\Element\Loop\BaseLoop",
- $name));
- }
-
- return $class->newInstance(
- $this->request,
- $this->dispatcher
- );
- }
-
- protected function getTemplateFilePath()
- {
- $file = $this->request->attributes->get('_view');
-
- $fileName = THELIA_TEMPLATE_DIR . rtrim($this->template, "/") . "/" . $file . ".html";
-
- if (file_exists($fileName)) return $fileName;
-
- 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;
- }
-}
diff --git a/core/lib/Thelia/Tpex b/core/lib/Thelia/Tpex
index 8561f3516..b1c517281 160000
--- a/core/lib/Thelia/Tpex
+++ b/core/lib/Thelia/Tpex
@@ -1 +1 @@
-Subproject commit 8561f3516ea03a20e397c4c3aba530fbc6adc364
+Subproject commit b1c517281eb3c9b50260b0cf2b5e41ffa94808e0
diff --git a/web/.htaccess b/web/.htaccess
index 1c2d2bbe7..4336ad269 100755
--- a/web/.htaccess
+++ b/web/.htaccess
@@ -8,7 +8,5 @@ AddDefaultCharset UTF-8
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
- RewriteBase /thelia2
-
RewriteRule ^admin(/.*)?$ index_dev.php/admin/$1 [L,QSA]
\ No newline at end of file