Passed
Pull Request — master (#3)
by Miloš
13:15
created

FlysystemExtension   A

Complexity

Total Complexity 19

Size/Duplication

Total Lines 164
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 11

Test Coverage

Coverage 94.37%

Importance

Changes 0
Metric Value
wmc 19
lcom 1
cbo 11
dl 0
loc 164
ccs 67
cts 71
cp 0.9437
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        http://www.ipublikuj.eu
7
 * @author         Adam Kadlec http://www.ipublikuj.eu
8
 * @package        iPublikuj:Flysystem!
9
 * @subpackage     DI
10
 * @since          1.0.0
11
 *
12
 * @date           05.04.16
13
 */
14
15
namespace IPub\Flysystem\DI;
16
17
use Nette;
18
use Nette\DI;
19
use Nette\Utils;
20
use Nette\PhpGenerator as Code;
21
22
use Tracy;
23
24
use League\Flysystem;
25
26
use IPub;
27
use IPub\Flysystem\Exceptions;
28
use IPub\Flysystem\Factories;
29
use IPub\Flysystem\Loaders;
30
31
/**
32
 * Flysystem extension container
33
 *
34
 * @package        iPublikuj:Flysystem!
35
 * @subpackage     DI
36
 *
37
 * @author         Adam Kadlec <[email protected]>
38
 */
39
class FlysystemExtension extends DI\CompilerExtension
40 1
{
41
	/**
42
	 * @var array
43
	 */
44
	private $defaults = [
45
		'adapters'    => [],
46
		'cache'       => [],
47
		'filesystems' => [],
48
	];
49
50
	public function loadConfiguration()
51
	{
52
		// Get container builder
53 1
		$builder = $this->getContainerBuilder();
54
		// Get extension configuration
55 1
		$configuration = $this->getConfig($this->defaults);
56
57
		// Load all configured adapters
58 1
		$this->loadServices($configuration['adapters'], 'adapters');
59
60
		// Load all configured cache systems
61 1
		$this->loadServices($configuration['cache'], 'cache');
62
63 1
		$mountManager = $builder->addDefinition($this->prefix('mountmanager'))
0 ignored issues
show
Deprecated Code introduced by
The method Nette\DI\ServiceDefinition::setClass() has been deprecated.

This method has been deprecated.

Loading history...
64 1
			->setClass(Flysystem\MountManager::class);
65
66 1
		foreach ($configuration['filesystems'] as $name => $filesystem) {
67
			// Check if filesystem is with cache
68 1
			if (array_key_exists('cache', $filesystem)) {
69
				// Create adapter name
70 1
				$adapterName = 'cached_' . $filesystem['adapter'] .'_'. $filesystem['cache'] .'_'. uniqid();
71
72
				// Create cached adapter
73 1
				$this->registerService(
74 1
					'adapters',
75 1
					$adapterName,
76 1
					Flysystem\Cached\CachedAdapter::class,
77 1
					'IPub\Flysystem\Factories\Adapters\CachedFactory::create',
78
					[
79 1
						'adapterServiceName' => $this->prefix('adapters.' . $filesystem['adapter']),
80 1
						'cacheServiceName'   => $this->prefix('cache.' . $filesystem['cache']),
81
					]
82 1
				);
83
84 1
			} else {
85 1
				$adapterName = $filesystem['adapter'];
86
			}
87
88 1
			$builder->addDefinition($this->prefix('filesystem.' . $name))
0 ignored issues
show
Deprecated Code introduced by
The method Nette\DI\ServiceDefinition::setClass() has been deprecated.

This method has been deprecated.

Loading history...
89 1
				->setClass(Flysystem\Filesystem::class)
90 1
				->setArguments(['adapter' => '@' . $this->prefix('adapters.' . $adapterName)])
91 1
				->addTag('ipub.flysystem.filesystem');
92
93 1
			$mountManager->addSetup('?->mountFilesystem(?, ?)', [$mountManager, $name, '@' . $this->prefix('filesystem.' . $name)]);
94 1
		}
95 1
	}
96
97
	/**
98
	 * @param array $services
99
	 * @param string $type
100
	 */
101
	private function loadServices(array $services, $type)
102
	{
103
		// Get neon file adapter
104 1
		$neonAdapter = new Loaders\NeonFileLoader;
105
106
		// Load adapters factories list
107 1
		$definitions = $neonAdapter->load(__DIR__ . DIRECTORY_SEPARATOR . $type . '.neon');
108
109 1
		foreach ($services as $serviceName => $configuration) {
110 1
			if (isset($configuration['type']) && array_key_exists($configuration['type'], $definitions)) {
111 1
				$service = $definitions[$configuration['type']];
112 1
				$serviceConfiguration = $this->validateParameters($service['parameters'], $configuration, $serviceName);
113
114 1
				$this->registerService($type, $serviceName, $service['class'], $service['factory'], [
115 1
					'parameters' => $serviceConfiguration,
116 1
				]);
117
118 1
			} else {
119
				throw new Exceptions\InvalidAdapterException(sprintf('The service "%s" is not defined in Flysystem configuration.', $serviceName));
120
			}
121 1
		}
122 1
	}
123
124
	/**
125
	 * @param string $type
126
	 * @param string $name
127
	 * @param string $class
128
	 * @param string $factory
129
	 * @param array $arguments
130
	 */
131
	private function registerService($type, $name, $class, $factory, array $arguments = [])
132
	{
133
		// Check if service class exists
134 1
		if (!class_exists($class)) {
135
			throw new Exceptions\InvalidArgumentException(sprintf('Class "%s" for service "%s" of "%s" does not exists.', $class, $name, $type));
136
		}
137
138
		// Get container builder
139 1
		$builder = $this->getContainerBuilder();
140
141 1
		$builder->addDefinition($this->prefix($type . '.' . $name))
0 ignored issues
show
Deprecated Code introduced by
The method Nette\DI\ServiceDefinition::setClass() has been deprecated.

This method has been deprecated.

Loading history...
142 1
			->setClass($class)
143 1
			->setFactory($factory)
144 1
			->setArguments($arguments)
145 1
			->addTag('ipub.flysystem.' . $type);
146 1
	}
147
148
	/**
149
	 * @param array $parameters
150
	 * @param array $configuration
151
	 * @param string $serviceName
152
	 *
153
	 * @return Utils\ArrayHash
154
	 *
155
	 * @throws Exceptions\InvalidParameterException
156
	 * @throws Exceptions\InvalidAdapterException
157
	 * @throws Utils\AssertionException
158
	 */
159
	private function validateParameters($parameters, $configuration, $serviceName)
160
	{
161 1
		$collection = [];
162
163 1
		if ($parameters === NULL) {
164 1
			return Utils\ArrayHash::from([]);
165
		}
166
167 1
		foreach ($parameters as $name => $definition) {
168 1
			if (!array_key_exists($name, $configuration) && $definition['required']) {
169
				throw new Exceptions\InvalidParameterException(sprintf('The parameter "%s" for "%s" is required.', $name, $serviceName));
170
			}
171
172 1
			if (array_key_exists('default', $definition)) {
173 1
				$collection[$name] = $definition['default'];
174 1
			}
175
176 1
			if (array_key_exists($name, $configuration)) {
177 1
				Utils\Validators::assert($configuration[$name], $definition['type'], $name);
178
179 1
				if (isset($definition['values']) && !in_array($configuration[$name], $definition['values'])) {
180
					throw new Exceptions\InvalidParameterException(sprintf('The parameter "%s" for "%s" is not in allowed range [%s].', $name, $serviceName, implode(', ', $definition['values'])));
181
				}
182
183 1
				$collection[$name] = $configuration[$name];
184 1
			}
185 1
		}
186
187 1
		$collection['extensionPrefix'] = $this->name;
188
189 1
		return Utils\ArrayHash::from($collection);
190
	}
191
192
	/**
193
	 * @param Nette\Configurator $config
194
	 * @param string $extensionName
195
	 */
196
	public static function register(Nette\Configurator $config, $extensionName = 'flysystem')
197
	{
198 1
		$config->onCompile[] = function (Nette\Configurator $config, Nette\DI\Compiler $compiler) use ($extensionName) {
199 1
			$compiler->addExtension($extensionName, new FlysystemExtension);
200 1
		};
201 1
	}
202
}
203