StreamWrapper   A
last analyzed

Complexity

Total Complexity 35

Size/Duplication

Total Lines 256
Duplicated Lines 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
eloc 67
dl 0
loc 256
rs 9.6
c 3
b 0
f 0
wmc 35

23 Methods

Rating   Name   Duplication   Size   Complexity  
A dir_rewinddir() 0 13 2
A dir_readdir() 0 6 1
A rename() 0 6 1
A mkdir() 0 8 1
A dir_opendir() 0 9 1
A dir_closedir() 0 11 1
A rmdir() 0 6 1
A stream_set_option() 0 10 1
B stream_open() 0 25 7
A stream_read() 0 6 1
A stream_write() 0 6 1
A stream_eof() 0 6 1
A stream_tell() 0 6 1
A stream_seek() 0 6 1
A stream_cast() 0 2 1
A stream_stat() 0 6 1
A stream_flush() 0 6 1
A url_stat() 0 12 4
A stream_close() 0 9 2
A stream_lock() 0 10 2
A stream_truncate() 0 6 1
A stream_metadata() 0 8 1
A unlink() 0 6 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Yii\Debug\Helper\StreamWrapper;
6
7
use Throwable;
8
9
use function trigger_error;
10
11
use const E_USER_ERROR;
12
use const STREAM_MKDIR_RECURSIVE;
13
use const STREAM_URL_STAT_QUIET;
14
use const STREAM_USE_PATH;
15
16
final class StreamWrapper implements StreamWrapperInterface
17
{
18
    private const STREAM_OPEN_FOR_INCLUDE = 128;
19
20
    /**
21
     * @var resource|null
22
     */
23
    public mixed $context = null;
24
25
    public ?string $filename = null;
26
27
    /**
28
     * @var resource|null
29
     */
30
    public $stream = null;
31
32
    public function dir_closedir(): bool
0 ignored issues
show
Coding Style introduced by
Method name "StreamWrapper::dir_closedir" is not in camel caps format
Loading history...
33
    {
34
        /**
35
         * @psalm-suppress PossiblyNullArgument
36
         */
37
        closedir($this->stream);
38
39
        /**
40
         * @psalm-suppress RedundantCondition
41
         */
42
        return is_resource($this->stream);
43
    }
44
45
    public function dir_opendir(string $path, int $options): bool
0 ignored issues
show
Coding Style introduced by
Method name "StreamWrapper::dir_opendir" is not in camel caps format
Loading history...
46
    {
47
        $this->filename = $path;
48
49
        /**
50
         * @psalm-suppress PossiblyNullArgument
51
         */
52
        $this->stream = opendir($path, $this->context);
53
        return is_resource($this->stream);
54
    }
55
56
    public function dir_readdir(): false|string
0 ignored issues
show
Coding Style introduced by
Method name "StreamWrapper::dir_readdir" is not in camel caps format
Loading history...
57
    {
58
        /**
59
         * @psalm-suppress PossiblyNullArgument
60
         */
61
        return readdir($this->stream);
62
    }
63
64
    public function dir_rewinddir(): bool
0 ignored issues
show
Coding Style introduced by
Method name "StreamWrapper::dir_rewinddir" is not in camel caps format
Loading history...
65
    {
66
        if (!is_resource($this->stream)) {
67
            return false;
68
        }
69
70
        rewinddir($this->stream);
71
72
        /**
73
         * @noinspection PhpConditionAlreadyCheckedInspection
74
         * @psalm-suppress RedundantCondition
75
         */
76
        return is_resource($this->stream);
77
    }
78
79
    public function mkdir(string $path, int $mode, int $options): bool
80
    {
81
        $this->filename = $path;
82
83
        /**
84
         * @psalm-suppress PossiblyNullArgument
85
         */
86
        return mkdir($path, $mode, ($options & STREAM_MKDIR_RECURSIVE) === STREAM_MKDIR_RECURSIVE, $this->context);
87
    }
88
89
    public function rename(string $path_from, string $path_to): bool
90
    {
91
        /**
92
         * @psalm-suppress PossiblyNullArgument
93
         */
94
        return rename($path_from, $path_to, $this->context);
95
    }
96
97
    public function rmdir(string $path, int $options): bool
98
    {
99
        /**
100
         * @psalm-suppress PossiblyNullArgument
101
         */
102
        return rmdir($path, $this->context);
103
    }
104
105
    /**
106
     * @psalm-suppress InvalidReturnType Unfortunately, I don't know what to return here.
107
     */
108
    public function stream_cast(int $castAs): void
0 ignored issues
show
Coding Style introduced by
Method name "StreamWrapper::stream_cast" is not in camel caps format
Loading history...
109
    {
110
        // ???
111
    }
112
113
    public function stream_eof(): bool
0 ignored issues
show
Coding Style introduced by
Method name "StreamWrapper::stream_eof" is not in camel caps format
Loading history...
114
    {
115
        /**
116
         * @psalm-suppress PossiblyNullArgument
117
         */
118
        return feof($this->stream);
119
    }
120
121
    public function stream_open(string $path, string $mode, int $options, ?string &$opened_path): bool
0 ignored issues
show
Coding Style introduced by
Method name "StreamWrapper::stream_open" is not in camel caps format
Loading history...
122
    {
123
        $this->filename = realpath($path) ?: $path;
124
125
        if ((self::STREAM_OPEN_FOR_INCLUDE & $options) === self::STREAM_OPEN_FOR_INCLUDE && function_exists(
0 ignored issues
show
Coding Style introduced by
The first expression of a multi-line control structure must be on the line after the opening parenthesis
Loading history...
126
            'opcache_invalidate'
127
        )) {
0 ignored issues
show
Coding Style introduced by
Each line in a multi-line control structure must be indented at least once; expected at least 12 spaces, but found 8
Loading history...
Coding Style introduced by
The closing parenthesis of a multi-line control structure must be on the line after the last expression
Loading history...
128
            opcache_invalidate($path, false);
129
        }
130
        $this->stream = fopen(
131
            $path,
132
            $mode,
133
            ($options & STREAM_USE_PATH) === STREAM_USE_PATH,
134
            (self::STREAM_OPEN_FOR_INCLUDE & $options) === self::STREAM_OPEN_FOR_INCLUDE ? null : $this->context
135
        );
136
137
        if (!is_resource($this->stream)) {
138
            return false;
139
        }
140
141
        if ($opened_path !== null) {
142
            $metaData = stream_get_meta_data($this->stream);
143
            $opened_path = $metaData['uri'];
144
        }
145
        return true;
146
    }
147
148
    public function stream_read(int $count): string|false
0 ignored issues
show
Coding Style introduced by
Method name "StreamWrapper::stream_read" is not in camel caps format
Loading history...
149
    {
150
        /**
151
         * @psalm-suppress PossiblyNullArgument
152
         */
153
        return fread($this->stream, $count);
154
    }
155
156
    public function stream_seek(int $offset, int $whence = SEEK_SET): bool
0 ignored issues
show
Coding Style introduced by
Method name "StreamWrapper::stream_seek" is not in camel caps format
Loading history...
157
    {
158
        /**
159
         * @psalm-suppress PossiblyNullArgument
160
         */
161
        return fseek($this->stream, $offset, $whence) !== -1;
162
    }
163
164
    public function stream_set_option(int $option, int $arg1, int $arg2): bool
0 ignored issues
show
Coding Style introduced by
Method name "StreamWrapper::stream_set_option" is not in camel caps format
Loading history...
165
    {
166
        /**
167
         * @psalm-suppress PossiblyNullArgument
168
         */
169
        return match ($option) {
170
            STREAM_OPTION_BLOCKING => stream_set_blocking($this->stream, $arg1 === STREAM_OPTION_BLOCKING),
171
            STREAM_OPTION_READ_TIMEOUT => stream_set_timeout($this->stream, $arg1, $arg2),
172
            STREAM_OPTION_WRITE_BUFFER => stream_set_write_buffer($this->stream, $arg2) === 0,
173
            default => false,
174
        };
175
    }
176
177
    public function stream_stat(): array|false
0 ignored issues
show
Coding Style introduced by
Method name "StreamWrapper::stream_stat" is not in camel caps format
Loading history...
178
    {
179
        /**
180
         * @psalm-suppress PossiblyNullArgument
181
         */
182
        return fstat($this->stream);
183
    }
184
185
    public function stream_tell(): int
0 ignored issues
show
Coding Style introduced by
Method name "StreamWrapper::stream_tell" is not in camel caps format
Loading history...
186
    {
187
        /**
188
         * @psalm-suppress PossiblyNullArgument
189
         */
190
        return ftell($this->stream);
191
    }
192
193
    public function stream_write(string $data): int
0 ignored issues
show
Coding Style introduced by
Method name "StreamWrapper::stream_write" is not in camel caps format
Loading history...
194
    {
195
        /**
196
         * @psalm-suppress PossiblyNullArgument
197
         */
198
        return fwrite($this->stream, $data);
199
    }
200
201
    public function url_stat(string $path, int $flags): array|false
0 ignored issues
show
Coding Style introduced by
Method name "StreamWrapper::url_stat" is not in camel caps format
Loading history...
202
    {
203
        try {
204
            if (($flags & STREAM_URL_STAT_QUIET) === STREAM_URL_STAT_QUIET) {
205
                return @stat($path);
206
            }
207
            return stat($path);
208
        } catch (Throwable $e) {
209
            if (($flags & STREAM_URL_STAT_QUIET) === STREAM_URL_STAT_QUIET) {
210
                return false;
211
            }
212
            trigger_error($e->getMessage(), E_USER_ERROR);
0 ignored issues
show
Bug Best Practice introduced by
In this branch, the function will implicitly return null which is incompatible with the type-hinted return array|false. 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...
213
        }
214
    }
215
216
    public function stream_metadata(string $path, int $option, mixed $value): bool
0 ignored issues
show
Coding Style introduced by
Method name "StreamWrapper::stream_metadata" is not in camel caps format
Loading history...
217
    {
218
        return match ($option) {
219
            STREAM_META_TOUCH => touch($path, ...$value),
0 ignored issues
show
Bug introduced by
$value is expanded, but the parameter $mtime of touch() does not expect variable arguments. ( Ignorable by Annotation )

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

219
            STREAM_META_TOUCH => touch($path, /** @scrutinizer ignore-type */ ...$value),
Loading history...
220
            STREAM_META_OWNER_NAME, STREAM_META_OWNER => chown($path, $value),
221
            STREAM_META_GROUP_NAME, STREAM_META_GROUP => chgrp($path, $value),
222
            STREAM_META_ACCESS => chmod($path, $value),
223
            default => false
224
        };
225
    }
226
227
    public function stream_flush(): bool
0 ignored issues
show
Coding Style introduced by
Method name "StreamWrapper::stream_flush" is not in camel caps format
Loading history...
228
    {
229
        /**
230
         * @psalm-suppress PossiblyNullArgument
231
         */
232
        return fflush($this->stream);
233
    }
234
235
    public function stream_close(): void
0 ignored issues
show
Coding Style introduced by
Method name "StreamWrapper::stream_close" is not in camel caps format
Loading history...
236
    {
237
        /**
238
         * @psalm-suppress InvalidPropertyAssignmentValue
239
         */
240
        if ($this->stream !== null) {
241
            fclose($this->stream);
242
        }
243
        $this->stream = null;
244
    }
245
246
    public function stream_lock(int $operation): bool
0 ignored issues
show
Coding Style introduced by
Method name "StreamWrapper::stream_lock" is not in camel caps format
Loading history...
247
    {
248
        if ($operation === 0) {
249
            $operation = LOCK_EX;
250
        }
251
252
        /**
253
         * @psalm-suppress PossiblyNullArgument
254
         */
255
        return flock($this->stream, $operation);
256
    }
257
258
    public function stream_truncate(int $new_size): bool
0 ignored issues
show
Coding Style introduced by
Method name "StreamWrapper::stream_truncate" is not in camel caps format
Loading history...
259
    {
260
        /**
261
         * @psalm-suppress PossiblyNullArgument
262
         */
263
        return ftruncate($this->stream, $new_size);
264
    }
265
266
    public function unlink(string $path): bool
267
    {
268
        /**
269
         * @psalm-suppress PossiblyNullArgument
270
         */
271
        return unlink($path, $this->context);
272
    }
273
}
274