Passed
Push — master ( f384a6...0a1f9b )
by Radovan
01:10 queued 13s
created

EnvironmentAdapter::getAttributes()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 5
nc 1
nop 1
dl 0
loc 7
rs 10
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
			$attributes = $this->getAttributes($entity->attributes);
50
51
			if ($entity->attributes['hidden'] ?? $entity->attributes[1] ?? false) {
52
				$envs[$var] = new Statement("Mallgroup\Environment::$type", $this->modifyStatementAttributes($name, $type, $attributes));
53
			} elseif ($type === 'array') {
54
				$envs[$var] = Environment::array($name, $attributes['separator'] ?: '|', $attributes['cast']);
55
			} else {
56
				$envs[$var] = (new Environment($name, $attributes['default'] ?? ''))->get($type);
57
			}
58
		}
59
		return ['parameters' => ['env' => $envs]];
60
	}
61
62
	/**
63
	 * @param string $name
64
	 * @param string $type
65
	 * @param array<"cast"|"default"|"separator", string> $arguments
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...
66
	 * @return array<"cast"|"default"|"separator"|"name", string>
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<"cast"|"default"|"...arator"|"name", string> at position 2 could not be parsed: Unknown type name '"cast"' at position 2 in array<"cast"|"default"|"separator"|"name", string>.
Loading history...
67
	 */
68
	protected function modifyStatementAttributes(string $name, string $type, array $arguments): array {
69
		$arguments['name'] = $name;
70
		if ($type === 'array') {
71
			unset($arguments['default']);
72
		} else {
73
			unset($arguments['separator']);
74
		}
75
		return $arguments;
76
	}
77
78
	protected function getEntityType(Entity $entity): string
79
	{
80
		$type = substr((string)$entity->value, 2);
81
		return match ($type) {
82
			Environment::INTEGER, Environment::INT, Environment::BOOLEAN, Environment::BOOL, Environment::FLOAT, 'array' => $type,
83
			default => Environment::STRING
84
		};
85
	}
86
87
	/**
88
	 * @param array<int|string, mixed> $arguments
89
	 * @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...
90
	 */
91
	protected function getAttributes(array $arguments): array
92
	{
93
		return array_filter([
94
			'separator' => (string)($arguments['separator'] ?? $arguments[0] ?? '|'),
95
			'cast' => (string)($arguments['cast'] ?? $arguments[2] ?? Environment::STRING),
96
			'default' => (string)($arguments['default'] ?? $arguments[0] ?? ''),
97
		], static fn($item) => $item !== '');
98
	}
99
100
	/**
101
	 * Generates configuration in PHP format.
102
	 * @param mixed[] $data
103
	 */
104
	public function dump(array $data): string
105
	{
106
		$data = (array)($data['parameters']['env'] ?? []);
107
		array_walk_recursive(
108
			$data,
109
			static function (mixed &$val): void {
110
				if ($val instanceof Statement && $entity = $val->getEntity()) {
111
					$arguments = [
112
						'hidden' => true,
113
					];
114
					/** @var array<"cast"|"default"|"separator", string> $args */
115
					$args = $val->arguments;
116
117
					if (is_array($entity) && $entity[0] === Environment::class) {
118
						$type = (string)($entity[1] ?? 'string');
119
120
						if ($type === 'array') {
121
							$arguments['separator'] = $args['separator'];
122
							$arguments['cast'] = $args['cast'];
123
						} else {
124
							$arguments['default'] = $args['default'];
125
						}
126
						$entity = '::' . $type;
127
					}
128
129
					$val = new Entity($entity, $arguments);
130
				}
131
			},
132
		);
133
		return "# generated by Nette\n\n" . Neon::encode($data, Neon::BLOCK);
134
	}
135
}
136