Completed
Push — master ( 2819f1...2ef162 )
by Pol
02:18
created

PhpVfs::stream_flush()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 5
ccs 3
cts 3
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types = 1);
4
5
namespace drupol\phpvfs;
6
7
use drupol\phpvfs\Command\Cd;
8
use drupol\phpvfs\Command\Exist;
9
use drupol\phpvfs\Command\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
/**
17
 * Class PhpVfs.
18
 */
19
class PhpVfs implements StreamWrapperInterface
20
{
21
    /**
22
     * The scheme.
23
     */
24
    protected const SCHEME = 'phpvfs';
25
26
    /**
27
     * The stream context.
28
     *
29
     * @var array
30
     */
31
    public $context;
32
33
    /**
34
     * {@inheritdoc}
35
     */
36
    public function dir_closedir(): bool // phpcs:ignore
37
    {
38
        throw new \Exception('Not implemented yet.');
39
    }
40
41
    /**
42
     * {@inheritdoc}
43
     */
44
    public function dir_opendir(string $path, int $options): bool // phpcs:ignore
45
    {
46
        throw new \Exception('Not implemented yet.');
47
    }
48
49
    /**
50
     * {@inheritdoc}
51
     */
52
    public function dir_readdir(): string // phpcs:ignore
53
    {
54
        throw new \Exception('Not implemented yet.');
55
    }
56
57
    /**
58
     * {@inheritdoc}
59
     */
60
    public function dir_rewinddir(): bool // phpcs:ignore
61
    {
62
        throw new \Exception('Not implemented yet.');
63
    }
64
65
    /**
66
     * {@inheritdoc}
67
     */
68 6
    public static function fs(): FilesystemInterface
69
    {
70 6
        $options = \stream_context_get_options(
71 6
            \stream_context_get_default()
72
        );
73
74 6
        return $options[static::SCHEME]['filesystem'];
75
    }
76
77
    /**
78
     * {@inheritdoc}
79
     */
80
    public function mkdir(string $path, int $mode, int $options): bool
81
    {
82
        throw new \Exception('Not implemented yet.');
83
    }
84
85
    /**
86
     * {@inheritdoc}
87
     */
88 6
    public static function register(Filesystem $filesystem, array $options = [])
89
    {
90
        $options = [
91 6
            static::SCHEME => [
92 6
                'filesystem' => $filesystem,
93
                'currentFile' => null,
94 6
            ] + $options,
95
        ];
96
97 6
        \stream_context_set_default($options);
98 6
        \stream_wrapper_register(self::SCHEME, __CLASS__);
99 6
    }
100
101
    /**
102
     * {@inheritdoc}
103
     */
104 1
    public function rename(string $from, string $to): bool
105
    {
106 1
        if (!Exist::exec($this::fs(), $from)) {
107
            throw new \Exception('Source resource does not exist.');
108
        }
109
110 1
        $from = Get::exec($this::fs(), $from);
111
112 1
        if (Exist::exec($this::fs(), $to)) {
113 1
            throw new \Exception('Destination already exist.');
114
        }
115
116 1
        $toPath = Path::fromString($to);
117
118 1
        $this::fs()
119 1
            ->getCwd()
120 1
            ->mkdir($toPath->dirname());
121
122 1
        if (null !== $parent = $from->getParent()) {
123 1
            $parent->delete($from);
124
        }
125
126 1
        Cd::exec($this::fs(), $toPath->dirname());
127
128 1
        $from->setAttribute('id', $toPath->basename());
129
130 1
        if ($from instanceof FileInterface) {
131 1
            $from->setPosition(0);
132
        }
133
134 1
        $this::fs()
135 1
            ->getCwd()
136 1
            ->add($from);
137
138 1
        return true;
139
    }
140
141
    /**
142
     * {@inheritdoc}
143
     */
144
    public function rmdir(string $path, int $options): bool
145
    {
146
        throw new \Exception('Not implemented yet.');
147
    }
148
149
    /**
150
     * {@inheritdoc}
151
     */
152
    public function stream_cast(int $cast_as) // phpcs:ignore
153
    {
154
        throw new \Exception('Not implemented yet.');
155
    }
156
157
    /**
158
     * {@inheritdoc}
159
     */
160 6
    public function stream_close(): void // phpcs:ignore
161
    {
162 6
        if (null !== $file = $this->getCurrentFile()) {
163 6
            $file->setPosition(0);
164
        }
165
166 6
        $this->setCurrentFile(null);
167 6
    }
168
169
    /**
170
     * {@inheritdoc}
171
     */
172 1
    public function stream_eof(): bool // phpcs:ignore
173
    {
174 1
        return true;
175
    }
176
177
    /**
178
     * {@inheritdoc}
179
     */
180 6
    public function stream_flush(): bool // phpcs:ignore
181
    {
182 6
        \clearstatcache();
183
184 6
        return true;
185
    }
186
187
    /**
188
     * {@inheritdoc}
189
     */
190
    public function stream_lock($operation): bool // phpcs:ignore
191
    {
192
        throw new \Exception('Not implemented yet.');
193
    }
194
195
    /**
196
     * {@inheritdoc}
197
     */
198 6
    public function stream_open(string $resource, string $mode, int $options, ?string &$openedPath): bool // phpcs:ignore
199
    {
200 6
        $mode = \str_split(\str_replace('b', '', $mode));
201
202 6
        $appendMode = \in_array('a', $mode, true);
0 ignored issues
show
Unused Code introduced by
The assignment to $appendMode is dead and can be removed.
Loading history...
203 6
        $readMode = \in_array('r', $mode, true);
204 6
        $writeMode = \in_array('w', $mode, true);
0 ignored issues
show
Unused Code introduced by
The assignment to $writeMode is dead and can be removed.
Loading history...
205 6
        $extended = \in_array('+', $mode, true);
0 ignored issues
show
Unused Code introduced by
The assignment to $extended is dead and can be removed.
Loading history...
206
207 6
        $resourcePath = Path::fromString($resource);
208
209 6
        if (!Exist::exec($this::fs(), $resource)) {
210
            if ($readMode || !Exist::exec($this::fs(), $resourcePath->dirname())) {
211
                if ($options & STREAM_REPORT_ERRORS) {
212
                    \trigger_error(\sprintf('%s: failed to open stream.', $resourcePath), E_USER_WARNING);
213
                }
214
215
                return false;
216
            }
217
218
            $file = File::create($resource);
219
220
            $this->setCurrentFile($file);
221
            $this::fs()
222
                ->getCwd()
223
                ->add($file->root());
224
        }
225
226 6
        if (null === $file = $this::fs()->get($resource)) {
227
            return false;
228
        }
229
230 6
        if (!($file instanceof FileInterface)) {
231
            return false;
232
        }
233
234 6
        $file->setPosition(0);
235
236 6
        $this->setCurrentFile($file);
237
238 6
        return true;
239
    }
240
241
    /**
242
     * {@inheritdoc}
243
     */
244
    public function stream_read(int $bytes) // phpcs:ignore
245
    {
246
        if (null !== $file = $this->getCurrentFile()) {
247
            return $file->read($bytes);
248
        }
249
250
        return false;
251
    }
252
253
    /**
254
     * {@inheritdoc}
255
     */
256
    public function stream_seek(int $offset, int $whence = SEEK_SET): bool // phpcs:ignore
257
    {
258
        throw new \Exception('Not implemented yet.');
259
    }
260
261
    /**
262
     * {@inheritdoc}
263
     */
264
    public function stream_set_option(int $option, int $arg1, int $arg2): bool // phpcs:ignore
265
    {
266
        throw new \Exception('Not implemented yet.');
267
    }
268
269
    /**
270
     * {@inheritdoc}
271
     */
272 1
    public function stream_stat(): array // phpcs:ignore
273
    {
274 1
        if (null === $file = $this->getCurrentFile()) {
275 1
            return [];
276
        }
277
278 1
        return (array) $file->getAttributes();
279
    }
280
281
    /**
282
     * {@inheritdoc}
283
     */
284
    public function stream_tell(): int // phpcs:ignore
285
    {
286
        throw new \Exception('Not implemented yet.');
287
    }
288
289
    /**
290
     * {@inheritdoc}
291
     */
292 6
    public function stream_write(string $data): int // phpcs:ignore
293
    {
294 6
        if (null !== $file = $this->getCurrentFile()) {
295 6
            return $file->write($data);
296
        }
297
298
        return 0;
299
    }
300
301
    /**
302
     * {@inheritdoc}
303
     */
304 1
    public function unlink(string $path): bool
305
    {
306 1
        if (true === Exist::exec($this::fs(), $path)) {
307 1
            $file = Get::exec($this::fs(), $path);
308
309 1
            if (null !== $parent = $file->getParent()) {
310 1
                $parent->delete($file);
311
            }
312
        }
313
314 1
        return true;
315
    }
316
317
    /**
318
     * {@inheritdoc}
319
     */
320 6
    public static function unregister()
321
    {
322 6
        \stream_wrapper_unregister(self::SCHEME);
323 6
    }
324
325
    /**
326
     * {@inheritdoc}
327
     */
328
    public function url_stat(string $path, int $flags): array // phpcs:ignore
329
    {
330
        throw new \Exception('Not implemented yet.');
331
    }
332
333
    /**
334
     * @return null|FileInterface
335
     */
336 6
    protected function getCurrentFile(): ?FileInterface
337
    {
338 6
        $options = \stream_context_get_options(
339 6
            \stream_context_get_default()
340
        );
341
342 6
        return $options[static::SCHEME]['currentFile'];
343
    }
344
345
    /**
346
     * @param null|FileInterface $file
347
     */
348 6
    protected function setCurrentFile(?FileInterface $file)
349
    {
350 6
        $options = \stream_context_get_options(
351 6
            \stream_context_get_default()
352
        );
353
354 6
        $options[static::SCHEME]['currentFile'] = $file;
355
356 6
        \stream_context_set_default($options);
357 6
    }
358
}
359