Subversion-Projekte lars-tiefland.laravel_shop

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
<?php
2
 
3
declare(strict_types=1);
4
 
5
namespace League\Flysystem;
6
 
7
use DateTimeInterface;
8
use Throwable;
9
 
10
use function method_exists;
11
use function sprintf;
12
 
13
class MountManager implements FilesystemOperator
14
{
15
    /**
16
     * @var array<string, FilesystemOperator>
17
     */
18
    private $filesystems = [];
19
 
20
    /**
21
     * MountManager constructor.
22
     *
23
     * @param array<string,FilesystemOperator> $filesystems
24
     */
25
    public function __construct(array $filesystems = [])
26
    {
27
        $this->mountFilesystems($filesystems);
28
    }
29
 
30
    public function fileExists(string $location): bool
31
    {
32
        /** @var FilesystemOperator $filesystem */
33
        [$filesystem, $path] = $this->determineFilesystemAndPath($location);
34
 
35
        try {
36
            return $filesystem->fileExists($path);
37
        } catch (Throwable $exception) {
38
            throw UnableToCheckFileExistence::forLocation($location, $exception);
39
        }
40
    }
41
 
42
    public function has(string $location): bool
43
    {
44
        /** @var FilesystemOperator $filesystem */
45
        [$filesystem, $path] = $this->determineFilesystemAndPath($location);
46
 
47
        try {
48
            return $filesystem->fileExists($path) || $filesystem->directoryExists($path);
49
        } catch (Throwable $exception) {
50
            throw UnableToCheckExistence::forLocation($location, $exception);
51
        }
52
    }
53
 
54
    public function directoryExists(string $location): bool
55
    {
56
        /** @var FilesystemOperator $filesystem */
57
        [$filesystem, $path] = $this->determineFilesystemAndPath($location);
58
 
59
        try {
60
            return $filesystem->directoryExists($path);
61
        } catch (Throwable $exception) {
62
            throw UnableToCheckDirectoryExistence::forLocation($location, $exception);
63
        }
64
    }
65
 
66
    public function read(string $location): string
67
    {
68
        /** @var FilesystemOperator $filesystem */
69
        [$filesystem, $path] = $this->determineFilesystemAndPath($location);
70
 
71
        try {
72
            return $filesystem->read($path);
73
        } catch (UnableToReadFile $exception) {
74
            throw UnableToReadFile::fromLocation($location, $exception->reason(), $exception);
75
        }
76
    }
77
 
78
    public function readStream(string $location)
79
    {
80
        /** @var FilesystemOperator $filesystem */
81
        [$filesystem, $path] = $this->determineFilesystemAndPath($location);
82
 
83
        try {
84
            return $filesystem->readStream($path);
85
        } catch (UnableToReadFile $exception) {
86
            throw UnableToReadFile::fromLocation($location, $exception->reason(), $exception);
87
        }
88
    }
89
 
90
    public function listContents(string $location, bool $deep = self::LIST_SHALLOW): DirectoryListing
91
    {
92
        /** @var FilesystemOperator $filesystem */
93
        [$filesystem, $path, $mountIdentifier] = $this->determineFilesystemAndPath($location);
94
 
95
        return
96
            $filesystem
97
                ->listContents($path, $deep)
98
                ->map(
99
                    function (StorageAttributes $attributes) use ($mountIdentifier) {
100
                        return $attributes->withPath(sprintf('%s://%s', $mountIdentifier, $attributes->path()));
101
                    }
102
                );
103
    }
104
 
105
    public function lastModified(string $location): int
106
    {
107
        /** @var FilesystemOperator $filesystem */
108
        [$filesystem, $path] = $this->determineFilesystemAndPath($location);
109
 
110
        try {
111
            return $filesystem->lastModified($path);
112
        } catch (UnableToRetrieveMetadata $exception) {
113
            throw UnableToRetrieveMetadata::lastModified($location, $exception->reason(), $exception);
114
        }
115
    }
116
 
117
    public function fileSize(string $location): int
118
    {
119
        /** @var FilesystemOperator $filesystem */
120
        [$filesystem, $path] = $this->determineFilesystemAndPath($location);
121
 
122
        try {
123
            return $filesystem->fileSize($path);
124
        } catch (UnableToRetrieveMetadata $exception) {
125
            throw UnableToRetrieveMetadata::fileSize($location, $exception->reason(), $exception);
126
        }
127
    }
128
 
129
    public function mimeType(string $location): string
130
    {
131
        /** @var FilesystemOperator $filesystem */
132
        [$filesystem, $path] = $this->determineFilesystemAndPath($location);
133
 
134
        try {
135
            return $filesystem->mimeType($path);
136
        } catch (UnableToRetrieveMetadata $exception) {
137
            throw UnableToRetrieveMetadata::mimeType($location, $exception->reason(), $exception);
138
        }
139
    }
140
 
141
    public function visibility(string $location): string
142
    {
143
        /** @var FilesystemOperator $filesystem */
144
        [$filesystem, $path] = $this->determineFilesystemAndPath($location);
145
 
146
        try {
147
            return $filesystem->visibility($path);
148
        } catch (UnableToRetrieveMetadata $exception) {
149
            throw UnableToRetrieveMetadata::visibility($location, $exception->reason(), $exception);
150
        }
151
    }
152
 
153
    public function write(string $location, string $contents, array $config = []): void
154
    {
155
        /** @var FilesystemOperator $filesystem */
156
        [$filesystem, $path] = $this->determineFilesystemAndPath($location);
157
 
158
        try {
159
            $filesystem->write($path, $contents, $config);
160
        } catch (UnableToWriteFile $exception) {
161
            throw UnableToWriteFile::atLocation($location, $exception->reason(), $exception);
162
        }
163
    }
164
 
165
    public function writeStream(string $location, $contents, array $config = []): void
166
    {
167
        /** @var FilesystemOperator $filesystem */
168
        [$filesystem, $path] = $this->determineFilesystemAndPath($location);
169
        $filesystem->writeStream($path, $contents, $config);
170
    }
171
 
172
    public function setVisibility(string $path, string $visibility): void
173
    {
174
        /** @var FilesystemOperator $filesystem */
175
        [$filesystem, $path] = $this->determineFilesystemAndPath($path);
176
        $filesystem->setVisibility($path, $visibility);
177
    }
178
 
179
    public function delete(string $location): void
180
    {
181
        /** @var FilesystemOperator $filesystem */
182
        [$filesystem, $path] = $this->determineFilesystemAndPath($location);
183
 
184
        try {
185
            $filesystem->delete($path);
186
        } catch (UnableToDeleteFile $exception) {
187
            throw UnableToDeleteFile::atLocation($location, $exception->reason(), $exception);
188
        }
189
    }
190
 
191
    public function deleteDirectory(string $location): void
192
    {
193
        /** @var FilesystemOperator $filesystem */
194
        [$filesystem, $path] = $this->determineFilesystemAndPath($location);
195
 
196
        try {
197
            $filesystem->deleteDirectory($path);
198
        } catch (UnableToDeleteDirectory $exception) {
199
            throw UnableToDeleteDirectory::atLocation($location, $exception->reason(), $exception);
200
        }
201
    }
202
 
203
    public function createDirectory(string $location, array $config = []): void
204
    {
205
        /** @var FilesystemOperator $filesystem */
206
        [$filesystem, $path] = $this->determineFilesystemAndPath($location);
207
 
208
        try {
209
            $filesystem->createDirectory($path, $config);
210
        } catch (UnableToCreateDirectory $exception) {
211
            throw UnableToCreateDirectory::dueToFailure($location, $exception);
212
        }
213
    }
214
 
215
    public function move(string $source, string $destination, array $config = []): void
216
    {
217
        /** @var FilesystemOperator $sourceFilesystem */
218
        /* @var FilesystemOperator $destinationFilesystem */
219
        [$sourceFilesystem, $sourcePath] = $this->determineFilesystemAndPath($source);
220
        [$destinationFilesystem, $destinationPath] = $this->determineFilesystemAndPath($destination);
221
 
222
        $sourceFilesystem === $destinationFilesystem ? $this->moveInTheSameFilesystem(
223
            $sourceFilesystem,
224
            $sourcePath,
225
            $destinationPath,
226
            $source,
227
            $destination
228
        ) : $this->moveAcrossFilesystems($source, $destination, $config);
229
    }
230
 
231
    public function copy(string $source, string $destination, array $config = []): void
232
    {
233
        /** @var FilesystemOperator $sourceFilesystem */
234
        /* @var FilesystemOperator $destinationFilesystem */
235
        [$sourceFilesystem, $sourcePath] = $this->determineFilesystemAndPath($source);
236
        [$destinationFilesystem, $destinationPath] = $this->determineFilesystemAndPath($destination);
237
 
238
        $sourceFilesystem === $destinationFilesystem ? $this->copyInSameFilesystem(
239
            $sourceFilesystem,
240
            $sourcePath,
241
            $destinationPath,
242
            $source,
243
            $destination
244
        ) : $this->copyAcrossFilesystem(
245
            $config['visibility'] ?? null,
246
            $sourceFilesystem,
247
            $sourcePath,
248
            $destinationFilesystem,
249
            $destinationPath,
250
            $source,
251
            $destination
252
        );
253
    }
254
 
255
    public function publicUrl(string $path, array $config = []): string
256
    {
257
        /** @var FilesystemOperator $filesystem */
258
        [$filesystem, $path] = $this->determineFilesystemAndPath($path);
259
 
260
        if ( ! method_exists($filesystem, 'publicUrl')) {
261
            throw new UnableToGeneratePublicUrl(sprintf('%s does not support generating public urls.', $filesystem::class), $path);
262
        }
263
 
264
        return $filesystem->publicUrl($path, $config);
265
    }
266
 
267
    public function temporaryUrl(string $path, DateTimeInterface $expiresAt, array $config = []): string
268
    {
269
        /** @var FilesystemOperator $filesystem */
270
        [$filesystem, $path] = $this->determineFilesystemAndPath($path);
271
 
272
        if ( ! method_exists($filesystem, 'temporaryUrl')) {
273
            throw new UnableToGenerateTemporaryUrl(sprintf('%s does not support generating public urls.', $filesystem::class), $path);
274
        }
275
 
276
        return $filesystem->temporaryUrl($path, $expiresAt, $config);
277
    }
278
 
279
    public function checksum(string $path, array $config = []): string
280
    {
281
        /** @var FilesystemOperator $filesystem */
282
        [$filesystem, $path] = $this->determineFilesystemAndPath($path);
283
 
284
        if ( ! method_exists($filesystem, 'checksum')) {
285
            throw new UnableToProvideChecksum(sprintf('%s does not support providing checksums.', $filesystem::class), $path);
286
        }
287
 
288
        return $filesystem->checksum($path, $config);
289
    }
290
 
291
    private function mountFilesystems(array $filesystems): void
292
    {
293
        foreach ($filesystems as $key => $filesystem) {
294
            $this->guardAgainstInvalidMount($key, $filesystem);
295
            /* @var string $key */
296
            /* @var FilesystemOperator $filesystem */
297
            $this->mountFilesystem($key, $filesystem);
298
        }
299
    }
300
 
301
    /**
302
     * @param mixed $key
303
     * @param mixed $filesystem
304
     */
305
    private function guardAgainstInvalidMount($key, $filesystem): void
306
    {
307
        if ( ! is_string($key)) {
308
            throw UnableToMountFilesystem::becauseTheKeyIsNotValid($key);
309
        }
310
 
311
        if ( ! $filesystem instanceof FilesystemOperator) {
312
            throw UnableToMountFilesystem::becauseTheFilesystemWasNotValid($filesystem);
313
        }
314
    }
315
 
316
    private function mountFilesystem(string $key, FilesystemOperator $filesystem): void
317
    {
318
        $this->filesystems[$key] = $filesystem;
319
    }
320
 
321
    /**
322
     * @param string $path
323
     *
324
     * @return array{0:FilesystemOperator, 1:string}
325
     */
326
    private function determineFilesystemAndPath(string $path): array
327
    {
328
        if (strpos($path, '://') < 1) {
329
            throw UnableToResolveFilesystemMount::becauseTheSeparatorIsMissing($path);
330
        }
331
 
332
        /** @var string $mountIdentifier */
333
        /** @var string $mountPath */
334
        [$mountIdentifier, $mountPath] = explode('://', $path, 2);
335
 
336
        if ( ! array_key_exists($mountIdentifier, $this->filesystems)) {
337
            throw UnableToResolveFilesystemMount::becauseTheMountWasNotRegistered($mountIdentifier);
338
        }
339
 
340
        return [$this->filesystems[$mountIdentifier], $mountPath, $mountIdentifier];
341
    }
342
 
343
    private function copyInSameFilesystem(
344
        FilesystemOperator $sourceFilesystem,
345
        string $sourcePath,
346
        string $destinationPath,
347
        string $source,
348
        string $destination
349
    ): void {
350
        try {
351
            $sourceFilesystem->copy($sourcePath, $destinationPath);
352
        } catch (UnableToCopyFile $exception) {
353
            throw UnableToCopyFile::fromLocationTo($source, $destination, $exception);
354
        }
355
    }
356
 
357
    private function copyAcrossFilesystem(
358
        ?string $visibility,
359
        FilesystemOperator $sourceFilesystem,
360
        string $sourcePath,
361
        FilesystemOperator $destinationFilesystem,
362
        string $destinationPath,
363
        string $source,
364
        string $destination
365
    ): void {
366
        try {
367
            $visibility = $visibility ?? $sourceFilesystem->visibility($sourcePath);
368
            $stream = $sourceFilesystem->readStream($sourcePath);
369
            $destinationFilesystem->writeStream($destinationPath, $stream, compact('visibility'));
370
        } catch (UnableToRetrieveMetadata | UnableToReadFile | UnableToWriteFile $exception) {
371
            throw UnableToCopyFile::fromLocationTo($source, $destination, $exception);
372
        }
373
    }
374
 
375
    private function moveInTheSameFilesystem(
376
        FilesystemOperator $sourceFilesystem,
377
        string $sourcePath,
378
        string $destinationPath,
379
        string $source,
380
        string $destination
381
    ): void {
382
        try {
383
            $sourceFilesystem->move($sourcePath, $destinationPath);
384
        } catch (UnableToMoveFile $exception) {
385
            throw UnableToMoveFile::fromLocationTo($source, $destination, $exception);
386
        }
387
    }
388
 
389
    private function moveAcrossFilesystems(string $source, string $destination, array $config = []): void
390
    {
391
        try {
392
            $this->copy($source, $destination, $config);
393
            $this->delete($source);
394
        } catch (UnableToCopyFile | UnableToDeleteFile $exception) {
395
            throw UnableToMoveFile::fromLocationTo($source, $destination, $exception);
396
        }
397
    }
398
}