Passed
Push — main ( 5ca287...d84479 )
by Thierry
05:24
created

Container::setSessionManager()   A

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
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
rs 10
c 1
b 0
f 0
1
<?php
2
3
/**
4
 * Container.php
5
 *
6
 * Jaxon DI container. Provide container service for Jaxon classes.
7
 *
8
 * @package jaxon-core
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
 */
14
15
namespace Jaxon\Di;
16
17
use Jaxon\App\I18n\Translator;
18
use Jaxon\App\Session\SessionInterface;
19
use Jaxon\Exception\SetupException;
20
use Pimple\Container as PimpleContainer;
21
use Psr\Container\ContainerInterface;
22
use Psr\Log\LoggerInterface;
23
use Psr\Log\NullLogger;
24
use Closure;
25
use Throwable;
26
27
use function is_a;
28
use function realpath;
29
30
class Container
31
{
32
    use Traits\AppTrait;
33
    use Traits\PsrTrait;
34
    use Traits\RequestTrait;
35
    use Traits\ResponseTrait;
36
    use Traits\PluginTrait;
37
    use Traits\CallableTrait;
38
    use Traits\ViewTrait;
39
    use Traits\UtilTrait;
40
    use Traits\MetadataTrait;
41
    use Traits\DiAutoTrait;
42
43
    /**
44
     * The library Dependency Injection Container
45
     *
46
     * @var PimpleContainer
47
     */
48
    private $xLibContainer;
49
50
    /**
51
     * The application or framework Dependency Injection Container
52
     *
53
     * @var ContainerInterface
54
     */
55
    private $xAppContainer = null;
56
57
    /**
58
     * The class constructor
59
     */
60
    public function __construct()
61
    {
62
        $this->xLibContainer = new PimpleContainer();
63
64
        $this->val(Container::class, $this);
65
66
        // Register the null logger by default
67
        $this->setLogger(new NullLogger());
68
69
        // Template directory
70
        $sTemplateDir = realpath(__DIR__ . '/../../templates');
71
        $this->val('jaxon.core.dir.template', $sTemplateDir);
72
73
        // Translation directory
74
        $sTranslationDir = realpath(__DIR__ . '/../../translations');
75
        $this->val('jaxon.core.dir.translation', $sTranslationDir);
76
77
        $this->registerAll();
78
        $this->setEventHandlers();
79
    }
80
81
    /**
82
     * The container for parameters
83
     *
84
     * @return Container
85
     */
86
    protected function cn(): Container
87
    {
88
        return $this;
89
    }
90
91
    /**
92
     * Register the values into the container
93
     *
94
     * @return void
95
     */
96
    private function registerAll()
97
    {
98
        $this->registerApp();
99
        $this->registerPsr();
100
        $this->registerRequests();
101
        $this->registerResponses();
102
        $this->registerPlugins();
103
        $this->registerCallables();
104
        $this->registerViews();
105
        $this->registerUtils();
106
        $this->registerMetadataReader();
107
    }
108
109
    /**
110
     * Set the logger
111
     *
112
     * @param LoggerInterface|Closure $xLogger
113
     *
114
     * @return void
115
     */
116
    public function setLogger(LoggerInterface|Closure $xLogger)
117
    {
118
        is_a($xLogger, LoggerInterface::class) ?
119
            $this->val(LoggerInterface::class, $xLogger) :
120
            $this->set(LoggerInterface::class, $xLogger);
121
    }
122
123
    /**
124
     * Get the logger
125
     *
126
     * @return LoggerInterface
127
     */
128
    public function getLogger(): LoggerInterface
129
    {
130
        return $this->get(LoggerInterface::class);
131
    }
132
133
    /**
134
     * Set the container provided by the integrated framework
135
     *
136
     * @param ContainerInterface $xContainer    The container implementation
137
     *
138
     * @return void
139
     */
140
    public function setContainer(ContainerInterface $xContainer)
141
    {
142
        $this->xAppContainer = $xContainer;
143
    }
144
145
    /**
146
     * Check if a class is defined in the container
147
     *
148
     * @param string $sClass    The full class name
149
     *
150
     * @return bool
151
     */
152
    public function h(string $sClass): bool
153
    {
154
        return $this->xLibContainer->offsetExists($sClass);
155
    }
156
157
    /**
158
     * Check if a class is defined in the container
159
     *
160
     * @param string $sClass    The full class name
161
     *
162
     * @return bool
163
     */
164
    public function has(string $sClass): bool
165
    {
166
        return $this->xAppContainer != null && $this->xAppContainer->has($sClass) ?
167
            true : $this->xLibContainer->offsetExists($sClass);
168
    }
169
170
    /**
171
     * Get a class instance
172
     *
173
     * @template T
174
     * @param class-string<T> $sClass The full class name
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string<T> at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string<T>.
Loading history...
175
     *
176
     * @return T
177
     */
178
    public function g(string $sClass): mixed
179
    {
180
        return $this->xLibContainer->offsetGet($sClass);
181
    }
182
183
    /**
184
     * Get a class instance
185
     *
186
     * @template T
187
     * @param class-string<T> $sClass The full class name
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string<T> at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string<T>.
Loading history...
188
     *
189
     * @return T
190
     * @throws SetupException
191
     */
192
    public function get(string $sClass): mixed
193
    {
194
        try
195
        {
196
            return $this->xAppContainer != null && $this->xAppContainer->has($sClass) ?
197
                $this->xAppContainer->get($sClass) : $this->xLibContainer->offsetGet($sClass);
198
        }
199
        catch(Throwable $e)
200
        {
201
            $xLogger = $this->g(LoggerInterface::class);
202
            $xTranslator = $this->g(Translator::class);
203
            $sMessage = $e->getMessage() . ': ' . $xTranslator->trans('errors.class.container', ['name' => $sClass]);
204
            $xLogger->error($e->getMessage(), ['message' => $sMessage]);
205
            throw new SetupException($sMessage);
206
        }
207
    }
208
209
    /**
210
     * Save a closure in the container
211
     *
212
     * @param string|class-string $sClass    The full class name
0 ignored issues
show
Documentation Bug introduced by
The doc comment string|class-string at position 2 could not be parsed: Unknown type name 'class-string' at position 2 in string|class-string.
Loading history...
213
     * @param Closure $xClosure    The closure
214
     * @param bool $bIsSingleton
215
     *
216
     * @return void
217
     */
218
    public function set(string $sClass, Closure $xClosure, bool $bIsSingleton = true)
0 ignored issues
show
Unused Code introduced by
The parameter $xClosure 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

218
    public function set(string $sClass, /** @scrutinizer ignore-unused */ Closure $xClosure, bool $bIsSingleton = true)

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...
219
    {
220
        // Wrap the user closure into a new closure, so it can take this container as a parameter.
221
        $xClosure = fn() => $xClosure($this);
222
        $this->xLibContainer->offsetSet($sClass, $bIsSingleton ?
223
            $xClosure : $this->xLibContainer->factory($xClosure));
224
    }
225
226
    /**
227
     * Save a value in the container
228
     *
229
     * @param string|class-string $sKey    The key
0 ignored issues
show
Documentation Bug introduced by
The doc comment string|class-string at position 2 could not be parsed: Unknown type name 'class-string' at position 2 in string|class-string.
Loading history...
230
     * @param mixed $xValue    The value
231
     *
232
     * @return void
233
     */
234
    public function val(string $sKey, $xValue)
235
    {
236
       $this->xLibContainer->offsetSet($sKey, $xValue);
237
    }
238
239
    /**
240
     * Set an alias in the container
241
     *
242
     * @param string|class-string $sAlias    The alias name
0 ignored issues
show
Documentation Bug introduced by
The doc comment string|class-string at position 2 could not be parsed: Unknown type name 'class-string' at position 2 in string|class-string.
Loading history...
243
     * @param string|class-string $sClass    The class name
244
     *
245
     * @return void
246
     */
247
    public function alias(string $sAlias, string $sClass)
248
    {
249
        $this->set($sAlias, function($di) use ($sClass) {
250
            return $di->get($sClass);
251
        });
252
    }
253
254
    /**
255
     * Get the session manager
256
     *
257
     * @return SessionInterface|null
258
     */
259
    public function getSessionManager(): ?SessionInterface
260
    {
261
        return $this->h(SessionInterface::class) ? $this->g(SessionInterface::class) : null;
262
    }
263
264
    /**
265
     * Set the session manager
266
     *
267
     * @param Closure $xClosure    A closure to create the session manager instance
268
     *
269
     * @return void
270
     */
271
    public function setSessionManager(Closure $xClosure)
272
    {
273
        $this->set(SessionInterface::class, $xClosure);
274
    }
275
}
276