MongoDownloadStream::write()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 4
ccs 0
cts 4
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
declare(strict_types=1);
3
/**
4
 * Minotaur
5
 *
6
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
7
 * use this file except in compliance with the License. You may obtain a copy of
8
 * the License at
9
 *
10
 * http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing, software
13
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15
 * License for the specific language governing permissions and limitations under
16
 * the License.
17
 *
18
 * @copyright 2015-2017 Appertly
19
 * @license   Apache-2.0
20
 */
21
namespace Minotaur\Db;
22
23
use Psr\Http\Message\StreamInterface;
24
25
/**
26
 * PSR-7 wrapper for MongoDB download stream
27
 */
28
class MongoDownloadStream implements StreamInterface
29
{
30
    /**
31
     * @var \MongoDB\GridFS\ReadableStream
32
     */
33
    private $download;
34
35
    /**
36
     * Creates a new MongoDownloadStream
37
     *
38
     * @param $download - The download object
39
     */
40
    public function __construct(\MongoDB\GridFS\ReadableStream $download)
41
    {
42
        $this->download = $download;
43
    }
44
45
    /**
46
     * Reads all data from the stream into a string, from the beginning to end.
47
     *
48
     * @return string
49
     */
50
    public function __toString(): string
51
    {
52
        return $this->getContents();
53
    }
54
55
    /**
56
     * Closes the stream and any underlying resources.
57
     */
58
    public function close(): void
59
    {
60
        $this->download->close();
61
    }
62
63
    /**
64
     * Separates any underlying resources from the stream.
65
     *
66
     * @return resource|null Underlying PHP stream, if any
67
     */
68
    public function detach()
69
    {
70
        return null;
71
    }
72
73
    /**
74
     * Get the size of the stream if known.
75
     *
76
     * @return int|null Returns the size in bytes if known, or null if unknown.
77
     */
78
    public function getSize(): ?int
79
    {
80
        return $this->download->getSize();
81
    }
82
83
    /**
84
     * Returns the current position of the file read/write pointer
85
     *
86
     * @return int Position of the file pointer
87
     * @throws \RuntimeException on error.
88
     */
89
    public function tell(): int
90
    {
91
        if ($this->download->isEOF()) {
92
            return $this->download->getSize();
93
        } else {
94
            // TODO kind of a messy implementation
95
            $reflectionProperty = new \ReflectionProperty(\MongoDB\GridFS\ReadableStream::class, 'bytesSeen');
96
            $reflectionProperty->setAccessible(true);
97
            return $reflectionProperty->getValue($this->download);
98
        }
99
    }
100
101
    /**
102
     * Returns true if the stream is at the end of the stream.
103
     *
104
     * @return bool
105
     */
106
    public function eof(): bool
107
    {
108
        return $this->download->isEOF();
109
    }
110
111
    /**
112
     * Returns whether or not the stream is seekable.
113
     *
114
     * @return bool
115
     */
116
    public function isSeekable(): bool
117
    {
118
        return false;
119
    }
120
121
    /**
122
     * Seek to a position in the stream.
123
     *
124
     * @link http://www.php.net/manual/en/function.fseek.php
125
     * @param int $offset Stream offset
126
     * @param int $whence Specifies how the cursor position will be calculated
127
     *     based on the seek offset. Valid values are identical to the built-in
128
     *     PHP $whence values for `fseek()`.  SEEK_SET: Set position equal to
129
     *     offset bytes SEEK_CUR: Set position to current location plus offset
130
     *     SEEK_END: Set position to end-of-stream plus offset.
131
     * @throws \RuntimeException on failure.
132
     */
133
    public function seek($offset, $whence = SEEK_SET): void
134
    {
135
        if ($offset === 0 && ($this->tell() === 0 || $whence !== SEEK_SET)) {
136
            return;
137
        }
138
        throw new \BadMethodCallException('Stream is not seekable');
139
    }
140
141
    /**
142
     * Seek to the beginning of the stream.
143
     *
144
     * If the stream is not seekable, this method will raise an exception;
145
     * otherwise, it will perform a seek(0).
146
     *
147
     * @see seek()
148
     * @link http://www.php.net/manual/en/function.fseek.php
149
     * @throws \RuntimeException on failure.
150
     */
151
    public function rewind(): void
152
    {
153
        if ($this->tell() === 0) {
154
            return;
155
        }
156
        throw new \BadMethodCallException('Stream is not seekable');
157
    }
158
159
    /**
160
     * Returns whether or not the stream is writable.
161
     *
162
     * @return bool
163
     */
164
    public function isWritable(): bool
165
    {
166
        return false;
167
    }
168
169
    /**
170
     * Write data to the stream.
171
     *
172
     * @param string $string The string that is to be written.
173
     * @return int Returns the number of bytes written to the stream.
174
     * @throws \RuntimeException on failure.
175
     */
176
    public function write($string): int
177
    {
178
        throw new \BadMethodCallException('Stream is not writable');
179
    }
180
181
    /**
182
     * Returns whether or not the stream is readable.
183
     *
184
     * @return bool
185
     */
186
    public function isReadable(): bool
187
    {
188
        return true;
189
    }
190
191
    /**
192
     * Read data from the stream.
193
     *
194
     * @param int $length Read up to $length bytes from the object and return
195
     *     them. Fewer than $length bytes may be returned if underlying stream
196
     *     call returns fewer bytes.
197
     * @return string Returns the data read from the stream, or an empty string
198
     *     if no bytes are available.
199
     * @throws \RuntimeException if an error occurs.
200
     */
201
    public function read($length): string
202
    {
203
        return $this->download->readBytes($length);
204
    }
205
206
    /**
207
     * Returns the remaining contents in a string
208
     *
209
     * @return string
210
     * @throws \RuntimeException if unable to read or an error occurs while
211
     *     reading.
212
     */
213
    public function getContents(): string
214
    {
215
        return $this->download->readBytes($this->download->getSize());
216
    }
217
218
    /**
219
     * Get stream metadata as an associative array or retrieve a specific key.
220
     *
221
     * The keys returned are identical to the keys returned from PHP's
222
     * stream_get_meta_data() function.
223
     *
224
     * @link http://php.net/manual/en/function.stream-get-meta-data.php
225
     * @param string $key Specific metadata to retrieve.
226
     * @return array|mixed|null Returns an associative array if no key is
227
     *     provided. Returns a specific key value if a key is provided and the
228
     *     value is found, or null if the key is not found.
229
     */
230
    public function getMetadata($key = null)
231
    {
232
        if ($key === null) {
233
            return [];
234
        } else {
235
            return null;
236
        }
237
    }
238
}
239