ソースを参照

Merge pull request #2302 from caponica/fix_transformer_array_access_entity

Fixed problem with ModelToIdPropertyTransformer and ArrayAccess entities
Andrej Hudec 10 年 前
コミット
e6fc41ccb7

+ 15 - 3
Form/DataTransformer/ModelToIdPropertyTransformer.php

@@ -84,10 +84,22 @@ class ModelToIdPropertyTransformer implements DataTransformerInterface
         if (!$entityOrCollection) {
             return $result;
         }
-        if ($entityOrCollection instanceof \ArrayAccess) {
-            $collection = $entityOrCollection;
+        if ($this->multiple) {
+            if (substr(get_class($entityOrCollection), -1 * strlen($this->className)) == $this->className) {
+                throw new \InvalidArgumentException('A multiple selection must be passed a collection not a single value.');
+            } elseif ($entityOrCollection instanceof \ArrayAccess) {
+                $collection = $entityOrCollection;
+            } else {
+                throw new \InvalidArgumentException('A multiple selection must be passed a collection not a single value.');
+            }
         } else {
-            $collection = array($entityOrCollection);
+            if (substr(get_class($entityOrCollection), -1 * strlen($this->className)) == $this->className) {
+                $collection = array($entityOrCollection);
+            } elseif ($entityOrCollection instanceof \ArrayAccess) {
+                throw new \InvalidArgumentException('A single selection must be passed a single value not a collection.');
+            } else {
+                $collection = array($entityOrCollection);
+            }
         }
 
         if (empty($this->property)) {

+ 59 - 0
Tests/Fixtures/Entity/FooArrayAccess.php

@@ -0,0 +1,59 @@
+<?php
+
+namespace Sonata\AdminBundle\Tests\Fixtures\Entity;
+
+class FooArrayAccess implements \ArrayAccess
+{
+    // methods to enable ArrayAccess
+    public function offsetExists($offset) {
+        $value = $this->offsetGet($offset);
+        return $value !== null;
+    }
+
+    public function offsetGet($offset) {
+        $offset = str_replace('_', '', $offset); // method names always use camels, field names can use snakes
+        $methodName = "get$offset";
+        if (method_exists($this, $methodName)) {
+            return $this->$methodName();
+        } else {
+            return null;
+        }
+    }
+
+    public function offsetSet($offset, $value) {
+        throw new \BadMethodCallException ("Array access of class " . get_class($this) . " is read-only!");
+    }
+
+    public function offsetUnset($offset) {
+        throw new \BadMethodCallException("Array access of class " . get_class($this) . " is read-only!");
+    }
+
+    private $bar;
+
+    private $baz;
+
+    public function getBar()
+    {
+        return $this->bar;
+    }
+
+    public function setBar($bar)
+    {
+        $this->bar = $bar;
+    }
+
+    public function getBaz()
+    {
+        return $this->baz;
+    }
+
+    public function setBaz($baz)
+    {
+        $this->baz = $baz;
+    }
+
+    public function __toString()
+    {
+        return (string) $this->bar;
+    }
+}

+ 15 - 0
Tests/Form/DataTransformer/ModelToIdPropertyTransformerTest.php

@@ -13,6 +13,7 @@ namespace Sonata\AdminBundle\Tests\Form\DataTransformer;
 
 use Sonata\AdminBundle\Form\DataTransformer\ModelToIdPropertyTransformer;
 use Sonata\AdminBundle\Tests\Fixtures\Entity\Foo;
+use Sonata\AdminBundle\Tests\Fixtures\Entity\FooArrayAccess;
 use Doctrine\Common\Collections\ArrayCollection;
 
 class ModelToIdPropertyTransformerTest extends \PHPUnit_Framework_TestCase
@@ -128,6 +129,20 @@ class ModelToIdPropertyTransformerTest extends \PHPUnit_Framework_TestCase
         $this->assertEquals(array('identifiers' => array(123), 'labels' => array('example')), $transformer->transform($entity));
     }
 
+    public function testTransformWorksWithArrayAccessEntity()
+    {
+        $entity = new FooArrayAccess();
+        $entity->setBar('example');
+
+        $this->modelManager->expects($this->once())
+            ->method('getIdentifierValues')
+            ->will($this->returnValue(array(123)));
+
+        $transformer = new ModelToIdPropertyTransformer($this->modelManager, 'Sonata\AdminBundle\Tests\Fixtures\Entity\FooArrayAccess', 'bar', false);
+
+        $this->assertEquals(array('identifiers' => array(123), 'labels' => array('example')), $transformer->transform($entity));
+    }
+
     public function testTransformToStringCallback()
     {
         $entity = new Foo();