Completed
Push — master ( 4e1fd0...6b9342 )
by Matthieu
02:24
created

DefinitionNormalizer::normalizeRootDefinition()   C

Complexity

Conditions 7
Paths 20

Duplication

Lines 0
Ratio 0 %

Size

Total Lines 30
Code Lines 21

Importance

Changes 0
Metric Value
cc 7
eloc 21
nc 20
nop 2
dl 0
loc 30
rs 6.7272
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace DI\Definition\Source;
6
7
use DI\Definition\ArrayDefinition;
8
use DI\Definition\AutowireDefinition;
9
use DI\Definition\DecoratorDefinition;
10
use DI\Definition\Definition;
11
use DI\Definition\Exception\InvalidDefinition;
12
use DI\Definition\FactoryDefinition;
13
use DI\Definition\Helper\DefinitionHelper;
14
use DI\Definition\ValueDefinition;
15
16
/**
17
 * Turns raw definitions/definition helpers into definitions ready
18
 * to be resolved or compiled.
19
 *
20
 * @author Matthieu Napoli <[email protected]>
21
 */
22
class DefinitionNormalizer
23
{
24
    /**
25
     * @var Autowiring
26
     */
27
    private $autowiring;
28
29
    public function __construct(Autowiring $autowiring)
30
    {
31
        $this->autowiring = $autowiring;
32
    }
33
34
    /**
35
     * Normalize a definition that is *not* nested in another one.
36
     *
37
     * This is usually a definition declared at the root of a definition array.
38
     *
39
     * @param mixed $definition
40
     * @param string $name The definition name.
41
     *
42
     * @throws InvalidDefinition
43
     */
44
    public function normalizeRootDefinition($definition, string $name) : Definition
45
    {
46
        if ($definition instanceof DefinitionHelper) {
47
            $definition = $definition->getDefinition($name);
48
        } elseif (is_array($definition)) {
49
            $definition = new ArrayDefinition($definition);
50
        } elseif ($definition instanceof \Closure) {
51
            $definition = new FactoryDefinition($name, $definition);
52
        } elseif (! $definition instanceof Definition) {
53
            $definition = new ValueDefinition($definition);
54
        }
55
56
        if ($definition instanceof AutowireDefinition) {
57
            $definition = $this->autowiring->autowire($name, $definition);
58
        }
59
60
        $definition->setName($name);
0 ignored issues
show
Bug introduced by Matthieu Napoli
It seems like $definition is not always an object, but can also be of type null. Maybe add an additional type check?

If a variable is not always an object, we recommend to add an additional type check to ensure your method call is safe:

function someFunction(A $objectMaybe = null)
{
    if ($objectMaybe instanceof A) {
        $objectMaybe->doSomething();
    }
}
Loading history...
61
62
        try {
63
            $definition->replaceNestedDefinitions([$this, 'normalizeNestedDefinition']);
64
        } catch (InvalidDefinition $e) {
65
            throw InvalidDefinition::create($definition, sprintf(
0 ignored issues
show
Bug introduced by Matthieu Napoli
It seems like $definition defined by $this->autowiring->autowire($name, $definition) on line 57 can be null; however, DI\Definition\Exception\...lidDefinition::create() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
66
                'Definition "%s" contains an error: %s',
67
                $definition->getName(),
68
                $e->getMessage()
69
            ), $e);
70
        }
71
72
        return $definition;
73
    }
74
75
    /**
76
     * Normalize a definition that is nested in another one.
77
     *
78
     * @param mixed $definition
79
     * @return mixed
80
     *
81
     * @throws InvalidDefinition
82
     */
83
    public function normalizeNestedDefinition($definition)
84
    {
85
        $name = '<nested definition>';
86
87
        if ($definition instanceof DefinitionHelper) {
88
            $definition = $definition->getDefinition($name);
89
        } elseif (is_array($definition)) {
90
            $definition = new ArrayDefinition($definition);
91
        } elseif ($definition instanceof \Closure) {
92
            $definition = new FactoryDefinition($name, $definition);
93
        }
94
95
        if ($definition instanceof DecoratorDefinition) {
96
            throw new InvalidDefinition('Decorators cannot be nested in another definition');
97
        }
98
99
        if ($definition instanceof AutowireDefinition) {
100
            $definition = $this->autowiring->autowire($name, $definition);
101
        }
102
103
        if ($definition instanceof Definition) {
104
            $definition->setName($name);
105
106
            // Recursively traverse nested definitions
107
            $definition->replaceNestedDefinitions([$this, 'normalizeNestedDefinition']);
108
        }
109
110
        return $definition;
111
    }
112
}
113