Proyectos de Subversion Moodle

Rev

| 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
{
21
    /** @var callable|null */
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
    /**
37
     * @param callable(int): (string|null|false)  $source  Source of the stream data. The callable MAY
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);
63
            return '';
64
        }
65
    }
66
 
67
    public function close(): void
68
    {
69
        $this->detach();
70
    }
71
 
72
    public function detach()
73
    {
74
        $this->tellPos = 0;
75
        $this->source = null;
76
 
77
        return null;
78
    }
79
 
80
    public function getSize(): ?int
81
    {
82
        return $this->size;
83
    }
84
 
85
    public function tell(): int
86
    {
87
        return $this->tellPos;
88
    }
89
 
90
    public function eof(): bool
91
    {
92
        return $this->source === null;
93
    }
94
 
95
    public function isSeekable(): bool
96
    {
97
        return false;
98
    }
99
 
100
    public function rewind(): void
101
    {
102
        $this->seek(0);
103
    }
104
 
105
    public function seek($offset, $whence = SEEK_SET): void
106
    {
107
        throw new \RuntimeException('Cannot seek a PumpStream');
108
    }
109
 
110
    public function isWritable(): bool
111
    {
112
        return false;
113
    }
114
 
115
    public function write($string): int
116
    {
117
        throw new \RuntimeException('Cannot write to a PumpStream');
118
    }
119
 
120
    public function isReadable(): bool
121
    {
122
        return true;
123
    }
124
 
125
    public function read($length): string
126
    {
127
        $data = $this->buffer->read($length);
128
        $readLen = strlen($data);
129
        $this->tellPos += $readLen;
130
        $remaining = $length - $readLen;
131
 
132
        if ($remaining) {
133
            $this->pump($remaining);
134
            $data .= $this->buffer->read($remaining);
135
            $this->tellPos += strlen($data) - $readLen;
136
        }
137
 
138
        return $data;
139
    }
140
 
141
    public function getContents(): string
142
    {
143
        $result = '';
144
        while (!$this->eof()) {
145
            $result .= $this->read(1000000);
146
        }
147
 
148
        return $result;
149
    }
150
 
151
    /**
152
     * {@inheritdoc}
153
     *
154
     * @return mixed
155
     */
156
    public function getMetadata($key = null)
157
    {
158
        if (!$key) {
159
            return $this->metadata;
160
        }
161
 
162
        return $this->metadata[$key] ?? null;
163
    }
164
 
165
    private function pump(int $length): void
166
    {
167
        if ($this->source) {
168
            do {
169
                $data = call_user_func($this->source, $length);
170
                if ($data === false || $data === null) {
171
                    $this->source = null;
172
                    return;
173
                }
174
                $this->buffer->write($data);
175
                $length -= strlen($data);
176
            } while ($length > 0);
177
        }
178
    }
179
}