Completed
Push — master ( 8b0d56...e2f78c )
by Arne
01:57
created

Container   B

Complexity

Total Complexity 36

Size/Duplication

Total Lines 278
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Importance

Changes 0
Metric Value
wmc 36
lcom 1
cbo 5
dl 0
loc 278
rs 8.8
c 0
b 0
f 0

32 Methods

Rating   Name   Duplication   Size   Complexity  
B __construct() 0 27 1
A injectConfiguration() 0 11 2
A injectStoreman() 0 11 2
A selectVault() 0 6 1
A get() 0 4 1
A has() 0 4 1
A getStoreman() 0 4 1
A getConfiguration() 0 4 1
A getVaults() 0 4 1
A getSelectedVault() 0 4 1
A getConflictHandler() 0 4 1
A addConflictHandler() 0 4 1
A getConflictHandlerNames() 0 4 1
A getIndexMerger() 0 4 1
A addIndexMerger() 0 4 1
A getIndexMergerNames() 0 4 1
A getLockAdapter() 0 4 1
A addLockAdapter() 0 4 1
A getLockAdapterNames() 0 4 1
A getOperationListBuilder() 0 4 1
A addOperationListBuilder() 0 4 1
A getOperationListBuilderNames() 0 4 1
A getStorageAdapter() 0 4 1
A addStorageAdapter() 0 4 1
A getStorageAdapterNames() 0 4 1
A getConflictHandlerServiceName() 0 4 1
A getIndexMergerServiceName() 0 4 1
A getLockAdapterServiceName() 0 4 1
A getOperationListBuilderServiceName() 0 4 1
A getStorageAdapterServiceName() 0 4 1
A registerVaultServiceFactory() 0 16 3
A getServiceNamesWithPrefix() 0 21 1
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
22
/**
23
 * Dependency injection container for modularized parts.
24
 * It is basically a facade for a PSR container implementation with some additional accessors for type safety.
25
 */
26
final class Container implements ContainerInterface
27
{
28
    protected const PREFIX_CONFLICT_HANDLER = 'conflictHandler.';
29
    protected const PREFIX_INDEX_MERGER = 'indexMerger.';
30
    protected const PREFIX_LOCK_ADAPTER = 'lockAdapter.';
31
    protected const PREFIX_OPERATION_LIST_BUILDER = 'operationListBuilder.';
32
    protected const PREFIX_STORAGE_ADAPTER = 'storageAdapter.';
33
34
35
    /**
36
     * @var InspectableContainer
37
     */
38
    protected $delegate;
39
40
    /**
41
     * Sets up the container with all bundled services.
42
     *
43
     * Note: Be very careful with shared services as the container is used shared by all vaults of a storeman instance.
44
     */
45
    public function __construct()
46
    {
47
        $this->delegate = new InspectableContainer();
48
49
        $this->delegate->add('vaults', new VaultContainer(), true);
50
        $this->delegate->add('vaultConfiguration', function(Vault $vault) { return $vault->getVaultConfiguration(); })->withArgument('vault');
51
52
        $this->registerVaultServiceFactory('conflictHandler');
53
        $this->addConflictHandler('panicking', PanickingConflictHandler::class, true);
54
        $this->addConflictHandler('preferLocal', PreferLocalConflictHandler::class, true);
55
        $this->addConflictHandler('preferRemote', PreferRemoteConflictHandler::class, true);
56
57
        $this->registerVaultServiceFactory('indexMerger');
58
        $this->addIndexMerger('standard', StandardIndexMerger::class, true);
59
60
        $this->registerVaultServiceFactory('lockAdapter');
61
        $this->addLockAdapter('dummy', DummyLockAdapter::class);
62
        $this->addLockAdapter('storage', StorageBasedLockAdapter::class)->withArgument('storageAdapter');
63
64
        $this->registerVaultServiceFactory('operationListBuilder');
65
        $this->addOperationListBuilder('standard', StandardOperationListBuilder::class, true);
66
67
        $this->registerVaultServiceFactory('storageAdapter', 'adapter');
68
        $this->addStorageAdapter('local', LocalStorageAdapter::class)->withArgument('vaultConfiguration');
69
70
        $this->delegate->add(ExistingServiceValidator::class)->withArgument($this);
71
    }
72
73
    public function injectConfiguration(Configuration $configuration): Container
74
    {
75
        if ($this->has('configuration'))
76
        {
77
            throw new \RuntimeException();
78
        }
79
80
        $this->delegate->add('configuration', $configuration, true);
81
82
        return $this;
83
    }
84
85
    public function injectStoreman(Storeman $storeman): Container
86
    {
87
        if ($this->has('storeman'))
88
        {
89
            throw new \RuntimeException();
90
        }
91
92
        $this->delegate->add('storeman', $storeman, true);
93
94
        return $this;
95
    }
96
97
    /**
98
     * Selects the given vault (or no vault) as the current one.
99
     *
100
     * @param Vault $vault
101
     * @return Container
102
     */
103
    public function selectVault(Vault $vault = null): Container
104
    {
105
        $this->delegate->add('vault', $vault, true);
106
107
        return $this;
108
    }
109
110
    /**
111
     * {@inheritdoc}
112
     */
113
    public function get($id)
114
    {
115
        return $this->delegate->get($id);
116
    }
117
118
    /**
119
     * {@inheritdoc}
120
     */
121
    public function has($id)
122
    {
123
        return $this->delegate->has($id);
124
    }
125
126
127
    public function getStoreman(): Storeman
128
    {
129
        return $this->get('storeman');
130
    }
131
132
    public function getConfiguration(): Configuration
133
    {
134
        return $this->get('configuration');
135
    }
136
137
    public function getVaults(): VaultContainer
138
    {
139
        return $this->get('vaults');
140
    }
141
142
    public function getSelectedVault(): ?Vault
143
    {
144
        return $this->get('vault');
145
    }
146
147
148
    public function getConflictHandler(string $name): ConflictHandlerInterface
149
    {
150
        return $this->delegate->get($this->getConflictHandlerServiceName($name));
151
    }
152
153
    public function addConflictHandler(string $name, $concrete, bool $shared = false): DefinitionInterface
154
    {
155
        return $this->delegate->add($this->getConflictHandlerServiceName($name), $concrete, $shared);
156
    }
157
158
    public function getConflictHandlerNames(): array
159
    {
160
        return $this->getServiceNamesWithPrefix(static::PREFIX_CONFLICT_HANDLER);
161
    }
162
163
164
    public function getIndexMerger(string $name): IndexMergerInterface
165
    {
166
        return $this->delegate->get($this->getIndexMergerServiceName($name));
167
    }
168
169
    public function addIndexMerger(string $name, $concrete, bool $shared = false): DefinitionInterface
170
    {
171
        return $this->delegate->add($this->getIndexMergerServiceName($name), $concrete, $shared);
172
    }
173
174
    public function getIndexMergerNames(): array
175
    {
176
        return $this->getServiceNamesWithPrefix(static::PREFIX_INDEX_MERGER);
177
    }
178
179
180
    public function getLockAdapter(string $name): LockAdapterInterface
181
    {
182
        return $this->delegate->get($this->getLockAdapterServiceName($name));
183
    }
184
185
    public function addLockAdapter(string $name, $concrete, bool $shared = false): DefinitionInterface
186
    {
187
        return $this->delegate->add($this->getLockAdapterServiceName($name), $concrete, $shared);
188
    }
189
190
    public function getLockAdapterNames(): array
191
    {
192
        return $this->getServiceNamesWithPrefix(static::PREFIX_LOCK_ADAPTER);
193
    }
194
195
    
196
    public function getOperationListBuilder(string $name): OperationListBuilderInterface
197
    {
198
        return $this->delegate->get($this->getOperationListBuilderServiceName($name));
199
    }
200
201
    public function addOperationListBuilder(string $name, $concrete, bool $shared = false): DefinitionInterface
202
    {
203
        return $this->delegate->add($this->getOperationListBuilderServiceName($name), $concrete, $shared);
204
    }
205
206
    public function getOperationListBuilderNames(): array
207
    {
208
        return $this->getServiceNamesWithPrefix(static::PREFIX_OPERATION_LIST_BUILDER);
209
    }
210
211
212
    public function getStorageAdapter(string $name): StorageAdapterInterface
213
    {
214
        return $this->delegate->get($this->getStorageAdapterServiceName($name));
215
    }
216
217
    public function addStorageAdapter(string $name, $concrete, bool $shared = false): DefinitionInterface
218
    {
219
        return $this->delegate->add($this->getStorageAdapterServiceName($name), $concrete, $shared);
220
    }
221
222
    public function getStorageAdapterNames(): array
223
    {
224
        return $this->getServiceNamesWithPrefix(static::PREFIX_STORAGE_ADAPTER);
225
    }
226
227
228
    protected function getConflictHandlerServiceName(string $name): string
229
    {
230
        return static::PREFIX_CONFLICT_HANDLER . $name;
231
    }
232
233
    protected function getIndexMergerServiceName(string $name): string
234
    {
235
        return static::PREFIX_INDEX_MERGER . $name;
236
    }
237
238
    protected function getLockAdapterServiceName(string $name): string
239
    {
240
        return static::PREFIX_LOCK_ADAPTER . $name;
241
    }
242
243
    protected function getOperationListBuilderServiceName(string $name): string
244
    {
245
        return static::PREFIX_OPERATION_LIST_BUILDER . $name;
246
    }
247
248
    protected function getStorageAdapterServiceName(string $name): string
249
    {
250
        return static::PREFIX_STORAGE_ADAPTER . $name;
251
    }
252
253
    /**
254
     * Registers a factory for a type of vault-specific module.
255
     *
256
     * @param string $type
257
     * @param string $vaultConfigurationKey
258
     */
259
    protected function registerVaultServiceFactory(string $type, string $vaultConfigurationKey = null): void
260
    {
261
        $this->delegate->add($type, function(Vault $vault) use ($type, $vaultConfigurationKey) {
262
263
            $array = $vault->getVaultConfiguration()->getArrayCopy();
264
            $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...
265
266
            if (!array_key_exists($vaultConfigurationKey, $array))
267
            {
268
                throw new \LogicException("Unknown vault config key: {$vaultConfigurationKey}");
269
            }
270
271
            return $this->delegate->get("{$type}.{$array[$vaultConfigurationKey]}");
272
273
        })->withArgument('vault');
274
    }
275
276
    /**
277
     * Builds and returns list of added service names starting with a given prefix.
278
     *
279
     * @param string $prefix
280
     * @return string[]
281
     */
282
    protected function getServiceNamesWithPrefix(string $prefix): array
283
    {
284
        return array_map(
285
286
            // remove prefix
287
            function(string $alias) use ($prefix) {
288
                return substr($alias, strlen($prefix));
289
            },
290
291
            array_filter(
292
293
                // search in all registered services
294
                $this->delegate->getProvidedServiceNames(),
295
296
                // only service names with given prefix
297
                function(string $alias) use ($prefix) {
298
                    return substr($alias, 0, strlen($prefix)) === $prefix;
299
                }
300
            )
301
        );
302
    }
303
}
304