Преглед на файлове

Merge remote branch 'CodeMeme/889-EntityChoiceField-grouped-choices'

* CodeMeme/889-EntityChoiceField-grouped-choices:
  Whitespace cleanup
  Fixed EntityChoiceList to support grouped entities Refs #889
  Added test for grouped entity choice list Refs #889
Fabien Potencier преди 14 години
родител
ревизия
610583899d

+ 35 - 11
src/Symfony/Bridge/Doctrine/Form/ChoiceList/EntityChoiceList.php

@@ -115,20 +115,12 @@ class EntityChoiceList extends ArrayChoiceList
     /**
      * Initializes the choices and returns them
      *
-     * The choices are generated from the entities. If the entities have a
-     * composite identifier, the choices are indexed using ascending integers.
-     * Otherwise the identifiers are used as indices.
-     *
      * If the entities were passed in the "choices" option, this method
      * does not have any significant overhead. Otherwise, if a query builder
      * was passed in the "query_builder" option, this builder is now used
      * to construct a query which is executed. In the last case, all entities
      * for the underlying class are fetched from the repository.
      *
-     * If the option "property" was passed, the property path in that option
-     * is used as option values. Otherwise this method tries to convert
-     * objects to strings using __toString().
-     *
      * @return array  An array of choices
      */
     protected function load()
@@ -146,7 +138,32 @@ class EntityChoiceList extends ArrayChoiceList
         $this->choices = array();
         $this->entities = array();
 
+        $this->loadEntities($entities);
+
+        return $this->choices;
+    }
+
+    /**
+     * Convert entities into choices with support for groups
+     *
+     * The choices are generated from the entities. If the entities have a
+     * composite identifier, the choices are indexed using ascending integers.
+     * Otherwise the identifiers are used as indices.
+     *
+     * If the option "property" was passed, the property path in that option
+     * is used as option values. Otherwise this method tries to convert
+     * objects to strings using __toString().
+     *
+     */
+    private function loadEntities($entities, $group = null)
+    {
         foreach ($entities as $key => $entity) {
+            if (is_array($entity)) {
+                // Entities are in named groups
+                $this->loadEntities($entity, $key);
+                continue;
+            }
+
             if ($this->propertyPath) {
                 // If the property option was given, use it
                 $value = $this->propertyPath->getValue($entity);
@@ -158,15 +175,22 @@ class EntityChoiceList extends ArrayChoiceList
             if (count($this->identifier) > 1) {
                 // When the identifier consists of multiple field, use
                 // naturally ordered keys to refer to the choices
-                $this->choices[$key] = $value;
-                $this->entities[$key] = $entity;
+                $id = $key;
             } else {
                 // When the identifier is a single field, index choices by
                 // entity ID for performance reasons
                 $id = current($this->getIdentifierValues($entity));
+            }
+            
+            if (null === $group) {
+                // Flat list of choices
                 $this->choices[$id] = $value;
-                $this->entities[$id] = $entity;
+            } else {
+                // Nested choices
+                $this->choices[$group][$id] = $value;
             }
+            
+            $this->entities[$id] = $entity;
         }
     }
 

+ 49 - 0
tests/Symfony/Tests/Bridge/Doctrine/Form/ChoiceList/EntityChoiceListTest.php

@@ -57,4 +57,53 @@ class EntityChoiceListTest extends DoctrineOrmTestCase
         // triggers loading -> exception
         $choiceList->getChoices();
     }
+
+    public function testFlattenedChoicesAreManaged()
+    {
+        $entity1 = new SingleIdentEntity(1, 'Foo');
+        $entity2 = new SingleIdentEntity(2, 'Bar');
+
+        // Persist for managed state
+        $this->em->persist($entity1);
+        $this->em->persist($entity2);
+
+        $choiceList = new EntityChoiceList(
+            $this->em,
+            self::SINGLE_IDENT_CLASS,
+            'name',
+            null,
+            array(
+                $entity1,
+                $entity2,
+            )
+        );
+
+        $this->assertSame(array(1 => 'Foo', 2 => 'Bar'), $choiceList->getChoices());
+    }
+
+    public function testNestedChoicesAreManaged()
+    {
+        $entity1 = new SingleIdentEntity(1, 'Foo');
+        $entity2 = new SingleIdentEntity(2, 'Bar');
+
+        // Oh yea, we're persistin' with fire now!
+        $this->em->persist($entity1);
+        $this->em->persist($entity2);
+
+        $choiceList = new EntityChoiceList(
+            $this->em,
+            self::SINGLE_IDENT_CLASS,
+            'name',
+            null,
+            array(
+                'group1' => array($entity1),
+                'group2' => array($entity2),
+            )
+        );
+
+        $this->assertSame(array(
+            'group1' => array(1 => 'Foo'),
+            'group2' => array(2 => 'Bar')
+        ), $choiceList->getChoices());
+    }
 }