PluginProbe
WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell / 2.8.16
WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell v2.8.16
3.13.4 3.13.3 3.13.2 3.13.1 3.13.0 3.12.13 3.12.12 3.12.11 3.12.10 3.12.9 3.12.8 3.12.7 3.12.6 3.12.5 3.12.4 3.12.3 3.12.1 3.12.2 3.12.0 3.11.1 3.11.0 3.10.9 3.10.8 3.10.7 3.10.6 All 262 releases
wpfunnels / vendor / symfony / http-client / Response / StreamWrapper.php

StreamWrapper.php in WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell 2.8.16, at vendor/symfony/http-client/Response/StreamWrapper.php

314 lines 9.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <[email protected]>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12 namespace Symfony\Component\HttpClient\Response;
13
14 use Symfony\Contracts\HttpClient\Exception\ExceptionInterface;
15 use Symfony\Contracts\HttpClient\HttpClientInterface;
16 use Symfony\Contracts\HttpClient\ResponseInterface;
17
18 /**
19 * Allows turning ResponseInterface instances to PHP streams.
20 *
21 * @author Nicolas Grekas <[email protected]>
22 */
23 class StreamWrapper
24 {
25 /** @var resource|null */
26 public $context;
27
28 /** @var HttpClientInterface */
29 private $client;
30
31 /** @var ResponseInterface */
32 private $response;
33
34 /** @var resource|string|null */
35 private $content;
36
37 /** @var resource|null */
38 private $handle;
39
40 private $blocking = true;
41 private $timeout;
42 private $eof = false;
43 private $offset = 0;
44
45 /**
46 * Creates a PHP stream resource from a ResponseInterface.
47 *
48 * @return resource
49 */
50 public static function createResource(ResponseInterface $response, HttpClientInterface $client = null)
51 {
52 if ($response instanceof StreamableInterface) {
53 $stack = debug_backtrace(\DEBUG_BACKTRACE_PROVIDE_OBJECT | \DEBUG_BACKTRACE_IGNORE_ARGS, 2);
54
55 if ($response !== ($stack[1]['object'] ?? null)) {
56 return $response->toStream(false);
57 }
58 }
59
60 if (null === $client && !method_exists($response, 'stream')) {
61 throw new \InvalidArgumentException(sprintf('Providing a client to "%s()" is required when the response doesn\'t have any "stream()" method.', __CLASS__));
62 }
63
64 static $registered = false;
65
66 if (!$registered = $registered || stream_wrapper_register(strtr(__CLASS__, '\\', '-'), __CLASS__)) {
67 throw new \RuntimeException(error_get_last()['message'] ?? 'Registering the "symfony" stream wrapper failed.');
68 }
69
70 $context = [
71 'client' => $client ?? $response,
72 'response' => $response,
73 ];
74
75 return fopen(strtr(__CLASS__, '\\', '-').'://'.$response->getInfo('url'), 'r', false, stream_context_create(['symfony' => $context]));
76 }
77
78 public function getResponse(): ResponseInterface
79 {
80 return $this->response;
81 }
82
83 /**
84 * @param resource|callable|null $handle The resource handle that should be monitored when
85 * stream_select() is used on the created stream
86 * @param resource|null $content The seekable resource where the response body is buffered
87 */
88 public function bindHandles(&$handle, &$content): void
89 {
90 $this->handle = &$handle;
91 $this->content = &$content;
92 $this->offset = null;
93 }
94
95 public function stream_open(string $path, string $mode, int $options): bool
96 {
97 if ('r' !== $mode) {
98 if ($options & \STREAM_REPORT_ERRORS) {
99 trigger_error(sprintf('Invalid mode "%s": only "r" is supported.', $mode), \E_USER_WARNING);
100 }
101
102 return false;
103 }
104
105 $context = stream_context_get_options($this->context)['symfony'] ?? null;
106 $this->client = $context['client'] ?? null;
107 $this->response = $context['response'] ?? null;
108 $this->context = null;
109
110 if (null !== $this->client && null !== $this->response) {
111 return true;
112 }
113
114 if ($options & \STREAM_REPORT_ERRORS) {
115 trigger_error('Missing options "client" or "response" in "symfony" stream context.', \E_USER_WARNING);
116 }
117
118 return false;
119 }
120
121 public function stream_read(int $count)
122 {
123 if (\is_resource($this->content)) {
124 // Empty the internal activity list
125 foreach ($this->client->stream([$this->response], 0) as $chunk) {
126 try {
127 if (!$chunk->isTimeout() && $chunk->isFirst()) {
128 $this->response->getStatusCode(); // ignore 3/4/5xx
129 }
130 } catch (ExceptionInterface $e) {
131 trigger_error($e->getMessage(), \E_USER_WARNING);
132
133 return false;
134 }
135 }
136
137 if (0 !== fseek($this->content, $this->offset ?? 0)) {
138 return false;
139 }
140
141 if ('' !== $data = fread($this->content, $count)) {
142 fseek($this->content, 0, \SEEK_END);
143 $this->offset += \strlen($data);
144
145 return $data;
146 }
147 }
148
149 if (\is_string($this->content)) {
150 if (\strlen($this->content) <= $count) {
151 $data = $this->content;
152 $this->content = null;
153 } else {
154 $data = substr($this->content, 0, $count);
155 $this->content = substr($this->content, $count);
156 }
157 $this->offset += \strlen($data);
158
159 return $data;
160 }
161
162 foreach ($this->client->stream([$this->response], $this->blocking ? $this->timeout : 0) as $chunk) {
163 try {
164 $this->eof = true;
165 $this->eof = !$chunk->isTimeout();
166
167 if (!$this->eof && !$this->blocking) {
168 return '';
169 }
170
171 $this->eof = $chunk->isLast();
172
173 if ($chunk->isFirst()) {
174 $this->response->getStatusCode(); // ignore 3/4/5xx
175 }
176
177 if ('' !== $data = $chunk->getContent()) {
178 if (\strlen($data) > $count) {
179 if (null === $this->content) {
180 $this->content = substr($data, $count);
181 }
182 $data = substr($data, 0, $count);
183 }
184 $this->offset += \strlen($data);
185
186 return $data;
187 }
188 } catch (ExceptionInterface $e) {
189 trigger_error($e->getMessage(), \E_USER_WARNING);
190
191 return false;
192 }
193 }
194
195 return '';
196 }
197
198 public function stream_set_option(int $option, int $arg1, ?int $arg2): bool
199 {
200 if (\STREAM_OPTION_BLOCKING === $option) {
201 $this->blocking = (bool) $arg1;
202 } elseif (\STREAM_OPTION_READ_TIMEOUT === $option) {
203 $this->timeout = $arg1 + $arg2 / 1e6;
204 } else {
205 return false;
206 }
207
208 return true;
209 }
210
211 public function stream_tell(): int
212 {
213 return $this->offset ?? 0;
214 }
215
216 public function stream_eof(): bool
217 {
218 return $this->eof && !\is_string($this->content);
219 }
220
221 public function stream_seek(int $offset, int $whence = \SEEK_SET): bool
222 {
223 if (null === $this->content && null === $this->offset) {
224 $this->response->getStatusCode();
225 $this->offset = 0;
226 }
227
228 if (!\is_resource($this->content) || 0 !== fseek($this->content, 0, \SEEK_END)) {
229 return false;
230 }
231
232 $size = ftell($this->content);
233
234 if (\SEEK_CUR === $whence) {
235 $offset += $this->offset ?? 0;
236 }
237
238 if (\SEEK_END === $whence || $size < $offset) {
239 foreach ($this->client->stream([$this->response]) as $chunk) {
240 try {
241 if ($chunk->isFirst()) {
242 $this->response->getStatusCode(); // ignore 3/4/5xx
243 }
244
245 // Chunks are buffered in $this->content already
246 $size += \strlen($chunk->getContent());
247
248 if (\SEEK_END !== $whence && $offset <= $size) {
249 break;
250 }
251 } catch (ExceptionInterface $e) {
252 trigger_error($e->getMessage(), \E_USER_WARNING);
253
254 return false;
255 }
256 }
257
258 if (\SEEK_END === $whence) {
259 $offset += $size;
260 }
261 }
262
263 if (0 <= $offset && $offset <= $size) {
264 $this->eof = false;
265 $this->offset = $offset;
266
267 return true;
268 }
269
270 return false;
271 }
272
273 public function stream_cast(int $castAs)
274 {
275 if (\STREAM_CAST_FOR_SELECT === $castAs) {
276 $this->response->getHeaders(false);
277
278 return (\is_callable($this->handle) ? ($this->handle)() : $this->handle) ?? false;
279 }
280
281 return false;
282 }
283
284 public function stream_stat(): array
285 {
286 try {
287 $headers = $this->response->getHeaders(false);
288 } catch (ExceptionInterface $e) {
289 trigger_error($e->getMessage(), \E_USER_WARNING);
290 $headers = [];
291 }
292
293 return [
294 'dev' => 0,
295 'ino' => 0,
296 'mode' => 33060,
297 'nlink' => 0,
298 'uid' => 0,
299 'gid' => 0,
300 'rdev' => 0,
301 'size' => (int) ($headers['content-length'][0] ?? -1),
302 'atime' => 0,
303 'mtime' => strtotime($headers['last-modified'][0] ?? '') ?: 0,
304 'ctime' => 0,
305 'blksize' => 0,
306 'blocks' => 0,
307 ];
308 }
309
310 private function __construct()
311 {
312 }
313 }
314