DIContainer   A
last analyzed

Complexity

Total Complexity 16

Size/Duplication

Total Lines 138
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 7

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 16
lcom 1
cbo 7
dl 0
loc 138
ccs 46
cts 46
cp 1
rs 10
c 0
b 0
f 0

9 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 9 1
A getResolver() 0 3 1
A retrieve() 0 10 3
A checkDependencyAccess() 0 9 3
A createDependency() 0 14 2
A resolveDefinition() 0 3 1
A hasSingletonScope() 0 3 1
A getSingleton() 0 6 2
A storeSingleton() 0 6 2
1
<?php
2
3
/*
4
 * Copyright (c) 2011-2015, Celestino Diaz <[email protected]>
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7
 * of this software and associated documentation files (the "Software"), to deal
8
 * in the Software without restriction, including without limitation the rights
9
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
 * copies of the Software, and to permit persons to whom the Software is
11
 * furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
 * THE SOFTWARE.
23
 */
24
25
namespace Brickoo\Component\IoC;
26
27
use Brickoo\Component\Common\Container;
28
use Brickoo\Component\IoC\Definition\DependencyDefinition;
29
use Brickoo\Component\IoC\Exception\DefinitionNotAvailableException;
30
use Brickoo\Component\IoC\Exception\InfiniteDependencyResolveLoopException;
31
use Brickoo\Component\IoC\Resolver\DefinitionResolver;
32
use Brickoo\Component\Validation\Validator\ConstraintValidator;
33
use Brickoo\Component\Validation\Constraint\IsInstanceOfConstraint;
34
35
/**
36
 * DIContainer
37
 *
38
 * Implements a dependency injection container.
39
 * @author Celestino Diaz <[email protected]>
40
 */
41
class DIContainer extends Container {
42
43
    /** @var \Brickoo\Component\IoC\Resolver\DefinitionResolver */
44
    private $resolver;
45
46
    /** @var array */
47
    private $calledDependencies;
48
49
    /** @var array */
50
    private $singletons;
51
52
    /** @var integer */
53
    private $recursionCounter;
54
55
    /**
56
     * Class constructor.
57
     * Calls the parent constructor.
58
     * @param \Brickoo\Component\IoC\Resolver\DefinitionResolver $resolver
59
     * @param array $definitions
60
     */
61 1
    public function __construct(DefinitionResolver $resolver, array $definitions = []) {
62 1
        parent::__construct($definitions, new ConstraintValidator(
63 1
            new IsInstanceOfConstraint("\\Brickoo\\Component\\IoC\\Definition\\DependencyDefinition")
64 1
        ));
65 1
        $this->resolver = $resolver;
66 1
        $this->calledDependencies = [];
67 1
        $this->singletons = [];
68 1
        $this->recursionCounter = 0;
69 1
    }
70
71
    /**
72
     * Return the definition resolver.
73
     * @return \Brickoo\Component\IoC\Resolver\DefinitionResolver
74
     */
75 3
    public function getResolver() {
76 3
        return $this->resolver;
77
    }
78
79
    /**
80
     * Return the resolved dependency.
81
     * @param string $dependencyName
82
     * @throws \Brickoo\Component\IoC\Exception
83
     * @return object the dependency
84
     */
85 4
    public function retrieve($dependencyName) {
86 4
        $this->checkDependencyAccess($dependencyName);
87 3
        $definition = $this->get($dependencyName);
88
89 3
        if ($this->hasSingletonScope($definition)
90 3
            && ($dependency = $this->getSingleton($dependencyName)) !== null) {
91 1
                return $dependency;
92
        }
93 3
        return $this->createDependency($dependencyName, $definition);
94
    }
95
96
    /**
97
     * Check if the dependency can be accessed.
98
     * @param string $dependencyName
99
     * @throws Exception\InfiniteDependencyResolveLoopException
100
     * @throws Exception\DefinitionNotAvailableException
101
     * @return void
102
     */
103 4
    private function checkDependencyAccess($dependencyName) {
104 4
        if (!$this->contains($dependencyName)) {
105 1
            throw new DefinitionNotAvailableException($dependencyName);
106
        }
107
108 3
        if (isset($this->calledDependencies[$dependencyName])) {
109 1
            throw new InfiniteDependencyResolveLoopException(array_pop($this->calledDependencies));
110
        }
111 3
    }
112
113
    /**
114
     * Create the dependency object.
115
     * @param string $dependencyName
116
     * @param \Brickoo\Component\IoC\Definition\DependencyDefinition $definition
117
     * @throws \Brickoo\Component\IoC\Exception
118
     * @return object
119
     */
120 2
    private function createDependency($dependencyName, DependencyDefinition $definition) {
121
        try {
122 2
            $this->calledDependencies[$dependencyName] = true;
123 2
            $dependency = $this->resolveDefinition($definition);
124
125 2
            if ($this->hasSingletonScope($definition)) {
126 1
                $this->storeSingleton($dependencyName, $dependency);
127 1
            }
128 2
            return $dependency;
129
        }
130
        finally {
131 2
            unset($this->calledDependencies[$dependencyName]);
132 2
        }
133
    }
134
135
    /**
136
     * Return the resolved dependency.
137
     * @param \Brickoo\Component\IoC\Definition\DependencyDefinition $dependencyDefinition
138
     * @return object
139
     */
140 2
    private function resolveDefinition(DependencyDefinition $dependencyDefinition) {
141 2
        return $this->getResolver()->resolve($this, $dependencyDefinition);
142
    }
143
144
    /**
145
     * Check if the definition targets singleton scope.
146
     * @param \Brickoo\Component\IoC\Definition\DependencyDefinition $definition
147
     * @return boolean
148
     */
149 2
    private function hasSingletonScope(DependencyDefinition $definition) {
150 2
        return ($definition->getScope() == DependencyDefinition::SCOPE_SINGLETON);
151
    }
152
153
    /**
154
     * Return the stored singleton dependency.
155
     * @param string $dependencyName
156
     * @return null|object
157
     */
158 1
    private function getSingleton($dependencyName) {
159 1
        if (isset($this->singletons[$dependencyName])) {
160 1
            return $this->singletons[$dependencyName];
161
        }
162 1
        return null;
163
    }
164
165
    /**
166
     * Store the dependency as singleton.
167
     * @param string $dependencyName
168
     * @param object $dependency
169
     * @return \Brickoo\Component\IoC\DIContainer
170
     */
171 1
    private function storeSingleton($dependencyName, $dependency) {
172 1
        if (!isset($this->singletons[$dependencyName])) {
173 1
            $this->singletons[$dependencyName] = $dependency;
174 1
        }
175 1
        return $this;
176
    }
177
178
}
179