Container::setContainer()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 1
c 1
b 0
f 0
dl 0
loc 3
rs 10
cc 1
nc 1
nop 1
1
<?php
2
3
/**
4
 * Container.php
5
 *
6
 * Jaxon DI container. Provide container service for Jaxon classes.
7
 *
8
 * @package jaxon-core
0 ignored issues
show
Coding Style introduced by
Package name "jaxon-core" is not valid; consider "Jaxoncore" instead
Loading history...
9
 * @author Thierry Feuzeu <[email protected]>
10
 * @copyright 2016 Thierry Feuzeu <[email protected]>
11
 * @license https://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License
12
 * @link https://github.com/jaxon-php/jaxon-core
13
 */
0 ignored issues
show
Coding Style introduced by
PHP version not specified
Loading history...
Coding Style introduced by
Missing @category tag in file comment
Loading history...
14
15
namespace Jaxon\Di;
16
17
use Jaxon\App\Ajax;
18
use Jaxon\App\I18n\Translator;
19
use Jaxon\App\Session\SessionInterface;
20
use Jaxon\Exception\SetupException;
21
use Pimple\Container as PimpleContainer;
22
use Psr\Container\ContainerInterface;
23
use Psr\Log\LoggerInterface;
24
use Psr\Log\NullLogger;
25
26
use Closure;
27
use Exception;
28
use ReflectionClass;
29
use ReflectionException;
30
use ReflectionNamedType;
31
use ReflectionParameter;
32
use Throwable;
33
34
use function array_map;
35
use function realpath;
36
37
class Container
0 ignored issues
show
Coding Style introduced by
Missing doc comment for class Container
Loading history...
38
{
39
    use Traits\AppTrait;
40
    use Traits\PsrTrait;
41
    use Traits\RequestTrait;
42
    use Traits\ResponseTrait;
43
    use Traits\PluginTrait;
44
    use Traits\CallableTrait;
45
    use Traits\RegisterTrait;
46
    use Traits\ViewTrait;
47
    use Traits\UtilTrait;
48
49
    /**
50
     * The library Dependency Injection Container
51
     *
52
     * @var PimpleContainer
53
     */
54
    private $xLibContainer;
55
56
    /**
57
     * The application or framework Dependency Injection Container
58
     *
59
     * @var ContainerInterface
60
     */
61
    private $xAppContainer = null;
62
63
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $jaxon should have a doc-comment as per coding-style.
Loading history...
64
     * The class constructor
65
     */
66
    public function __construct(Ajax $jaxon)
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines before function; 1 found
Loading history...
67
    {
68
        $this->xLibContainer = new PimpleContainer();
69
70
        // Save the Ajax and Container instances
71
        $this->val(Ajax::class, $jaxon);
72
        $this->val(Container::class, $this);
0 ignored issues
show
Coding Style introduced by
As per coding style, self should be used for accessing local static members.

This check looks for accesses to local static members using the fully qualified name instead of self::.

<?php

class Certificate {
    const TRIPLEDES_CBC = 'ASDFGHJKL';

    private $key;

    public function __construct()
    {
        $this->key = Certificate::TRIPLEDES_CBC;
    }
}

While this is perfectly valid, the fully qualified name of Certificate::TRIPLEDES_CBC could just as well be replaced by self::TRIPLEDES_CBC. Referencing local members with self:: assured the access will still work when the class is renamed, makes it perfectly clear that the member is in fact local and will usually be shorter.

Loading history...
73
74
        // Register the null logger by default
75
        $this->setLogger(new NullLogger());
76
77
        // Template directory
78
        $sTemplateDir = realpath(__DIR__ . '/../../templates');
79
        $this->val('jaxon.core.dir.template', $sTemplateDir);
80
81
        // Translation directory
82
        $sTranslationDir = realpath(__DIR__ . '/../../translations');
83
        $this->val('jaxon.core.dir.translation', $sTranslationDir);
84
85
        $this->registerAll();
86
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
87
88
    /**
89
     * Register the values into the container
90
     *
91
     * @return void
92
     */
93
    private function registerAll()
94
    {
95
        $this->registerApp();
96
        $this->registerPsr();
97
        $this->registerRequests();
98
        $this->registerResponses();
99
        $this->registerPlugins();
100
        $this->registerCallables();
101
        $this->registerViews();
102
        $this->registerUtils();
103
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
104
105
    /**
106
     * Set the logger
107
     *
108
     * @param LoggerInterface $xLogger
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
109
     *
110
     * @return void
111
     */
112
    public function setLogger(LoggerInterface $xLogger)
113
    {
114
        $this->val(LoggerInterface::class, $xLogger);
115
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
116
117
    /**
118
     * Get the logger
119
     *
120
     * @return LoggerInterface
121
     */
122
    public function getLogger(): LoggerInterface
123
    {
124
        return $this->get(LoggerInterface::class);
125
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
126
127
    /**
128
     * Set the container provided by the integrated framework
129
     *
130
     * @param ContainerInterface $xContainer    The container implementation
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
131
     *
132
     * @return void
133
     */
134
    public function setContainer(ContainerInterface $xContainer)
135
    {
136
        $this->xAppContainer = $xContainer;
137
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
138
139
    /**
140
     * Check if a class is defined in the container
141
     *
142
     * @param string $sClass    The full class name
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
143
     *
144
     * @return bool
145
     */
146
    public function h(string $sClass): bool
147
    {
148
        return $this->xLibContainer->offsetExists($sClass);
149
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
150
151
    /**
152
     * Check if a class is defined in the container
153
     *
154
     * @param string $sClass    The full class name
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
155
     *
156
     * @return bool
157
     */
158
    public function has(string $sClass): bool
159
    {
160
        if($this->xAppContainer != null && $this->xAppContainer->has($sClass))
161
        {
162
            return true;
163
        }
164
        return $this->xLibContainer->offsetExists($sClass);
165
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
166
167
    /**
168
     * Get a class instance
169
     *
170
     * @param string $sClass    The full class name
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
171
     *
172
     * @return mixed
173
     */
174
    public function g(string $sClass)
175
    {
176
        return $this->xLibContainer->offsetGet($sClass);
177
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
178
179
    /**
180
     * Get a class instance
181
     *
182
     * @param string $sClass The full class name
183
     *
184
     * @return mixed
185
     * @throws SetupException
186
     */
187
    public function get(string $sClass)
188
    {
189
        try
190
        {
191
            if($this->xAppContainer != null && $this->xAppContainer->has($sClass))
192
            {
193
                return $this->xAppContainer->get($sClass);
194
            }
195
            return $this->xLibContainer->offsetGet($sClass);
196
        }
197
        catch(Exception|Throwable $e)
0 ignored issues
show
Coding Style introduced by
Expected 1 space before "|"; 0 found
Loading history...
Coding Style introduced by
Expected 1 space after "|"; 0 found
Loading history...
198
        {
199
            $xLogger = $this->g(LoggerInterface::class);
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 5 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
200
            $xTranslator = $this->g(Translator::class);
201
            $sMessage = $e->getMessage() . ': ' . $xTranslator->trans('errors.class.container', ['name' => $sClass]);
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 4 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
202
            $xLogger->error($e->getMessage(), ['message' => $sMessage]);
203
            throw new SetupException($sMessage);
204
        }
205
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
206
207
    /**
208
     * Save a closure in the container
209
     *
210
     * @param string $sClass    The full class name
0 ignored issues
show
Coding Style introduced by
Expected 3 spaces after parameter name; 4 found
Loading history...
Coding Style introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
211
     * @param Closure $xClosure    The closure
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
212
     *
213
     * @return void
214
     */
215
    public function set(string $sClass, Closure $xClosure)
216
    {
217
       $this->xLibContainer->offsetSet($sClass, function() use($xClosure) {
218
            return $xClosure($this);
219
        });
220
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
221
222
    /**
223
     * Save a value in the container
224
     *
225
     * @param string $sKey    The key
0 ignored issues
show
Coding Style introduced by
Expected 3 spaces after parameter name; 4 found
Loading history...
226
     * @param mixed $xValue    The value
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
227
     *
228
     * @return void
229
     */
230
    public function val(string $sKey, $xValue)
231
    {
232
       $this->xLibContainer->offsetSet($sKey, $xValue);
233
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
234
235
    /**
236
     * Set an alias in the container
237
     *
238
     * @param string $sAlias    The alias name
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
239
     * @param string $sClass    The class name
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
240
     *
241
     * @return void
242
     */
243
    public function alias(string $sAlias, string $sClass)
244
    {
245
        $this->set($sAlias, function($di) use ($sClass) {
246
            return $di->get($sClass);
247
        });
248
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
249
250
    /**
251
     * @param ReflectionClass $xClass
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 5 spaces after parameter type; 1 found
Loading history...
252
     * @param ReflectionParameter $xParameter
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
253
     *
254
     * @return mixed
255
     * @throws SetupException
256
     */
257
    protected function getParameter(ReflectionClass $xClass, ReflectionParameter $xParameter)
0 ignored issues
show
Unused Code introduced by
The parameter $xClass is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

257
    protected function getParameter(/** @scrutinizer ignore-unused */ ReflectionClass $xClass, ReflectionParameter $xParameter)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
258
    {
259
        $xType = $xParameter->getType();
260
        // Check the parameter class first.
261
        if($xType instanceof ReflectionNamedType)
262
        {
263
            // Check the class + the name
264
            if($this->has($xType->getName() . ' $' . $xParameter->getName()))
265
            {
266
                return $this->get($xType->getName() . ' $' . $xParameter->getName());
267
            }
268
            // Check the class only
269
            if($this->get($xType->getName()))
270
            {
271
                return $this->get($xType->getName());
272
            }
273
        }
274
        // Check the name only
275
        return $this->get('$' . $xParameter->getName());
276
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
277
278
    /**
279
     * Create an instance of a class, getting the constructor parameters from the DI container
280
     *
281
     * @param string|ReflectionClass $xClass The class name or the reflection class
282
     *
283
     * @return object|null
284
     * @throws ReflectionException
285
     * @throws SetupException
286
     */
287
    public function make($xClass)
288
    {
289
        if(is_string($xClass))
290
        {
291
            $xClass = new ReflectionClass($xClass); // Create the reflection class instance
292
        }
293
        if(!($xClass instanceof ReflectionClass))
0 ignored issues
show
introduced by
$xClass is always a sub-type of ReflectionClass.
Loading history...
294
        {
295
            return null;
296
        }
297
        // Use the Reflection class to get the parameters of the constructor
298
        if(($constructor = $xClass->getConstructor()) === null)
0 ignored issues
show
Coding Style introduced by
Variable assignment found within a condition. Did you mean to do a comparison ?
Loading history...
299
        {
300
            return $xClass->newInstance();
301
        }
302
        $aParameterInstances = array_map(function($xParameter) use($xClass) {
303
            return $this->getParameter($xClass, $xParameter);
304
        }, $constructor->getParameters());
305
306
        return $xClass->newInstanceArgs($aParameterInstances);
307
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
308
309
    /**
310
     * Create an instance of a class by automatically fetching the dependencies in the constructor.
311
     *
312
     * @param string $sClass    The class name
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
313
     *
314
     * @return void
315
     */
316
    public function auto(string $sClass)
317
    {
318
        $this->set($sClass, function() use ($sClass) {
319
            return $this->make($sClass);
320
        });
321
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
322
323
    /**
324
     * Get the session manager
325
     *
326
     * @return SessionInterface|null
327
     */
328
    public function getSessionManager(): ?SessionInterface
329
    {
330
        return $this->h(SessionInterface::class) ? $this->g(SessionInterface::class) : null;
331
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
332
333
    /**
334
     * Set the session manager
335
     *
336
     * @param Closure $xClosure    A closure to create the session manager instance
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
337
     *
338
     * @return void
339
     */
340
    public function setSessionManager(Closure $xClosure)
341
    {
342
        $this->set(SessionInterface::class, $xClosure);
343
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 0 found
Loading history...
344
}
345