Completed
Push — master ( de9752...8b76b3 )
by Cedric
01:40
created

FlysystemDriver::deleteFile()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 3
Bugs 0 Features 1
Metric Value
c 3
b 0
f 1
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 1
crap 1
1
<?php
2
3
namespace CedricZiel\FalFlysystem\Fal;
4
5
use League\Flysystem\Adapter\Local;
6
use League\Flysystem\AdapterInterface;
7
use League\Flysystem\Config;
8
use League\Flysystem\FilesystemInterface;
9
use TYPO3\CMS\Core\Resource\Driver\AbstractHierarchicalFilesystemDriver;
10
use TYPO3\CMS\Core\Resource\ResourceStorage;
11
use TYPO3\CMS\Core\Type\File\FileInfo;
12
use TYPO3\CMS\Core\Utility\GeneralUtility;
13
use TYPO3\CMS\Core\Utility\PathUtility;
14
use TYPO3\CMS\Extbase\Utility\DebuggerUtility;
15
16
/**
17
 * Class FlysystemDriver
18
 * @package CedricZiel\FalFlysystem\Fal
19
 */
20
abstract class FlysystemDriver extends AbstractHierarchicalFilesystemDriver
21
{
22
    /**
23
     * @var FilesystemInterface
24
     */
25
    protected $filesystem;
26
27
    /**
28
     * @var AdapterInterface
29
     */
30
    protected $adapter;
31
32
    /**
33
     * @var string
34
     */
35
    protected $entryPath;
36
37
    /**
38
     * FlysystemDriver constructor.
39
     * @param array $configuration
40
     */
41 48
    public function __construct(array $configuration = [])
42
    {
43 48
        parent::__construct($configuration);
44
        // The capabilities default of this driver. See CAPABILITY_* constants for possible values
45 48
        $this->capabilities =
46 16
            ResourceStorage::CAPABILITY_BROWSABLE
47 48
            | ResourceStorage::CAPABILITY_PUBLIC
48 48
            | ResourceStorage::CAPABILITY_WRITABLE;
49 48
    }
50
51
    /**
52
     * Processes the configuration for this driver.
53
     * @return void
54
     */
55
    public function processConfiguration()
56
    {
57
        $this->entryPath = $this->configuration['path'];
58
    }
59
60
    /**
61
     * Merges the capabilities merged by the user at the storage
62
     * configuration into the actual capabilities of the driver
63
     * and returns the result.
64
     *
65
     * @param int $capabilities
66
     * @return int
67
     */
68
    public function mergeConfigurationCapabilities($capabilities)
69
    {
70
        // TODO: Implement mergeConfigurationCapabilities() method.
71
    }
72
73
    /**
74
     * Returns the identifier of the root level folder of the storage.
75
     *
76
     * @return string
77
     */
78
    public function getRootLevelFolder()
79
    {
80
        return '/';
81
    }
82
83
    /**
84
     * Returns the identifier of the default folder new files should be put into.
85
     *
86
     * @return string
87
     */
88 3
    public function getDefaultFolder()
89
    {
90 3
        $identifier = '/user_upload/';
91 3
        $createFolder = !$this->folderExists($identifier);
92 3
        if (true === $createFolder) {
93 3
            $identifier = $this->createFolder('user_upload');
94 2
        }
95 3
        return $identifier;
96
    }
97
98
    /**
99
     * Checks if a folder exists.
100
     *
101
     * @param string $folderIdentifier
102
     * @return bool
103
     */
104 6
    public function folderExists($folderIdentifier)
105
    {
106 6
        if ('/' === $folderIdentifier) {
107
            return true;
108
        } else {
109 6
            return ($this->filesystem->has('/' . $folderIdentifier) && $this->filesystem->get('/' . $folderIdentifier)->isDir());
110
        }
111
    }
112
113
    /**
114
     * Creates a folder, within a parent folder.
115
     * If no parent folder is given, a root level folder will be created
116
     *
117
     * @param string $newFolderName
118
     * @param string $parentFolderIdentifier
119
     * @param bool $recursive
120
     * @return string the Identifier of the new folder
121
     */
122 9
    public function createFolder($newFolderName, $parentFolderIdentifier = '', $recursive = false)
123
    {
124 9
        $parentFolderIdentifier = $this->canonicalizeAndCheckFolderIdentifier($parentFolderIdentifier);
125 9
        $newFolderName = trim($newFolderName, '/');
126 9
        if (false === $recursive) {
127 9
            $newFolderName = $this->sanitizeFileName($newFolderName);
128 9
            $newIdentifier = $parentFolderIdentifier . $newFolderName . '/';
129 9
            $this->filesystem->createDir($newIdentifier);
130 6
        } else {
131
            $parts = GeneralUtility::trimExplode('/', $newFolderName);
132
            $parts = array_map(array($this, 'sanitizeFileName'), $parts);
133
            $newFolderName = implode('/', $parts);
134
            $newIdentifier = $parentFolderIdentifier . $newFolderName . '/';
135
        }
136 9
        return $newIdentifier;
137
    }
138
139
    /**
140
     * Returns the public URL to a file.
141
     * Either fully qualified URL or relative to PATH_site (rawurlencoded).
142
     *
143
     * @param string $identifier
144
     * @return string
145
     */
146
    public function getPublicUrl($identifier)
147
    {
148
        return '/';
149
    }
150
151
    /**
152
     * Renames a folder in this storage.
153
     *
154
     * @param string $folderIdentifier
155
     * @param string $newName
156
     * @return array A map of old to new file identifiers of all affected resources
157
     */
158 3
    public function renameFolder($folderIdentifier, $newName)
159
    {
160 3
        $renameResult = $this->filesystem->rename($folderIdentifier, $newName);
161
162 3
        if (true === $renameResult) {
163 3
            return [$folderIdentifier => $newName];
164
        } else {
165
            return [$folderIdentifier => $folderIdentifier];
166
        }
167
    }
168
169
    /**
170
     * Removes a folder in filesystem.
171
     *
172
     * @param string $folderIdentifier
173
     * @param bool $deleteRecursively
174
     * @return bool
175
     */
176
    public function deleteFolder($folderIdentifier, $deleteRecursively = false)
177
    {
178
        return $this->filesystem->deleteDir($folderIdentifier);
179
    }
180
181
    /**
182
     * Checks if a file exists.
183
     *
184
     * @param string $fileIdentifier
185
     * @return bool
186
     */
187 9
    public function fileExists($fileIdentifier)
188
    {
189 9
        if ($this->filesystem->has($fileIdentifier) && !$this->filesystem->get($fileIdentifier)->isDir()) {
190 9
            return true;
191
        }
192 6
        return false;
193
    }
194
195
    /**
196
     * Checks if a folder contains files and (if supported) other folders.
197
     *
198
     * @param string $folderIdentifier
199
     * @return bool TRUE if there are no files and folders within $folder
200
     */
201 3
    public function isFolderEmpty($folderIdentifier)
202
    {
203 3
        return 0 === count($this->filesystem->listContents($folderIdentifier));
204
    }
205
206
    /**
207
     * Adds a file from the local server hard disk to a given path in TYPO3s
208
     * virtual file system. This assumes that the local file exists, so no
209
     * further check is done here! After a successful the original file must
210
     * not exist anymore.
211
     *
212
     * @param string $localFilePath (within PATH_site)
213
     * @param string $targetFolderIdentifier
214
     * @param string $newFileName optional, if not given original name is used
215
     * @param bool $removeOriginal if set the original file will be removed
216
     *                                after successful operation
217
     * @return string the identifier of the new file
218
     */
219 3
    public function addFile($localFilePath, $targetFolderIdentifier, $newFileName = '', $removeOriginal = true)
220
    {
221 3
        $localFilePath = $this->canonicalizeAndCheckFilePath($localFilePath);
222 3
        $newFileName = $this->sanitizeFileName($newFileName !== '' ? $newFileName : PathUtility::basename($localFilePath));
223 3
        $newFileIdentifier = $this->canonicalizeAndCheckFolderIdentifier($targetFolderIdentifier) . $newFileName;
224
225 3
        $targetPath = ltrim($newFileIdentifier, '/');
226
227 3
        $content = file_get_contents($localFilePath);
228
229 3
        if ($removeOriginal) {
230
            if (is_uploaded_file($localFilePath)) {
231
                $result = $this->filesystem->put($targetPath, $content);
232
            } else {
233
                $result = rename($localFilePath, $targetPath);
234
            }
235
            unlink($localFilePath);
236
        } else {
237 3
            $result = $this->filesystem->put($targetPath, $content);
238
        }
239 3
        if ($result === false || !$this->filesystem->has($targetPath)) {
240
            throw new \RuntimeException('Adding file ' . $localFilePath . ' at ' . $newFileIdentifier . ' failed.');
241
        }
242 3
        clearstatcache();
243 3
        return $newFileIdentifier;
244
    }
245
246
    /**
247
     * Creates a new (empty) file and returns the identifier.
248
     *
249
     * @param string $fileName
250
     * @param string $parentFolderIdentifier
251
     * @return string
252
     */
253
    public function createFile($fileName, $parentFolderIdentifier)
254
    {
255
        // TODO: Implement createFile() method.
256
        DebuggerUtility::var_dump([
257
            '$fileName' => $fileName,
258
            '$parentFolderIdentifier' => $parentFolderIdentifier
259
        ], 'createFile');
260
    }
261
262
    /**
263
     * Copies a file *within* the current storage.
264
     * Note that this is only about an inner storage copy action,
265
     * where a file is just copied to another folder in the same storage.
266
     *
267
     * @param string $fileIdentifier
268
     * @param string $targetFolderIdentifier
269
     * @param string $fileName
270
     * @return string the Identifier of the new file
271
     */
272
    public function copyFileWithinStorage($fileIdentifier, $targetFolderIdentifier, $fileName)
273
    {
274
        // TODO: Implement copyFileWithinStorage() method.
275
        DebuggerUtility::var_dump([
276
            '$fileIdentifier' => $fileIdentifier,
277
            '$targetFolderIdentifier' => $targetFolderIdentifier,
278
            '$fileName' => $fileName
279
        ], 'copyFileWithinStorage');
280
    }
281
282
    /**
283
     * Renames a file in this storage.
284
     *
285
     * @param string $fileIdentifier
286
     * @param string $newName The target path (including the file name!)
287
     * @return string The identifier of the file after renaming
288
     */
289
    public function renameFile($fileIdentifier, $newName)
290
    {
291
        // TODO: Implement renameFile() method.
292
        DebuggerUtility::var_dump([
293
            '$fileIdentifier' => $fileIdentifier,
294
            '$newName' => $newName
295
        ], 'renameFile');
296
    }
297
298
    /**
299
     * Replaces a file with file in local file system.
300
     *
301
     * @param string $fileIdentifier
302
     * @param string $localFilePath
303
     * @return bool TRUE if the operation succeeded
304
     */
305
    public function replaceFile($fileIdentifier, $localFilePath)
306
    {
307
        // TODO: Implement replaceFile() method.
308
        DebuggerUtility::var_dump([
309
            '$fileIdentifier' => $fileIdentifier,
310
            '$localFilePath' => $localFilePath
311
        ], 'replaceFile');
312
    }
313
314
    /**
315
     * Removes a file from the filesystem. This does not check if the file is
316
     * still used or if it is a bad idea to delete it for some other reason
317
     * this has to be taken care of in the upper layers (e.g. the Storage)!
318
     *
319
     * @param string $fileIdentifier
320
     * @return bool TRUE if deleting the file succeeded
321
     */
322 3
    public function deleteFile($fileIdentifier)
323
    {
324 3
        return $this->filesystem->delete($fileIdentifier);
325
    }
326
327
    /**
328
     * Creates a hash for a file.
329
     *
330
     * @param string $fileIdentifier
331
     * @param string $hashAlgorithm The hash algorithm to use
332
     * @return string
333
     */
334
    public function hash($fileIdentifier, $hashAlgorithm)
335
    {
336
        // TODO: Implement hash() method.
337
    }
338
339
    /**
340
     * Moves a file *within* the current storage.
341
     * Note that this is only about an inner-storage move action,
342
     * where a file is just moved to another folder in the same storage.
343
     *
344
     * @param string $fileIdentifier
345
     * @param string $targetFolderIdentifier
346
     * @param string $newFileName
347
     * @return string
348
     */
349
    public function moveFileWithinStorage($fileIdentifier, $targetFolderIdentifier, $newFileName)
350
    {
351
        // TODO: Implement moveFileWithinStorage() method.
352
    }
353
354
    /**
355
     * Folder equivalent to moveFileWithinStorage().
356
     *
357
     * @param string $sourceFolderIdentifier
358
     * @param string $targetFolderIdentifier
359
     * @param string $newFolderName
360
     * @return array All files which are affected, map of old => new file identifiers
361
     */
362
    public function moveFolderWithinStorage($sourceFolderIdentifier, $targetFolderIdentifier, $newFolderName)
363
    {
364
        // TODO: Implement moveFolderWithinStorage() method.
365
    }
366
367
    /**
368
     * Folder equivalent to copyFileWithinStorage().
369
     *
370
     * @param string $sourceFolderIdentifier
371
     * @param string $targetFolderIdentifier
372
     * @param string $newFolderName
373
     * @return bool
374
     */
375
    public function copyFolderWithinStorage($sourceFolderIdentifier, $targetFolderIdentifier, $newFolderName)
376
    {
377
        // TODO: Implement copyFolderWithinStorage() method.
378
    }
379
380
    /**
381
     * Returns the contents of a file. Beware that this requires to load the
382
     * complete file into memory and also may require fetching the file from an
383
     * external location. So this might be an expensive operation (both in terms
384
     * of processing resources and money) for large files.
385
     *
386
     * @param string $fileIdentifier
387
     * @return string The file contents
388
     */
389 3
    public function getFileContents($fileIdentifier)
390
    {
391 3
        return $this->filesystem->read($fileIdentifier);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The expression $this->filesystem->read($fileIdentifier); of type string|false adds false to the return on line 391 which is incompatible with the return type declared by the interface TYPO3\CMS\Core\Resource\...erface::getFileContents of type string. It seems like you forgot to handle an error condition.
Loading history...
392
    }
393
394
    /**
395
     * Sets the contents of a file to the specified value.
396
     *
397
     * @param string $fileIdentifier
398
     * @param string $contents
399
     * @return int The number of bytes written to the file
400
     */
401 3
    public function setFileContents($fileIdentifier, $contents)
402
    {
403 3
        $this->filesystem->put($fileIdentifier, $contents);
404
405 3
        return $this->filesystem->getSize($fileIdentifier);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The expression $this->filesystem->getSize($fileIdentifier); of type integer|false adds false to the return on line 405 which is incompatible with the return type declared by the interface TYPO3\CMS\Core\Resource\...erface::setFileContents of type integer. It seems like you forgot to handle an error condition.
Loading history...
406
    }
407
408
    /**
409
     * Checks if a file inside a folder exists
410
     *
411
     * @param string $fileName
412
     * @param string $folderIdentifier
413
     * @return bool
414
     */
415 3
    public function fileExistsInFolder($fileName, $folderIdentifier)
416
    {
417 3
        $identifier = $folderIdentifier . '/' . $fileName;
418 3
        $identifier = $this->canonicalizeAndCheckFileIdentifier($identifier);
419 3
        return $this->fileExists($identifier);
420
    }
421
422
    /**
423
     * Checks if a folder inside a folder exists.
424
     *
425
     * @param string $folderName
426
     * @param string $folderIdentifier
427
     * @return bool
428
     */
429 3
    public function folderExistsInFolder($folderName, $folderIdentifier)
430
    {
431 3
        $identifier = $folderIdentifier . '/' . $folderName;
432 3
        $identifier = $this->canonicalizeAndCheckFolderIdentifier($identifier);
433 3
        return $this->folderExists($identifier);
434
    }
435
436
    /**
437
     * Returns a path to a local copy of a file for processing it. When changing the
438
     * file, you have to take care of replacing the current version yourself!
439
     *
440
     * @param string $fileIdentifier
441
     * @param bool $writable Set this to FALSE if you only need the file for read
442
     *                       operations. This might speed up things, e.g. by using
443
     *                       a cached local version. Never modify the file if you
444
     *                       have set this flag!
445
     * @return string The path to the file on the local disk
446
     */
447
    public function getFileForLocalProcessing($fileIdentifier, $writable = true)
448
    {
449
        // TODO: Implement getFileForLocalProcessing() method.
450
        DebuggerUtility::var_dump([
451
            '$fileIdentifier' => $fileIdentifier,
452
            '$writable' => $writable,
453
        ], 'getFileForLocalProcessing');
454
    }
455
456
    /**
457
     * Returns the permissions of a file/folder as an array
458
     * (keys r, w) of boolean flags
459
     *
460
     * @param string $identifier
461
     * @return array
462
     */
463
    public function getPermissions($identifier)
464
    {
465
        return array(
466
            'r' => true,
467
            'w' => true,
468
        );
469
    }
470
471
    /**
472
     * Directly output the contents of the file to the output
473
     * buffer. Should not take care of header files or flushing
474
     * buffer before. Will be taken care of by the Storage.
475
     *
476
     * @param string $identifier
477
     * @return void
478
     */
479
    public function dumpFileContents($identifier)
480
    {
481
        // TODO: Implement dumpFileContents() method.
482
        DebuggerUtility::var_dump([
483
            '$identifier' => $identifier,
484
        ], 'dumpFileContents');
485
    }
486
487
    /**
488
     * Checks if a given identifier is within a container, e.g. if
489
     * a file or folder is within another folder.
490
     * This can e.g. be used to check for web-mounts.
491
     *
492
     * Hint: this also needs to return TRUE if the given identifier
493
     * matches the container identifier to allow access to the root
494
     * folder of a filemount.
495
     *
496
     * @param string $folderIdentifier
497
     * @param string $identifier identifier to be checked against $folderIdentifier
498
     * @return bool TRUE if $content is within or matches $folderIdentifier
499
     */
500
    public function isWithin($folderIdentifier, $identifier)
501
    {
502
        $folderIdentifier = $this->canonicalizeAndCheckFileIdentifier($folderIdentifier);
503
        $entryIdentifier = $this->canonicalizeAndCheckFileIdentifier($identifier);
504
        if ($folderIdentifier === $entryIdentifier) {
505
            return true;
506
        }
507
        // File identifier canonicalization will not modify a single slash so
508
        // we must not append another slash in that case.
509
        if ($folderIdentifier !== '/') {
510
            $folderIdentifier .= '/';
511
        }
512
        return GeneralUtility::isFirstPartOfStr($entryIdentifier, $folderIdentifier);
513
    }
514
515
    /**
516
     * Returns information about a file.
517
     *
518
     * @param string $fileIdentifier
519
     * @param array $propertiesToExtract Array of properties which are be extracted
520
     *                                   If empty all will be extracted
521
     * @return array
522
     */
523
    public function getFileInfoByIdentifier($fileIdentifier, array $propertiesToExtract = [])
524
    {
525
        $relativeDriverPath = ltrim($fileIdentifier, '/');
526
        if (!$this->filesystem->has($relativeDriverPath) || !$this->filesystem->get($relativeDriverPath)->isFile()) {
527
            throw new \InvalidArgumentException('File ' . $fileIdentifier . ' does not exist.', 1314516809);
528
        }
529
        $dirPath = PathUtility::dirname($fileIdentifier);
530
        $dirPath = $this->canonicalizeAndCheckFolderIdentifier($dirPath);
531
        return $this->extractFileInformation($relativeDriverPath, $dirPath, $propertiesToExtract);
532
    }
533
534
    /**
535
     * Returns information about a file.
536
     *
537
     * @param string $folderIdentifier
538
     * @return array
539
     */
540 3
    public function getFolderInfoByIdentifier($folderIdentifier)
541
    {
542 3
        $folderIdentifier = $this->canonicalizeAndCheckFolderIdentifier($folderIdentifier);
543
544
        return [
545 3
            'identifier' => $folderIdentifier,
546 3
            'name' => PathUtility::basename($folderIdentifier),
547 3
            'storage' => $this->storageUid
548 2
        ];
549
    }
550
551
    /**
552
     * Returns the identifier of a file inside the folder
553
     *
554
     * @param string $fileName
555
     * @param string $folderIdentifier
556
     * @return string file identifier
557
     */
558
    public function getFileInFolder($fileName, $folderIdentifier)
559
    {
560
        return $this->canonicalizeAndCheckFileIdentifier($folderIdentifier . '/' . $fileName);
561
    }
562
563
    /**
564
     * Returns a list of files inside the specified path
565
     *
566
     * @param string $folderIdentifier
567
     * @param int $start
568
     * @param int $numberOfItems
569
     * @param bool $recursive
570
     * @param array $filenameFilterCallbacks callbacks for filtering the items
571
     * @param string $sort Property name used to sort the items.
572
     *                     Among them may be: '' (empty, no sorting), name,
573
     *                     fileext, size, tstamp and rw.
574
     *                     If a driver does not support the given property, it
575
     *                     should fall back to "name".
576
     * @param bool $sortRev TRUE to indicate reverse sorting (last to first)
577
     * @return array of FileIdentifiers
578
     */
579 3
    public function getFilesInFolder(
580
        $folderIdentifier,
581
        $start = 0,
582
        $numberOfItems = 0,
583
        $recursive = false,
584
        array $filenameFilterCallbacks = [],
585
        $sort = '',
586
        $sortRev = false
587
    ) {
588 3
        $calculatedFolderIdentifier = ltrim($this->canonicalizeAndCheckFolderIdentifier($folderIdentifier), '/');
589 3
        $contents = $this->filesystem->listContents($calculatedFolderIdentifier);
590 3
        $files = [];
591
592
        /*
593
         * Filter directories
594
         */
595 3
        foreach ($contents as $directoryItem) {
596 3
            if ('file' === $directoryItem['type']) {
597 3
                $files['/' . $directoryItem['path']] = '/' . $directoryItem['path'];
598 2
            }
599 2
        }
600
601 3
        return $files;
602
    }
603
604
    /**
605
     * Returns the identifier of a folder inside the folder
606
     *
607
     * @param string $folderName The name of the target folder
608
     * @param string $folderIdentifier
609
     * @return string folder identifier
610
     */
611 3
    public function getFolderInFolder($folderName, $folderIdentifier)
612
    {
613 3
        $folderIdentifier = $this->canonicalizeAndCheckFolderIdentifier($folderIdentifier . '/' . $folderName);
614 3
        return $folderIdentifier;
615
    }
616
617
    /**
618
     * Returns a list of folders inside the specified path
619
     *
620
     * @param string $folderIdentifier
621
     * @param int $start
622
     * @param int $numberOfItems
623
     * @param bool $recursive
624
     * @param array $folderNameFilterCallbacks callbacks for filtering the items
625
     * @param string $sort Property name used to sort the items.
626
     *                     Among them may be: '' (empty, no sorting), name,
627
     *                     fileext, size, tstamp and rw.
628
     *                     If a driver does not support the given property, it
629
     *                     should fall back to "name".
630
     * @param bool $sortRev TRUE to indicate reverse sorting (last to first)
631
     * @return array of Folder Identifier
632
     * @TODO: Implement pagination with $start and $numberOfItems
633
     * @TODO: Implement directory filter callbacks
634
     * @TODO: Implement sorting
635
     */
636 3
    public function getFoldersInFolder(
637
        $folderIdentifier,
638
        $start = 0,
639
        $numberOfItems = 0,
640
        $recursive = false,
641
        array $folderNameFilterCallbacks = [],
642
        $sort = '',
643
        $sortRev = false
644
    ) {
645 3
        $calculatedFolderIdentifier = ltrim($this->canonicalizeAndCheckFolderIdentifier($folderIdentifier), '/');
646 3
        $contents = $this->filesystem->listContents($calculatedFolderIdentifier);
647 3
        $directories = [];
648
649
        /*
650
         * Filter directories
651
         */
652 3
        foreach ($contents as $directoryItem) {
653 3
            if ('dir' === $directoryItem['type']) {
654 3
                $directories['/' . $directoryItem['path']]
655 3
                    = '/' . $directoryItem['path'];
656 2
            }
657 2
        }
658
659 3
        return $directories;
660
    }
661
662
    /**
663
     * Returns the number of files inside the specified path
664
     *
665
     * @param string $folderIdentifier
666
     * @param bool $recursive
667
     * @param array $filenameFilterCallbacks callbacks for filtering the items
668
     * @return int Number of files in folder
669
     * @TODO: Implement recursive count
670
     * @TODO: Implement filename filtering
671
     */
672
    public function countFilesInFolder($folderIdentifier, $recursive = false, array $filenameFilterCallbacks = [])
673
    {
674
675
        return count($this->getFilesInFolder($folderIdentifier, 0, 0, $recursive, $filenameFilterCallbacks));
676
    }
677
678
    /**
679
     * Returns the number of folders inside the specified path
680
     *
681
     * @param string $folderIdentifier
682
     * @param bool $recursive
683
     * @param array $folderNameFilterCallbacks callbacks for filtering the items
684
     * @return int Number of folders in folder
685
     */
686 3
    public function countFoldersInFolder($folderIdentifier, $recursive = false, array $folderNameFilterCallbacks = [])
687
    {
688 3
        $count = 0;
689 3
        $filesystemRelativeIdentifier = ltrim($folderIdentifier, '/');
690 3
        $directoryListing = $this->filesystem->listContents($filesystemRelativeIdentifier);
691 3
        foreach ($directoryListing as $entry) {
692 3
            if ('dir' === $entry['type']) {
693 3
                $count++;
694 2
            }
695 2
        }
696
697 3
        return $count;
698
    }
699
700
    /**
701
     * Extracts information about a file from the filesystem.
702
     *
703
     * @param string $filePath The absolute path to the file
704
     * @param string $containerPath The relative path to the file's container
705
     * @param array $propertiesToExtract array of properties which should be returned, if empty all will be extracted
706
     * @return array
707
     */
708
    protected function extractFileInformation($filePath, $containerPath, array $propertiesToExtract = array())
709
    {
710
        if (empty($propertiesToExtract)) {
711
            $propertiesToExtract = array(
712
                'size',
713
                'atime',
714
                'atime',
715
                'mtime',
716
                'ctime',
717
                'mimetype',
718
                'name',
719
                'identifier',
720
                'identifier_hash',
721
                'storage',
722
                'folder_hash'
723
            );
724
        }
725
        $fileInformation = array();
726
        foreach ($propertiesToExtract as $property) {
727
            $fileInformation[$property] = $this->getSpecificFileInformation($filePath, $containerPath, $property);
728
        }
729
        return $fileInformation;
730
    }
731
732
    /**
733
     * Extracts a specific FileInformation from the FileSystems.
734
     *
735
     * @param string $fileIdentifier
736
     * @param string $containerPath
737
     * @param string $property
738
     *
739
     * @return bool|int|string
740
     * @throws \InvalidArgumentException
741
     */
742
    public function getSpecificFileInformation($fileIdentifier, $containerPath, $property)
743
    {
744
        $identifier = $this->canonicalizeAndCheckFileIdentifier($containerPath . PathUtility::basename($fileIdentifier));
745
        $file = $this->filesystem->getMetadata($fileIdentifier);
746
747
        switch ($property) {
748
            case 'size':
749
                return $file['size'];
750
            case 'atime':
751
                return $file['timestamp'];
752
            case 'mtime':
753
                return $file['timestamp'];
754
            case 'ctime':
755
                return $file['timestamp'];
756
            case 'name':
757
                return PathUtility::basename($fileIdentifier);
758
            case 'mimetype':
759
                return 'application/octet-stream';
760
            case 'identifier':
761
                return $identifier;
762
            case 'storage':
763
                return $this->storageUid;
764
            case 'identifier_hash':
765
                return $this->hashIdentifier($identifier);
766
            case 'folder_hash':
767
                return $this->hashIdentifier($this->getParentFolderIdentifierOfIdentifier($identifier));
768
            default:
769
                throw new \InvalidArgumentException(sprintf('The information "%s" is not available.', $property));
770
        }
771
    }
772
}
773