1<?php
2
3declare(strict_types=1);
4
5namespace JMS\Serializer\Tests\Metadata\Driver;
6
7use Doctrine\Common\Annotations\AnnotationReader;
8use Doctrine\ODM\PHPCR\Configuration;
9use Doctrine\ODM\PHPCR\DocumentManager;
10use Doctrine\ODM\PHPCR\Mapping\Driver\AnnotationDriver as DoctrinePHPCRDriver;
11use JMS\Serializer\Metadata\Driver\AnnotationDriver;
12use JMS\Serializer\Metadata\Driver\DoctrinePHPCRTypeDriver;
13use JMS\Serializer\Naming\IdenticalPropertyNamingStrategy;
14use PHPUnit\Framework\TestCase;
15
16class DoctrinePHPCRDriverTest extends TestCase
17{
18    public function getMetadata()
19    {
20        $refClass = new \ReflectionClass('JMS\Serializer\Tests\Fixtures\DoctrinePHPCR\BlogPost');
21        return $this->getDoctrinePHPCRDriver()->loadMetadataForClass($refClass);
22    }
23
24    public function testTypelessPropertyIsGivenTypeFromDoctrineMetadata()
25    {
26        $metadata = $this->getMetadata();
27        self::assertEquals(
28            ['name' => 'DateTime', 'params' => []],
29            $metadata->propertyMetadata['createdAt']->type
30        );
31    }
32
33    public function testSingleValuedAssociationIsProperlyHinted()
34    {
35        $metadata = $this->getMetadata();
36        self::assertEquals(
37            ['name' => 'JMS\Serializer\Tests\Fixtures\DoctrinePHPCR\Author', 'params' => []],
38            $metadata->propertyMetadata['author']->type
39        );
40    }
41
42    public function testMultiValuedAssociationIsProperlyHinted()
43    {
44        $metadata = $this->getMetadata();
45
46        self::assertEquals(
47            [
48                'name' => 'ArrayCollection',
49                'params' => [
50                    ['name' => 'JMS\Serializer\Tests\Fixtures\DoctrinePHPCR\Comment', 'params' => []],
51                ],
52            ],
53            $metadata->propertyMetadata['comments']->type
54        );
55    }
56
57    public function testTypeGuessByDoctrineIsOverwrittenByDelegateDriver()
58    {
59        $metadata = $this->getMetadata();
60
61        // This would be guessed as boolean but we've overridden it to integer
62        self::assertEquals(
63            ['name' => 'integer', 'params' => []],
64            $metadata->propertyMetadata['published']->type
65        );
66    }
67
68    public function testNonDoctrineDocumentClassIsNotModified()
69    {
70        // Note: Using regular BlogPost fixture here instead of Doctrine fixture
71        // because it has no Doctrine metadata.
72        $refClass = new \ReflectionClass('JMS\Serializer\Tests\Fixtures\BlogPost');
73
74        $plainMetadata = $this->getAnnotationDriver()->loadMetadataForClass($refClass);
75        $doctrineMetadata = $this->getDoctrinePHPCRDriver()->loadMetadataForClass($refClass);
76
77        // Do not compare timestamps
78        if (abs($doctrineMetadata->createdAt - $plainMetadata->createdAt) < 2) {
79            $plainMetadata->createdAt = $doctrineMetadata->createdAt;
80        }
81
82        self::assertEquals($plainMetadata, $doctrineMetadata);
83    }
84
85    protected function getDocumentManager()
86    {
87        $config = new Configuration();
88        $config->setProxyDir(sys_get_temp_dir() . '/JMSDoctrineTestProxies');
89        $config->setProxyNamespace('JMS\Tests\Proxies');
90        $config->setMetadataDriverImpl(
91            new DoctrinePHPCRDriver(new AnnotationReader(), __DIR__ . '/../../Fixtures/DoctrinePHPCR')
92        );
93
94        $session = $this->getMockBuilder('PHPCR\SessionInterface')->getMock();
95
96        return DocumentManager::create($session, $config);
97    }
98
99    public function getAnnotationDriver()
100    {
101        return new AnnotationDriver(new AnnotationReader(), new IdenticalPropertyNamingStrategy());
102    }
103
104    protected function getDoctrinePHPCRDriver()
105    {
106        $registry = $this->getMockBuilder('Doctrine\Common\Persistence\ManagerRegistry')->getMock();
107        $registry->expects($this->atLeastOnce())
108            ->method('getManagerForClass')
109            ->will($this->returnValue($this->getDocumentManager()));
110
111        return new DoctrinePHPCRTypeDriver(
112            $this->getAnnotationDriver(),
113            $registry
114        );
115    }
116}
117