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