Passed
Push — master ( b5fd53...298c35 )
by Peter
02:38
created

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