IntegrationTest.php 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. <?php
  2. namespace JMS\Serializer\Tests\Serializer\Doctrine;
  3. use Doctrine\Common\Annotations\AnnotationReader;
  4. use Doctrine\Common\Annotations\Reader;
  5. use Doctrine\Common\Persistence\AbstractManagerRegistry;
  6. use Doctrine\Common\Persistence\ManagerRegistry;
  7. use Doctrine\DBAL\Connection;
  8. use Doctrine\DBAL\DriverManager;
  9. use Doctrine\ORM\Configuration;
  10. use Doctrine\ORM\EntityManager;
  11. use Doctrine\ORM\Mapping\Driver\AnnotationDriver;
  12. use Doctrine\ORM\ORMException;
  13. use Doctrine\ORM\Tools\SchemaTool;
  14. use JMS\Serializer\Builder\CallbackDriverFactory;
  15. use JMS\Serializer\Builder\DefaultDriverFactory;
  16. use JMS\Serializer\Metadata\Driver\DoctrineTypeDriver;
  17. use JMS\Serializer\Serializer;
  18. use JMS\Serializer\SerializerBuilder;
  19. use JMS\Serializer\Tests\Fixtures\Doctrine\SingleTableInheritance\Clazz;
  20. use JMS\Serializer\Tests\Fixtures\Doctrine\SingleTableInheritance\Excursion;
  21. use JMS\Serializer\Tests\Fixtures\Doctrine\SingleTableInheritance\Organization;
  22. use JMS\Serializer\Tests\Fixtures\Doctrine\SingleTableInheritance\Person;
  23. use JMS\Serializer\Tests\Fixtures\Doctrine\SingleTableInheritance\School;
  24. use JMS\Serializer\Tests\Fixtures\Doctrine\SingleTableInheritance\Student;
  25. use JMS\Serializer\Tests\Fixtures\Doctrine\SingleTableInheritance\Teacher;
  26. class IntegrationTest extends \PHPUnit_Framework_TestCase
  27. {
  28. /** @var ManagerRegistry */
  29. private $registry;
  30. /** @var Serializer */
  31. private $serializer;
  32. public function testDiscriminatorIsInferredForEntityBaseClass()
  33. {
  34. $school = new School();
  35. $json = $this->serializer->serialize($school, 'json');
  36. $this->assertEquals('{"type":"school"}', $json);
  37. $deserialized = $this->serializer->deserialize($json, Organization::class, 'json');
  38. $this->assertEquals($school, $deserialized);
  39. }
  40. public function testDiscriminatorIsInferredForGenericBaseClass()
  41. {
  42. $student = new Student();
  43. $json = $this->serializer->serialize($student, 'json');
  44. $this->assertEquals('{"type":"student"}', $json);
  45. $deserialized = $this->serializer->deserialize($json, Person::class, 'json');
  46. $this->assertEquals($student, $deserialized);
  47. }
  48. public function testDiscriminatorIsInferredFromDoctrine()
  49. {
  50. /** @var EntityManager $em */
  51. $em = $this->registry->getManager();
  52. $student1 = new Student();
  53. $student2 = new Student();
  54. $teacher = new Teacher();
  55. $class = new Clazz($teacher, array($student1, $student2));
  56. $em->persist($student1);
  57. $em->persist($student2);
  58. $em->persist($teacher);
  59. $em->persist($class);
  60. $em->flush();
  61. $em->clear();
  62. $reloadedClass = $em->find(get_class($class), $class->getId());
  63. $this->assertNotSame($class, $reloadedClass);
  64. $json = $this->serializer->serialize($reloadedClass, 'json');
  65. $this->assertEquals('{"id":1,"teacher":{"id":1,"type":"teacher"},"students":[{"id":2,"type":"student"},{"id":3,"type":"student"}]}', $json);
  66. }
  67. protected function setUp()
  68. {
  69. $connection = $this->createConnection();
  70. $entityManager = $this->createEntityManager($connection);
  71. $this->registry = $registry = new SimpleManagerRegistry(
  72. function ($id) use ($connection, $entityManager) {
  73. switch ($id) {
  74. case 'default_connection':
  75. return $connection;
  76. case 'default_manager':
  77. return $entityManager;
  78. default:
  79. throw new \RuntimeException(sprintf('Unknown service id "%s".', $id));
  80. }
  81. }
  82. );
  83. $this->serializer = SerializerBuilder::create()
  84. ->setMetadataDriverFactory(new CallbackDriverFactory(
  85. function (array $metadataDirs, Reader $annotationReader) use ($registry) {
  86. $defaultFactory = new DefaultDriverFactory();
  87. return new DoctrineTypeDriver($defaultFactory->createDriver($metadataDirs, $annotationReader), $registry);
  88. }
  89. ))
  90. ->build();
  91. $this->prepareDatabase();
  92. }
  93. private function prepareDatabase()
  94. {
  95. /** @var EntityManager $em */
  96. $em = $this->registry->getManager();
  97. $tool = new SchemaTool($em);
  98. $tool->createSchema($em->getMetadataFactory()->getAllMetadata());
  99. }
  100. private function createConnection()
  101. {
  102. $con = DriverManager::getConnection(array(
  103. 'driver' => 'pdo_sqlite',
  104. 'memory' => true,
  105. ));
  106. return $con;
  107. }
  108. private function createEntityManager(Connection $con)
  109. {
  110. $cfg = new Configuration();
  111. $cfg->setMetadataDriverImpl(new AnnotationDriver(new AnnotationReader(), array(
  112. __DIR__ . '/../../Fixtures/Doctrine/SingleTableInheritance',
  113. )));
  114. $cfg->setAutoGenerateProxyClasses(true);
  115. $cfg->setProxyNamespace('JMS\Serializer\DoctrineProxy');
  116. $cfg->setProxyDir(sys_get_temp_dir() . '/serializer-test-proxies');
  117. $em = EntityManager::create($con, $cfg);
  118. return $em;
  119. }
  120. }
  121. class SimpleManagerRegistry extends AbstractManagerRegistry
  122. {
  123. private $services = array();
  124. private $serviceCreator;
  125. 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')
  126. {
  127. if (null === $defaultConnection) {
  128. $defaultConnection = key($connections);
  129. }
  130. if (null === $defaultManager) {
  131. $defaultManager = key($managers);
  132. }
  133. parent::__construct($name, $connections, $managers, $defaultConnection, $defaultManager, $proxyInterface);
  134. if (!is_callable($serviceCreator)) {
  135. throw new \InvalidArgumentException('$serviceCreator must be a valid callable.');
  136. }
  137. $this->serviceCreator = $serviceCreator;
  138. }
  139. public function getService($name)
  140. {
  141. if (isset($this->services[$name])) {
  142. return $this->services[$name];
  143. }
  144. return $this->services[$name] = call_user_func($this->serviceCreator, $name);
  145. }
  146. public function resetService($name)
  147. {
  148. unset($this->services[$name]);
  149. }
  150. public function getAliasNamespace($alias)
  151. {
  152. foreach (array_keys($this->getManagers()) as $name) {
  153. $manager = $this->getManager($name);
  154. if ($manager instanceof EntityManager) {
  155. try {
  156. return $manager->getConfiguration()->getEntityNamespace($alias);
  157. } catch (ORMException $ex) {
  158. // Probably mapped by another entity manager, or invalid, just ignore this here.
  159. }
  160. } else {
  161. throw new \LogicException(sprintf('Unsupported manager type "%s".', get_class($manager)));
  162. }
  163. }
  164. throw new \RuntimeException(sprintf('The namespace alias "%s" is not known to any manager.', $alias));
  165. }
  166. }