Passed
Push — master ( 235c52...927bab )
by Daniel
30:30 queued 10s
created

TemplatesService::installTemplates()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 20
rs 9.6
c 0
b 0
f 0
cc 3
nc 3
nop 1
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)
67
	{
68 4
		$templates = $this->getTemplates();
69
70 4
		if (!isset($templates[$templateName])) {
71 1
			throw new TemplateNotFoundException();
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 4
	public function getTemplates(): array
87
	{
88 4
		return $this->getSystemTemplates() + $this->getCustomTemplates();
89
	}
90
91
	/**
92
	 * @return array[]
93
	 */
94 4
	public function getSystemTemplates(): array
95
	{
96 4
		$json = $this->configService->getAppValue(ConfigService::SYSTEM_TEMPLATES);
97 4
		return $json ? json_decode($json, true) : [];
98
	}
99
100
	/**
101
	 * @return array[]
102
	 */
103 4
	public function getCustomTemplates(): array
104
	{
105 4
		$json = $this->configService->getAppValue(ConfigService::CUSTOM_TEMPLATES);
106 4
		return $json ? json_decode($json, true) : [];
107
	}
108
109
	/**
110
	 * @return string[]
111
	 */
112 1
	public function getNewCustomTemplates(): array
113
	{
114 1
		$customTemplatesFolder = $this->fileService->getAppDataFolder(PicoService::DIR_TEMPLATES);
115 1
		$customTemplatesFolder->sync(FolderInterface::SYNC_SHALLOW);
116
117 1
		$currentTemplates = $this->getTemplates();
118
119 1
		$newCustomTemplates = [];
120 1
		foreach ($customTemplatesFolder as $templateFolder) {
121 1
			$templateName = $templateFolder->getName();
122 1
			if ($templateFolder->isFolder() && !isset($currentTemplates[$templateName])) {
123 1
				$newCustomTemplates[] = $templateName;
124
			}
125
		}
126
127 1
		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)
138
	{
139
		if (!$templateName) {
140
			throw new TemplateNotFoundException();
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();
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 1
	public function registerCustomTemplate(string $templateName)
167
	{
168 1
		if (!$templateName) {
169
			throw new TemplateNotFoundException();
170
		}
171
172 1
		$systemTemplates = $this->getSystemTemplates();
173 1
		if (isset($systemTemplates[$templateName])) {
174
			throw new TemplateAlreadyExistsException();
175
		}
176
177 1
		$appDataTemplatesFolder = $this->fileService->getAppDataFolder(PicoService::DIR_TEMPLATES);
178 1
		$appDataTemplatesFolder->sync(FolderInterface::SYNC_SHALLOW);
179
180
		try {
181 1
			$templateFolder = $appDataTemplatesFolder->getFolder($templateName);
182
		} catch (NotFoundException $e) {
183
			throw new TemplateNotFoundException();
184
		}
185
186 1
		$templates = $this->getCustomTemplates();
187 1
		$templates[$templateName] = new Template($templateFolder, Template::TYPE_CUSTOM);
188 1
		$this->configService->setAppValue(ConfigService::CUSTOM_TEMPLATES, json_encode($templates));
189
190 1
		return $templates[$templateName];
191
	}
192
193
	/**
194
	 * @param string $templateName
195
	 *
196
	 * @throws TemplateNotFoundException
197
	 */
198 1
	public function removeCustomTemplate(string $templateName)
199
	{
200 1
		if (!$templateName) {
201
			throw new TemplateNotFoundException();
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
	public function copyTemplate(string $baseTemplateName, string $templateName)
218
	{
219
		if (!$baseTemplateName || !$templateName) {
220
			throw new TemplateNotFoundException();
221
		}
222
223
		$systemTemplates = $this->getSystemTemplates();
224
		$customTemplates = $this->getCustomTemplates();
225
226
		if (isset($systemTemplates[$templateName]) || isset($customTemplates[$templateName])) {
227
			throw new TemplateAlreadyExistsException();
228
		}
229
230
		$baseTemplateFolder = $this->getTemplateFolder($baseTemplateName);
231
		$appDataTemplatesFolder = $this->fileService->getAppDataFolder(PicoService::DIR_TEMPLATES);
232
233
		try {
234
			$baseTemplateFolder->copy($appDataTemplatesFolder, $templateName);
235
		} catch (AlreadyExistsException $e) {
236
			throw new TemplateAlreadyExistsException();
237
		}
238
239
		return $this->registerCustomTemplate($templateName);
240
	}
241
242
	/**
243
	 * @param Website $website
244
	 *
245
	 * @throws TemplateNotFoundException
246
	 */
247 3
	public function installTemplate(Website $website)
248
	{
249 3
		$userFolder = new StorageFolder(\OC::$server->getUserFolder($website->getUserId()));
250
251
		try {
252 3
			$userFolder->get($website->getPath());
253
254
			// website folder exists; since we don't want to
255
			// mess around with a user's files, bail out
256
			return;
257 3
		} catch (NotFoundException $e) {
258
			// proceed if the website folder doesn't exist yet
259
		}
260
261 3
		$websiteFolder = $userFolder->newFolder($website->getPath());
262
263 3
		$templateFolder = $this->getTemplateFolder($website->getTemplateSource());
264 3
		$templateFolder->sync();
265
266 3
		$templateData = $this->getTemplateData($website);
267 3
		foreach (new \RecursiveIteratorIterator($templateFolder) as $file) {
268
			/** @var FileInterface $file */
269 3
			$templateFile = new TemplateFile($file);
270
271
			try {
272 3
				$targetFolder = $websiteFolder->getFolder($templateFile->getParent());
273 3
			} catch (NotFoundException $e) {
274 3
				$targetFolder = $websiteFolder->newFolder($templateFile->getParent());
275
			}
276
277 3
			if ($templateFile->getName() === 'empty') {
278
				continue;
279
			}
280
281 3
			$templateFile->setTemplateData($templateData);
282 3
			$templateFile->copy($targetFolder);
283
		}
284 3
	}
285
286
	/**
287
	 * @param Website $website
288
	 *
289
	 * @return array<string,string>
290
	 */
291 3
	private function getTemplateData(Website $website): array
292
	{
293
		return [
294 3
			'site_title' => $website->getName()
295
		];
296
	}
297
298
	/**
299
	 * @param string $templateName
300
	 *
301
	 * @return FolderInterface
302
	 * @throws TemplateNotFoundException
303
	 */
304 3
	public function getTemplateFolder(string $templateName): FolderInterface
305
	{
306 3
		if (!$templateName) {
307
			throw new TemplateNotFoundException();
308
		}
309
310 3
		$systemTemplatesFolder = $this->fileService->getSystemFolder(PicoService::DIR_TEMPLATES);
311 3
		$systemTemplatesFolder->sync(FolderInterface::SYNC_SHALLOW);
312
313 3
		$customTemplatesFolder = $this->fileService->getAppDataFolder(PicoService::DIR_TEMPLATES);
314 3
		$customTemplatesFolder->sync(FolderInterface::SYNC_SHALLOW);
315
316
		try {
317 3
			$templateFolder = $systemTemplatesFolder->getFolder($templateName);
318
		} catch (NotFoundException $e) {
319
			try {
320
				$templateFolder = $customTemplatesFolder->getFolder($templateName);
321
			} catch (NotFoundException $e) {
322
				throw new TemplateNotFoundException();
323
			}
324
		}
325
326 3
		return $templateFolder->fakeRoot();
327
	}
328
}
329