1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Doctrine\Bundle\DoctrineBundle\Tests\Repository; |
4
|
|
|
|
5
|
|
|
use Doctrine\Bundle\DoctrineBundle\Repository\ContainerRepositoryFactory; |
6
|
|
|
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepositoryInterface; |
7
|
|
|
use Doctrine\ORM\Configuration; |
8
|
|
|
use Doctrine\ORM\EntityManagerInterface; |
9
|
|
|
use Doctrine\ORM\EntityRepository; |
10
|
|
|
use Doctrine\ORM\Mapping\ClassMetadata; |
11
|
|
|
use PHPUnit\Framework\TestCase; |
12
|
|
|
use Psr\Container\ContainerInterface; |
13
|
|
|
|
14
|
|
|
class ContainerRepositoryFactoryTest extends TestCase |
15
|
|
|
{ |
16
|
|
View Code Duplication |
public function testGetRepositoryReturnsService() |
|
|
|
|
17
|
|
|
{ |
18
|
|
|
if (!interface_exists(ContainerInterface::class)) { |
19
|
|
|
$this->markTestSkipped('Symfony 3.3 is needed for this feature.'); |
20
|
|
|
} |
21
|
|
|
|
22
|
|
|
$em = $this->createEntityManager([ |
23
|
|
|
'Foo\CoolEntity' => 'my_repo', |
24
|
|
|
]); |
25
|
|
|
$repo = new StubRepository($em, new ClassMetadata('')); |
26
|
|
|
$container = $this->createContainer([ |
27
|
|
|
'my_repo' => $repo, |
28
|
|
|
]); |
29
|
|
|
|
30
|
|
|
$factory = new ContainerRepositoryFactory($container); |
31
|
|
|
$this->assertSame($repo, $factory->getRepository($em, 'Foo\CoolEntity')); |
32
|
|
|
} |
33
|
|
|
|
34
|
|
View Code Duplication |
public function testGetRepositoryReturnsEntityRepository() |
|
|
|
|
35
|
|
|
{ |
36
|
|
|
if (!interface_exists(ContainerInterface::class)) { |
37
|
|
|
$this->markTestSkipped('Symfony 3.3 is needed for this feature.'); |
38
|
|
|
} |
39
|
|
|
|
40
|
|
|
$container = $this->createContainer([]); |
41
|
|
|
$em = $this->createEntityManager([ |
42
|
|
|
'Foo\BoringEntity' => null, |
43
|
|
|
]); |
44
|
|
|
|
45
|
|
|
$factory = new ContainerRepositoryFactory($container); |
46
|
|
|
$actualRepo = $factory->getRepository($em, 'Foo\BoringEntity'); |
47
|
|
|
$this->assertInstanceOf(EntityRepository::class, $actualRepo); |
48
|
|
|
// test the same instance is returned |
49
|
|
|
$this->assertSame($actualRepo, $factory->getRepository($em, 'Foo\BoringEntity')); |
50
|
|
|
} |
51
|
|
|
|
52
|
|
View Code Duplication |
public function testCustomRepositoryIsReturned() |
|
|
|
|
53
|
|
|
{ |
54
|
|
|
if (!interface_exists(ContainerInterface::class)) { |
55
|
|
|
$this->markTestSkipped('Symfony 3.3 is needed for this feature.'); |
56
|
|
|
} |
57
|
|
|
|
58
|
|
|
$container = $this->createContainer([]); |
59
|
|
|
$em = $this->createEntityManager([ |
60
|
|
|
'Foo\CustomNormalRepoEntity' => StubRepository::class, |
61
|
|
|
]); |
62
|
|
|
|
63
|
|
|
$factory = new ContainerRepositoryFactory($container); |
64
|
|
|
$actualRepo = $factory->getRepository($em, 'Foo\CustomNormalRepoEntity'); |
65
|
|
|
$this->assertInstanceOf(StubRepository::class, $actualRepo); |
66
|
|
|
// test the same instance is returned |
67
|
|
|
$this->assertSame($actualRepo, $factory->getRepository($em, 'Foo\CustomNormalRepoEntity')); |
68
|
|
|
} |
69
|
|
|
|
70
|
|
|
/** |
71
|
|
|
* @expectedException \RuntimeException |
72
|
|
|
* @expectedExceptionMessage The service "my_repo" must extend EntityRepository (or a base class, like ServiceEntityRepository). |
73
|
|
|
*/ |
74
|
|
View Code Duplication |
public function testServiceRepositoriesMustExtendEntityRepository() |
|
|
|
|
75
|
|
|
{ |
76
|
|
|
if (!interface_exists(ContainerInterface::class)) { |
77
|
|
|
$this->markTestSkipped('Symfony 3.3 is needed for this feature.'); |
78
|
|
|
} |
79
|
|
|
|
80
|
|
|
$repo = new \stdClass(); |
81
|
|
|
|
82
|
|
|
$container = $this->createContainer([ |
83
|
|
|
'my_repo' => $repo, |
84
|
|
|
]); |
85
|
|
|
|
86
|
|
|
$em = $this->createEntityManager([ |
87
|
|
|
'Foo\CoolEntity' => 'my_repo', |
88
|
|
|
]); |
89
|
|
|
|
90
|
|
|
$factory = new ContainerRepositoryFactory($container); |
91
|
|
|
$factory->getRepository($em, 'Foo\CoolEntity'); |
92
|
|
|
} |
93
|
|
|
|
94
|
|
|
/** |
95
|
|
|
* @expectedException \RuntimeException |
96
|
|
|
* @expectedExceptionMessage The "Doctrine\Bundle\DoctrineBundle\Tests\Repository\StubServiceRepository" entity repository implements "Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepositoryInterface", but its service could not be found. Make sure the service exists and is tagged with "doctrine.repository_service". |
97
|
|
|
*/ |
98
|
|
View Code Duplication |
public function testRepositoryMatchesServiceInterfaceButServiceNotFound() |
|
|
|
|
99
|
|
|
{ |
100
|
|
|
if (!interface_exists(ContainerInterface::class)) { |
101
|
|
|
$this->markTestSkipped('Symfony 3.3 is needed for this feature.'); |
102
|
|
|
} |
103
|
|
|
|
104
|
|
|
$container = $this->createContainer([]); |
105
|
|
|
|
106
|
|
|
$em = $this->createEntityManager([ |
107
|
|
|
'Foo\CoolEntity' => StubServiceRepository::class, |
108
|
|
|
]); |
109
|
|
|
|
110
|
|
|
$factory = new ContainerRepositoryFactory($container); |
111
|
|
|
$factory->getRepository($em, 'Foo\CoolEntity'); |
112
|
|
|
} |
113
|
|
|
|
114
|
|
|
/** |
115
|
|
|
* @expectedException \RuntimeException |
116
|
|
|
* @expectedExceptionMessage The "Foo\CoolEntity" entity has a repositoryClass set to "not_a_real_class", but this is not a valid class. Check your class naming. If this is meant to be a service id, make sure this service exists and is tagged with "doctrine.repository_service". |
117
|
|
|
*/ |
118
|
|
View Code Duplication |
public function testCustomRepositoryIsNotAValidClass() |
|
|
|
|
119
|
|
|
{ |
120
|
|
|
if (interface_exists(ContainerInterface::class)) { |
121
|
|
|
$container = $this->createContainer([]); |
122
|
|
|
} else { |
123
|
|
|
// Symfony 3.2 and lower support |
124
|
|
|
$container = null; |
125
|
|
|
} |
126
|
|
|
|
127
|
|
|
$em = $this->createEntityManager([ |
128
|
|
|
'Foo\CoolEntity' => 'not_a_real_class', |
129
|
|
|
]); |
130
|
|
|
|
131
|
|
|
$factory = new ContainerRepositoryFactory($container); |
132
|
|
|
$factory->getRepository($em, 'Foo\CoolEntity'); |
133
|
|
|
} |
134
|
|
|
|
135
|
|
|
private function createContainer(array $services) |
|
|
|
|
136
|
|
|
{ |
137
|
|
|
$container = $this->getMockBuilder(ContainerInterface::class)->getMock(); |
138
|
|
|
$container->expects($this->any()) |
139
|
|
|
->method('has') |
140
|
|
|
->willReturnCallback(function ($id) use ($services) { |
141
|
|
|
return isset($services[$id]); |
142
|
|
|
}); |
143
|
|
|
$container->expects($this->any()) |
144
|
|
|
->method('get') |
145
|
|
|
->willReturnCallback(function ($id) use ($services) { |
146
|
|
|
return $services[$id]; |
147
|
|
|
}); |
148
|
|
|
|
149
|
|
|
return $container; |
150
|
|
|
} |
151
|
|
|
|
152
|
|
|
private function createEntityManager(array $entityRepositoryClasses) |
|
|
|
|
153
|
|
|
{ |
154
|
|
|
$classMetadatas = []; |
155
|
|
|
foreach ($entityRepositoryClasses as $entityClass => $entityRepositoryClass) { |
156
|
|
|
$metadata = new ClassMetadata($entityClass); |
157
|
|
|
$metadata->customRepositoryClassName = $entityRepositoryClass; |
158
|
|
|
|
159
|
|
|
$classMetadatas[$entityClass] = $metadata; |
160
|
|
|
} |
161
|
|
|
|
162
|
|
|
$em = $this->getMockBuilder(EntityManagerInterface::class)->getMock(); |
163
|
|
|
$em->expects($this->any()) |
164
|
|
|
->method('getClassMetadata') |
165
|
|
|
->willReturnCallback(function ($class) use ($classMetadatas) { |
166
|
|
|
return $classMetadatas[$class]; |
167
|
|
|
}); |
168
|
|
|
|
169
|
|
|
$em->expects($this->any()) |
170
|
|
|
->method('getConfiguration') |
171
|
|
|
->willReturn(new Configuration()); |
172
|
|
|
|
173
|
|
|
return $em; |
174
|
|
|
} |
175
|
|
|
} |
176
|
|
|
|
177
|
|
|
class StubRepository extends EntityRepository |
|
|
|
|
178
|
|
|
{ |
179
|
|
|
} |
180
|
|
|
|
181
|
|
|
class StubServiceRepository extends EntityRepository implements ServiceEntityRepositoryInterface |
|
|
|
|
182
|
|
|
{ |
183
|
|
|
} |
184
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.