Passed
Pull Request — master (#1)
by Radovan
02:33
created

EnvironmentAdapter::process()   B

Complexity

Conditions 7
Paths 6

Size

Total Lines 31
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 20
nc 6
nop 1
dl 0
loc 31
rs 8.6666
c 0
b 0
f 0
1
<?php
2
declare(strict_types=1);
3
4
namespace Mallgroup\DI\Config\Adapters;
5
6
use Mallgroup\Environment;
7
use Nette\DI\Config\Adapter;
8
use Nette\DI\Definitions\Statement;
9
use Nette\DI\InvalidConfigurationException;
10
use Nette\Neon\Entity;
11
use Nette\Neon\Neon;
12
use Nette\Utils\FileSystem;
13
use function array_walk_recursive;
14
use function gettype;
15
use function strtoupper;
16
use function substr;
17
18
class EnvironmentAdapter implements Adapter
19
{
20
	/**
21
	 * Reads configuration from PHP file.
22
	 * @return array<string, array<string, array<string, mixed>>>
23
	 */
24
	public function load(string $file): array
25
	{
26
		/** @var array<string, mixed> $data */
27
		$data = (array)Neon::decode(FileSystem::read($file));
28
		return $this->process($data);
29
	}
30
31
	/**
32
	 * @param array<string,mixed> $data
33
	 * @return array<string, array<string, array<string, mixed>>>
34
	 */
35
	protected function process(array $data): array
36
	{
37
		$envs = [];
38
39
		foreach ($data as $name => $entity) {
40
			if (!$entity instanceof Entity) {
41
				throw new InvalidConfigurationException(
42
					"Invalid argument type ({$name}). Expected Entity, got " . gettype($entity)
43
				);
44
			}
45
46
			$name = strtoupper($name);
47
			$var = strtolower($name);
48
			$type = $this->getEntityType($entity);
49
			$arguments = ['name' => $name] + $this->getAttributes($entity->attributes);
50
51
			if ($entity->attributes['hidden'] ?? $entity->attributes[1] ?? false) {
52
				if ($type === 'array') {
53
					unset($arguments['default']);
54
				} else {
55
					unset($arguments['separator']);
56
				}
57
58
				$envs[$var] = new Statement("Mallgroup\Environment::$type", $arguments);
59
			} elseif ($type === 'array') {
60
				$envs[$var] = Environment::array($name, $arguments['separator'] ?: '|', $arguments['cast']);
61
			} else {
62
				$envs[$var] = (new Environment($name, $arguments['default'] ?? ''))->get($type);
63
			}
64
		}
65
		return ['parameters' => ['env' => $envs]];
66
	}
67
68
	protected function getEntityType(Entity $entity): string
69
	{
70
		$type = substr((string)$entity->value, 2);
71
		return match ($type) {
72
			Environment::INTEGER, Environment::INT, Environment::BOOLEAN, Environment::BOOL, Environment::FLOAT, 'array' => $type,
73
			default => Environment::STRING
74
		};
75
	}
76
77
	/**
78
	 * @param array<int|string, mixed> $arguments
79
	 * @return array<"cast"|"default"|"separator", string>
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<"cast"|"default"|"separator", string> at position 2 could not be parsed: Unknown type name '"cast"' at position 2 in array<"cast"|"default"|"separator", string>.
Loading history...
80
	 */
81
	protected function getAttributes(array $arguments): array
82
	{
83
		return array_filter([
84
			'separator' => (string)($arguments['separator'] ?? $arguments[0] ?? '|'),
85
			'cast' => (string)($arguments['cast'] ?? $arguments[2] ?? Environment::STRING),
86
			'default' => (string)($arguments['default'] ?? $arguments[0] ?? ''),
87
		], static fn($item) => $item !== '');
88
	}
89
90
	/**
91
	 * Generates configuration in PHP format.
92
	 * @param mixed[] $data
93
	 */
94
	public function dump(array $data): string
95
	{
96
		$data = (array)($data['parameters']['env'] ?? []);
97
		array_walk_recursive(
98
			$data,
99
			static function (mixed &$val): void {
100
				if ($val instanceof Statement && $entity = $val->getEntity()) {
101
					$arguments = [
102
						'hidden' => true,
103
					];
104
					/** @var array<"cast"|"default"|"separator", string> $args */
105
					$args = $val->arguments;
106
107
					if (is_array($entity) && $entity[0] === Environment::class) {
108
						$type = (string)($entity[1] ?? 'string');
109
110
						if ($type === 'array') {
111
							$arguments['separator'] = $args['separator'];
112
							$arguments['cast'] = $args['cast'];
113
						} else {
114
							$arguments['default'] = $args['default'];
115
						}
116
						$entity = '::' . $type;
117
					}
118
119
					$val = new Entity($entity, $arguments);
120
				}
121
			},
122
		);
123
		return "# generated by Nette\n\n" . Neon::encode($data, Neon::BLOCK);
124
	}
125
}
126