TemplatesService::getSystemTemplates()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 2
c 0
b 0
f 0
dl 0
loc 4
ccs 3
cts 3
cp 1
rs 10
cc 2
nc 2
nop 0
crap 2
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\StorageUserFolder;
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 StorageUserFolder($website->getUserId());
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