diff --git a/core/lib/Thelia/Core/Template/Element/BaseLoop.php b/core/lib/Thelia/Core/Template/Element/BaseLoop.php index b6085ad7c..519aae4bd 100755 --- a/core/lib/Thelia/Core/Template/Element/BaseLoop.php +++ b/core/lib/Thelia/Core/Template/Element/BaseLoop.php @@ -25,6 +25,7 @@ namespace Thelia\Core\Template\Element; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Thelia\Core\Template\Loop\Argument\ArgumentCollection; /** * @@ -96,7 +97,7 @@ abstract class BaseLoop * ) * ); * - * @return array + * @return ArgumentCollection */ abstract public function defineArgs(); diff --git a/core/lib/Thelia/Core/Template/Loop/Argument/Argument.php b/core/lib/Thelia/Core/Template/Loop/Argument/Argument.php new file mode 100755 index 000000000..d2b6cdbb2 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/Argument/Argument.php @@ -0,0 +1,45 @@ +. */ +/* */ +/*************************************************************************************/ +namespace Thelia\Core\Template\Loop\Argument; + +/** + * + * @author Etienne Roudeix + * + */ +class Argument +{ + public $name; + public $type; + public $default; + public $mandatory; + public $empty; + + public function __construct($name, \Thelia\Type\TypeCollection $type, $default = null, $mandatory = false, $empty = true) + { + $this->name = $name; + $this->type = $type; + $this->mandatory = $mandatory ? true : false; + $this->default = $default; + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/Argument/ArgumentCollection.php b/core/lib/Thelia/Core/Template/Loop/Argument/ArgumentCollection.php new file mode 100755 index 000000000..d3422c1e9 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/Argument/ArgumentCollection.php @@ -0,0 +1,119 @@ +. */ +/* */ +/*************************************************************************************/ +namespace Thelia\Core\Template\Loop\Argument; + +/** + * + * @author Etienne Roudeix + * + */ + +class ArgumentCollection implements \Iterator +{ + private $position; + protected $arguments = array(); + + public function __construct() + { + foreach(func_get_args() as $argument) { + $this->addArgument($argument); + } + } + + public function isEmpty() + { + return count($this->arguments) == 0; + } + + /** + * @param Argument $argument + * + * @return ArgumentCollection + */ + public function addArgument(Argument $argument) + { + $this->arguments[] = $argument; + return $this; + } + + public function getCount() + { + return count($this->arguments); + } + + /** + * (PHP 5 >= 5.0.0)
+ * Return the current element + * @link http://php.net/manual/en/iterator.current.php + * @return Argument + */ + public function current() + { + return $this->arguments[$this->position]; + } + + /** + * (PHP 5 >= 5.0.0)
+ * Move forward to next element + * @link http://php.net/manual/en/iterator.next.php + * @return void Any returned value is ignored. + */ + public function next() + { + $this->position++; + } + + /** + * (PHP 5 >= 5.0.0)
+ * Return the key of the current element + * @link http://php.net/manual/en/iterator.key.php + * @return mixed scalar on success, or null on failure. + */ + public function key() + { + return $this->position; + } + + /** + * (PHP 5 >= 5.0.0)
+ * Checks if current position is valid + * @link http://php.net/manual/en/iterator.valid.php + * @return boolean The return value will be casted to boolean and then evaluated. + * Returns true on success or false on failure. + */ + public function valid() + { + return isset($this->arguments[$this->position]); + } + + /** + * (PHP 5 >= 5.0.0)
+ * Rewind the Iterator to the first element + * @link http://php.net/manual/en/iterator.rewind.php + * @return void Any returned value is ignored. + */ + public function rewind() + { + $this->position = 0; + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/Category.php b/core/lib/Thelia/Core/Template/Loop/Category.php index 6a996d813..dadb69505 100755 --- a/core/lib/Thelia/Core/Template/Loop/Category.php +++ b/core/lib/Thelia/Core/Template/Loop/Category.php @@ -28,8 +28,12 @@ namespace Thelia\Core\Template\Loop; use Thelia\Core\Template\Element\BaseLoop; use Thelia\Core\Template\Element\LoopResult; use Thelia\Core\Template\Element\LoopResultRow; +use Thelia\Core\Template\Loop\Argument\ArgumentCollection; +use Thelia\Core\Template\Loop\Argument\Argument; use Thelia\Log\Tlog; use Thelia\Model\CategoryQuery; +use Thelia\Type\TypeCollection; +use Thelia\Type; /** * @@ -77,18 +81,78 @@ class Category extends BaseLoop { public function defineArgs() { - return array( - "id" => "optional", - "parent" => "optional", - "current" => "optional", - "not_empty" => 0, - "visible" => 1, - "link" => "optional", - "order" => "optional", - "random" => 0, - "exclude" => "optional", - "limit" => 10, - "offset" => 0, + return new ArgumentCollection( + new Argument( + 'id', + new TypeCollection( + new Type\IntListType() + ) + ), + new Argument( + 'parent', + new TypeCollection( + new Type\IntType() + ) + ), + new Argument( + 'current', + new TypeCollection( + new Type\IntType() + ) + ), + new Argument( + 'not_empty', + new TypeCollection( + new Type\IntType() + ), + 0 + ), + new Argument( + 'visible', + new TypeCollection( + new Type\IntType() + ), + 1 + ), + new Argument( + 'link', + new TypeCollection( + new Type\AnyType() + ) + ), + new Argument( + 'order', + new TypeCollection( + new Type\EnumType('alpha', 'alpha_reverse', 'reverse') + ) + ), + new Argument( + 'random', + new TypeCollection( + new Type\AnyType() + ), + 0 + ), + new Argument( + 'exclude', + new TypeCollection( + new Type\IntListType() + ) + ), + new Argument( + 'limit', + new TypeCollection( + new Type\IntType() + ), + 10 + ), + new Argument( + 'offset', + new TypeCollection( + new Type\IntType() + ), + 0 + ) ); } diff --git a/core/lib/Thelia/Core/Template/Smarty/Plugins/TheliaLoop.php b/core/lib/Thelia/Core/Template/Smarty/Plugins/TheliaLoop.php index d8b1abd9a..67ccfcf98 100755 --- a/core/lib/Thelia/Core/Template/Smarty/Plugins/TheliaLoop.php +++ b/core/lib/Thelia/Core/Template/Smarty/Plugins/TheliaLoop.php @@ -23,6 +23,7 @@ namespace Thelia\Core\Template\Smarty\Plugins; +use Thelia\Core\Template\Element\BaseLoop; use Thelia\Core\Template\Smarty\SmartyPluginInterface; use Thelia\Core\Template\Smarty\SmartyPluginDescriptor; @@ -32,7 +33,8 @@ use Thelia\Core\Template\Element\Exception\InvalidElementException; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\EventDispatcher\EventDispatcherInterface; -class TheliaLoop implements SmartyPluginInterface { +class TheliaLoop implements SmartyPluginInterface +{ protected $loopDefinition = array(); @@ -40,7 +42,8 @@ class TheliaLoop implements SmartyPluginInterface { protected $dispatcher; - public function __construct(Request $request, EventDispatcherInterface $dispatcher) { + public function __construct(Request $request, EventDispatcherInterface $dispatcher) + { $this->request = $request; $this->dispatcher = $dispatcher; } @@ -55,7 +58,8 @@ class TheliaLoop implements SmartyPluginInterface { * @throws \InvalidArgumentException * @return string */ - public function theliaLoop($params, $content, $template, &$repeat) { + public function theliaLoop($params, $content, $template, &$repeat) + { if (empty($params['name'])) throw new \InvalidArgumentException("Missing 'name' parameter in loop arguments"); @@ -87,13 +91,12 @@ class TheliaLoop implements SmartyPluginInterface { $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()); } + $template->assign('__COUNT__', 1 + $loopResults->key()); + $template->assign('__TOTAL__', $loopResults->getCount()); + $repeat = $loopResults->valid(); } @@ -115,7 +118,8 @@ class TheliaLoop implements SmartyPluginInterface { * @param unknown $repeat * @return Ambigous */ - public function theliaElseloop($params, $content, $template, &$repeat) { + public function theliaElseloop($params, $content, $template, &$repeat) + { // When encoutering close tag, check if loop has results. if ($repeat === false) { @@ -133,7 +137,8 @@ class TheliaLoop implements SmartyPluginInterface { * @param unknown $repeat * @return Ambigous */ - public function theliaIfLoop($params, $content, $template, &$repeat) { + public function theliaIfLoop($params, $content, $template, &$repeat) + { // When encountering close tag, check if loop has results. if ($repeat === false) { @@ -149,7 +154,8 @@ class TheliaLoop implements SmartyPluginInterface { * @param unknown $template * @throws \InvalidArgumentException */ - protected function checkEmptyLoop($params, $template) { + protected function checkEmptyLoop($params, $template) + { if (empty($params['rel'])) throw new \InvalidArgumentException("Missing 'rel' parameter in ifloop/elseloop arguments"); @@ -202,7 +208,7 @@ class TheliaLoop implements SmartyPluginInterface { * @param unknown $smartyParam * @throws \InvalidArgumentException */ - protected function getLoopArgument($loop, $smartyParam) + protected function getLoopArgument(BaseLoop $loop, $smartyParam) { $defaultItemsParams = array('required' => true); @@ -212,35 +218,40 @@ class TheliaLoop implements SmartyPluginInterface { $faultActor = array(); $faultDetails = array(); - foreach($loop->defineArgs() as $name => $param){ - if(is_integer($name)){ - $name = $param; - $param = $defaultItemsParams; - } + $argumentsCollection = $loop->defineArgs(); + foreach( $argumentsCollection as $argument ) { - if(is_string($param) && array_key_exists($param, $shortcutItemParams)){ - $param = $shortcutItemParams[$param]; - } + $value = isset($smartyParam[$argument->name]) ? $smartyParam[$argument->name] : null; - if(!is_array($param)){ - $param = array('default' => $param); - } + /* check if mandatory */ + if($value === null && $argument->mandatory) { + $faultActor[] = $argument->name; + $faultDetails[] = sprintf('"%s" parameter is missing', $argument->name); + continue; + } - $value = isset($smartyParam[$name]) ? $smartyParam[$name] : null; + /* check if empty */ + if($value === '' && !$argument->empty) { + $faultActor[] = $argument->name; + $faultDetails[] = sprintf('"%s" parameter cannot be empty', $argument->name); + continue; + } - 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; - } - } + /* check type */ + if($value !== null && !$argument->type->isValid($value)) { + $faultActor[] = $argument->name; + $faultDetails[] = sprintf('Invalid value for "%s" argument', $argument->name); + continue; + } - $loop->{$name} = $value; - } + /* set default */ + /* did it as last checking for we consider default value is acceptable no matter type or empty restriction */ + if($value === null) { + $value = $argument->default; + } + + $loop->{$argument->name} = $value; + } if(!empty($faultActor)){ @@ -288,7 +299,7 @@ class TheliaLoop implements SmartyPluginInterface { return array( new SmartyPluginDescriptor('block', 'loop' , $this, 'theliaLoop'), new SmartyPluginDescriptor('block', 'elseloop' , $this, 'theliaElseloop'), - new SmartyPluginDescriptor('block', 'ifloop' , $this, 'theliaIfLoop') + new SmartyPluginDescriptor('block', 'ifloop' , $this, 'theliaIfLoop'), ); } } \ 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 index 61ceab822..6800ca6f5 100755 --- a/core/lib/Thelia/Core/Template/Smarty/SmartyParser.php +++ b/core/lib/Thelia/Core/Template/Smarty/SmartyParser.php @@ -8,17 +8,17 @@ use \Symfony\Component\EventDispatcher\EventDispatcherInterface; use \Smarty; use Thelia\Core\Template\ParserInterface; -use Thelia\Core\Template\Loop\Category; use Thelia\Core\Template\Smarty\SmartyPluginInterface; -use Thelia\Core\Template\Smarty\Assets\SmartyAssetsManager; use Thelia\Core\Template\Exception\ResourceNotFoundException; /** * * @author Franck Allimant + * @author Etienne Roudeix */ -class SmartyParser extends Smarty implements ParserInterface { +class SmartyParser extends Smarty implements ParserInterface +{ public $plugins = array(); @@ -59,14 +59,28 @@ class SmartyParser extends Smarty implements ParserInterface { // Prevent smarty ErrorException: Notice: Undefined index bla bla bla... $this->error_reporting = E_ALL ^ E_NOTICE; - // Activate caching, with a 15mn lifetime, and check template sources modifications. - // FIXME: put this in configuration - $this->caching = 1; - $this->cache_lifetime = 300; - $this->compile_check = true; + // Si on n'est pas en mode debug, activer le cache, avec une lifetime de 15mn, et en vérifiant que les templates sources n'ont pas été modifiés. + if($debug === false) { + $this->caching = Smarty::CACHING_LIFETIME_CURRENT; + $this->cache_lifetime = 300; + $this->compile_check = true; + } else { + $this->caching = Smarty::CACHING_OFF; + $this->force_compile = true; + } // The default HTTP status $this->status = 200; + + $this->registerFilter('pre', array($this, "pretest")); + } + + public function pretest($tpl_source, \Smarty_Internal_Template $template) + { + $new_source = preg_replace('`{#([a-zA-Z][a-zA-Z0-9\-_]*)(.*)}`', '{\$$1$2}', $tpl_source); + $new_source = preg_replace('`#([a-zA-Z][a-zA-Z0-9\-_]*)`', '{\$$1|default:\'#$1\'}', $new_source); + + return $new_source; } public function setTemplate($template_path_from_template_base) { diff --git a/core/lib/Thelia/Tests/Core/Template/Loop/Argument/ArgumentTest.php b/core/lib/Thelia/Tests/Core/Template/Loop/Argument/ArgumentTest.php new file mode 100755 index 000000000..7c5ce5d16 --- /dev/null +++ b/core/lib/Thelia/Tests/Core/Template/Loop/Argument/ArgumentTest.php @@ -0,0 +1,129 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Tests\Core\Template\Loop\Argument; + +use Thelia\Core\Template\Loop\Argument\ArgumentCollection; +use Thelia\Core\Template\Loop\Argument\Argument; +use Thelia\Type; +use Thelia\Type\TypeCollection; + +/** + * + * @author Etienne Roudeix + * + */ +class ArgumentTest extends \PHPUnit_Framework_TestCase +{ + public function testArgumentCollectionConstruction() + { + $collection = new ArgumentCollection( + new Argument( + 'arg0', + new TypeCollection( + new Type\AnyType() + ) + ), + new Argument( + 'arg1', + new TypeCollection( + new Type\AnyType() + ) + ) + ); + + $collection->addArgument( + new Argument( + 'arg2', + new TypeCollection( + new Type\AnyType() + ) + ) + ); + + $this->assertAttributeEquals( + array( + 0 => new Argument( + 'arg0', + new TypeCollection( + new Type\AnyType() + ) + ), + 1 => new Argument( + 'arg1', + new TypeCollection( + new Type\AnyType() + ) + ), + 2 => new Argument( + 'arg2', + new TypeCollection( + new Type\AnyType() + ) + ), + ), + 'arguments', + $collection + ); + } + + public function testArgumentCollectionFetch() + { + $collection = new ArgumentCollection( + new Argument( + 'arg0', + new TypeCollection( + new Type\AnyType() + ) + ), + new Argument( + 'arg1', + new TypeCollection( + new Type\AnyType() + ) + ), + new Argument( + 'arg2', + new TypeCollection( + new Type\AnyType() + ) + ) + ); + + + $arguments = \PHPUnit_Framework_Assert::readAttribute($collection, 'arguments'); + + $collection->rewind(); + while ($collection->valid()) { + + $argument = $collection->current(); + + $this->assertEquals( + $argument, + $arguments[$collection->key()] + ); + + $collection->next(); + } + } +} diff --git a/core/lib/Thelia/Tests/Type/TypeTest.php b/core/lib/Thelia/Tests/Type/TypeTest.php new file mode 100755 index 000000000..4b7c65df8 --- /dev/null +++ b/core/lib/Thelia/Tests/Type/TypeTest.php @@ -0,0 +1,113 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Tests\Type; + +use Thelia\Type; +use Thelia\Type\TypeCollection; + +/** + * + * @author Etienne Roudeix + * + */ +class TypeTest extends \PHPUnit_Framework_TestCase +{ + public function testTypeCollectionConstruction() + { + $collection = new TypeCollection( + new Type\AnyType(), + new Type\AnyType() + ); + + $collection->addType( + new Type\AnyType() + ); + + $this->assertAttributeEquals( + array( + new Type\AnyType(), + new Type\AnyType(), + new Type\AnyType(), + ), + 'types', + $collection + ); + } + + public function testTypeCollectionFetch() + { + $collection = new TypeCollection( + new Type\AnyType(), + new Type\AnyType(), + new Type\AnyType() + ); + + + $types = \PHPUnit_Framework_Assert::readAttribute($collection, 'types'); + + $collection->rewind(); + while ($collection->valid()) { + + $type = $collection->current(); + + $this->assertEquals( + $type, + $types[$collection->key()] + ); + + $collection->next(); + } + } + + public function testTypes() + { + $anyType = new Type\AnyType(); + $this->assertTrue($anyType->isValid(md5(rand(1000, 10000)))); + + $intType = new Type\IntType(); + $this->assertTrue($intType->isValid('1')); + $this->assertTrue($intType->isValid(2)); + $this->assertFalse($intType->isValid('3.3')); + + $floatType = new Type\FloatType(); + $this->assertTrue($floatType->isValid('1.1')); + $this->assertTrue($floatType->isValid(2.2)); + $this->assertFalse($floatType->isValid('foo')); + + $enumType = new Type\EnumType(array("cat", "dog")); + $this->assertTrue($enumType->isValid('cat')); + $this->assertTrue($enumType->isValid('dog')); + $this->assertFalse($enumType->isValid('monkey')); + $this->assertFalse($enumType->isValid('catdog')); + + $intListType = new Type\IntListType(); + $this->assertTrue($intListType->isValid('1')); + $this->assertTrue($intListType->isValid('1,2,3')); + $this->assertFalse($intListType->isValid('1,2,3.3')); + + $jsonType = new Type\JsonType(); + $this->assertTrue($jsonType->isValid('{"k0":"v0","k1":"v1","k2":"v2"}')); + $this->assertFalse($jsonType->isValid('1,2,3')); + } +} diff --git a/core/lib/Thelia/Type/AnyType.php b/core/lib/Thelia/Type/AnyType.php new file mode 100755 index 000000000..5b00a5aeb --- /dev/null +++ b/core/lib/Thelia/Type/AnyType.php @@ -0,0 +1,42 @@ +. */ +/* */ +/*************************************************************************************/ +namespace Thelia\Type; + +/** + * + * @author Etienne Roudeix + * + */ + +class AnyType implements TypeInterface +{ + public function getType() + { + return 'Any type'; + } + + public function isValid($value) + { + return true; + } +} diff --git a/core/lib/Thelia/Type/EnumType.php b/core/lib/Thelia/Type/EnumType.php new file mode 100755 index 000000000..d0a1c9b89 --- /dev/null +++ b/core/lib/Thelia/Type/EnumType.php @@ -0,0 +1,50 @@ +. */ +/* */ +/*************************************************************************************/ +namespace Thelia\Type; + +/** + * + * @author Etienne Roudeix + * + */ + +class EnumType implements TypeInterface +{ + protected $values = array(); + + public function __construct($values = array()) + { + if(is_array($values)) + $this->values = $values; + } + + public function getType() + { + return 'Enum type'; + } + + public function isValid($value) + { + return in_array($value, $this->values); + } +} diff --git a/core/lib/Thelia/Type/FloatType.php b/core/lib/Thelia/Type/FloatType.php new file mode 100755 index 000000000..e341b540f --- /dev/null +++ b/core/lib/Thelia/Type/FloatType.php @@ -0,0 +1,42 @@ +. */ +/* */ +/*************************************************************************************/ +namespace Thelia\Type; + +/** + * + * @author Etienne Roudeix + * + */ + +class FloatType implements TypeInterface +{ + public function getType() + { + return 'Float type'; + } + + public function isValid($value) + { + return filter_var($value, FILTER_VALIDATE_FLOAT) === false ? false : true; + } +} diff --git a/core/lib/Thelia/Type/IntListType.php b/core/lib/Thelia/Type/IntListType.php new file mode 100755 index 000000000..74b0a6790 --- /dev/null +++ b/core/lib/Thelia/Type/IntListType.php @@ -0,0 +1,47 @@ +. */ +/* */ +/*************************************************************************************/ +namespace Thelia\Type; + +/** + * + * @author Etienne Roudeix + * + */ + +class IntListType implements TypeInterface +{ + public function getType() + { + return 'Int list type'; + } + + public function isValid($values) + { + foreach(explode(',', $values) as $value) { + if(filter_var($value, FILTER_VALIDATE_INT) === false) + return false; + } + + return true; + } +} diff --git a/core/lib/Thelia/Type/IntType.php b/core/lib/Thelia/Type/IntType.php new file mode 100755 index 000000000..d077a6c89 --- /dev/null +++ b/core/lib/Thelia/Type/IntType.php @@ -0,0 +1,42 @@ +. */ +/* */ +/*************************************************************************************/ +namespace Thelia\Type; + +/** + * + * @author Etienne Roudeix + * + */ + +class IntType implements TypeInterface +{ + public function getType() + { + return 'Int type'; + } + + public function isValid($value) + { + return filter_var($value, FILTER_VALIDATE_INT) === false ? false : true; + } +} diff --git a/core/lib/Thelia/Type/JsonType.php b/core/lib/Thelia/Type/JsonType.php new file mode 100755 index 000000000..805977a32 --- /dev/null +++ b/core/lib/Thelia/Type/JsonType.php @@ -0,0 +1,43 @@ +. */ +/* */ +/*************************************************************************************/ +namespace Thelia\Type; + +/** + * + * @author Etienne Roudeix + * + */ + +class JsonType implements TypeInterface +{ + public function getType() + { + return 'Json type'; + } + + public function isValid($value) + { + json_decode($value); + return (json_last_error() == JSON_ERROR_NONE); + } +} diff --git a/core/lib/Thelia/Type/TypeCollection.php b/core/lib/Thelia/Type/TypeCollection.php new file mode 100755 index 000000000..4430be5df --- /dev/null +++ b/core/lib/Thelia/Type/TypeCollection.php @@ -0,0 +1,135 @@ +. */ +/* */ +/*************************************************************************************/ +namespace Thelia\Type; + +/** + * + * @author Etienne Roudeix + * + */ + +class TypeCollection implements \Iterator +{ + private $position; + protected $types = array(); + + public function __construct() + { + foreach(func_get_args() as $type) { + $this->addType($type); + } + } + + public function isEmpty() + { + return count($this->types) == 0; + } + + /** + * @param TypeInterface $type + * + * @return TypeCollection + */ + public function addType(TypeInterface $type) + { + $this->types[] = $type; + return $this; + } + + public function getCount() + { + return count($this->types); + } + + /** + * (PHP 5 >= 5.0.0)
+ * Return the current element + * @link http://php.net/manual/en/iterator.current.php + * @return \Thelia\Type\TypeInterface + */ + public function current() + { + return $this->types[$this->position]; + } + + /** + * (PHP 5 >= 5.0.0)
+ * Move forward to next element + * @link http://php.net/manual/en/iterator.next.php + * @return void Any returned value is ignored. + */ + public function next() + { + $this->position++; + } + + /** + * (PHP 5 >= 5.0.0)
+ * Return the key of the current element + * @link http://php.net/manual/en/iterator.key.php + * @return mixed scalar on success, or null on failure. + */ + public function key() + { + return $this->position; + } + + /** + * (PHP 5 >= 5.0.0)
+ * Checks if current position is valid + * @link http://php.net/manual/en/iterator.valid.php + * @return boolean The return value will be casted to boolean and then evaluated. + * Returns true on success or false on failure. + */ + public function valid() + { + return isset($this->types[$this->position]); + } + + /** + * (PHP 5 >= 5.0.0)
+ * Rewind the Iterator to the first element + * @link http://php.net/manual/en/iterator.rewind.php + * @return void Any returned value is ignored. + */ + public function rewind() + { + $this->position = 0; + } + + /** + * @param $value + * + * @return bool + */ + public function isValid($value) + { + foreach($this as $type) { + if($type->isValid($value)) { + return true; + } + } + + return false; + } +} diff --git a/core/lib/Thelia/Type/TypeInterface.php b/core/lib/Thelia/Type/TypeInterface.php new file mode 100755 index 000000000..ae626f0b9 --- /dev/null +++ b/core/lib/Thelia/Type/TypeInterface.php @@ -0,0 +1,36 @@ +. */ +/* */ +/*************************************************************************************/ +namespace Thelia\Type; + +/** + * + * @author Etienne Roudeix + * + */ + +interface TypeInterface +{ + public function getType(); + + public function isValid($value); +} diff --git a/templates/smarty-sample/index.html b/templates/smarty-sample/index.html index f93dd3876..9135b8867 100755 --- a/templates/smarty-sample/index.html +++ b/templates/smarty-sample/index.html @@ -77,4 +77,11 @@ An image from asset directory : {/for} +
+

Loops also work with #

+ {loop type="category" name="catloop1"} + #TITLE : {#DESCRIPTION|upper} #NOTATAG
+ {/loop} +
+ {include file="includes/footer.html"} \ No newline at end of file