Passed
Push — master ( ee003d...721255 )
by Pol
03:14
created

PhpVfs::stream_open()   B

Complexity

Conditions 8
Paths 12

Size

Total Lines 52
Code Lines 30

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 20
CRAP Score 10.8584

Importance

Changes 7
Bugs 0 Features 0
Metric Value
cc 8
eloc 30
c 7
b 0
f 0
nc 12
nop 4
dl 0
loc 52
ccs 20
cts 31
cp 0.6452
crap 10.8584
rs 8.1954

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 8
    public static function fs(): FilesystemInterface
66
    {
67 8
        $options = \stream_context_get_options(
68 8
            \stream_context_get_default()
69
        );
70
71 8
        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 9
    public static function register(Filesystem $filesystem, array $options = [])
86
    {
87
        $options = [
88 9
            static::SCHEME => [
89 9
                'filesystem' => $filesystem,
90
                'currentFile' => null,
91 9
            ] + $options,
92
        ];
93
94 9
        \stream_context_set_default($options);
95 9
        \stream_wrapper_register(self::SCHEME, __CLASS__);
96 9
    }
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 7
    public function stream_close(): void // phpcs:ignore
160
    {
161 7
        $this->setCurrentFile(null);
162 7
    }
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 7
    public function stream_open(string $resource, string $mode, int $options, ?string &$openedPath): bool // phpcs:ignore
198
    {
199 7
        $modeSplit = \str_split(\str_replace('b', '', $mode));
200
201 7
        $appendMode = \in_array('a', $modeSplit, true);
202 7
        $readMode = \in_array('r', $modeSplit, true);
203 7
        $writeMode = \in_array('w', $modeSplit, true);
204 7
        $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 7
        $resourcePath = Path::fromString($resource);
207
208 7
        $resourceExist = $this::fs()->getCwd()->exist($resource);
209 7
        $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 7
        if (false === $resourceExist) {
212
            if (true === $readMode) {
213
                if ($options & STREAM_REPORT_ERRORS) {
214
                    \trigger_error(\sprintf('%s: failed to open stream.', $resourcePath), E_USER_WARNING);
215
                }
216
217
                return false;
218
            }
219
220
            $this::fs()
221
                ->getCwd()
222
                ->add(File::create($resource)->root());
223
        }
224
225 7
        $file = $this::fs()->getCwd()->get($resource);
226
227 7
        if (!($file instanceof FileInterface)) {
228
            if ($options & STREAM_REPORT_ERRORS) {
229
                \trigger_error(\sprintf('fopen(%s): failed to open stream: Not a file.', $resource), E_USER_WARNING);
230
            }
231
232
            return false;
233
        }
234
235 7
        $fileHandler = new Handler\File($file, $mode, 0);
236
237 7
        if (true === $appendMode) {
238
            $fileHandler->seekToEnd();
239 7
        } elseif (true === $writeMode) {
240 5
            $fileHandler->truncate();
241 5
            \clearstatcache();
242
        }
243
244 7
        $this->setCurrentFile($fileHandler);
245
246 7
        $openedPath = $file->getPath()->__toString();
247
248 7
        return true;
249
    }
250
251
    /**
252
     * {@inheritdoc}
253
     */
254 2
    public function stream_read(int $bytes) // phpcs:ignore
255
    {
256 2
        if ((null === $file = $this->getCurrentFile()) || (false === $file->isReadable())) {
257
            return false;
258
        }
259
260 2
        return $file->read($bytes);
261
    }
262
263
    /**
264
     * {@inheritdoc}
265
     */
266 1
    public function stream_seek(int $offset, int $whence = SEEK_SET): bool // phpcs:ignore
267
    {
268 1
        if (($file = $this->getCurrentFile()) instanceof Handler\File) {
269 1
            $file->setPosition($offset);
270
        }
271
272 1
        return true;
273
    }
274
275
    /**
276
     * {@inheritdoc}
277
     */
278
    public function stream_set_option(int $option, int $arg1, int $arg2): bool // phpcs:ignore
279
    {
280
        throw new \Exception('Not implemented yet.');
281
    }
282
283
    /**
284
     * {@inheritdoc}
285
     */
286 1
    public function stream_stat(): array // phpcs:ignore
287
    {
288 1
        if (null === $file = $this->getCurrentFile()) {
289 1
            return [];
290
        }
291
292 1
        return (array) $file->getFile()->getAttributes();
293
    }
294
295
    /**
296
     * {@inheritdoc}
297
     */
298 1
    public function stream_tell(): int // phpcs:ignore
299
    {
300 1
        if (($file = $this->getCurrentFile()) instanceof Handler\File) {
301 1
            return $file->getPosition();
302
        }
0 ignored issues
show
Bug Best Practice introduced by
The function implicitly returns null when the if condition on line 300 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...
303
    }
304
305
    /**
306
     * {@inheritdoc}
307
     */
308 1
    public function stream_truncate(int $bytes): bool // phpcs:ignore
309
    {
310 1
        if (($file = $this->getCurrentFile()) instanceof Handler\File) {
311 1
            $file->truncate($bytes);
312 1
            \clearstatcache();
313
        }
314
315 1
        return true;
316
    }
317
318
    /**
319
     * {@inheritdoc}
320
     */
321 5
    public function stream_write(string $data): int // phpcs:ignore
322
    {
323 5
        if ((null === $file = $this->getCurrentFile()) || (false === $file->isWritable())) {
324 1
            return 0;
325
        }
326
327 5
        return $file->write($data);
328
    }
329
330
    /**
331
     * {@inheritdoc}
332
     */
333 1
    public function unlink(string $path): bool
334
    {
335 1
        if (true === $this::fs()->getCwd()->exist($path)) {
336 1
            $file = $this::fs()->getCwd()->get($path);
337
338 1
            if (null !== $parent = $file->getParent()) {
339 1
                $parent->delete($file);
340
            }
341
        }
342
343 1
        return true;
344
    }
345
346
    /**
347
     * {@inheritdoc}
348
     */
349 9
    public static function unregister()
350
    {
351 9
        \stream_wrapper_unregister(self::SCHEME);
352 9
    }
353
354
    /**
355
     * {@inheritdoc}
356
     */
357
    public function url_stat(string $path, int $flags): array // phpcs:ignore
358
    {
359
        throw new \Exception('Not implemented yet.');
360
    }
361
362
    /**
363
     * @return null|\drupol\phpvfs\Handler\FileInterface
364
     */
365 7
    private function getCurrentFile(): ?Handler\FileInterface
366
    {
367 7
        $options = \stream_context_get_options(
368 7
            \stream_context_get_default()
369
        );
370
371 7
        return $options[static::SCHEME]['currentFile'];
372
    }
373
374
    /**
375
     * @param null|\drupol\phpvfs\Handler\FileInterface $file
376
     */
377 7
    private function setCurrentFile(?Handler\FileInterface $file)
378
    {
379 7
        $options = \stream_context_get_options(
380 7
            \stream_context_get_default()
381
        );
382
383 7
        $options[static::SCHEME]['currentFile'] = $file;
384
385 7
        \stream_context_set_default($options);
386 7
    }
387
}
388