Passed
Push — master ( a7615b...593a68 )
by Matthias
02:32
created

DependencyInjectionManager::initiateObject()   C

Complexity

Conditions 8
Paths 13

Size

Total Lines 39
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 72

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 39
ccs 0
cts 21
cp 0
rs 5.3846
cc 8
eloc 21
nc 13
nop 3
crap 72
1
<?php
2
/*
3
 * The MIT License (MIT)
4
 *
5
 * Copyright (c) 2015 zepi
6
 *
7
 * Permission is hereby granted, free of charge, to any person obtaining a copy
8
 * of this software and associated documentation files (the "Software"), to deal
9
 * in the Software without restriction, including without limitation the rights
10
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
 * copies of the Software, and to permit persons to whom the Software is
12
 * furnished to do so, subject to the following conditions:
13
 *
14
 * The above copyright notice and this permission notice shall be included in
15
 * all copies or substantial portions of the Software.
16
 *
17
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
 * THE SOFTWARE.
24
 *
25
 */
26
27
/**
28
 * The DependenyInjectionManager manages the initiation of new
29
 * objects. The manager will analyze the construct method of the
30
 * given class name and loads the needed objects for the construction.
31
 * 
32
 * @package Zepi\Turbo\Manager
33
 * @author Matthias Zobrist <[email protected]>
34
 * @copyright Copyright (c) 2016 zepi
35
 */
36
37
namespace Zepi\Turbo\Manager;
38
39
use \Zepi\Turbo\Framework;
40
use \Zepi\Turbo\Exception;
41
use \ReflectionClass;
42
43
/**
44
 * The DependenyInjectionManager manages the initiation of new
45
 * objects. The manager will analyze the construct method of the
46
 * given class name and loads the needed objects for the construction.
47
 * 
48
 * @author Matthias Zobrist <[email protected]>
49
 * @copyright Copyright (c) 2016 zepi
50
 */
51
class DependencyInjectionManager
52
{
53
    /**
54
     * @access protected
55
     * @var Framework
56
     */
57
    protected $framework;
58
    
59
    /**
60
     * @var array
61
     */
62
    protected $sharedInstances = array();
63
    
64
    /**
65
     * Constructs the object
66
     * 
67
     * @access public
68
     * @param \Zepi\Turbo\Framework $framework
69
     */
70 17
    public function __construct(Framework $framework)
71
    {
72 17
        $this->framework = $framework;
73 17
    }
74
    
75
    /**
76
     * Initiates the given class name
77
     *
78
     * @param string $className
79
     * @param array $additionalParameters
80
     * @param boolean $shared
81
     * @return object
82
     * 
83
     * @throws \Zepi\Turbo\Exception Cannot find correct value for parameter "{parameterName}" in class "{className}".
84
     */
85
    public function initiateObject($className, $additionalParameters = array(), $shared = false)
86
    {
87
        if (isset($this->sharedInstances[$className])) {
88
            return $this->sharedInstances[$className];
89
        }
90
        
91
        $reflection = new ReflectionClass($className);
92
        
93
        if (!$reflection->hasMethod('__construct')) {
94
            return new $className();
95
        }
96
        
97
        $constructor = $reflection->getConstructor();
98
        
99
        $parameters = array();
100
        foreach ($constructor->getParameters() as $parameter) {
101
            $parameterValue = null;
102
            
103
            if (isset($additionalParameters[$parameter->name])) {
104
                $parameterValue = $additionalParameters[$parameter->name];
105
            } else if ($parameter->getClass() !== null) {
106
                $parameterValue = $this->getInstance($parameter->getClass());
107
            } 
108
            
109
            if ($parameterValue === null) {
110
                throw new Exception('Cannot find correct value for parameter "' . $parameter->name . '" in class "' . $className . '".');
111
            }
112
            
113
            $parameters[] = $parameterValue;
114
        }
115
        
116
        $instance = $reflection->newInstanceArgs($parameters);
117
        
118
        if ($shared) {
119
            $this->sharedInstances[$className] = $instance;
120
        }
121
        
122
        return $instance;
123
    }
124
    
125
    /**
126
     * Returns the instance for the given class
127
     * 
128
     * @param \ReflectionClass $parameterClass
129
     * @return null|object
130
     */
131
    protected function getInstance(ReflectionClass $parameterClass)
132
    {
133
        if (!class_exists($parameterClass->name, true)) {
134
            return null;
135
        }
136
        
137
        if (strpos($parameterClass->name, 'Zepi\\Turbo\\') === 0) {
138
            return $this->getFrameworkInstance($parameterClass);
139
        }
140
        
141
        if ($parameterClass->isInstantiable()) {
142
            return $this->framework->getInstance($parameterClass->name);
143
        }
144
    }
145
    
146
    /**
147
     * Returns the instance for the given class if the class path
148
     * starts with Zepi\Turbo.
149
     * 
150
     * @param \ReflectionClass $parameterClass
151
     * @return object
152
     */
153
    protected function getFrameworkInstance(ReflectionClass $parameterClass)
154
    {
155
        if ($parameterClass->name == 'Zepi\\Turbo\\Framework') {
156
            return $this->framework;
157
        }
158
        
159
        if ($parameterClass->name == 'Zepi\\Turbo\\Request\\RequestAbstract') {
160
            return $this->framework->getRequest();
161
        }
162
        
163
        if ($parameterClass->name == 'Zepi\\Turbo\\Response\\Response') {
164
            return $this->framework->getResponse();
165
        }
166
        
167
        if ($parameterClass->getNamespaceName() === 'Zepi\\Turbo\\Manager') {
168
            return $this->getFrameworkManager($parameterClass->name);
169
        }
170
    }
171
    
172
    /**
173
     * Returns the framework manager for the given class name
174
     * 
175
     * @param string $className
176
     * @return object
177
     * 
178
     * @throws \Zepi\Turbo\Exception Cannot find framework manager "{className}".
179
     */
180
    protected function getFrameworkManager($className)
181
    {
182
        switch ($className) {
183
            case 'Zepi\\Turbo\\Manager\\DataSourceManager':
184
                return $this->framework->getDataSourceManager();
185
            break;
186
            
187
            case 'Zepi\\Turbo\\Manager\\DependencyInjectionManager':
188
                return $this->framework->getDependencyInjectionManager();
189
            break;
190
                
191
            case 'Zepi\\Turbo\\Manager\\ModuleManager':
192
                return $this->framework->getModuleManager();
193
            break;
194
                
195
            case 'Zepi\\Turbo\\Manager\\RequestManager':
196
                return $this->framework->getRequestManager();
197
            break;
198
                
199
            case 'Zepi\\Turbo\\Manager\\RouteManager':
200
                return $this->framework->getRouteManager();
201
            break;
202
            
203
            case 'Zepi\\Turbo\\Manager\\RuntimeManager':
204
                return $this->framework->getRuntimeManager();
205
            break;
206
            
207
            default:
208
                throw new Exception('Cannot find framework manager "' . $className . '".');
209
            break;
210
        }
211
    }
212
}
213