Completed
Push — master ( 06005b...ba639e )
by Alex
01:33
created

Buffer   A

Complexity

Total Complexity 27

Size/Duplication

Total Lines 161
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 0

Test Coverage

Coverage 92.54%

Importance

Changes 0
Metric Value
wmc 27
lcom 1
cbo 0
dl 0
loc 161
ccs 62
cts 67
cp 0.9254
rs 10
c 0
b 0
f 0

12 Methods

Rating   Name   Duplication   Size   Complexity  
A stream_open() 0 14 2
A stream_eof() 0 4 1
A stream_tell() 0 4 1
A stream_write() 0 15 2
A stream_read() 0 18 3
A stream_seek() 0 17 4
A stream_stat() 0 4 1
A stream_truncate() 0 15 2
A stream_set_option() 0 4 1
A configureLimits() 0 14 4
A canRead() 0 8 3
A canWrite() 0 8 3
1
<?php
2
declare(strict_types=1);
3
4
namespace FakeSocket\Stream;
5
6
use FakeSocket\StreamWrapper;
7
8
final class Buffer implements StreamWrapper
9
{
10
    /** @var string */
11
    private $stream = '';
12
13
    /** @var int */
14
    private $position = 0;
15
16
    /** @var int */
17
    private $readCount = 0;
18
19
    /** @var int */
20
    private $writeCount = 0;
21
22
    /** @var array */
23
    private $limits = [
24
        'read'        => -1,
25
        'read_after'  => 0,
26
        'read_every'  => 1,
27
        'write'       => -1,
28
        'write_after' => 0,
29
        'write_every' => 1,
30
    ];
31
32 8
    public function stream_open($path, $mode, $options, &$opened_path)
0 ignored issues
show
Unused Code introduced by
The parameter $mode is not used and could be removed.

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

Loading history...
Unused Code introduced by
The parameter $options is not used and could be removed.

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

Loading history...
Unused Code introduced by
The parameter $opened_path is not used and could be removed.

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

Loading history...
Coding Style introduced by
Method name "Buffer::stream_open" is not in camel caps format
Loading history...
33
    {
34 8
        $components = parse_url($path);
35
36 8
        static $query = [];
37
38 8
        if (isset($components['query'])) {
39 2
            parse_str($components['query'], $query);
40
        }
41
42 8
        $this->configureLimits($query);
0 ignored issues
show
Bug introduced by
It seems like $query can also be of type null; however, FakeSocket\Stream\Buffer::configureLimits() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
43
44 8
        return true;
45
    }
46
47 5
    public function stream_eof()
0 ignored issues
show
Coding Style introduced by
Method name "Buffer::stream_eof" is not in camel caps format
Loading history...
48
    {
49 5
        return $this->position >= strlen($this->stream);
50
    }
51
52 1
    public function stream_tell()
0 ignored issues
show
Coding Style introduced by
Method name "Buffer::stream_tell" is not in camel caps format
Loading history...
53
    {
54 1
        return $this->position;
55
    }
56
57 5
    public function stream_write($data)
0 ignored issues
show
Coding Style introduced by
Method name "Buffer::stream_write" is not in camel caps format
Loading history...
58
    {
59 5
        ++$this->writeCount;
60
61 5
        if (!$this->canWrite()) {
62 1
            return false;
63
        }
64
65 5
        $left = substr($this->stream, 0, $this->position);
66
67 5
        $this->stream = "{$left}{$data}";
68 5
        $this->position += $bytesWritten = strlen($data);
69
70 5
        return $bytesWritten;
71
    }
72
73 1
    public function stream_read($count)
0 ignored issues
show
Coding Style introduced by
Method name "Buffer::stream_read" is not in camel caps format
Loading history...
74
    {
75 1
        ++$this->readCount;
76
77 1
        if (!$this->canRead()) {
78
            return false;
79
        }
80
81 1
        $data = substr($this->stream, $this->position, $count);
82
83 1
        if (false === $data) {
84
            return false;
85
        }
86
87 1
        $this->position += strlen($data);
88
89 1
        return $data;
90
    }
91
92 1
    public function stream_seek($offset, $whence)
0 ignored issues
show
Coding Style introduced by
Method name "Buffer::stream_seek" is not in camel caps format
Loading history...
93
    {
94 1
        static $values = [SEEK_SET, SEEK_CUR, SEEK_END];
95
96 1
        if (in_array($whence, $values)) {
97 1
            if (SEEK_END === $whence) {
98
                $offset = strlen($this->stream) + $offset;
99
            }
100
101 1
            if ($offset >= 0) {
102 1
                $this->position = $offset;
103 1
                return true;
104
            }
105
        }
106
107
        return false;
108
    }
109
110 1
    public function stream_stat()
0 ignored issues
show
Coding Style introduced by
Method name "Buffer::stream_stat" is not in camel caps format
Loading history...
111
    {
112 1
        return [];
113
    }
114
115 2
    public function stream_truncate($new_size)
0 ignored issues
show
Coding Style introduced by
Method name "Buffer::stream_truncate" is not in camel caps format
Loading history...
116
    {
117 2
        $currentLength = strlen($this->stream);
118
119 2
        if ($new_size > $currentLength) {
120 1
            $multiplier = $new_size - $currentLength;
121 1
            $this->stream .= str_repeat(chr(0), $multiplier);
122
123 1
            return true;
124
        }
125
126 1
        $this->stream = substr($this->stream, 0, $new_size);
127
128 1
        return true;
129
    }
130
131 1
    public function stream_set_option($option, $arg1, $arg2)
0 ignored issues
show
Coding Style introduced by
Method name "Buffer::stream_set_option" is not in camel caps format
Loading history...
132
    {
133 1
        return true;
134
    }
135
136 8
    private function configureLimits(array $query): void
137
    {
138 8
        foreach (array_keys($this->limits) as $limit) {
139 8
            if (!isset($query[$limit])) {
140 8
                continue;
141
            }
142
143 7
            if (false !== strrpos($limit, 'every')) {
144
                $query[$limit] = max(1, (int) $query[$limit]);
145
            }
146
147 7
            $this->limits[$limit] = (int) $query[$limit];
148
        }
149 8
    }
150
151 1
    private function canRead(): bool
152
    {
153 1
        $noLimit = $this->readCount !== $this->limits['read'] + 1;
154
155 1
        return $noLimit
156 1
            && $this->readCount > $this->limits['read_after']
157 1
            && $this->readCount % $this->limits['read_every'] === 0;
158
    }
159
160 5
    private function canWrite(): bool
161
    {
162 5
        $noLimit = $this->writeCount !== $this->limits['write'] + 1;
163
164 5
        return $noLimit
165 5
            && $this->writeCount > $this->limits['write_after']
166 5
            && $this->writeCount % $this->limits['write_every'] === 0;
167
    }
168
}
169