-
-
Notifications
You must be signed in to change notification settings - Fork 55
/
Copy pathStorageAdapterFactory.php
121 lines (103 loc) · 4.49 KB
/
StorageAdapterFactory.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
<?php
declare(strict_types=1);
namespace Laminas\Cache\Service;
use InvalidArgumentException;
use Laminas\Cache\Exception;
use Laminas\Cache\Storage\PluginAwareInterface;
use Laminas\Cache\Storage\StorageInterface;
use Laminas\ServiceManager\PluginManagerInterface;
use Webmozart\Assert\Assert;
use function assert;
use function get_class;
use function sprintf;
/**
* @psalm-import-type PluginArrayConfigurationWithPriorityType from StorageAdapterFactoryInterface
*/
final class StorageAdapterFactory implements StorageAdapterFactoryInterface
{
public const DEFAULT_PLUGIN_PRIORITY = 1;
/** @var PluginManagerInterface */
private $adapters;
/** @var StoragePluginFactoryInterface */
private $pluginFactory;
public function __construct(PluginManagerInterface $adapters, StoragePluginFactoryInterface $pluginFactory)
{
$this->adapters = $adapters;
$this->pluginFactory = $pluginFactory;
}
public function createFromArrayConfiguration(array $configuration): StorageInterface
{
$adapterName = $configuration['name'];
$adapterOptions = $configuration['options'] ?? [];
$plugins = $configuration['plugins'] ?? [];
return $this->create($adapterName, $adapterOptions, $plugins);
}
public function create(string $storage, array $options = [], array $plugins = []): StorageInterface
{
$adapter = $this->adapters->build($storage, $options);
assert($adapter instanceof StorageInterface);
if ($plugins === []) {
return $adapter;
}
if (! $adapter instanceof PluginAwareInterface) {
throw new Exception\RuntimeException(sprintf(
"The adapter '%s' doesn't implement '%s' and therefore can't handle plugins",
get_class($adapter),
PluginAwareInterface::class
));
}
foreach ($plugins as $pluginConfiguration) {
$plugin = $this->pluginFactory->createFromArrayConfiguration($pluginConfiguration);
$pluginPriority = $pluginConfiguration['priority'] ?? self::DEFAULT_PLUGIN_PRIORITY;
if (! $adapter->hasPlugin($plugin)) {
$adapter->addPlugin($plugin, $pluginPriority);
}
}
return $adapter;
}
public function assertValidConfigurationStructure(array $configuration): void
{
try {
Assert::isNonEmptyMap($configuration, 'Configuration must be a non-empty array.');
Assert::keyExists($configuration, 'name', 'Configuration must contain a "name" key.');
Assert::stringNotEmpty($configuration['name'], 'Storage "name" has to be a non-empty string.');
Assert::nullOrIsMap(
$configuration['options'] ?? null,
'Storage "options" must be an array with string keys.'
);
if (isset($configuration['plugins'])) {
Assert::isList($configuration['plugins'], 'Storage "plugins" must be a list of plugin configurations.');
$this->assertValidPluginConfigurationStructure($configuration['name'], $configuration['plugins']);
}
} catch (InvalidArgumentException $exception) {
throw new Exception\InvalidArgumentException($exception->getMessage(), 0, $exception);
}
}
/**
* @psalm-param non-empty-string $adapter
* @psalm-param list<mixed> $plugins
* @psalm-assert list<PluginArrayConfigurationWithPriorityType> $plugins
*/
private function assertValidPluginConfigurationStructure(string $adapter, array $plugins): void
{
Assert::allIsArray($plugins, 'All plugin configurations are expected to be an array.');
foreach ($plugins as $pluginConfiguration) {
try {
$this->pluginFactory->assertValidConfigurationStructure($pluginConfiguration);
if (isset($pluginConfiguration['priority'])) {
Assert::integer($pluginConfiguration['priority'], 'Plugin priority has to be integer.');
}
} catch (Exception\InvalidArgumentException | InvalidArgumentException $exception) {
throw new Exception\InvalidArgumentException(
sprintf(
'Plugin configuration for adapter "%s" is invalid: %s',
$adapter,
$exception->getMessage()
),
0,
$exception
);
}
}
}
}