Browse Source

Merge pull request #1739 from pulzarraider/list_choice_multiple_values

Added support for `multiple` option in list/show `choice` field type.
Thomas 11 years ago
parent
commit
7517db3d59

+ 17 - 2
Resources/doc/reference/field_types.rst

@@ -19,14 +19,29 @@ There are many field types that can be used in the list action or show action :
 * percent: display a percentage
 * choice: uses the given value as index for the ``choices`` array and displays (and optionally translates) the matching value
 
+Choice
+^^^^^^
+
+.. code-block:: php
+
+    // For value ``prog`` is displayed text ``In progress``. The ``AcmeDemoBundle`` catalogue will be used to translate ``In progress`` message.
+    $listMapper->add('status', 'choice', array('choices'=>array('prep'=>'Prepared', 'prog'=>'In progress', 'done'=>'Done'), 'catalogue' => 'AcmeDemoBundle'));
+
+``choice`` filed type also supports multiple values that can be separated by ``delimiter`` (default delimiter is a comma ``, ``).
+
+.. code-block:: php
+
+    // For value ``array('r', 'b')`` is displayed `text ``red | blue``.
+    $listMapper->add('colors', 'choice', array('multiple'=>true, 'delimiter'=>' | ', 'choices'=>array('r'=>'red', 'g'=>'green', 'b'=>'blue')));
+
 .. note::
 
     If the ``SonataIntlBundle`` is installed in the project some template types
     will be changed to use localized information.
-    
+
     Option for currency type must be an official ISO code, example : EUR for "euros".
     List of iso code : http://en.wikipedia.org/wiki/List_of_circulating_currencies
-    
+
     In ``date`` and ``datetime`` field types, ``format`` pattern must match twig's
     ``date`` filter specification, available at: http://twig.sensiolabs.org/doc/filters/date.html
 

+ 34 - 6
Resources/views/CRUD/list_choice.html.twig

@@ -12,12 +12,40 @@ file that was distributed with this source code.
 {% extends admin.getTemplate('base_list_field') %}
 
 {% block field %}
-    {% if field_description.options.choices and value in field_description.options.choices|keys %}
-        {% if field_description.options.catalogue is not defined %}
-            {% set value = field_description.options.choices[value] %}
-        {% else %}
-            {% set value = field_description.options.choices[value]|trans({}, field_description.options.catalogue) %}
+{% spaceless %}
+    {% if field_description.options.choices  is defined %}
+        {% if field_description.options.multiple is defined and field_description.options.multiple==true and value is iterable %}
+
+            {% set result = '' %}
+            {% set delimiter = field_description.options.delimiter|default(', ') %}
+
+            {% for val in value %}
+                {% if result is not empty %}
+                    {% set result = result ~ delimiter %}
+                {% endif %}
+
+                {% if field_description.options.choices[val] is defined %}
+                    {% if field_description.options.catalogue is not defined %}
+                        {% set result = result ~ field_description.options.choices[val] %}
+                    {% else %}
+                        {% set result = result ~ field_description.options.choices[val]|trans({}, field_description.options.catalogue) %}
+                    {% endif %}
+                {% else %}
+                    {% set result = result ~ val %}
+                {% endif %}
+            {% endfor %}
+
+            {% set value = result %}
+
+        {% elseif value in field_description.options.choices|keys %}
+            {% if field_description.options.catalogue is not defined %}
+                {% set value = field_description.options.choices[value] %}
+            {% else %}
+                {% set value = field_description.options.choices[value]|trans({}, field_description.options.catalogue) %}
+            {% endif %}
         {% endif %}
     {% endif %}
-    {{ parent() }}
+
+    {{ value }}
+{% endspaceless %}
 {% endblock %}

+ 33 - 5
Resources/views/CRUD/show_choice.html.twig

@@ -11,11 +11,37 @@ file that was distributed with this source code.
 {% extends 'SonataAdminBundle:CRUD:base_show_field.html.twig' %}
 
 {% block field%}
-    {% if field_description.options.choices and value in field_description.options.choices|keys %}
-        {% if field_description.options.catalogue is not defined %}
-            {% set value = field_description.options.choices[value] %}
-        {% else %}
-            {% set value = field_description.options.choices[value]|trans({}, field_description.options.catalogue) %}
+{% spaceless %}
+    {% if field_description.options.choices  is defined %}
+        {% if field_description.options.multiple is defined and field_description.options.multiple==true and value is iterable %}
+
+            {% set result = '' %}
+            {% set delimiter = field_description.options.delimiter|default(', ') %}
+
+            {% for val in value %}
+                {% if result is not empty %}
+                    {% set result = result ~ delimiter %}
+                {% endif %}
+
+                {% if field_description.options.choices[val] is defined %}
+                    {% if field_description.options.catalogue is not defined %}
+                        {% set result = result ~ field_description.options.choices[val] %}
+                    {% else %}
+                        {% set result = result ~ field_description.options.choices[val]|trans({}, field_description.options.catalogue) %}
+                    {% endif %}
+                {% else %}
+                    {% set result = result ~ val %}
+                {% endif %}
+            {% endfor %}
+
+            {% set value = result %}
+
+        {% elseif value in field_description.options.choices|keys %}
+            {% if field_description.options.catalogue is not defined %}
+                {% set value = field_description.options.choices[value] %}
+            {% else %}
+                {% set value = field_description.options.choices[value]|trans({}, field_description.options.catalogue) %}
+            {% endif %}
         {% endif %}
     {% endif %}
 
@@ -24,4 +50,6 @@ file that was distributed with this source code.
     {% else %}
         {{ value }}
     {% endif %}
+
+{% endspaceless %}
 {% endblock %}

+ 29 - 12
Tests/Twig/Extension/SonataAdminExtensionTest.php

@@ -246,20 +246,28 @@ class SonataAdminExtensionTest extends \PHPUnit_Framework_TestCase
             array('<td class="sonata-ba-list-field sonata-ba-list-field-currency" objectId="12345"> </td>', 'currency', null, array('currency' => 'EUR')),
             array('<td class="sonata-ba-list-field sonata-ba-list-field-currency" objectId="12345"> GBP 51.23456 </td>', 'currency', 51.23456, array('currency' => 'GBP')),
             array('<td class="sonata-ba-list-field sonata-ba-list-field-currency" objectId="12345"> </td>', 'currency', null, array('currency' => 'GBP')),
-            array('<td class="sonata-ba-list-field sonata-ba-list-field-array" objectId="12345"> [1 => First] [2 => Second] </td>', 'array', array(1 => 'First', 2 => 'Second'), array('safe' => false)),
-            array('<td class="sonata-ba-list-field sonata-ba-list-field-array" objectId="12345"> </td>', 'array', null, array('safe' => false)),
+            array('<td class="sonata-ba-list-field sonata-ba-list-field-array" objectId="12345"> [1 => First] [2 => Second] </td>', 'array', array(1 => 'First', 2 => 'Second'), array()),
+            array('<td class="sonata-ba-list-field sonata-ba-list-field-array" objectId="12345"> </td>', 'array', null, array()),
             array('<td class="sonata-ba-list-field sonata-ba-list-field-boolean" objectId="12345"> <i class="icon-ok-circle"></i>&nbsp;yes </td>', 'boolean', true, array('editable'=>false)),
             array('<td class="sonata-ba-list-field sonata-ba-list-field-boolean" objectId="12345"> <i class="icon-ban-circle"></i>&nbsp;no </td>', 'boolean', false, array('editable'=>false)),
             array('<td class="sonata-ba-list-field sonata-ba-list-field-boolean" objectId="12345"> <i class="icon-ban-circle"></i>&nbsp;no </td>', 'boolean', null, array('editable'=>false)),
             array('<td class="sonata-ba-list-field sonata-ba-list-field-boolean" objectId="12345"> <a href="http://localhost/core/set-object-field-value?context=list&amp;field=fd_name&amp;objectId=12345&amp;value=0&amp;code=xyz" class="sonata-ba-action sonata-ba-edit-inline"><i class="icon-ok-circle"></i>&nbsp;yes</a> </td>', 'boolean', true, array('editable'=>true)),
             array('<td class="sonata-ba-list-field sonata-ba-list-field-boolean" objectId="12345"> <a href="http://localhost/core/set-object-field-value?context=list&amp;field=fd_name&amp;objectId=12345&amp;value=1&amp;code=xyz" class="sonata-ba-action sonata-ba-edit-inline"><i class="icon-ban-circle"></i>&nbsp;no</a> </td>', 'boolean', false, array('editable'=>true)),
             array('<td class="sonata-ba-list-field sonata-ba-list-field-boolean" objectId="12345"> <a href="http://localhost/core/set-object-field-value?context=list&amp;field=fd_name&amp;objectId=12345&amp;value=1&amp;code=xyz" class="sonata-ba-action sonata-ba-edit-inline"><i class="icon-ban-circle"></i>&nbsp;no</a> </td>', 'boolean', null, array('editable'=>true)),
-            array('<td class="sonata-ba-list-field sonata-ba-list-field-trans" objectId="12345"> Delete </td>', 'trans', 'action_delete', array('safe'=>false, 'catalogue'=>'SonataAdminBundle')),
-            array('<td class="sonata-ba-list-field sonata-ba-list-field-trans" objectId="12345"> </td>', 'trans', null, array('safe'=>false, 'catalogue'=>'SonataAdminBundle')),
-            array('<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> Description of status1 </td>', 'choice', 'Status1', array('safe'=>false, 'choices'=>array('Status1'=>'Description of status1', 'Status2'=>'Description of status2'))),
-            array('<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> </td>', 'choice', null, array('safe'=>false, 'choices'=>array('Status1'=>'Description of status1', 'Status2'=>'Description of status2'))),
-            array('<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> NoValidKeyInChoices </td>', 'choice', 'NoValidKeyInChoices', array('safe'=>false, 'choices'=>array('Status1'=>'Description of status1', 'Status2'=>'Description of status2'))),
-            array('<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> Delete </td>', 'choice', 'Foo', array('safe'=>false, 'catalogue'=>'SonataAdminBundle', 'choices'=>array('Foo'=>'action_delete', 'Status2'=>'Description of status2'))),
+            array('<td class="sonata-ba-list-field sonata-ba-list-field-trans" objectId="12345"> Delete </td>', 'trans', 'action_delete', array('catalogue'=>'SonataAdminBundle')),
+            array('<td class="sonata-ba-list-field sonata-ba-list-field-trans" objectId="12345"> </td>', 'trans', null, array('catalogue'=>'SonataAdminBundle')),
+            array('<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> Status1 </td>', 'choice', 'Status1', array()),
+            array('<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> Alias1 </td>', 'choice', 'Status1', array('choices'=>array('Status1'=>'Alias1', 'Status2'=>'Alias2', 'Status3'=>'Alias3'))),
+            array('<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> </td>', 'choice', null, array('choices'=>array('Status1'=>'Alias1', 'Status2'=>'Alias2', 'Status3'=>'Alias3'))),
+            array('<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> NoValidKeyInChoices </td>', 'choice', 'NoValidKeyInChoices', array('choices'=>array('Status1'=>'Alias1', 'Status2'=>'Alias2', 'Status3'=>'Alias3'))),
+            array('<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> Delete </td>', 'choice', 'Foo', array('catalogue'=>'SonataAdminBundle', 'choices'=>array('Foo'=>'action_delete', 'Status2'=>'Alias2', 'Status3'=>'Alias3'))),
+            array('<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> Alias1, Alias3 </td>', 'choice', array('Status1', 'Status3'), array('choices'=>array('Status1'=>'Alias1', 'Status2'=>'Alias2', 'Status3'=>'Alias3'), 'multiple'=>true)),
+            array('<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> Alias1 | Alias3 </td>', 'choice', array('Status1', 'Status3'), array('choices'=>array('Status1'=>'Alias1', 'Status2'=>'Alias2', 'Status3'=>'Alias3'), 'multiple'=>true, 'delimiter'=>' | ')),
+            array('<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> </td>', 'choice', null, array('choices'=>array('Status1'=>'Alias1', 'Status2'=>'Alias2', 'Status3'=>'Alias3'), 'multiple'=>true)),
+            array('<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> NoValidKeyInChoices </td>', 'choice', array('NoValidKeyInChoices'), array('choices'=>array('Status1'=>'Alias1', 'Status2'=>'Alias2', 'Status3'=>'Alias3'), 'multiple'=>true)),
+            array('<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> NoValidKeyInChoices, Alias2 </td>', 'choice', array('NoValidKeyInChoices', 'Status2'), array('choices'=>array('Status1'=>'Alias1', 'Status2'=>'Alias2', 'Status3'=>'Alias3'), 'multiple'=>true)),
+            array('<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> Delete, Alias3 </td>', 'choice', array('Foo', 'Status3'), array('catalogue'=>'SonataAdminBundle', 'choices'=>array('Foo'=>'action_delete', 'Status2'=>'Alias2', 'Status3'=>'Alias3'), 'multiple'=>true)),
+            array('<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> &lt;b&gt;Alias1&lt;/b&gt;, &lt;b&gt;Alias3&lt;/b&gt; </td>', 'choice', array('Status1', 'Status3'), array('choices'=>array('Status1'=>'<b>Alias1</b>', 'Status2'=>'<b>Alias2</b>', 'Status3'=>'<b>Alias3</b>'), 'multiple'=>true)),
         );
     }
 
@@ -340,9 +348,17 @@ class SonataAdminExtensionTest extends \PHPUnit_Framework_TestCase
             array('<th>Data</th> <td><i class="icon-ok-circle"></i>yes</td>', 'boolean', true, array()),
             array('<th>Data</th> <td><i class="icon-ban-circle"></i>no</td>', 'boolean', false, array()),
             array('<th>Data</th> <td> Delete </td>', 'trans', 'action_delete', array('safe'=>false, 'catalogue'=>'SonataAdminBundle')),
-            array('<th>Data</th> <td> Description of status1 </td>', 'choice', 'Status1', array('safe'=>false, 'choices'=>array('Status1'=>'Description of status1', 'Status2'=>'Description of status2'))),
-            array('<th>Data</th> <td> NoValidKeyInChoices </td>', 'choice', 'NoValidKeyInChoices', array('safe'=>false, 'choices'=>array('Status1'=>'Description of status1', 'Status2'=>'Description of status2'))),
-            array('<th>Data</th> <td> Delete </td>', 'choice', 'Foo', array('safe'=>false, 'catalogue'=>'SonataAdminBundle', 'choices'=>array('Foo'=>'action_delete', 'Status2'=>'Description of status2'))),
+            array('<th>Data</th> <td>Status1</td>', 'choice', 'Status1', array('safe'=>false)),
+            array('<th>Data</th> <td>Alias1</td>', 'choice', 'Status1', array('safe'=>false, 'choices'=>array('Status1'=>'Alias1', 'Status2'=>'Alias2', 'Status3'=>'Alias3'))),
+            array('<th>Data</th> <td>NoValidKeyInChoices</td>', 'choice', 'NoValidKeyInChoices', array('safe'=>false, 'choices'=>array('Status1'=>'Alias1', 'Status2'=>'Alias2', 'Status3'=>'Alias3'))),
+            array('<th>Data</th> <td>Delete</td>', 'choice', 'Foo', array('safe'=>false, 'catalogue'=>'SonataAdminBundle', 'choices'=>array('Foo'=>'action_delete', 'Status2'=>'Alias2', 'Status3'=>'Alias3'))),
+            array('<th>Data</th> <td>NoValidKeyInChoices</td>', 'choice', array('NoValidKeyInChoices'), array('safe'=>false, 'choices'=>array('Status1'=>'Alias1', 'Status2'=>'Alias2', 'Status3'=>'Alias3'), 'multiple'=>true,)),
+            array('<th>Data</th> <td>NoValidKeyInChoices, Alias2</td>', 'choice', array('NoValidKeyInChoices', 'Status2'), array('safe'=>false, 'choices'=>array('Status1'=>'Alias1', 'Status2'=>'Alias2', 'Status3'=>'Alias3'), 'multiple'=>true,)),
+            array('<th>Data</th> <td>Alias1, Alias3</td>', 'choice', array('Status1', 'Status3'), array('safe'=>false, 'choices'=>array('Status1'=>'Alias1', 'Status2'=>'Alias2', 'Status3'=>'Alias3'), 'multiple'=>true,)),
+            array('<th>Data</th> <td>Alias1 | Alias3</td>', 'choice', array('Status1', 'Status3'), array('safe'=>false, 'choices'=>array('Status1'=>'Alias1', 'Status2'=>'Alias2', 'Status3'=>'Alias3'), 'multiple'=>true, 'delimiter'=>' | ')),
+            array('<th>Data</th> <td>Delete, Alias3</td>', 'choice', array('Foo', 'Status3'), array('safe'=>false, 'catalogue'=>'SonataAdminBundle', 'choices'=>array('Foo'=>'action_delete', 'Status2'=>'Alias2', 'Status3'=>'Alias3'), 'multiple'=>true,)),
+            array('<th>Data</th> <td><b>Alias1</b>, <b>Alias3</b></td>', 'choice', array('Status1', 'Status3'), array('safe'=>true, 'choices'=>array('Status1'=>'<b>Alias1</b>', 'Status2'=>'<b>Alias2</b>', 'Status3'=>'<b>Alias3</b>'), 'multiple'=>true,)),
+            array('<th>Data</th> <td>&lt;b&gt;Alias1&lt;/b&gt;, &lt;b&gt;Alias3&lt;/b&gt;</td>', 'choice', array('Status1', 'Status3'), array('safe'=>false, 'choices'=>array('Status1'=>'<b>Alias1</b>', 'Status2'=>'<b>Alias2</b>', 'Status3'=>'<b>Alias3</b>'), 'multiple'=>true,)),
 
             // NoValueException
             array('<th>Data</th> <td></td>', 'string', new NoValueException(), array('safe' => false)),
@@ -361,7 +377,8 @@ class SonataAdminExtensionTest extends \PHPUnit_Framework_TestCase
             array('<th>Data</th> <td> </td>', 'array', new NoValueException(), array('safe' => false)),
             array('<th>Data</th> <td><i class="icon-ban-circle"></i>no</td>', 'boolean', new NoValueException(), array()),
             array('<th>Data</th> <td> </td>', 'trans', new NoValueException(), array('safe'=>false, 'catalogue'=>'SonataAdminBundle')),
-            array('<th>Data</th> <td> </td>', 'choice', new NoValueException(), array('safe'=>false, 'choices'=>array())),
+            array('<th>Data</th> <td></td>', 'choice', new NoValueException(), array('safe'=>false, 'choices'=>array())),
+            array('<th>Data</th> <td></td>', 'choice', new NoValueException(), array('safe'=>false, 'choices'=>array(), 'multiple'=>true)),
         );
     }