Passed
Push — master ( 5635f8...3ce074 )
by Peter
02:21
created

Flysystem::setIsFlushable()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 5
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace AbterPhp\Framework\Assets\CacheManager;
6
7
use League\Flysystem\FileExistsException;
8
use League\Flysystem\FilesystemInterface;
9
10
class Flysystem implements ICacheManager
11
{
12
    const ERROR_FILESYSTEM_NOT_FOUND = 'filesystem not found';
13
14
    /** @var FilesystemInterface[] */
15
    protected $filesystems = [];
16
17
    /** @var callable[] callables that can check if a filesystem is suited to be used for a given path */
18
    protected $pathCheckers = [];
19
20
    /** @var callable used to decide if a file can be deleted or not */
21
    protected $isFlushable;
22
23
    public function __construct()
24
    {
25
        $this->isFlushable = function (array $obj) {
26
            if ($obj['basename'] === '.gitignore') {
27
                return false;
28
            }
29
30
            if (!empty($obj['extension']) && strtolower($obj['extension']) === 'php') {
31
                return false;
32
            }
33
34
            return true;
35
        };
36
    }
37
38
    /**
39
     * @param callable $isFlushable must expect an array containing file information and return a true if a file is
40
     *                              flushable
41
     * @return $this
42
     */
43
    public function setIsFlushable(callable $isFlushable): ICacheManager
44
    {
45
        $this->isFlushable = $isFlushable;
46
47
        return $this;
48
    }
49
50
    /**
51
     * @param string $path
52
     *
53
     * @return FilesystemInterface
54
     */
55
    protected function getFilesystem(string $path): FilesystemInterface
56
    {
57
        foreach ($this->filesystems as $priority => $filesystem) {
58
            if (empty($this->pathCheckers[$priority])) {
59
                return $filesystem;
60
            }
61
62
            if (call_user_func($this->pathCheckers[$priority], $path)) {
63
                return $filesystem;
64
            }
65
        }
66
67
        throw new \InvalidArgumentException(static::ERROR_FILESYSTEM_NOT_FOUND);
68
    }
69
70
    /**
71
     * @param FilesystemInterface $filesystem
72
     * @param callable|null       $checker
73
     * @param int|null            $priority
74
     */
75
    public function registerFilesystem(FilesystemInterface $filesystem, callable $checker = null, ?int $priority = null)
76
    {
77
        $priority = $priority === null ? count($this->filesystems) * -1 : $priority;
78
79
        $this->filesystems[$priority]  = $filesystem;
80
        $this->pathCheckers[$priority] = $checker;
81
82
        krsort($this->filesystems);
83
        krsort($this->pathCheckers);
84
    }
85
86
    /**
87
     * @param string $path
88
     * @param string $groupName
89
     *
90
     * @return bool
91
     */
92
    public function has(string $path): bool
93
    {
94
        $fs = $this->getFilesystem($path);
95
96
        return $fs->has($path);
97
    }
98
99
    /**
100
     * @param string $path
101
     *
102
     * @return string|null
103
     * @throws \League\Flysystem\FileNotFoundException
104
     */
105
    public function read(string $path): ?string
106
    {
107
        $fs = $this->getFilesystem($path);
108
109
        if (!$fs->has($path)) {
110
            return null;
111
        }
112
113
        $content = $fs->read($path);
114
        if ($content === false) {
115
            return null;
116
        }
117
118
        return (string)$content;
119
    }
120
121
    /**
122
     * @param string $path
123
     * @param string $content
124
     * @param string $force
125
     *
126
     * @return bool
127
     * @throws \League\Flysystem\FileExistsException
128
     */
129
    public function write(string $path, string $content, bool $force = true): bool
130
    {
131
        $fs = $this->getFilesystem($path);
132
133
        try {
134
            return (bool)$fs->write($path, $content);
135
        } catch (FileExistsException $e) {
136
            if ($force) {
137
                $fs->delete($path);
138
139
                return (bool)$fs->write($path, $content);
140
            }
141
        }
142
143
        return false;
144
    }
145
146
    /**
147
     * @param string $path
148
     *
149
     * @return string
150
     * @throws \League\Flysystem\FileNotFoundException
151
     */
152
    public function getWebPath(string $path): string
153
    {
154
        $fs = $this->getFilesystem($path);
155
156
        $timestamp = (string)$fs->getTimestamp($path);
157
158
        $path = '/' . ltrim($path, '/');
159
        $rand = substr(md5($timestamp), 0, 5);
160
161
        return sprintf('%s?%s', $path, $rand);
162
    }
163
164
    /**
165
     * @throws \League\Flysystem\FileNotFoundException
166
     */
167
    public function flush()
168
    {
169
        foreach ($this->filesystems as $filesystem) {
170
            $objects = $filesystem->listContents('/', false);
171
172
            foreach ($objects as $object) {
173
                if (!call_user_func($this->isFlushable, $object)) {
174
                    continue;
175
                }
176
                $filesystem->delete($object['path']);
177
            }
178
        }
179
    }
180
}
181