Passed
Push — master ( a3a054...93611a )
by Pol
02:16
created

PhpVfs   A

Complexity

Total Complexity 26

Size/Duplication

Total Lines 231
Duplicated Lines 0 %

Test Coverage

Coverage 82.14%

Importance

Changes 4
Bugs 0 Features 0
Metric Value
eloc 74
c 4
b 0
f 0
dl 0
loc 231
ccs 69
cts 84
cp 0.8214
rs 10
wmc 26

11 Methods

Rating   Name   Duplication   Size   Complexity  
A register() 0 10 1
A fs() 0 7 1
A stream_close() 0 7 2
A stream_eof() 0 3 1
A rename() 0 38 5
A stream_read() 0 7 2
B stream_open() 0 41 7
A stream_write() 0 7 2
A stripScheme() 0 3 1
A unlink() 0 9 3
A unregister() 0 3 1
1
<?php
2
3
declare(strict_types = 1);
4
5
namespace drupol\phpvfs;
6
7
use drupol\phpvfs\Commands\Cd;
8
use drupol\phpvfs\Commands\Exist;
9
use drupol\phpvfs\Commands\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
class PhpVfs
17
{
18
    public const SCHEME = 'phpvfs';
19
20
    /**
21
     * @var array
22
     */
23
    public $context;
24
25
    /**
26
     * @var null|\drupol\phpvfs\Node\FileInterface
27
     */
28
    private $currentFile;
29
30
    /**
31
     * @return \drupol\phpvfs\Filesystem\FilesystemInterface
32
     */
33 5
    public static function fs(): FilesystemInterface
34
    {
35 5
        $options = \stream_context_get_options(
36 5
            \stream_context_get_default()
37
        );
38
39 5
        return $options[static::SCHEME]['filesystem'];
40
    }
41
42
    /**
43
     * @param \drupol\phpvfs\Filesystem\Filesystem $filesystem
44
     * @param array $options
45
     */
46 5
    public static function register(Filesystem $filesystem, array $options = [])
47
    {
48
        $options = [
49 5
            static::SCHEME => [
50 5
                'filesystem' => $filesystem,
51 5
            ] + $options,
52
        ];
53
54 5
        \stream_context_set_default($options);
55 5
        \stream_wrapper_register(self::SCHEME, __CLASS__);
56 5
    }
57
58
    /**
59
     * @param string $from
60
     * @param string $to
61
     *
62
     * @throws \Exception
63
     *
64
     * @return bool
65
     */
66 1
    public function rename(string $from, string $to): bool
67
    {
68 1
        $from = $this->stripScheme($from);
69 1
        $to = $this->stripScheme($to);
70
71 1
        if (!Exist::exec($this::fs(), $from)) {
72 1
            throw new \Exception('Source resource does not exist.');
73
        }
74
75 1
        $from = Get::exec($this::fs(), $from);
76
77 1
        if (Exist::exec($this::fs(), $to)) {
78 1
            throw new \Exception('Destination already exist.');
79
        }
80
81 1
        $toPath = Path::fromString($to);
82
83 1
        $this::fs()
84 1
            ->getCwd()
85 1
            ->mkdir($toPath->dirname());
86
87 1
        if (null !== $parent = $from->getParent()) {
88 1
            $parent->delete($from);
89
        }
90
91 1
        Cd::exec($this::fs(), $toPath->dirname());
92
93 1
        $from->setAttribute('id', $toPath->basename());
94
95 1
        if ($from instanceof FileInterface) {
96 1
            $from->setPosition(0);
97
        }
98
99 1
        $this::fs()
100 1
            ->getCwd()
101 1
            ->add($from);
102
103 1
        return true;
104
    }
105
106
    /**
107
     * @see http://php.net/streamwrapper.stream-close
108
     */
109 5
    public function stream_close() // phpcs:ignore
110
    {
111 5
        if (null !== $this->currentFile) {
112 5
            $this->currentFile->setPosition(0);
113
        }
114
115 5
        $this->currentFile = null;
116 5
    }
117
118
    /**
119
     * @return bool
120
     *
121
     * @see http://php.net/streamwrapper.stream-eof
122
     */
123 1
    public function stream_eof(): bool // phpcs:ignore
124
    {
125 1
        return true;
126
    }
127
128
    /**
129
     * @param string $resource
130
     * @param mixed $mode
131
     * @param mixed $options
132
     * @param mixed $openedPath
133
     *
134
     * @throws \Exception
135
     *
136
     * @return bool
137
     */
138 5
    public function stream_open(string $resource, $mode, $options, &$openedPath) // phpcs:ignore
0 ignored issues
show
Unused Code introduced by
The parameter $openedPath is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

138
    public function stream_open(string $resource, $mode, $options, /** @scrutinizer ignore-unused */ &$openedPath) // phpcs:ignore

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
139
    {
140 5
        $mode = \str_split(\str_replace('b', '', $mode));
141
142 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...
143 5
        $readMode = \in_array('r', $mode, true);
144 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...
145 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...
146
147 5
        $resource = $this->stripScheme($resource);
148
149 5
        $resourcePath = Path::fromString($resource);
150
151 5
        if (!Exist::exec($this::fs(), $resource)) {
152
            if ($readMode || !Exist::exec($this::fs(), $resourcePath->dirname())) {
153
                if ($options & STREAM_REPORT_ERRORS) {
154
                    \trigger_error(\sprintf('%s: failed to open stream.', $resourcePath), E_USER_WARNING);
155
                }
156
157
                return false;
158
            }
159
160
            $this->currentFile = File::create($resource);
161
            $this::fs()
162
                ->getCwd()
163
                ->add($this->currentFile->root());
164
        }
165
166 5
        if (null === $file = $this::fs()->get($resource)) {
167
            return false;
168
        }
169
170 5
        if (!($file instanceof FileInterface)) {
171
            return false;
172
        }
173
174 5
        $this->currentFile = $file;
175
176 5
        $this->currentFile->setPosition(0);
177
178 5
        return true;
179
    }
180
181
    /**
182
     * @see http://php.net/streamwrapper.stream-read
183
     *
184
     * @param int $bytes
185
     *
186
     * @return mixed
187
     */
188
    public function stream_read(int $bytes) // phpcs:ignore
189
    {
190
        if (null !== $this->currentFile) {
191
            return $this->currentFile->read($bytes);
192
        }
193
194
        return false;
195
    }
196
197
    /**
198
     * @param string $data
199
     *
200
     * @return int
201
     */
202 5
    public function stream_write(string $data) // phpcs:ignore
203
    {
204 5
        if (null !== $this->currentFile) {
205 5
            return $this->currentFile->write($data);
206
        }
207
208
        return 0;
209
    }
210
211
    /**
212
     * @param string $path
213
     *
214
     * @throws \Exception
215
     */
216 1
    public function unlink(string $path)
217
    {
218 1
        $path = $this->stripScheme($path);
219
220 1
        if (true === Exist::exec($this::fs(), $path)) {
221 1
            $file = Get::exec($this::fs(), $path);
222
223 1
            if (null !== $parent = $file->getParent()) {
224 1
                $parent->delete($file);
225
            }
226
        }
227 1
    }
228
229
    /**
230
     * @todo
231
     */
232 5
    public static function unregister()
233
    {
234 5
        \stream_wrapper_unregister(self::SCHEME);
235 5
    }
236
237
    /**
238
     * Returns path stripped of url scheme (http://, ftp://, test:// etc.).
239
     *
240
     * @param string $path
241
     *
242
     * @return string
243
     */
244 5
    protected function stripScheme(string $path): string
245
    {
246 5
        return '/' . \ltrim(\substr($path, 9), '/');
247
    }
248
}
249