Passed
Push — master ( ad2033...9db3b2 )
by Roeland
12:21 queued 15s
created
lib/private/Files/Template/TemplateManager.php 1 patch
Indentation   +300 added lines, -300 removed lines patch added patch discarded remove patch
@@ -51,304 +51,304 @@
 block discarded – undo
51 51
 use Psr\Log\LoggerInterface;
52 52
 
53 53
 class TemplateManager implements ITemplateManager {
54
-	private $registeredTypes = [];
55
-	private $types = [];
56
-
57
-	/** @var array|null */
58
-	private $providers = null;
59
-
60
-	private $serverContainer;
61
-	private $eventDispatcher;
62
-	private $rootFolder;
63
-	private $userManager;
64
-	private $previewManager;
65
-	private $config;
66
-	private $l10n;
67
-	private $logger;
68
-	private $userId;
69
-	private $l10nFactory;
70
-	/** @var Coordinator */
71
-	private $bootstrapCoordinator;
72
-
73
-	public function __construct(
74
-		IServerContainer $serverContainer,
75
-		IEventDispatcher $eventDispatcher,
76
-		Coordinator $coordinator,
77
-		IRootFolder $rootFolder,
78
-		IUserSession $userSession,
79
-		IUserManager $userManager,
80
-		IPreview $previewManager,
81
-		IConfig $config,
82
-		IFactory $l10nFactory,
83
-		LoggerInterface $logger
84
-	) {
85
-		$this->serverContainer = $serverContainer;
86
-		$this->eventDispatcher = $eventDispatcher;
87
-		$this->bootstrapCoordinator = $coordinator;
88
-		$this->rootFolder = $rootFolder;
89
-		$this->userManager = $userManager;
90
-		$this->previewManager = $previewManager;
91
-		$this->config = $config;
92
-		$this->l10nFactory = $l10nFactory;
93
-		$this->l10n = $l10nFactory->get('lib');
94
-		$this->logger = $logger;
95
-		$user = $userSession->getUser();
96
-		$this->userId = $user ? $user->getUID() : null;
97
-	}
98
-
99
-	public function registerTemplateFileCreator(callable $callback): void {
100
-		$this->registeredTypes[] = $callback;
101
-	}
102
-
103
-	public function getRegisteredProviders(): array {
104
-		if ($this->providers !== null) {
105
-			return $this->providers;
106
-		}
107
-
108
-		$context = $this->bootstrapCoordinator->getRegistrationContext();
109
-
110
-		$this->providers = [];
111
-		foreach ($context->getTemplateProviders() as $provider) {
112
-			$this->providers[$provider['class']] = $this->serverContainer->get($provider['class']);
113
-		}
114
-		return $this->providers;
115
-	}
116
-
117
-	public function getTypes(): array {
118
-		if (!empty($this->types)) {
119
-			return $this->types;
120
-		}
121
-		foreach ($this->registeredTypes as $registeredType) {
122
-			$this->types[] = $registeredType();
123
-		}
124
-		return $this->types;
125
-	}
126
-
127
-	public function listCreators(): array {
128
-		$types = $this->getTypes();
129
-		usort($types, function (TemplateFileCreator $a, TemplateFileCreator $b) {
130
-			return $a->getOrder() - $b->getOrder();
131
-		});
132
-		return $types;
133
-	}
134
-
135
-	public function listTemplates(): array {
136
-		return array_map(function (TemplateFileCreator $entry) {
137
-			return array_merge($entry->jsonSerialize(), [
138
-				'templates' => $this->getTemplateFiles($entry)
139
-			]);
140
-		}, $this->listCreators());
141
-	}
142
-
143
-	/**
144
-	 * @param string $filePath
145
-	 * @param string $templateId
146
-	 * @return array
147
-	 * @throws GenericFileException
148
-	 */
149
-	public function createFromTemplate(string $filePath, string $templateId = '', string $templateType = 'user'): array {
150
-		$userFolder = $this->rootFolder->getUserFolder($this->userId);
151
-		try {
152
-			$userFolder->get($filePath);
153
-			throw new GenericFileException($this->l10n->t('File already exists'));
154
-		} catch (NotFoundException $e) {
155
-		}
156
-		try {
157
-			$targetFile = $userFolder->newFile($filePath);
158
-			if ($templateType === 'user' && $templateId !== '') {
159
-				$template = $userFolder->get($templateId);
160
-				$template->copy($targetFile->getPath());
161
-			} else {
162
-				$matchingProvider = array_filter($this->getRegisteredProviders(), function (ICustomTemplateProvider $provider) use ($templateType) {
163
-					return $templateType === get_class($provider);
164
-				});
165
-				$provider = array_shift($matchingProvider);
166
-				if ($provider) {
167
-					$template = $provider->getCustomTemplate($templateId);
168
-					$template->copy($targetFile->getPath());
169
-				}
170
-			}
171
-			$this->eventDispatcher->dispatchTyped(new FileCreatedFromTemplateEvent($template, $targetFile));
172
-			return $this->formatFile($userFolder->get($filePath));
173
-		} catch (\Exception $e) {
174
-			$this->logger->error($e->getMessage(), ['exception' => $e]);
175
-			throw new GenericFileException($this->l10n->t('Failed to create file from template'));
176
-		}
177
-	}
178
-
179
-	/**
180
-	 * @return Folder
181
-	 * @throws \OCP\Files\NotFoundException
182
-	 * @throws \OCP\Files\NotPermittedException
183
-	 * @throws \OC\User\NoUserException
184
-	 */
185
-	private function getTemplateFolder(): Node {
186
-		if ($this->getTemplatePath() !== '') {
187
-			return $this->rootFolder->getUserFolder($this->userId)->get($this->getTemplatePath());
188
-		}
189
-		throw new NotFoundException();
190
-	}
191
-
192
-	private function getTemplateFiles(TemplateFileCreator $type): array {
193
-		$templates = [];
194
-		foreach ($this->getRegisteredProviders() as $provider) {
195
-			foreach ($type->getMimetypes() as $mimetype) {
196
-				foreach ($provider->getCustomTemplates($mimetype) as $template) {
197
-					$templates[] = $template;
198
-				}
199
-			}
200
-		}
201
-		try {
202
-			$userTemplateFolder = $this->getTemplateFolder();
203
-		} catch (\Exception $e) {
204
-			return $templates;
205
-		}
206
-		foreach ($type->getMimetypes() as $mimetype) {
207
-			foreach ($userTemplateFolder->searchByMime($mimetype) as $templateFile) {
208
-				$template = new Template(
209
-					'user',
210
-					$this->rootFolder->getUserFolder($this->userId)->getRelativePath($templateFile->getPath()),
211
-					$templateFile
212
-				);
213
-				$template->setHasPreview($this->previewManager->isAvailable($templateFile));
214
-				$templates[] = $template;
215
-			}
216
-		}
217
-
218
-		return $templates;
219
-	}
220
-
221
-	/**
222
-	 * @param Node|File $file
223
-	 * @return array
224
-	 * @throws NotFoundException
225
-	 * @throws \OCP\Files\InvalidPathException
226
-	 */
227
-	private function formatFile(Node $file): array {
228
-		return [
229
-			'basename' => $file->getName(),
230
-			'etag' => $file->getEtag(),
231
-			'fileid' => $file->getId(),
232
-			'filename' => $this->rootFolder->getUserFolder($this->userId)->getRelativePath($file->getPath()),
233
-			'lastmod' => $file->getMTime(),
234
-			'mime' => $file->getMimetype(),
235
-			'size' => $file->getSize(),
236
-			'type' => $file->getType(),
237
-			'hasPreview' => $this->previewManager->isAvailable($file)
238
-		];
239
-	}
240
-
241
-	public function hasTemplateDirectory(): bool {
242
-		try {
243
-			$this->getTemplateFolder();
244
-			return true;
245
-		} catch (\Exception $e) {
246
-		}
247
-		return false;
248
-	}
249
-
250
-	public function setTemplatePath(string $path): void {
251
-		$this->config->setUserValue($this->userId, 'core', 'templateDirectory', $path);
252
-	}
253
-
254
-	public function getTemplatePath(): string {
255
-		return $this->config->getUserValue($this->userId, 'core', 'templateDirectory', '');
256
-	}
257
-
258
-	public function initializeTemplateDirectory(string $path = null, string $userId = null, $copyTemplates = true): string {
259
-		if ($userId !== null) {
260
-			$this->userId = $userId;
261
-		}
262
-
263
-		$defaultSkeletonDirectory = \OC::$SERVERROOT . '/core/skeleton';
264
-		$defaultTemplateDirectory = \OC::$SERVERROOT . '/core/skeleton/Templates';
265
-		$skeletonPath = $this->config->getSystemValue('skeletondirectory', $defaultSkeletonDirectory);
266
-		$skeletonTemplatePath = $this->config->getSystemValue('templatedirectory', $defaultTemplateDirectory);
267
-		$isDefaultSkeleton = $skeletonPath === $defaultSkeletonDirectory;
268
-		$isDefaultTemplates = $skeletonTemplatePath === $defaultTemplateDirectory;
269
-		$userLang = $this->l10nFactory->getUserLanguage($this->userManager->get($this->userId));
270
-
271
-		try {
272
-			$l10n = $this->l10nFactory->get('lib', $userLang);
273
-			$userFolder = $this->rootFolder->getUserFolder($this->userId);
274
-			$userTemplatePath = $path ?? $l10n->t('Templates') . '/';
275
-
276
-			// Initial user setup without a provided path
277
-			if ($path === null) {
278
-				// All locations are default so we just need to rename the directory to the users language
279
-				if ($isDefaultSkeleton && $isDefaultTemplates) {
280
-					if (!$userFolder->nodeExists('Templates')) {
281
-						return '';
282
-					}
283
-					$newPath = Filesystem::normalizePath($userFolder->getPath() . '/' . $userTemplatePath);
284
-					if ($newPath !== $userFolder->get('Templates')->getPath()) {
285
-						$userFolder->get('Templates')->move($newPath);
286
-					}
287
-					$this->setTemplatePath($userTemplatePath);
288
-					return $userTemplatePath;
289
-				}
290
-
291
-				if ($isDefaultSkeleton && !empty($skeletonTemplatePath) && !$isDefaultTemplates && $userFolder->nodeExists('Templates')) {
292
-					$shippedSkeletonTemplates = $userFolder->get('Templates');
293
-					$shippedSkeletonTemplates->delete();
294
-				}
295
-			}
296
-
297
-			try {
298
-				$folder = $userFolder->newFolder($userTemplatePath);
299
-			} catch (NotPermittedException $e) {
300
-				$folder = $userFolder->get($userTemplatePath);
301
-			}
302
-
303
-			$folderIsEmpty = count($folder->getDirectoryListing()) === 0;
304
-
305
-			if (!$copyTemplates) {
306
-				$this->setTemplatePath($userTemplatePath);
307
-				return $userTemplatePath;
308
-			}
309
-
310
-			if (!$isDefaultTemplates && $folderIsEmpty) {
311
-				$localizedSkeletonTemplatePath = $this->getLocalizedTemplatePath($skeletonTemplatePath, $userLang);
312
-				if (!empty($localizedSkeletonTemplatePath) && file_exists($localizedSkeletonTemplatePath)) {
313
-					\OC_Util::copyr($localizedSkeletonTemplatePath, $folder);
314
-					$userFolder->getStorage()->getScanner()->scan($folder->getInternalPath(), Scanner::SCAN_RECURSIVE);
315
-					$this->setTemplatePath($userTemplatePath);
316
-					return $userTemplatePath;
317
-				}
318
-			}
319
-
320
-			if ($path !== null && $isDefaultSkeleton && $isDefaultTemplates && $folderIsEmpty) {
321
-				$localizedSkeletonPath = $this->getLocalizedTemplatePath($skeletonPath . '/Templates', $userLang);
322
-				if (!empty($localizedSkeletonPath) && file_exists($localizedSkeletonPath)) {
323
-					\OC_Util::copyr($localizedSkeletonPath, $folder);
324
-					$userFolder->getStorage()->getScanner()->scan($folder->getInternalPath(), Scanner::SCAN_RECURSIVE);
325
-					$this->setTemplatePath($userTemplatePath);
326
-					return $userTemplatePath;
327
-				}
328
-			}
329
-
330
-			$this->setTemplatePath($path ?? '');
331
-			return $this->getTemplatePath();
332
-		} catch (\Throwable $e) {
333
-			$this->logger->error('Failed to initialize templates directory to user language ' . $userLang . ' for ' . $userId, ['app' => 'files_templates', 'exception' => $e]);
334
-		}
335
-		$this->setTemplatePath('');
336
-		return $this->getTemplatePath();
337
-	}
338
-
339
-	private function getLocalizedTemplatePath(string $skeletonTemplatePath, string $userLang) {
340
-		$localizedSkeletonTemplatePath = str_replace('{lang}', $userLang, $skeletonTemplatePath);
341
-
342
-		if (!file_exists($localizedSkeletonTemplatePath)) {
343
-			$dialectStart = strpos($userLang, '_');
344
-			if ($dialectStart !== false) {
345
-				$localizedSkeletonTemplatePath = str_replace('{lang}', substr($userLang, 0, $dialectStart), $skeletonTemplatePath);
346
-			}
347
-			if ($dialectStart === false || !file_exists($localizedSkeletonTemplatePath)) {
348
-				$localizedSkeletonTemplatePath = str_replace('{lang}', 'default', $skeletonTemplatePath);
349
-			}
350
-		}
351
-
352
-		return $localizedSkeletonTemplatePath;
353
-	}
54
+    private $registeredTypes = [];
55
+    private $types = [];
56
+
57
+    /** @var array|null */
58
+    private $providers = null;
59
+
60
+    private $serverContainer;
61
+    private $eventDispatcher;
62
+    private $rootFolder;
63
+    private $userManager;
64
+    private $previewManager;
65
+    private $config;
66
+    private $l10n;
67
+    private $logger;
68
+    private $userId;
69
+    private $l10nFactory;
70
+    /** @var Coordinator */
71
+    private $bootstrapCoordinator;
72
+
73
+    public function __construct(
74
+        IServerContainer $serverContainer,
75
+        IEventDispatcher $eventDispatcher,
76
+        Coordinator $coordinator,
77
+        IRootFolder $rootFolder,
78
+        IUserSession $userSession,
79
+        IUserManager $userManager,
80
+        IPreview $previewManager,
81
+        IConfig $config,
82
+        IFactory $l10nFactory,
83
+        LoggerInterface $logger
84
+    ) {
85
+        $this->serverContainer = $serverContainer;
86
+        $this->eventDispatcher = $eventDispatcher;
87
+        $this->bootstrapCoordinator = $coordinator;
88
+        $this->rootFolder = $rootFolder;
89
+        $this->userManager = $userManager;
90
+        $this->previewManager = $previewManager;
91
+        $this->config = $config;
92
+        $this->l10nFactory = $l10nFactory;
93
+        $this->l10n = $l10nFactory->get('lib');
94
+        $this->logger = $logger;
95
+        $user = $userSession->getUser();
96
+        $this->userId = $user ? $user->getUID() : null;
97
+    }
98
+
99
+    public function registerTemplateFileCreator(callable $callback): void {
100
+        $this->registeredTypes[] = $callback;
101
+    }
102
+
103
+    public function getRegisteredProviders(): array {
104
+        if ($this->providers !== null) {
105
+            return $this->providers;
106
+        }
107
+
108
+        $context = $this->bootstrapCoordinator->getRegistrationContext();
109
+
110
+        $this->providers = [];
111
+        foreach ($context->getTemplateProviders() as $provider) {
112
+            $this->providers[$provider['class']] = $this->serverContainer->get($provider['class']);
113
+        }
114
+        return $this->providers;
115
+    }
116
+
117
+    public function getTypes(): array {
118
+        if (!empty($this->types)) {
119
+            return $this->types;
120
+        }
121
+        foreach ($this->registeredTypes as $registeredType) {
122
+            $this->types[] = $registeredType();
123
+        }
124
+        return $this->types;
125
+    }
126
+
127
+    public function listCreators(): array {
128
+        $types = $this->getTypes();
129
+        usort($types, function (TemplateFileCreator $a, TemplateFileCreator $b) {
130
+            return $a->getOrder() - $b->getOrder();
131
+        });
132
+        return $types;
133
+    }
134
+
135
+    public function listTemplates(): array {
136
+        return array_map(function (TemplateFileCreator $entry) {
137
+            return array_merge($entry->jsonSerialize(), [
138
+                'templates' => $this->getTemplateFiles($entry)
139
+            ]);
140
+        }, $this->listCreators());
141
+    }
142
+
143
+    /**
144
+     * @param string $filePath
145
+     * @param string $templateId
146
+     * @return array
147
+     * @throws GenericFileException
148
+     */
149
+    public function createFromTemplate(string $filePath, string $templateId = '', string $templateType = 'user'): array {
150
+        $userFolder = $this->rootFolder->getUserFolder($this->userId);
151
+        try {
152
+            $userFolder->get($filePath);
153
+            throw new GenericFileException($this->l10n->t('File already exists'));
154
+        } catch (NotFoundException $e) {
155
+        }
156
+        try {
157
+            $targetFile = $userFolder->newFile($filePath);
158
+            if ($templateType === 'user' && $templateId !== '') {
159
+                $template = $userFolder->get($templateId);
160
+                $template->copy($targetFile->getPath());
161
+            } else {
162
+                $matchingProvider = array_filter($this->getRegisteredProviders(), function (ICustomTemplateProvider $provider) use ($templateType) {
163
+                    return $templateType === get_class($provider);
164
+                });
165
+                $provider = array_shift($matchingProvider);
166
+                if ($provider) {
167
+                    $template = $provider->getCustomTemplate($templateId);
168
+                    $template->copy($targetFile->getPath());
169
+                }
170
+            }
171
+            $this->eventDispatcher->dispatchTyped(new FileCreatedFromTemplateEvent($template, $targetFile));
172
+            return $this->formatFile($userFolder->get($filePath));
173
+        } catch (\Exception $e) {
174
+            $this->logger->error($e->getMessage(), ['exception' => $e]);
175
+            throw new GenericFileException($this->l10n->t('Failed to create file from template'));
176
+        }
177
+    }
178
+
179
+    /**
180
+     * @return Folder
181
+     * @throws \OCP\Files\NotFoundException
182
+     * @throws \OCP\Files\NotPermittedException
183
+     * @throws \OC\User\NoUserException
184
+     */
185
+    private function getTemplateFolder(): Node {
186
+        if ($this->getTemplatePath() !== '') {
187
+            return $this->rootFolder->getUserFolder($this->userId)->get($this->getTemplatePath());
188
+        }
189
+        throw new NotFoundException();
190
+    }
191
+
192
+    private function getTemplateFiles(TemplateFileCreator $type): array {
193
+        $templates = [];
194
+        foreach ($this->getRegisteredProviders() as $provider) {
195
+            foreach ($type->getMimetypes() as $mimetype) {
196
+                foreach ($provider->getCustomTemplates($mimetype) as $template) {
197
+                    $templates[] = $template;
198
+                }
199
+            }
200
+        }
201
+        try {
202
+            $userTemplateFolder = $this->getTemplateFolder();
203
+        } catch (\Exception $e) {
204
+            return $templates;
205
+        }
206
+        foreach ($type->getMimetypes() as $mimetype) {
207
+            foreach ($userTemplateFolder->searchByMime($mimetype) as $templateFile) {
208
+                $template = new Template(
209
+                    'user',
210
+                    $this->rootFolder->getUserFolder($this->userId)->getRelativePath($templateFile->getPath()),
211
+                    $templateFile
212
+                );
213
+                $template->setHasPreview($this->previewManager->isAvailable($templateFile));
214
+                $templates[] = $template;
215
+            }
216
+        }
217
+
218
+        return $templates;
219
+    }
220
+
221
+    /**
222
+     * @param Node|File $file
223
+     * @return array
224
+     * @throws NotFoundException
225
+     * @throws \OCP\Files\InvalidPathException
226
+     */
227
+    private function formatFile(Node $file): array {
228
+        return [
229
+            'basename' => $file->getName(),
230
+            'etag' => $file->getEtag(),
231
+            'fileid' => $file->getId(),
232
+            'filename' => $this->rootFolder->getUserFolder($this->userId)->getRelativePath($file->getPath()),
233
+            'lastmod' => $file->getMTime(),
234
+            'mime' => $file->getMimetype(),
235
+            'size' => $file->getSize(),
236
+            'type' => $file->getType(),
237
+            'hasPreview' => $this->previewManager->isAvailable($file)
238
+        ];
239
+    }
240
+
241
+    public function hasTemplateDirectory(): bool {
242
+        try {
243
+            $this->getTemplateFolder();
244
+            return true;
245
+        } catch (\Exception $e) {
246
+        }
247
+        return false;
248
+    }
249
+
250
+    public function setTemplatePath(string $path): void {
251
+        $this->config->setUserValue($this->userId, 'core', 'templateDirectory', $path);
252
+    }
253
+
254
+    public function getTemplatePath(): string {
255
+        return $this->config->getUserValue($this->userId, 'core', 'templateDirectory', '');
256
+    }
257
+
258
+    public function initializeTemplateDirectory(string $path = null, string $userId = null, $copyTemplates = true): string {
259
+        if ($userId !== null) {
260
+            $this->userId = $userId;
261
+        }
262
+
263
+        $defaultSkeletonDirectory = \OC::$SERVERROOT . '/core/skeleton';
264
+        $defaultTemplateDirectory = \OC::$SERVERROOT . '/core/skeleton/Templates';
265
+        $skeletonPath = $this->config->getSystemValue('skeletondirectory', $defaultSkeletonDirectory);
266
+        $skeletonTemplatePath = $this->config->getSystemValue('templatedirectory', $defaultTemplateDirectory);
267
+        $isDefaultSkeleton = $skeletonPath === $defaultSkeletonDirectory;
268
+        $isDefaultTemplates = $skeletonTemplatePath === $defaultTemplateDirectory;
269
+        $userLang = $this->l10nFactory->getUserLanguage($this->userManager->get($this->userId));
270
+
271
+        try {
272
+            $l10n = $this->l10nFactory->get('lib', $userLang);
273
+            $userFolder = $this->rootFolder->getUserFolder($this->userId);
274
+            $userTemplatePath = $path ?? $l10n->t('Templates') . '/';
275
+
276
+            // Initial user setup without a provided path
277
+            if ($path === null) {
278
+                // All locations are default so we just need to rename the directory to the users language
279
+                if ($isDefaultSkeleton && $isDefaultTemplates) {
280
+                    if (!$userFolder->nodeExists('Templates')) {
281
+                        return '';
282
+                    }
283
+                    $newPath = Filesystem::normalizePath($userFolder->getPath() . '/' . $userTemplatePath);
284
+                    if ($newPath !== $userFolder->get('Templates')->getPath()) {
285
+                        $userFolder->get('Templates')->move($newPath);
286
+                    }
287
+                    $this->setTemplatePath($userTemplatePath);
288
+                    return $userTemplatePath;
289
+                }
290
+
291
+                if ($isDefaultSkeleton && !empty($skeletonTemplatePath) && !$isDefaultTemplates && $userFolder->nodeExists('Templates')) {
292
+                    $shippedSkeletonTemplates = $userFolder->get('Templates');
293
+                    $shippedSkeletonTemplates->delete();
294
+                }
295
+            }
296
+
297
+            try {
298
+                $folder = $userFolder->newFolder($userTemplatePath);
299
+            } catch (NotPermittedException $e) {
300
+                $folder = $userFolder->get($userTemplatePath);
301
+            }
302
+
303
+            $folderIsEmpty = count($folder->getDirectoryListing()) === 0;
304
+
305
+            if (!$copyTemplates) {
306
+                $this->setTemplatePath($userTemplatePath);
307
+                return $userTemplatePath;
308
+            }
309
+
310
+            if (!$isDefaultTemplates && $folderIsEmpty) {
311
+                $localizedSkeletonTemplatePath = $this->getLocalizedTemplatePath($skeletonTemplatePath, $userLang);
312
+                if (!empty($localizedSkeletonTemplatePath) && file_exists($localizedSkeletonTemplatePath)) {
313
+                    \OC_Util::copyr($localizedSkeletonTemplatePath, $folder);
314
+                    $userFolder->getStorage()->getScanner()->scan($folder->getInternalPath(), Scanner::SCAN_RECURSIVE);
315
+                    $this->setTemplatePath($userTemplatePath);
316
+                    return $userTemplatePath;
317
+                }
318
+            }
319
+
320
+            if ($path !== null && $isDefaultSkeleton && $isDefaultTemplates && $folderIsEmpty) {
321
+                $localizedSkeletonPath = $this->getLocalizedTemplatePath($skeletonPath . '/Templates', $userLang);
322
+                if (!empty($localizedSkeletonPath) && file_exists($localizedSkeletonPath)) {
323
+                    \OC_Util::copyr($localizedSkeletonPath, $folder);
324
+                    $userFolder->getStorage()->getScanner()->scan($folder->getInternalPath(), Scanner::SCAN_RECURSIVE);
325
+                    $this->setTemplatePath($userTemplatePath);
326
+                    return $userTemplatePath;
327
+                }
328
+            }
329
+
330
+            $this->setTemplatePath($path ?? '');
331
+            return $this->getTemplatePath();
332
+        } catch (\Throwable $e) {
333
+            $this->logger->error('Failed to initialize templates directory to user language ' . $userLang . ' for ' . $userId, ['app' => 'files_templates', 'exception' => $e]);
334
+        }
335
+        $this->setTemplatePath('');
336
+        return $this->getTemplatePath();
337
+    }
338
+
339
+    private function getLocalizedTemplatePath(string $skeletonTemplatePath, string $userLang) {
340
+        $localizedSkeletonTemplatePath = str_replace('{lang}', $userLang, $skeletonTemplatePath);
341
+
342
+        if (!file_exists($localizedSkeletonTemplatePath)) {
343
+            $dialectStart = strpos($userLang, '_');
344
+            if ($dialectStart !== false) {
345
+                $localizedSkeletonTemplatePath = str_replace('{lang}', substr($userLang, 0, $dialectStart), $skeletonTemplatePath);
346
+            }
347
+            if ($dialectStart === false || !file_exists($localizedSkeletonTemplatePath)) {
348
+                $localizedSkeletonTemplatePath = str_replace('{lang}', 'default', $skeletonTemplatePath);
349
+            }
350
+        }
351
+
352
+        return $localizedSkeletonTemplatePath;
353
+    }
354 354
 }
Please login to merge, or discard this patch.