Passed
Push — master ( de351b...604f37 )
by Pol
02:29
created

PhpVfs::stream_open()   B

Complexity

Conditions 8
Paths 12

Size

Total Lines 59
Code Lines 35

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 21
CRAP Score 12.6306

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 8
eloc 35
c 1
b 0
f 0
nc 12
nop 4
dl 0
loc 59
ccs 21
cts 36
cp 0.5833
crap 12.6306
rs 8.1155

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