Passed
Push — master ( 5a4455...a3a054 )
by Pol
02:30
created

PhpVfs   A

Complexity

Total Complexity 23

Size/Duplication

Total Lines 209
Duplicated Lines 0 %

Test Coverage

Coverage 91.67%

Importance

Changes 4
Bugs 0 Features 0
Metric Value
eloc 63
dl 0
loc 209
ccs 66
cts 72
cp 0.9167
rs 10
c 4
b 0
f 0
wmc 23

11 Methods

Rating   Name   Duplication   Size   Complexity  
A register() 0 10 1
A fs() 0 7 1
A stream_close() 0 7 2
A stream_eof() 0 3 1
A stream_read() 0 7 2
A stream_open() 0 22 4
A stream_write() 0 7 2
A stripScheme() 0 3 1
A rename() 0 38 5
A unlink() 0 9 3
A unregister() 0 3 1
1
<?php
2
3
declare(strict_types = 1);
4
5
namespace drupol\phpvfs;
6
7
use drupol\phpvfs\Commands\Cd;
8
use drupol\phpvfs\Commands\Exist;
9
use drupol\phpvfs\Commands\Get;
10
use drupol\phpvfs\Filesystem\Filesystem;
11
use drupol\phpvfs\Filesystem\FilesystemInterface;
12
use drupol\phpvfs\Node\File;
13
use drupol\phpvfs\Node\FileInterface;
14
use drupol\phpvfs\Utils\Path;
15
16
class PhpVfs
17
{
18
    public const SCHEME = 'phpvfs';
19
20
    /**
21
     * @var array
22
     */
23
    public $context;
24
25
    /**
26
     * @var null|\drupol\phpvfs\Node\FileInterface
27
     */
28
    private $currentFile;
29
30
    /**
31
     * @return \drupol\phpvfs\Filesystem\FilesystemInterface
32
     */
33 5
    public static function fs(): FilesystemInterface
34
    {
35 5
        $options = \stream_context_get_options(
36 5
            \stream_context_get_default()
37
        );
38
39 5
        return $options[static::SCHEME]['filesystem'];
40
    }
41
42
    /**
43
     * @param \drupol\phpvfs\Filesystem\Filesystem $filesystem
44
     * @param array $options
45
     */
46 5
    public static function register(Filesystem $filesystem, array $options = [])
47
    {
48
        $options = [
49 5
            static::SCHEME => [
50 5
                'filesystem' => $filesystem,
51 5
            ] + $options,
52
        ];
53
54 5
        \stream_context_set_default($options);
55 5
        \stream_wrapper_register(self::SCHEME, __CLASS__);
56 5
    }
57
58
    /**
59
     * @param string $from
60
     * @param string $to
61
     *
62
     * @throws \Exception
63
     *
64
     * @return bool
65
     */
66 1
    public function rename(string $from, string $to): bool
67
    {
68 1
        $from = $this->stripScheme($from);
69 1
        $to = $this->stripScheme($to);
70
71 1
        if (!Exist::exec($this::fs(), $from)) {
72 1
            throw new \Exception('Source resource does not exist.');
73
        }
74
75 1
        $from = Get::exec($this::fs(), $from);
76
77 1
        if (Exist::exec($this::fs(), $to)) {
78 1
            throw new \Exception('Destination already exist.');
79
        }
80
81 1
        $toPath = Path::fromString($to);
82
83 1
        $this::fs()
84 1
            ->getCwd()
85 1
            ->mkdir($toPath->dirname());
86
87 1
        if (null !== $parent = $from->getParent()) {
88 1
            $parent->delete($from);
89
        }
90
91 1
        Cd::exec($this::fs(), $toPath->dirname());
92
93 1
        $from->setAttribute('id', $toPath->basename());
94
95 1
        if ($from instanceof FileInterface) {
96 1
            $from->setPosition(0);
97
        }
98
99 1
        $this::fs()
100 1
            ->getCwd()
101 1
            ->add($from);
102
103 1
        return true;
104
    }
105
106
    /**
107
     * @see http://php.net/streamwrapper.stream-close
108
     */
109 5
    public function stream_close() // phpcs:ignore
110
    {
111 5
        if (null !== $this->currentFile) {
112 5
            $this->currentFile->setPosition(0);
113
        }
114
115 5
        $this->currentFile = null;
116 5
    }
117
118
    /**
119
     * @return bool
120
     *
121
     * @see http://php.net/streamwrapper.stream-eof
122
     */
123 1
    public function stream_eof(): bool // phpcs:ignore
124
    {
125 1
        return true;
126
    }
127
128
    /**
129
     * @param string $resource
130
     *
131
     * @throws \Exception
132
     *
133
     * @return bool
134
     */
135 5
    public function stream_open(string $resource) // phpcs:ignore
136
    {
137 5
        $resource = $this->stripScheme($resource);
138
139 5
        if (true === $this::fs()->exist($resource)) {
140 1
            $file = $this::fs()->get($resource);
141
142 1
            if ($file instanceof FileInterface) {
143 1
                $this->currentFile = $file;
144
            }
145
        } else {
146 5
            $this->currentFile = File::create($resource);
147 5
            $this::fs()->getCwd()->add($this->currentFile->root());
148
        }
149
150 5
        if (null === $this->currentFile) {
151
            return false;
152
        }
153
154 5
        $this->currentFile->setPosition(0);
155
156 5
        return true;
157
    }
158
159
    /**
160
     * @see http://php.net/streamwrapper.stream-read
161
     *
162
     * @param int $bytes
163
     *
164
     * @return mixed
165
     */
166
    public function stream_read(int $bytes) // phpcs:ignore
167
    {
168
        if (null !== $this->currentFile) {
169
            return $this->currentFile->read($bytes);
170
        }
171
172
        return false;
173
    }
174
175
    /**
176
     * @param string $data
177
     *
178
     * @return int
179
     */
180 5
    public function stream_write(string $data) // phpcs:ignore
181
    {
182 5
        if (null !== $this->currentFile) {
183 5
            return $this->currentFile->write($data);
184
        }
185
186
        return 0;
187
    }
188
189
    /**
190
     * @param string $path
191
     *
192
     * @throws \Exception
193
     */
194 1
    public function unlink(string $path)
195
    {
196 1
        $path = $this->stripScheme($path);
197
198 1
        if (true === Exist::exec($this::fs(), $path)) {
199 1
            $file = Get::exec($this::fs(), $path);
200
201 1
            if (null !== $parent = $file->getParent()) {
202 1
                $parent->delete($file);
203
            }
204
        }
205 1
    }
206
207
    /**
208
     * @todo
209
     */
210 5
    public static function unregister()
211
    {
212 5
        \stream_wrapper_unregister(self::SCHEME);
213 5
    }
214
215
    /**
216
     * Returns path stripped of url scheme (http://, ftp://, test:// etc.).
217
     *
218
     * @param string $path
219
     *
220
     * @return string
221
     */
222 5
    protected function stripScheme(string $path): string
223
    {
224 5
        return '/' . \ltrim(\substr($path, 9), '/');
225
    }
226
}
227