1<?php 2 3declare(strict_types=1); 4 5namespace JMS\Serializer\Tests\Metadata\Driver; 6 7use Doctrine\Common\Annotations\AnnotationReader; 8use Doctrine\ORM\Configuration; 9use Doctrine\ORM\EntityManager; 10use Doctrine\ORM\Mapping\Driver\AnnotationDriver as DoctrineDriver; 11use JMS\Serializer\Metadata\Driver\AnnotationDriver; 12use JMS\Serializer\Metadata\Driver\DoctrineTypeDriver; 13use JMS\Serializer\Naming\IdenticalPropertyNamingStrategy; 14use JMS\Serializer\Tests\Fixtures\Doctrine\BlogPostWithEmbedded; 15use PHPUnit\Framework\TestCase; 16 17class DoctrineDriverTest extends TestCase 18{ 19 public function getMetadata() 20 { 21 $refClass = new \ReflectionClass('JMS\Serializer\Tests\Fixtures\Doctrine\BlogPost'); 22 return $this->getDoctrineDriver()->loadMetadataForClass($refClass); 23 } 24 25 public function testMetadataForEmbedded() 26 { 27 $refClass = new \ReflectionClass(BlogPostWithEmbedded::class); 28 $meta = $this->getDoctrineDriver()->loadMetadataForClass($refClass); 29 self::assertNotNull($meta); 30 } 31 32 public function testTypelessPropertyIsGivenTypeFromDoctrineMetadata() 33 { 34 $metadata = $this->getMetadata(); 35 36 self::assertEquals( 37 ['name' => 'DateTime', 'params' => []], 38 $metadata->propertyMetadata['createdAt']->type 39 ); 40 } 41 42 public function testSingleValuedAssociationIsProperlyHinted() 43 { 44 $metadata = $this->getMetadata(); 45 self::assertEquals( 46 ['name' => 'JMS\Serializer\Tests\Fixtures\Doctrine\Author', 'params' => []], 47 $metadata->propertyMetadata['author']->type 48 ); 49 } 50 51 public function testMultiValuedAssociationIsProperlyHinted() 52 { 53 $metadata = $this->getMetadata(); 54 55 self::assertEquals( 56 [ 57 'name' => 'ArrayCollection', 58 'params' => [ 59 ['name' => 'JMS\Serializer\Tests\Fixtures\Doctrine\Comment', 'params' => []], 60 ], 61 ], 62 $metadata->propertyMetadata['comments']->type 63 ); 64 } 65 66 public function testTypeGuessByDoctrineIsOverwrittenByDelegateDriver() 67 { 68 $metadata = $this->getMetadata(); 69 70 // This would be guessed as boolean but we've overriden it to integer 71 self::assertEquals( 72 ['name' => 'integer', 'params' => []], 73 $metadata->propertyMetadata['published']->type 74 ); 75 } 76 77 public function testUnknownDoctrineTypeDoesNotResultInAGuess() 78 { 79 $metadata = $this->getMetadata(); 80 self::assertNull($metadata->propertyMetadata['slug']->type); 81 } 82 83 public function testNonDoctrineEntityClassIsNotModified() 84 { 85 // Note: Using regular BlogPost fixture here instead of Doctrine fixture 86 // because it has no Doctrine metadata. 87 $refClass = new \ReflectionClass('JMS\Serializer\Tests\Fixtures\BlogPost'); 88 89 $plainMetadata = $this->getAnnotationDriver()->loadMetadataForClass($refClass); 90 $doctrineMetadata = $this->getDoctrineDriver()->loadMetadataForClass($refClass); 91 92 // Do not compare timestamps 93 if (abs($doctrineMetadata->createdAt - $plainMetadata->createdAt) < 2) { 94 $plainMetadata->createdAt = $doctrineMetadata->createdAt; 95 } 96 97 self::assertEquals($plainMetadata, $doctrineMetadata); 98 } 99 100 public function testExcludePropertyNoPublicAccessorException() 101 { 102 $first = $this->getAnnotationDriver() 103 ->loadMetadataForClass(new \ReflectionClass('JMS\Serializer\Tests\Fixtures\ExcludePublicAccessor')); 104 105 self::assertArrayHasKey('id', $first->propertyMetadata); 106 self::assertArrayNotHasKey('iShallNotBeAccessed', $first->propertyMetadata); 107 } 108 109 public function testVirtualPropertiesAreNotModified() 110 { 111 $doctrineMetadata = $this->getMetadata(); 112 self::assertNull($doctrineMetadata->propertyMetadata['ref']->type); 113 } 114 115 public function testGuidPropertyIsGivenStringType() 116 { 117 $metadata = $this->getMetadata(); 118 119 self::assertEquals( 120 ['name' => 'string', 'params' => []], 121 $metadata->propertyMetadata['id']->type 122 ); 123 } 124 125 protected function getEntityManager() 126 { 127 $config = new Configuration(); 128 $config->setProxyDir(sys_get_temp_dir() . '/JMSDoctrineTestProxies'); 129 $config->setProxyNamespace('JMS\Tests\Proxies'); 130 $config->setMetadataDriverImpl( 131 new DoctrineDriver(new AnnotationReader(), __DIR__ . '/../../Fixtures/Doctrine') 132 ); 133 134 $conn = [ 135 'driver' => 'pdo_sqlite', 136 'memory' => true, 137 ]; 138 139 return EntityManager::create($conn, $config); 140 } 141 142 public function getAnnotationDriver() 143 { 144 return new AnnotationDriver(new AnnotationReader(), new IdenticalPropertyNamingStrategy()); 145 } 146 147 protected function getDoctrineDriver() 148 { 149 $registry = $this->getMockBuilder('Doctrine\Common\Persistence\ManagerRegistry')->getMock(); 150 $registry->expects($this->atLeastOnce()) 151 ->method('getManagerForClass') 152 ->will($this->returnValue($this->getEntityManager())); 153 154 return new DoctrineTypeDriver( 155 $this->getAnnotationDriver(), 156 $registry 157 ); 158 } 159} 160