FakeReferencesPass   A
last analyzed

Complexity

Total Complexity 13

Size/Duplication

Total Lines 77
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Test Coverage

Coverage 93.75%

Importance

Changes 0
Metric Value
wmc 13
lcom 1
cbo 3
dl 0
loc 77
ccs 30
cts 32
cp 0.9375
rs 10
c 0
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
A process() 0 8 2
A processDefinition() 0 10 2
A processReferences() 0 12 3
A addMissingDefinitionReferenceToContainer() 0 15 4
A isMissingDefinitionReference() 0 5 2
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of Symplify.
7
 * Copyright (c) 2016 Tomas Votruba (http://tomasvotruba.cz).
8
 */
9
10
namespace Symplify\NetteAdapterForSymfonyBundles\Compiler;
11
12
use ReflectionClass;
13
use stdClass;
14
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
15
use Symfony\Component\DependencyInjection\ContainerBuilder;
16
use Symfony\Component\DependencyInjection\ContainerInterface;
17
use Symfony\Component\DependencyInjection\Definition;
18
use Symfony\Component\DependencyInjection\Reference;
19
20
/**
21
 * This compiler pass will disable all missing references to named services.
22
 * Missing parameter resolution shall be resolved in Nette's ContainerBuilder.
23
 *
24
 * Based on @see \Symfony\Component\DependencyInjection\Compiler\CheckExceptionOnInvalidReferenceBehaviorPass
25
 */
26
final class FakeReferencesPass implements CompilerPassInterface
27
{
28
    /**
29
     * @var ContainerBuilder
30
     */
31
    private $container;
32
33
    /**
34
     * {@inheritdoc}
35
     */
36 2
    public function process(ContainerBuilder $container)
37
    {
38 2
        $this->container = $container;
39
40 2
        foreach ($container->getDefinitions() as $id => $definition) {
41 2
            $this->processDefinition($definition);
42
        }
43 2
    }
44
45
    /**
46
     * @param mixed $definition
47
     */
48 2
    private function processDefinition($definition)
49
    {
50 2
        if (! $definition instanceof Definition) {
51 2
            return;
52
        }
53
54 2
        $this->processReferences($definition->getArguments());
55 2
        $this->processReferences($definition->getMethodCalls());
56 2
        $this->processReferences($definition->getProperties());
57 2
    }
58
59
    /**
60
     * @param mixed $arguments
61
     */
62 2
    private function processReferences($arguments)
63
    {
64 2
        if (! is_array($arguments)) {
65 2
            return;
66
        }
67
68 2
        foreach ($arguments as $argument) {
69 2
            $this->processReferences($argument);
70 2
            $this->processDefinition($argument);
71 2
            $this->addMissingDefinitionReferenceToContainer($argument);
72
        }
73 2
    }
74
75
    /**
76
     * @param mixed $argument
77
     */
78 2
    private function addMissingDefinitionReferenceToContainer($argument)
79
    {
80 2
        if (! $this->isMissingDefinitionReference($argument)) {
81 2
            return;
82
        }
83
84 2
        $serviceName = (string) $argument;
85 2
        if (class_exists($serviceName)) {
86
            $serviceName = (new ReflectionClass($serviceName))->name;
87
        }
88
89 2
        if (! $this->container->has($serviceName)) {
90
            $this->container->setDefinition($serviceName, new Definition(stdClass::class));
91
        }
92 2
    }
93
94
    /**
95
     * @param mixed $argument
96
     */
97 2
    private function isMissingDefinitionReference($argument) : bool
98
    {
99 2
        return $argument instanceof Reference
100 2
        && $argument->getInvalidBehavior() === ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE;
101
    }
102
}
103