diff --git a/core/lib/Thelia/Core/Template/Element/BaseLoop.php b/core/lib/Thelia/Core/Template/Element/BaseLoop.php index 6863f1a09..0ee3872de 100755 --- a/core/lib/Thelia/Core/Template/Element/BaseLoop.php +++ b/core/lib/Thelia/Core/Template/Element/BaseLoop.php @@ -67,6 +67,9 @@ abstract class BaseLoop $this->dispatcher = $dispatcher; } + /** + * @return \Thelia\Core\Template\Loop\Argument\ArgumentCollection + */ public function getArgs() { return $this->defineArgs()->addArguments($this->getDefaultArgs()); diff --git a/core/lib/Thelia/Core/Template/Loop/Argument/Argument.php b/core/lib/Thelia/Core/Template/Loop/Argument/Argument.php index 9fb72bff0..e8c44da03 100755 --- a/core/lib/Thelia/Core/Template/Loop/Argument/Argument.php +++ b/core/lib/Thelia/Core/Template/Loop/Argument/Argument.php @@ -72,6 +72,19 @@ class Argument ); } + public static function createBooleanTypeArgument($name, $default=null, $mandatory=false, $empty=true) + { + return new Argument( + $name, + new TypeCollection( + new Type\BoolType() + ), + $default, + $mandatory, + $empty + ); + } + public static function createIntListTypeArgument($name, $default=null, $mandatory=false, $empty=true) { return new Argument( diff --git a/core/lib/Thelia/Core/Template/Loop/Category.php b/core/lib/Thelia/Core/Template/Loop/Category.php index 55be4d69a..0d3426dfa 100755 --- a/core/lib/Thelia/Core/Template/Loop/Category.php +++ b/core/lib/Thelia/Core/Template/Loop/Category.php @@ -62,6 +62,7 @@ use Thelia\Type; * Class Category * @package Thelia\Core\Template\Loop * @author Manuel Raynaud + * @author Etienne Roudeix */ class Category extends BaseLoop { diff --git a/core/lib/Thelia/Core/Template/Loop/Product.php b/core/lib/Thelia/Core/Template/Loop/Product.php new file mode 100755 index 000000000..55be4d69a --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/Product.php @@ -0,0 +1,186 @@ +. */ +/* */ +/*************************************************************************************/ + +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; + +/** + * + * Category loop, all params available : + * + * - id : can be an id (eq : 3) or a "string list" (eg: 3, 4, 5) + * - parent : categories having this parent id + * - current : current id is used if you are on a category page + * - not_empty : if value is 1, category and subcategories must have at least 1 product + * - visible : default 1, if you want category not visible put 0 + * - order : all value available : + * * alpha : sorting by title alphabetical order + * * alpha_reverse : sorting by title alphabetical reverse order + * * reverse : sorting by position descending + * * by default results are sorting by position ascending + * - random : if 1, random results. Default value is 0 + * - exclude : all category id you want to exclude (as for id, an integer or a "string list" can be used) + * + * example : + * + * + * #TITLE : #ID + * + * + * + * Class Category + * @package Thelia\Core\Template\Loop + * @author Manuel Raynaud + */ +class Category extends BaseLoop +{ + public $id; + public $parent; + public $current; + public $not_empty; + public $visible; + public $link; + public $order; + public $random; + public $exclude; + + /** + * @return ArgumentCollection + */ + protected function defineArgs() + { + return new ArgumentCollection( + Argument::createIntListTypeArgument('id'), + Argument::createIntTypeArgument('parent'), + Argument::createIntTypeArgument('current'), + Argument::createIntTypeArgument('not_empty', 0), + Argument::createIntTypeArgument('visible', 1), + Argument::createAnyTypeArgument('link'), + new Argument( + 'order', + new TypeCollection( + new Type\EnumType('alpha', 'alpha_reverse', 'reverse') + ) + ), + Argument::createIntTypeArgument('random', 0), + Argument::createIntListTypeArgument('exclude') + ); + } + + /** + * @param $pagination + * + * @return \Thelia\Core\Template\Element\LoopResult + */ + public function exec(&$pagination) + { + $search = CategoryQuery::create(); + + if (!is_null($this->id)) { + $search->filterById(explode(',', $this->id), \Criteria::IN); + } + + if (!is_null($this->parent)) { + $search->filterByParent($this->parent); + } + + if ($this->current == 1) { + $search->filterById($this->request->get("category_id")); + } elseif (null !== $this->current && $this->current == 0) { + $search->filterById($this->request->get("category_id"), \Criteria::NOT_IN); + } + + if (!is_null($this->exclude)) { + $search->filterById(explode(",", $this->exclude), \Criteria::NOT_IN); + } + + if (!is_null($this->link)) { + $search->filterByLink($this->link); + } + + $search->filterByVisible($this->visible); + + switch ($this->order) { + case "alpha": + $search->addAscendingOrderByColumn(\Thelia\Model\CategoryI18nPeer::TITLE); + break; + case "alpha_reverse": + $search->addDescendingOrderByColumn(\Thelia\Model\CategoryI18nPeer::TITLE); + break; + case "reverse": + $search->orderByPosition(\Criteria::DESC); + break; + default: + $search->orderByPosition(); + break; + } + + if ($this->random == 1) { + $search->clearOrderByColumns(); + $search->addAscendingOrderByColumn('RAND()'); + } + + /** + * \Criteria::INNER_JOIN in second parameter for joinWithI18n exclude query without translation. + * + * @todo : verify here if we want results for row without translations. + */ + $search->joinWithI18n($this->request->getSession()->get('locale', 'en_US'), \Criteria::INNER_JOIN); + + $categories = $this->search($search, $pagination); + + $loopResult = new LoopResult(); + + foreach ($categories as $category) { + + if ($this->not_empty && $category->countAllProducts() == 0) continue; + + $loopResultRow = new LoopResultRow(); + $loopResultRow->set("TITLE",$category->getTitle()); + $loopResultRow->set("CHAPO", $category->getChapo()); + $loopResultRow->set("DESCRIPTION", $category->getDescription()); + $loopResultRow->set("POSTSCRIPTUM", $category->getPostscriptum()); + $loopResultRow->set("PARENT", $category->getParent()); + $loopResultRow->set("ID", $category->getId()); + $loopResultRow->set("URL", $category->getUrl()); + $loopResultRow->set("LINK", $category->getLink()); + $loopResultRow->set("NB_CHILD", $category->countChild()); + + $loopResult->addRow($loopResultRow); + } + + return $loopResult; + } + +} diff --git a/core/lib/Thelia/Core/Template/Smarty/Plugins/TheliaLoop.php b/core/lib/Thelia/Core/Template/Smarty/Plugins/TheliaLoop.php index 4d2ea7d57..3bc019c59 100755 --- a/core/lib/Thelia/Core/Template/Smarty/Plugins/TheliaLoop.php +++ b/core/lib/Thelia/Core/Template/Smarty/Plugins/TheliaLoop.php @@ -308,7 +308,7 @@ class TheliaLoop implements SmartyPluginInterface $value = $argument->default; } - $loop->{$argument->name} = $value; + $loop->{$argument->name} = $value === null ? null : $argument->type->getFormatedValue($value); } if (!empty($faultActor)) { diff --git a/core/lib/Thelia/Tests/Type/BooleanTypeTest.php b/core/lib/Thelia/Tests/Type/BooleanTypeTest.php new file mode 100755 index 000000000..84889ff40 --- /dev/null +++ b/core/lib/Thelia/Tests/Type/BooleanTypeTest.php @@ -0,0 +1,55 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Tests\Type; + +use Thelia\Type\BooleanType; + +/** + * + * @author Etienne Roudeix + * + */ +class BooleanTypeTest extends \PHPUnit_Framework_TestCase +{ + public function testBooleanType() + { + $booleanType = new BooleanType(); + $this->assertTrue($booleanType->isValid('y')); + $this->assertTrue($booleanType->isValid('yes')); + $this->assertTrue($booleanType->isValid('true')); + $this->assertTrue($booleanType->isValid('no')); + $this->assertTrue($booleanType->isValid('n')); + $this->assertTrue($booleanType->isValid('false')); + $this->assertFalse($booleanType->isValid('foo')); + $this->assertFalse($booleanType->isValid(5)); + } + + public function testFormatBooleanType() + { + $booleanType = new BooleanType(); + $this->assertTrue($booleanType->getFormatedValue('yes')); + $this->assertFalse($booleanType->getFormatedValue('no')); + $this->assertNull($booleanType->getFormatedValue('foo')); + } +} diff --git a/core/lib/Thelia/Tests/Type/IntListTypeTest.php b/core/lib/Thelia/Tests/Type/IntListTypeTest.php index 68b628a5c..bbe410bd1 100755 --- a/core/lib/Thelia/Tests/Type/IntListTypeTest.php +++ b/core/lib/Thelia/Tests/Type/IntListTypeTest.php @@ -39,4 +39,11 @@ class IntListTypeTest extends \PHPUnit_Framework_TestCase $this->assertTrue($intListType->isValid('1,2,3')); $this->assertFalse($intListType->isValid('1,2,3.3')); } + + public function testFormatJsonType() + { + $intListType = new IntListType(); + $this->assertTrue(is_array($intListType->getFormatedValue('1,2,3'))); + $this->assertNull($intListType->getFormatedValue('foo')); + } } diff --git a/core/lib/Thelia/Tests/Type/JsonTypeTest.php b/core/lib/Thelia/Tests/Type/JsonTypeTest.php index 276a867d2..2dc15a2f5 100755 --- a/core/lib/Thelia/Tests/Type/JsonTypeTest.php +++ b/core/lib/Thelia/Tests/Type/JsonTypeTest.php @@ -38,4 +38,11 @@ class JsonTypeTest extends \PHPUnit_Framework_TestCase $this->assertTrue($jsonType->isValid('{"k0":"v0","k1":"v1","k2":"v2"}')); $this->assertFalse($jsonType->isValid('1,2,3')); } + + public function testFormatJsonType() + { + $jsonType = new JsonType(); + $this->assertTrue(is_array($jsonType->getFormatedValue('{"k0":"v0","k1":"v1","k2":"v2"}'))); + $this->assertNull($jsonType->getFormatedValue('foo')); + } } diff --git a/core/lib/Thelia/Type/AnyType.php b/core/lib/Thelia/Type/AnyType.php index 5b00a5aeb..8e22d44eb 100755 --- a/core/lib/Thelia/Type/AnyType.php +++ b/core/lib/Thelia/Type/AnyType.php @@ -39,4 +39,9 @@ class AnyType implements TypeInterface { return true; } + + public function getFormatedValue($value) + { + return $value; + } } diff --git a/core/lib/Thelia/Type/BooleanType.php b/core/lib/Thelia/Type/BooleanType.php new file mode 100755 index 000000000..939ff0d79 --- /dev/null +++ b/core/lib/Thelia/Type/BooleanType.php @@ -0,0 +1,60 @@ +. */ +/* */ +/*************************************************************************************/ +namespace Thelia\Type; + +/** + * + * @author Etienne Roudeix + * + */ + +class BooleanType implements TypeInterface +{ + protected $trueValuesArray = array( + '1', + 'true', + 'yes', + 'y', + ); + protected $falseValuesArray = array( + '0', + 'false', + 'no', + 'n', + ); + + public function getType() + { + return 'Boolean type'; + } + + public function isValid($value) + { + return in_array($value, $this->trueValuesArray) || in_array($value, $this->falseValuesArray); + } + + public function getFormatedValue($value) + { + return $this->isValid($value) ? ( in_array($value, $this->trueValuesArray) ) : null; + } +} diff --git a/core/lib/Thelia/Type/EnumType.php b/core/lib/Thelia/Type/EnumType.php index d0a1c9b89..0aff0ec88 100755 --- a/core/lib/Thelia/Type/EnumType.php +++ b/core/lib/Thelia/Type/EnumType.php @@ -47,4 +47,9 @@ class EnumType implements TypeInterface { return in_array($value, $this->values); } + + public function getFormatedValue($value) + { + return $this->isValid($value) ? $value : null; + } } diff --git a/core/lib/Thelia/Type/FloatType.php b/core/lib/Thelia/Type/FloatType.php index e341b540f..83d3561a4 100755 --- a/core/lib/Thelia/Type/FloatType.php +++ b/core/lib/Thelia/Type/FloatType.php @@ -39,4 +39,9 @@ class FloatType implements TypeInterface { return filter_var($value, FILTER_VALIDATE_FLOAT) === false ? false : true; } + + public function getFormatedValue($value) + { + return $this->isValid($value) ? $value : null; + } } diff --git a/core/lib/Thelia/Type/IntListType.php b/core/lib/Thelia/Type/IntListType.php index 74b0a6790..b023173f7 100755 --- a/core/lib/Thelia/Type/IntListType.php +++ b/core/lib/Thelia/Type/IntListType.php @@ -44,4 +44,9 @@ class IntListType implements TypeInterface return true; } + + public function getFormatedValue($values) + { + return $this->isValid($values) ? explode(',', $values) : null; + } } diff --git a/core/lib/Thelia/Type/IntType.php b/core/lib/Thelia/Type/IntType.php index d077a6c89..4adc2e10e 100755 --- a/core/lib/Thelia/Type/IntType.php +++ b/core/lib/Thelia/Type/IntType.php @@ -39,4 +39,9 @@ class IntType implements TypeInterface { return filter_var($value, FILTER_VALIDATE_INT) === false ? false : true; } + + public function getFormatedValue($value) + { + return $this->isValid($value) ? $value : null; + } } diff --git a/core/lib/Thelia/Type/JsonType.php b/core/lib/Thelia/Type/JsonType.php index 805977a32..397967df9 100755 --- a/core/lib/Thelia/Type/JsonType.php +++ b/core/lib/Thelia/Type/JsonType.php @@ -37,7 +37,12 @@ class JsonType implements TypeInterface public function isValid($value) { - json_decode($value); + json_decode($value, true); return (json_last_error() == JSON_ERROR_NONE); } + + public function getFormatedValue($value) + { + return $this->isValid($value) ? json_decode($value, true) : null; + } } diff --git a/core/lib/Thelia/Type/TypeCollection.php b/core/lib/Thelia/Type/TypeCollection.php index 4430be5df..bff384f92 100755 --- a/core/lib/Thelia/Type/TypeCollection.php +++ b/core/lib/Thelia/Type/TypeCollection.php @@ -132,4 +132,14 @@ class TypeCollection implements \Iterator return false; } + + public function getFormatedValue($value) { + foreach($this as $type) { + if($type->isValid($value)) { + return $type->getFormatedValue($value); + } + } + + return null; + } } diff --git a/core/lib/Thelia/Type/TypeInterface.php b/core/lib/Thelia/Type/TypeInterface.php index ae626f0b9..9268df7d5 100755 --- a/core/lib/Thelia/Type/TypeInterface.php +++ b/core/lib/Thelia/Type/TypeInterface.php @@ -33,4 +33,6 @@ interface TypeInterface public function getType(); public function isValid($value); + + public function getFormatedValue($value); }