FlysystemExtension   A
last analyzed

Complexity

Total Complexity 19

Size/Duplication

Total Lines 177
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Test Coverage

Coverage 95.08%

Importance

Changes 0
Metric Value
wmc 19
lcom 1
cbo 4
dl 0
loc 177
ccs 58
cts 61
cp 0.9508
rs 10
c 0
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
B loadConfiguration() 0 46 3
B loadServices() 0 22 4
A registerService() 0 16 2
D validateParameters() 0 32 9
A register() 0 6 1
1
<?php
2
/**
3
 * FlysystemExtension.php
4
 *
5
 * @copyright      More in license.md
6
 * @license        https://www.ipublikuj.eu
7
 * @author         Adam Kadlec <[email protected]>
8
 * @package        iPublikuj:Flysystem!
9
 * @subpackage     DI
10
 * @since          1.0.0
11
 *
12
 * @date           05.04.16
13
 */
14
15
declare(strict_types = 1);
16
17
namespace IPub\Flysystem\DI;
18
19
use Nette;
20
use Nette\DI;
21
use Nette\Utils;
22
23
use League\Flysystem;
24
25
use IPub\Flysystem\Exceptions;
26
use IPub\Flysystem\Factories;
27
use IPub\Flysystem\Loaders;
28
29
/**
30
 * Flysystem extension container
31
 *
32
 * @package        iPublikuj:Flysystem!
33
 * @subpackage     DI
34
 *
35
 * @author         Adam Kadlec <[email protected]>
36
 */
37 1
class FlysystemExtension extends DI\CompilerExtension
38
{
39
	/**
40
	 * @var array
41
	 */
42
	private $defaults = [
43
		'adapters'    => [],
44
		'cache'       => [],
45
		'filesystems' => [],
46
	];
47
48
	/**
49
	 * @void
50
	 *
51
	 * @throws Utils\AssertionException
52
	 */
53
	public function loadConfiguration() : void
54
	{
55
		/** @var DI\ContainerBuilder $builder */
56 1
		$builder = $this->getContainerBuilder();
57
		// Get extension configuration
58 1
		$configuration = $this->getConfig($this->defaults);
59
60
		// Load all configured adapters
61 1
		$this->loadServices($configuration['adapters'], 'adapters');
62
63
		// Load all configured cache systems
64 1
		$this->loadServices($configuration['cache'], 'cache');
65
66 1
		$mountManager = $builder->addDefinition($this->prefix('mountmanager'))
67 1
			->setType(Flysystem\MountManager::class);
68
69 1
		foreach ($configuration['filesystems'] as $name => $filesystem) {
70
			// Check if filesystem is with cache
71 1
			if (array_key_exists('cache', $filesystem)) {
72
				// Create adapter name
73 1
				$adapterName = 'cached_' . $filesystem['adapter'] . '_' . $filesystem['cache'] . '_' . uniqid();
74
75
				// Create cached adapter
76 1
				$this->registerService(
77 1
					'adapters',
78
					$adapterName,
79 1
					Flysystem\Cached\CachedAdapter::class,
80 1
					'IPub\Flysystem\Factories\Adapters\CachedFactory::create',
81
					[
82 1
						'adapterServiceName' => $this->prefix('adapters.' . $filesystem['adapter']),
83 1
						'cacheServiceName'   => $this->prefix('cache.' . $filesystem['cache']),
84
					]
85
				);
86
87
			} else {
88 1
				$adapterName = $filesystem['adapter'];
89
			}
90
91 1
			$builder->addDefinition($this->prefix('filesystem.' . $name))
92 1
				->setType(Flysystem\Filesystem::class)
93 1
				->setArguments(['adapter' => '@' . $this->prefix('adapters.' . $adapterName)])
94 1
				->addTag('ipub.flysystem.filesystem');
95
96 1
			$mountManager->addSetup('?->mountFilesystem(?, ?)', [$mountManager, $name, '@' . $this->prefix('filesystem.' . $name)]);
97
		}
98 1
	}
99
100
	/**
101
	 * @param array $services
102
	 * @param string $type
103
	 *
104
	 * @return void
105
	 *
106
	 * @throws Utils\AssertionException
107
	 */
108
	private function loadServices(array $services, string $type) : void
109
	{
110
		// Get neon file adapter
111 1
		$neonAdapter = new Loaders\NeonFileLoader;
112
113
		// Load adapters factories list
114 1
		$definitions = $neonAdapter->load(__DIR__ . DIRECTORY_SEPARATOR . $type . '.neon');
115
116 1
		foreach ($services as $serviceName => $configuration) {
117 1
			if (isset($configuration['type']) && array_key_exists($configuration['type'], $definitions)) {
118 1
				$service = $definitions[$configuration['type']];
119 1
				$serviceConfiguration = $this->validateParameters($service['parameters'], $configuration, $serviceName);
120
121 1
				$this->registerService($type, $serviceName, $service['class'], $service['factory'], [
122 1
					'parameters' => $serviceConfiguration,
123
				]);
124
125
			} else {
126 1
				throw new Exceptions\InvalidAdapterException(sprintf('The service "%s" is not defined in Flysystem configuration.', $serviceName));
127
			}
128
		}
129 1
	}
130
131
	/**
132
	 * @param string $type
133
	 * @param string $name
134
	 * @param string $class
135
	 * @param string $factory
136
	 * @param array $arguments
137
	 *
138
	 * @return void
139
	 */
140
	private function registerService(string $type, string $name, string $class, string $factory, array $arguments = []) : void
141
	{
142
		// Check if service class exists
143 1
		if (!class_exists($class)) {
144
			throw new Exceptions\InvalidArgumentException(sprintf('Class "%s" for service "%s" of "%s" does not exists.', $class, $name, $type));
145
		}
146
147
		/** @var DI\ContainerBuilder $builder */
148 1
		$builder = $this->getContainerBuilder();
149
150 1
		$builder->addDefinition($this->prefix($type . '.' . $name))
151 1
			->setType($class)
152 1
			->setFactory($factory)
153 1
			->setArguments($arguments)
154 1
			->addTag('ipub.flysystem.' . $type);
155 1
	}
156
157
	/**
158
	 * @param array|NULL $parameters
159
	 * @param array $configuration
160
	 * @param string $serviceName
161
	 *
162
	 * @return Utils\ArrayHash
163
	 *
164
	 * @throws Exceptions\InvalidParameterException
165
	 * @throws Exceptions\InvalidAdapterException
166
	 * @throws Utils\AssertionException
167
	 */
168
	private function validateParameters(?array $parameters, array $configuration, string $serviceName) : Utils\ArrayHash
169
	{
170 1
		$collection = [];
171
172 1
		if ($parameters === NULL) {
173 1
			return Utils\ArrayHash::from([]);
174
		}
175
176 1
		foreach ($parameters as $name => $definition) {
177 1
			if (!array_key_exists($name, $configuration) && $definition['required']) {
178
				throw new Exceptions\InvalidParameterException(sprintf('The parameter "%s" for "%s" is required.', $name, $serviceName));
179
			}
180
181 1
			if (array_key_exists('default', $definition)) {
182 1
				$collection[$name] = $definition['default'];
183
			}
184
185 1
			if (array_key_exists($name, $configuration)) {
186 1
				Utils\Validators::assert($configuration[$name], $definition['type'], $name);
187
188 1
				if (isset($definition['values']) && !in_array($configuration[$name], $definition['values'])) {
189
					throw new Exceptions\InvalidParameterException(sprintf('The parameter "%s" for "%s" is not in allowed range [%s].', $name, $serviceName, implode(', ', $definition['values'])));
190
				}
191
192 1
				$collection[$name] = $configuration[$name];
193
			}
194
		}
195
196 1
		$collection['extensionPrefix'] = $this->name;
197
198 1
		return Utils\ArrayHash::from($collection);
199
	}
200
201
	/**
202
	 * @param Nette\Configurator $config
203
	 * @param string $extensionName
204
	 *
205
	 * @return void
206
	 */
207
	public static function register(Nette\Configurator $config, string $extensionName = 'flysystem') : void
208
	{
209 1
		$config->onCompile[] = function (Nette\Configurator $config, Nette\DI\Compiler $compiler) use ($extensionName) {
210 1
			$compiler->addExtension($extensionName, new FlysystemExtension);
211 1
		};
212 1
	}
213
}
214