Passed
Push — master ( 51cba3...dc9091 )
by Peter
03:11
created

FileFinder::fileExists()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 2
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace AbterPhp\Framework\Filesystem;
6
7
use League\Flysystem\FilesystemException;
8
use League\Flysystem\FilesystemOperator;
9
use League\Flysystem\UnableToReadFile;
10
11
class FileFinder implements IFileFinder
12
{
13
    /** @var FilesystemOperator[][][] */
14
    protected $filesystems = [];
15
16
    /** @var string[] */
17
    protected $filesystemKeys = [];
18
19
    /**
20
     * @param FilesystemOperator $filesystem
21
     * @param string             $key
22
     * @param int                $priority
23
     */
24
    public function registerFilesystem(
25
        FilesystemOperator $filesystem,
26
        string $key = IFileFinder::DEFAULT_KEY,
27
        int $priority = -1
28
    ) {
29
        if (empty($this->filesystems[$key][$priority])) {
30
            $this->filesystems[$key][$priority] = [];
31
        }
32
33
        $this->filesystems[$key][$priority][] = $filesystem;
34
35
        krsort($this->filesystems[$key]);
36
37
        $this->filesystemKeys[spl_object_id($filesystem)] = $key;
38
    }
39
40
    /**
41
     * @param string $path
42
     * @param string $groupName
43
     *
44
     * @return bool
45
     */
46
    public function fileExists(string $path, string $groupName = IFileFinder::DEFAULT_KEY): bool
47
    {
48
        return $this->findFilesystem($path, $groupName) !== null;
49
    }
50
51
    /**
52
     * @param string $path
53
     * @param string $key
54
     *
55
     * @return string|null
56
     * @throws UnableToReadFile
57
     * @throws FilesystemException
58
     */
59
    public function read(string $path, string $key = IFileFinder::DEFAULT_KEY): ?string
60
    {
61
        $filesystem = $this->findFilesystem($path, $key);
62
        if (!$filesystem) {
63
            return null;
64
        }
65
66
        try {
67
            $filesystemPath = $this->getFilesystemPath($filesystem, $path);
68
69
            return (string)$filesystem->read($filesystemPath);
70
        } catch (\Exception $e) {
71
            return null;
72
        }
73
    }
74
75
    /**
76
     * @param string $path
77
     * @param string $key
78
     *
79
     * @return FilesystemOperator|null
80
     */
81
    protected function findFilesystem(string $path, string $key): ?FilesystemOperator
82
    {
83
        $possibleKeys = $this->getPossibleKeys($path, $key);
84
        foreach ($possibleKeys as $rootKey) {
85
            foreach ($this->filesystems[$rootKey] as $filesystems) {
86
                foreach ($filesystems as $filesystem) {
87
                    $realPath = $this->getFilesystemPath($filesystem, $path);
88
                    if ($filesystem->fileExists($realPath)) {
89
                        return $filesystem;
90
                    }
91
                }
92
            }
93
        }
94
95
        return null;
96
    }
97
98
    /**
99
     * @param FilesystemOperator $filesystem
100
     * @param string             $path
101
     *
102
     * @return string
103
     */
104
    protected function getFilesystemPath(FilesystemOperator $filesystem, string $path): string
105
    {
106
        $rootKey = $this->filesystemKeys[spl_object_id($filesystem)];
107
        if ($rootKey === static::DEFAULT_KEY) {
108
            return $path;
109
        }
110
111
        $fixedPath = ltrim($path, '/');
112
        if (strpos($fixedPath, $rootKey) === 0) {
113
            return substr($fixedPath, strlen($rootKey));
114
        }
115
116
        return $path;
117
    }
118
119
    /**
120
     * @param string $path
121
     * @param string $key
122
     *
123
     * @return string[]
124
     */
125
    protected function getPossibleKeys(string $path, string $key): array
126
    {
127
        if ($key !== static::DEFAULT_KEY && isset($this->filesystems[$key])) {
128
            return [$key];
129
        }
130
131
        $fixedPath = ltrim($path, '/');
132
133
        $keys = [];
134
        foreach (array_keys($this->filesystems) as $rootKey) {
135
            if (substr($fixedPath, 0, strlen($rootKey)) === $rootKey) {
136
                $keys[] = $rootKey;
137
            }
138
        }
139
140
        if (isset($this->filesystems[static::DEFAULT_KEY])) {
141
            $keys[] = static::DEFAULT_KEY;
142
        }
143
144
        return $keys;
145
    }
146
}
147