Completed
Push — master ( b2e536...a4e6dd )
by Arne
02:05
created

Container::addVaultLayout()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 3
1
<?php
2
3
namespace Storeman;
4
5
use League\Container\Definition\DefinitionInterface;
6
use Psr\Container\ContainerInterface;
7
use Storeman\ConflictHandler\ConflictHandlerInterface;
8
use Storeman\ConflictHandler\PanickingConflictHandler;
9
use Storeman\ConflictHandler\PreferLocalConflictHandler;
10
use Storeman\ConflictHandler\PreferRemoteConflictHandler;
11
use Storeman\IndexMerger\IndexMergerInterface;
12
use Storeman\IndexMerger\StandardIndexMerger;
13
use Storeman\LockAdapter\DummyLockAdapter;
14
use Storeman\LockAdapter\LockAdapterInterface;
15
use Storeman\LockAdapter\StorageBasedLockAdapter;
16
use Storeman\OperationListBuilder\OperationListBuilderInterface;
17
use Storeman\OperationListBuilder\StandardOperationListBuilder;
18
use Storeman\StorageAdapter\LocalStorageAdapter;
19
use Storeman\StorageAdapter\StorageAdapterInterface;
20
use Storeman\Validation\Constraints\ExistingServiceValidator;
21
use Storeman\VaultLayout\Amberjack\AmberjackVaultLayout;
22
use Storeman\VaultLayout\VaultLayoutInterface;
23
24
/**
25
 * Dependency injection container for modularized parts.
26
 * It is basically a facade for a PSR container implementation with some additional accessors for type safety.
27
 */
28
final class Container implements ContainerInterface
29
{
30
    protected const PREFIX_CONFLICT_HANDLER = 'conflictHandler.';
31
    protected const PREFIX_INDEX_MERGER = 'indexMerger.';
32
    protected const PREFIX_LOCK_ADAPTER = 'lockAdapter.';
33
    protected const PREFIX_OPERATION_LIST_BUILDER = 'operationListBuilder.';
34
    protected const PREFIX_STORAGE_ADAPTER = 'storageAdapter.';
35
    protected const PREFIX_VAULT_LAYOUT = 'vaultLayout.';
36
37
38
    /**
39
     * @var InspectableContainer
40
     */
41
    protected $delegate;
42
43
    /**
44
     * Sets up the container with all bundled services.
45
     *
46
     * Note: Be very careful with shared services as the container is used shared by all vaults of a storeman instance.
47
     */
48
    public function __construct()
49
    {
50
        $this->delegate = new InspectableContainer();
51
52
        $this->delegate->add('vaults', new VaultContainer(), true);
53
        $this->delegate->add('vaultConfiguration', function(Vault $vault) { return $vault->getVaultConfiguration(); })->withArgument('vault');
54
55
        $this->registerVaultServiceFactory('conflictHandler');
56
        $this->addConflictHandler('panicking', PanickingConflictHandler::class, true);
57
        $this->addConflictHandler('preferLocal', PreferLocalConflictHandler::class, true);
58
        $this->addConflictHandler('preferRemote', PreferRemoteConflictHandler::class, true);
59
60
        $this->registerVaultServiceFactory('indexMerger');
61
        $this->addIndexMerger('standard', StandardIndexMerger::class, true);
62
63
        $this->registerVaultServiceFactory('lockAdapter');
64
        $this->addLockAdapter('dummy', DummyLockAdapter::class);
65
        $this->addLockAdapter('storage', StorageBasedLockAdapter::class)->withArgument('storageAdapter');
66
67
        $this->registerVaultServiceFactory('operationListBuilder');
68
        $this->addOperationListBuilder('standard', StandardOperationListBuilder::class, true);
69
70
        $this->registerVaultServiceFactory('storageAdapter', 'adapter');
71
        $this->addStorageAdapter('local', LocalStorageAdapter::class)->withArgument('vaultConfiguration');
72
73
        $this->registerVaultServiceFactory('vaultLayout');
74
        $this->addVaultLayout('amberjack', AmberjackVaultLayout::class)->withArguments(['storageAdapter', 'vaultConfiguration']);
75
76
        $this->delegate->add(ExistingServiceValidator::class)->withArgument($this);
77
    }
78
79
    public function injectConfiguration(Configuration $configuration): Container
80
    {
81
        if ($this->has('configuration'))
82
        {
83
            throw new \RuntimeException();
84
        }
85
86
        $this->delegate->add('configuration', $configuration, true);
87
88
        return $this;
89
    }
90
91
    public function injectStoreman(Storeman $storeman): Container
92
    {
93
        if ($this->has('storeman'))
94
        {
95
            throw new \RuntimeException();
96
        }
97
98
        $this->delegate->add('storeman', $storeman, true);
99
100
        return $this;
101
    }
102
103
    /**
104
     * Selects the given vault (or no vault) as the current one.
105
     *
106
     * @param Vault $vault
107
     * @return Container
108
     */
109
    public function selectVault(Vault $vault = null): Container
110
    {
111
        $this->delegate->add('vault', $vault, true);
112
113
        return $this;
114
    }
115
116
    /**
117
     * {@inheritdoc}
118
     */
119
    public function get($id)
120
    {
121
        return $this->delegate->get($id);
122
    }
123
124
    /**
125
     * {@inheritdoc}
126
     */
127
    public function has($id)
128
    {
129
        return $this->delegate->has($id);
130
    }
131
132
133
    public function getStoreman(): Storeman
134
    {
135
        return $this->get('storeman');
136
    }
137
138
    public function getConfiguration(): Configuration
139
    {
140
        return $this->get('configuration');
141
    }
142
143
    public function getVaults(): VaultContainer
144
    {
145
        return $this->get('vaults');
146
    }
147
148
    public function getSelectedVault(): ?Vault
149
    {
150
        return $this->get('vault');
151
    }
152
153
154
    public function getConflictHandler(string $name): ConflictHandlerInterface
155
    {
156
        return $this->delegate->get($this->getConflictHandlerServiceName($name));
157
    }
158
159
    public function addConflictHandler(string $name, $concrete, bool $shared = false): DefinitionInterface
160
    {
161
        return $this->delegate->add($this->getConflictHandlerServiceName($name), $concrete, $shared);
162
    }
163
164
    public function getConflictHandlerNames(): array
165
    {
166
        return $this->getServiceNamesWithPrefix(static::PREFIX_CONFLICT_HANDLER);
167
    }
168
169
170
    public function getIndexMerger(string $name): IndexMergerInterface
171
    {
172
        return $this->delegate->get($this->getIndexMergerServiceName($name));
173
    }
174
175
    public function addIndexMerger(string $name, $concrete, bool $shared = false): DefinitionInterface
176
    {
177
        return $this->delegate->add($this->getIndexMergerServiceName($name), $concrete, $shared);
178
    }
179
180
    public function getIndexMergerNames(): array
181
    {
182
        return $this->getServiceNamesWithPrefix(static::PREFIX_INDEX_MERGER);
183
    }
184
185
186
    public function getLockAdapter(string $name): LockAdapterInterface
187
    {
188
        return $this->delegate->get($this->getLockAdapterServiceName($name));
189
    }
190
191
    public function addLockAdapter(string $name, $concrete, bool $shared = false): DefinitionInterface
192
    {
193
        return $this->delegate->add($this->getLockAdapterServiceName($name), $concrete, $shared);
194
    }
195
196
    public function getLockAdapterNames(): array
197
    {
198
        return $this->getServiceNamesWithPrefix(static::PREFIX_LOCK_ADAPTER);
199
    }
200
201
    
202
    public function getOperationListBuilder(string $name): OperationListBuilderInterface
203
    {
204
        return $this->delegate->get($this->getOperationListBuilderServiceName($name));
205
    }
206
207
    public function addOperationListBuilder(string $name, $concrete, bool $shared = false): DefinitionInterface
208
    {
209
        return $this->delegate->add($this->getOperationListBuilderServiceName($name), $concrete, $shared);
210
    }
211
212
    public function getOperationListBuilderNames(): array
213
    {
214
        return $this->getServiceNamesWithPrefix(static::PREFIX_OPERATION_LIST_BUILDER);
215
    }
216
217
218
    public function getStorageAdapter(string $name): StorageAdapterInterface
219
    {
220
        return $this->delegate->get($this->getStorageAdapterServiceName($name));
221
    }
222
223
    public function addStorageAdapter(string $name, $concrete, bool $shared = false): DefinitionInterface
224
    {
225
        return $this->delegate->add($this->getStorageAdapterServiceName($name), $concrete, $shared);
226
    }
227
228
    public function getStorageAdapterNames(): array
229
    {
230
        return $this->getServiceNamesWithPrefix(static::PREFIX_STORAGE_ADAPTER);
231
    }
232
233
234
    public function getVaultLayout(string $name): VaultLayoutInterface
235
    {
236
        return $this->delegate->get($this->getVaultLayoutServiceName($name));
237
    }
238
239
    public function addVaultLayout(string $name, $concrete, bool $shared = false): DefinitionInterface
240
    {
241
        return $this->delegate->add($this->getVaultLayoutServiceName($name), $concrete, $shared);
242
    }
243
244
    public function getVaultLayoutNames(): array
245
    {
246
        return $this->getServiceNamesWithPrefix(static::PREFIX_VAULT_LAYOUT);
247
    }
248
249
250
    protected function getConflictHandlerServiceName(string $name): string
251
    {
252
        return static::PREFIX_CONFLICT_HANDLER . $name;
253
    }
254
255
    protected function getIndexMergerServiceName(string $name): string
256
    {
257
        return static::PREFIX_INDEX_MERGER . $name;
258
    }
259
260
    protected function getLockAdapterServiceName(string $name): string
261
    {
262
        return static::PREFIX_LOCK_ADAPTER . $name;
263
    }
264
265
    protected function getOperationListBuilderServiceName(string $name): string
266
    {
267
        return static::PREFIX_OPERATION_LIST_BUILDER . $name;
268
    }
269
270
    protected function getStorageAdapterServiceName(string $name): string
271
    {
272
        return static::PREFIX_STORAGE_ADAPTER . $name;
273
    }
274
275
    protected function getVaultLayoutServiceName(string $name): string
276
    {
277
        return static::PREFIX_VAULT_LAYOUT . $name;
278
    }
279
280
    /**
281
     * Registers a factory for a type of vault-specific module.
282
     *
283
     * @param string $type
284
     * @param string $vaultConfigurationKey
285
     */
286
    protected function registerVaultServiceFactory(string $type, string $vaultConfigurationKey = null): void
287
    {
288
        $this->delegate->add($type, function(Vault $vault) use ($type, $vaultConfigurationKey) {
289
290
            $array = $vault->getVaultConfiguration()->getArrayCopy();
291
            $vaultConfigurationKey = $vaultConfigurationKey ?: $type;
0 ignored issues
show
Bug introduced by
Consider using a different name than the imported variable $vaultConfigurationKey, or did you forget to import by reference?

It seems like you are assigning to a variable which was imported through a use statement which was not imported by reference.

For clarity, we suggest to use a different name or import by reference depending on whether you would like to have the change visibile in outer-scope.

Change not visible in outer-scope

$x = 1;
$callable = function() use ($x) {
    $x = 2; // Not visible in outer scope. If you would like this, how
            // about using a different variable name than $x?
};

$callable();
var_dump($x); // integer(1)

Change visible in outer-scope

$x = 1;
$callable = function() use (&$x) {
    $x = 2;
};

$callable();
var_dump($x); // integer(2)
Loading history...
292
293
            if (!array_key_exists($vaultConfigurationKey, $array))
294
            {
295
                throw new \LogicException("Unknown vault config key: {$vaultConfigurationKey}");
296
            }
297
298
            return $this->delegate->get("{$type}.{$array[$vaultConfigurationKey]}");
299
300
        })->withArgument('vault');
301
    }
302
303
    /**
304
     * Builds and returns list of added service names starting with a given prefix.
305
     *
306
     * @param string $prefix
307
     * @return string[]
308
     */
309
    protected function getServiceNamesWithPrefix(string $prefix): array
310
    {
311
        return array_map(
312
313
            // remove prefix
314
            function(string $alias) use ($prefix) {
315
                return substr($alias, strlen($prefix));
316
            },
317
318
            array_filter(
319
320
                // search in all registered services
321
                $this->delegate->getProvidedServiceNames(),
322
323
                // only service names with given prefix
324
                function(string $alias) use ($prefix) {
325
                    return substr($alias, 0, strlen($prefix)) === $prefix;
326
                }
327
            )
328
        );
329
    }
330
}
331