Passed
Pull Request — master (#77)
by Daniel
24:04
created

AppDataRepairStep   A

Complexity

Total Complexity 37

Size/Duplication

Total Lines 280
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 6
Bugs 0 Features 0
Metric Value
wmc 37
eloc 111
c 6
b 0
f 0
dl 0
loc 280
ccs 0
cts 169
cp 0
rs 9.44

14 Methods

Rating   Name   Duplication   Size   Complexity  
A logChanges() 0 15 4
A syncAppDataFolder() 0 3 1
A publishSystemThemes() 0 16 3
A __construct() 0 12 1
A getName() 0 3 1
A copyConfig() 0 22 5
A run() 0 16 1
A publishCustomThemes() 0 19 5
A publishPlugins() 0 9 1
A log() 0 3 1
A publishCustomPlugins() 0 19 5
A publishThemes() 0 9 1
A publishSystemPlugins() 0 16 3
A copyTemplates() 0 22 5
1
<?php
2
/**
3
 * CMS Pico - Create websites using Pico CMS for Nextcloud.
4
 *
5
 * @copyright Copyright (c) 2019, Daniel Rudolf (<[email protected]>)
6
 *
7
 * @license GNU AGPL version 3 or any later version
8
 *
9
 * This program is free software: you can redistribute it and/or modify
10
 * it under the terms of the GNU Affero General Public License as
11
 * published by the Free Software Foundation, either version 3 of the
12
 * License, or (at your option) any later version.
13
 *
14
 * This program is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 * GNU Affero General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU Affero General Public License
20
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
 */
22
23
declare(strict_types=1);
24
25
namespace OCA\CMSPico\Migration;
26
27
use OCA\CMSPico\AppInfo\Application;
28
use OCA\CMSPico\Service\ConfigService;
29
use OCA\CMSPico\Service\FileService;
30
use OCA\CMSPico\Service\PicoService;
31
use OCA\CMSPico\Service\PluginsService;
32
use OCA\CMSPico\Service\ThemesService;
33
use OCP\Files\NotFoundException;
34
use OCP\ILogger;
35
use OCP\Migration\IOutput;
36
use OCP\Migration\IRepairStep;
37
38
class AppDataRepairStep implements IRepairStep
39
{
40
	/** @var ILogger */
41
	private $logger;
42
43
	/** @var ConfigService */
44
	private $configService;
45
46
	/** @var ThemesService */
47
	private $themesService;
48
49
	/** @var PluginsService */
50
	private $pluginsService;
51
52
	/** @var FileService */
53
	private $fileService;
54
55
	/**
56
	 * AppDataRepairStep constructor.
57
	 *
58
	 * @param ILogger        $logger
59
	 * @param ConfigService  $configService
60
	 * @param ThemesService  $themesService
61
	 * @param PluginsService $pluginsService
62
	 * @param FileService    $fileService
63
	 */
64
	public function __construct(
65
		ILogger $logger,
66
		ConfigService $configService,
67
		ThemesService $themesService,
68
		PluginsService $pluginsService,
69
		FileService $fileService
70
	) {
71
		$this->logger = $logger;
72
		$this->configService = $configService;
73
		$this->themesService = $themesService;
74
		$this->pluginsService = $pluginsService;
75
		$this->fileService = $fileService;
76
	}
77
78
	/**
79
	 * @return string
80
	 */
81
	public function getName(): string
82
	{
83
		return 'Preparing app data of Pico CMS for Nextcloud';
84
	}
85
86
	/**
87
	 * @param IOutput $output
88
	 */
89
	public function run(IOutput $output)
90
	{
91
		$this->log('Syncing Pico CMS app data folder …');
92
		$this->syncAppDataFolder();
93
94
		$this->log('Copying Pico CMS config …');
95
		$this->copyConfig();
96
97
		$this->log('Copying Pico CMS templates …');
98
		$this->copyTemplates();
99
100
		$this->log('Publishing Pico CMS themes …');
101
		$this->publishThemes();
102
103
		$this->log('Publishing Pico CMS plugins …');
104
		$this->publishPlugins();
105
	}
106
107
	/**
108
	 * @return void
109
	 */
110
	private function syncAppDataFolder()
111
	{
112
		$this->fileService->syncAppDataFolder();
113
	}
114
115
	/**
116
	 * @return void
117
	 */
118
	private function copyConfig()
119
	{
120
		$appDataConfigFolder = $this->fileService->getAppDataFolder(PicoService::DIR_CONFIG);
121
		$systemConfigFolder = $this->fileService->getSystemFolder(PicoService::DIR_CONFIG);
122
123
		foreach ($systemConfigFolder as $configFile) {
124
			$configFileName = $configFile->getName();
125
126
			if (!$configFile->isFile()) {
127
				continue;
128
			}
129
130
			try {
131
				$appDataConfigFolder->getFile($configFileName)->delete();
132
				$this->log(sprintf('Replacing %s "%s"', 'config file', $configFileName), ILogger::WARN);
133
			} catch (NotFoundException $e) {
134
				$this->log(sprintf('Adding %s "%s"', 'config file', $configFileName));
135
			} catch (\Exception $e) {
136
				$this->log(sprintf('Unable to create %s "%s"', 'config file', $configFileName), ILogger::ERROR);
137
			}
138
139
			$configFile->copy($appDataConfigFolder);
140
		}
141
	}
142
143
	/**
144
	 * @return void
145
	 */
146
	private function copyTemplates()
147
	{
148
		$appDataTemplatesFolder = $this->fileService->getAppDataFolder(PicoService::DIR_TEMPLATES);
149
		$systemTemplatesFolder = $this->fileService->getSystemFolder(PicoService::DIR_TEMPLATES);
150
151
		foreach ($systemTemplatesFolder as $templateFolder) {
152
			$templateFileName = $templateFolder->getName();
153
154
			if (!$templateFolder->isFolder()) {
155
				continue;
156
			}
157
158
			try {
159
				$appDataTemplatesFolder->getFolder($templateFileName)->delete();
160
				$this->log(sprintf('Replacing %s "%s"', 'template', $templateFileName), ILogger::WARN);
161
			} catch (NotFoundException $e) {
162
				$this->log(sprintf('Adding %s "%s"', 'template', $templateFileName));
163
			} catch (\Exception $e) {
164
				$this->log(sprintf('Unable to create %s "%s"', 'template', $templateFileName), ILogger::ERROR);
165
			}
166
167
			$templateFolder->copy($appDataTemplatesFolder);
168
		}
169
	}
170
171
	/**
172
	 * @return void
173
	 */
174
	private function publishThemes()
175
	{
176
		$publicThemesFolder = $this->fileService->getPublicFolder(PicoService::DIR_THEMES);
177
		$publicThemesFolder->truncate();
178
179
		$this->configService->deleteAppValue(ConfigService::THEMES_ETAG);
180
181
		$this->publishSystemThemes();
182
		$this->publishCustomThemes();
183
	}
184
185
	/**
186
	 * @return void
187
	 */
188
	private function publishSystemThemes()
189
	{
190
		$systemThemesFolder = $this->fileService->getSystemFolder(PicoService::DIR_THEMES);
191
192
		$oldSystemThemes = $this->themesService->getSystemThemes();
193
		$this->configService->deleteAppValue(ConfigService::SYSTEM_THEMES);
194
195
		foreach ($systemThemesFolder as $themeFolder) {
196
			$themeName = $themeFolder->getName();
197
			if ($themeFolder->isFolder()) {
198
				$this->themesService->publishSystemTheme($themeName);
199
			}
200
		}
201
202
		$newSystemThemes = $this->themesService->getSystemThemes();
203
		$this->logChanges('system theme', array_keys($newSystemThemes), array_keys($oldSystemThemes));
204
	}
205
206
	/**
207
	 * @return void
208
	 */
209
	private function publishCustomThemes()
210
	{
211
		$appDataThemesFolder = $this->fileService->getAppDataFolder(PicoService::DIR_THEMES);
212
213
		$oldCustomThemes = $this->themesService->getCustomThemes();
214
		$this->configService->deleteAppValue(ConfigService::CUSTOM_THEMES);
215
216
		$systemThemes = $this->themesService->getSystemThemes();
217
		foreach ($appDataThemesFolder as $themeFolder) {
218
			$themeName = $themeFolder->getName();
219
			if ($themeFolder->isFolder()) {
220
				if (isset($oldCustomThemes[$themeName]) && !isset($systemThemes[$themeName])) {
221
					$this->themesService->publishCustomTheme($themeName);
222
				}
223
			}
224
		}
225
226
		$newCustomThemes = $this->themesService->getCustomThemes();
227
		$this->logChanges('custom theme', array_keys($newCustomThemes), array_keys($oldCustomThemes));
228
	}
229
230
	/**
231
	 * @return void
232
	 */
233
	private function publishPlugins()
234
	{
235
		$publicPluginsFolder = $this->fileService->getPublicFolder(PicoService::DIR_PLUGINS);
236
		$publicPluginsFolder->truncate();
237
238
		$this->configService->deleteAppValue(ConfigService::PLUGINS_ETAG);
239
240
		$this->publishSystemPlugins();
241
		$this->publishCustomPlugins();
242
	}
243
244
	/**
245
	 * @return void
246
	 */
247
	private function publishSystemPlugins()
248
	{
249
		$systemPluginsFolder = $this->fileService->getSystemFolder(PicoService::DIR_PLUGINS);
250
251
		$oldSystemPlugins = $this->pluginsService->getSystemPlugins();
252
		$this->configService->deleteAppValue(ConfigService::SYSTEM_PLUGINS);
253
254
		foreach ($systemPluginsFolder as $pluginFolder) {
255
			$pluginName = $pluginFolder->getName();
256
			if ($pluginFolder->isFolder()) {
257
				$this->pluginsService->publishSystemPlugin($pluginName);
258
			}
259
		}
260
261
		$newSystemPlugins = $this->pluginsService->getSystemPlugins();
262
		$this->logChanges('system plugin', array_keys($newSystemPlugins), array_keys($oldSystemPlugins));
263
	}
264
265
	/**
266
	 * @return void
267
	 */
268
	private function publishCustomPlugins()
269
	{
270
		$appDataPluginsFolder = $this->fileService->getAppDataFolder(PicoService::DIR_PLUGINS);
271
272
		$oldCustomPlugins = $this->pluginsService->getCustomPlugins();
273
		$this->configService->deleteAppValue(ConfigService::CUSTOM_PLUGINS);
274
275
		$systemPlugins = $this->pluginsService->getSystemPlugins();
276
		foreach ($appDataPluginsFolder as $pluginFolder) {
277
			$pluginName = $pluginFolder->getName();
278
			if ($pluginFolder->isFolder()) {
279
				if (isset($oldCustomPlugins[$pluginName]) && !isset($systemPlugins[$pluginName])) {
280
					$this->pluginsService->publishCustomPlugin($pluginName);
281
				}
282
			}
283
		}
284
285
		$newCustomPlugins = $this->pluginsService->getCustomPlugins();
286
		$this->logChanges('custom plugin', array_keys($newCustomPlugins), array_keys($oldCustomPlugins));
287
	}
288
289
	/**
290
	 * @param string $message
291
	 * @param int    $level
292
	 */
293
	private function log(string $message, int $level = ILogger::DEBUG)
294
	{
295
		$this->logger->log($level, $message, [ 'app' => Application::APP_NAME ]);
296
	}
297
298
	/**
299
	 * @param string $title
300
	 * @param array  $newItems
301
	 * @param array  $oldItems
302
	 */
303
	private function logChanges(string $title, array $newItems, array $oldItems)
304
	{
305
		$addedItems = array_diff($newItems, $oldItems);
306
		foreach ($addedItems as $item) {
307
			$this->log(sprintf('Adding %s "%s"', $title, $item));
308
		}
309
310
		$updatedItems = array_intersect($newItems, $oldItems);
311
		foreach ($updatedItems as $item) {
312
			$this->log(sprintf('Replacing %s "%s"', $title, $item), ILogger::WARN);
313
		}
314
315
		$removedItems = array_diff($oldItems, $newItems);
316
		foreach ($removedItems as $item) {
317
			$this->log(sprintf('Removing %s "%s"', $title, $item), ILogger::WARN);
318
		}
319
	}
320
}
321