Passed
Push — master ( b48497...62d16d )
by Pol
02:10
created

PhpVfs   A

Complexity

Total Complexity 41

Size/Duplication

Total Lines 342
Duplicated Lines 0 %

Test Coverage

Coverage 68.6%

Importance

Changes 8
Bugs 0 Features 0
Metric Value
eloc 98
c 8
b 0
f 0
dl 0
loc 342
ccs 83
cts 121
cp 0.686
rs 9.1199
wmc 41

26 Methods

Rating   Name   Duplication   Size   Complexity  
A dir_readdir() 0 3 1
A mkdir() 0 3 1
A dir_rewinddir() 0 3 1
A dir_opendir() 0 3 1
A rename() 0 34 5
A register() 0 11 1
A dir_closedir() 0 3 1
A fs() 0 7 1
A getCurrentFile() 0 7 1
A stream_close() 0 7 2
A stream_eof() 0 3 1
A stream_cast() 0 3 1
A stream_read() 0 7 2
A url_stat() 0 3 1
A setCurrentFile() 0 9 1
B stream_open() 0 39 6
A stream_write() 0 7 2
A stream_lock() 0 3 1
A stream_stat() 0 7 2
A rmdir() 0 10 1
A stream_set_option() 0 3 1
A stream_flush() 0 5 1
A stream_seek() 0 3 1
A unlink() 0 11 3
A stream_tell() 0 3 1
A unregister() 0 3 1

How to fix   Complexity   

Complex Class

Complex classes like PhpVfs often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use PhpVfs, and based on these observations, apply Extract Interface, too.

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 6
    public static function fs(): FilesystemInterface
66
    {
67 6
        $options = \stream_context_get_options(
68 6
            \stream_context_get_default()
69
        );
70
71 6
        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 6
    public static function register(Filesystem $filesystem, array $options = [])
86
    {
87
        $options = [
88 6
            static::SCHEME => [
89 6
                'filesystem' => $filesystem,
90
                'currentFile' => null,
91 6
            ] + $options,
92
        ];
93
94 6
        \stream_context_set_default($options);
95 6
        \stream_wrapper_register(self::SCHEME, __CLASS__);
96 6
    }
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 1
        if ($from instanceof FileInterface) {
128 1
            $from->setPosition(0);
129
        }
130
131
        $directory
132 1
            ->add($from);
133
134 1
        return true;
135
    }
136
137
    /**
138
     * {@inheritdoc}
139
     */
140 1
    public function rmdir(string $path, int $options): bool
141
    {
142 1
        $cwd = $this::fs()
143 1
            ->getCwd()
144 1
            ->rmdir($path);
145
146 1
        $this::fs()
147 1
            ->setCwd($cwd);
148
149 1
        return true;
150
    }
151
152
    /**
153
     * {@inheritdoc}
154
     */
155
    public function stream_cast(int $cast_as) // phpcs:ignore
156
    {
157
        throw new \Exception('Not implemented yet.');
158
    }
159
160
    /**
161
     * {@inheritdoc}
162
     */
163 5
    public function stream_close(): void // phpcs:ignore
164
    {
165 5
        if (null !== $file = $this->getCurrentFile()) {
166 5
            $file->setPosition(0);
167
        }
168
169 5
        $this->setCurrentFile(null);
170 5
    }
171
172
    /**
173
     * {@inheritdoc}
174
     */
175 1
    public function stream_eof(): bool // phpcs:ignore
176
    {
177 1
        return true;
178
    }
179
180
    /**
181
     * {@inheritdoc}
182
     */
183 5
    public function stream_flush(): bool // phpcs:ignore
184
    {
185 5
        \clearstatcache();
186
187 5
        return true;
188
    }
189
190
    /**
191
     * {@inheritdoc}
192
     */
193
    public function stream_lock($operation): bool // phpcs:ignore
194
    {
195
        throw new \Exception('Not implemented yet.');
196
    }
197
198
    /**
199
     * {@inheritdoc}
200
     */
201 5
    public function stream_open(string $resource, string $mode, int $options, ?string &$openedPath): bool // phpcs:ignore
202
    {
203 5
        $mode = \str_split(\str_replace('b', '', $mode));
204
205 5
        $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...
206 5
        $readMode = \in_array('r', $mode, true);
207 5
        $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...
208 5
        $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...
209
210 5
        $resourcePath = Path::fromString($resource);
211
212 5
        if (!$this::fs()->getCwd()->exist($resource)) {
213
            if ($readMode || !$this::fs()->getCwd()->exist($resourcePath->dirname())) {
214
                if ($options & STREAM_REPORT_ERRORS) {
215
                    \trigger_error(\sprintf('%s: failed to open stream.', $resourcePath), E_USER_WARNING);
216
                }
217
218
                return false;
219
            }
220
221
            $file = File::create($resource);
222
223
            $this->setCurrentFile($file);
224
            $this::fs()
225
                ->getCwd()
226
                ->add($file->root());
227
        }
228
229 5
        $file = $this::fs()->getCwd()->get($resource);
230
231 5
        if (!($file instanceof FileInterface)) {
232
            return false;
233
        }
234
235 5
        $file->setPosition(0);
236
237 5
        $this->setCurrentFile($file);
238
239 5
        return true;
240
    }
241
242
    /**
243
     * {@inheritdoc}
244
     */
245
    public function stream_read(int $bytes) // phpcs:ignore
246
    {
247
        if (null !== $file = $this->getCurrentFile()) {
248
            return $file->read($bytes);
249
        }
250
251
        return false;
252
    }
253
254
    /**
255
     * {@inheritdoc}
256
     */
257
    public function stream_seek(int $offset, int $whence = SEEK_SET): bool // phpcs:ignore
258
    {
259
        throw new \Exception('Not implemented yet.');
260
    }
261
262
    /**
263
     * {@inheritdoc}
264
     */
265
    public function stream_set_option(int $option, int $arg1, int $arg2): bool // phpcs:ignore
266
    {
267
        throw new \Exception('Not implemented yet.');
268
    }
269
270
    /**
271
     * {@inheritdoc}
272
     */
273 1
    public function stream_stat(): array // phpcs:ignore
274
    {
275 1
        if (null === $file = $this->getCurrentFile()) {
276 1
            return [];
277
        }
278
279 1
        return (array) $file->getAttributes();
280
    }
281
282
    /**
283
     * {@inheritdoc}
284
     */
285
    public function stream_tell(): int // phpcs:ignore
286
    {
287
        throw new \Exception('Not implemented yet.');
288
    }
289
290
    /**
291
     * {@inheritdoc}
292
     */
293 5
    public function stream_write(string $data): int // phpcs:ignore
294
    {
295 5
        if (null !== $file = $this->getCurrentFile()) {
296 5
            return $file->write($data);
297
        }
298
299
        return 0;
300
    }
301
302
    /**
303
     * {@inheritdoc}
304
     */
305 1
    public function unlink(string $path): bool
306
    {
307 1
        if (true === $this::fs()->getCwd()->exist($path)) {
308 1
            $file = $this::fs()->getCwd()->get($path);
309
310 1
            if (null !== $parent = $file->getParent()) {
311 1
                $parent->delete($file);
312
            }
313
        }
314
315 1
        return true;
316
    }
317
318
    /**
319
     * {@inheritdoc}
320
     */
321 6
    public static function unregister()
322
    {
323 6
        \stream_wrapper_unregister(self::SCHEME);
324 6
    }
325
326
    /**
327
     * {@inheritdoc}
328
     */
329
    public function url_stat(string $path, int $flags): array // phpcs:ignore
330
    {
331
        throw new \Exception('Not implemented yet.');
332
    }
333
334
    /**
335
     * @return null|FileInterface
336
     */
337 5
    protected function getCurrentFile(): ?FileInterface
338
    {
339 5
        $options = \stream_context_get_options(
340 5
            \stream_context_get_default()
341
        );
342
343 5
        return $options[static::SCHEME]['currentFile'];
344
    }
345
346
    /**
347
     * @param null|FileInterface $file
348
     */
349 5
    protected function setCurrentFile(?FileInterface $file)
350
    {
351 5
        $options = \stream_context_get_options(
352 5
            \stream_context_get_default()
353
        );
354
355 5
        $options[static::SCHEME]['currentFile'] = $file;
356
357 5
        \stream_context_set_default($options);
358 5
    }
359
}
360