Passed
Push — master ( 0c29e2...c7b87e )
by Pol
02:37
created

PhpVfs::stream_open()   B

Complexity

Conditions 8
Paths 12

Size

Total Lines 58
Code Lines 34

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 20
CRAP Score 13.0389

Importance

Changes 9
Bugs 0 Features 0
Metric Value
cc 8
eloc 34
c 9
b 0
f 0
nc 12
nop 4
dl 0
loc 58
ccs 20
cts 35
cp 0.5714
crap 13.0389
rs 8.1315

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types = 1);
4
5
namespace drupol\phpvfs;
6
7
use drupol\phpvfs\Filesystem\Filesystem;
8
use drupol\phpvfs\Filesystem\FilesystemInterface;
9
use drupol\phpvfs\Node\File;
10
use drupol\phpvfs\Node\FileInterface;
11
use drupol\phpvfs\Utils\Path;
12
13
/**
14
 * Class PhpVfs.
15
 */
16
class PhpVfs implements StreamWrapperInterface
17
{
18
    /**
19
     * The scheme.
20
     */
21
    protected const SCHEME = 'phpvfs';
22
23
    /**
24
     * The stream context.
25
     *
26
     * @var array
27
     */
28
    public $context;
29
30
    /**
31
     * {@inheritdoc}
32
     */
33
    public function dir_closedir(): bool // phpcs:ignore
34
    {
35
        throw new \Exception('Not implemented yet.');
36
    }
37
38
    /**
39
     * {@inheritdoc}
40
     */
41
    public function dir_opendir(string $path, int $options): bool // phpcs:ignore
42
    {
43
        throw new \Exception('Not implemented yet.');
44
    }
45
46
    /**
47
     * {@inheritdoc}
48
     */
49
    public function dir_readdir(): string // phpcs:ignore
50
    {
51
        throw new \Exception('Not implemented yet.');
52
    }
53
54
    /**
55
     * {@inheritdoc}
56
     */
57
    public function dir_rewinddir(): bool // phpcs:ignore
58
    {
59
        throw new \Exception('Not implemented yet.');
60
    }
61
62
    /**
63
     * {@inheritdoc}
64
     */
65 9
    public static function fs(): FilesystemInterface
66
    {
67 9
        $options = \stream_context_get_options(
68 9
            \stream_context_get_default()
69
        );
70
71 9
        return $options[static::SCHEME]['filesystem'];
72
    }
73
74
    /**
75
     * {@inheritdoc}
76
     */
77
    public function mkdir(string $path, int $mode, int $options): bool
78
    {
79
        throw new \Exception('Not implemented yet.');
80
    }
81
82
    /**
83
     * {@inheritdoc}
84
     */
85 10
    public static function register(Filesystem $filesystem, array $options = [])
86
    {
87
        $options = [
88 10
            static::SCHEME => [
89 10
                'filesystem' => $filesystem,
90
                'currentFile' => null,
91 10
            ] + $options,
92
        ];
93
94 10
        \stream_context_set_default($options);
95 10
        \stream_wrapper_register(self::SCHEME, __CLASS__);
96 10
    }
97
98
    /**
99
     * {@inheritdoc}
100
     */
101 1
    public function rename(string $from, string $to): bool
102
    {
103 1
        if (!$this::fs()->getCwd()->exist($from)) {
104
            throw new \Exception('Source resource does not exist.');
105
        }
106
107 1
        $from = $this::fs()->getCwd()->get($from);
108
109 1
        if ($this::fs()->getCwd()->exist($to)) {
110 1
            throw new \Exception('Destination already exist.');
111
        }
112
113 1
        $toPath = Path::fromString($to);
114
115 1
        $this::fs()
116 1
            ->getCwd()
117 1
            ->mkdir($toPath->dirname());
118
119 1
        if (null !== $parent = $from->getParent()) {
120 1
            $parent->delete($from);
121
        }
122
123 1
        $directory = $this::fs()->getCwd()->cd($toPath->dirname());
124
125 1
        $from->setAttribute('id', $toPath->basename());
126
127
        $directory
128 1
            ->add($from);
129
130 1
        return true;
131
    }
132
133
    /**
134
     * {@inheritdoc}
135
     */
136 1
    public function rmdir(string $path, int $options): bool
137
    {
138 1
        $cwd = $this::fs()
139 1
            ->getCwd()
140 1
            ->rmdir($path);
141
142 1
        $this::fs()
143 1
            ->setCwd($cwd);
144
145 1
        return true;
146
    }
147
148
    /**
149
     * {@inheritdoc}
150
     */
151
    public function stream_cast(int $cast_as) // phpcs:ignore
152
    {
153
        throw new \Exception('Not implemented yet.');
154
    }
155
156
    /**
157
     * {@inheritdoc}
158
     */
159 8
    public function stream_close(): void // phpcs:ignore
160
    {
161 8
        $this->setCurrentFile(null);
162 8
    }
163
164
    /**
165
     * {@inheritdoc}
166
     */
167 3
    public function stream_eof(): bool // phpcs:ignore
168
    {
169 3
        if (!(($file = $this->getCurrentFile()) instanceof Handler\FileInterface)) {
170
            throw new \Exception('The current file does not implement FileInterface.');
171
        }
172
173 3
        return $file->getPosition() === $file->size();
174
    }
175
176
    /**
177
     * {@inheritdoc}
178
     */
179 6
    public function stream_flush(): bool // phpcs:ignore
180
    {
181 6
        \clearstatcache();
182
183 6
        return true;
184
    }
185
186
    /**
187
     * {@inheritdoc}
188
     */
189
    public function stream_lock($operation): bool // phpcs:ignore
190
    {
191
        throw new \Exception('Not implemented yet.');
192
    }
193
194
    /**
195
     * {@inheritdoc}
196
     */
197 8
    public function stream_open(string $resource, string $mode, int $options, ?string &$openedPath): bool // phpcs:ignore
198
    {
199 8
        $modeSplit = \str_split(\str_replace('b', '', $mode));
200
201 8
        $appendMode = \in_array('a', $modeSplit, true);
202 8
        $readMode = \in_array('r', $modeSplit, true);
203 8
        $writeMode = \in_array('w', $modeSplit, true);
204 8
        $extended = \in_array('+', $modeSplit, true);
0 ignored issues
show
Unused Code introduced by
The assignment to $extended is dead and can be removed.
Loading history...
205
206 8
        $resourcePath = Path::fromString($resource);
207
208 8
        $resourceExist = $this::fs()->getCwd()->exist($resource);
209 8
        $resourceDirnameExist = $this::fs()->getCwd()->exist($resourcePath->dirname());
0 ignored issues
show
Unused Code introduced by
The assignment to $resourceDirnameExist is dead and can be removed.
Loading history...
210
211 8
        if (false === $resourceExist) {
212
            if (true === $readMode) {
213
                if ($options & STREAM_REPORT_ERRORS) {
214
                    \trigger_error(
215
                        \sprintf(
216
                            '%s: failed to open stream: Unknown resource.',
217
                            $resourcePath
218
                        ),
219
                        E_USER_WARNING
220
                    );
221
                }
222
223
                return false;
224
            }
225
226
            $this::fs()
227
                ->getCwd()
228
                ->add(File::create($resource)->root());
229
        }
230
231 8
        $file = $this::fs()->getCwd()->get($resource);
232
233 8
        if (!($file instanceof FileInterface)) {
234
            if ($options & STREAM_REPORT_ERRORS) {
235
                \trigger_error(\sprintf('fopen(%s): failed to open stream: Not a file.', $resource), E_USER_WARNING);
236
            }
237
238
            return false;
239
        }
240
241 8
        $fileHandler = new Handler\File($file, $mode);
242
243 8
        if (true === $appendMode) {
244
            $fileHandler->seekToEnd();
245 8
        } elseif (true === $writeMode) {
246 5
            $fileHandler->truncate();
247 5
            \clearstatcache();
248
        }
249
250 8
        $this->setCurrentFile($fileHandler);
251
252 8
        $openedPath = $file->getPath()->__toString();
253
254 8
        return true;
255
    }
256
257
    /**
258
     * {@inheritdoc}
259
     */
260 3
    public function stream_read(int $bytes) // phpcs:ignore
261
    {
262 3
        if ((null === $file = $this->getCurrentFile()) || (false === $file->isReadable())) {
263
            return false;
264
        }
265
266 3
        return $file->read($bytes);
267
    }
268
269
    /**
270
     * {@inheritdoc}
271
     */
272 2
    public function stream_seek(int $offset, int $whence = SEEK_SET): bool // phpcs:ignore
273
    {
274 2
        if (($file = $this->getCurrentFile()) instanceof Handler\File) {
275 2
            $file->setPosition($offset);
276
        }
277
278 2
        return true;
279
    }
280
281
    /**
282
     * {@inheritdoc}
283
     */
284
    public function stream_set_option(int $option, int $arg1, int $arg2): bool // phpcs:ignore
285
    {
286
        throw new \Exception('Not implemented yet.');
287
    }
288
289
    /**
290
     * {@inheritdoc}
291
     */
292 1
    public function stream_stat(): array // phpcs:ignore
293
    {
294 1
        if (null === $file = $this->getCurrentFile()) {
295 1
            return [];
296
        }
297
298 1
        return (array) $file->getFile()->getAttributes();
299
    }
300
301
    /**
302
     * {@inheritdoc}
303
     */
304 1
    public function stream_tell(): int // phpcs:ignore
305
    {
306 1
        if (($file = $this->getCurrentFile()) instanceof Handler\File) {
307 1
            return $file->getPosition();
308
        }
0 ignored issues
show
Bug Best Practice introduced by
The function implicitly returns null when the if condition on line 306 is false. This is incompatible with the type-hinted return integer. Consider adding a return statement or allowing null as return value.

For hinted functions/methods where all return statements with the correct type are only reachable via conditions, ?null? gets implicitly returned which may be incompatible with the hinted type. Let?s take a look at an example:

interface ReturnsInt {
    public function returnsIntHinted(): int;
}

class MyClass implements ReturnsInt {
    public function returnsIntHinted(): int
    {
        if (foo()) {
            return 123;
        }
        // here: null is implicitly returned
    }
}
Loading history...
309
    }
310
311
    /**
312
     * {@inheritdoc}
313
     */
314 1
    public function stream_truncate(int $bytes): bool // phpcs:ignore
315
    {
316 1
        if (($file = $this->getCurrentFile()) instanceof Handler\File) {
317 1
            $file->truncate($bytes);
318 1
            \clearstatcache();
319
        }
320
321 1
        return true;
322
    }
323
324
    /**
325
     * {@inheritdoc}
326
     */
327 5
    public function stream_write(string $data): int // phpcs:ignore
328
    {
329 5
        if ((null === $file = $this->getCurrentFile()) || (false === $file->isWritable())) {
330 1
            return 0;
331
        }
332
333 5
        return $file->write($data);
334
    }
335
336
    /**
337
     * {@inheritdoc}
338
     */
339 1
    public function unlink(string $path): bool
340
    {
341 1
        if (true === $this::fs()->getCwd()->exist($path)) {
342 1
            $file = $this::fs()->getCwd()->get($path);
343
344 1
            if (null !== $parent = $file->getParent()) {
345 1
                $parent->delete($file);
346
            }
347
        }
348
349 1
        return true;
350
    }
351
352
    /**
353
     * {@inheritdoc}
354
     */
355 10
    public static function unregister()
356
    {
357 10
        \stream_wrapper_unregister(self::SCHEME);
358 10
    }
359
360
    /**
361
     * {@inheritdoc}
362
     */
363
    public function url_stat(string $path, int $flags): array // phpcs:ignore
364
    {
365
        throw new \Exception('Not implemented yet.');
366
    }
367
368
    /**
369
     * @return null|\drupol\phpvfs\Handler\FileInterface
370
     */
371 8
    private function getCurrentFile(): ?Handler\FileInterface
372
    {
373 8
        $options = \stream_context_get_options(
374 8
            \stream_context_get_default()
375
        );
376
377 8
        return $options[static::SCHEME]['currentFile'];
378
    }
379
380
    /**
381
     * @param null|\drupol\phpvfs\Handler\FileInterface $file
382
     */
383 8
    private function setCurrentFile(?Handler\FileInterface $file)
384
    {
385 8
        $options = \stream_context_get_options(
386 8
            \stream_context_get_default()
387
        );
388
389 8
        $options[static::SCHEME]['currentFile'] = $file;
390
391 8
        \stream_context_set_default($options);
392 8
    }
393
}
394