Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
1 | <?php |
||
15 | class ContainerRepositoryFactoryTest extends TestCase |
||
16 | { |
||
17 | View Code Duplication | public function testGetRepositoryReturnsService() |
|
30 | |||
31 | View Code Duplication | public function testGetRepositoryReturnsEntityRepository() |
|
46 | |||
47 | View Code Duplication | public function testCustomRepositoryIsReturned() |
|
64 | |||
65 | /** |
||
66 | * @expectedException \RuntimeException |
||
67 | * @expectedExceptionMessage The service "my_repo" must implement ObjectRepository (or extend a base class, like ServiceEntityRepository). |
||
68 | */ |
||
69 | View Code Duplication | public function testServiceRepositoriesMustExtendObjectRepository() |
|
70 | { |
||
71 | if (! interface_exists(ContainerInterface::class)) { |
||
72 | $this->markTestSkipped('Symfony 3.3 is needed for this feature.'); |
||
73 | } |
||
74 | |||
75 | $repo = new \stdClass(); |
||
76 | |||
77 | $container = $this->createContainer(['my_repo' => $repo]); |
||
78 | |||
79 | $em = $this->createEntityManager(['Foo\CoolEntity' => 'my_repo']); |
||
80 | |||
81 | $factory = new ContainerRepositoryFactory($container); |
||
82 | $factory->getRepository($em, 'Foo\CoolEntity'); |
||
83 | } |
||
84 | |||
85 | public function testServiceRepositoriesCanNotExtendsEntityRepository() |
||
86 | { |
||
87 | if (! interface_exists(ContainerInterface::class)) { |
||
88 | $this->markTestSkipped('Symfony 3.3 is needed for this feature.'); |
||
89 | } |
||
90 | |||
91 | $repo = $this->getMockBuilder(ObjectRepository::class)->getMock(); |
||
92 | |||
93 | $container = $this->createContainer(['my_repo' => $repo]); |
||
94 | |||
95 | $em = $this->createEntityManager(['Foo\CoolEntity' => 'my_repo']); |
||
96 | |||
97 | $factory = new ContainerRepositoryFactory($container); |
||
98 | $factory->getRepository($em, 'Foo\CoolEntity'); |
||
99 | $actualRepo = $factory->getRepository($em, 'Foo\CoolEntity'); |
||
100 | $this->assertSame($repo, $actualRepo); |
||
101 | } |
||
102 | |||
103 | |||
104 | /** |
||
105 | * @expectedException \RuntimeException |
||
106 | * @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". |
||
107 | */ |
||
108 | View Code Duplication | public function testRepositoryMatchesServiceInterfaceButServiceNotFound() |
|
109 | { |
||
110 | if (! interface_exists(ContainerInterface::class)) { |
||
111 | $this->markTestSkipped('Symfony 3.3 is needed for this feature.'); |
||
112 | } |
||
113 | |||
114 | $container = $this->createContainer([]); |
||
115 | |||
116 | $em = $this->createEntityManager([ |
||
117 | 'Foo\CoolEntity' => StubServiceRepository::class, |
||
118 | ]); |
||
119 | |||
120 | $factory = new ContainerRepositoryFactory($container); |
||
121 | $factory->getRepository($em, 'Foo\CoolEntity'); |
||
122 | } |
||
123 | |||
124 | /** |
||
125 | * @expectedException \RuntimeException |
||
126 | * @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". |
||
127 | */ |
||
128 | View Code Duplication | public function testCustomRepositoryIsNotAValidClass() |
|
129 | { |
||
130 | if (interface_exists(ContainerInterface::class)) { |
||
131 | $container = $this->createContainer([]); |
||
132 | } else { |
||
133 | // Symfony 3.2 and lower support |
||
134 | $container = null; |
||
135 | } |
||
136 | |||
137 | $em = $this->createEntityManager(['Foo\CoolEntity' => 'not_a_real_class']); |
||
138 | |||
139 | $factory = new ContainerRepositoryFactory($container); |
||
140 | $factory->getRepository($em, 'Foo\CoolEntity'); |
||
141 | } |
||
142 | |||
143 | private function createContainer(array $services) |
||
144 | { |
||
145 | $container = $this->getMockBuilder(ContainerInterface::class)->getMock(); |
||
146 | $container->expects($this->any()) |
||
147 | ->method('has') |
||
148 | ->willReturnCallback(function ($id) use ($services) { |
||
149 | return isset($services[$id]); |
||
150 | }); |
||
151 | $container->expects($this->any()) |
||
152 | ->method('get') |
||
153 | ->willReturnCallback(function ($id) use ($services) { |
||
154 | return $services[$id]; |
||
155 | }); |
||
156 | |||
157 | return $container; |
||
158 | } |
||
159 | |||
160 | private function createEntityManager(array $entityRepositoryClasses) |
||
183 | } |
||
184 | |||
185 | class StubRepository extends EntityRepository |
||
186 | { |
||
187 | } |
||
188 | |||
192 |
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.