Proyectos de Subversion Moodle

Rev

Rev 1 | | Comparar con el anterior | Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
 
3
declare(strict_types=1);
4
 
5
namespace GuzzleHttp\Psr7;
6
 
7
use Psr\Http\Message\StreamInterface;
8
 
9
/**
10
 * Provides a read only stream that pumps data from a PHP callable.
11
 *
12
 * When invoking the provided callable, the PumpStream will pass the amount of
13
 * data requested to read to the callable. The callable can choose to ignore
14
 * this value and return fewer or more bytes than requested. Any extra data
15
 * returned by the provided callable is buffered internally until drained using
16
 * the read() function of the PumpStream. The provided callable MUST return
17
 * false when there is no more data to read.
18
 */
19
final class PumpStream implements StreamInterface
20
{
1441 ariadna 21
    /** @var callable(int): (string|false|null)|null */
1 efrain 22
    private $source;
23
 
24
    /** @var int|null */
25
    private $size;
26
 
27
    /** @var int */
28
    private $tellPos = 0;
29
 
30
    /** @var array */
31
    private $metadata;
32
 
33
    /** @var BufferStream */
34
    private $buffer;
35
 
36
    /**
1441 ariadna 37
     * @param callable(int): (string|false|null)  $source  Source of the stream data. The callable MAY
1 efrain 38
     *                                                     accept an integer argument used to control the
39
     *                                                     amount of data to return. The callable MUST
40
     *                                                     return a string when called, or false|null on error
41
     *                                                     or EOF.
42
     * @param array{size?: int, metadata?: array} $options Stream options:
43
     *                                                     - metadata: Hash of metadata to use with stream.
44
     *                                                     - size: Size of the stream, if known.
45
     */
46
    public function __construct(callable $source, array $options = [])
47
    {
48
        $this->source = $source;
49
        $this->size = $options['size'] ?? null;
50
        $this->metadata = $options['metadata'] ?? [];
51
        $this->buffer = new BufferStream();
52
    }
53
 
54
    public function __toString(): string
55
    {
56
        try {
57
            return Utils::copyToString($this);
58
        } catch (\Throwable $e) {
59
            if (\PHP_VERSION_ID >= 70400) {
60
                throw $e;
61
            }
62
            trigger_error(sprintf('%s::__toString exception: %s', self::class, (string) $e), E_USER_ERROR);
1441 ariadna 63
 
1 efrain 64
            return '';
65
        }
66
    }
67
 
68
    public function close(): void
69
    {
70
        $this->detach();
71
    }
72
 
73
    public function detach()
74
    {
75
        $this->tellPos = 0;
76
        $this->source = null;
77
 
78
        return null;
79
    }
80
 
81
    public function getSize(): ?int
82
    {
83
        return $this->size;
84
    }
85
 
86
    public function tell(): int
87
    {
88
        return $this->tellPos;
89
    }
90
 
91
    public function eof(): bool
92
    {
93
        return $this->source === null;
94
    }
95
 
96
    public function isSeekable(): bool
97
    {
98
        return false;
99
    }
100
 
101
    public function rewind(): void
102
    {
103
        $this->seek(0);
104
    }
105
 
106
    public function seek($offset, $whence = SEEK_SET): void
107
    {
108
        throw new \RuntimeException('Cannot seek a PumpStream');
109
    }
110
 
111
    public function isWritable(): bool
112
    {
113
        return false;
114
    }
115
 
116
    public function write($string): int
117
    {
118
        throw new \RuntimeException('Cannot write to a PumpStream');
119
    }
120
 
121
    public function isReadable(): bool
122
    {
123
        return true;
124
    }
125
 
126
    public function read($length): string
127
    {
128
        $data = $this->buffer->read($length);
129
        $readLen = strlen($data);
130
        $this->tellPos += $readLen;
131
        $remaining = $length - $readLen;
132
 
133
        if ($remaining) {
134
            $this->pump($remaining);
135
            $data .= $this->buffer->read($remaining);
136
            $this->tellPos += strlen($data) - $readLen;
137
        }
138
 
139
        return $data;
140
    }
141
 
142
    public function getContents(): string
143
    {
144
        $result = '';
145
        while (!$this->eof()) {
146
            $result .= $this->read(1000000);
147
        }
148
 
149
        return $result;
150
    }
151
 
152
    /**
153
     * @return mixed
154
     */
155
    public function getMetadata($key = null)
156
    {
157
        if (!$key) {
158
            return $this->metadata;
159
        }
160
 
161
        return $this->metadata[$key] ?? null;
162
    }
163
 
164
    private function pump(int $length): void
165
    {
1441 ariadna 166
        if ($this->source !== null) {
1 efrain 167
            do {
1441 ariadna 168
                $data = ($this->source)($length);
1 efrain 169
                if ($data === false || $data === null) {
170
                    $this->source = null;
1441 ariadna 171
 
1 efrain 172
                    return;
173
                }
174
                $this->buffer->write($data);
175
                $length -= strlen($data);
176
            } while ($length > 0);
177
        }
178
    }
179
}