FileFinder::read()   A
last analyzed

Complexity

Conditions 3
Paths 4

Size

Total Lines 13
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 8
nc 4
nop 2
dl 0
loc 13
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 array $filesystems = [];
15
16
    /** @var string[] */
17
    protected array $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
    ): void {
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
     * @throws FilesystemException
46
     */
47
    public function fileExists(string $path, string $groupName = IFileFinder::DEFAULT_KEY): bool
48
    {
49
        return $this->findFilesystem($path, $groupName) !== null;
50
    }
51
52
    /**
53
     * @param string $path
54
     * @param string $groupName
55
     *
56
     * @return string|null
57
     * @throws UnableToReadFile
58
     * @throws FilesystemException
59
     */
60
    public function read(string $path, string $groupName = IFileFinder::DEFAULT_KEY): ?string
61
    {
62
        $filesystem = $this->findFilesystem($path, $groupName);
63
        if (!$filesystem) {
64
            return null;
65
        }
66
67
        try {
68
            $filesystemPath = $this->getFilesystemPath($filesystem, $path);
69
70
            return (string)$filesystem->read($filesystemPath);
71
        } catch (\Exception $e) {
72
            return null;
73
        }
74
    }
75
76
    /**
77
     * @param string $path
78
     * @param string $key
79
     *
80
     * @return FilesystemOperator|null
81
     * @throws FilesystemException
82
     */
83
    protected function findFilesystem(string $path, string $key): ?FilesystemOperator
84
    {
85
        $possibleKeys = $this->getPossibleKeys($path, $key);
86
        foreach ($possibleKeys as $rootKey) {
87
            foreach ($this->filesystems[$rootKey] as $filesystems) {
88
                foreach ($filesystems as $filesystem) {
89
                    $realPath = $this->getFilesystemPath($filesystem, $path);
90
                    if ($filesystem->fileExists($realPath)) {
91
                        return $filesystem;
92
                    }
93
                }
94
            }
95
        }
96
97
        return null;
98
    }
99
100
    /**
101
     * @param FilesystemOperator $filesystem
102
     * @param string             $path
103
     *
104
     * @return string
105
     */
106
    protected function getFilesystemPath(FilesystemOperator $filesystem, string $path): string
107
    {
108
        $rootKey = $this->filesystemKeys[spl_object_id($filesystem)];
109
        if ($rootKey === static::DEFAULT_KEY) {
110
            return $path;
111
        }
112
113
        $fixedPath = ltrim($path, '/');
114
        if (strpos($fixedPath, $rootKey) === 0) {
115
            return substr($fixedPath, strlen($rootKey));
116
        }
117
118
        return $path;
119
    }
120
121
    /**
122
     * @param string $path
123
     * @param string $key
124
     *
125
     * @return string[]
126
     */
127
    protected function getPossibleKeys(string $path, string $key): array
128
    {
129
        if ($key !== static::DEFAULT_KEY && isset($this->filesystems[$key])) {
130
            return [$key];
131
        }
132
133
        $fixedPath = ltrim($path, '/');
134
135
        $keys = [];
136
        foreach (array_keys($this->filesystems) as $rootKey) {
137
            if (substr($fixedPath, 0, strlen($rootKey)) === $rootKey) {
138
                $keys[] = $rootKey;
139
            }
140
        }
141
142
        if (isset($this->filesystems[static::DEFAULT_KEY])) {
143
            $keys[] = static::DEFAULT_KEY;
144
        }
145
146
        return $keys;
147
    }
148
}
149