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

RepositoryAliasPass::process()   C

Complexity

Conditions 14
Paths 66

Size

Total Lines 72
Code Lines 41

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 0 Features 1
Metric Value
c 4
b 0
f 1
dl 0
loc 72
rs 5.4961
cc 14
eloc 41
nc 66
nop 1

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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
            $rootConflicts = [];
51
            foreach ($customRepositories as $repositoryClass => $entities) {
52
                $repoConflicts = $this->findConflictingServices($container, $repositoryClass);
53
54
                if (count($repoConflicts)) {
55
                    $rootConflicts[$repositoryClass] = $repoConflicts;
56
                }
57
            }
58
59
            foreach ($customRepositories as $repositoryClass => $entities) {
60
                if ($container->has($repositoryClass)) {
61
                    continue;
62
                }
63
64
                if (count($entities) !== 1) {
65
                    $this->log($container, "Cannot auto-register repository \"".$repositoryClass."\": Entity belongs to multiple entity managers.");
66
                    continue;
67
                }
68
69
                if (isset($rootConflicts[$repositoryClass])) {
70
                    $this->log($container, "Cannot auto-register repository \"".$repositoryClass."\": There are already services for the repository class.");
71
                    continue;
72
                }
73
74
                foreach ($rootConflicts as $conflictingRepo => $conflicts) {
75
                    if (is_subclass_of($repositoryClass, $conflictingRepo, true)) {
0 ignored issues
show
Bug introduced by
Due to PHP Bug #53727, is_subclass_of might return inconsistent results on some PHP versions if $conflictingRepo can be an interface. If so, you could instead use ReflectionClass::implementsInterface.
Loading history...
76
                        $this->log($container, "Cannot auto-register repository \"".$repositoryClass."\": There are already services for a superclass of the repository class.");
77
                        continue 2;
78
                    }
79
                }
80
81
                $container->register($repositoryClass, $repositoryClass)
82
                    ->setFactory([new Reference('doctrine'), 'getRepository'])
83
                    ->setArguments($entities[0])
84
                    ->setShared(false)
85
                    ->setPublic(false)
86
                ;
87
            }
88
        }
89
    }
90
91
    private function findConflictingServices(ContainerBuilder $container, $repositoryClass)
92
    {
93
        if (Kernel::MAJOR_VERSION >= 4) {
94
            return [];
95
        }
96
97
        $conflictingServices = [];
98
        $parameterBag = $container->getParameterBag();
99
100
        foreach ($container->getDefinitions() as $id => $definition) {
101
            $defClass = $parameterBag->resolveValue($definition->getClass());
102
103
            if ($defClass != $repositoryClass) {
104
                continue;
105
            }
106
107
            $conflictingServices[] = $id;
108
        }
109
110
        return $conflictingServices;
111
    }
112
113
    private function log(ContainerBuilder $container, $message)
114
    {
115
        if (method_exists($container, 'log')) {
116
            $container->log($this, $message);
0 ignored issues
show
Bug introduced by
The method log() does not seem to exist on object<Symfony\Component...ction\ContainerBuilder>.

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...
117
        }
118
    }
119
}
120