Passed
Pull Request — master (#96)
by
unknown
02:20
created

StreamHandler::__destruct()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
eloc 3
nc 2
nop 0
dl 0
loc 6
ccs 4
cts 4
cp 1
crap 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\VarDumper\Handler;
6
7
use InvalidArgumentException;
8
use RuntimeException;
9
use Socket;
10
use Yiisoft\VarDumper\HandlerInterface;
11
12
use function fsockopen;
13
use function fwrite;
14
use function get_debug_type;
15
use function is_resource;
16
use function is_string;
17
18
final class StreamHandler implements HandlerInterface
19
{
20
    /**
21
     * @var callable|null
22
     */
23
    private $encoder = null;
24
    /**
25
     * @var resource|Socket
26
     * @psalm-suppress PropertyNotSetInConstructor
27
     */
28
    private $stream;
29
30
    /**
31
     * @var resource|Socket|string
32
     */
33
    private $uri;
34
35
    /**
36
     * @param mixed|resource|string $uri
37
     */
38 17
    public function __construct(
39
        mixed $uri = 'udp://127.0.0.1:8890'
40
    ) {
41 17
        if (!is_string($uri) && !is_resource($uri) && !$uri instanceof Socket) {
42 1
            throw new InvalidArgumentException(
43 1
                sprintf(
44 1
                    'Argument $uri must be a string or a resource, "%s" given.',
45 1
                    get_debug_type($uri)
46 1
                )
47 1
            );
48
        }
49 16
        $this->uri = $uri;
50
    }
51
52
    /**
53
     * Encodes {@param $variable} with {@see self::$encoder} and sends the result to the stream.
0 ignored issues
show
Bug introduced by
The type Yiisoft\VarDumper\Handler\with was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
54
     */
55 15
    public function handle(mixed $variable, int $depth, bool $highlight = false): void
56
    {
57 15
        $data = ($this->encoder ?? '\json_encode')($variable);
58 15
        if (!is_string($data)) {
59 1
            throw new RuntimeException(
60 1
                sprintf(
61 1
                    'Encoder must return a string, "%s" returned.',
62 1
                    get_debug_type($data)
63 1
                )
64 1
            );
65
        }
66
67 14
        $this->initializeStream();
68
69 14
        if ($this->stream instanceof Socket) {
70 1
            socket_write($this->stream, $data, strlen($data));
71 1
            return;
72
        }
73
74 13
        if (@fwrite($this->stream, $data) === false) {
75
            $this->initializeStream();
76
77
            if ($this->stream instanceof Socket) {
78
                socket_write($this->stream, $data, strlen($data));
79
                return;
80
            }
81
82
            if (@fwrite($this->stream, $data) === false) {
83
                throw new RuntimeException('Cannot write a stream.');
84
            }
85
        }
86
    }
87
88 3
    public function withEncoder(callable $encoder): HandlerInterface
89
    {
90 3
        $new = clone $this;
91 3
        $new->encoder = $encoder;
92 3
        return $new;
93
    }
94
95 14
    private function initializeStream(): void
96
    {
97 14
        if (is_string($this->uri)) {
98
            if (
99 3
                str_starts_with($this->uri, 'udp://') ||
100 3
                str_starts_with($this->uri, 'udg://') ||
101 1
                str_starts_with($this->uri, 'tcp://') ||
102 3
                str_starts_with($this->uri, 'unix://')
103
            ) {
104 2
                $this->stream = fsockopen($this->uri);
105
            } else {
106 3
                $this->stream = fopen($this->uri, 'wb+');
107
            }
108
        } else {
109 11
            $this->stream = $this->uri;
110
        }
111
112 14
        if (!is_resource($this->stream) && !$this->stream instanceof Socket) {
0 ignored issues
show
introduced by
$this->stream is always a sub-type of Socket.
Loading history...
113 1
            throw new RuntimeException('Cannot initialize a stream.');
114
        }
115
    }
116
117 16
    public function __destruct()
118
    {
119 16
        if (!is_string($this->uri) || !is_resource($this->stream)) {
120 14
            return;
121
        }
122 3
        fclose($this->stream);
123
    }
124
}
125