Skip to content

Commit 9b8062a

Browse files
committed
2.0: Use SF options resolver...
and improve QA tooling
1 parent a1d0e2b commit 9b8062a

File tree

5 files changed

+116
-66
lines changed

5 files changed

+116
-66
lines changed

composer.json

+13-3
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,13 @@
1010
}
1111
],
1212
"require": {
13-
"psr/container": "^1.0"
13+
"psr/container": "^1.0",
14+
"symfony/options-resolver": "^4.2"
1415
},
1516
"require-dev": {
16-
"phpunit/phpunit": "^4.8.36"
17+
"phpunit/phpunit": "^8",
18+
"phpstan/phpstan": "^0.12.52",
19+
"friendsofphp/php-cs-fixer": "^2.16"
1720
},
1821
"autoload": {
1922
"psr-4": {
@@ -28,7 +31,14 @@
2831
},
2932
"extra": {
3033
"branch-alias": {
31-
"dev-master": "1.0-dev"
34+
"dev-master": "2.0-dev"
3235
}
36+
},
37+
"scripts": {
38+
"integrate": [
39+
"vendor/bin/phpunit",
40+
"vendor/bin/php-cs-fixer fix lib",
41+
"vendor/bin/phpstan analyse lib --level=7"
42+
]
3343
}
3444
}

lib/Container.php

+64-34
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@
1111

1212
namespace PhpBench\DependencyInjection;
1313

14+
use Closure;
1415
use Psr\Container\ContainerInterface;
16+
use Symfony\Component\OptionsResolver\Exception\ExceptionInterface;
17+
use Symfony\Component\OptionsResolver\OptionsResolver;
1518

1619
/**
1720
* PHPBench Container.
@@ -20,18 +23,39 @@
2023
*/
2124
class Container implements ContainerInterface
2225
{
26+
/**
27+
* @var array<string,Callable>
28+
*/
2329
private $instantiators = [];
30+
31+
/**
32+
* @var array<string, mixed>
33+
*/
2434
private $services = [];
35+
36+
/**
37+
* @var array<string,array<string,mixed>>
38+
*/
2539
private $tags = [];
40+
41+
/**
42+
* @var array<string,mixed>
43+
*/
2644
private $config = [];
27-
private $userConfig = [];
2845

46+
/**
47+
* @var array<string>
48+
*/
2949
private $extensionClasses = [];
3050

31-
public function __construct(array $extensionClasses = [], array $userConfig = [])
51+
/**
52+
* @param array<string,mixed> $config
53+
* @param array<string> $extensionClasses
54+
*/
55+
public function __construct(array $extensionClasses = [], array $config = [])
3256
{
3357
$this->extensionClasses = $extensionClasses;
34-
$this->userConfig = $userConfig;
58+
$this->config = $config;
3559
}
3660

3761
/**
@@ -41,11 +65,13 @@ public function __construct(array $extensionClasses = [], array $userConfig = []
4165
*
4266
* This method must be called before `build()`.
4367
*/
44-
public function init()
68+
public function init(): void
4569
{
70+
$resolver = new OptionsResolver();
4671
$extensions = [];
72+
$config = [];
4773

48-
if (empty($this->extensionClasses) && empty($this->userConfig)) {
74+
if (empty($this->extensionClasses) && empty($this->config)) {
4975
return;
5076
}
5177

@@ -68,26 +94,27 @@ public function init()
6894
}
6995

7096
$extensions[] = $extension;
71-
72-
$this->config = array_merge(
73-
$this->config,
74-
$extension->getDefaultConfig()
75-
);
97+
$extension->configure($resolver);
7698
}
7799

78-
$diff = array_diff(array_keys($this->userConfig), array_keys($this->config));
100+
$diff = array_diff(array_keys($this->config), array_keys($this->config));
79101

80102
if ($diff) {
81103
throw new \InvalidArgumentException(sprintf(
82104
'Unknown configuration keys: "%s". Permitted keys: "%s"',
83-
implode('", "', $diff), implode('", "', array_keys($this->config))
105+
implode('", "', $diff),
106+
implode('", "', array_keys($this->config))
84107
));
85108
}
86109

87-
$this->config = array_merge(
88-
$this->config,
89-
$this->userConfig
90-
);
110+
try {
111+
$this->config = $resolver->resolve($this->config);
112+
} catch (ExceptionInterface $resolverException) {
113+
throw new InvalidConfigurationException(sprintf(
114+
'Invalid user configuration: %s',
115+
$resolverException->getMessage()
116+
), 0, $resolverException);
117+
}
91118

92119
foreach ($extensions as $extension) {
93120
$extension->load($this);
@@ -99,8 +126,6 @@ public function init()
99126
* Note that this method will return the same instance on subsequent calls.
100127
*
101128
* @param string $serviceId
102-
*
103-
* @return mixed
104129
*/
105130
public function get($serviceId)
106131
{
@@ -120,30 +145,30 @@ public function get($serviceId)
120145
return $this->services[$serviceId];
121146
}
122147

123-
public function has($serviceId)
148+
/**
149+
* @param string $serviceId
150+
*/
151+
public function has($serviceId): bool
124152
{
125153
return isset($this->instantiators[$serviceId]);
126154
}
127155

128156
/**
129157
* Set a service instance.
130158
*
131-
* @param string $serviceId
132159
* @param mixed $instance
133160
*/
134-
public function set($serviceId, $instance)
161+
public function set(string $serviceId, $instance): void
135162
{
136163
$this->services[$serviceId] = $instance;
137164
}
138165

139166
/**
140167
* Return services IDs for the given tag.
141168
*
142-
* @param string $tag
143-
*
144-
* @return string[][]
169+
* @return array<string, array<string, mixed>>
145170
*/
146-
public function getServiceIdsForTag($tag)
171+
public function getServiceIdsForTag(string $tag): array
147172
{
148173
$serviceIds = [];
149174
foreach ($this->tags as $serviceId => $tags) {
@@ -161,15 +186,15 @@ public function getServiceIdsForTag($tag)
161186
* The instantiator is a closure which accepts an instance of this container and
162187
* returns a new instance of the service class.
163188
*
164-
* @param string $serviceId
165-
* @param \Closure $instantiator
166-
* @param string[][] $tags
189+
* @param array<string, array<string, mixed>> $tags
167190
*/
168-
public function register($serviceId, \Closure $instantiator, array $tags = [])
191+
public function register(string $serviceId, Closure $instantiator, array $tags = []): void
169192
{
170193
if (isset($this->instantiators[$serviceId])) {
171194
throw new \InvalidArgumentException(sprintf(
172-
'Service with ID "%s" has already been registered', $serviceId));
195+
'Service with ID "%s" has already been registered',
196+
$serviceId
197+
));
173198
}
174199

175200
$this->instantiators[$serviceId] = $instantiator;
@@ -179,15 +204,17 @@ public function register($serviceId, \Closure $instantiator, array $tags = [])
179204
/**
180205
* Set the value of the parameter with the given name.
181206
*
182-
* @param string $name
183207
* @param mixed $value
184208
*/
185-
public function setParameter($name, $value)
209+
public function setParameter(string $name, $value): void
186210
{
187211
$this->config[$name] = $value;
188212
}
189213

190-
public function mergeParameter($name, array $values)
214+
/**
215+
* @param array<mixed> $values
216+
*/
217+
public function mergeParameter(string $name, array $values): void
191218
{
192219
$actual = $this->getParameter($name);
193220

@@ -225,7 +252,10 @@ public function getParameter($name)
225252
return $this->config[$name];
226253
}
227254

228-
public function getParameters()
255+
/**
256+
* @return array<mixed,mixed>
257+
*/
258+
public function getParameters(): array
229259
{
230260
return $this->config;
231261
}

lib/ExtensionInterface.php

+5-5
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,19 @@
1111

1212
namespace PhpBench\DependencyInjection;
1313

14+
use Symfony\Component\OptionsResolver\OptionsResolver;
15+
1416
interface ExtensionInterface
1517
{
1618
/**
1719
* Register services with the container.
1820
*
1921
* @param Container $container
2022
*/
21-
public function load(Container $container);
23+
public function load(Container $container): void;
2224

2325
/**
24-
* Return the default parameters for the container.
25-
*
26-
* @return array
26+
* Configure the parameters which can be accessed by the extension.
2727
*/
28-
public function getDefaultConfig();
28+
public function configure(OptionsResolver $resolver): void;
2929
}

lib/InvalidConfigurationException.php

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
namespace PhpBench\DependencyInjection;
4+
5+
use RuntimeException;
6+
7+
class InvalidConfigurationException extends RuntimeException
8+
{
9+
}

0 commit comments

Comments
 (0)