Passed
Push — master ( 50f52a...30592e )
by Mauro
02:43
created

DIC::getMetadata()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 2
c 1
b 0
f 0
dl 0
loc 4
rs 10
cc 2
nc 2
nop 1
1
<?php
2
3
namespace SimpleDIC;
4
5
use SimpleDIC\Parser\Parser;
6
7
class DIC
8
{
9
    /**
10
     * @var string
11
     */
12
    private static $filename;
13
14
    /**
15
     * @param string $filename
16
     *
17
     * @throws Exceptions\ParserException
18
     */
19
    public static function initFromFile($filename)
20
    {
21
        self::$filename = $filename;
22
23
        // create cache file if does not exists
24
        if (false === file_exists($sha1file = self::getCacheFilePath())) {
25
            $cachedMap = [];
26
27
            foreach (Parser::parse(self::$filename) as $key => $content) {
28
                $start = microtime(true);
29
                $memoryUsage = memory_get_usage();
30
31
                $cachedMap[$key] = [
32
                    'value'     => self::setInCache($cachedMap, $content),
33
                    '@metadata' => [
34
                        'type'         => gettype(self::setInCache($cachedMap, $content)),
35
                        'create_time'  => self::calculateCreatingTime($start),
36
                        'memory_usage' => (memory_get_usage() - $memoryUsage),
37
                    ],
38
                ];
39
            }
40
41
            if (false === is_dir(self::getCacheDir())) {
42
                mkdir(self::getCacheDir(), 0755, true);
43
            }
44
45
            file_put_contents($sha1file, '<?php return unserialize(\''. serialize($cachedMap) .'\');' . PHP_EOL);
46
        }
47
    }
48
49
    /**
50
     * @param float $start
51
     *
52
     * @return float
53
     */
54
    private static function calculateCreatingTime($start)
55
    {
56
        $stringval = microtime(true) - $start;
57
        $numericval = sscanf((string)$stringval, "%f")[0];
58
59
        $seconds = number_format($numericval, 8);
60
61
        return (float)$seconds * 1000000;
62
    }
63
64
    /**
65
     * @return string
66
     */
67
    private static function getCacheDir()
68
    {
69
        return __DIR__.'/../_cache/';
70
    }
71
72
    /**
73
     * @return string
74
     */
75
    private static function getCacheFilePath()
76
    {
77
        return self::getCacheDir() . sha1_file(self::$filename) .'.php';
78
    }
79
80
    /**
81
     * @return mixed
82
     */
83
    private static function getCache()
84
    {
85
        return include(self::getCacheFilePath());
86
    }
87
88
    /**
89
     * @return int
90
     */
91
    public static function count()
92
    {
93
        return count(self::getCache());
94
    }
95
96
    /**
97
     * @param string $id
98
     *
99
     * @return mixed
100
     */
101
    public static function get($id)
102
    {
103
        if (self::has($id)) {
104
            return self::getCache()[$id]['value'];
105
        }
106
    }
107
108
    /**
109
     * @param string $id
110
     *
111
     * @return mixed
112
     */
113
    public static function getMetadata($id)
114
    {
115
        if (self::has($id)) {
116
            return self::getCache()[$id]['@metadata'];
117
        }
118
    }
119
120
    /**
121
     * @param string $id
122
     *
123
     * @return bool
124
     */
125
    public static function has($id)
126
    {
127
        if (false === file_exists($sha1file = self::getCacheFilePath())) {
128
            return false;
129
        }
130
131
        return isset(self::getCache()[$id]);
132
    }
133
134
    /**
135
     * @return array
136
     */
137
    public static function keys()
138
    {
139
        return array_keys(self::getCache());
140
    }
141
142
    /**
143
     * Set an entry in the container.
144
     *
145
     * @param array $cachedMap
146
     * @param mixed $content
147
     *
148
     * @return mixed|bool|null
149
     */
150
    private static function setInCache($cachedMap, $content)
151
    {
152
        // if is not a class set the entry value in DIC
153
        if (false === isset($content['class'])) {
154
            return self::getFromEnvOrDICParams($content);
155
        }
156
157
        // otherwise it's a class, so extract variables
158
        $class           = $content['class'];
159
        $classArguments  = isset($content['arguments']) ? $content['arguments'] : null;
160
        $method          = isset($content['method']) ? $content['method'] : null;
161
        $methodArguments = isset($content['method_arguments']) ? $content['method_arguments'] : null;
162
163
        $methodArgsToInject = self::getArgumentsToInject($cachedMap, $methodArguments);
164
        $classArgsToInject = self::getArgumentsToInject($cachedMap, $classArguments);
165
166
        try {
167
            return self::instantiateTheClass($class, $classArgsToInject, $method, $methodArgsToInject);
168
        } catch (\Error $error) {
169
            return false;
170
        } catch (\Exception $exception) {
171
            return false;
172
        }
173
    }
174
175
    /**
176
     * @param string $class
177
     * @param array $classArguments
178
     * @param null $method
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $method is correct as it would always require null to be passed?
Loading history...
179
     * @param array $methodArguments
180
     *
181
     * @return mixed|bool
182
     *
183
     * @throws \ReflectionException
184
     */
185
    private static function instantiateTheClass($class, array $classArguments = [], $method = null, array $methodArguments = [])
186
    {
187
        if (false === class_exists($class)) {
188
            return false;
189
        }
190
191
        $reflected = new \ReflectionClass($class);
192
193
        // 1. the class has no method to call
194
        if (null == $method) {
0 ignored issues
show
introduced by
The condition null == $method is always true.
Loading history...
195
            return new $class(...$classArguments);
196
        }
197
198
        if (false === $reflected->hasMethod($method)) {
199
            return false;
200
        }
201
202
        // 2. the method to call is static
203
        if ($reflected->getMethod($method)->isStatic()) {
204
            return $class::$method(...$methodArguments);
205
        }
206
207
        // 3. the class has a private constructor
208
        if ($reflected->hasMethod('__construct') and $reflected->getConstructor()->isPrivate()) {
209
            return call_user_func_array([$class, $method], $methodArguments);
210
        }
211
212
        // 4. the class has a public constructor
213
        return (new $class(...$classArguments))->$method(...$methodArguments);
214
    }
215
216
    /**
217
     * Get the arguments to inject into the class to instantiate within DIC.
218
     *
219
     * @param array $cachedMap
220
     * @param null  $providedArguments
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $providedArguments is correct as it would always require null to be passed?
Loading history...
221
     *
222
     * @return array
223
     */
224
    private static function getArgumentsToInject(array $cachedMap = [], $providedArguments = null)
225
    {
226
        $returnArguments = [];
227
228
        if (null != $providedArguments) {
0 ignored issues
show
introduced by
The condition null != $providedArguments is always false.
Loading history...
229
            foreach ($providedArguments as $argument) {
230
                $returnArguments[] = self::getArgumentToInject($cachedMap, $argument);
231
            }
232
        }
233
234
        return $returnArguments;
235
    }
236
237
    /**
238
     * @param array $cachedMap
239
     * @param string $argument
240
     *
241
     * @return mixed|string|null
242
     */
243
    private static function getArgumentToInject(array $cachedMap = [], $argument)
244
    {
245
        $id = ltrim($argument, '@');
246
247
        return (isset($cachedMap[$id])) ? $cachedMap[$id]['value'] : self::getFromEnvOrDICParams($argument);
248
    }
249
250
    /**
251
     * @param string $parameter
252
     *
253
     * @return mixed|string|null
254
     */
255
    private static function getFromEnvOrDICParams($parameter)
256
    {
257
        if (is_string($parameter)) {
0 ignored issues
show
introduced by
The condition is_string($parameter) is always true.
Loading history...
258
            if (null !== self::getEnvKey($parameter)) {
259
                return (getenv(self::getEnvKey($parameter))) ? getenv(self::getEnvKey($parameter)) : $parameter;
260
            }
261
262
            return (DICParams::has(self::getParamKey($parameter))) ? DICParams::get(self::getParamKey($parameter)) : $parameter;
263
        }
264
265
        return $parameter;
266
    }
267
268
    /**
269
     * Extract from a string like %env(FOO)%
270
     *
271
     * @param string $string
272
     *
273
     * @return mixed|null
274
     */
275
    private static function getEnvKey($string)
276
    {
277
        preg_match('~%env\((.*?)\)%~', $string, $matches);
278
279
        return (count($matches) > 0) ? $matches[1] : null;
280
    }
281
282
    /**
283
     * @param string $string
284
     *
285
     * @return string
286
     */
287
    private static function getParamKey($string)
288
    {
289
        return trim($string, '%');
290
    }
291
}
292