Completed
Push — 2.1 ( dc42a5...e82b9c )
by
unknown
12:47
created

MemoryStream::write()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 18
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 18
ccs 12
cts 12
cp 1
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 12
nc 2
nop 1
crap 2
1
<?php
2
/**
3
 * @link http://www.yiiframework.com/
4
 * @copyright Copyright (c) 2008 Yii Software LLC
5
 * @license http://www.yiiframework.com/license/
6
 */
7
8
namespace yii\http;
9
10
use Psr\Http\Message\StreamInterface;
11
use yii\base\BaseObject;
12
use yii\base\InvalidArgumentException;
13
14
/**
15
 * MemoryStream uses internal field as a stream source. Thus data associated with this stream exists only in
16
 * memory and will be lost once stream is closed.
17
 *
18
 * Example:
19
 *
20
 * ```php
21
 * $stream = new MemoryStream();
22
 *
23
 * $stream->write('some content...');
24
 * // ...
25
 * $stream->rewind();
26
 * echo $stream->getContents();
27
 * ```
28
 *
29
 * @author Paul Klimov <[email protected]>
30
 * @since 2.1.0
31
 */
32
class MemoryStream extends BaseObject implements StreamInterface
33
{
34
    /**
35
     * @var string internal content.
36
     */
37
    private $buffer = '';
38
    /**
39
     * @var int internal stream pointer.
40
     */
41
    private $pointer = 0;
42
43
44
    /**
45
     * {@inheritdoc}
46
     */
47 54
    public function __toString()
48
    {
49 54
        return $this->buffer;
50
    }
51
52
    /**
53
     * {@inheritdoc}
54
     */
55 18
    public function close()
56
    {
57 18
        $this->buffer = '';
58 18
        $this->pointer = 0;
59 18
    }
60
61
    /**
62
     * {@inheritdoc}
63
     */
64
    public function detach()
65
    {
66
        $this->close();
67
        return null;
68
    }
69
70
    /**
71
     * {@inheritdoc}
72
     */
73 63
    public function getSize()
74
    {
75 63
        return strlen($this->buffer);
76
    }
77
78
    /**
79
     * {@inheritdoc}
80
     */
81
    public function tell()
82
    {
83
        return $this->pointer;
84
    }
85
86
    /**
87
     * {@inheritdoc}
88
     */
89 19
    public function eof()
90
    {
91 19
        return $this->pointer >= $this->getSize();
92
    }
93
94
    /**
95
     * {@inheritdoc}
96
     */
97 20
    public function isSeekable()
98
    {
99 20
        return true;
100
    }
101
102
    /**
103
     * {@inheritdoc}
104
     */
105 23
    public function seek($offset, $whence = SEEK_SET)
106
    {
107
        switch ($whence) {
108 23
            case SEEK_SET:
109 23
                $this->pointer = $offset;
110 23
                break;
111
            case SEEK_CUR:
112
                $this->pointer += $offset;
113
                break;
114
            case SEEK_END:
115
                $this->pointer = $this->getSize() + $offset;
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->getSize() + $offset can also be of type double. However, the property $pointer is declared as type integer. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
116
                break;
117
            default:
118
                throw new InvalidArgumentException("Unknown seek whence: '{$whence}'.");
119
        }
120 23
    }
121
122
    /**
123
     * {@inheritdoc}
124
     */
125 4
    public function rewind()
126
    {
127 4
        $this->seek(0);
128 4
    }
129
130
    /**
131
     * {@inheritdoc}
132
     */
133 1
    public function isWritable()
134
    {
135 1
        return true;
136
    }
137
138
    /**
139
     * {@inheritdoc}
140
     */
141 63
    public function write($string)
142
    {
143 63
        $size = $this->getSize();
144 63
        $writeSize = strlen($string);
145
146 63
        if ($this->pointer >= $size) {
147 63
            $this->buffer .= $string;
148 63
            $this->pointer = $size + $writeSize;
0 ignored issues
show
Documentation Bug introduced by
It seems like $size + $writeSize can also be of type double. However, the property $pointer is declared as type integer. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
149 63
            return $writeSize;
150
        }
151
152 1
        $begin = substr($this->buffer, 0, $this->pointer);
153 1
        $end = substr($this->buffer, $this->pointer + $writeSize);
154
155 1
        $this->buffer = $begin . $string . $end;
156 1
        $this->pointer += $writeSize;
157 1
        return $writeSize;
158
    }
159
160
    /**
161
     * {@inheritdoc}
162
     */
163 19
    public function isReadable()
164
    {
165 19
        return true;
166
    }
167
168
    /**
169
     * {@inheritdoc}
170
     */
171 20
    public function read($length)
172
    {
173 20
        $data = substr($this->buffer, $this->pointer, $length);
174 20
        $this->pointer += $length;
175 20
        return $data;
176
    }
177
178
    /**
179
     * {@inheritdoc}
180
     */
181 1
    public function getContents()
182
    {
183 1
        if ($this->pointer === 0) {
184 1
            return $this->buffer;
185
        }
186 1
        return substr($this->buffer, $this->pointer);
187
    }
188
189
    /**
190
     * {@inheritdoc}
191
     */
192 1
    public function getMetadata($key = null)
193
    {
194
        $metadata = [
195 1
            'mode' => 'rw',
196 1
            'seekable' => $this->isSeekable(),
197
        ];
198
199 1
        if ($key === null) {
200 1
            return $metadata;
201
        }
202
203 1
        return (isset($metadata[$key])) ? $metadata[$key] : null;
204
    }
205
}