Completed
Push — master ( 60e59a...334051 )
by Adam
06:35
created

ConfigurationScript::getRecursiveDiff()   C

Complexity

Conditions 14
Paths 14

Size

Total Lines 31
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 31
rs 5.0864
cc 14
eloc 16
nc 14
nop 2

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