浏览代码

adds a test for handling single table inheritance with proxies

Johannes Schmitt 11 年之前
父节点
当前提交
0c313929e3

+ 2 - 0
src/JMS/Serializer/SerializerBuilder.php

@@ -329,6 +329,8 @@ class SerializerBuilder
     public function setMetadataDriverFactory(DriverFactoryInterface $driverFactory)
     {
         $this->driverFactory = $driverFactory;
+
+        return $this;
     }
 
     public function build()

+ 43 - 0
tests/JMS/Serializer/Tests/Fixtures/Doctrine/SingleTableInheritance/Clazz.php

@@ -0,0 +1,43 @@
+<?php
+
+namespace JMS\Serializer\Tests\Fixture\Doctrine\SingleTableInheritance;
+
+use Doctrine\Common\Collections\ArrayCollection;
+use Doctrine\ORM\Mapping as ORM;
+use JMS\Serializer\Tests\Fixtures\Doctrine\SingleTableInheritance\Teacher;
+
+/**
+ * @ORM\Entity
+ */
+class Clazz
+{
+    /** @ORM\Id @ORM\GeneratedValue(strategy = "AUTO") @ORM\Column(type = "integer") */
+    private $id;
+
+    /** @ORM\ManyToOne(targetEntity = "JMS\Serializer\Tests\Fixtures\Doctrine\SingleTableInheritance\Teacher") */
+    private $teacher;
+
+    /** @ORM\ManyToMany(targetEntity = "JMS\Serializer\Tests\Fixtures\Doctrine\SingleTableInheritance\Student") */
+    private $students;
+
+    public function __construct(Teacher $teacher, array $students)
+    {
+        $this->teacher = $teacher;
+        $this->students = new ArrayCollection($students);
+    }
+
+    public function getId()
+    {
+        return $this->id;
+    }
+
+    public function getTeacher()
+    {
+        return $this->teacher;
+    }
+
+    public function getStudents()
+    {
+        return $this->students;
+    }
+}

+ 20 - 0
tests/JMS/Serializer/Tests/Fixtures/Doctrine/SingleTableInheritance/Person.php

@@ -0,0 +1,20 @@
+<?php
+
+namespace JMS\Serializer\Tests\Fixtures\Doctrine\SingleTableInheritance;
+
+use Doctrine\ORM\Mapping as ORM;
+
+/**
+ * @ORM\Entity
+ * @ORM\InheritanceType("SINGLE_TABLE")
+ * @ORM\DiscriminatorColumn(name="type", type="string")
+ * @ORM\DiscriminatorMap({
+ *     "student" = "JMS\Serializer\Tests\Fixtures\Doctrine\SingleTableInheritance\Student",
+ *     "teacher" = "JMS\Serializer\Tests\Fixtures\Doctrine\SingleTableInheritance\Teacher",
+ * })
+ */
+abstract class Person
+{
+    /** @ORM\Id @ORM\GeneratedValue(strategy = "AUTO") @ORM\Column(type = "integer") */
+    private $id;
+}

+ 10 - 0
tests/JMS/Serializer/Tests/Fixtures/Doctrine/SingleTableInheritance/Student.php

@@ -0,0 +1,10 @@
+<?php
+
+namespace JMS\Serializer\Tests\Fixtures\Doctrine\SingleTableInheritance;
+
+use Doctrine\ORM\Mapping as ORM;
+
+/**
+ * @ORM\Entity
+ */
+class Student extends Person { }

+ 10 - 0
tests/JMS/Serializer/Tests/Fixtures/Doctrine/SingleTableInheritance/Teacher.php

@@ -0,0 +1,10 @@
+<?php
+
+namespace JMS\Serializer\Tests\Fixtures\Doctrine\SingleTableInheritance;
+
+use Doctrine\ORM\Mapping as ORM;
+
+/**
+ * @ORM\Entity
+ */
+class Teacher extends Person { }

+ 179 - 0
tests/JMS/Serializer/Tests/Serializer/Doctrine/IntegrationTest.php

@@ -0,0 +1,179 @@
+<?php
+
+namespace JMS\Serializer\Tests\Serializer\Doctrine;
+
+use Doctrine\Common\Annotations\AnnotationReader;
+use Doctrine\Common\Annotations\Reader;
+use Doctrine\Common\Persistence\AbstractManagerRegistry;
+use Doctrine\Common\Persistence\ManagerRegistry;
+use Doctrine\DBAL\Connection;
+use Doctrine\DBAL\DriverManager;
+use Doctrine\ORM\Configuration;
+use Doctrine\ORM\Mapping\Driver\AnnotationDriver;
+use Doctrine\ORM\Tools\SchemaTool;
+use JMS\Serializer\Builder\CallbackDriverFactory;
+use JMS\Serializer\Builder\DefaultDriverFactory;
+use JMS\Serializer\Metadata\Driver\DoctrineTypeDriver;
+use JMS\Serializer\Serializer;
+use JMS\Serializer\SerializerBuilder;
+use Doctrine\ORM\EntityManager;
+use Doctrine\ORM\ORMException;
+use JMS\Serializer\Tests\Fixture\Doctrine\SingleTableInheritance\Clazz;
+use JMS\Serializer\Tests\Fixtures\Doctrine\SingleTableInheritance\Excursion;
+use JMS\Serializer\Tests\Fixtures\Doctrine\SingleTableInheritance\Person;
+use JMS\Serializer\Tests\Fixtures\Doctrine\SingleTableInheritance\Student;
+use JMS\Serializer\Tests\Fixtures\Doctrine\SingleTableInheritance\Teacher;
+
+class IntegrationTest extends \PHPUnit_Framework_TestCase
+{
+    /** @var ManagerRegistry */
+    private $registry;
+
+    /** @var Serializer */
+    private $serializer;
+
+    public function testDiscriminatorIsInferredFromDoctrine()
+    {
+        /** @var EntityManager $em */
+        $em = $this->registry->getManager();
+
+        $student1 = new Student();
+        $student2 = new Student();
+        $teacher = new Teacher();
+        $class = new Clazz($teacher, array($student1, $student2));
+
+        $em->persist($student1);
+        $em->persist($student2);
+        $em->persist($teacher);
+        $em->persist($class);
+        $em->flush();
+        $em->clear();
+
+        $reloadedClass = $em->find(get_class($class), $class->getId());
+        $this->assertNotSame($class, $reloadedClass);
+
+        $json = $this->serializer->serialize($reloadedClass, 'json');
+        $this->assertEquals('{"id":1,"teacher":{"id":1,"type":"teacher"},"students":[{"id":2,"type":"student"},{"id":3,"type":"student"}]}', $json);
+    }
+
+    protected function setUp()
+    {
+        $this->registry = new SimpleManagerRegistry(
+            function($id) {
+                switch ($id) {
+                    case 'default_connection':
+                        return $this->createConnection();
+
+                    case 'default_manager':
+                        return $this->createEntityManager($this->registry->getConnection());
+
+                    default:
+                        throw new \RuntimeException(sprintf('Unknown service id "%s".', $id));
+                }
+            }
+        );
+
+        $this->serializer = SerializerBuilder::create()
+            ->setMetadataDriverFactory(new CallbackDriverFactory(
+                function(array $metadataDirs, Reader $annotationReader) {
+                    $defaultFactory = new DefaultDriverFactory();
+
+                    return new DoctrineTypeDriver($defaultFactory->createDriver($metadataDirs, $annotationReader), $this->registry);
+                }
+            ))
+            ->build()
+        ;
+
+        $this->prepareDatabase();
+    }
+
+    private function prepareDatabase()
+    {
+        /** @var EntityManager $em */
+        $em = $this->registry->getManager();
+
+        $tool = new SchemaTool($em);
+        $tool->createSchema($em->getMetadataFactory()->getAllMetadata());
+    }
+
+    private function createConnection()
+    {
+        $con = DriverManager::getConnection(array(
+            'driver' => 'pdo_sqlite',
+            'memory' => true,
+        ));
+
+        return $con;
+    }
+
+    private function createEntityManager(Connection $con)
+    {
+        $cfg = new Configuration();
+        $cfg->setMetadataDriverImpl(new AnnotationDriver(new AnnotationReader(), array(
+            __DIR__.'/../../Fixtures/Doctrine/SingleTableInheritance',
+        )));
+        $cfg->setAutoGenerateProxyClasses(true);
+        $cfg->setProxyNamespace('JMS\Serializer\DoctrineProxy');
+        $cfg->setProxyDir(sys_get_temp_dir().'/serializer-test-proxies');
+
+        $em = EntityManager::create($con, $cfg);
+
+        return $em;
+    }
+}
+
+class SimpleManagerRegistry extends AbstractManagerRegistry
+{
+    private $services = array();
+    private $serviceCreator;
+
+    public function __construct($serviceCreator, $name = 'anonymous', array $connections = array('default' => 'default_connection'), array $managers = array('default' => 'default_manager'), $defaultConnection = null, $defaultManager = null, $proxyInterface = 'Doctrine\Common\Persistence\Proxy')
+    {
+        if (null === $defaultConnection) {
+            list($defaultConnection, ) = each($connections);
+        }
+        if (null === $defaultManager) {
+            list($defaultManager, ) = each($managers);
+        }
+
+        parent::__construct($name, $connections, $managers, $defaultConnection, $defaultManager, $proxyInterface);
+
+        if ( ! is_callable($serviceCreator)) {
+            throw new \InvalidArgumentException('$serviceCreator must be a valid callable.');
+        }
+        $this->serviceCreator = $serviceCreator;
+    }
+
+    public function getService($name)
+    {
+        if (isset($this->services[$name])) {
+            return $this->services[$name];
+        }
+
+        return $this->services[$name] = call_user_func($this->serviceCreator, $name);
+    }
+
+    public function resetService($name)
+    {
+        unset($this->services[$name]);
+    }
+
+    public function getAliasNamespace($alias)
+    {
+        foreach (array_keys($this->getManagers()) as $name) {
+            $manager = $this->getManager($name);
+
+            if ($manager instanceof EntityManager) {
+                try {
+                    return $manager->getConfiguration()->getEntityNamespace($alias);
+                } catch (ORMException $ex) {
+                    // Probably mapped by another entity manager, or invalid, just ignore this here.
+                }
+            } else {
+                throw new \LogicException(sprintf('Unsupported manager type "%s".', get_class($manager)));
+            }
+        }
+
+        throw new \RuntimeException(sprintf('The namespace alias "%s" is not known to any manager.', $alias));
+    }
+}