Completed
Pull Request — master (#658)
by Magnus
02:48
created

RepositoryAliasPass::findConflictingServices()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 21
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 21
rs 9.0534
cc 4
eloc 11
nc 4
nop 2
1
<?php
2
3
namespace Doctrine\Bundle\DoctrineBundle\DependencyInjection\Compiler;
4
5
use Doctrine\Common\Persistence\Mapping\Driver\MappingDriver;
6
use Doctrine\ORM\Mapping\ClassMetadata;
7
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
8
use Symfony\Component\DependencyInjection\ContainerBuilder;
9
use Symfony\Component\DependencyInjection\Definition;
10
use Symfony\Component\DependencyInjection\Reference;
11
use Symfony\Component\HttpKernel\Kernel;
12
13
class RepositoryAliasPass implements CompilerPassInterface
14
{
15
    /**
16
     * {@inheritDoc}
17
     */
18
    public function process(ContainerBuilder $container)
19
    {
20
        if (!$container->hasParameter('doctrine.entity_managers')) {
21
            return;
22
        }
23
24
        $entityManagers = $container->getParameter('doctrine.entity_managers');
25
        $customRepositories = [];
26
27
        foreach ($entityManagers as $name => $serviceName) {
28
            $metadataDriverService = sprintf('doctrine.orm.%s_metadata_driver', $name);
29
30
            if (!$container->has($metadataDriverService)) {
31
                continue;
32
            }
33
34
            /** @var MappingDriver $metadataDriver */
35
            $metadataDriver = $container->get($metadataDriverService);
36
            $entityClassNames = $metadataDriver->getAllClassNames();
37
38
            foreach ($entityClassNames as $entityClassName) {
39
                $classMetadata = new ClassMetadata($entityClassName);
40
                $metadataDriver->loadMetadataForClass($entityClassName, $classMetadata);
41
42
                if ($classMetadata->customRepositoryClassName) {
43
                    $customRepositories[$classMetadata->customRepositoryClassName][] = [
44
                        0 => $entityClassName,
45
                        1 => $name,
46
                    ];
47
                }
48
            }
49
        }
50
51
        $rootConflicts = [];
52
        foreach ($customRepositories as $repositoryClass => $entities) {
53
            $repoConflicts = $this->findConflictingServices($container, $repositoryClass);
54
55
            if (count($repoConflicts)) {
56
                $rootConflicts[$repositoryClass] = $repoConflicts;
57
            }
58
        }
59
60
        foreach ($customRepositories as $repositoryClass => $entities) {
61
            if ($container->has($repositoryClass)) {
62
                continue;
63
            }
64
65
            if (count($entities) !== 1) {
66
                $this->log($container, "Cannot auto-register repository \"".$repositoryClass."\": Entity belongs to multiple entity managers.");
67
                continue;
68
            }
69
70
            if (isset($rootConflicts[$repositoryClass])) {
71
                $this->log($container, "Cannot auto-register repository \"".$repositoryClass."\": There are already services for the repository class.");
72
                continue;
73
            }
74
75
            $definition = $container->register($repositoryClass, $repositoryClass)
76
                ->setFactory([new Reference('doctrine'), 'getRepository'])
77
                ->setArguments($entities[0])
78
                ->setPublic(false)
79
            ;
80
81
            if (Kernel::MAJOR_VERSION <= 2 && Kernel::MINOR_VERSION <= 7) {
82
                $definition->setScope('prototype');
0 ignored issues
show
Bug introduced by
The method setScope() does not seem to exist on object<Symfony\Component...cyInjection\Definition>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
83
            } else {
84
                $definition->setShared(false);
85
            }
86
        }
87
88
    }
89
90
    private function findConflictingServices(ContainerBuilder $container, $repositoryClass)
91
    {
92
        if (Kernel::MAJOR_VERSION >= 4) {
93
            return [];
94
        }
95
96
        $conflictingServices = [];
97
        $parameterBag = $container->getParameterBag();
98
99
        foreach ($container->getDefinitions() as $id => $definition) {
100
            $defClass = $parameterBag->resolveValue($definition->getClass());
101
102
            if ($defClass != $repositoryClass) {
103
                continue;
104
            }
105
106
            $conflictingServices[] = $id;
107
        }
108
109
        return $conflictingServices;
110
    }
111
112
    private function log(ContainerBuilder $container, $message)
113
    {
114
        if (method_exists($container, 'log')) {
115
            $container->log($this, $message);
116
        }
117
    }
118
}
119