[BUGFIX] SelectViewHelper must respect option(Value|Label)Field for arrays 09/36909/2
authorAlexander Schnitzler <git@alexanderschnitzler.de>
Sat, 14 Feb 2015 16:32:28 +0000 (17:32 +0100)
committerAnja Leichsenring <aleichsenring@ab-softlab.de>
Sat, 28 Feb 2015 20:46:20 +0000 (21:46 +0100)
The SelectViewHelper tries to resolve the value and label
field as long as options are of type object, i.e. domain
objects but that functionality must also exist for arrays
because their structure is similar to objects.

Example:
<f:form.select
options="{items}"
optionValueField="uid"
optionLabelField="title"
/>

$items = array(
    0 => array(
        'uid' => 1,
        'title' => 'Foo'
    ),
);

Currently the view helper tries to use the array key as
value field (i.e. 0) and the array value (i.e. array) as
label and fails calling htmlspecialchars on the array.

This patch allows values to be arrays themselves and to
be treated like domain objects.

Resolves: #65073
Releases: master, 6.2
Change-Id: Ia803ceb38c1f7488d48863f5a6781b229def50c4
Reviewed-on: http://review.typo3.org/36909
Reviewed-by: Stefan Froemken <froemken@gmail.com>
Tested-by: Stefan Froemken <froemken@gmail.com>
Tested-by: Andy Grunwald <andygrunwald@gmail.com>
Reviewed-by: Wouter Wolters <typo3@wouterwolters.nl>
Reviewed-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Tested-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
typo3/sysext/fluid/Classes/ViewHelpers/Form/SelectViewHelper.php
typo3/sysext/fluid/Tests/Unit/ViewHelpers/Form/SelectViewHelperTest.php

index ad9ef7e..6c992c3 100644 (file)
@@ -155,7 +155,7 @@ class SelectViewHelper extends \TYPO3\CMS\Fluid\ViewHelpers\Form\AbstractFormFie
                $options = array();
                $optionsArgument = $this->arguments['options'];
                foreach ($optionsArgument as $key => $value) {
-                       if (is_object($value)) {
+                       if (is_object($value) || is_array($value)) {
                                if ($this->hasArgument('optionValueField')) {
                                        $key = \TYPO3\CMS\Extbase\Reflection\ObjectAccess::getPropertyPath($value, $this->arguments['optionValueField']);
                                        if (is_object($key)) {
index e055ec2..8624044 100644 (file)
@@ -84,6 +84,113 @@ class SelectViewHelperTest extends \TYPO3\CMS\Fluid\Tests\Unit\ViewHelpers\Form\
        /**
         * @test
         */
+       public function selectCreatesExpectedOptionsWithArraysAndOptionValueFieldAndOptionLabelFieldSet() {
+               $this->tagBuilder->expects($this->once())->method('setContent')->with(
+                       '<option value="2"></option>' . chr(10) .
+                       '<option value="-1">Bar</option>' . chr(10) .
+                       '<option value="">Baz</option>' . chr(10) .
+                       '<option value="1">Foo</option>' . chr(10)
+               );
+
+               $this->arguments['optionValueField'] = 'uid';
+               $this->arguments['optionLabelField'] = 'title';
+               $this->arguments['sortByOptionLabel'] = TRUE;
+               $this->arguments['options'] = array(
+                       array(
+                               'uid' => 1,
+                               'title' => 'Foo'
+                       ),
+                       array(
+                               'uid' => -1,
+                               'title' => 'Bar'
+                       ),
+                       array(
+                               'title' => 'Baz'
+                       ),
+                       array(
+                               'uid' => '2'
+                       ),
+               );
+
+               $this->injectDependenciesIntoViewHelper($this->viewHelper);
+               $this->viewHelper->initialize();
+               $this->viewHelper->render();
+       }
+
+       /**
+        * @test
+        */
+       public function selectCreatesExpectedOptionsWithStdClassesAndOptionValueFieldAndOptionLabelFieldSet() {
+               $this->tagBuilder->expects($this->once())->method('setContent')->with(
+                       '<option value="2"></option>' . chr(10) .
+                       '<option value="-1">Bar</option>' . chr(10) .
+                       '<option value="">Baz</option>' . chr(10) .
+                       '<option value="1">Foo</option>' . chr(10)
+               );
+
+               $obj1 = new \StdClass();
+               $obj1->uid = 1;
+               $obj1->title = 'Foo';
+
+               $obj2 = new \StdClass();
+               $obj2->uid = -1;
+               $obj2->title = 'Bar';
+
+               $obj3 = new \StdClass();
+               $obj3->title = 'Baz';
+
+               $obj4 = new \StdClass();
+               $obj4->uid = 2;
+
+               $this->arguments['optionValueField'] = 'uid';
+               $this->arguments['optionLabelField'] = 'title';
+               $this->arguments['sortByOptionLabel'] = TRUE;
+               $this->arguments['options'] = array($obj1, $obj2, $obj3, $obj4);
+
+               $this->injectDependenciesIntoViewHelper($this->viewHelper);
+               $this->viewHelper->initialize();
+               $this->viewHelper->render();
+       }
+
+       /**
+        * @test
+        */
+       public function selectCreatesExpectedOptionsWithArrayObjectsAndOptionValueFieldAndOptionLabelFieldSet() {
+               $this->tagBuilder->expects($this->once())->method('setContent')->with(
+                       '<option value="2"></option>' . chr(10) .
+                       '<option value="-1">Bar</option>' . chr(10) .
+                       '<option value="">Baz</option>' . chr(10) .
+                       '<option value="1">Foo</option>' . chr(10)
+               );
+
+               $this->arguments['optionValueField'] = 'uid';
+               $this->arguments['optionLabelField'] = 'title';
+               $this->arguments['sortByOptionLabel'] = TRUE;
+               $this->arguments['options'] = new \ArrayObject(array(
+                       array(
+                               'uid' => 1,
+                               'title' => 'Foo'
+                       ),
+                       array(
+                               'uid' => -1,
+                               'title' => 'Bar'
+                       ),
+                       array(
+                               'title' => 'Baz'
+                       ),
+                       array(
+                               'uid' => '2'
+                       ),
+               ));
+
+               $this->injectDependenciesIntoViewHelper($this->viewHelper);
+               $this->viewHelper->initialize();
+               $this->viewHelper->render();
+       }
+
+       /**
+        * @test
+        */
        public function anEmptyOptionTagIsRenderedIfOptionsArrayIsEmptyToAssureXhtmlCompatibility() {
                $this->tagBuilder->expects($this->once())->method('addAttribute')->with('name', 'myName');
                $this->viewHelper->expects($this->once())->method('registerFieldNameForFormTokenGeneration')->with('myName');