-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
/
Container.php
179 lines (163 loc) · 6.06 KB
/
Container.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
<?php
/**
* Slim Framework (https://slimframework.com)
*
* @link https://github.com/slimphp/Slim
* @copyright Copyright (c) 2011-2017 Josh Lockhart
* @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
*/
namespace Slim;
use Interop\Container\ContainerInterface;
use Interop\Container\Exception\ContainerException;
use Pimple\Container as PimpleContainer;
use Slim\Exception\ContainerValueNotFoundException;
use Slim\Exception\ContainerException as SlimContainerException;
/**
* Slim's default DI container is Pimple.
*
* Slim\App expects a container that implements Psr\Container\ContainerInterface
* with these service keys configured and ready for use:
*
* - settings: an array or instance of \ArrayAccess
* - environment: an instance of \Slim\Interfaces\Http\EnvironmentInterface
* - request: an instance of \Psr\Http\Message\ServerRequestInterface
* - response: an instance of \Psr\Http\Message\ResponseInterface
* - router: an instance of \Slim\Interfaces\RouterInterface
* - foundHandler: an instance of \Slim\Interfaces\InvocationStrategyInterface
* - errorHandler: a callable with the signature: function($request, $response, $exception)
* - notFoundHandler: a callable with the signature: function($request, $response)
* - notAllowedHandler: a callable with the signature: function($request, $response, $allowedHttpMethods)
* - callableResolver: an instance of \Slim\Interfaces\CallableResolverInterface
*
* @property-read array $settings
* @property-read \Slim\Interfaces\Http\EnvironmentInterface $environment
* @property-read \Psr\Http\Message\ServerRequestInterface $request
* @property-read \Psr\Http\Message\ResponseInterface $response
* @property-read \Slim\Interfaces\RouterInterface $router
* @property-read \Slim\Interfaces\InvocationStrategyInterface $foundHandler
* @property-read callable $errorHandler
* @property-read callable $notFoundHandler
* @property-read callable $notAllowedHandler
* @property-read \Slim\Interfaces\CallableResolverInterface $callableResolver
*/
class Container extends PimpleContainer implements ContainerInterface
{
/**
* Default settings
*
* @var array
*/
private $defaultSettings = [
'httpVersion' => '1.1',
'responseChunkSize' => 4096,
'outputBuffering' => 'append',
'determineRouteBeforeAppMiddleware' => false,
'displayErrorDetails' => false,
'addContentLengthHeader' => true,
'routerCacheFile' => false,
];
/**
* Create new container
*
* @param array $values The parameters or objects.
*/
public function __construct(array $values = [])
{
parent::__construct($values);
$userSettings = isset($values['settings']) ? $values['settings'] : [];
$this->registerDefaultServices($userSettings);
}
/**
* This function registers the default services that Slim needs to work.
*
* All services are shared - that is, they are registered such that the
* same instance is returned on subsequent calls.
*
* @param array $userSettings Associative array of application settings
*
* @return void
*/
private function registerDefaultServices($userSettings)
{
$defaultSettings = $this->defaultSettings;
/**
* This service MUST return an array or an
* instance of \ArrayAccess.
*
* @return array|\ArrayAccess
*/
$this['settings'] = function () use ($userSettings, $defaultSettings) {
return new Collection(array_merge($defaultSettings, $userSettings));
};
$defaultProvider = new DefaultServicesProvider();
$defaultProvider->register($this);
}
/********************************************************************************
* Methods to satisfy Psr\Container\ContainerInterface
*******************************************************************************/
/**
* Finds an entry of the container by its identifier and returns it.
*
* @param string $id Identifier of the entry to look for.
*
* @throws ContainerValueNotFoundException No entry was found for this identifier.
* @throws ContainerException Error while retrieving the entry.
*
* @return mixed Entry.
*/
public function get($id)
{
if (!$this->offsetExists($id)) {
throw new ContainerValueNotFoundException(sprintf('Identifier "%s" is not defined.', $id));
}
try {
return $this->offsetGet($id);
} catch (\InvalidArgumentException $exception) {
if ($this->exceptionThrownByContainer($exception)) {
throw new SlimContainerException(
sprintf('Container error while retrieving "%s"', $id),
null,
$exception
);
} else {
throw $exception;
}
}
}
/**
* Tests whether an exception needs to be recast for compliance with Container-Interop. This will be if the
* exception was thrown by Pimple.
*
* @param \InvalidArgumentException $exception
*
* @return bool
*/
private function exceptionThrownByContainer(\InvalidArgumentException $exception)
{
$trace = $exception->getTrace()[0];
return $trace['class'] === PimpleContainer::class && $trace['function'] === 'offsetGet';
}
/**
* Returns true if the container can return an entry for the given identifier.
* Returns false otherwise.
*
* @param string $id Identifier of the entry to look for.
*
* @return boolean
*/
public function has($id)
{
return $this->offsetExists($id);
}
/********************************************************************************
* Magic methods for convenience
*******************************************************************************/
public function __get($name)
{
return $this->get($name);
}
public function __isset($name)
{
return $this->has($name);
}
}