[~TASK] Fluid: tweaked exception that is thrown when trying to iterate through non...
authorBastian Waidelich <bastian@typo3.org>
Wed, 16 Sep 2009 16:52:53 +0000 (16:52 +0000)
committerBastian Waidelich <bastian@typo3.org>
Wed, 16 Sep 2009 16:52:53 +0000 (16:52 +0000)
[~TASK] Fluid: fixed typo in ForViewHelperTest
[+FEATURE] Fluid: added CycleViewHelper. Resolves #4458
[+FEATURE] Fluid: added GroupedForViewHelper. Resolves #4460
[+TASK] Fluid: added test case for PaddingViewHelper. Relates to #4459

typo3/sysext/fluid/Classes/ViewHelpers/CycleViewHelper.php [new file with mode: 0644]
typo3/sysext/fluid/Classes/ViewHelpers/ForViewHelper.php
typo3/sysext/fluid/Classes/ViewHelpers/GroupedForViewHelper.php [new file with mode: 0644]
typo3/sysext/fluid/Tests/ViewHelpers/CycleViewHelperTest_testcase.php [new file with mode: 0644]
typo3/sysext/fluid/Tests/ViewHelpers/ForViewHelperTest_testcase.php
typo3/sysext/fluid/Tests/ViewHelpers/Format/PaddingViewHelperTest_testcase.php [new file with mode: 0644]
typo3/sysext/fluid/Tests/ViewHelpers/GroupedForViewHelperTest_testcase.php [new file with mode: 0644]

diff --git a/typo3/sysext/fluid/Classes/ViewHelpers/CycleViewHelper.php b/typo3/sysext/fluid/Classes/ViewHelpers/CycleViewHelper.php
new file mode 100644 (file)
index 0000000..319392f
--- /dev/null
@@ -0,0 +1,133 @@
+<?php
+
+/*                                                                        *
+ * This script belongs to the FLOW3 package "Fluid".                      *
+ *                                                                        *
+ * It is free software; you can redistribute it and/or modify it under    *
+ * the terms of the GNU Lesser General Public License as published by the *
+ * Free Software Foundation, either version 3 of the License, or (at your *
+ * option) any later version.                                             *
+ *                                                                        *
+ * This script is distributed in the hope that it will be useful, but     *
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN-    *
+ * TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser       *
+ * General Public License for more details.                               *
+ *                                                                        *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with the script.                                         *
+ * If not, see http://www.gnu.org/licenses/lgpl.html                      *
+ *                                                                        *
+ * The TYPO3 project - inspiring people to share!                         *
+ *                                                                        */
+
+/**
+ * Cycle view helper. Iterates through the specified values.
+ *
+ * = Examples =
+ *
+ * <code title="Simple">
+ * <f:for each="{0:1, 1:2, 2:3, 3:4}" as="foo"><f:cycle values="{0: 'foo', 1: 'bar', 2: 'baz'}" as="cycle">{cycle}</f:cycle></f:for>
+ * </code>
+ *
+ * Output:
+ * foobarbazfoo
+ *
+ * <code title="Alternating CSS class">
+ * <ul>
+ *   <f:for each="{0:1, 1:2, 2:3, 3:4}" as="foo">
+ *     <f:cycle values="{0: 'odd', 1: 'even'}" as="zebraClass">
+ *       <li class="{zebraClass}">{foo}</li>
+ *     </f:cycle>
+ *   </f:for>
+ * </ul>
+ * </code>
+ *
+ * Output:
+ * <ul>
+ *   <li class="odd">1</li>
+ *   <li class="even">2</li>
+ *   <li class="odd">3</li>
+ *   <li class="even">4</li>
+ * </ul>
+ *
+ * @version $Id$
+ * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License, version 3 or later
+ * @scope prototype
+ */
+class Tx_Fluid_ViewHelpers_CycleViewHelper extends Tx_Fluid_Core_ViewHelper_AbstractViewHelper {
+
+       /**
+        * @var array|\SplObjectStorage the values to be iterated through
+        */
+       protected $values = NULL;
+
+       /**
+        * @var integer current values index
+        */
+       protected $currentCycleIndex = NULL;
+
+       /**
+        * @param array $values The array or SplObjectStorage to iterated over
+        * @param string $as The name of the iteration variable
+        * @return string Rendered result
+        * @author Bastian Waidelich <bastian@typo3.org>
+        * @api
+        */
+       public function render($values, $as) {
+               if ($values === NULL) {
+                       return $this->renderChildren();
+               }
+               if ($this->values === NULL) {
+                       $this->initializeValues($values);
+               }
+               if ($this->currentCycleIndex === NULL || $this->currentCycleIndex >= count($this->values)) {
+                       $this->currentCycleIndex = 0;
+               }
+
+               $currentValue = isset($this->values[$this->currentCycleIndex]) ? $this->values[$this->currentCycleIndex] : NULL;
+               $this->templateVariableContainer->add($as, $currentValue);
+               $output = $this->renderChildren();
+               $this->templateVariableContainer->remove($as);
+
+               $this->currentCycleIndex ++;
+
+               return $output;
+       }
+
+       /**
+        * Sets this->values to the current values argument and resets $this->currentCycleIndex.
+        *
+        * @param array $values The array or SplObjectStorage to be stored in $this->values
+        * @return void
+        * @author Bastian Waidelich <bastian@typo3.org>
+        */
+       protected function initializeValues($values) {
+               if (is_object($values)) {
+                       if (!$values instanceof Traversable) {
+                               throw new Tx_Fluid_Core_ViewHelper_Exception('CycleViewHelper only supports arrays and objects implementing Traversable interface' , 1248728393);
+                       }
+                       $this->values = $this->convertToArray($values);
+               } else {
+                       $this->values = array_values($values);
+               }
+               $this->currentCycleIndex = 0;
+       }
+
+       /**
+        * Turns the given object into an array.
+        * The object has to implement the Traversable interface
+        *
+        * @param Traversable $object The object to be turned into an array. If the object implements Iterator the key will NOT be preserved.
+        * @return array The resulting array
+        * @author Bastian Waidelich <bastian@typo3.org>
+        */
+       protected function convertToArray(Traversable $object) {
+               $array = array();
+               foreach ($object as $singleElement) {
+                       $array[] = $singleElement;
+               }
+               return $array;
+       }
+}
+
+?>
index 3533bd7..f5f734d 100644 (file)
@@ -48,7 +48,7 @@
  *   <li>fruit4: cherry</li>
  * </ul>
  *
- * @version $Id: ForViewHelper.php 2914 2009-07-28 18:26:38Z bwaidelich $
+ * @version $Id: ForViewHelper.php 3190 2009-09-16 16:48:39Z bwaidelich $
  * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License, version 3 or later
  * @scope prototype
  */
@@ -74,7 +74,7 @@ class Tx_Fluid_ViewHelpers_ForViewHelper extends Tx_Fluid_Core_ViewHelper_Abstra
                }
                if (is_object($each)) {
                        if (!$each instanceof Traversable) {
-                               throw new Tx_Fluid_Core_ViewHelper_Exception('Only objects implementing Traversable interface' , 1248728393);
+                               throw new Tx_Fluid_Core_ViewHelper_Exception('ForViewHelper only supports arrays and objects implementing Traversable interface' , 1248728393);
                        }
                        $each = $this->convertToArray($each);
                }
diff --git a/typo3/sysext/fluid/Classes/ViewHelpers/GroupedForViewHelper.php b/typo3/sysext/fluid/Classes/ViewHelpers/GroupedForViewHelper.php
new file mode 100644 (file)
index 0000000..f7e49b6
--- /dev/null
@@ -0,0 +1,143 @@
+<?php
+
+/*                                                                        *
+ * This script belongs to the FLOW3 package "Fluid".                      *
+ *                                                                        *
+ * It is free software; you can redistribute it and/or modify it under    *
+ * the terms of the GNU Lesser General Public License as published by the *
+ * Free Software Foundation, either version 3 of the License, or (at your *
+ * option) any later version.                                             *
+ *                                                                        *
+ * This script is distributed in the hope that it will be useful, but     *
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN-    *
+ * TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser       *
+ * General Public License for more details.                               *
+ *                                                                        *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with the script.                                         *
+ * If not, see http://www.gnu.org/licenses/lgpl.html                      *
+ *                                                                        *
+ * The TYPO3 project - inspiring people to share!                         *
+ *                                                                        */
+
+/**
+ * Grouped loop view helper.
+ * Loops through the specified values
+ *
+ * = Examples =
+ *
+ * <code title="Simple">
+ * <f:groupedFor each="{0: {name: 'apple', color: 'green'}, 1: {name: 'cherry', color: 'red'}, 2: {name: 'banana', color: 'yellow'}, 3: {name: 'strawberry', color: 'red'}}" as="fruitsOfThisColor" groupBy="color">
+ *   <f:for each="{fruitsOfThisColor}" as="fruit">
+ *     {fruit.name}
+ *   </f:for>
+ * </f:groupedFor>
+ * </code>
+ *
+ * Output:
+ * apple cherry strawberry banana
+ *
+ * <code title="Two dimensional list">
+ * <ul>
+ *   <f:groupedFor each="{0: {name: 'apple', color: 'green'}, 1: {name: 'cherry', color: 'red'}, 2: {name: 'banana', color: 'yellow'}, 3: {name: 'strawberry', color: 'red'}}" as="fruitsOfThisColor" groupBy="color" groupKey="color">
+ *     <li>
+ *       {color} fruits:
+ *       <ul>
+ *         <f:for each="{fruitsOfThisColor}" as="fruit" key="label">
+ *           <li>{label}: {fruit.name}</li>
+ *         </f:for>
+ *       </ul>
+ *     </li>
+ *   </f:groupedFor>
+ * </ul>
+ * </code>
+ *
+ * Output:
+ * <ul>
+ *   <li>green fruits
+ *     <ul>
+ *       <li>0: apple</li>
+ *     </ul>
+ *   </li>
+ *   <li>red fruits
+ *     <ul>
+ *       <li>1: cherry</li>
+ *     </ul>
+ *     <ul>
+ *       <li>3: strawberry</li>
+ *     </ul>
+ *   </li>
+  *   <li>yellow fruits
+ *     <ul>
+ *       <li>2: banana</li>
+ *     </ul>
+ *   </li>
+ * </ul>
+ *
+ * @version $Id$
+ * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License, version 3 or later
+ * @scope prototype
+ */
+class Tx_Fluid_ViewHelpers_GroupedForViewHelper extends Tx_Fluid_Core_ViewHelper_AbstractViewHelper {
+
+       /**
+        * Iterates through elements of $each and renders child nodes
+        *
+        * @param array $each The array or SplObjectStorage to iterated over
+        * @param string $as The name of the iteration variable
+        * @param string $groupBy Group by this property
+        * @param string $groupKey The name of the variable to store the current group
+        * @return string Rendered string
+        * @author Bastian Waidelich <bastian@typo3.org>
+        * @api
+        */
+       public function render($each, $as, $groupBy, $groupKey = 'groupKey') {
+               $output = '';
+               if ($each === NULL) {
+                       return '';
+               }
+               if (is_object($each)) {
+                       if (!$each instanceof Traversable) {
+                               throw new Tx_Fluid_Core_ViewHelper_Exception('GroupedForViewHelper only supports arrays and objects implementing Traversable interface' , 1253108907);
+                       }
+                       $each = $this->convertToArray($each);
+               }
+               $groups = array();
+               foreach ($each as $keyValue => $singleElement) {
+                       if (is_array($singleElement)) {
+                               $currentGroupKey = isset($singleElement[$groupBy]) ? $singleElement[$groupBy] : NULL;
+                       } elseif (is_object($singleElement)) {
+                               $currentGroupKey = Tx_Extbase_Reflection_ObjectAccess::getProperty($singleElement, $groupBy);
+                       } else {
+                               throw new Tx_Fluid_Core_ViewHelper_Exception('GroupedForViewHelper only supports multi-dimensional arrays and objects' , 1253120365);
+                       }
+                       $groups[$currentGroupKey][$keyValue] = $singleElement;
+               }
+               foreach ($groups as $currentGroupKey => $group) {
+                       $this->templateVariableContainer->add($groupKey, $currentGroupKey);
+                       $this->templateVariableContainer->add($as, $group);
+                       $output .= $this->renderChildren();
+                       $this->templateVariableContainer->remove($groupKey);
+                       $this->templateVariableContainer->remove($as);
+               }
+               return $output;
+       }
+
+       /**
+        * Turns the given object into an array.
+        * The object has to implement the Traversable interface
+        *
+        * @param Traversable $object The object to be turned into an array. If the object implements Iterator the key will be preserved.
+        * @return array The resulting array
+        * @author Bastian Waidelich <bastian@typo3.org>
+        */
+       protected function convertToArray(Traversable $object) {
+               $array = array();
+               foreach ($object as $keyValue => $singleElement) {
+                       $array[$keyValue] = $singleElement;
+               }
+               return $array;
+       }
+}
+
+?>
diff --git a/typo3/sysext/fluid/Tests/ViewHelpers/CycleViewHelperTest_testcase.php b/typo3/sysext/fluid/Tests/ViewHelpers/CycleViewHelperTest_testcase.php
new file mode 100644 (file)
index 0000000..661ddd5
--- /dev/null
@@ -0,0 +1,140 @@
+<?php
+
+/*                                                                        *
+ * This script is part of the TYPO3 project - inspiring people to share!  *
+ *                                                                        *
+ * TYPO3 is free software; you can redistribute it and/or modify it under *
+ * the terms of the GNU General Public License version 2 as published by  *
+ * the Free Software Foundation.                                          *
+ *                                                                        *
+ * This script is distributed in the hope that it will be useful, but     *
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN-    *
+ * TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General      *
+ * Public License for more details.                                       *
+ *                                                                        */
+
+/**
+ * Testcase for CycleViewHelper
+ *
+ * @version $Id$
+ * @license http://opensource.org/licenses/gpl-license.php GNU Public License, version 2
+ */
+
+require_once(dirname(__FILE__) . '/ViewHelperBaseTestcase.php');
+require_once(t3lib_extMgm::extPath('extbase', 'Tests/Base_testcase.php'));
+class Tx_Fluid_ViewHelpers_CycleViewHelperTest_testcase extends Tx_Fluid_ViewHelpers_ViewHelperBaseTestcase {
+
+       /**
+        * var Tx_Fluid_ViewHelpers_CycleViewHelper
+        */
+       protected $viewHelper;
+
+       public function setUp() {
+               parent::setUp();
+               $this->viewHelper = $this->getMock('Tx_Fluid_ViewHelpers_CycleViewHelper', array('renderChildren'));
+               $this->injectDependenciesIntoViewHelper($this->viewHelper);
+               $this->viewHelper->initializeArguments();
+       }
+
+       /**
+        * @test
+        * @author Bastian Waidelich <bastian@typo3.org>
+        */
+       public function renderAddsCurrentValueToTemplateVariableContainerAndRemovesItAfterRendering() {
+               $this->templateVariableContainer->expects($this->at(0))->method('add')->with('innerVariable', 'bar');
+               $this->templateVariableContainer->expects($this->at(1))->method('remove')->with('innerVariable');
+
+               $values = array('bar', 'Fluid');
+               $this->viewHelper->render($values, 'innerVariable');
+       }
+
+       /**
+        * @test
+        * @author Bastian Waidelich <bastian@typo3.org>
+        */
+       public function renderAddsFirstValueToTemplateVariableContainerAfterLastValue() {
+               $this->templateVariableContainer->expects($this->at(0))->method('add')->with('innerVariable', 'bar');
+               $this->templateVariableContainer->expects($this->at(1))->method('remove')->with('innerVariable');
+               $this->templateVariableContainer->expects($this->at(2))->method('add')->with('innerVariable', 'Fluid');
+               $this->templateVariableContainer->expects($this->at(3))->method('remove')->with('innerVariable');
+               $this->templateVariableContainer->expects($this->at(4))->method('add')->with('innerVariable', 'bar');
+               $this->templateVariableContainer->expects($this->at(5))->method('remove')->with('innerVariable');
+
+               $values = array('bar', 'Fluid');
+               $this->viewHelper->render($values, 'innerVariable');
+               $this->viewHelper->render($values, 'innerVariable');
+               $this->viewHelper->render($values, 'innerVariable');
+       }
+
+       /**
+        * @test
+        * @author Bastian Waidelich <bastian@typo3.org>
+        */
+       public function viewHelperSupportsAssociativeArrays() {
+               $this->templateVariableContainer->expects($this->at(0))->method('add')->with('innerVariable', 'FLOW3');
+               $this->templateVariableContainer->expects($this->at(1))->method('remove')->with('innerVariable');
+               $this->templateVariableContainer->expects($this->at(2))->method('add')->with('innerVariable', 'Fluid');
+               $this->templateVariableContainer->expects($this->at(3))->method('remove')->with('innerVariable');
+               $this->templateVariableContainer->expects($this->at(4))->method('add')->with('innerVariable', 'FLOW3');
+               $this->templateVariableContainer->expects($this->at(5))->method('remove')->with('innerVariable');
+
+               $values = array('foo' => 'FLOW3', 'bar' => 'Fluid');
+               $this->viewHelper->render($values, 'innerVariable');
+               $this->viewHelper->render($values, 'innerVariable');
+               $this->viewHelper->render($values, 'innerVariable');
+       }
+
+       /**
+        * @test
+        * @expectedException Tx_Fluid_Core_ViewHelper_Exception
+        * @author Bastian Waidelich <bastian@typo3.org>
+        */
+       public function renderThrowsExceptionWhenPassingObjectsToValuesThatAreNotTraversable() {
+               $object = new stdClass();
+
+               $this->viewHelper->render($object, 'innerVariable');
+       }
+
+       /**
+        * @test
+        * @author Bastian Waidelich <bastian@typo3.org>
+        */
+       public function renderReturnsChildNodesIfValuesIsNull() {
+               $this->viewHelper->expects($this->once())->method('renderChildren')->will($this->returnValue('Child nodes'));
+
+               $this->assertEquals('Child nodes', $this->viewHelper->render(NULL, 'foo'));
+       }
+
+       /**
+        * @test
+        * @author Bastian Waidelich <bastian@typo3.org>
+        */
+       public function renderReturnsChildNodesIfValuesIsAnEmptyArray() {
+               $this->templateVariableContainer->expects($this->at(0))->method('add')->with('foo', NULL);
+               $this->templateVariableContainer->expects($this->at(1))->method('remove')->with('foo');
+
+               $this->viewHelper->expects($this->once())->method('renderChildren')->will($this->returnValue('Child nodes'));
+
+               $this->assertEquals('Child nodes', $this->viewHelper->render(array(), 'foo'));
+       }
+
+       /**
+        * @test
+        * @author Bastian Waidelich <bastian@typo3.org>
+        */
+       public function renderIteratesThroughElementsOfTraversableObjects() {
+               $this->templateVariableContainer->expects($this->at(0))->method('add')->with('innerVariable', 'value1');
+               $this->templateVariableContainer->expects($this->at(1))->method('remove')->with('innerVariable');
+               $this->templateVariableContainer->expects($this->at(2))->method('add')->with('innerVariable', 'value2');
+               $this->templateVariableContainer->expects($this->at(3))->method('remove')->with('innerVariable');
+               $this->templateVariableContainer->expects($this->at(4))->method('add')->with('innerVariable', 'value1');
+               $this->templateVariableContainer->expects($this->at(5))->method('remove')->with('innerVariable');
+
+               $traversableObject = new ArrayObject(array('key1' => 'value1', 'key2' => 'value2'));
+               $this->viewHelper->render($traversableObject, 'innerVariable');
+               $this->viewHelper->render($traversableObject, 'innerVariable');
+               $this->viewHelper->render($traversableObject, 'innerVariable');
+       }
+}
+
+?>
index 2ce878b..5643ff1 100644 (file)
@@ -93,7 +93,7 @@ class Tx_Fluid_ViewHelpers_ForViewHelperTest_testcase extends Tx_Fluid_ViewHelpe
         * @test
         * @author Bastian Waidelich <bastian@typo3.org>
         */
-       public function renderReturnsEmptyStringIfObjectIsEmtyArray() {
+       public function renderReturnsEmptyStringIfObjectIsEmptyArray() {
                $viewHelper = new Tx_Fluid_ViewHelpers_ForViewHelper();
 
                $this->assertEquals('', $viewHelper->render(array(), 'foo'));
diff --git a/typo3/sysext/fluid/Tests/ViewHelpers/Format/PaddingViewHelperTest_testcase.php b/typo3/sysext/fluid/Tests/ViewHelpers/Format/PaddingViewHelperTest_testcase.php
new file mode 100644 (file)
index 0000000..c323fd0
--- /dev/null
@@ -0,0 +1,73 @@
+<?php
+
+/*                                                                        *
+ * This script belongs to the FLOW3 package "Fluid".                      *
+ *                                                                        *
+ * It 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, or (at your      *
+ * option) any later version.                                             *
+ *                                                                        *
+ * This script is distributed in the hope that it will be useful, but     *
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN-    *
+ * TABILITY 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 the script.                                                 *
+ * If not, see http://www.gnu.org/licenses/gpl.html                       *
+ *                                                                        *
+ * The TYPO3 project - inspiring people to share!                         *
+ *                                                                        */
+
+/**
+ * @version $Id$
+ */
+require_once(t3lib_extMgm::extPath('extbase', 'Tests/Base_testcase.php'));
+class Tx_Fluid_ViewHelpers_Format_PaddingViewHelperTest_testcase extends Tx_Extbase_Base_testcase {
+
+       /**
+        * @test
+        * @author Bastian Waidelich <bastian@typo3.org>
+        */
+       public function stringsArePaddedWithBlanksByDefault() {
+               $viewHelper = $this->getMock('Tx_Fluid_ViewHelpers_Format_PaddingViewHelper', array('renderChildren'));
+               $viewHelper->expects($this->once())->method('renderChildren')->will($this->returnValue('foo'));
+               $actualResult = $viewHelper->render(10);
+               $this->assertEquals('foo       ', $actualResult);
+       }
+
+       /**
+        * @test
+        * @author Bastian Waidelich <bastian@typo3.org>
+        */
+       public function paddingStringCanBeSpecified() {
+               $viewHelper = $this->getMock('Tx_Fluid_ViewHelpers_Format_PaddingViewHelper', array('renderChildren'));
+               $viewHelper->expects($this->once())->method('renderChildren')->will($this->returnValue('foo'));
+               $actualResult = $viewHelper->render(10, '-=');
+               $this->assertEquals('foo-=-=-=-', $actualResult);
+       }
+
+       /**
+        * @test
+        * @author Bastian Waidelich <bastian@typo3.org>
+        */
+       public function stringIsNotTruncatedIfPadLengthIsBelowStringLength() {
+               $viewHelper = $this->getMock('Tx_Fluid_ViewHelpers_Format_PaddingViewHelper', array('renderChildren'));
+               $viewHelper->expects($this->once())->method('renderChildren')->will($this->returnValue('some long string'));
+               $actualResult = $viewHelper->render(5);
+               $this->assertEquals('some long string', $actualResult);
+       }
+
+       /**
+        * @test
+        * @author Bastian Waidelich <bastian@typo3.org>
+        */
+       public function integersArePaddedCorrectly() {
+               $viewHelper = $this->getMock('Tx_Fluid_ViewHelpers_Format_PaddingViewHelper', array('renderChildren'));
+               $viewHelper->expects($this->once())->method('renderChildren')->will($this->returnValue(123));
+               $actualResult = $viewHelper->render(5, '0');
+               $this->assertEquals('12300', $actualResult);
+       }
+}
+?>
\ No newline at end of file
diff --git a/typo3/sysext/fluid/Tests/ViewHelpers/GroupedForViewHelperTest_testcase.php b/typo3/sysext/fluid/Tests/ViewHelpers/GroupedForViewHelperTest_testcase.php
new file mode 100644 (file)
index 0000000..7c3222d
--- /dev/null
@@ -0,0 +1,182 @@
+<?php
+
+/*                                                                        *
+ * This script is part of the TYPO3 project - inspiring people to share!  *
+ *                                                                        *
+ * TYPO3 is free software; you can redistribute it and/or modify it under *
+ * the terms of the GNU General Public License version 2 as published by  *
+ * the Free Software Foundation.                                          *
+ *                                                                        *
+ * This script is distributed in the hope that it will be useful, but     *
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN-    *
+ * TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General      *
+ * Public License for more details.                                       *
+ *                                                                        */
+
+/**
+ * Testcase for CycleViewHelper
+ *
+ * @version $Id$
+ * @license http://opensource.org/licenses/gpl-license.php GNU Public License, version 2
+ */
+
+require_once(dirname(__FILE__) . '/ViewHelperBaseTestcase.php');
+require_once(t3lib_extMgm::extPath('extbase', 'Tests/Base_testcase.php'));
+class Tx_Fluid_ViewHelpers_GroupedForViewHelperTest_testcase extends Tx_Fluid_ViewHelpers_ViewHelperBaseTestcase {
+
+       /**
+        * var Tx_Fluid_ViewHelpers_GroupedForViewHelper
+        */
+       protected $viewHelper;
+
+       public function setUp() {
+               parent::setUp();
+               $this->viewHelper = $this->getMock('Tx_Fluid_ViewHelpers_GroupedForViewHelper', array('renderChildren'));
+               $this->injectDependenciesIntoViewHelper($this->viewHelper);
+               $this->viewHelper->initializeArguments();
+       }
+
+       /**
+        * @test
+        * @author Bastian Waidelich <bastian@typo3.org>
+        */
+       public function renderReturnsEmptyStringIfObjectIsNull() {
+               $this->assertEquals('', $this->viewHelper->render(NULL, 'foo', 'bar'));
+       }
+
+       /**
+        * @test
+        * @author Bastian Waidelich <bastian@typo3.org>
+        */
+       public function renderReturnsEmptyStringIfObjectIsEmptyArray() {
+               $this->assertEquals('', $this->viewHelper->render(array(), 'foo', 'bar'));
+       }
+
+       /**
+        * @test
+        * @expectedException Tx_Fluid_Core_ViewHelper_Exception
+        * @author Bastian Waidelich <bastian@typo3.org>
+        */
+       public function renderThrowsExceptionWhenPassingObjectsToEachThatAreNotTraversable() {
+               $object = new stdClass();
+
+               $this->viewHelper->render($object, 'innerVariable', 'someKey');
+       }
+
+       /**
+        * @test
+        * @author Bastian Waidelich <bastian@typo3.org>
+        */
+       public function renderGroupsMultidimensionalArrayAndPreservesKeys() {
+               $photoshop = array('name' => 'Adobe Photoshop', 'license' => 'commercial');
+               $typo3 = array('name' => 'TYPO3', 'license' => 'GPL');
+               $office = array('name' => 'Microsoft Office', 'license' => 'commercial');
+               $drupal = array('name' => 'Drupal', 'license' => 'GPL');
+               $wordpress = array('name' => 'Wordpress', 'license' => 'GPL');
+
+               $products = array('photoshop' => $photoshop, 'typo3' => $typo3, 'office' => $office, 'drupal' => $drupal, 'wordpress' => $wordpress);
+
+               $this->templateVariableContainer->expects($this->at(0))->method('add')->with('myGroupKey', 'commercial');
+               $this->templateVariableContainer->expects($this->at(1))->method('add')->with('products', array('photoshop' => $photoshop, 'office' => $office));
+               $this->templateVariableContainer->expects($this->at(2))->method('remove')->with('myGroupKey');
+               $this->templateVariableContainer->expects($this->at(3))->method('remove')->with('products');
+               $this->templateVariableContainer->expects($this->at(4))->method('add')->with('myGroupKey', 'GPL');
+               $this->templateVariableContainer->expects($this->at(5))->method('add')->with('products', array('typo3' => $typo3, 'drupal' => $drupal, 'wordpress' => $wordpress));
+               $this->templateVariableContainer->expects($this->at(6))->method('remove')->with('myGroupKey');
+               $this->templateVariableContainer->expects($this->at(7))->method('remove')->with('products');
+
+               $this->viewHelper->render($products, 'products', 'license', 'myGroupKey');
+       }
+
+       /**
+        * @test
+        * @author Bastian Waidelich <bastian@typo3.org>
+        */
+       public function renderGroupsMultidimensionalArrayObjectAndPreservesKeys() {
+               $photoshop = new ArrayObject(array('name' => 'Adobe Photoshop', 'license' => 'commercial'));
+               $typo3 = new ArrayObject(array('name' => 'TYPO3', 'license' => 'GPL'));
+               $office = new ArrayObject(array('name' => 'Microsoft Office', 'license' => 'commercial'));
+               $drupal = new ArrayObject(array('name' => 'Drupal', 'license' => 'GPL'));
+               $wordpress = new ArrayObject(array('name' => 'Wordpress', 'license' => 'GPL'));
+
+               $products = new ArrayObject(array('photoshop' => $photoshop, 'typo3' => $typo3, 'office' => $office, 'drupal' => $drupal, 'wordpress' => $wordpress));
+
+               $this->templateVariableContainer->expects($this->at(0))->method('add')->with('myGroupKey', 'commercial');
+               $this->templateVariableContainer->expects($this->at(1))->method('add')->with('products', array('photoshop' => $photoshop, 'office' => $office));
+               $this->templateVariableContainer->expects($this->at(2))->method('remove')->with('myGroupKey');
+               $this->templateVariableContainer->expects($this->at(3))->method('remove')->with('products');
+               $this->templateVariableContainer->expects($this->at(4))->method('add')->with('myGroupKey', 'GPL');
+               $this->templateVariableContainer->expects($this->at(5))->method('add')->with('products', array('typo3' => $typo3, 'drupal' => $drupal, 'wordpress' => $wordpress));
+               $this->templateVariableContainer->expects($this->at(6))->method('remove')->with('myGroupKey');
+               $this->templateVariableContainer->expects($this->at(7))->method('remove')->with('products');
+
+               $this->viewHelper->render($products, 'products', 'license', 'myGroupKey');
+       }
+
+       /**
+        * @test
+        * @author Bastian Waidelich <bastian@typo3.org>
+        */
+       public function renderGroupsArrayOfObjectsAndPreservesKeys() {
+               $photoshop = new stdClass();
+               $photoshop->name = 'Adobe Photoshop';
+               $photoshop->license = 'commercial';
+               $typo3 = new stdClass();
+               $typo3->name = 'TYPO3';
+               $typo3->license = 'GPL';
+               $office = new stdClass();
+               $office->name = 'Microsoft Office';
+               $office->license = 'commercial';
+               $drupal = new stdClass();
+               $drupal->name = 'Drupal';
+               $drupal->license = 'GPL';
+               $wordpress = new stdClass();
+               $wordpress->name = 'Wordpress';
+               $wordpress->license = 'GPL';
+
+               $products = array('photoshop' => $photoshop, 'typo3' => $typo3, 'office' => $office, 'drupal' => $drupal, 'wordpress' => $wordpress);
+
+               $this->templateVariableContainer->expects($this->at(0))->method('add')->with('myGroupKey', 'commercial');
+               $this->templateVariableContainer->expects($this->at(1))->method('add')->with('products', array('photoshop' => $photoshop, 'office' => $office));
+               $this->templateVariableContainer->expects($this->at(2))->method('remove')->with('myGroupKey');
+               $this->templateVariableContainer->expects($this->at(3))->method('remove')->with('products');
+               $this->templateVariableContainer->expects($this->at(4))->method('add')->with('myGroupKey', 'GPL');
+               $this->templateVariableContainer->expects($this->at(5))->method('add')->with('products', array('typo3' => $typo3, 'drupal' => $drupal, 'wordpress' => $wordpress));
+               $this->templateVariableContainer->expects($this->at(6))->method('remove')->with('myGroupKey');
+               $this->templateVariableContainer->expects($this->at(7))->method('remove')->with('products');
+
+               $this->viewHelper->render($products, 'products', 'license', 'myGroupKey');
+       }
+
+       /**
+        * @test
+        * @author Bastian Waidelich <bastian@typo3.org>
+        */
+       public function groupingByAKeyThatDoesNotExistCreatesASingleGroup() {
+               $photoshop = array('name' => 'Adobe Photoshop', 'license' => 'commercial');
+               $typo3 = array('name' => 'TYPO3', 'license' => 'GPL');
+               $office = array('name' => 'Microsoft Office', 'license' => 'commercial');
+
+               $products = array('photoshop' => $photoshop, 'typo3' => $typo3, 'office' => $office);
+
+               $this->templateVariableContainer->expects($this->at(0))->method('add')->with('groupKey', NULL);
+               $this->templateVariableContainer->expects($this->at(1))->method('add')->with('innerKey', $products);
+               $this->templateVariableContainer->expects($this->at(2))->method('remove')->with('groupKey');
+               $this->templateVariableContainer->expects($this->at(3))->method('remove')->with('innerKey');
+
+               $this->viewHelper->render($products, 'innerKey', 'NonExistingKey');
+       }
+
+       /**
+        * @test
+        * @expectedException Tx_Fluid_Core_ViewHelper_Exception
+        * @author Bastian Waidelich <bastian@typo3.org>
+        */
+       public function renderThrowsExceptionWhenPassingOneDimensionalArraysToEach() {
+               $values = array('some', 'simple', 'array');
+
+               $this->viewHelper->render($values, 'innerVariable', 'someKey');
+       }
+}
+
+?>