Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
89.36% |
42 / 47 |
|
70.59% |
12 / 17 |
CRAP | |
0.00% |
0 / 1 |
StringStream | |
89.36% |
42 / 47 |
|
70.59% |
12 / 17 |
30.01 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
copyToStream | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
__toString | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
close | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
detach | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getSize | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
tell | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
eof | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
isSeekable | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
seek | |
92.86% |
13 / 14 |
|
0.00% |
0 / 1 |
7.02 | |||
rewind | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
isWritable | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
write | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
2 | |||
isReadable | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
read | |
85.71% |
6 / 7 |
|
0.00% |
0 / 1 |
4.05 | |||
getContents | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
3 | |||
getMetadata | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | |
3 | namespace MediaWiki\Rest; |
4 | |
5 | use InvalidArgumentException; |
6 | use Stringable; |
7 | |
8 | /** |
9 | * A stream class which uses a string as the underlying storage. Surprisingly, |
10 | * Guzzle does not appear to have one of these. BufferStream does not do what |
11 | * we want. |
12 | * |
13 | * The normal use of this class should be to first write to the stream, then |
14 | * rewind, then read back the whole buffer with getContents(). |
15 | * |
16 | * Seeking is supported, however seeking past the end of the string does not |
17 | * fill with null bytes as in a real file, it throws an exception instead. |
18 | */ |
19 | class StringStream implements Stringable, CopyableStreamInterface { |
20 | |
21 | /** @var string */ |
22 | private $contents; |
23 | /** @var int */ |
24 | private $offset = 0; |
25 | |
26 | /** |
27 | * Construct a StringStream with the given contents. |
28 | * |
29 | * The offset will start at 0, ready for reading. If appending to the |
30 | * given string is desired, you should first seek to the end. |
31 | * |
32 | * @param string $contents |
33 | */ |
34 | public function __construct( $contents = '' ) { |
35 | $this->contents = $contents; |
36 | } |
37 | |
38 | public function copyToStream( $stream ) { |
39 | fwrite( $stream, $this->getContents() ); |
40 | } |
41 | |
42 | public function __toString() { |
43 | return $this->contents; |
44 | } |
45 | |
46 | public function close() { |
47 | } |
48 | |
49 | public function detach() { |
50 | return null; |
51 | } |
52 | |
53 | public function getSize() { |
54 | return strlen( $this->contents ); |
55 | } |
56 | |
57 | public function tell() { |
58 | return $this->offset; |
59 | } |
60 | |
61 | public function eof() { |
62 | return $this->offset >= strlen( $this->contents ); |
63 | } |
64 | |
65 | public function isSeekable() { |
66 | return true; |
67 | } |
68 | |
69 | public function seek( $offset, $whence = SEEK_SET ) { |
70 | switch ( $whence ) { |
71 | case SEEK_SET: |
72 | $this->offset = $offset; |
73 | break; |
74 | |
75 | case SEEK_CUR: |
76 | $this->offset += $offset; |
77 | break; |
78 | |
79 | case SEEK_END: |
80 | $this->offset = strlen( $this->contents ) + $offset; |
81 | break; |
82 | |
83 | default: |
84 | throw new InvalidArgumentException( "Invalid value for \$whence" ); |
85 | } |
86 | if ( $this->offset > strlen( $this->contents ) ) { |
87 | throw new InvalidArgumentException( "Cannot seek beyond the end of a StringStream" ); |
88 | } |
89 | if ( $this->offset < 0 ) { |
90 | throw new InvalidArgumentException( "Cannot seek before the start of a StringStream" ); |
91 | } |
92 | } |
93 | |
94 | public function rewind() { |
95 | $this->offset = 0; |
96 | } |
97 | |
98 | public function isWritable() { |
99 | return true; |
100 | } |
101 | |
102 | public function write( $string ) { |
103 | if ( $this->offset === strlen( $this->contents ) ) { |
104 | $this->contents .= $string; |
105 | } else { |
106 | $this->contents = substr_replace( $this->contents, $string, |
107 | $this->offset, strlen( $string ) ); |
108 | } |
109 | $this->offset += strlen( $string ); |
110 | return strlen( $string ); |
111 | } |
112 | |
113 | public function isReadable() { |
114 | return true; |
115 | } |
116 | |
117 | public function read( $length ) { |
118 | if ( $this->offset === 0 && $length >= strlen( $this->contents ) ) { |
119 | $ret = $this->contents; |
120 | } elseif ( $this->offset >= strlen( $this->contents ) ) { |
121 | $ret = ''; |
122 | } else { |
123 | $ret = substr( $this->contents, $this->offset, $length ); |
124 | } |
125 | $this->offset += strlen( $ret ); |
126 | return $ret; |
127 | } |
128 | |
129 | public function getContents() { |
130 | if ( $this->offset === 0 ) { |
131 | $ret = $this->contents; |
132 | } elseif ( $this->offset >= strlen( $this->contents ) ) { |
133 | $ret = ''; |
134 | } else { |
135 | $ret = substr( $this->contents, $this->offset ); |
136 | } |
137 | $this->offset = strlen( $this->contents ); |
138 | return $ret; |
139 | } |
140 | |
141 | public function getMetadata( $key = null ) { |
142 | return null; |
143 | } |
144 | } |