Completed
Push — master ( 59ed89...26050b )
by Daniel
13:12 queued 13:12
created

TemplatesService   A

Complexity

Total Complexity 38

Size/Duplication

Total Lines 290
Duplicated Lines 0 %

Test Coverage

Coverage 71.3%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 38
eloc 109
dl 0
loc 290
ccs 82
cts 115
cp 0.713
rs 9.36
c 2
b 0
f 0

13 Methods

Rating   Name   Duplication   Size   Complexity  
A getSystemTemplates() 0 4 2
A getNewCustomTemplates() 0 16 4
A registerSystemTemplate() 0 20 3
A getTemplates() 0 3 1
A registerCustomTemplate() 0 25 4
A getCustomTemplates() 0 4 2
A removeCustomTemplate() 0 9 2
A __construct() 0 4 1
A assertValidTemplate() 0 13 3
A getTemplateFolder() 0 23 4
A getTemplateData() 0 4 1
A copyTemplate() 0 25 6
A installTemplate() 0 36 5
1
<?php
2
/**
3
 * CMS Pico - Create websites using Pico CMS for Nextcloud.
4
 *
5
 * @copyright Copyright (c) 2017, Maxence Lange (<[email protected]>)
6
 * @copyright Copyright (c) 2019, Daniel Rudolf (<[email protected]>)
7
 *
8
 * @license GNU AGPL version 3 or any later version
9
 *
10
 * This program is free software: you can redistribute it and/or modify
11
 * it under the terms of the GNU Affero General Public License as
12
 * published by the Free Software Foundation, either version 3 of the
13
 * License, or (at your option) any later version.
14
 *
15
 * This program is distributed in the hope that it will be useful,
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 * GNU Affero General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU Affero General Public License
21
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
22
 */
23
24
declare(strict_types=1);
25
26
namespace OCA\CMSPico\Service;
27
28
use OCA\CMSPico\Exceptions\TemplateAlreadyExistsException;
29
use OCA\CMSPico\Exceptions\TemplateNotCompatibleException;
30
use OCA\CMSPico\Exceptions\TemplateNotFoundException;
31
use OCA\CMSPico\Files\FileInterface;
32
use OCA\CMSPico\Files\FolderInterface;
33
use OCA\CMSPico\Files\StorageFolder;
34
use OCA\CMSPico\Model\Template;
35
use OCA\CMSPico\Model\TemplateFile;
36
use OCA\CMSPico\Model\Website;
37
use OCP\Files\AlreadyExistsException;
38
use OCP\Files\NotFoundException;
39
40
class TemplatesService
41
{
42
	/** @var ConfigService */
43
	private $configService;
44
45
	/** @var FileService */
46
	private $fileService;
47
48
	/**
49
	 * TemplatesService constructor.
50
	 *
51
	 * @param ConfigService $configService
52
	 * @param FileService   $fileService
53
	 */
54 1
	public function __construct(ConfigService $configService, FileService $fileService)
55
	{
56 1
		$this->configService = $configService;
57 1
		$this->fileService = $fileService;
58 1
	}
59
60
	/**
61
	 * @param string $templateName
62
	 *
63
	 * @throws TemplateNotFoundException
64
	 * @throws TemplateNotCompatibleException
65
	 */
66 4
	public function assertValidTemplate(string $templateName): void
67
	{
68 4
		$templates = $this->getTemplates();
69
70 4
		if (!isset($templates[$templateName])) {
71
			throw new TemplateNotFoundException($templateName);
72
		}
73
74 4
		if (!$templates[$templateName]['compat']) {
75
			throw new TemplateNotCompatibleException(
76
				$templateName,
77
				$templates[$templateName]['compatReason'],
78
				$templates[$templateName]['compatReasonData']
79
			);
80
		}
81 4
	}
82
83
	/**
84
	 * @return array[]
85
	 */
86 9
	public function getTemplates(): array
87
	{
88 9
		return $this->getSystemTemplates() + $this->getCustomTemplates();
89
	}
90
91
	/**
92
	 * @return array[]
93
	 */
94 9
	public function getSystemTemplates(): array
95
	{
96 9
		$json = $this->configService->getAppValue(ConfigService::SYSTEM_TEMPLATES);
97 9
		return $json ? json_decode($json, true) : [];
98
	}
99
100
	/**
101
	 * @return array[]
102
	 */
103 9
	public function getCustomTemplates(): array
104
	{
105 9
		$json = $this->configService->getAppValue(ConfigService::CUSTOM_TEMPLATES);
106 9
		return $json ? json_decode($json, true) : [];
107
	}
108
109
	/**
110
	 * @return string[]
111
	 */
112 5
	public function getNewCustomTemplates(): array
113
	{
114 5
		$customTemplatesFolder = $this->fileService->getAppDataFolder(PicoService::DIR_TEMPLATES);
115 5
		$customTemplatesFolder->sync(FolderInterface::SYNC_SHALLOW);
116
117 5
		$currentTemplates = $this->getTemplates();
118
119 5
		$newCustomTemplates = [];
120 5
		foreach ($customTemplatesFolder as $templateFolder) {
121 4
			$templateName = $templateFolder->getName();
122 4
			if ($templateFolder->isFolder() && !isset($currentTemplates[$templateName])) {
123 2
				$newCustomTemplates[] = $templateName;
124
			}
125
		}
126
127 5
		return $newCustomTemplates;
128
	}
129
130
	/**
131
	 * @param string $templateName
132
	 *
133
	 * @return Template
134
	 * @throws TemplateNotFoundException
135
	 * @throws TemplateAlreadyExistsException
136
	 */
137
	public function registerSystemTemplate(string $templateName): Template
138
	{
139
		if (!$templateName) {
140
			throw new TemplateNotFoundException($templateName);
141
		}
142
143
		$systemTemplatesFolder = $this->fileService->getSystemFolder(PicoService::DIR_TEMPLATES);
144
		$systemTemplatesFolder->sync(FolderInterface::SYNC_SHALLOW);
145
146
		try {
147
			$templateFolder = $systemTemplatesFolder->getFolder($templateName);
148
		} catch (NotFoundException $e) {
149
			throw new TemplateNotFoundException($templateName, $e);
150
		}
151
152
		$templates = $this->getSystemTemplates();
153
		$templates[$templateName] = new Template($templateFolder, Template::TYPE_SYSTEM);
154
		$this->configService->setAppValue(ConfigService::SYSTEM_TEMPLATES, json_encode($templates));
155
156
		return $templates[$templateName];
157
	}
158
159
	/**
160
	 * @param string $templateName
161
	 *
162
	 * @return Template
163
	 * @throws TemplateNotFoundException
164
	 * @throws TemplateAlreadyExistsException
165
	 */
166 2
	public function registerCustomTemplate(string $templateName): Template
167
	{
168 2
		if (!$templateName) {
169
			throw new TemplateNotFoundException($templateName);
170
		}
171
172 2
		$systemTemplates = $this->getSystemTemplates();
173 2
		if (isset($systemTemplates[$templateName])) {
174
			throw new TemplateAlreadyExistsException($templateName);
175
		}
176
177 2
		$appDataTemplatesFolder = $this->fileService->getAppDataFolder(PicoService::DIR_TEMPLATES);
178 2
		$appDataTemplatesFolder->sync(FolderInterface::SYNC_SHALLOW);
179
180
		try {
181 2
			$templateFolder = $appDataTemplatesFolder->getFolder($templateName);
182
		} catch (NotFoundException $e) {
183
			throw new TemplateNotFoundException($templateName, $e);
184
		}
185
186 2
		$templates = $this->getCustomTemplates();
187 2
		$templates[$templateName] = new Template($templateFolder, Template::TYPE_CUSTOM);
188 2
		$this->configService->setAppValue(ConfigService::CUSTOM_TEMPLATES, json_encode($templates));
189
190 2
		return $templates[$templateName];
191
	}
192
193
	/**
194
	 * @param string $templateName
195
	 *
196
	 * @throws TemplateNotFoundException
197
	 */
198 1
	public function removeCustomTemplate(string $templateName): void
199
	{
200 1
		if (!$templateName) {
201
			throw new TemplateNotFoundException($templateName);
202
		}
203
204 1
		$customTemplates = $this->getCustomTemplates();
205 1
		unset($customTemplates[$templateName]);
206 1
		$this->configService->setAppValue(ConfigService::CUSTOM_TEMPLATES, json_encode($customTemplates));
207 1
	}
208
209
	/**
210
	 * @param string $baseTemplateName
211
	 * @param string $templateName
212
	 *
213
	 * @return Template
214
	 * @throws TemplateNotFoundException
215
	 * @throws TemplateAlreadyExistsException
216
	 */
217 1
	public function copyTemplate(string $baseTemplateName, string $templateName): Template
218
	{
219 1
		if (!$baseTemplateName) {
220
			throw new TemplateNotFoundException($baseTemplateName);
221 1
		} elseif (!$templateName) {
222
			throw new TemplateNotFoundException($templateName);
223
		}
224
225 1
		$systemTemplates = $this->getSystemTemplates();
226 1
		$customTemplates = $this->getCustomTemplates();
227
228 1
		if (isset($systemTemplates[$templateName]) || isset($customTemplates[$templateName])) {
229
			throw new TemplateAlreadyExistsException($templateName);
230
		}
231
232 1
		$baseTemplateFolder = $this->getTemplateFolder($baseTemplateName);
233 1
		$appDataTemplatesFolder = $this->fileService->getAppDataFolder(PicoService::DIR_TEMPLATES);
234
235
		try {
236 1
			$baseTemplateFolder->copy($appDataTemplatesFolder, $templateName);
237
		} catch (AlreadyExistsException $e) {
238
			throw new TemplateAlreadyExistsException($templateName, $e);
239
		}
240
241 1
		return $this->registerCustomTemplate($templateName);
242
	}
243
244
	/**
245
	 * @param Website $website
246
	 * @param string  $templateName
247
	 *
248
	 * @throws TemplateNotFoundException
249
	 */
250 4
	public function installTemplate(Website $website, string $templateName): void
251
	{
252 4
		$userFolder = new StorageFolder(\OC::$server->getUserFolder($website->getUserId()));
0 ignored issues
show
Bug introduced by
It seems like OC::server->getUserFolder($website->getUserId()) can also be of type null; however, parameter $folder of OCA\CMSPico\Files\StorageFolder::__construct() does only seem to accept OCP\Files\Folder, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

252
		$userFolder = new StorageFolder(/** @scrutinizer ignore-type */ \OC::$server->getUserFolder($website->getUserId()));
Loading history...
Deprecated Code introduced by
The function OC\Server::getUserFolder() has been deprecated: 20.0.0 ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

252
		$userFolder = new StorageFolder(/** @scrutinizer ignore-deprecated */ \OC::$server->getUserFolder($website->getUserId()));

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
253
254
		try {
255 4
			$userFolder->get($website->getPath());
256
257
			// website folder exists; since we don't want to
258
			// mess around with a user's files, bail out
259 1
			return;
260 3
		} catch (NotFoundException $e) {
261
			// proceed if the website folder doesn't exist yet
262
		}
263
264 3
		$websiteFolder = $userFolder->newFolder($website->getPath());
265
266 3
		$templateFolder = $this->getTemplateFolder($templateName);
267 3
		$templateFolder->sync();
268
269 3
		$templateData = $this->getTemplateData($website);
270 3
		foreach (new \RecursiveIteratorIterator($templateFolder) as $file) {
271
			/** @var FileInterface $file */
272 3
			$templateFile = new TemplateFile($file);
273
274
			try {
275 3
				$targetFolder = $websiteFolder->getFolder($templateFile->getParentPath());
276 3
			} catch (NotFoundException $e) {
277 3
				$targetFolder = $websiteFolder->newFolder($templateFile->getParentPath());
278
			}
279
280 3
			if ($templateFile->getName() === 'empty') {
281
				continue;
282
			}
283
284 3
			$templateFile->setTemplateData($templateData);
285 3
			$templateFile->copy($targetFolder);
286
		}
287 3
	}
288
289
	/**
290
	 * @param Website $website
291
	 *
292
	 * @return array<string,string>
293
	 */
294 3
	private function getTemplateData(Website $website): array
295
	{
296
		return [
297 3
			'site_title' => $website->getName()
298
		];
299
	}
300
301
	/**
302
	 * @param string $templateName
303
	 *
304
	 * @return FolderInterface
305
	 * @throws TemplateNotFoundException
306
	 */
307 4
	public function getTemplateFolder(string $templateName): FolderInterface
308
	{
309 4
		if (!$templateName) {
310
			throw new TemplateNotFoundException($templateName);
311
		}
312
313 4
		$systemTemplatesFolder = $this->fileService->getSystemFolder(PicoService::DIR_TEMPLATES);
314 4
		$systemTemplatesFolder->sync(FolderInterface::SYNC_SHALLOW);
315
316 4
		$customTemplatesFolder = $this->fileService->getAppDataFolder(PicoService::DIR_TEMPLATES);
317 4
		$customTemplatesFolder->sync(FolderInterface::SYNC_SHALLOW);
318
319
		try {
320 4
			$templateFolder = $systemTemplatesFolder->getFolder($templateName);
321
		} catch (NotFoundException $e) {
322
			try {
323
				$templateFolder = $customTemplatesFolder->getFolder($templateName);
324
			} catch (NotFoundException $e) {
325
				throw new TemplateNotFoundException($templateName, $e);
326
			}
327
		}
328
329 4
		return $templateFolder->fakeRoot();
330
	}
331
}
332