ConfigurationScript::getRecursiveDiff()   C
last analyzed

Complexity

Conditions 14
Paths 14

Size

Total Lines 31

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 210

Importance

Changes 0
Metric Value
dl 0
loc 31
ccs 0
cts 15
cp 0
rs 6.2666
c 0
b 0
f 0
cc 14
nc 14
nop 2
crap 210

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * ConfigurationScript.php
4
 *
5
 * @copyright      More in license.md
6
 * @license        https://www.ipublikuj.eu
7
 * @author         Adam Kadlec <[email protected]>
8
 * @package        iPublikuj:Packages!
9
 * @subpackage     Scripts
10
 * @since          2.0.0
11
 *
12
 * @date           25.06.16
13
 */
14
15
declare(strict_types = 1);
16
17
namespace IPub\Packages\Scripts;
18
19
use Nette\Neon;
20
use Nette\Utils;
21
22
use IPub\Packages\Entities;
23
24
/**
25
 * Nette neon installer
26
 *
27
 * @package      iPublikuj:Packages!
28
 * @subpackage   Scripts
29
 *
30
 * @author       Adam Kadlec <[email protected]>
31
 */
32 1
final class ConfigurationScript implements IScript
33
{
34
	/**
35
	 * @var string[]
36
	 */
37
	private $actions = [];
38
39
	/**
40
	 * @var string
41
	 */
42
	private $configDir;
43
44
	/**
45
	 * @var string
46
	 */
47
	private $configFile;
48
49
	/**
50
	 * @param string $configDir
51
	 * @param string $configFile
52
	 */
53
	public function __construct(string $configDir, string $configFile)
54
	{
55 1
		$this->configDir = $configDir;
56 1
		$this->configFile = $configFile;
57 1
	}
58
59
	/**
60
	 * {@inheritdoc}
61
	 */
62
	public function install(Entities\IPackage $package) : void
63
	{
64
		// Do nothing here
65
	}
66
67
	/**
68
	 * {@inheritdoc}
69
	 */
70
	public function uninstall(Entities\IPackage $package) : void
71
	{
72
		// Do nothing here
73
	}
74
75
	/**
76
	 * {@inheritdoc}
77
	 */
78
	public function enable(Entities\IPackage $package) : void
79
	{
80
		try {
81
			$configuration = $package->getConfiguration();
82
83
			// Update main config.neon
84
			if (count($configuration) > 0) {
85
				$orig = $data = $this->loadConfig();
86
87
				$data = array_merge_recursive($data, (array) $configuration);
88
89
				$this->saveConfig($data);
90
91
				$this->actions[] = function () use ($orig) {
92
					$this->saveConfig($orig);
93
				};
94
			}
95
96
		} catch (\Exception $ex) {
97
			$actions = array_reverse($this->actions);
98
99
			try {
100
				foreach ($actions as $action) {
101
					$action($this);
102
				}
103
104
			} catch (\Exception $ex) {
105
				echo $ex->getMessage();
106
			}
107
108
			throw $ex;
109
		}
110
	}
111
112
	/**
113
	 * {@inheritdoc}
114
	 */
115
	public function disable(Entities\IPackage $package) : void
116
	{
117
		$configuration = $package->getConfiguration();
118
119
		// Update main config.neon
120
		if (count($configuration) > 0) {
121
			$orig = $data = $this->loadConfig();
122
123
			$data = $this->getRecursiveDiff($data, (array) $configuration);
124
125
			// Remove extension parameters
126
			$configuration = $package->getConfiguration();
127
128
			if (isset($configuration['extensions'])) {
129
				foreach ($configuration['extensions'] as $key => $values) {
130
					if (isset($data[$key])) {
131
						unset($data[$key]);
132
					}
133
				}
134
			}
135
136
			$this->saveConfig($data);
137
138
			$this->actions[] = function () use ($orig) {
139
				$this->saveConfig($orig);
140
			};
141
		}
142
	}
143
144
	/**
145
	 * @param mixed[] $arr1
146
	 * @param mixed[] $arr2
147
	 *
148
	 * @return mixed[]
149
	 */
150
	private function getRecursiveDiff(array $arr1, array $arr2) : array
151
	{
152
		$isList = Utils\Validators::isList($arr1);
153
		$arr2IsList = Utils\Validators::isList($arr2);
154
155
		foreach ($arr1 as $key => $item) {
156
			if (!is_array($arr1[$key])) {
157
158
				// If key is numeric, remove the same value
159
				if (is_numeric($key) && ($pos = array_search($arr1[$key], $arr2)) !== FALSE) {
160
					unset($arr1[$key]);
161
162
				} elseif ((!$isList && isset($arr2[$key])) || ($isList && $arr2IsList && array_search($item, $arr2) !== FALSE)) {
163
					unset($arr1[$key]);
164
				}
165
166
			} elseif (isset($arr2[$key])) {
167
				$arr1[$key] = $item = $this->getRecursiveDiff($arr1[$key], $arr2[$key]);
168
169
				if (is_array($item) && count($item) === 0) {
170
					unset($arr1[$key]);
171
				}
172
			}
173
		}
174
175
		if ($isList) {
176
			$arr1 = array_merge($arr1);
177
		}
178
179
		return $arr1;
180
	}
181
182
	/**
183
	 * @return string
184
	 */
185
	private function getConfigPath() : string
186
	{
187
		return $this->configDir . DIRECTORY_SEPARATOR . $this->configFile;
188
	}
189
190
	/**
191
	 * @return mixed[]
192
	 */
193
	private function loadConfig() : array
194
	{
195
		return (array) Neon\Neon::decode(file_get_contents($this->getConfigPath()));
196
	}
197
198
	/**
199
	 * @param mixed[] $data
200
	 */
201
	private function saveConfig(array $data) : void
202
	{
203
		file_put_contents($this->getConfigPath(), Neon\Neon::encode($data, Neon\Neon::BLOCK));
204
	}
205
}
206