1<?php
2
3
4namespace ComboStrap;
5
6
7use renderer_plugin_combo_analytics;
8
9class FileSystems
10{
11
12    public const CONTAINER = "container";
13    public const LEAF = "leaf";
14
15    static function exists(Path $path): bool
16    {
17        $scheme = $path->getScheme();
18        switch ($scheme) {
19            case LocalFileSystem::SCHEME:
20                return LocalFileSystem::getOrCreate()->exists($path);
21            case WikiFileSystem::SCHEME:
22                return WikiFileSystem::getOrCreate()->exists($path);
23            case MarkupFileSystem::SCHEME:
24                return MarkupFileSystem::getOrCreate()->exists($path);
25            default:
26                throw new ExceptionRuntime("File system ($scheme) unknown");
27        }
28    }
29
30    /**
31     * @throws ExceptionNotFound - if the file does not exists or the mime is unknown
32     */
33    public static function getContent(Path $path): string
34    {
35        $scheme = $path->getScheme();
36        switch ($scheme) {
37            case LocalFileSystem::SCHEME:
38                return LocalFileSystem::getOrCreate()->getContent($path);
39            case WikiFileSystem::SCHEME:
40                return WikiFileSystem::getOrCreate()->getContent($path);
41        }
42        throw new ExceptionRuntime("File system ($scheme) unknown");
43    }
44
45    /**
46     * @throws ExceptionNotFound - if the file does not exist
47     */
48    public static function getModifiedTime(Path $path): \DateTime
49    {
50        $scheme = $path->getScheme();
51        switch ($scheme) {
52            case LocalFileSystem::SCHEME:
53                /** @noinspection PhpParamsInspection */
54                return LocalFileSystem::getOrCreate()->getModifiedTime($path);
55            case WikiFileSystem::SCHEME:
56                return WikiFileSystem::getOrCreate()->getModifiedTime($path);
57            default:
58                throw new ExceptionRuntime("File system ($scheme) unknown");
59        }
60
61    }
62
63    /**
64     * @throws ExceptionNotFound
65     */
66    public static function getCreationTime(Path $path)
67    {
68        $scheme = $path->getScheme();
69        switch ($scheme) {
70            case LocalFileSystem::SCHEME:
71                return LocalFileSystem::getOrCreate()->getCreationTime($path);
72            case WikiFileSystem::SCHEME:
73                return WikiFileSystem::getOrCreate()->getCreationTime($path);
74            default:
75                // Internal Error: should not happen
76                throw new ExceptionRuntime("File system ($scheme) unknown");
77        }
78    }
79
80    public static function deleteIfExists(Path $path)
81    {
82        if (FileSystems::exists($path)) {
83            FileSystems::delete($path);
84        }
85    }
86
87    /**
88     * @throws ExceptionFileSystem
89     */
90    public static function delete(Path $path)
91    {
92        $scheme = $path->getScheme();
93        switch ($scheme) {
94            case LocalFileSystem::SCHEME:
95                LocalFileSystem::getOrCreate()->delete($path);
96                return;
97            case WikiFileSystem::SCHEME:
98                WikiFileSystem::getOrCreate()->delete($path);
99                return;
100            case MarkupFileSystem::SCHEME:
101                MarkupFileSystem::getOrCreate()->delete($path);
102                return;
103            default:
104                throw new ExceptionRuntime("File system ($scheme) unknown");
105        }
106    }
107
108    public static function getSize(Path $path)
109    {
110
111        $scheme = $path->getScheme();
112        switch ($scheme) {
113            case LocalFileSystem::SCHEME:
114                return LocalFileSystem::getOrCreate()->getSize($path);
115            case WikiFileSystem::SCHEME:
116                return WikiFileSystem::getOrCreate()->getSize($path);
117            default:
118                throw new ExceptionRuntime("File system ($scheme) unknown");
119        }
120    }
121
122
123    /**
124     * @throws ExceptionCompile
125     */
126    public static function createDirectory(Path $dirPath)
127    {
128        $scheme = $dirPath->getScheme();
129        switch ($scheme) {
130            case LocalFileSystem::SCHEME:
131                return LocalFileSystem::getOrCreate()->createDirectory($dirPath);
132            case WikiFileSystem::SCHEME:
133                return WikiFileSystem::getOrCreate()->createDirectory($dirPath);
134            default:
135                throw new ExceptionRuntime("File system ($scheme) unknown");
136        }
137    }
138
139    public static function isDirectory(Path $path): bool
140    {
141        $scheme = $path->getScheme();
142        switch ($scheme) {
143            case LocalFileSystem::SCHEME:
144                return LocalFileSystem::getOrCreate()->isDirectory($path);
145            case WikiFileSystem::SCHEME:
146                return WikiFileSystem::getOrCreate()->isDirectory($path);
147            default:
148                throw new ExceptionRuntime("File system ($scheme) unknown");
149        }
150    }
151
152
153    /**
154     * @return Path[]
155     */
156    public static function getChildren(Path $path, string $type = null): array
157    {
158        $scheme = $path->getScheme();
159        switch ($scheme) {
160            case LocalFileSystem::SCHEME:
161                return LocalFileSystem::getOrCreate()->getChildren($path, $type);
162            case WikiFileSystem::SCHEME:
163                return WikiFileSystem::getOrCreate()->getChildren($path, $type);
164            case MarkupFileSystem::SCHEME:
165                return MarkupFileSystem::getOrCreate()->getChildren($path, $type);
166            default:
167                throw new ExceptionRuntime("File system ($scheme) unknown");
168        }
169    }
170
171    /**
172     * @param Path $namespacePath
173     * @return Path[]
174     */
175    public static function getChildrenContainer(Path $namespacePath): array
176    {
177        return self::getChildren($namespacePath, FileSystems::CONTAINER);
178    }
179
180    /**
181     * @param Path $namespacePath
182     * @return Path[]
183     */
184    public static function getChildrenLeaf(Path $namespacePath): array
185    {
186        try {
187            return self::getChildren($namespacePath, FileSystems::LEAF);
188        } catch (ExceptionBadArgument $e) {
189            // as we path the type, it should not happen
190            throw new ExceptionRuntime("Error getting the children. Error: {$e->getMessage()}");
191        }
192    }
193
194    /**
195     * Return a cache buster
196     * @throws ExceptionNotFound
197     * Utility function to calculate a buster based on a path for the implementation of {@link FetchAbstract::getBuster()}
198     */
199    public static function getCacheBuster(Path $path): string
200    {
201        $time = FileSystems::getModifiedTime($path);
202        return strval($time->getTimestamp());
203    }
204
205    /**
206     * @throws ExceptionNotFound
207     */
208    public static function closest(Path $path, string $name): Path
209    {
210        $scheme = $path->getScheme();
211        switch ($scheme) {
212            case LocalFileSystem::SCHEME:
213                return LocalFileSystem::getOrCreate()->closest($path, $name);
214            case WikiFileSystem::SCHEME:
215                return WikiFileSystem::getOrCreate()->closest($path, $name);
216            default:
217                throw new ExceptionRuntime("File system ($scheme) unknown");
218        }
219    }
220
221    public static function createRegularFile(Path $path)
222    {
223        $scheme = $path->getScheme();
224        switch ($scheme) {
225            case LocalFileSystem::SCHEME:
226                LocalFileSystem::getOrCreate()->createRegularFile($path);
227                break;
228            case WikiFileSystem::SCHEME:
229                WikiFileSystem::getOrCreate()->createRegularFile($path);
230                break;
231            default:
232                throw new ExceptionRuntime("File system ($scheme) unknown");
233        }
234    }
235
236    /**
237     * @throws ExceptionNotFound - if the mime is unknown and was not found
238     */
239    public static function getMime(Path $path): Mime
240    {
241        $extension = $path->getExtension();
242        try {
243            return Mime::createFromExtension($extension);
244        } catch (ExceptionNotFound $e) {
245            $mime = mimetype($path->getLastName(), true)[1];
246            if ($mime === null || $mime === false) {
247                throw new ExceptionNotFound("No mime found for path ($path). The mime type of the media is <a href=\"https://www.dokuwiki.org/mime\">unknown (not in the configuration file)</a>");
248            }
249            return new Mime($mime);
250        }
251    }
252
253    public static function setContent(Path $path, string $content)
254    {
255        $scheme = $path->getScheme();
256        switch ($scheme) {
257            case LocalFileSystem::SCHEME:
258                LocalFileSystem::getOrCreate()->setContent($path, $content);
259                break;
260            case WikiFileSystem::SCHEME:
261                WikiFileSystem::getOrCreate()->setContent($path, $content);
262                break;
263            case MarkupFileSystem::SCHEME:
264                MarkupFileSystem::getOrCreate()->setContent($path, $content);
265                break;
266            default:
267                throw new ExceptionRuntime("File system ($scheme) unknown");
268        }
269    }
270
271    /**
272     * @param Path[] $paths
273     * @return Path
274     * @throws ExceptionNotFound
275     */
276    public static function getFirstExistingPath(array $paths): Path
277    {
278
279        foreach ($paths as $path) {
280            if (FileSystems::exists($path)) {
281                return $path;
282            }
283        }
284        throw new ExceptionNotFound("Existing file could be found");
285
286    }
287
288    public static function getTree(Path $path): PathTreeNode
289    {
290        return PathTreeNode::buildTreeViaFileSystemChildren($path);
291    }
292
293    /**
294     * @throws ExceptionBadArgument - if they are not local path
295     */
296    public static function copy(Path $source, Path $destination)
297    {
298        $sourceLocal = LocalPath::createFromPathObject($source);
299        $destinationLocal = LocalPath::createFromPathObject($destination);
300        copy($sourceLocal->toAbsoluteId(), $destinationLocal->toAbsoluteId());
301
302        // D:\dokuwiki\lib\plugins\combo\_test\resources\bootstrapLocal.json
303    }
304
305    /**
306     * Debug
307     * @param Path $mediaFile
308     * @return void
309     * Unfortunately, due to php, the time may be not use
310     * at the second
311     * as for the same file, we may end up in the same
312     * process to two differents modified time.
313     * ie
314     * Fri, 10 Feb 2023 18:22:09 +0000
315     * Fri, 10 Feb 2023 18:22:30 +0000
316     */
317    public static function printModificationTimeToConsole(Path $mediaFile, string $log)
318    {
319        fputs(STDOUT, "ModificationTime of {$mediaFile->toAbsoluteId()}" . PHP_EOL);
320        $filename = $mediaFile->toAbsolutePath()->toAbsoluteId();
321        fputs(STDOUT, "ModificationTime of $filename at $log ");
322        $timestamp = filemtime($filename);
323        fputs(STDOUT, " $timestamp" . PHP_EOL);
324    }
325
326    public static function clearStatCache(Path $path)
327    {
328        try {
329            $pathString = $path->toLocalPath()->toCanonicalAbsolutePath()->toAbsoluteId();
330            clearstatcache(true, $pathString);
331        } catch (ExceptionCast $e) {
332            throw new ExceptionRuntimeInternal("The cache can be clear only for local path");
333        }
334
335    }
336
337
338    /**
339     * @throws ExceptionBadSyntax
340     * @throws ExceptionBadArgument
341     */
342    public static function createPathFromUri($uri): Path
343    {
344        $firstColon = strpos($uri, ":");
345        if ($firstColon === false) {
346            throw new ExceptionBadSyntax("$uri is not a valid uri");
347        }
348        $scheme = substr($uri, 0, $firstColon);
349        switch ($scheme) {
350            case WikiFileSystem::SCHEME:
351                return WikiPath::createFromUri($uri);
352            case LocalFileSystem::SCHEME:
353                return LocalPath::createFromUri($uri);
354            default:
355                throw new ExceptionRuntimeInternal("The scheme ($scheme) is not yet supported");
356        }
357
358    }
359
360    /**
361     * @throws ExceptionCompile
362     */
363    public static function createDirectoryIfNotExists(Path $directoryPath)
364    {
365        if (!self::exists($directoryPath)){
366            self::createDirectory($directoryPath);
367        }
368    }
369}
370