Completed
Push — master ( 444b7c...2b29c8 )
by Maxence
17s queued 14s
created
lib/Vendor/GuzzleHttp/MessageFormatter.php 1 patch
Indentation   +129 added lines, -129 removed lines patch added patch discarded remove patch
@@ -36,133 +36,133 @@
 block discarded – undo
36 36
  */
37 37
 class MessageFormatter implements MessageFormatterInterface
38 38
 {
39
-    /**
40
-     * Apache Common Log Format.
41
-     *
42
-     * @see https://httpd.apache.org/docs/2.4/logs.html#common
43
-     *
44
-     * @var string
45
-     */
46
-    public const CLF = '{hostname} {req_header_User-Agent} - [{date_common_log}] "{method} {target} HTTP/{version}" {code} {res_header_Content-Length}';
47
-    public const DEBUG = ">>>>>>>>\n{request}\n<<<<<<<<\n{response}\n--------\n{error}";
48
-    public const SHORT = '[{ts}] "{method} {target} HTTP/{version}" {code}';
49
-    /**
50
-     * @var string Template used to format log messages
51
-     */
52
-    private $template;
53
-    /**
54
-     * @param string $template Log message template
55
-     */
56
-    public function __construct(?string $template = self::CLF)
57
-    {
58
-        $this->template = $template ?: self::CLF;
59
-    }
60
-    /**
61
-     * Returns a formatted message string.
62
-     *
63
-     * @param RequestInterface       $request  Request that was sent
64
-     * @param ResponseInterface|null $response Response that was received
65
-     * @param \Throwable|null        $error    Exception that was received
66
-     */
67
-    public function format(RequestInterface $request, ?ResponseInterface $response = null, ?\Throwable $error = null) : string
68
-    {
69
-        $cache = [];
70
-        /** @var string */
71
-        return \preg_replace_callback('/{\\s*([A-Za-z_\\-\\.0-9]+)\\s*}/', function (array $matches) use($request, $response, $error, &$cache) {
72
-            if (isset($cache[$matches[1]])) {
73
-                return $cache[$matches[1]];
74
-            }
75
-            $result = '';
76
-            switch ($matches[1]) {
77
-                case 'request':
78
-                    $result = Psr7\Message::toString($request);
79
-                    break;
80
-                case 'response':
81
-                    $result = $response ? Psr7\Message::toString($response) : '';
82
-                    break;
83
-                case 'req_headers':
84
-                    $result = \trim($request->getMethod() . ' ' . $request->getRequestTarget()) . ' HTTP/' . $request->getProtocolVersion() . "\r\n" . $this->headers($request);
85
-                    break;
86
-                case 'res_headers':
87
-                    $result = $response ? \sprintf('HTTP/%s %d %s', $response->getProtocolVersion(), $response->getStatusCode(), $response->getReasonPhrase()) . "\r\n" . $this->headers($response) : 'NULL';
88
-                    break;
89
-                case 'req_body':
90
-                    $result = $request->getBody()->__toString();
91
-                    break;
92
-                case 'res_body':
93
-                    if (!$response instanceof ResponseInterface) {
94
-                        $result = 'NULL';
95
-                        break;
96
-                    }
97
-                    $body = $response->getBody();
98
-                    if (!$body->isSeekable()) {
99
-                        $result = 'RESPONSE_NOT_LOGGEABLE';
100
-                        break;
101
-                    }
102
-                    $result = $response->getBody()->__toString();
103
-                    break;
104
-                case 'ts':
105
-                case 'date_iso_8601':
106
-                    $result = \gmdate('c');
107
-                    break;
108
-                case 'date_common_log':
109
-                    $result = \date('d/M/Y:H:i:s O');
110
-                    break;
111
-                case 'method':
112
-                    $result = $request->getMethod();
113
-                    break;
114
-                case 'version':
115
-                    $result = $request->getProtocolVersion();
116
-                    break;
117
-                case 'uri':
118
-                case 'url':
119
-                    $result = $request->getUri()->__toString();
120
-                    break;
121
-                case 'target':
122
-                    $result = $request->getRequestTarget();
123
-                    break;
124
-                case 'req_version':
125
-                    $result = $request->getProtocolVersion();
126
-                    break;
127
-                case 'res_version':
128
-                    $result = $response ? $response->getProtocolVersion() : 'NULL';
129
-                    break;
130
-                case 'host':
131
-                    $result = $request->getHeaderLine('Host');
132
-                    break;
133
-                case 'hostname':
134
-                    $result = \gethostname();
135
-                    break;
136
-                case 'code':
137
-                    $result = $response ? $response->getStatusCode() : 'NULL';
138
-                    break;
139
-                case 'phrase':
140
-                    $result = $response ? $response->getReasonPhrase() : 'NULL';
141
-                    break;
142
-                case 'error':
143
-                    $result = $error ? $error->getMessage() : 'NULL';
144
-                    break;
145
-                default:
146
-                    // handle prefixed dynamic headers
147
-                    if (\strpos($matches[1], 'req_header_') === 0) {
148
-                        $result = $request->getHeaderLine(\substr($matches[1], 11));
149
-                    } elseif (\strpos($matches[1], 'res_header_') === 0) {
150
-                        $result = $response ? $response->getHeaderLine(\substr($matches[1], 11)) : 'NULL';
151
-                    }
152
-            }
153
-            $cache[$matches[1]] = $result;
154
-            return $result;
155
-        }, $this->template);
156
-    }
157
-    /**
158
-     * Get headers from message as string
159
-     */
160
-    private function headers(MessageInterface $message) : string
161
-    {
162
-        $result = '';
163
-        foreach ($message->getHeaders() as $name => $values) {
164
-            $result .= $name . ': ' . \implode(', ', $values) . "\r\n";
165
-        }
166
-        return \trim($result);
167
-    }
39
+	/**
40
+	 * Apache Common Log Format.
41
+	 *
42
+	 * @see https://httpd.apache.org/docs/2.4/logs.html#common
43
+	 *
44
+	 * @var string
45
+	 */
46
+	public const CLF = '{hostname} {req_header_User-Agent} - [{date_common_log}] "{method} {target} HTTP/{version}" {code} {res_header_Content-Length}';
47
+	public const DEBUG = ">>>>>>>>\n{request}\n<<<<<<<<\n{response}\n--------\n{error}";
48
+	public const SHORT = '[{ts}] "{method} {target} HTTP/{version}" {code}';
49
+	/**
50
+	 * @var string Template used to format log messages
51
+	 */
52
+	private $template;
53
+	/**
54
+	 * @param string $template Log message template
55
+	 */
56
+	public function __construct(?string $template = self::CLF)
57
+	{
58
+		$this->template = $template ?: self::CLF;
59
+	}
60
+	/**
61
+	 * Returns a formatted message string.
62
+	 *
63
+	 * @param RequestInterface       $request  Request that was sent
64
+	 * @param ResponseInterface|null $response Response that was received
65
+	 * @param \Throwable|null        $error    Exception that was received
66
+	 */
67
+	public function format(RequestInterface $request, ?ResponseInterface $response = null, ?\Throwable $error = null) : string
68
+	{
69
+		$cache = [];
70
+		/** @var string */
71
+		return \preg_replace_callback('/{\\s*([A-Za-z_\\-\\.0-9]+)\\s*}/', function (array $matches) use($request, $response, $error, &$cache) {
72
+			if (isset($cache[$matches[1]])) {
73
+				return $cache[$matches[1]];
74
+			}
75
+			$result = '';
76
+			switch ($matches[1]) {
77
+				case 'request':
78
+					$result = Psr7\Message::toString($request);
79
+					break;
80
+				case 'response':
81
+					$result = $response ? Psr7\Message::toString($response) : '';
82
+					break;
83
+				case 'req_headers':
84
+					$result = \trim($request->getMethod() . ' ' . $request->getRequestTarget()) . ' HTTP/' . $request->getProtocolVersion() . "\r\n" . $this->headers($request);
85
+					break;
86
+				case 'res_headers':
87
+					$result = $response ? \sprintf('HTTP/%s %d %s', $response->getProtocolVersion(), $response->getStatusCode(), $response->getReasonPhrase()) . "\r\n" . $this->headers($response) : 'NULL';
88
+					break;
89
+				case 'req_body':
90
+					$result = $request->getBody()->__toString();
91
+					break;
92
+				case 'res_body':
93
+					if (!$response instanceof ResponseInterface) {
94
+						$result = 'NULL';
95
+						break;
96
+					}
97
+					$body = $response->getBody();
98
+					if (!$body->isSeekable()) {
99
+						$result = 'RESPONSE_NOT_LOGGEABLE';
100
+						break;
101
+					}
102
+					$result = $response->getBody()->__toString();
103
+					break;
104
+				case 'ts':
105
+				case 'date_iso_8601':
106
+					$result = \gmdate('c');
107
+					break;
108
+				case 'date_common_log':
109
+					$result = \date('d/M/Y:H:i:s O');
110
+					break;
111
+				case 'method':
112
+					$result = $request->getMethod();
113
+					break;
114
+				case 'version':
115
+					$result = $request->getProtocolVersion();
116
+					break;
117
+				case 'uri':
118
+				case 'url':
119
+					$result = $request->getUri()->__toString();
120
+					break;
121
+				case 'target':
122
+					$result = $request->getRequestTarget();
123
+					break;
124
+				case 'req_version':
125
+					$result = $request->getProtocolVersion();
126
+					break;
127
+				case 'res_version':
128
+					$result = $response ? $response->getProtocolVersion() : 'NULL';
129
+					break;
130
+				case 'host':
131
+					$result = $request->getHeaderLine('Host');
132
+					break;
133
+				case 'hostname':
134
+					$result = \gethostname();
135
+					break;
136
+				case 'code':
137
+					$result = $response ? $response->getStatusCode() : 'NULL';
138
+					break;
139
+				case 'phrase':
140
+					$result = $response ? $response->getReasonPhrase() : 'NULL';
141
+					break;
142
+				case 'error':
143
+					$result = $error ? $error->getMessage() : 'NULL';
144
+					break;
145
+				default:
146
+					// handle prefixed dynamic headers
147
+					if (\strpos($matches[1], 'req_header_') === 0) {
148
+						$result = $request->getHeaderLine(\substr($matches[1], 11));
149
+					} elseif (\strpos($matches[1], 'res_header_') === 0) {
150
+						$result = $response ? $response->getHeaderLine(\substr($matches[1], 11)) : 'NULL';
151
+					}
152
+			}
153
+			$cache[$matches[1]] = $result;
154
+			return $result;
155
+		}, $this->template);
156
+	}
157
+	/**
158
+	 * Get headers from message as string
159
+	 */
160
+	private function headers(MessageInterface $message) : string
161
+	{
162
+		$result = '';
163
+		foreach ($message->getHeaders() as $name => $values) {
164
+			$result .= $name . ': ' . \implode(', ', $values) . "\r\n";
165
+		}
166
+		return \trim($result);
167
+	}
168 168
 }
Please login to merge, or discard this patch.
lib/Vendor/GuzzleHttp/Middleware.php 2 patches
Indentation   +210 added lines, -210 removed lines patch added patch discarded remove patch
@@ -14,214 +14,214 @@
 block discarded – undo
14 14
  */
15 15
 final class Middleware
16 16
 {
17
-    /**
18
-     * Middleware that adds cookies to requests.
19
-     *
20
-     * The options array must be set to a CookieJarInterface in order to use
21
-     * cookies. This is typically handled for you by a client.
22
-     *
23
-     * @return callable Returns a function that accepts the next handler.
24
-     */
25
-    public static function cookies() : callable
26
-    {
27
-        return static function (callable $handler) : callable {
28
-            return static function ($request, array $options) use($handler) {
29
-                if (empty($options['cookies'])) {
30
-                    return $handler($request, $options);
31
-                } elseif (!$options['cookies'] instanceof CookieJarInterface) {
32
-                    throw new \InvalidArgumentException('OCA\\FullTextSearch_Elasticsearch\\Vendor\\cookies must be an instance of GuzzleHttp\\Cookie\\CookieJarInterface');
33
-                }
34
-                $cookieJar = $options['cookies'];
35
-                $request = $cookieJar->withCookieHeader($request);
36
-                return $handler($request, $options)->then(static function (ResponseInterface $response) use($cookieJar, $request) : ResponseInterface {
37
-                    $cookieJar->extractCookies($request, $response);
38
-                    return $response;
39
-                });
40
-            };
41
-        };
42
-    }
43
-    /**
44
-     * Middleware that throws exceptions for 4xx or 5xx responses when the
45
-     * "http_errors" request option is set to true.
46
-     *
47
-     * @param BodySummarizerInterface|null $bodySummarizer The body summarizer to use in exception messages.
48
-     *
49
-     * @return callable(callable): callable Returns a function that accepts the next handler.
50
-     */
51
-    public static function httpErrors(?BodySummarizerInterface $bodySummarizer = null) : callable
52
-    {
53
-        return static function (callable $handler) use($bodySummarizer) : callable {
54
-            return static function ($request, array $options) use($handler, $bodySummarizer) {
55
-                if (empty($options['http_errors'])) {
56
-                    return $handler($request, $options);
57
-                }
58
-                return $handler($request, $options)->then(static function (ResponseInterface $response) use($request, $bodySummarizer) {
59
-                    $code = $response->getStatusCode();
60
-                    if ($code < 400) {
61
-                        return $response;
62
-                    }
63
-                    throw RequestException::create($request, $response, null, [], $bodySummarizer);
64
-                });
65
-            };
66
-        };
67
-    }
68
-    /**
69
-     * Middleware that pushes history data to an ArrayAccess container.
70
-     *
71
-     * @param array|\ArrayAccess<int, array> $container Container to hold the history (by reference).
72
-     *
73
-     * @return callable(callable): callable Returns a function that accepts the next handler.
74
-     *
75
-     * @throws \InvalidArgumentException if container is not an array or ArrayAccess.
76
-     */
77
-    public static function history(&$container) : callable
78
-    {
79
-        if (!\is_array($container) && !$container instanceof \ArrayAccess) {
80
-            throw new \InvalidArgumentException('history container must be an array or object implementing ArrayAccess');
81
-        }
82
-        return static function (callable $handler) use(&$container) : callable {
83
-            return static function (RequestInterface $request, array $options) use($handler, &$container) {
84
-                return $handler($request, $options)->then(static function ($value) use($request, &$container, $options) {
85
-                    $container[] = ['request' => $request, 'response' => $value, 'error' => null, 'options' => $options];
86
-                    return $value;
87
-                }, static function ($reason) use($request, &$container, $options) {
88
-                    $container[] = ['request' => $request, 'response' => null, 'error' => $reason, 'options' => $options];
89
-                    return P\Create::rejectionFor($reason);
90
-                });
91
-            };
92
-        };
93
-    }
94
-    /**
95
-     * Middleware that invokes a callback before and after sending a request.
96
-     *
97
-     * The provided listener cannot modify or alter the response. It simply
98
-     * "taps" into the chain to be notified before returning the promise. The
99
-     * before listener accepts a request and options array, and the after
100
-     * listener accepts a request, options array, and response promise.
101
-     *
102
-     * @param callable $before Function to invoke before forwarding the request.
103
-     * @param callable $after  Function invoked after forwarding.
104
-     *
105
-     * @return callable Returns a function that accepts the next handler.
106
-     */
107
-    public static function tap(?callable $before = null, ?callable $after = null) : callable
108
-    {
109
-        return static function (callable $handler) use($before, $after) : callable {
110
-            return static function (RequestInterface $request, array $options) use($handler, $before, $after) {
111
-                if ($before) {
112
-                    $before($request, $options);
113
-                }
114
-                $response = $handler($request, $options);
115
-                if ($after) {
116
-                    $after($request, $options, $response);
117
-                }
118
-                return $response;
119
-            };
120
-        };
121
-    }
122
-    /**
123
-     * Middleware that handles request redirects.
124
-     *
125
-     * @return callable Returns a function that accepts the next handler.
126
-     */
127
-    public static function redirect() : callable
128
-    {
129
-        return static function (callable $handler) : RedirectMiddleware {
130
-            return new RedirectMiddleware($handler);
131
-        };
132
-    }
133
-    /**
134
-     * Middleware that retries requests based on the boolean result of
135
-     * invoking the provided "decider" function.
136
-     *
137
-     * If no delay function is provided, a simple implementation of exponential
138
-     * backoff will be utilized.
139
-     *
140
-     * @param callable $decider Function that accepts the number of retries,
141
-     *                          a request, [response], and [exception] and
142
-     *                          returns true if the request is to be retried.
143
-     * @param callable $delay   Function that accepts the number of retries and
144
-     *                          returns the number of milliseconds to delay.
145
-     *
146
-     * @return callable Returns a function that accepts the next handler.
147
-     */
148
-    public static function retry(callable $decider, ?callable $delay = null) : callable
149
-    {
150
-        return static function (callable $handler) use($decider, $delay) : RetryMiddleware {
151
-            return new RetryMiddleware($decider, $handler, $delay);
152
-        };
153
-    }
154
-    /**
155
-     * Middleware that logs requests, responses, and errors using a message
156
-     * formatter.
157
-     *
158
-     * @phpstan-param \Psr\Log\LogLevel::* $logLevel  Level at which to log requests.
159
-     *
160
-     * @param LoggerInterface                            $logger    Logs messages.
161
-     * @param MessageFormatterInterface|MessageFormatter $formatter Formatter used to create message strings.
162
-     * @param string                                     $logLevel  Level at which to log requests.
163
-     *
164
-     * @return callable Returns a function that accepts the next handler.
165
-     */
166
-    public static function log(LoggerInterface $logger, $formatter, string $logLevel = 'info') : callable
167
-    {
168
-        // To be compatible with Guzzle 7.1.x we need to allow users to pass a MessageFormatter
169
-        if (!$formatter instanceof MessageFormatter && !$formatter instanceof MessageFormatterInterface) {
170
-            throw new \LogicException(\sprintf('Argument 2 to %s::log() must be of type %s', self::class, MessageFormatterInterface::class));
171
-        }
172
-        return static function (callable $handler) use($logger, $formatter, $logLevel) : callable {
173
-            return static function (RequestInterface $request, array $options = []) use($handler, $logger, $formatter, $logLevel) {
174
-                return $handler($request, $options)->then(static function ($response) use($logger, $request, $formatter, $logLevel) : ResponseInterface {
175
-                    $message = $formatter->format($request, $response);
176
-                    $logger->log($logLevel, $message);
177
-                    return $response;
178
-                }, static function ($reason) use($logger, $request, $formatter) : PromiseInterface {
179
-                    $response = $reason instanceof RequestException ? $reason->getResponse() : null;
180
-                    $message = $formatter->format($request, $response, P\Create::exceptionFor($reason));
181
-                    $logger->error($message);
182
-                    return P\Create::rejectionFor($reason);
183
-                });
184
-            };
185
-        };
186
-    }
187
-    /**
188
-     * This middleware adds a default content-type if possible, a default
189
-     * content-length or transfer-encoding header, and the expect header.
190
-     */
191
-    public static function prepareBody() : callable
192
-    {
193
-        return static function (callable $handler) : PrepareBodyMiddleware {
194
-            return new PrepareBodyMiddleware($handler);
195
-        };
196
-    }
197
-    /**
198
-     * Middleware that applies a map function to the request before passing to
199
-     * the next handler.
200
-     *
201
-     * @param callable $fn Function that accepts a RequestInterface and returns
202
-     *                     a RequestInterface.
203
-     */
204
-    public static function mapRequest(callable $fn) : callable
205
-    {
206
-        return static function (callable $handler) use($fn) : callable {
207
-            return static function (RequestInterface $request, array $options) use($handler, $fn) {
208
-                return $handler($fn($request), $options);
209
-            };
210
-        };
211
-    }
212
-    /**
213
-     * Middleware that applies a map function to the resolved promise's
214
-     * response.
215
-     *
216
-     * @param callable $fn Function that accepts a ResponseInterface and
217
-     *                     returns a ResponseInterface.
218
-     */
219
-    public static function mapResponse(callable $fn) : callable
220
-    {
221
-        return static function (callable $handler) use($fn) : callable {
222
-            return static function (RequestInterface $request, array $options) use($handler, $fn) {
223
-                return $handler($request, $options)->then($fn);
224
-            };
225
-        };
226
-    }
17
+	/**
18
+	 * Middleware that adds cookies to requests.
19
+	 *
20
+	 * The options array must be set to a CookieJarInterface in order to use
21
+	 * cookies. This is typically handled for you by a client.
22
+	 *
23
+	 * @return callable Returns a function that accepts the next handler.
24
+	 */
25
+	public static function cookies() : callable
26
+	{
27
+		return static function (callable $handler) : callable {
28
+			return static function ($request, array $options) use($handler) {
29
+				if (empty($options['cookies'])) {
30
+					return $handler($request, $options);
31
+				} elseif (!$options['cookies'] instanceof CookieJarInterface) {
32
+					throw new \InvalidArgumentException('OCA\\FullTextSearch_Elasticsearch\\Vendor\\cookies must be an instance of GuzzleHttp\\Cookie\\CookieJarInterface');
33
+				}
34
+				$cookieJar = $options['cookies'];
35
+				$request = $cookieJar->withCookieHeader($request);
36
+				return $handler($request, $options)->then(static function (ResponseInterface $response) use($cookieJar, $request) : ResponseInterface {
37
+					$cookieJar->extractCookies($request, $response);
38
+					return $response;
39
+				});
40
+			};
41
+		};
42
+	}
43
+	/**
44
+	 * Middleware that throws exceptions for 4xx or 5xx responses when the
45
+	 * "http_errors" request option is set to true.
46
+	 *
47
+	 * @param BodySummarizerInterface|null $bodySummarizer The body summarizer to use in exception messages.
48
+	 *
49
+	 * @return callable(callable): callable Returns a function that accepts the next handler.
50
+	 */
51
+	public static function httpErrors(?BodySummarizerInterface $bodySummarizer = null) : callable
52
+	{
53
+		return static function (callable $handler) use($bodySummarizer) : callable {
54
+			return static function ($request, array $options) use($handler, $bodySummarizer) {
55
+				if (empty($options['http_errors'])) {
56
+					return $handler($request, $options);
57
+				}
58
+				return $handler($request, $options)->then(static function (ResponseInterface $response) use($request, $bodySummarizer) {
59
+					$code = $response->getStatusCode();
60
+					if ($code < 400) {
61
+						return $response;
62
+					}
63
+					throw RequestException::create($request, $response, null, [], $bodySummarizer);
64
+				});
65
+			};
66
+		};
67
+	}
68
+	/**
69
+	 * Middleware that pushes history data to an ArrayAccess container.
70
+	 *
71
+	 * @param array|\ArrayAccess<int, array> $container Container to hold the history (by reference).
72
+	 *
73
+	 * @return callable(callable): callable Returns a function that accepts the next handler.
74
+	 *
75
+	 * @throws \InvalidArgumentException if container is not an array or ArrayAccess.
76
+	 */
77
+	public static function history(&$container) : callable
78
+	{
79
+		if (!\is_array($container) && !$container instanceof \ArrayAccess) {
80
+			throw new \InvalidArgumentException('history container must be an array or object implementing ArrayAccess');
81
+		}
82
+		return static function (callable $handler) use(&$container) : callable {
83
+			return static function (RequestInterface $request, array $options) use($handler, &$container) {
84
+				return $handler($request, $options)->then(static function ($value) use($request, &$container, $options) {
85
+					$container[] = ['request' => $request, 'response' => $value, 'error' => null, 'options' => $options];
86
+					return $value;
87
+				}, static function ($reason) use($request, &$container, $options) {
88
+					$container[] = ['request' => $request, 'response' => null, 'error' => $reason, 'options' => $options];
89
+					return P\Create::rejectionFor($reason);
90
+				});
91
+			};
92
+		};
93
+	}
94
+	/**
95
+	 * Middleware that invokes a callback before and after sending a request.
96
+	 *
97
+	 * The provided listener cannot modify or alter the response. It simply
98
+	 * "taps" into the chain to be notified before returning the promise. The
99
+	 * before listener accepts a request and options array, and the after
100
+	 * listener accepts a request, options array, and response promise.
101
+	 *
102
+	 * @param callable $before Function to invoke before forwarding the request.
103
+	 * @param callable $after  Function invoked after forwarding.
104
+	 *
105
+	 * @return callable Returns a function that accepts the next handler.
106
+	 */
107
+	public static function tap(?callable $before = null, ?callable $after = null) : callable
108
+	{
109
+		return static function (callable $handler) use($before, $after) : callable {
110
+			return static function (RequestInterface $request, array $options) use($handler, $before, $after) {
111
+				if ($before) {
112
+					$before($request, $options);
113
+				}
114
+				$response = $handler($request, $options);
115
+				if ($after) {
116
+					$after($request, $options, $response);
117
+				}
118
+				return $response;
119
+			};
120
+		};
121
+	}
122
+	/**
123
+	 * Middleware that handles request redirects.
124
+	 *
125
+	 * @return callable Returns a function that accepts the next handler.
126
+	 */
127
+	public static function redirect() : callable
128
+	{
129
+		return static function (callable $handler) : RedirectMiddleware {
130
+			return new RedirectMiddleware($handler);
131
+		};
132
+	}
133
+	/**
134
+	 * Middleware that retries requests based on the boolean result of
135
+	 * invoking the provided "decider" function.
136
+	 *
137
+	 * If no delay function is provided, a simple implementation of exponential
138
+	 * backoff will be utilized.
139
+	 *
140
+	 * @param callable $decider Function that accepts the number of retries,
141
+	 *                          a request, [response], and [exception] and
142
+	 *                          returns true if the request is to be retried.
143
+	 * @param callable $delay   Function that accepts the number of retries and
144
+	 *                          returns the number of milliseconds to delay.
145
+	 *
146
+	 * @return callable Returns a function that accepts the next handler.
147
+	 */
148
+	public static function retry(callable $decider, ?callable $delay = null) : callable
149
+	{
150
+		return static function (callable $handler) use($decider, $delay) : RetryMiddleware {
151
+			return new RetryMiddleware($decider, $handler, $delay);
152
+		};
153
+	}
154
+	/**
155
+	 * Middleware that logs requests, responses, and errors using a message
156
+	 * formatter.
157
+	 *
158
+	 * @phpstan-param \Psr\Log\LogLevel::* $logLevel  Level at which to log requests.
159
+	 *
160
+	 * @param LoggerInterface                            $logger    Logs messages.
161
+	 * @param MessageFormatterInterface|MessageFormatter $formatter Formatter used to create message strings.
162
+	 * @param string                                     $logLevel  Level at which to log requests.
163
+	 *
164
+	 * @return callable Returns a function that accepts the next handler.
165
+	 */
166
+	public static function log(LoggerInterface $logger, $formatter, string $logLevel = 'info') : callable
167
+	{
168
+		// To be compatible with Guzzle 7.1.x we need to allow users to pass a MessageFormatter
169
+		if (!$formatter instanceof MessageFormatter && !$formatter instanceof MessageFormatterInterface) {
170
+			throw new \LogicException(\sprintf('Argument 2 to %s::log() must be of type %s', self::class, MessageFormatterInterface::class));
171
+		}
172
+		return static function (callable $handler) use($logger, $formatter, $logLevel) : callable {
173
+			return static function (RequestInterface $request, array $options = []) use($handler, $logger, $formatter, $logLevel) {
174
+				return $handler($request, $options)->then(static function ($response) use($logger, $request, $formatter, $logLevel) : ResponseInterface {
175
+					$message = $formatter->format($request, $response);
176
+					$logger->log($logLevel, $message);
177
+					return $response;
178
+				}, static function ($reason) use($logger, $request, $formatter) : PromiseInterface {
179
+					$response = $reason instanceof RequestException ? $reason->getResponse() : null;
180
+					$message = $formatter->format($request, $response, P\Create::exceptionFor($reason));
181
+					$logger->error($message);
182
+					return P\Create::rejectionFor($reason);
183
+				});
184
+			};
185
+		};
186
+	}
187
+	/**
188
+	 * This middleware adds a default content-type if possible, a default
189
+	 * content-length or transfer-encoding header, and the expect header.
190
+	 */
191
+	public static function prepareBody() : callable
192
+	{
193
+		return static function (callable $handler) : PrepareBodyMiddleware {
194
+			return new PrepareBodyMiddleware($handler);
195
+		};
196
+	}
197
+	/**
198
+	 * Middleware that applies a map function to the request before passing to
199
+	 * the next handler.
200
+	 *
201
+	 * @param callable $fn Function that accepts a RequestInterface and returns
202
+	 *                     a RequestInterface.
203
+	 */
204
+	public static function mapRequest(callable $fn) : callable
205
+	{
206
+		return static function (callable $handler) use($fn) : callable {
207
+			return static function (RequestInterface $request, array $options) use($handler, $fn) {
208
+				return $handler($fn($request), $options);
209
+			};
210
+		};
211
+	}
212
+	/**
213
+	 * Middleware that applies a map function to the resolved promise's
214
+	 * response.
215
+	 *
216
+	 * @param callable $fn Function that accepts a ResponseInterface and
217
+	 *                     returns a ResponseInterface.
218
+	 */
219
+	public static function mapResponse(callable $fn) : callable
220
+	{
221
+		return static function (callable $handler) use($fn) : callable {
222
+			return static function (RequestInterface $request, array $options) use($handler, $fn) {
223
+				return $handler($request, $options)->then($fn);
224
+			};
225
+		};
226
+	}
227 227
 }
Please login to merge, or discard this patch.
Spacing   +23 added lines, -23 removed lines patch added patch discarded remove patch
@@ -24,8 +24,8 @@  discard block
 block discarded – undo
24 24
      */
25 25
     public static function cookies() : callable
26 26
     {
27
-        return static function (callable $handler) : callable {
28
-            return static function ($request, array $options) use($handler) {
27
+        return static function(callable $handler) : callable {
28
+            return static function($request, array $options) use($handler) {
29 29
                 if (empty($options['cookies'])) {
30 30
                     return $handler($request, $options);
31 31
                 } elseif (!$options['cookies'] instanceof CookieJarInterface) {
@@ -33,7 +33,7 @@  discard block
 block discarded – undo
33 33
                 }
34 34
                 $cookieJar = $options['cookies'];
35 35
                 $request = $cookieJar->withCookieHeader($request);
36
-                return $handler($request, $options)->then(static function (ResponseInterface $response) use($cookieJar, $request) : ResponseInterface {
36
+                return $handler($request, $options)->then(static function(ResponseInterface $response) use($cookieJar, $request) : ResponseInterface {
37 37
                     $cookieJar->extractCookies($request, $response);
38 38
                     return $response;
39 39
                 });
@@ -50,12 +50,12 @@  discard block
 block discarded – undo
50 50
      */
51 51
     public static function httpErrors(?BodySummarizerInterface $bodySummarizer = null) : callable
52 52
     {
53
-        return static function (callable $handler) use($bodySummarizer) : callable {
54
-            return static function ($request, array $options) use($handler, $bodySummarizer) {
53
+        return static function(callable $handler) use($bodySummarizer) : callable {
54
+            return static function($request, array $options) use($handler, $bodySummarizer) {
55 55
                 if (empty($options['http_errors'])) {
56 56
                     return $handler($request, $options);
57 57
                 }
58
-                return $handler($request, $options)->then(static function (ResponseInterface $response) use($request, $bodySummarizer) {
58
+                return $handler($request, $options)->then(static function(ResponseInterface $response) use($request, $bodySummarizer) {
59 59
                     $code = $response->getStatusCode();
60 60
                     if ($code < 400) {
61 61
                         return $response;
@@ -79,12 +79,12 @@  discard block
 block discarded – undo
79 79
         if (!\is_array($container) && !$container instanceof \ArrayAccess) {
80 80
             throw new \InvalidArgumentException('history container must be an array or object implementing ArrayAccess');
81 81
         }
82
-        return static function (callable $handler) use(&$container) : callable {
83
-            return static function (RequestInterface $request, array $options) use($handler, &$container) {
84
-                return $handler($request, $options)->then(static function ($value) use($request, &$container, $options) {
82
+        return static function(callable $handler) use(&$container) : callable {
83
+            return static function(RequestInterface $request, array $options) use($handler, &$container) {
84
+                return $handler($request, $options)->then(static function($value) use($request, &$container, $options) {
85 85
                     $container[] = ['request' => $request, 'response' => $value, 'error' => null, 'options' => $options];
86 86
                     return $value;
87
-                }, static function ($reason) use($request, &$container, $options) {
87
+                }, static function($reason) use($request, &$container, $options) {
88 88
                     $container[] = ['request' => $request, 'response' => null, 'error' => $reason, 'options' => $options];
89 89
                     return P\Create::rejectionFor($reason);
90 90
                 });
@@ -106,8 +106,8 @@  discard block
 block discarded – undo
106 106
      */
107 107
     public static function tap(?callable $before = null, ?callable $after = null) : callable
108 108
     {
109
-        return static function (callable $handler) use($before, $after) : callable {
110
-            return static function (RequestInterface $request, array $options) use($handler, $before, $after) {
109
+        return static function(callable $handler) use($before, $after) : callable {
110
+            return static function(RequestInterface $request, array $options) use($handler, $before, $after) {
111 111
                 if ($before) {
112 112
                     $before($request, $options);
113 113
                 }
@@ -126,7 +126,7 @@  discard block
 block discarded – undo
126 126
      */
127 127
     public static function redirect() : callable
128 128
     {
129
-        return static function (callable $handler) : RedirectMiddleware {
129
+        return static function(callable $handler) : RedirectMiddleware {
130 130
             return new RedirectMiddleware($handler);
131 131
         };
132 132
     }
@@ -147,7 +147,7 @@  discard block
 block discarded – undo
147 147
      */
148 148
     public static function retry(callable $decider, ?callable $delay = null) : callable
149 149
     {
150
-        return static function (callable $handler) use($decider, $delay) : RetryMiddleware {
150
+        return static function(callable $handler) use($decider, $delay) : RetryMiddleware {
151 151
             return new RetryMiddleware($decider, $handler, $delay);
152 152
         };
153 153
     }
@@ -169,13 +169,13 @@  discard block
 block discarded – undo
169 169
         if (!$formatter instanceof MessageFormatter && !$formatter instanceof MessageFormatterInterface) {
170 170
             throw new \LogicException(\sprintf('Argument 2 to %s::log() must be of type %s', self::class, MessageFormatterInterface::class));
171 171
         }
172
-        return static function (callable $handler) use($logger, $formatter, $logLevel) : callable {
173
-            return static function (RequestInterface $request, array $options = []) use($handler, $logger, $formatter, $logLevel) {
174
-                return $handler($request, $options)->then(static function ($response) use($logger, $request, $formatter, $logLevel) : ResponseInterface {
172
+        return static function(callable $handler) use($logger, $formatter, $logLevel) : callable {
173
+            return static function(RequestInterface $request, array $options = []) use($handler, $logger, $formatter, $logLevel) {
174
+                return $handler($request, $options)->then(static function($response) use($logger, $request, $formatter, $logLevel) : ResponseInterface {
175 175
                     $message = $formatter->format($request, $response);
176 176
                     $logger->log($logLevel, $message);
177 177
                     return $response;
178
-                }, static function ($reason) use($logger, $request, $formatter) : PromiseInterface {
178
+                }, static function($reason) use($logger, $request, $formatter) : PromiseInterface {
179 179
                     $response = $reason instanceof RequestException ? $reason->getResponse() : null;
180 180
                     $message = $formatter->format($request, $response, P\Create::exceptionFor($reason));
181 181
                     $logger->error($message);
@@ -190,7 +190,7 @@  discard block
 block discarded – undo
190 190
      */
191 191
     public static function prepareBody() : callable
192 192
     {
193
-        return static function (callable $handler) : PrepareBodyMiddleware {
193
+        return static function(callable $handler) : PrepareBodyMiddleware {
194 194
             return new PrepareBodyMiddleware($handler);
195 195
         };
196 196
     }
@@ -203,8 +203,8 @@  discard block
 block discarded – undo
203 203
      */
204 204
     public static function mapRequest(callable $fn) : callable
205 205
     {
206
-        return static function (callable $handler) use($fn) : callable {
207
-            return static function (RequestInterface $request, array $options) use($handler, $fn) {
206
+        return static function(callable $handler) use($fn) : callable {
207
+            return static function(RequestInterface $request, array $options) use($handler, $fn) {
208 208
                 return $handler($fn($request), $options);
209 209
             };
210 210
         };
@@ -218,8 +218,8 @@  discard block
 block discarded – undo
218 218
      */
219 219
     public static function mapResponse(callable $fn) : callable
220 220
     {
221
-        return static function (callable $handler) use($fn) : callable {
222
-            return static function (RequestInterface $request, array $options) use($handler, $fn) {
221
+        return static function(callable $handler) use($fn) : callable {
222
+            return static function(RequestInterface $request, array $options) use($handler, $fn) {
223 223
                 return $handler($request, $options)->then($fn);
224 224
             };
225 225
         };
Please login to merge, or discard this patch.
lib/Vendor/GuzzleHttp/Handler/StreamHandler.php 1 patch
Indentation   +435 added lines, -435 removed lines patch added patch discarded remove patch
@@ -21,439 +21,439 @@
 block discarded – undo
21 21
  */
22 22
 class StreamHandler
23 23
 {
24
-    /**
25
-     * @var array
26
-     */
27
-    private $lastHeaders = [];
28
-    /**
29
-     * Sends an HTTP request.
30
-     *
31
-     * @param RequestInterface $request Request to send.
32
-     * @param array            $options Request transfer options.
33
-     */
34
-    public function __invoke(RequestInterface $request, array $options) : PromiseInterface
35
-    {
36
-        // Sleep if there is a delay specified.
37
-        if (isset($options['delay'])) {
38
-            \usleep($options['delay'] * 1000);
39
-        }
40
-        $protocolVersion = $request->getProtocolVersion();
41
-        if ('1.0' !== $protocolVersion && '1.1' !== $protocolVersion) {
42
-            throw new ConnectException(\sprintf('HTTP/%s is not supported by the stream handler.', $protocolVersion), $request);
43
-        }
44
-        $startTime = isset($options['on_stats']) ? Utils::currentTime() : null;
45
-        try {
46
-            // Does not support the expect header.
47
-            $request = $request->withoutHeader('Expect');
48
-            // Append a content-length header if body size is zero to match
49
-            // cURL's behavior.
50
-            if (0 === $request->getBody()->getSize()) {
51
-                $request = $request->withHeader('Content-Length', '0');
52
-            }
53
-            return $this->createResponse($request, $options, $this->createStream($request, $options), $startTime);
54
-        } catch (\InvalidArgumentException $e) {
55
-            throw $e;
56
-        } catch (\Exception $e) {
57
-            // Determine if the error was a networking error.
58
-            $message = $e->getMessage();
59
-            // This list can probably get more comprehensive.
60
-            if (\false !== \strpos($message, 'getaddrinfo') || \false !== \strpos($message, 'Connection refused') || \false !== \strpos($message, "couldn't connect to host") || \false !== \strpos($message, 'connection attempt failed')) {
61
-                $e = new ConnectException($e->getMessage(), $request, $e);
62
-            } else {
63
-                $e = RequestException::wrapException($request, $e);
64
-            }
65
-            $this->invokeStats($options, $request, $startTime, null, $e);
66
-            return P\Create::rejectionFor($e);
67
-        }
68
-    }
69
-    private function invokeStats(array $options, RequestInterface $request, ?float $startTime, ?ResponseInterface $response = null, ?\Throwable $error = null) : void
70
-    {
71
-        if (isset($options['on_stats'])) {
72
-            $stats = new TransferStats($request, $response, Utils::currentTime() - $startTime, $error, []);
73
-            $options['on_stats']($stats);
74
-        }
75
-    }
76
-    /**
77
-     * @param resource $stream
78
-     */
79
-    private function createResponse(RequestInterface $request, array $options, $stream, ?float $startTime) : PromiseInterface
80
-    {
81
-        $hdrs = $this->lastHeaders;
82
-        $this->lastHeaders = [];
83
-        try {
84
-            [$ver, $status, $reason, $headers] = HeaderProcessor::parseHeaders($hdrs);
85
-        } catch (\Exception $e) {
86
-            return P\Create::rejectionFor(new RequestException('An error was encountered while creating the response', $request, null, $e));
87
-        }
88
-        [$stream, $headers] = $this->checkDecode($options, $headers, $stream);
89
-        $stream = Psr7\Utils::streamFor($stream);
90
-        $sink = $stream;
91
-        if (\strcasecmp('HEAD', $request->getMethod())) {
92
-            $sink = $this->createSink($stream, $options);
93
-        }
94
-        try {
95
-            $response = new Psr7\Response($status, $headers, $sink, $ver, $reason);
96
-        } catch (\Exception $e) {
97
-            return P\Create::rejectionFor(new RequestException('An error was encountered while creating the response', $request, null, $e));
98
-        }
99
-        if (isset($options['on_headers'])) {
100
-            try {
101
-                $options['on_headers']($response);
102
-            } catch (\Exception $e) {
103
-                return P\Create::rejectionFor(new RequestException('An error was encountered during the on_headers event', $request, $response, $e));
104
-            }
105
-        }
106
-        // Do not drain when the request is a HEAD request because they have
107
-        // no body.
108
-        if ($sink !== $stream) {
109
-            $this->drain($stream, $sink, $response->getHeaderLine('Content-Length'));
110
-        }
111
-        $this->invokeStats($options, $request, $startTime, $response, null);
112
-        return new FulfilledPromise($response);
113
-    }
114
-    private function createSink(StreamInterface $stream, array $options) : StreamInterface
115
-    {
116
-        if (!empty($options['stream'])) {
117
-            return $stream;
118
-        }
119
-        $sink = $options['sink'] ?? Psr7\Utils::tryFopen('php://temp', 'r+');
120
-        return \is_string($sink) ? new Psr7\LazyOpenStream($sink, 'w+') : Psr7\Utils::streamFor($sink);
121
-    }
122
-    /**
123
-     * @param resource $stream
124
-     */
125
-    private function checkDecode(array $options, array $headers, $stream) : array
126
-    {
127
-        // Automatically decode responses when instructed.
128
-        if (!empty($options['decode_content'])) {
129
-            $normalizedKeys = Utils::normalizeHeaderKeys($headers);
130
-            if (isset($normalizedKeys['content-encoding'])) {
131
-                $encoding = $headers[$normalizedKeys['content-encoding']];
132
-                if ($encoding[0] === 'gzip' || $encoding[0] === 'deflate') {
133
-                    $stream = new Psr7\InflateStream(Psr7\Utils::streamFor($stream));
134
-                    $headers['x-encoded-content-encoding'] = $headers[$normalizedKeys['content-encoding']];
135
-                    // Remove content-encoding header
136
-                    unset($headers[$normalizedKeys['content-encoding']]);
137
-                    // Fix content-length header
138
-                    if (isset($normalizedKeys['content-length'])) {
139
-                        $headers['x-encoded-content-length'] = $headers[$normalizedKeys['content-length']];
140
-                        $length = (int) $stream->getSize();
141
-                        if ($length === 0) {
142
-                            unset($headers[$normalizedKeys['content-length']]);
143
-                        } else {
144
-                            $headers[$normalizedKeys['content-length']] = [$length];
145
-                        }
146
-                    }
147
-                }
148
-            }
149
-        }
150
-        return [$stream, $headers];
151
-    }
152
-    /**
153
-     * Drains the source stream into the "sink" client option.
154
-     *
155
-     * @param string $contentLength Header specifying the amount of
156
-     *                              data to read.
157
-     *
158
-     * @throws \RuntimeException when the sink option is invalid.
159
-     */
160
-    private function drain(StreamInterface $source, StreamInterface $sink, string $contentLength) : StreamInterface
161
-    {
162
-        // If a content-length header is provided, then stop reading once
163
-        // that number of bytes has been read. This can prevent infinitely
164
-        // reading from a stream when dealing with servers that do not honor
165
-        // Connection: Close headers.
166
-        Psr7\Utils::copyToStream($source, $sink, \strlen($contentLength) > 0 && (int) $contentLength > 0 ? (int) $contentLength : -1);
167
-        $sink->seek(0);
168
-        $source->close();
169
-        return $sink;
170
-    }
171
-    /**
172
-     * Create a resource and check to ensure it was created successfully
173
-     *
174
-     * @param callable $callback Callable that returns stream resource
175
-     *
176
-     * @return resource
177
-     *
178
-     * @throws \RuntimeException on error
179
-     */
180
-    private function createResource(callable $callback)
181
-    {
182
-        $errors = [];
183
-        \set_error_handler(static function ($_, $msg, $file, $line) use(&$errors) : bool {
184
-            $errors[] = ['message' => $msg, 'file' => $file, 'line' => $line];
185
-            return \true;
186
-        });
187
-        try {
188
-            $resource = $callback();
189
-        } finally {
190
-            \restore_error_handler();
191
-        }
192
-        if (!$resource) {
193
-            $message = 'Error creating resource: ';
194
-            foreach ($errors as $err) {
195
-                foreach ($err as $key => $value) {
196
-                    $message .= "[{$key}] {$value}" . \PHP_EOL;
197
-                }
198
-            }
199
-            throw new \RuntimeException(\trim($message));
200
-        }
201
-        return $resource;
202
-    }
203
-    /**
204
-     * @return resource
205
-     */
206
-    private function createStream(RequestInterface $request, array $options)
207
-    {
208
-        static $methods;
209
-        if (!$methods) {
210
-            $methods = \array_flip(\get_class_methods(__CLASS__));
211
-        }
212
-        if (!\in_array($request->getUri()->getScheme(), ['http', 'https'])) {
213
-            throw new RequestException(\sprintf("The scheme '%s' is not supported.", $request->getUri()->getScheme()), $request);
214
-        }
215
-        // HTTP/1.1 streams using the PHP stream wrapper require a
216
-        // Connection: close header
217
-        if ($request->getProtocolVersion() === '1.1' && !$request->hasHeader('Connection')) {
218
-            $request = $request->withHeader('Connection', 'close');
219
-        }
220
-        // Ensure SSL is verified by default
221
-        if (!isset($options['verify'])) {
222
-            $options['verify'] = \true;
223
-        }
224
-        $params = [];
225
-        $context = $this->getDefaultContext($request);
226
-        if (isset($options['on_headers']) && !\is_callable($options['on_headers'])) {
227
-            throw new \InvalidArgumentException('on_headers must be callable');
228
-        }
229
-        if (!empty($options)) {
230
-            foreach ($options as $key => $value) {
231
-                $method = "add_{$key}";
232
-                if (isset($methods[$method])) {
233
-                    $this->{$method}($request, $context, $value, $params);
234
-                }
235
-            }
236
-        }
237
-        if (isset($options['stream_context'])) {
238
-            if (!\is_array($options['stream_context'])) {
239
-                throw new \InvalidArgumentException('stream_context must be an array');
240
-            }
241
-            $context = \array_replace_recursive($context, $options['stream_context']);
242
-        }
243
-        // Microsoft NTLM authentication only supported with curl handler
244
-        if (isset($options['auth'][2]) && 'ntlm' === $options['auth'][2]) {
245
-            throw new \InvalidArgumentException('Microsoft NTLM authentication only supported with curl handler');
246
-        }
247
-        $uri = $this->resolveHost($request, $options);
248
-        $contextResource = $this->createResource(static function () use($context, $params) {
249
-            return \stream_context_create($context, $params);
250
-        });
251
-        return $this->createResource(function () use($uri, &$http_response_header, $contextResource, $context, $options, $request) {
252
-            $resource = @\fopen((string) $uri, 'r', \false, $contextResource);
253
-            $this->lastHeaders = $http_response_header ?? [];
254
-            if (\false === $resource) {
255
-                throw new ConnectException(\sprintf('Connection refused for URI %s', $uri), $request, null, $context);
256
-            }
257
-            if (isset($options['read_timeout'])) {
258
-                $readTimeout = $options['read_timeout'];
259
-                $sec = (int) $readTimeout;
260
-                $usec = ($readTimeout - $sec) * 100000;
261
-                \stream_set_timeout($resource, $sec, $usec);
262
-            }
263
-            return $resource;
264
-        });
265
-    }
266
-    private function resolveHost(RequestInterface $request, array $options) : UriInterface
267
-    {
268
-        $uri = $request->getUri();
269
-        if (isset($options['force_ip_resolve']) && !\filter_var($uri->getHost(), \FILTER_VALIDATE_IP)) {
270
-            if ('v4' === $options['force_ip_resolve']) {
271
-                $records = \dns_get_record($uri->getHost(), \DNS_A);
272
-                if (\false === $records || !isset($records[0]['ip'])) {
273
-                    throw new ConnectException(\sprintf("Could not resolve IPv4 address for host '%s'", $uri->getHost()), $request);
274
-                }
275
-                return $uri->withHost($records[0]['ip']);
276
-            }
277
-            if ('v6' === $options['force_ip_resolve']) {
278
-                $records = \dns_get_record($uri->getHost(), \DNS_AAAA);
279
-                if (\false === $records || !isset($records[0]['ipv6'])) {
280
-                    throw new ConnectException(\sprintf("Could not resolve IPv6 address for host '%s'", $uri->getHost()), $request);
281
-                }
282
-                return $uri->withHost('[' . $records[0]['ipv6'] . ']');
283
-            }
284
-        }
285
-        return $uri;
286
-    }
287
-    private function getDefaultContext(RequestInterface $request) : array
288
-    {
289
-        $headers = '';
290
-        foreach ($request->getHeaders() as $name => $value) {
291
-            foreach ($value as $val) {
292
-                $headers .= "{$name}: {$val}\r\n";
293
-            }
294
-        }
295
-        $context = ['http' => ['method' => $request->getMethod(), 'header' => $headers, 'protocol_version' => $request->getProtocolVersion(), 'ignore_errors' => \true, 'follow_location' => 0], 'ssl' => ['peer_name' => $request->getUri()->getHost()]];
296
-        $body = (string) $request->getBody();
297
-        if ('' !== $body) {
298
-            $context['http']['content'] = $body;
299
-            // Prevent the HTTP handler from adding a Content-Type header.
300
-            if (!$request->hasHeader('Content-Type')) {
301
-                $context['http']['header'] .= "Content-Type:\r\n";
302
-            }
303
-        }
304
-        $context['http']['header'] = \rtrim($context['http']['header']);
305
-        return $context;
306
-    }
307
-    /**
308
-     * @param mixed $value as passed via Request transfer options.
309
-     */
310
-    private function add_proxy(RequestInterface $request, array &$options, $value, array &$params) : void
311
-    {
312
-        $uri = null;
313
-        if (!\is_array($value)) {
314
-            $uri = $value;
315
-        } else {
316
-            $scheme = $request->getUri()->getScheme();
317
-            if (isset($value[$scheme])) {
318
-                if (!isset($value['no']) || !Utils::isHostInNoProxy($request->getUri()->getHost(), $value['no'])) {
319
-                    $uri = $value[$scheme];
320
-                }
321
-            }
322
-        }
323
-        if (!$uri) {
324
-            return;
325
-        }
326
-        $parsed = $this->parse_proxy($uri);
327
-        $options['http']['proxy'] = $parsed['proxy'];
328
-        if ($parsed['auth']) {
329
-            if (!isset($options['http']['header'])) {
330
-                $options['http']['header'] = [];
331
-            }
332
-            $options['http']['header'] .= "\r\nProxy-Authorization: {$parsed['auth']}";
333
-        }
334
-    }
335
-    /**
336
-     * Parses the given proxy URL to make it compatible with the format PHP's stream context expects.
337
-     */
338
-    private function parse_proxy(string $url) : array
339
-    {
340
-        $parsed = \parse_url($url);
341
-        if ($parsed !== \false && isset($parsed['scheme']) && $parsed['scheme'] === 'http') {
342
-            if (isset($parsed['host']) && isset($parsed['port'])) {
343
-                $auth = null;
344
-                if (isset($parsed['user']) && isset($parsed['pass'])) {
345
-                    $auth = \base64_encode("{$parsed['user']}:{$parsed['pass']}");
346
-                }
347
-                return ['proxy' => "tcp://{$parsed['host']}:{$parsed['port']}", 'auth' => $auth ? "Basic {$auth}" : null];
348
-            }
349
-        }
350
-        // Return proxy as-is.
351
-        return ['proxy' => $url, 'auth' => null];
352
-    }
353
-    /**
354
-     * @param mixed $value as passed via Request transfer options.
355
-     */
356
-    private function add_timeout(RequestInterface $request, array &$options, $value, array &$params) : void
357
-    {
358
-        if ($value > 0) {
359
-            $options['http']['timeout'] = $value;
360
-        }
361
-    }
362
-    /**
363
-     * @param mixed $value as passed via Request transfer options.
364
-     */
365
-    private function add_crypto_method(RequestInterface $request, array &$options, $value, array &$params) : void
366
-    {
367
-        if ($value === \STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT || $value === \STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT || $value === \STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT || \defined('STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT') && $value === \STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT) {
368
-            $options['http']['crypto_method'] = $value;
369
-            return;
370
-        }
371
-        throw new \InvalidArgumentException('Invalid crypto_method request option: unknown version provided');
372
-    }
373
-    /**
374
-     * @param mixed $value as passed via Request transfer options.
375
-     */
376
-    private function add_verify(RequestInterface $request, array &$options, $value, array &$params) : void
377
-    {
378
-        if ($value === \false) {
379
-            $options['ssl']['verify_peer'] = \false;
380
-            $options['ssl']['verify_peer_name'] = \false;
381
-            return;
382
-        }
383
-        if (\is_string($value)) {
384
-            $options['ssl']['cafile'] = $value;
385
-            if (!\file_exists($value)) {
386
-                throw new \RuntimeException("SSL CA bundle not found: {$value}");
387
-            }
388
-        } elseif ($value !== \true) {
389
-            throw new \InvalidArgumentException('Invalid verify request option');
390
-        }
391
-        $options['ssl']['verify_peer'] = \true;
392
-        $options['ssl']['verify_peer_name'] = \true;
393
-        $options['ssl']['allow_self_signed'] = \false;
394
-    }
395
-    /**
396
-     * @param mixed $value as passed via Request transfer options.
397
-     */
398
-    private function add_cert(RequestInterface $request, array &$options, $value, array &$params) : void
399
-    {
400
-        if (\is_array($value)) {
401
-            $options['ssl']['passphrase'] = $value[1];
402
-            $value = $value[0];
403
-        }
404
-        if (!\file_exists($value)) {
405
-            throw new \RuntimeException("SSL certificate not found: {$value}");
406
-        }
407
-        $options['ssl']['local_cert'] = $value;
408
-    }
409
-    /**
410
-     * @param mixed $value as passed via Request transfer options.
411
-     */
412
-    private function add_progress(RequestInterface $request, array &$options, $value, array &$params) : void
413
-    {
414
-        self::addNotification($params, static function ($code, $a, $b, $c, $transferred, $total) use($value) {
415
-            if ($code == \STREAM_NOTIFY_PROGRESS) {
416
-                // The upload progress cannot be determined. Use 0 for cURL compatibility:
417
-                // https://curl.se/libcurl/c/CURLOPT_PROGRESSFUNCTION.html
418
-                $value($total, $transferred, 0, 0);
419
-            }
420
-        });
421
-    }
422
-    /**
423
-     * @param mixed $value as passed via Request transfer options.
424
-     */
425
-    private function add_debug(RequestInterface $request, array &$options, $value, array &$params) : void
426
-    {
427
-        if ($value === \false) {
428
-            return;
429
-        }
430
-        static $map = [\STREAM_NOTIFY_CONNECT => 'CONNECT', \STREAM_NOTIFY_AUTH_REQUIRED => 'AUTH_REQUIRED', \STREAM_NOTIFY_AUTH_RESULT => 'AUTH_RESULT', \STREAM_NOTIFY_MIME_TYPE_IS => 'MIME_TYPE_IS', \STREAM_NOTIFY_FILE_SIZE_IS => 'FILE_SIZE_IS', \STREAM_NOTIFY_REDIRECTED => 'REDIRECTED', \STREAM_NOTIFY_PROGRESS => 'PROGRESS', \STREAM_NOTIFY_FAILURE => 'FAILURE', \STREAM_NOTIFY_COMPLETED => 'COMPLETED', \STREAM_NOTIFY_RESOLVE => 'RESOLVE'];
431
-        static $args = ['severity', 'message', 'message_code', 'bytes_transferred', 'bytes_max'];
432
-        $value = Utils::debugResource($value);
433
-        $ident = $request->getMethod() . ' ' . $request->getUri()->withFragment('');
434
-        self::addNotification($params, static function (int $code, ...$passed) use($ident, $value, $map, $args) : void {
435
-            \fprintf($value, '<%s> [%s] ', $ident, $map[$code]);
436
-            foreach (\array_filter($passed) as $i => $v) {
437
-                \fwrite($value, $args[$i] . ': "' . $v . '" ');
438
-            }
439
-            \fwrite($value, "\n");
440
-        });
441
-    }
442
-    private static function addNotification(array &$params, callable $notify) : void
443
-    {
444
-        // Wrap the existing function if needed.
445
-        if (!isset($params['notification'])) {
446
-            $params['notification'] = $notify;
447
-        } else {
448
-            $params['notification'] = self::callArray([$params['notification'], $notify]);
449
-        }
450
-    }
451
-    private static function callArray(array $functions) : callable
452
-    {
453
-        return static function (...$args) use($functions) {
454
-            foreach ($functions as $fn) {
455
-                $fn(...$args);
456
-            }
457
-        };
458
-    }
24
+	/**
25
+	 * @var array
26
+	 */
27
+	private $lastHeaders = [];
28
+	/**
29
+	 * Sends an HTTP request.
30
+	 *
31
+	 * @param RequestInterface $request Request to send.
32
+	 * @param array            $options Request transfer options.
33
+	 */
34
+	public function __invoke(RequestInterface $request, array $options) : PromiseInterface
35
+	{
36
+		// Sleep if there is a delay specified.
37
+		if (isset($options['delay'])) {
38
+			\usleep($options['delay'] * 1000);
39
+		}
40
+		$protocolVersion = $request->getProtocolVersion();
41
+		if ('1.0' !== $protocolVersion && '1.1' !== $protocolVersion) {
42
+			throw new ConnectException(\sprintf('HTTP/%s is not supported by the stream handler.', $protocolVersion), $request);
43
+		}
44
+		$startTime = isset($options['on_stats']) ? Utils::currentTime() : null;
45
+		try {
46
+			// Does not support the expect header.
47
+			$request = $request->withoutHeader('Expect');
48
+			// Append a content-length header if body size is zero to match
49
+			// cURL's behavior.
50
+			if (0 === $request->getBody()->getSize()) {
51
+				$request = $request->withHeader('Content-Length', '0');
52
+			}
53
+			return $this->createResponse($request, $options, $this->createStream($request, $options), $startTime);
54
+		} catch (\InvalidArgumentException $e) {
55
+			throw $e;
56
+		} catch (\Exception $e) {
57
+			// Determine if the error was a networking error.
58
+			$message = $e->getMessage();
59
+			// This list can probably get more comprehensive.
60
+			if (\false !== \strpos($message, 'getaddrinfo') || \false !== \strpos($message, 'Connection refused') || \false !== \strpos($message, "couldn't connect to host") || \false !== \strpos($message, 'connection attempt failed')) {
61
+				$e = new ConnectException($e->getMessage(), $request, $e);
62
+			} else {
63
+				$e = RequestException::wrapException($request, $e);
64
+			}
65
+			$this->invokeStats($options, $request, $startTime, null, $e);
66
+			return P\Create::rejectionFor($e);
67
+		}
68
+	}
69
+	private function invokeStats(array $options, RequestInterface $request, ?float $startTime, ?ResponseInterface $response = null, ?\Throwable $error = null) : void
70
+	{
71
+		if (isset($options['on_stats'])) {
72
+			$stats = new TransferStats($request, $response, Utils::currentTime() - $startTime, $error, []);
73
+			$options['on_stats']($stats);
74
+		}
75
+	}
76
+	/**
77
+	 * @param resource $stream
78
+	 */
79
+	private function createResponse(RequestInterface $request, array $options, $stream, ?float $startTime) : PromiseInterface
80
+	{
81
+		$hdrs = $this->lastHeaders;
82
+		$this->lastHeaders = [];
83
+		try {
84
+			[$ver, $status, $reason, $headers] = HeaderProcessor::parseHeaders($hdrs);
85
+		} catch (\Exception $e) {
86
+			return P\Create::rejectionFor(new RequestException('An error was encountered while creating the response', $request, null, $e));
87
+		}
88
+		[$stream, $headers] = $this->checkDecode($options, $headers, $stream);
89
+		$stream = Psr7\Utils::streamFor($stream);
90
+		$sink = $stream;
91
+		if (\strcasecmp('HEAD', $request->getMethod())) {
92
+			$sink = $this->createSink($stream, $options);
93
+		}
94
+		try {
95
+			$response = new Psr7\Response($status, $headers, $sink, $ver, $reason);
96
+		} catch (\Exception $e) {
97
+			return P\Create::rejectionFor(new RequestException('An error was encountered while creating the response', $request, null, $e));
98
+		}
99
+		if (isset($options['on_headers'])) {
100
+			try {
101
+				$options['on_headers']($response);
102
+			} catch (\Exception $e) {
103
+				return P\Create::rejectionFor(new RequestException('An error was encountered during the on_headers event', $request, $response, $e));
104
+			}
105
+		}
106
+		// Do not drain when the request is a HEAD request because they have
107
+		// no body.
108
+		if ($sink !== $stream) {
109
+			$this->drain($stream, $sink, $response->getHeaderLine('Content-Length'));
110
+		}
111
+		$this->invokeStats($options, $request, $startTime, $response, null);
112
+		return new FulfilledPromise($response);
113
+	}
114
+	private function createSink(StreamInterface $stream, array $options) : StreamInterface
115
+	{
116
+		if (!empty($options['stream'])) {
117
+			return $stream;
118
+		}
119
+		$sink = $options['sink'] ?? Psr7\Utils::tryFopen('php://temp', 'r+');
120
+		return \is_string($sink) ? new Psr7\LazyOpenStream($sink, 'w+') : Psr7\Utils::streamFor($sink);
121
+	}
122
+	/**
123
+	 * @param resource $stream
124
+	 */
125
+	private function checkDecode(array $options, array $headers, $stream) : array
126
+	{
127
+		// Automatically decode responses when instructed.
128
+		if (!empty($options['decode_content'])) {
129
+			$normalizedKeys = Utils::normalizeHeaderKeys($headers);
130
+			if (isset($normalizedKeys['content-encoding'])) {
131
+				$encoding = $headers[$normalizedKeys['content-encoding']];
132
+				if ($encoding[0] === 'gzip' || $encoding[0] === 'deflate') {
133
+					$stream = new Psr7\InflateStream(Psr7\Utils::streamFor($stream));
134
+					$headers['x-encoded-content-encoding'] = $headers[$normalizedKeys['content-encoding']];
135
+					// Remove content-encoding header
136
+					unset($headers[$normalizedKeys['content-encoding']]);
137
+					// Fix content-length header
138
+					if (isset($normalizedKeys['content-length'])) {
139
+						$headers['x-encoded-content-length'] = $headers[$normalizedKeys['content-length']];
140
+						$length = (int) $stream->getSize();
141
+						if ($length === 0) {
142
+							unset($headers[$normalizedKeys['content-length']]);
143
+						} else {
144
+							$headers[$normalizedKeys['content-length']] = [$length];
145
+						}
146
+					}
147
+				}
148
+			}
149
+		}
150
+		return [$stream, $headers];
151
+	}
152
+	/**
153
+	 * Drains the source stream into the "sink" client option.
154
+	 *
155
+	 * @param string $contentLength Header specifying the amount of
156
+	 *                              data to read.
157
+	 *
158
+	 * @throws \RuntimeException when the sink option is invalid.
159
+	 */
160
+	private function drain(StreamInterface $source, StreamInterface $sink, string $contentLength) : StreamInterface
161
+	{
162
+		// If a content-length header is provided, then stop reading once
163
+		// that number of bytes has been read. This can prevent infinitely
164
+		// reading from a stream when dealing with servers that do not honor
165
+		// Connection: Close headers.
166
+		Psr7\Utils::copyToStream($source, $sink, \strlen($contentLength) > 0 && (int) $contentLength > 0 ? (int) $contentLength : -1);
167
+		$sink->seek(0);
168
+		$source->close();
169
+		return $sink;
170
+	}
171
+	/**
172
+	 * Create a resource and check to ensure it was created successfully
173
+	 *
174
+	 * @param callable $callback Callable that returns stream resource
175
+	 *
176
+	 * @return resource
177
+	 *
178
+	 * @throws \RuntimeException on error
179
+	 */
180
+	private function createResource(callable $callback)
181
+	{
182
+		$errors = [];
183
+		\set_error_handler(static function ($_, $msg, $file, $line) use(&$errors) : bool {
184
+			$errors[] = ['message' => $msg, 'file' => $file, 'line' => $line];
185
+			return \true;
186
+		});
187
+		try {
188
+			$resource = $callback();
189
+		} finally {
190
+			\restore_error_handler();
191
+		}
192
+		if (!$resource) {
193
+			$message = 'Error creating resource: ';
194
+			foreach ($errors as $err) {
195
+				foreach ($err as $key => $value) {
196
+					$message .= "[{$key}] {$value}" . \PHP_EOL;
197
+				}
198
+			}
199
+			throw new \RuntimeException(\trim($message));
200
+		}
201
+		return $resource;
202
+	}
203
+	/**
204
+	 * @return resource
205
+	 */
206
+	private function createStream(RequestInterface $request, array $options)
207
+	{
208
+		static $methods;
209
+		if (!$methods) {
210
+			$methods = \array_flip(\get_class_methods(__CLASS__));
211
+		}
212
+		if (!\in_array($request->getUri()->getScheme(), ['http', 'https'])) {
213
+			throw new RequestException(\sprintf("The scheme '%s' is not supported.", $request->getUri()->getScheme()), $request);
214
+		}
215
+		// HTTP/1.1 streams using the PHP stream wrapper require a
216
+		// Connection: close header
217
+		if ($request->getProtocolVersion() === '1.1' && !$request->hasHeader('Connection')) {
218
+			$request = $request->withHeader('Connection', 'close');
219
+		}
220
+		// Ensure SSL is verified by default
221
+		if (!isset($options['verify'])) {
222
+			$options['verify'] = \true;
223
+		}
224
+		$params = [];
225
+		$context = $this->getDefaultContext($request);
226
+		if (isset($options['on_headers']) && !\is_callable($options['on_headers'])) {
227
+			throw new \InvalidArgumentException('on_headers must be callable');
228
+		}
229
+		if (!empty($options)) {
230
+			foreach ($options as $key => $value) {
231
+				$method = "add_{$key}";
232
+				if (isset($methods[$method])) {
233
+					$this->{$method}($request, $context, $value, $params);
234
+				}
235
+			}
236
+		}
237
+		if (isset($options['stream_context'])) {
238
+			if (!\is_array($options['stream_context'])) {
239
+				throw new \InvalidArgumentException('stream_context must be an array');
240
+			}
241
+			$context = \array_replace_recursive($context, $options['stream_context']);
242
+		}
243
+		// Microsoft NTLM authentication only supported with curl handler
244
+		if (isset($options['auth'][2]) && 'ntlm' === $options['auth'][2]) {
245
+			throw new \InvalidArgumentException('Microsoft NTLM authentication only supported with curl handler');
246
+		}
247
+		$uri = $this->resolveHost($request, $options);
248
+		$contextResource = $this->createResource(static function () use($context, $params) {
249
+			return \stream_context_create($context, $params);
250
+		});
251
+		return $this->createResource(function () use($uri, &$http_response_header, $contextResource, $context, $options, $request) {
252
+			$resource = @\fopen((string) $uri, 'r', \false, $contextResource);
253
+			$this->lastHeaders = $http_response_header ?? [];
254
+			if (\false === $resource) {
255
+				throw new ConnectException(\sprintf('Connection refused for URI %s', $uri), $request, null, $context);
256
+			}
257
+			if (isset($options['read_timeout'])) {
258
+				$readTimeout = $options['read_timeout'];
259
+				$sec = (int) $readTimeout;
260
+				$usec = ($readTimeout - $sec) * 100000;
261
+				\stream_set_timeout($resource, $sec, $usec);
262
+			}
263
+			return $resource;
264
+		});
265
+	}
266
+	private function resolveHost(RequestInterface $request, array $options) : UriInterface
267
+	{
268
+		$uri = $request->getUri();
269
+		if (isset($options['force_ip_resolve']) && !\filter_var($uri->getHost(), \FILTER_VALIDATE_IP)) {
270
+			if ('v4' === $options['force_ip_resolve']) {
271
+				$records = \dns_get_record($uri->getHost(), \DNS_A);
272
+				if (\false === $records || !isset($records[0]['ip'])) {
273
+					throw new ConnectException(\sprintf("Could not resolve IPv4 address for host '%s'", $uri->getHost()), $request);
274
+				}
275
+				return $uri->withHost($records[0]['ip']);
276
+			}
277
+			if ('v6' === $options['force_ip_resolve']) {
278
+				$records = \dns_get_record($uri->getHost(), \DNS_AAAA);
279
+				if (\false === $records || !isset($records[0]['ipv6'])) {
280
+					throw new ConnectException(\sprintf("Could not resolve IPv6 address for host '%s'", $uri->getHost()), $request);
281
+				}
282
+				return $uri->withHost('[' . $records[0]['ipv6'] . ']');
283
+			}
284
+		}
285
+		return $uri;
286
+	}
287
+	private function getDefaultContext(RequestInterface $request) : array
288
+	{
289
+		$headers = '';
290
+		foreach ($request->getHeaders() as $name => $value) {
291
+			foreach ($value as $val) {
292
+				$headers .= "{$name}: {$val}\r\n";
293
+			}
294
+		}
295
+		$context = ['http' => ['method' => $request->getMethod(), 'header' => $headers, 'protocol_version' => $request->getProtocolVersion(), 'ignore_errors' => \true, 'follow_location' => 0], 'ssl' => ['peer_name' => $request->getUri()->getHost()]];
296
+		$body = (string) $request->getBody();
297
+		if ('' !== $body) {
298
+			$context['http']['content'] = $body;
299
+			// Prevent the HTTP handler from adding a Content-Type header.
300
+			if (!$request->hasHeader('Content-Type')) {
301
+				$context['http']['header'] .= "Content-Type:\r\n";
302
+			}
303
+		}
304
+		$context['http']['header'] = \rtrim($context['http']['header']);
305
+		return $context;
306
+	}
307
+	/**
308
+	 * @param mixed $value as passed via Request transfer options.
309
+	 */
310
+	private function add_proxy(RequestInterface $request, array &$options, $value, array &$params) : void
311
+	{
312
+		$uri = null;
313
+		if (!\is_array($value)) {
314
+			$uri = $value;
315
+		} else {
316
+			$scheme = $request->getUri()->getScheme();
317
+			if (isset($value[$scheme])) {
318
+				if (!isset($value['no']) || !Utils::isHostInNoProxy($request->getUri()->getHost(), $value['no'])) {
319
+					$uri = $value[$scheme];
320
+				}
321
+			}
322
+		}
323
+		if (!$uri) {
324
+			return;
325
+		}
326
+		$parsed = $this->parse_proxy($uri);
327
+		$options['http']['proxy'] = $parsed['proxy'];
328
+		if ($parsed['auth']) {
329
+			if (!isset($options['http']['header'])) {
330
+				$options['http']['header'] = [];
331
+			}
332
+			$options['http']['header'] .= "\r\nProxy-Authorization: {$parsed['auth']}";
333
+		}
334
+	}
335
+	/**
336
+	 * Parses the given proxy URL to make it compatible with the format PHP's stream context expects.
337
+	 */
338
+	private function parse_proxy(string $url) : array
339
+	{
340
+		$parsed = \parse_url($url);
341
+		if ($parsed !== \false && isset($parsed['scheme']) && $parsed['scheme'] === 'http') {
342
+			if (isset($parsed['host']) && isset($parsed['port'])) {
343
+				$auth = null;
344
+				if (isset($parsed['user']) && isset($parsed['pass'])) {
345
+					$auth = \base64_encode("{$parsed['user']}:{$parsed['pass']}");
346
+				}
347
+				return ['proxy' => "tcp://{$parsed['host']}:{$parsed['port']}", 'auth' => $auth ? "Basic {$auth}" : null];
348
+			}
349
+		}
350
+		// Return proxy as-is.
351
+		return ['proxy' => $url, 'auth' => null];
352
+	}
353
+	/**
354
+	 * @param mixed $value as passed via Request transfer options.
355
+	 */
356
+	private function add_timeout(RequestInterface $request, array &$options, $value, array &$params) : void
357
+	{
358
+		if ($value > 0) {
359
+			$options['http']['timeout'] = $value;
360
+		}
361
+	}
362
+	/**
363
+	 * @param mixed $value as passed via Request transfer options.
364
+	 */
365
+	private function add_crypto_method(RequestInterface $request, array &$options, $value, array &$params) : void
366
+	{
367
+		if ($value === \STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT || $value === \STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT || $value === \STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT || \defined('STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT') && $value === \STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT) {
368
+			$options['http']['crypto_method'] = $value;
369
+			return;
370
+		}
371
+		throw new \InvalidArgumentException('Invalid crypto_method request option: unknown version provided');
372
+	}
373
+	/**
374
+	 * @param mixed $value as passed via Request transfer options.
375
+	 */
376
+	private function add_verify(RequestInterface $request, array &$options, $value, array &$params) : void
377
+	{
378
+		if ($value === \false) {
379
+			$options['ssl']['verify_peer'] = \false;
380
+			$options['ssl']['verify_peer_name'] = \false;
381
+			return;
382
+		}
383
+		if (\is_string($value)) {
384
+			$options['ssl']['cafile'] = $value;
385
+			if (!\file_exists($value)) {
386
+				throw new \RuntimeException("SSL CA bundle not found: {$value}");
387
+			}
388
+		} elseif ($value !== \true) {
389
+			throw new \InvalidArgumentException('Invalid verify request option');
390
+		}
391
+		$options['ssl']['verify_peer'] = \true;
392
+		$options['ssl']['verify_peer_name'] = \true;
393
+		$options['ssl']['allow_self_signed'] = \false;
394
+	}
395
+	/**
396
+	 * @param mixed $value as passed via Request transfer options.
397
+	 */
398
+	private function add_cert(RequestInterface $request, array &$options, $value, array &$params) : void
399
+	{
400
+		if (\is_array($value)) {
401
+			$options['ssl']['passphrase'] = $value[1];
402
+			$value = $value[0];
403
+		}
404
+		if (!\file_exists($value)) {
405
+			throw new \RuntimeException("SSL certificate not found: {$value}");
406
+		}
407
+		$options['ssl']['local_cert'] = $value;
408
+	}
409
+	/**
410
+	 * @param mixed $value as passed via Request transfer options.
411
+	 */
412
+	private function add_progress(RequestInterface $request, array &$options, $value, array &$params) : void
413
+	{
414
+		self::addNotification($params, static function ($code, $a, $b, $c, $transferred, $total) use($value) {
415
+			if ($code == \STREAM_NOTIFY_PROGRESS) {
416
+				// The upload progress cannot be determined. Use 0 for cURL compatibility:
417
+				// https://curl.se/libcurl/c/CURLOPT_PROGRESSFUNCTION.html
418
+				$value($total, $transferred, 0, 0);
419
+			}
420
+		});
421
+	}
422
+	/**
423
+	 * @param mixed $value as passed via Request transfer options.
424
+	 */
425
+	private function add_debug(RequestInterface $request, array &$options, $value, array &$params) : void
426
+	{
427
+		if ($value === \false) {
428
+			return;
429
+		}
430
+		static $map = [\STREAM_NOTIFY_CONNECT => 'CONNECT', \STREAM_NOTIFY_AUTH_REQUIRED => 'AUTH_REQUIRED', \STREAM_NOTIFY_AUTH_RESULT => 'AUTH_RESULT', \STREAM_NOTIFY_MIME_TYPE_IS => 'MIME_TYPE_IS', \STREAM_NOTIFY_FILE_SIZE_IS => 'FILE_SIZE_IS', \STREAM_NOTIFY_REDIRECTED => 'REDIRECTED', \STREAM_NOTIFY_PROGRESS => 'PROGRESS', \STREAM_NOTIFY_FAILURE => 'FAILURE', \STREAM_NOTIFY_COMPLETED => 'COMPLETED', \STREAM_NOTIFY_RESOLVE => 'RESOLVE'];
431
+		static $args = ['severity', 'message', 'message_code', 'bytes_transferred', 'bytes_max'];
432
+		$value = Utils::debugResource($value);
433
+		$ident = $request->getMethod() . ' ' . $request->getUri()->withFragment('');
434
+		self::addNotification($params, static function (int $code, ...$passed) use($ident, $value, $map, $args) : void {
435
+			\fprintf($value, '<%s> [%s] ', $ident, $map[$code]);
436
+			foreach (\array_filter($passed) as $i => $v) {
437
+				\fwrite($value, $args[$i] . ': "' . $v . '" ');
438
+			}
439
+			\fwrite($value, "\n");
440
+		});
441
+	}
442
+	private static function addNotification(array &$params, callable $notify) : void
443
+	{
444
+		// Wrap the existing function if needed.
445
+		if (!isset($params['notification'])) {
446
+			$params['notification'] = $notify;
447
+		} else {
448
+			$params['notification'] = self::callArray([$params['notification'], $notify]);
449
+		}
450
+	}
451
+	private static function callArray(array $functions) : callable
452
+	{
453
+		return static function (...$args) use($functions) {
454
+			foreach ($functions as $fn) {
455
+				$fn(...$args);
456
+			}
457
+		};
458
+	}
459 459
 }
Please login to merge, or discard this patch.
lib/Vendor/GuzzleHttp/Handler/CurlMultiHandler.php 1 patch
Indentation   +213 added lines, -213 removed lines patch added patch discarded remove patch
@@ -19,217 +19,217 @@
 block discarded – undo
19 19
  */
20 20
 class CurlMultiHandler
21 21
 {
22
-    /**
23
-     * @var CurlFactoryInterface
24
-     */
25
-    private $factory;
26
-    /**
27
-     * @var int
28
-     */
29
-    private $selectTimeout;
30
-    /**
31
-     * @var int Will be higher than 0 when `curl_multi_exec` is still running.
32
-     */
33
-    private $active = 0;
34
-    /**
35
-     * @var array Request entry handles, indexed by handle id in `addRequest`.
36
-     *
37
-     * @see CurlMultiHandler::addRequest
38
-     */
39
-    private $handles = [];
40
-    /**
41
-     * @var array<int, float> An array of delay times, indexed by handle id in `addRequest`.
42
-     *
43
-     * @see CurlMultiHandler::addRequest
44
-     */
45
-    private $delays = [];
46
-    /**
47
-     * @var array<mixed> An associative array of CURLMOPT_* options and corresponding values for curl_multi_setopt()
48
-     */
49
-    private $options = [];
50
-    /** @var resource|\CurlMultiHandle */
51
-    private $_mh;
52
-    /**
53
-     * This handler accepts the following options:
54
-     *
55
-     * - handle_factory: An optional factory  used to create curl handles
56
-     * - select_timeout: Optional timeout (in seconds) to block before timing
57
-     *   out while selecting curl handles. Defaults to 1 second.
58
-     * - options: An associative array of CURLMOPT_* options and
59
-     *   corresponding values for curl_multi_setopt()
60
-     */
61
-    public function __construct(array $options = [])
62
-    {
63
-        $this->factory = $options['handle_factory'] ?? new CurlFactory(50);
64
-        if (isset($options['select_timeout'])) {
65
-            $this->selectTimeout = $options['select_timeout'];
66
-        } elseif ($selectTimeout = Utils::getenv('GUZZLE_CURL_SELECT_TIMEOUT')) {
67
-            @\trigger_error('Since guzzlehttp/guzzle 7.2.0: Using environment variable GUZZLE_CURL_SELECT_TIMEOUT is deprecated. Use option "select_timeout" instead.', \E_USER_DEPRECATED);
68
-            $this->selectTimeout = (int) $selectTimeout;
69
-        } else {
70
-            $this->selectTimeout = 1;
71
-        }
72
-        $this->options = $options['options'] ?? [];
73
-        // unsetting the property forces the first access to go through
74
-        // __get().
75
-        unset($this->_mh);
76
-    }
77
-    /**
78
-     * @param string $name
79
-     *
80
-     * @return resource|\CurlMultiHandle
81
-     *
82
-     * @throws \BadMethodCallException when another field as `_mh` will be gotten
83
-     * @throws \RuntimeException       when curl can not initialize a multi handle
84
-     */
85
-    public function __get($name)
86
-    {
87
-        if ($name !== '_mh') {
88
-            throw new \BadMethodCallException("Can not get other property as '_mh'.");
89
-        }
90
-        $multiHandle = \curl_multi_init();
91
-        if (\false === $multiHandle) {
92
-            throw new \RuntimeException('Can not initialize curl multi handle.');
93
-        }
94
-        $this->_mh = $multiHandle;
95
-        foreach ($this->options as $option => $value) {
96
-            // A warning is raised in case of a wrong option.
97
-            \curl_multi_setopt($this->_mh, $option, $value);
98
-        }
99
-        return $this->_mh;
100
-    }
101
-    public function __destruct()
102
-    {
103
-        if (isset($this->_mh)) {
104
-            \curl_multi_close($this->_mh);
105
-            unset($this->_mh);
106
-        }
107
-    }
108
-    public function __invoke(RequestInterface $request, array $options) : PromiseInterface
109
-    {
110
-        $easy = $this->factory->create($request, $options);
111
-        $id = (int) $easy->handle;
112
-        $promise = new Promise([$this, 'execute'], function () use($id) {
113
-            return $this->cancel($id);
114
-        });
115
-        $this->addRequest(['easy' => $easy, 'deferred' => $promise]);
116
-        return $promise;
117
-    }
118
-    /**
119
-     * Ticks the curl event loop.
120
-     */
121
-    public function tick() : void
122
-    {
123
-        // Add any delayed handles if needed.
124
-        if ($this->delays) {
125
-            $currentTime = Utils::currentTime();
126
-            foreach ($this->delays as $id => $delay) {
127
-                if ($currentTime >= $delay) {
128
-                    unset($this->delays[$id]);
129
-                    \curl_multi_add_handle($this->_mh, $this->handles[$id]['easy']->handle);
130
-                }
131
-            }
132
-        }
133
-        // Run curl_multi_exec in the queue to enable other async tasks to run
134
-        P\Utils::queue()->add(Closure::fromCallable([$this, 'tickInQueue']));
135
-        // Step through the task queue which may add additional requests.
136
-        P\Utils::queue()->run();
137
-        if ($this->active && \curl_multi_select($this->_mh, $this->selectTimeout) === -1) {
138
-            // Perform a usleep if a select returns -1.
139
-            // See: https://bugs.php.net/bug.php?id=61141
140
-            \usleep(250);
141
-        }
142
-        while (\curl_multi_exec($this->_mh, $this->active) === \CURLM_CALL_MULTI_PERFORM) {
143
-            // Prevent busy looping for slow HTTP requests.
144
-            \curl_multi_select($this->_mh, $this->selectTimeout);
145
-        }
146
-        $this->processMessages();
147
-    }
148
-    /**
149
-     * Runs \curl_multi_exec() inside the event loop, to prevent busy looping
150
-     */
151
-    private function tickInQueue() : void
152
-    {
153
-        if (\curl_multi_exec($this->_mh, $this->active) === \CURLM_CALL_MULTI_PERFORM) {
154
-            \curl_multi_select($this->_mh, 0);
155
-            P\Utils::queue()->add(Closure::fromCallable([$this, 'tickInQueue']));
156
-        }
157
-    }
158
-    /**
159
-     * Runs until all outstanding connections have completed.
160
-     */
161
-    public function execute() : void
162
-    {
163
-        $queue = P\Utils::queue();
164
-        while ($this->handles || !$queue->isEmpty()) {
165
-            // If there are no transfers, then sleep for the next delay
166
-            if (!$this->active && $this->delays) {
167
-                \usleep($this->timeToNext());
168
-            }
169
-            $this->tick();
170
-        }
171
-    }
172
-    private function addRequest(array $entry) : void
173
-    {
174
-        $easy = $entry['easy'];
175
-        $id = (int) $easy->handle;
176
-        $this->handles[$id] = $entry;
177
-        if (empty($easy->options['delay'])) {
178
-            \curl_multi_add_handle($this->_mh, $easy->handle);
179
-        } else {
180
-            $this->delays[$id] = Utils::currentTime() + $easy->options['delay'] / 1000;
181
-        }
182
-    }
183
-    /**
184
-     * Cancels a handle from sending and removes references to it.
185
-     *
186
-     * @param int $id Handle ID to cancel and remove.
187
-     *
188
-     * @return bool True on success, false on failure.
189
-     */
190
-    private function cancel($id) : bool
191
-    {
192
-        if (!\is_int($id)) {
193
-            trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing an integer to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__);
194
-        }
195
-        // Cannot cancel if it has been processed.
196
-        if (!isset($this->handles[$id])) {
197
-            return \false;
198
-        }
199
-        $handle = $this->handles[$id]['easy']->handle;
200
-        unset($this->delays[$id], $this->handles[$id]);
201
-        \curl_multi_remove_handle($this->_mh, $handle);
202
-        \curl_close($handle);
203
-        return \true;
204
-    }
205
-    private function processMessages() : void
206
-    {
207
-        while ($done = \curl_multi_info_read($this->_mh)) {
208
-            if ($done['msg'] !== \CURLMSG_DONE) {
209
-                // if it's not done, then it would be premature to remove the handle. ref https://github.com/guzzle/guzzle/pull/2892#issuecomment-945150216
210
-                continue;
211
-            }
212
-            $id = (int) $done['handle'];
213
-            \curl_multi_remove_handle($this->_mh, $done['handle']);
214
-            if (!isset($this->handles[$id])) {
215
-                // Probably was cancelled.
216
-                continue;
217
-            }
218
-            $entry = $this->handles[$id];
219
-            unset($this->handles[$id], $this->delays[$id]);
220
-            $entry['easy']->errno = $done['result'];
221
-            $entry['deferred']->resolve(CurlFactory::finish($this, $entry['easy'], $this->factory));
222
-        }
223
-    }
224
-    private function timeToNext() : int
225
-    {
226
-        $currentTime = Utils::currentTime();
227
-        $nextTime = \PHP_INT_MAX;
228
-        foreach ($this->delays as $time) {
229
-            if ($time < $nextTime) {
230
-                $nextTime = $time;
231
-            }
232
-        }
233
-        return (int) \max(0, $nextTime - $currentTime) * 1000000;
234
-    }
22
+	/**
23
+	 * @var CurlFactoryInterface
24
+	 */
25
+	private $factory;
26
+	/**
27
+	 * @var int
28
+	 */
29
+	private $selectTimeout;
30
+	/**
31
+	 * @var int Will be higher than 0 when `curl_multi_exec` is still running.
32
+	 */
33
+	private $active = 0;
34
+	/**
35
+	 * @var array Request entry handles, indexed by handle id in `addRequest`.
36
+	 *
37
+	 * @see CurlMultiHandler::addRequest
38
+	 */
39
+	private $handles = [];
40
+	/**
41
+	 * @var array<int, float> An array of delay times, indexed by handle id in `addRequest`.
42
+	 *
43
+	 * @see CurlMultiHandler::addRequest
44
+	 */
45
+	private $delays = [];
46
+	/**
47
+	 * @var array<mixed> An associative array of CURLMOPT_* options and corresponding values for curl_multi_setopt()
48
+	 */
49
+	private $options = [];
50
+	/** @var resource|\CurlMultiHandle */
51
+	private $_mh;
52
+	/**
53
+	 * This handler accepts the following options:
54
+	 *
55
+	 * - handle_factory: An optional factory  used to create curl handles
56
+	 * - select_timeout: Optional timeout (in seconds) to block before timing
57
+	 *   out while selecting curl handles. Defaults to 1 second.
58
+	 * - options: An associative array of CURLMOPT_* options and
59
+	 *   corresponding values for curl_multi_setopt()
60
+	 */
61
+	public function __construct(array $options = [])
62
+	{
63
+		$this->factory = $options['handle_factory'] ?? new CurlFactory(50);
64
+		if (isset($options['select_timeout'])) {
65
+			$this->selectTimeout = $options['select_timeout'];
66
+		} elseif ($selectTimeout = Utils::getenv('GUZZLE_CURL_SELECT_TIMEOUT')) {
67
+			@\trigger_error('Since guzzlehttp/guzzle 7.2.0: Using environment variable GUZZLE_CURL_SELECT_TIMEOUT is deprecated. Use option "select_timeout" instead.', \E_USER_DEPRECATED);
68
+			$this->selectTimeout = (int) $selectTimeout;
69
+		} else {
70
+			$this->selectTimeout = 1;
71
+		}
72
+		$this->options = $options['options'] ?? [];
73
+		// unsetting the property forces the first access to go through
74
+		// __get().
75
+		unset($this->_mh);
76
+	}
77
+	/**
78
+	 * @param string $name
79
+	 *
80
+	 * @return resource|\CurlMultiHandle
81
+	 *
82
+	 * @throws \BadMethodCallException when another field as `_mh` will be gotten
83
+	 * @throws \RuntimeException       when curl can not initialize a multi handle
84
+	 */
85
+	public function __get($name)
86
+	{
87
+		if ($name !== '_mh') {
88
+			throw new \BadMethodCallException("Can not get other property as '_mh'.");
89
+		}
90
+		$multiHandle = \curl_multi_init();
91
+		if (\false === $multiHandle) {
92
+			throw new \RuntimeException('Can not initialize curl multi handle.');
93
+		}
94
+		$this->_mh = $multiHandle;
95
+		foreach ($this->options as $option => $value) {
96
+			// A warning is raised in case of a wrong option.
97
+			\curl_multi_setopt($this->_mh, $option, $value);
98
+		}
99
+		return $this->_mh;
100
+	}
101
+	public function __destruct()
102
+	{
103
+		if (isset($this->_mh)) {
104
+			\curl_multi_close($this->_mh);
105
+			unset($this->_mh);
106
+		}
107
+	}
108
+	public function __invoke(RequestInterface $request, array $options) : PromiseInterface
109
+	{
110
+		$easy = $this->factory->create($request, $options);
111
+		$id = (int) $easy->handle;
112
+		$promise = new Promise([$this, 'execute'], function () use($id) {
113
+			return $this->cancel($id);
114
+		});
115
+		$this->addRequest(['easy' => $easy, 'deferred' => $promise]);
116
+		return $promise;
117
+	}
118
+	/**
119
+	 * Ticks the curl event loop.
120
+	 */
121
+	public function tick() : void
122
+	{
123
+		// Add any delayed handles if needed.
124
+		if ($this->delays) {
125
+			$currentTime = Utils::currentTime();
126
+			foreach ($this->delays as $id => $delay) {
127
+				if ($currentTime >= $delay) {
128
+					unset($this->delays[$id]);
129
+					\curl_multi_add_handle($this->_mh, $this->handles[$id]['easy']->handle);
130
+				}
131
+			}
132
+		}
133
+		// Run curl_multi_exec in the queue to enable other async tasks to run
134
+		P\Utils::queue()->add(Closure::fromCallable([$this, 'tickInQueue']));
135
+		// Step through the task queue which may add additional requests.
136
+		P\Utils::queue()->run();
137
+		if ($this->active && \curl_multi_select($this->_mh, $this->selectTimeout) === -1) {
138
+			// Perform a usleep if a select returns -1.
139
+			// See: https://bugs.php.net/bug.php?id=61141
140
+			\usleep(250);
141
+		}
142
+		while (\curl_multi_exec($this->_mh, $this->active) === \CURLM_CALL_MULTI_PERFORM) {
143
+			// Prevent busy looping for slow HTTP requests.
144
+			\curl_multi_select($this->_mh, $this->selectTimeout);
145
+		}
146
+		$this->processMessages();
147
+	}
148
+	/**
149
+	 * Runs \curl_multi_exec() inside the event loop, to prevent busy looping
150
+	 */
151
+	private function tickInQueue() : void
152
+	{
153
+		if (\curl_multi_exec($this->_mh, $this->active) === \CURLM_CALL_MULTI_PERFORM) {
154
+			\curl_multi_select($this->_mh, 0);
155
+			P\Utils::queue()->add(Closure::fromCallable([$this, 'tickInQueue']));
156
+		}
157
+	}
158
+	/**
159
+	 * Runs until all outstanding connections have completed.
160
+	 */
161
+	public function execute() : void
162
+	{
163
+		$queue = P\Utils::queue();
164
+		while ($this->handles || !$queue->isEmpty()) {
165
+			// If there are no transfers, then sleep for the next delay
166
+			if (!$this->active && $this->delays) {
167
+				\usleep($this->timeToNext());
168
+			}
169
+			$this->tick();
170
+		}
171
+	}
172
+	private function addRequest(array $entry) : void
173
+	{
174
+		$easy = $entry['easy'];
175
+		$id = (int) $easy->handle;
176
+		$this->handles[$id] = $entry;
177
+		if (empty($easy->options['delay'])) {
178
+			\curl_multi_add_handle($this->_mh, $easy->handle);
179
+		} else {
180
+			$this->delays[$id] = Utils::currentTime() + $easy->options['delay'] / 1000;
181
+		}
182
+	}
183
+	/**
184
+	 * Cancels a handle from sending and removes references to it.
185
+	 *
186
+	 * @param int $id Handle ID to cancel and remove.
187
+	 *
188
+	 * @return bool True on success, false on failure.
189
+	 */
190
+	private function cancel($id) : bool
191
+	{
192
+		if (!\is_int($id)) {
193
+			trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing an integer to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__);
194
+		}
195
+		// Cannot cancel if it has been processed.
196
+		if (!isset($this->handles[$id])) {
197
+			return \false;
198
+		}
199
+		$handle = $this->handles[$id]['easy']->handle;
200
+		unset($this->delays[$id], $this->handles[$id]);
201
+		\curl_multi_remove_handle($this->_mh, $handle);
202
+		\curl_close($handle);
203
+		return \true;
204
+	}
205
+	private function processMessages() : void
206
+	{
207
+		while ($done = \curl_multi_info_read($this->_mh)) {
208
+			if ($done['msg'] !== \CURLMSG_DONE) {
209
+				// if it's not done, then it would be premature to remove the handle. ref https://github.com/guzzle/guzzle/pull/2892#issuecomment-945150216
210
+				continue;
211
+			}
212
+			$id = (int) $done['handle'];
213
+			\curl_multi_remove_handle($this->_mh, $done['handle']);
214
+			if (!isset($this->handles[$id])) {
215
+				// Probably was cancelled.
216
+				continue;
217
+			}
218
+			$entry = $this->handles[$id];
219
+			unset($this->handles[$id], $this->delays[$id]);
220
+			$entry['easy']->errno = $done['result'];
221
+			$entry['deferred']->resolve(CurlFactory::finish($this, $entry['easy'], $this->factory));
222
+		}
223
+	}
224
+	private function timeToNext() : int
225
+	{
226
+		$currentTime = Utils::currentTime();
227
+		$nextTime = \PHP_INT_MAX;
228
+		foreach ($this->delays as $time) {
229
+			if ($time < $nextTime) {
230
+				$nextTime = $time;
231
+			}
232
+		}
233
+		return (int) \max(0, $nextTime - $currentTime) * 1000000;
234
+	}
235 235
 }
Please login to merge, or discard this patch.
lib/Vendor/GuzzleHttp/Handler/MockHandler.php 1 patch
Indentation   +153 added lines, -153 removed lines patch added patch discarded remove patch
@@ -18,157 +18,157 @@
 block discarded – undo
18 18
  */
19 19
 class MockHandler implements \Countable
20 20
 {
21
-    /**
22
-     * @var array
23
-     */
24
-    private $queue = [];
25
-    /**
26
-     * @var RequestInterface|null
27
-     */
28
-    private $lastRequest;
29
-    /**
30
-     * @var array
31
-     */
32
-    private $lastOptions = [];
33
-    /**
34
-     * @var callable|null
35
-     */
36
-    private $onFulfilled;
37
-    /**
38
-     * @var callable|null
39
-     */
40
-    private $onRejected;
41
-    /**
42
-     * Creates a new MockHandler that uses the default handler stack list of
43
-     * middlewares.
44
-     *
45
-     * @param array|null    $queue       Array of responses, callables, or exceptions.
46
-     * @param callable|null $onFulfilled Callback to invoke when the return value is fulfilled.
47
-     * @param callable|null $onRejected  Callback to invoke when the return value is rejected.
48
-     */
49
-    public static function createWithMiddleware(?array $queue = null, ?callable $onFulfilled = null, ?callable $onRejected = null) : HandlerStack
50
-    {
51
-        return HandlerStack::create(new self($queue, $onFulfilled, $onRejected));
52
-    }
53
-    /**
54
-     * The passed in value must be an array of
55
-     * {@see ResponseInterface} objects, Exceptions,
56
-     * callables, or Promises.
57
-     *
58
-     * @param array<int, mixed>|null $queue       The parameters to be passed to the append function, as an indexed array.
59
-     * @param callable|null          $onFulfilled Callback to invoke when the return value is fulfilled.
60
-     * @param callable|null          $onRejected  Callback to invoke when the return value is rejected.
61
-     */
62
-    public function __construct(?array $queue = null, ?callable $onFulfilled = null, ?callable $onRejected = null)
63
-    {
64
-        $this->onFulfilled = $onFulfilled;
65
-        $this->onRejected = $onRejected;
66
-        if ($queue) {
67
-            // array_values included for BC
68
-            $this->append(...\array_values($queue));
69
-        }
70
-    }
71
-    public function __invoke(RequestInterface $request, array $options) : PromiseInterface
72
-    {
73
-        if (!$this->queue) {
74
-            throw new \OutOfBoundsException('Mock queue is empty');
75
-        }
76
-        if (isset($options['delay']) && \is_numeric($options['delay'])) {
77
-            \usleep((int) $options['delay'] * 1000);
78
-        }
79
-        $this->lastRequest = $request;
80
-        $this->lastOptions = $options;
81
-        $response = \array_shift($this->queue);
82
-        if (isset($options['on_headers'])) {
83
-            if (!\is_callable($options['on_headers'])) {
84
-                throw new \InvalidArgumentException('on_headers must be callable');
85
-            }
86
-            try {
87
-                $options['on_headers']($response);
88
-            } catch (\Exception $e) {
89
-                $msg = 'An error was encountered during the on_headers event';
90
-                $response = new RequestException($msg, $request, $response, $e);
91
-            }
92
-        }
93
-        if (\is_callable($response)) {
94
-            $response = $response($request, $options);
95
-        }
96
-        $response = $response instanceof \Throwable ? P\Create::rejectionFor($response) : P\Create::promiseFor($response);
97
-        return $response->then(function (?ResponseInterface $value) use($request, $options) {
98
-            $this->invokeStats($request, $options, $value);
99
-            if ($this->onFulfilled) {
100
-                ($this->onFulfilled)($value);
101
-            }
102
-            if ($value !== null && isset($options['sink'])) {
103
-                $contents = (string) $value->getBody();
104
-                $sink = $options['sink'];
105
-                if (\is_resource($sink)) {
106
-                    \fwrite($sink, $contents);
107
-                } elseif (\is_string($sink)) {
108
-                    \file_put_contents($sink, $contents);
109
-                } elseif ($sink instanceof StreamInterface) {
110
-                    $sink->write($contents);
111
-                }
112
-            }
113
-            return $value;
114
-        }, function ($reason) use($request, $options) {
115
-            $this->invokeStats($request, $options, null, $reason);
116
-            if ($this->onRejected) {
117
-                ($this->onRejected)($reason);
118
-            }
119
-            return P\Create::rejectionFor($reason);
120
-        });
121
-    }
122
-    /**
123
-     * Adds one or more variadic requests, exceptions, callables, or promises
124
-     * to the queue.
125
-     *
126
-     * @param mixed ...$values
127
-     */
128
-    public function append(...$values) : void
129
-    {
130
-        foreach ($values as $value) {
131
-            if ($value instanceof ResponseInterface || $value instanceof \Throwable || $value instanceof PromiseInterface || \is_callable($value)) {
132
-                $this->queue[] = $value;
133
-            } else {
134
-                throw new \TypeError('Expected a Response, Promise, Throwable or callable. Found ' . Utils::describeType($value));
135
-            }
136
-        }
137
-    }
138
-    /**
139
-     * Get the last received request.
140
-     */
141
-    public function getLastRequest() : ?RequestInterface
142
-    {
143
-        return $this->lastRequest;
144
-    }
145
-    /**
146
-     * Get the last received request options.
147
-     */
148
-    public function getLastOptions() : array
149
-    {
150
-        return $this->lastOptions;
151
-    }
152
-    /**
153
-     * Returns the number of remaining items in the queue.
154
-     */
155
-    public function count() : int
156
-    {
157
-        return \count($this->queue);
158
-    }
159
-    public function reset() : void
160
-    {
161
-        $this->queue = [];
162
-    }
163
-    /**
164
-     * @param mixed $reason Promise or reason.
165
-     */
166
-    private function invokeStats(RequestInterface $request, array $options, ?ResponseInterface $response = null, $reason = null) : void
167
-    {
168
-        if (isset($options['on_stats'])) {
169
-            $transferTime = $options['transfer_time'] ?? 0;
170
-            $stats = new TransferStats($request, $response, $transferTime, $reason);
171
-            $options['on_stats']($stats);
172
-        }
173
-    }
21
+	/**
22
+	 * @var array
23
+	 */
24
+	private $queue = [];
25
+	/**
26
+	 * @var RequestInterface|null
27
+	 */
28
+	private $lastRequest;
29
+	/**
30
+	 * @var array
31
+	 */
32
+	private $lastOptions = [];
33
+	/**
34
+	 * @var callable|null
35
+	 */
36
+	private $onFulfilled;
37
+	/**
38
+	 * @var callable|null
39
+	 */
40
+	private $onRejected;
41
+	/**
42
+	 * Creates a new MockHandler that uses the default handler stack list of
43
+	 * middlewares.
44
+	 *
45
+	 * @param array|null    $queue       Array of responses, callables, or exceptions.
46
+	 * @param callable|null $onFulfilled Callback to invoke when the return value is fulfilled.
47
+	 * @param callable|null $onRejected  Callback to invoke when the return value is rejected.
48
+	 */
49
+	public static function createWithMiddleware(?array $queue = null, ?callable $onFulfilled = null, ?callable $onRejected = null) : HandlerStack
50
+	{
51
+		return HandlerStack::create(new self($queue, $onFulfilled, $onRejected));
52
+	}
53
+	/**
54
+	 * The passed in value must be an array of
55
+	 * {@see ResponseInterface} objects, Exceptions,
56
+	 * callables, or Promises.
57
+	 *
58
+	 * @param array<int, mixed>|null $queue       The parameters to be passed to the append function, as an indexed array.
59
+	 * @param callable|null          $onFulfilled Callback to invoke when the return value is fulfilled.
60
+	 * @param callable|null          $onRejected  Callback to invoke when the return value is rejected.
61
+	 */
62
+	public function __construct(?array $queue = null, ?callable $onFulfilled = null, ?callable $onRejected = null)
63
+	{
64
+		$this->onFulfilled = $onFulfilled;
65
+		$this->onRejected = $onRejected;
66
+		if ($queue) {
67
+			// array_values included for BC
68
+			$this->append(...\array_values($queue));
69
+		}
70
+	}
71
+	public function __invoke(RequestInterface $request, array $options) : PromiseInterface
72
+	{
73
+		if (!$this->queue) {
74
+			throw new \OutOfBoundsException('Mock queue is empty');
75
+		}
76
+		if (isset($options['delay']) && \is_numeric($options['delay'])) {
77
+			\usleep((int) $options['delay'] * 1000);
78
+		}
79
+		$this->lastRequest = $request;
80
+		$this->lastOptions = $options;
81
+		$response = \array_shift($this->queue);
82
+		if (isset($options['on_headers'])) {
83
+			if (!\is_callable($options['on_headers'])) {
84
+				throw new \InvalidArgumentException('on_headers must be callable');
85
+			}
86
+			try {
87
+				$options['on_headers']($response);
88
+			} catch (\Exception $e) {
89
+				$msg = 'An error was encountered during the on_headers event';
90
+				$response = new RequestException($msg, $request, $response, $e);
91
+			}
92
+		}
93
+		if (\is_callable($response)) {
94
+			$response = $response($request, $options);
95
+		}
96
+		$response = $response instanceof \Throwable ? P\Create::rejectionFor($response) : P\Create::promiseFor($response);
97
+		return $response->then(function (?ResponseInterface $value) use($request, $options) {
98
+			$this->invokeStats($request, $options, $value);
99
+			if ($this->onFulfilled) {
100
+				($this->onFulfilled)($value);
101
+			}
102
+			if ($value !== null && isset($options['sink'])) {
103
+				$contents = (string) $value->getBody();
104
+				$sink = $options['sink'];
105
+				if (\is_resource($sink)) {
106
+					\fwrite($sink, $contents);
107
+				} elseif (\is_string($sink)) {
108
+					\file_put_contents($sink, $contents);
109
+				} elseif ($sink instanceof StreamInterface) {
110
+					$sink->write($contents);
111
+				}
112
+			}
113
+			return $value;
114
+		}, function ($reason) use($request, $options) {
115
+			$this->invokeStats($request, $options, null, $reason);
116
+			if ($this->onRejected) {
117
+				($this->onRejected)($reason);
118
+			}
119
+			return P\Create::rejectionFor($reason);
120
+		});
121
+	}
122
+	/**
123
+	 * Adds one or more variadic requests, exceptions, callables, or promises
124
+	 * to the queue.
125
+	 *
126
+	 * @param mixed ...$values
127
+	 */
128
+	public function append(...$values) : void
129
+	{
130
+		foreach ($values as $value) {
131
+			if ($value instanceof ResponseInterface || $value instanceof \Throwable || $value instanceof PromiseInterface || \is_callable($value)) {
132
+				$this->queue[] = $value;
133
+			} else {
134
+				throw new \TypeError('Expected a Response, Promise, Throwable or callable. Found ' . Utils::describeType($value));
135
+			}
136
+		}
137
+	}
138
+	/**
139
+	 * Get the last received request.
140
+	 */
141
+	public function getLastRequest() : ?RequestInterface
142
+	{
143
+		return $this->lastRequest;
144
+	}
145
+	/**
146
+	 * Get the last received request options.
147
+	 */
148
+	public function getLastOptions() : array
149
+	{
150
+		return $this->lastOptions;
151
+	}
152
+	/**
153
+	 * Returns the number of remaining items in the queue.
154
+	 */
155
+	public function count() : int
156
+	{
157
+		return \count($this->queue);
158
+	}
159
+	public function reset() : void
160
+	{
161
+		$this->queue = [];
162
+	}
163
+	/**
164
+	 * @param mixed $reason Promise or reason.
165
+	 */
166
+	private function invokeStats(RequestInterface $request, array $options, ?ResponseInterface $response = null, $reason = null) : void
167
+	{
168
+		if (isset($options['on_stats'])) {
169
+			$transferTime = $options['transfer_time'] ?? 0;
170
+			$stats = new TransferStats($request, $response, $transferTime, $reason);
171
+			$options['on_stats']($stats);
172
+		}
173
+	}
174 174
 }
Please login to merge, or discard this patch.
lib/Vendor/GuzzleHttp/Handler/CurlFactory.php 2 patches
Indentation   +541 added lines, -541 removed lines patch added patch discarded remove patch
@@ -19,545 +19,545 @@
 block discarded – undo
19 19
  */
20 20
 class CurlFactory implements CurlFactoryInterface
21 21
 {
22
-    public const CURL_VERSION_STR = 'curl_version';
23
-    /**
24
-     * @deprecated
25
-     */
26
-    public const LOW_CURL_VERSION_NUMBER = '7.21.2';
27
-    /**
28
-     * @var resource[]|\CurlHandle[]
29
-     */
30
-    private $handles = [];
31
-    /**
32
-     * @var int Total number of idle handles to keep in cache
33
-     */
34
-    private $maxHandles;
35
-    /**
36
-     * @param int $maxHandles Maximum number of idle handles.
37
-     */
38
-    public function __construct(int $maxHandles)
39
-    {
40
-        $this->maxHandles = $maxHandles;
41
-    }
42
-    public function create(RequestInterface $request, array $options) : EasyHandle
43
-    {
44
-        $protocolVersion = $request->getProtocolVersion();
45
-        if ('2' === $protocolVersion || '2.0' === $protocolVersion) {
46
-            if (!self::supportsHttp2()) {
47
-                throw new ConnectException('HTTP/2 is supported by the cURL handler, however libcurl is built without HTTP/2 support.', $request);
48
-            }
49
-        } elseif ('1.0' !== $protocolVersion && '1.1' !== $protocolVersion) {
50
-            throw new ConnectException(\sprintf('HTTP/%s is not supported by the cURL handler.', $protocolVersion), $request);
51
-        }
52
-        if (isset($options['curl']['body_as_string'])) {
53
-            $options['_body_as_string'] = $options['curl']['body_as_string'];
54
-            unset($options['curl']['body_as_string']);
55
-        }
56
-        $easy = new EasyHandle();
57
-        $easy->request = $request;
58
-        $easy->options = $options;
59
-        $conf = $this->getDefaultConf($easy);
60
-        $this->applyMethod($easy, $conf);
61
-        $this->applyHandlerOptions($easy, $conf);
62
-        $this->applyHeaders($easy, $conf);
63
-        unset($conf['_headers']);
64
-        // Add handler options from the request configuration options
65
-        if (isset($options['curl'])) {
66
-            $conf = \array_replace($conf, $options['curl']);
67
-        }
68
-        $conf[\CURLOPT_HEADERFUNCTION] = $this->createHeaderFn($easy);
69
-        $easy->handle = $this->handles ? \array_pop($this->handles) : \curl_init();
70
-        \curl_setopt_array($easy->handle, $conf);
71
-        return $easy;
72
-    }
73
-    private static function supportsHttp2() : bool
74
-    {
75
-        static $supportsHttp2 = null;
76
-        if (null === $supportsHttp2) {
77
-            $supportsHttp2 = self::supportsTls12() && \defined('CURL_VERSION_HTTP2') && \CURL_VERSION_HTTP2 & \curl_version()['features'];
78
-        }
79
-        return $supportsHttp2;
80
-    }
81
-    private static function supportsTls12() : bool
82
-    {
83
-        static $supportsTls12 = null;
84
-        if (null === $supportsTls12) {
85
-            $supportsTls12 = \CURL_SSLVERSION_TLSv1_2 & \curl_version()['features'];
86
-        }
87
-        return $supportsTls12;
88
-    }
89
-    private static function supportsTls13() : bool
90
-    {
91
-        static $supportsTls13 = null;
92
-        if (null === $supportsTls13) {
93
-            $supportsTls13 = \defined('CURL_SSLVERSION_TLSv1_3') && \CURL_SSLVERSION_TLSv1_3 & \curl_version()['features'];
94
-        }
95
-        return $supportsTls13;
96
-    }
97
-    public function release(EasyHandle $easy) : void
98
-    {
99
-        $resource = $easy->handle;
100
-        unset($easy->handle);
101
-        if (\count($this->handles) >= $this->maxHandles) {
102
-            \curl_close($resource);
103
-        } else {
104
-            // Remove all callback functions as they can hold onto references
105
-            // and are not cleaned up by curl_reset. Using curl_setopt_array
106
-            // does not work for some reason, so removing each one
107
-            // individually.
108
-            \curl_setopt($resource, \CURLOPT_HEADERFUNCTION, null);
109
-            \curl_setopt($resource, \CURLOPT_READFUNCTION, null);
110
-            \curl_setopt($resource, \CURLOPT_WRITEFUNCTION, null);
111
-            \curl_setopt($resource, \CURLOPT_PROGRESSFUNCTION, null);
112
-            \curl_reset($resource);
113
-            $this->handles[] = $resource;
114
-        }
115
-    }
116
-    /**
117
-     * Completes a cURL transaction, either returning a response promise or a
118
-     * rejected promise.
119
-     *
120
-     * @param callable(RequestInterface, array): PromiseInterface $handler
121
-     * @param CurlFactoryInterface                                $factory Dictates how the handle is released
122
-     */
123
-    public static function finish(callable $handler, EasyHandle $easy, CurlFactoryInterface $factory) : PromiseInterface
124
-    {
125
-        if (isset($easy->options['on_stats'])) {
126
-            self::invokeStats($easy);
127
-        }
128
-        if (!$easy->response || $easy->errno) {
129
-            return self::finishError($handler, $easy, $factory);
130
-        }
131
-        // Return the response if it is present and there is no error.
132
-        $factory->release($easy);
133
-        // Rewind the body of the response if possible.
134
-        $body = $easy->response->getBody();
135
-        if ($body->isSeekable()) {
136
-            $body->rewind();
137
-        }
138
-        return new FulfilledPromise($easy->response);
139
-    }
140
-    private static function invokeStats(EasyHandle $easy) : void
141
-    {
142
-        $curlStats = \curl_getinfo($easy->handle);
143
-        $curlStats['appconnect_time'] = \curl_getinfo($easy->handle, \CURLINFO_APPCONNECT_TIME);
144
-        $stats = new TransferStats($easy->request, $easy->response, $curlStats['total_time'], $easy->errno, $curlStats);
145
-        $easy->options['on_stats']($stats);
146
-    }
147
-    /**
148
-     * @param callable(RequestInterface, array): PromiseInterface $handler
149
-     */
150
-    private static function finishError(callable $handler, EasyHandle $easy, CurlFactoryInterface $factory) : PromiseInterface
151
-    {
152
-        // Get error information and release the handle to the factory.
153
-        $ctx = ['errno' => $easy->errno, 'error' => \curl_error($easy->handle), 'appconnect_time' => \curl_getinfo($easy->handle, \CURLINFO_APPCONNECT_TIME)] + \curl_getinfo($easy->handle);
154
-        $ctx[self::CURL_VERSION_STR] = self::getCurlVersion();
155
-        $factory->release($easy);
156
-        // Retry when nothing is present or when curl failed to rewind.
157
-        if (empty($easy->options['_err_message']) && (!$easy->errno || $easy->errno == 65)) {
158
-            return self::retryFailedRewind($handler, $easy, $ctx);
159
-        }
160
-        return self::createRejection($easy, $ctx);
161
-    }
162
-    private static function getCurlVersion() : string
163
-    {
164
-        static $curlVersion = null;
165
-        if (null === $curlVersion) {
166
-            $curlVersion = \curl_version()['version'];
167
-        }
168
-        return $curlVersion;
169
-    }
170
-    private static function createRejection(EasyHandle $easy, array $ctx) : PromiseInterface
171
-    {
172
-        static $connectionErrors = [\CURLE_OPERATION_TIMEOUTED => \true, \CURLE_COULDNT_RESOLVE_HOST => \true, \CURLE_COULDNT_CONNECT => \true, \CURLE_SSL_CONNECT_ERROR => \true, \CURLE_GOT_NOTHING => \true];
173
-        if ($easy->createResponseException) {
174
-            return P\Create::rejectionFor(new RequestException('An error was encountered while creating the response', $easy->request, $easy->response, $easy->createResponseException, $ctx));
175
-        }
176
-        // If an exception was encountered during the onHeaders event, then
177
-        // return a rejected promise that wraps that exception.
178
-        if ($easy->onHeadersException) {
179
-            return P\Create::rejectionFor(new RequestException('An error was encountered during the on_headers event', $easy->request, $easy->response, $easy->onHeadersException, $ctx));
180
-        }
181
-        $uri = $easy->request->getUri();
182
-        $sanitizedError = self::sanitizeCurlError($ctx['error'] ?? '', $uri);
183
-        $message = \sprintf('cURL error %s: %s (%s)', $ctx['errno'], $sanitizedError, 'see https://curl.haxx.se/libcurl/c/libcurl-errors.html');
184
-        if ('' !== $sanitizedError) {
185
-            $redactedUriString = \OCA\FullTextSearch_Elasticsearch\Vendor\GuzzleHttp\Psr7\Utils::redactUserInfo($uri)->__toString();
186
-            if ($redactedUriString !== '' && \false === \strpos($sanitizedError, $redactedUriString)) {
187
-                $message .= \sprintf(' for %s', $redactedUriString);
188
-            }
189
-        }
190
-        // Create a connection exception if it was a specific error code.
191
-        $error = isset($connectionErrors[$easy->errno]) ? new ConnectException($message, $easy->request, null, $ctx) : new RequestException($message, $easy->request, $easy->response, null, $ctx);
192
-        return P\Create::rejectionFor($error);
193
-    }
194
-    private static function sanitizeCurlError(string $error, UriInterface $uri) : string
195
-    {
196
-        if ('' === $error) {
197
-            return $error;
198
-        }
199
-        $baseUri = $uri->withQuery('')->withFragment('');
200
-        $baseUriString = $baseUri->__toString();
201
-        if ('' === $baseUriString) {
202
-            return $error;
203
-        }
204
-        $redactedUriString = \OCA\FullTextSearch_Elasticsearch\Vendor\GuzzleHttp\Psr7\Utils::redactUserInfo($baseUri)->__toString();
205
-        return \str_replace($baseUriString, $redactedUriString, $error);
206
-    }
207
-    /**
208
-     * @return array<int|string, mixed>
209
-     */
210
-    private function getDefaultConf(EasyHandle $easy) : array
211
-    {
212
-        $conf = ['_headers' => $easy->request->getHeaders(), \CURLOPT_CUSTOMREQUEST => $easy->request->getMethod(), \CURLOPT_URL => (string) $easy->request->getUri()->withFragment(''), \CURLOPT_RETURNTRANSFER => \false, \CURLOPT_HEADER => \false, \CURLOPT_CONNECTTIMEOUT => 300];
213
-        if (\defined('CURLOPT_PROTOCOLS')) {
214
-            $conf[\CURLOPT_PROTOCOLS] = \CURLPROTO_HTTP | \CURLPROTO_HTTPS;
215
-        }
216
-        $version = $easy->request->getProtocolVersion();
217
-        if ('2' === $version || '2.0' === $version) {
218
-            $conf[\CURLOPT_HTTP_VERSION] = \CURL_HTTP_VERSION_2_0;
219
-        } elseif ('1.1' === $version) {
220
-            $conf[\CURLOPT_HTTP_VERSION] = \CURL_HTTP_VERSION_1_1;
221
-        } else {
222
-            $conf[\CURLOPT_HTTP_VERSION] = \CURL_HTTP_VERSION_1_0;
223
-        }
224
-        return $conf;
225
-    }
226
-    private function applyMethod(EasyHandle $easy, array &$conf) : void
227
-    {
228
-        $body = $easy->request->getBody();
229
-        $size = $body->getSize();
230
-        if ($size === null || $size > 0) {
231
-            $this->applyBody($easy->request, $easy->options, $conf);
232
-            return;
233
-        }
234
-        $method = $easy->request->getMethod();
235
-        if ($method === 'PUT' || $method === 'POST') {
236
-            // See https://datatracker.ietf.org/doc/html/rfc7230#section-3.3.2
237
-            if (!$easy->request->hasHeader('Content-Length')) {
238
-                $conf[\CURLOPT_HTTPHEADER][] = 'Content-Length: 0';
239
-            }
240
-        } elseif ($method === 'HEAD') {
241
-            $conf[\CURLOPT_NOBODY] = \true;
242
-            unset($conf[\CURLOPT_WRITEFUNCTION], $conf[\CURLOPT_READFUNCTION], $conf[\CURLOPT_FILE], $conf[\CURLOPT_INFILE]);
243
-        }
244
-    }
245
-    private function applyBody(RequestInterface $request, array $options, array &$conf) : void
246
-    {
247
-        $size = $request->hasHeader('Content-Length') ? (int) $request->getHeaderLine('Content-Length') : null;
248
-        // Send the body as a string if the size is less than 1MB OR if the
249
-        // [curl][body_as_string] request value is set.
250
-        if ($size !== null && $size < 1000000 || !empty($options['_body_as_string'])) {
251
-            $conf[\CURLOPT_POSTFIELDS] = (string) $request->getBody();
252
-            // Don't duplicate the Content-Length header
253
-            $this->removeHeader('Content-Length', $conf);
254
-            $this->removeHeader('Transfer-Encoding', $conf);
255
-        } else {
256
-            $conf[\CURLOPT_UPLOAD] = \true;
257
-            if ($size !== null) {
258
-                $conf[\CURLOPT_INFILESIZE] = $size;
259
-                $this->removeHeader('Content-Length', $conf);
260
-            }
261
-            $body = $request->getBody();
262
-            if ($body->isSeekable()) {
263
-                $body->rewind();
264
-            }
265
-            $conf[\CURLOPT_READFUNCTION] = static function ($ch, $fd, $length) use($body) {
266
-                return $body->read($length);
267
-            };
268
-        }
269
-        // If the Expect header is not present, prevent curl from adding it
270
-        if (!$request->hasHeader('Expect')) {
271
-            $conf[\CURLOPT_HTTPHEADER][] = 'Expect:';
272
-        }
273
-        // cURL sometimes adds a content-type by default. Prevent this.
274
-        if (!$request->hasHeader('Content-Type')) {
275
-            $conf[\CURLOPT_HTTPHEADER][] = 'Content-Type:';
276
-        }
277
-    }
278
-    private function applyHeaders(EasyHandle $easy, array &$conf) : void
279
-    {
280
-        foreach ($conf['_headers'] as $name => $values) {
281
-            foreach ($values as $value) {
282
-                $value = (string) $value;
283
-                if ($value === '') {
284
-                    // cURL requires a special format for empty headers.
285
-                    // See https://github.com/guzzle/guzzle/issues/1882 for more details.
286
-                    $conf[\CURLOPT_HTTPHEADER][] = "{$name};";
287
-                } else {
288
-                    $conf[\CURLOPT_HTTPHEADER][] = "{$name}: {$value}";
289
-                }
290
-            }
291
-        }
292
-        // Remove the Accept header if one was not set
293
-        if (!$easy->request->hasHeader('Accept')) {
294
-            $conf[\CURLOPT_HTTPHEADER][] = 'Accept:';
295
-        }
296
-    }
297
-    /**
298
-     * Remove a header from the options array.
299
-     *
300
-     * @param string $name    Case-insensitive header to remove
301
-     * @param array  $options Array of options to modify
302
-     */
303
-    private function removeHeader(string $name, array &$options) : void
304
-    {
305
-        foreach (\array_keys($options['_headers']) as $key) {
306
-            if (!\strcasecmp($key, $name)) {
307
-                unset($options['_headers'][$key]);
308
-                return;
309
-            }
310
-        }
311
-    }
312
-    private function applyHandlerOptions(EasyHandle $easy, array &$conf) : void
313
-    {
314
-        $options = $easy->options;
315
-        if (isset($options['verify'])) {
316
-            if ($options['verify'] === \false) {
317
-                unset($conf[\CURLOPT_CAINFO]);
318
-                $conf[\CURLOPT_SSL_VERIFYHOST] = 0;
319
-                $conf[\CURLOPT_SSL_VERIFYPEER] = \false;
320
-            } else {
321
-                $conf[\CURLOPT_SSL_VERIFYHOST] = 2;
322
-                $conf[\CURLOPT_SSL_VERIFYPEER] = \true;
323
-                if (\is_string($options['verify'])) {
324
-                    // Throw an error if the file/folder/link path is not valid or doesn't exist.
325
-                    if (!\file_exists($options['verify'])) {
326
-                        throw new \InvalidArgumentException("SSL CA bundle not found: {$options['verify']}");
327
-                    }
328
-                    // If it's a directory or a link to a directory use CURLOPT_CAPATH.
329
-                    // If not, it's probably a file, or a link to a file, so use CURLOPT_CAINFO.
330
-                    if (\is_dir($options['verify']) || \is_link($options['verify']) === \true && ($verifyLink = \readlink($options['verify'])) !== \false && \is_dir($verifyLink)) {
331
-                        $conf[\CURLOPT_CAPATH] = $options['verify'];
332
-                    } else {
333
-                        $conf[\CURLOPT_CAINFO] = $options['verify'];
334
-                    }
335
-                }
336
-            }
337
-        }
338
-        if (!isset($options['curl'][\CURLOPT_ENCODING]) && !empty($options['decode_content'])) {
339
-            $accept = $easy->request->getHeaderLine('Accept-Encoding');
340
-            if ($accept) {
341
-                $conf[\CURLOPT_ENCODING] = $accept;
342
-            } else {
343
-                // The empty string enables all available decoders and implicitly
344
-                // sets a matching 'Accept-Encoding' header.
345
-                $conf[\CURLOPT_ENCODING] = '';
346
-                // But as the user did not specify any encoding preference,
347
-                // let's leave it up to server by preventing curl from sending
348
-                // the header, which will be interpreted as 'Accept-Encoding: *'.
349
-                // https://www.rfc-editor.org/rfc/rfc9110#field.accept-encoding
350
-                $conf[\CURLOPT_HTTPHEADER][] = 'Accept-Encoding:';
351
-            }
352
-        }
353
-        if (!isset($options['sink'])) {
354
-            // Use a default temp stream if no sink was set.
355
-            $options['sink'] = \OCA\FullTextSearch_Elasticsearch\Vendor\GuzzleHttp\Psr7\Utils::tryFopen('php://temp', 'w+');
356
-        }
357
-        $sink = $options['sink'];
358
-        if (!\is_string($sink)) {
359
-            $sink = \OCA\FullTextSearch_Elasticsearch\Vendor\GuzzleHttp\Psr7\Utils::streamFor($sink);
360
-        } elseif (!\is_dir(\dirname($sink))) {
361
-            // Ensure that the directory exists before failing in curl.
362
-            throw new \RuntimeException(\sprintf('Directory %s does not exist for sink value of %s', \dirname($sink), $sink));
363
-        } else {
364
-            $sink = new LazyOpenStream($sink, 'w+');
365
-        }
366
-        $easy->sink = $sink;
367
-        $conf[\CURLOPT_WRITEFUNCTION] = static function ($ch, $write) use($sink) : int {
368
-            return $sink->write($write);
369
-        };
370
-        $timeoutRequiresNoSignal = \false;
371
-        if (isset($options['timeout'])) {
372
-            $timeoutRequiresNoSignal |= $options['timeout'] < 1;
373
-            $conf[\CURLOPT_TIMEOUT_MS] = $options['timeout'] * 1000;
374
-        }
375
-        // CURL default value is CURL_IPRESOLVE_WHATEVER
376
-        if (isset($options['force_ip_resolve'])) {
377
-            if ('v4' === $options['force_ip_resolve']) {
378
-                $conf[\CURLOPT_IPRESOLVE] = \CURL_IPRESOLVE_V4;
379
-            } elseif ('v6' === $options['force_ip_resolve']) {
380
-                $conf[\CURLOPT_IPRESOLVE] = \CURL_IPRESOLVE_V6;
381
-            }
382
-        }
383
-        if (isset($options['connect_timeout'])) {
384
-            $timeoutRequiresNoSignal |= $options['connect_timeout'] < 1;
385
-            $conf[\CURLOPT_CONNECTTIMEOUT_MS] = $options['connect_timeout'] * 1000;
386
-        }
387
-        if ($timeoutRequiresNoSignal && \strtoupper(\substr(\PHP_OS, 0, 3)) !== 'WIN') {
388
-            $conf[\CURLOPT_NOSIGNAL] = \true;
389
-        }
390
-        if (isset($options['proxy'])) {
391
-            if (!\is_array($options['proxy'])) {
392
-                $conf[\CURLOPT_PROXY] = $options['proxy'];
393
-            } else {
394
-                $scheme = $easy->request->getUri()->getScheme();
395
-                if (isset($options['proxy'][$scheme])) {
396
-                    $host = $easy->request->getUri()->getHost();
397
-                    if (isset($options['proxy']['no']) && Utils::isHostInNoProxy($host, $options['proxy']['no'])) {
398
-                        unset($conf[\CURLOPT_PROXY]);
399
-                    } else {
400
-                        $conf[\CURLOPT_PROXY] = $options['proxy'][$scheme];
401
-                    }
402
-                }
403
-            }
404
-        }
405
-        if (isset($options['crypto_method'])) {
406
-            $protocolVersion = $easy->request->getProtocolVersion();
407
-            // If HTTP/2, upgrade TLS 1.0 and 1.1 to 1.2
408
-            if ('2' === $protocolVersion || '2.0' === $protocolVersion) {
409
-                if (\STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT === $options['crypto_method'] || \STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT === $options['crypto_method'] || \STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT === $options['crypto_method']) {
410
-                    $conf[\CURLOPT_SSLVERSION] = \CURL_SSLVERSION_TLSv1_2;
411
-                } elseif (\defined('STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT') && \STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT === $options['crypto_method']) {
412
-                    if (!self::supportsTls13()) {
413
-                        throw new \InvalidArgumentException('Invalid crypto_method request option: TLS 1.3 not supported by your version of cURL');
414
-                    }
415
-                    $conf[\CURLOPT_SSLVERSION] = \CURL_SSLVERSION_TLSv1_3;
416
-                } else {
417
-                    throw new \InvalidArgumentException('Invalid crypto_method request option: unknown version provided');
418
-                }
419
-            } elseif (\STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT === $options['crypto_method']) {
420
-                $conf[\CURLOPT_SSLVERSION] = \CURL_SSLVERSION_TLSv1_0;
421
-            } elseif (\STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT === $options['crypto_method']) {
422
-                $conf[\CURLOPT_SSLVERSION] = \CURL_SSLVERSION_TLSv1_1;
423
-            } elseif (\STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT === $options['crypto_method']) {
424
-                if (!self::supportsTls12()) {
425
-                    throw new \InvalidArgumentException('Invalid crypto_method request option: TLS 1.2 not supported by your version of cURL');
426
-                }
427
-                $conf[\CURLOPT_SSLVERSION] = \CURL_SSLVERSION_TLSv1_2;
428
-            } elseif (\defined('STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT') && \STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT === $options['crypto_method']) {
429
-                if (!self::supportsTls13()) {
430
-                    throw new \InvalidArgumentException('Invalid crypto_method request option: TLS 1.3 not supported by your version of cURL');
431
-                }
432
-                $conf[\CURLOPT_SSLVERSION] = \CURL_SSLVERSION_TLSv1_3;
433
-            } else {
434
-                throw new \InvalidArgumentException('Invalid crypto_method request option: unknown version provided');
435
-            }
436
-        }
437
-        if (isset($options['cert'])) {
438
-            $cert = $options['cert'];
439
-            if (\is_array($cert)) {
440
-                $conf[\CURLOPT_SSLCERTPASSWD] = $cert[1];
441
-                $cert = $cert[0];
442
-            }
443
-            if (!\file_exists($cert)) {
444
-                throw new \InvalidArgumentException("SSL certificate not found: {$cert}");
445
-            }
446
-            // OpenSSL (versions 0.9.3 and later) also support "P12" for PKCS#12-encoded files.
447
-            // see https://curl.se/libcurl/c/CURLOPT_SSLCERTTYPE.html
448
-            $ext = \pathinfo($cert, \PATHINFO_EXTENSION);
449
-            if (\preg_match('#^(der|p12)$#i', $ext)) {
450
-                $conf[\CURLOPT_SSLCERTTYPE] = \strtoupper($ext);
451
-            }
452
-            $conf[\CURLOPT_SSLCERT] = $cert;
453
-        }
454
-        if (isset($options['ssl_key'])) {
455
-            if (\is_array($options['ssl_key'])) {
456
-                if (\count($options['ssl_key']) === 2) {
457
-                    [$sslKey, $conf[\CURLOPT_SSLKEYPASSWD]] = $options['ssl_key'];
458
-                } else {
459
-                    [$sslKey] = $options['ssl_key'];
460
-                }
461
-            }
462
-            $sslKey = $sslKey ?? $options['ssl_key'];
463
-            if (!\file_exists($sslKey)) {
464
-                throw new \InvalidArgumentException("SSL private key not found: {$sslKey}");
465
-            }
466
-            $conf[\CURLOPT_SSLKEY] = $sslKey;
467
-        }
468
-        if (isset($options['progress'])) {
469
-            $progress = $options['progress'];
470
-            if (!\is_callable($progress)) {
471
-                throw new \InvalidArgumentException('progress client option must be callable');
472
-            }
473
-            $conf[\CURLOPT_NOPROGRESS] = \false;
474
-            $conf[\CURLOPT_PROGRESSFUNCTION] = static function ($resource, int $downloadSize, int $downloaded, int $uploadSize, int $uploaded) use($progress) {
475
-                $progress($downloadSize, $downloaded, $uploadSize, $uploaded);
476
-            };
477
-        }
478
-        if (!empty($options['debug'])) {
479
-            $conf[\CURLOPT_STDERR] = Utils::debugResource($options['debug']);
480
-            $conf[\CURLOPT_VERBOSE] = \true;
481
-        }
482
-    }
483
-    /**
484
-     * This function ensures that a response was set on a transaction. If one
485
-     * was not set, then the request is retried if possible. This error
486
-     * typically means you are sending a payload, curl encountered a
487
-     * "Connection died, retrying a fresh connect" error, tried to rewind the
488
-     * stream, and then encountered a "necessary data rewind wasn't possible"
489
-     * error, causing the request to be sent through curl_multi_info_read()
490
-     * without an error status.
491
-     *
492
-     * @param callable(RequestInterface, array): PromiseInterface $handler
493
-     */
494
-    private static function retryFailedRewind(callable $handler, EasyHandle $easy, array $ctx) : PromiseInterface
495
-    {
496
-        try {
497
-            // Only rewind if the body has been read from.
498
-            $body = $easy->request->getBody();
499
-            if ($body->tell() > 0) {
500
-                $body->rewind();
501
-            }
502
-        } catch (\RuntimeException $e) {
503
-            $ctx['error'] = 'The connection unexpectedly failed without ' . 'providing an error. The request would have been retried, ' . 'but attempting to rewind the request body failed. ' . 'Exception: ' . $e;
504
-            return self::createRejection($easy, $ctx);
505
-        }
506
-        // Retry no more than 3 times before giving up.
507
-        if (!isset($easy->options['_curl_retries'])) {
508
-            $easy->options['_curl_retries'] = 1;
509
-        } elseif ($easy->options['_curl_retries'] == 2) {
510
-            $ctx['error'] = 'The cURL request was retried 3 times ' . 'and did not succeed. The most likely reason for the failure ' . 'is that cURL was unable to rewind the body of the request ' . 'and subsequent retries resulted in the same error. Turn on ' . 'the debug option to see what went wrong. See ' . 'https://bugs.php.net/bug.php?id=47204 for more information.';
511
-            return self::createRejection($easy, $ctx);
512
-        } else {
513
-            ++$easy->options['_curl_retries'];
514
-        }
515
-        return $handler($easy->request, $easy->options);
516
-    }
517
-    private function createHeaderFn(EasyHandle $easy) : callable
518
-    {
519
-        if (isset($easy->options['on_headers'])) {
520
-            $onHeaders = $easy->options['on_headers'];
521
-            if (!\is_callable($onHeaders)) {
522
-                throw new \InvalidArgumentException('on_headers must be callable');
523
-            }
524
-        } else {
525
-            $onHeaders = null;
526
-        }
527
-        return static function ($ch, $h) use($onHeaders, $easy, &$startingResponse) {
528
-            $value = \trim($h);
529
-            if ($value === '') {
530
-                $startingResponse = \true;
531
-                try {
532
-                    $easy->createResponse();
533
-                } catch (\Exception $e) {
534
-                    $easy->createResponseException = $e;
535
-                    return -1;
536
-                }
537
-                if ($onHeaders !== null) {
538
-                    try {
539
-                        $onHeaders($easy->response);
540
-                    } catch (\Exception $e) {
541
-                        // Associate the exception with the handle and trigger
542
-                        // a curl header write error by returning 0.
543
-                        $easy->onHeadersException = $e;
544
-                        return -1;
545
-                    }
546
-                }
547
-            } elseif ($startingResponse) {
548
-                $startingResponse = \false;
549
-                $easy->headers = [$value];
550
-            } else {
551
-                $easy->headers[] = $value;
552
-            }
553
-            return \strlen($h);
554
-        };
555
-    }
556
-    public function __destruct()
557
-    {
558
-        foreach ($this->handles as $id => $handle) {
559
-            \curl_close($handle);
560
-            unset($this->handles[$id]);
561
-        }
562
-    }
22
+	public const CURL_VERSION_STR = 'curl_version';
23
+	/**
24
+	 * @deprecated
25
+	 */
26
+	public const LOW_CURL_VERSION_NUMBER = '7.21.2';
27
+	/**
28
+	 * @var resource[]|\CurlHandle[]
29
+	 */
30
+	private $handles = [];
31
+	/**
32
+	 * @var int Total number of idle handles to keep in cache
33
+	 */
34
+	private $maxHandles;
35
+	/**
36
+	 * @param int $maxHandles Maximum number of idle handles.
37
+	 */
38
+	public function __construct(int $maxHandles)
39
+	{
40
+		$this->maxHandles = $maxHandles;
41
+	}
42
+	public function create(RequestInterface $request, array $options) : EasyHandle
43
+	{
44
+		$protocolVersion = $request->getProtocolVersion();
45
+		if ('2' === $protocolVersion || '2.0' === $protocolVersion) {
46
+			if (!self::supportsHttp2()) {
47
+				throw new ConnectException('HTTP/2 is supported by the cURL handler, however libcurl is built without HTTP/2 support.', $request);
48
+			}
49
+		} elseif ('1.0' !== $protocolVersion && '1.1' !== $protocolVersion) {
50
+			throw new ConnectException(\sprintf('HTTP/%s is not supported by the cURL handler.', $protocolVersion), $request);
51
+		}
52
+		if (isset($options['curl']['body_as_string'])) {
53
+			$options['_body_as_string'] = $options['curl']['body_as_string'];
54
+			unset($options['curl']['body_as_string']);
55
+		}
56
+		$easy = new EasyHandle();
57
+		$easy->request = $request;
58
+		$easy->options = $options;
59
+		$conf = $this->getDefaultConf($easy);
60
+		$this->applyMethod($easy, $conf);
61
+		$this->applyHandlerOptions($easy, $conf);
62
+		$this->applyHeaders($easy, $conf);
63
+		unset($conf['_headers']);
64
+		// Add handler options from the request configuration options
65
+		if (isset($options['curl'])) {
66
+			$conf = \array_replace($conf, $options['curl']);
67
+		}
68
+		$conf[\CURLOPT_HEADERFUNCTION] = $this->createHeaderFn($easy);
69
+		$easy->handle = $this->handles ? \array_pop($this->handles) : \curl_init();
70
+		\curl_setopt_array($easy->handle, $conf);
71
+		return $easy;
72
+	}
73
+	private static function supportsHttp2() : bool
74
+	{
75
+		static $supportsHttp2 = null;
76
+		if (null === $supportsHttp2) {
77
+			$supportsHttp2 = self::supportsTls12() && \defined('CURL_VERSION_HTTP2') && \CURL_VERSION_HTTP2 & \curl_version()['features'];
78
+		}
79
+		return $supportsHttp2;
80
+	}
81
+	private static function supportsTls12() : bool
82
+	{
83
+		static $supportsTls12 = null;
84
+		if (null === $supportsTls12) {
85
+			$supportsTls12 = \CURL_SSLVERSION_TLSv1_2 & \curl_version()['features'];
86
+		}
87
+		return $supportsTls12;
88
+	}
89
+	private static function supportsTls13() : bool
90
+	{
91
+		static $supportsTls13 = null;
92
+		if (null === $supportsTls13) {
93
+			$supportsTls13 = \defined('CURL_SSLVERSION_TLSv1_3') && \CURL_SSLVERSION_TLSv1_3 & \curl_version()['features'];
94
+		}
95
+		return $supportsTls13;
96
+	}
97
+	public function release(EasyHandle $easy) : void
98
+	{
99
+		$resource = $easy->handle;
100
+		unset($easy->handle);
101
+		if (\count($this->handles) >= $this->maxHandles) {
102
+			\curl_close($resource);
103
+		} else {
104
+			// Remove all callback functions as they can hold onto references
105
+			// and are not cleaned up by curl_reset. Using curl_setopt_array
106
+			// does not work for some reason, so removing each one
107
+			// individually.
108
+			\curl_setopt($resource, \CURLOPT_HEADERFUNCTION, null);
109
+			\curl_setopt($resource, \CURLOPT_READFUNCTION, null);
110
+			\curl_setopt($resource, \CURLOPT_WRITEFUNCTION, null);
111
+			\curl_setopt($resource, \CURLOPT_PROGRESSFUNCTION, null);
112
+			\curl_reset($resource);
113
+			$this->handles[] = $resource;
114
+		}
115
+	}
116
+	/**
117
+	 * Completes a cURL transaction, either returning a response promise or a
118
+	 * rejected promise.
119
+	 *
120
+	 * @param callable(RequestInterface, array): PromiseInterface $handler
121
+	 * @param CurlFactoryInterface                                $factory Dictates how the handle is released
122
+	 */
123
+	public static function finish(callable $handler, EasyHandle $easy, CurlFactoryInterface $factory) : PromiseInterface
124
+	{
125
+		if (isset($easy->options['on_stats'])) {
126
+			self::invokeStats($easy);
127
+		}
128
+		if (!$easy->response || $easy->errno) {
129
+			return self::finishError($handler, $easy, $factory);
130
+		}
131
+		// Return the response if it is present and there is no error.
132
+		$factory->release($easy);
133
+		// Rewind the body of the response if possible.
134
+		$body = $easy->response->getBody();
135
+		if ($body->isSeekable()) {
136
+			$body->rewind();
137
+		}
138
+		return new FulfilledPromise($easy->response);
139
+	}
140
+	private static function invokeStats(EasyHandle $easy) : void
141
+	{
142
+		$curlStats = \curl_getinfo($easy->handle);
143
+		$curlStats['appconnect_time'] = \curl_getinfo($easy->handle, \CURLINFO_APPCONNECT_TIME);
144
+		$stats = new TransferStats($easy->request, $easy->response, $curlStats['total_time'], $easy->errno, $curlStats);
145
+		$easy->options['on_stats']($stats);
146
+	}
147
+	/**
148
+	 * @param callable(RequestInterface, array): PromiseInterface $handler
149
+	 */
150
+	private static function finishError(callable $handler, EasyHandle $easy, CurlFactoryInterface $factory) : PromiseInterface
151
+	{
152
+		// Get error information and release the handle to the factory.
153
+		$ctx = ['errno' => $easy->errno, 'error' => \curl_error($easy->handle), 'appconnect_time' => \curl_getinfo($easy->handle, \CURLINFO_APPCONNECT_TIME)] + \curl_getinfo($easy->handle);
154
+		$ctx[self::CURL_VERSION_STR] = self::getCurlVersion();
155
+		$factory->release($easy);
156
+		// Retry when nothing is present or when curl failed to rewind.
157
+		if (empty($easy->options['_err_message']) && (!$easy->errno || $easy->errno == 65)) {
158
+			return self::retryFailedRewind($handler, $easy, $ctx);
159
+		}
160
+		return self::createRejection($easy, $ctx);
161
+	}
162
+	private static function getCurlVersion() : string
163
+	{
164
+		static $curlVersion = null;
165
+		if (null === $curlVersion) {
166
+			$curlVersion = \curl_version()['version'];
167
+		}
168
+		return $curlVersion;
169
+	}
170
+	private static function createRejection(EasyHandle $easy, array $ctx) : PromiseInterface
171
+	{
172
+		static $connectionErrors = [\CURLE_OPERATION_TIMEOUTED => \true, \CURLE_COULDNT_RESOLVE_HOST => \true, \CURLE_COULDNT_CONNECT => \true, \CURLE_SSL_CONNECT_ERROR => \true, \CURLE_GOT_NOTHING => \true];
173
+		if ($easy->createResponseException) {
174
+			return P\Create::rejectionFor(new RequestException('An error was encountered while creating the response', $easy->request, $easy->response, $easy->createResponseException, $ctx));
175
+		}
176
+		// If an exception was encountered during the onHeaders event, then
177
+		// return a rejected promise that wraps that exception.
178
+		if ($easy->onHeadersException) {
179
+			return P\Create::rejectionFor(new RequestException('An error was encountered during the on_headers event', $easy->request, $easy->response, $easy->onHeadersException, $ctx));
180
+		}
181
+		$uri = $easy->request->getUri();
182
+		$sanitizedError = self::sanitizeCurlError($ctx['error'] ?? '', $uri);
183
+		$message = \sprintf('cURL error %s: %s (%s)', $ctx['errno'], $sanitizedError, 'see https://curl.haxx.se/libcurl/c/libcurl-errors.html');
184
+		if ('' !== $sanitizedError) {
185
+			$redactedUriString = \OCA\FullTextSearch_Elasticsearch\Vendor\GuzzleHttp\Psr7\Utils::redactUserInfo($uri)->__toString();
186
+			if ($redactedUriString !== '' && \false === \strpos($sanitizedError, $redactedUriString)) {
187
+				$message .= \sprintf(' for %s', $redactedUriString);
188
+			}
189
+		}
190
+		// Create a connection exception if it was a specific error code.
191
+		$error = isset($connectionErrors[$easy->errno]) ? new ConnectException($message, $easy->request, null, $ctx) : new RequestException($message, $easy->request, $easy->response, null, $ctx);
192
+		return P\Create::rejectionFor($error);
193
+	}
194
+	private static function sanitizeCurlError(string $error, UriInterface $uri) : string
195
+	{
196
+		if ('' === $error) {
197
+			return $error;
198
+		}
199
+		$baseUri = $uri->withQuery('')->withFragment('');
200
+		$baseUriString = $baseUri->__toString();
201
+		if ('' === $baseUriString) {
202
+			return $error;
203
+		}
204
+		$redactedUriString = \OCA\FullTextSearch_Elasticsearch\Vendor\GuzzleHttp\Psr7\Utils::redactUserInfo($baseUri)->__toString();
205
+		return \str_replace($baseUriString, $redactedUriString, $error);
206
+	}
207
+	/**
208
+	 * @return array<int|string, mixed>
209
+	 */
210
+	private function getDefaultConf(EasyHandle $easy) : array
211
+	{
212
+		$conf = ['_headers' => $easy->request->getHeaders(), \CURLOPT_CUSTOMREQUEST => $easy->request->getMethod(), \CURLOPT_URL => (string) $easy->request->getUri()->withFragment(''), \CURLOPT_RETURNTRANSFER => \false, \CURLOPT_HEADER => \false, \CURLOPT_CONNECTTIMEOUT => 300];
213
+		if (\defined('CURLOPT_PROTOCOLS')) {
214
+			$conf[\CURLOPT_PROTOCOLS] = \CURLPROTO_HTTP | \CURLPROTO_HTTPS;
215
+		}
216
+		$version = $easy->request->getProtocolVersion();
217
+		if ('2' === $version || '2.0' === $version) {
218
+			$conf[\CURLOPT_HTTP_VERSION] = \CURL_HTTP_VERSION_2_0;
219
+		} elseif ('1.1' === $version) {
220
+			$conf[\CURLOPT_HTTP_VERSION] = \CURL_HTTP_VERSION_1_1;
221
+		} else {
222
+			$conf[\CURLOPT_HTTP_VERSION] = \CURL_HTTP_VERSION_1_0;
223
+		}
224
+		return $conf;
225
+	}
226
+	private function applyMethod(EasyHandle $easy, array &$conf) : void
227
+	{
228
+		$body = $easy->request->getBody();
229
+		$size = $body->getSize();
230
+		if ($size === null || $size > 0) {
231
+			$this->applyBody($easy->request, $easy->options, $conf);
232
+			return;
233
+		}
234
+		$method = $easy->request->getMethod();
235
+		if ($method === 'PUT' || $method === 'POST') {
236
+			// See https://datatracker.ietf.org/doc/html/rfc7230#section-3.3.2
237
+			if (!$easy->request->hasHeader('Content-Length')) {
238
+				$conf[\CURLOPT_HTTPHEADER][] = 'Content-Length: 0';
239
+			}
240
+		} elseif ($method === 'HEAD') {
241
+			$conf[\CURLOPT_NOBODY] = \true;
242
+			unset($conf[\CURLOPT_WRITEFUNCTION], $conf[\CURLOPT_READFUNCTION], $conf[\CURLOPT_FILE], $conf[\CURLOPT_INFILE]);
243
+		}
244
+	}
245
+	private function applyBody(RequestInterface $request, array $options, array &$conf) : void
246
+	{
247
+		$size = $request->hasHeader('Content-Length') ? (int) $request->getHeaderLine('Content-Length') : null;
248
+		// Send the body as a string if the size is less than 1MB OR if the
249
+		// [curl][body_as_string] request value is set.
250
+		if ($size !== null && $size < 1000000 || !empty($options['_body_as_string'])) {
251
+			$conf[\CURLOPT_POSTFIELDS] = (string) $request->getBody();
252
+			// Don't duplicate the Content-Length header
253
+			$this->removeHeader('Content-Length', $conf);
254
+			$this->removeHeader('Transfer-Encoding', $conf);
255
+		} else {
256
+			$conf[\CURLOPT_UPLOAD] = \true;
257
+			if ($size !== null) {
258
+				$conf[\CURLOPT_INFILESIZE] = $size;
259
+				$this->removeHeader('Content-Length', $conf);
260
+			}
261
+			$body = $request->getBody();
262
+			if ($body->isSeekable()) {
263
+				$body->rewind();
264
+			}
265
+			$conf[\CURLOPT_READFUNCTION] = static function ($ch, $fd, $length) use($body) {
266
+				return $body->read($length);
267
+			};
268
+		}
269
+		// If the Expect header is not present, prevent curl from adding it
270
+		if (!$request->hasHeader('Expect')) {
271
+			$conf[\CURLOPT_HTTPHEADER][] = 'Expect:';
272
+		}
273
+		// cURL sometimes adds a content-type by default. Prevent this.
274
+		if (!$request->hasHeader('Content-Type')) {
275
+			$conf[\CURLOPT_HTTPHEADER][] = 'Content-Type:';
276
+		}
277
+	}
278
+	private function applyHeaders(EasyHandle $easy, array &$conf) : void
279
+	{
280
+		foreach ($conf['_headers'] as $name => $values) {
281
+			foreach ($values as $value) {
282
+				$value = (string) $value;
283
+				if ($value === '') {
284
+					// cURL requires a special format for empty headers.
285
+					// See https://github.com/guzzle/guzzle/issues/1882 for more details.
286
+					$conf[\CURLOPT_HTTPHEADER][] = "{$name};";
287
+				} else {
288
+					$conf[\CURLOPT_HTTPHEADER][] = "{$name}: {$value}";
289
+				}
290
+			}
291
+		}
292
+		// Remove the Accept header if one was not set
293
+		if (!$easy->request->hasHeader('Accept')) {
294
+			$conf[\CURLOPT_HTTPHEADER][] = 'Accept:';
295
+		}
296
+	}
297
+	/**
298
+	 * Remove a header from the options array.
299
+	 *
300
+	 * @param string $name    Case-insensitive header to remove
301
+	 * @param array  $options Array of options to modify
302
+	 */
303
+	private function removeHeader(string $name, array &$options) : void
304
+	{
305
+		foreach (\array_keys($options['_headers']) as $key) {
306
+			if (!\strcasecmp($key, $name)) {
307
+				unset($options['_headers'][$key]);
308
+				return;
309
+			}
310
+		}
311
+	}
312
+	private function applyHandlerOptions(EasyHandle $easy, array &$conf) : void
313
+	{
314
+		$options = $easy->options;
315
+		if (isset($options['verify'])) {
316
+			if ($options['verify'] === \false) {
317
+				unset($conf[\CURLOPT_CAINFO]);
318
+				$conf[\CURLOPT_SSL_VERIFYHOST] = 0;
319
+				$conf[\CURLOPT_SSL_VERIFYPEER] = \false;
320
+			} else {
321
+				$conf[\CURLOPT_SSL_VERIFYHOST] = 2;
322
+				$conf[\CURLOPT_SSL_VERIFYPEER] = \true;
323
+				if (\is_string($options['verify'])) {
324
+					// Throw an error if the file/folder/link path is not valid or doesn't exist.
325
+					if (!\file_exists($options['verify'])) {
326
+						throw new \InvalidArgumentException("SSL CA bundle not found: {$options['verify']}");
327
+					}
328
+					// If it's a directory or a link to a directory use CURLOPT_CAPATH.
329
+					// If not, it's probably a file, or a link to a file, so use CURLOPT_CAINFO.
330
+					if (\is_dir($options['verify']) || \is_link($options['verify']) === \true && ($verifyLink = \readlink($options['verify'])) !== \false && \is_dir($verifyLink)) {
331
+						$conf[\CURLOPT_CAPATH] = $options['verify'];
332
+					} else {
333
+						$conf[\CURLOPT_CAINFO] = $options['verify'];
334
+					}
335
+				}
336
+			}
337
+		}
338
+		if (!isset($options['curl'][\CURLOPT_ENCODING]) && !empty($options['decode_content'])) {
339
+			$accept = $easy->request->getHeaderLine('Accept-Encoding');
340
+			if ($accept) {
341
+				$conf[\CURLOPT_ENCODING] = $accept;
342
+			} else {
343
+				// The empty string enables all available decoders and implicitly
344
+				// sets a matching 'Accept-Encoding' header.
345
+				$conf[\CURLOPT_ENCODING] = '';
346
+				// But as the user did not specify any encoding preference,
347
+				// let's leave it up to server by preventing curl from sending
348
+				// the header, which will be interpreted as 'Accept-Encoding: *'.
349
+				// https://www.rfc-editor.org/rfc/rfc9110#field.accept-encoding
350
+				$conf[\CURLOPT_HTTPHEADER][] = 'Accept-Encoding:';
351
+			}
352
+		}
353
+		if (!isset($options['sink'])) {
354
+			// Use a default temp stream if no sink was set.
355
+			$options['sink'] = \OCA\FullTextSearch_Elasticsearch\Vendor\GuzzleHttp\Psr7\Utils::tryFopen('php://temp', 'w+');
356
+		}
357
+		$sink = $options['sink'];
358
+		if (!\is_string($sink)) {
359
+			$sink = \OCA\FullTextSearch_Elasticsearch\Vendor\GuzzleHttp\Psr7\Utils::streamFor($sink);
360
+		} elseif (!\is_dir(\dirname($sink))) {
361
+			// Ensure that the directory exists before failing in curl.
362
+			throw new \RuntimeException(\sprintf('Directory %s does not exist for sink value of %s', \dirname($sink), $sink));
363
+		} else {
364
+			$sink = new LazyOpenStream($sink, 'w+');
365
+		}
366
+		$easy->sink = $sink;
367
+		$conf[\CURLOPT_WRITEFUNCTION] = static function ($ch, $write) use($sink) : int {
368
+			return $sink->write($write);
369
+		};
370
+		$timeoutRequiresNoSignal = \false;
371
+		if (isset($options['timeout'])) {
372
+			$timeoutRequiresNoSignal |= $options['timeout'] < 1;
373
+			$conf[\CURLOPT_TIMEOUT_MS] = $options['timeout'] * 1000;
374
+		}
375
+		// CURL default value is CURL_IPRESOLVE_WHATEVER
376
+		if (isset($options['force_ip_resolve'])) {
377
+			if ('v4' === $options['force_ip_resolve']) {
378
+				$conf[\CURLOPT_IPRESOLVE] = \CURL_IPRESOLVE_V4;
379
+			} elseif ('v6' === $options['force_ip_resolve']) {
380
+				$conf[\CURLOPT_IPRESOLVE] = \CURL_IPRESOLVE_V6;
381
+			}
382
+		}
383
+		if (isset($options['connect_timeout'])) {
384
+			$timeoutRequiresNoSignal |= $options['connect_timeout'] < 1;
385
+			$conf[\CURLOPT_CONNECTTIMEOUT_MS] = $options['connect_timeout'] * 1000;
386
+		}
387
+		if ($timeoutRequiresNoSignal && \strtoupper(\substr(\PHP_OS, 0, 3)) !== 'WIN') {
388
+			$conf[\CURLOPT_NOSIGNAL] = \true;
389
+		}
390
+		if (isset($options['proxy'])) {
391
+			if (!\is_array($options['proxy'])) {
392
+				$conf[\CURLOPT_PROXY] = $options['proxy'];
393
+			} else {
394
+				$scheme = $easy->request->getUri()->getScheme();
395
+				if (isset($options['proxy'][$scheme])) {
396
+					$host = $easy->request->getUri()->getHost();
397
+					if (isset($options['proxy']['no']) && Utils::isHostInNoProxy($host, $options['proxy']['no'])) {
398
+						unset($conf[\CURLOPT_PROXY]);
399
+					} else {
400
+						$conf[\CURLOPT_PROXY] = $options['proxy'][$scheme];
401
+					}
402
+				}
403
+			}
404
+		}
405
+		if (isset($options['crypto_method'])) {
406
+			$protocolVersion = $easy->request->getProtocolVersion();
407
+			// If HTTP/2, upgrade TLS 1.0 and 1.1 to 1.2
408
+			if ('2' === $protocolVersion || '2.0' === $protocolVersion) {
409
+				if (\STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT === $options['crypto_method'] || \STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT === $options['crypto_method'] || \STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT === $options['crypto_method']) {
410
+					$conf[\CURLOPT_SSLVERSION] = \CURL_SSLVERSION_TLSv1_2;
411
+				} elseif (\defined('STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT') && \STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT === $options['crypto_method']) {
412
+					if (!self::supportsTls13()) {
413
+						throw new \InvalidArgumentException('Invalid crypto_method request option: TLS 1.3 not supported by your version of cURL');
414
+					}
415
+					$conf[\CURLOPT_SSLVERSION] = \CURL_SSLVERSION_TLSv1_3;
416
+				} else {
417
+					throw new \InvalidArgumentException('Invalid crypto_method request option: unknown version provided');
418
+				}
419
+			} elseif (\STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT === $options['crypto_method']) {
420
+				$conf[\CURLOPT_SSLVERSION] = \CURL_SSLVERSION_TLSv1_0;
421
+			} elseif (\STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT === $options['crypto_method']) {
422
+				$conf[\CURLOPT_SSLVERSION] = \CURL_SSLVERSION_TLSv1_1;
423
+			} elseif (\STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT === $options['crypto_method']) {
424
+				if (!self::supportsTls12()) {
425
+					throw new \InvalidArgumentException('Invalid crypto_method request option: TLS 1.2 not supported by your version of cURL');
426
+				}
427
+				$conf[\CURLOPT_SSLVERSION] = \CURL_SSLVERSION_TLSv1_2;
428
+			} elseif (\defined('STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT') && \STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT === $options['crypto_method']) {
429
+				if (!self::supportsTls13()) {
430
+					throw new \InvalidArgumentException('Invalid crypto_method request option: TLS 1.3 not supported by your version of cURL');
431
+				}
432
+				$conf[\CURLOPT_SSLVERSION] = \CURL_SSLVERSION_TLSv1_3;
433
+			} else {
434
+				throw new \InvalidArgumentException('Invalid crypto_method request option: unknown version provided');
435
+			}
436
+		}
437
+		if (isset($options['cert'])) {
438
+			$cert = $options['cert'];
439
+			if (\is_array($cert)) {
440
+				$conf[\CURLOPT_SSLCERTPASSWD] = $cert[1];
441
+				$cert = $cert[0];
442
+			}
443
+			if (!\file_exists($cert)) {
444
+				throw new \InvalidArgumentException("SSL certificate not found: {$cert}");
445
+			}
446
+			// OpenSSL (versions 0.9.3 and later) also support "P12" for PKCS#12-encoded files.
447
+			// see https://curl.se/libcurl/c/CURLOPT_SSLCERTTYPE.html
448
+			$ext = \pathinfo($cert, \PATHINFO_EXTENSION);
449
+			if (\preg_match('#^(der|p12)$#i', $ext)) {
450
+				$conf[\CURLOPT_SSLCERTTYPE] = \strtoupper($ext);
451
+			}
452
+			$conf[\CURLOPT_SSLCERT] = $cert;
453
+		}
454
+		if (isset($options['ssl_key'])) {
455
+			if (\is_array($options['ssl_key'])) {
456
+				if (\count($options['ssl_key']) === 2) {
457
+					[$sslKey, $conf[\CURLOPT_SSLKEYPASSWD]] = $options['ssl_key'];
458
+				} else {
459
+					[$sslKey] = $options['ssl_key'];
460
+				}
461
+			}
462
+			$sslKey = $sslKey ?? $options['ssl_key'];
463
+			if (!\file_exists($sslKey)) {
464
+				throw new \InvalidArgumentException("SSL private key not found: {$sslKey}");
465
+			}
466
+			$conf[\CURLOPT_SSLKEY] = $sslKey;
467
+		}
468
+		if (isset($options['progress'])) {
469
+			$progress = $options['progress'];
470
+			if (!\is_callable($progress)) {
471
+				throw new \InvalidArgumentException('progress client option must be callable');
472
+			}
473
+			$conf[\CURLOPT_NOPROGRESS] = \false;
474
+			$conf[\CURLOPT_PROGRESSFUNCTION] = static function ($resource, int $downloadSize, int $downloaded, int $uploadSize, int $uploaded) use($progress) {
475
+				$progress($downloadSize, $downloaded, $uploadSize, $uploaded);
476
+			};
477
+		}
478
+		if (!empty($options['debug'])) {
479
+			$conf[\CURLOPT_STDERR] = Utils::debugResource($options['debug']);
480
+			$conf[\CURLOPT_VERBOSE] = \true;
481
+		}
482
+	}
483
+	/**
484
+	 * This function ensures that a response was set on a transaction. If one
485
+	 * was not set, then the request is retried if possible. This error
486
+	 * typically means you are sending a payload, curl encountered a
487
+	 * "Connection died, retrying a fresh connect" error, tried to rewind the
488
+	 * stream, and then encountered a "necessary data rewind wasn't possible"
489
+	 * error, causing the request to be sent through curl_multi_info_read()
490
+	 * without an error status.
491
+	 *
492
+	 * @param callable(RequestInterface, array): PromiseInterface $handler
493
+	 */
494
+	private static function retryFailedRewind(callable $handler, EasyHandle $easy, array $ctx) : PromiseInterface
495
+	{
496
+		try {
497
+			// Only rewind if the body has been read from.
498
+			$body = $easy->request->getBody();
499
+			if ($body->tell() > 0) {
500
+				$body->rewind();
501
+			}
502
+		} catch (\RuntimeException $e) {
503
+			$ctx['error'] = 'The connection unexpectedly failed without ' . 'providing an error. The request would have been retried, ' . 'but attempting to rewind the request body failed. ' . 'Exception: ' . $e;
504
+			return self::createRejection($easy, $ctx);
505
+		}
506
+		// Retry no more than 3 times before giving up.
507
+		if (!isset($easy->options['_curl_retries'])) {
508
+			$easy->options['_curl_retries'] = 1;
509
+		} elseif ($easy->options['_curl_retries'] == 2) {
510
+			$ctx['error'] = 'The cURL request was retried 3 times ' . 'and did not succeed. The most likely reason for the failure ' . 'is that cURL was unable to rewind the body of the request ' . 'and subsequent retries resulted in the same error. Turn on ' . 'the debug option to see what went wrong. See ' . 'https://bugs.php.net/bug.php?id=47204 for more information.';
511
+			return self::createRejection($easy, $ctx);
512
+		} else {
513
+			++$easy->options['_curl_retries'];
514
+		}
515
+		return $handler($easy->request, $easy->options);
516
+	}
517
+	private function createHeaderFn(EasyHandle $easy) : callable
518
+	{
519
+		if (isset($easy->options['on_headers'])) {
520
+			$onHeaders = $easy->options['on_headers'];
521
+			if (!\is_callable($onHeaders)) {
522
+				throw new \InvalidArgumentException('on_headers must be callable');
523
+			}
524
+		} else {
525
+			$onHeaders = null;
526
+		}
527
+		return static function ($ch, $h) use($onHeaders, $easy, &$startingResponse) {
528
+			$value = \trim($h);
529
+			if ($value === '') {
530
+				$startingResponse = \true;
531
+				try {
532
+					$easy->createResponse();
533
+				} catch (\Exception $e) {
534
+					$easy->createResponseException = $e;
535
+					return -1;
536
+				}
537
+				if ($onHeaders !== null) {
538
+					try {
539
+						$onHeaders($easy->response);
540
+					} catch (\Exception $e) {
541
+						// Associate the exception with the handle and trigger
542
+						// a curl header write error by returning 0.
543
+						$easy->onHeadersException = $e;
544
+						return -1;
545
+					}
546
+				}
547
+			} elseif ($startingResponse) {
548
+				$startingResponse = \false;
549
+				$easy->headers = [$value];
550
+			} else {
551
+				$easy->headers[] = $value;
552
+			}
553
+			return \strlen($h);
554
+		};
555
+	}
556
+	public function __destruct()
557
+	{
558
+		foreach ($this->handles as $id => $handle) {
559
+			\curl_close($handle);
560
+			unset($this->handles[$id]);
561
+		}
562
+	}
563 563
 }
Please login to merge, or discard this patch.
Spacing   +10 added lines, -10 removed lines patch added patch discarded remove patch
@@ -209,7 +209,7 @@  discard block
 block discarded – undo
209 209
      */
210 210
     private function getDefaultConf(EasyHandle $easy) : array
211 211
     {
212
-        $conf = ['_headers' => $easy->request->getHeaders(), \CURLOPT_CUSTOMREQUEST => $easy->request->getMethod(), \CURLOPT_URL => (string) $easy->request->getUri()->withFragment(''), \CURLOPT_RETURNTRANSFER => \false, \CURLOPT_HEADER => \false, \CURLOPT_CONNECTTIMEOUT => 300];
212
+        $conf = ['_headers' => $easy->request->getHeaders(), \CURLOPT_CUSTOMREQUEST => $easy->request->getMethod(), \CURLOPT_URL => (string)$easy->request->getUri()->withFragment(''), \CURLOPT_RETURNTRANSFER => \false, \CURLOPT_HEADER => \false, \CURLOPT_CONNECTTIMEOUT => 300];
213 213
         if (\defined('CURLOPT_PROTOCOLS')) {
214 214
             $conf[\CURLOPT_PROTOCOLS] = \CURLPROTO_HTTP | \CURLPROTO_HTTPS;
215 215
         }
@@ -244,11 +244,11 @@  discard block
 block discarded – undo
244 244
     }
245 245
     private function applyBody(RequestInterface $request, array $options, array &$conf) : void
246 246
     {
247
-        $size = $request->hasHeader('Content-Length') ? (int) $request->getHeaderLine('Content-Length') : null;
247
+        $size = $request->hasHeader('Content-Length') ? (int)$request->getHeaderLine('Content-Length') : null;
248 248
         // Send the body as a string if the size is less than 1MB OR if the
249 249
         // [curl][body_as_string] request value is set.
250 250
         if ($size !== null && $size < 1000000 || !empty($options['_body_as_string'])) {
251
-            $conf[\CURLOPT_POSTFIELDS] = (string) $request->getBody();
251
+            $conf[\CURLOPT_POSTFIELDS] = (string)$request->getBody();
252 252
             // Don't duplicate the Content-Length header
253 253
             $this->removeHeader('Content-Length', $conf);
254 254
             $this->removeHeader('Transfer-Encoding', $conf);
@@ -262,7 +262,7 @@  discard block
 block discarded – undo
262 262
             if ($body->isSeekable()) {
263 263
                 $body->rewind();
264 264
             }
265
-            $conf[\CURLOPT_READFUNCTION] = static function ($ch, $fd, $length) use($body) {
265
+            $conf[\CURLOPT_READFUNCTION] = static function($ch, $fd, $length) use($body) {
266 266
                 return $body->read($length);
267 267
             };
268 268
         }
@@ -279,7 +279,7 @@  discard block
 block discarded – undo
279 279
     {
280 280
         foreach ($conf['_headers'] as $name => $values) {
281 281
             foreach ($values as $value) {
282
-                $value = (string) $value;
282
+                $value = (string)$value;
283 283
                 if ($value === '') {
284 284
                     // cURL requires a special format for empty headers.
285 285
                     // See https://github.com/guzzle/guzzle/issues/1882 for more details.
@@ -364,7 +364,7 @@  discard block
 block discarded – undo
364 364
             $sink = new LazyOpenStream($sink, 'w+');
365 365
         }
366 366
         $easy->sink = $sink;
367
-        $conf[\CURLOPT_WRITEFUNCTION] = static function ($ch, $write) use($sink) : int {
367
+        $conf[\CURLOPT_WRITEFUNCTION] = static function($ch, $write) use($sink) : int {
368 368
             return $sink->write($write);
369 369
         };
370 370
         $timeoutRequiresNoSignal = \false;
@@ -471,7 +471,7 @@  discard block
 block discarded – undo
471 471
                 throw new \InvalidArgumentException('progress client option must be callable');
472 472
             }
473 473
             $conf[\CURLOPT_NOPROGRESS] = \false;
474
-            $conf[\CURLOPT_PROGRESSFUNCTION] = static function ($resource, int $downloadSize, int $downloaded, int $uploadSize, int $uploaded) use($progress) {
474
+            $conf[\CURLOPT_PROGRESSFUNCTION] = static function($resource, int $downloadSize, int $downloaded, int $uploadSize, int $uploaded) use($progress) {
475 475
                 $progress($downloadSize, $downloaded, $uploadSize, $uploaded);
476 476
             };
477 477
         }
@@ -500,14 +500,14 @@  discard block
 block discarded – undo
500 500
                 $body->rewind();
501 501
             }
502 502
         } catch (\RuntimeException $e) {
503
-            $ctx['error'] = 'The connection unexpectedly failed without ' . 'providing an error. The request would have been retried, ' . 'but attempting to rewind the request body failed. ' . 'Exception: ' . $e;
503
+            $ctx['error'] = 'The connection unexpectedly failed without '.'providing an error. The request would have been retried, '.'but attempting to rewind the request body failed. '.'Exception: '.$e;
504 504
             return self::createRejection($easy, $ctx);
505 505
         }
506 506
         // Retry no more than 3 times before giving up.
507 507
         if (!isset($easy->options['_curl_retries'])) {
508 508
             $easy->options['_curl_retries'] = 1;
509 509
         } elseif ($easy->options['_curl_retries'] == 2) {
510
-            $ctx['error'] = 'The cURL request was retried 3 times ' . 'and did not succeed. The most likely reason for the failure ' . 'is that cURL was unable to rewind the body of the request ' . 'and subsequent retries resulted in the same error. Turn on ' . 'the debug option to see what went wrong. See ' . 'https://bugs.php.net/bug.php?id=47204 for more information.';
510
+            $ctx['error'] = 'The cURL request was retried 3 times '.'and did not succeed. The most likely reason for the failure '.'is that cURL was unable to rewind the body of the request '.'and subsequent retries resulted in the same error. Turn on '.'the debug option to see what went wrong. See '.'https://bugs.php.net/bug.php?id=47204 for more information.';
511 511
             return self::createRejection($easy, $ctx);
512 512
         } else {
513 513
             ++$easy->options['_curl_retries'];
@@ -524,7 +524,7 @@  discard block
 block discarded – undo
524 524
         } else {
525 525
             $onHeaders = null;
526 526
         }
527
-        return static function ($ch, $h) use($onHeaders, $easy, &$startingResponse) {
527
+        return static function($ch, $h) use($onHeaders, $easy, &$startingResponse) {
528 528
             $value = \trim($h);
529 529
             if ($value === '') {
530 530
                 $startingResponse = \true;
Please login to merge, or discard this patch.
lib/Vendor/GuzzleHttp/Promise/Coroutine.php 1 patch
Indentation   +97 added lines, -97 removed lines patch added patch discarded remove patch
@@ -43,101 +43,101 @@
 block discarded – undo
43 43
  */
44 44
 final class Coroutine implements PromiseInterface
45 45
 {
46
-    /**
47
-     * @var PromiseInterface|null
48
-     */
49
-    private $currentPromise;
50
-    /**
51
-     * @var Generator
52
-     */
53
-    private $generator;
54
-    /**
55
-     * @var Promise
56
-     */
57
-    private $result;
58
-    public function __construct(callable $generatorFn)
59
-    {
60
-        $this->generator = $generatorFn();
61
-        $this->result = new Promise(function () : void {
62
-            while (isset($this->currentPromise)) {
63
-                $this->currentPromise->wait();
64
-            }
65
-        });
66
-        try {
67
-            $this->nextCoroutine($this->generator->current());
68
-        } catch (Throwable $throwable) {
69
-            $this->result->reject($throwable);
70
-        }
71
-    }
72
-    /**
73
-     * Create a new coroutine.
74
-     */
75
-    public static function of(callable $generatorFn) : self
76
-    {
77
-        return new self($generatorFn);
78
-    }
79
-    public function then(?callable $onFulfilled = null, ?callable $onRejected = null) : PromiseInterface
80
-    {
81
-        return $this->result->then($onFulfilled, $onRejected);
82
-    }
83
-    public function otherwise(callable $onRejected) : PromiseInterface
84
-    {
85
-        return $this->result->otherwise($onRejected);
86
-    }
87
-    public function wait(bool $unwrap = \true)
88
-    {
89
-        return $this->result->wait($unwrap);
90
-    }
91
-    public function getState() : string
92
-    {
93
-        return $this->result->getState();
94
-    }
95
-    public function resolve($value) : void
96
-    {
97
-        $this->result->resolve($value);
98
-    }
99
-    public function reject($reason) : void
100
-    {
101
-        $this->result->reject($reason);
102
-    }
103
-    public function cancel() : void
104
-    {
105
-        $this->currentPromise->cancel();
106
-        $this->result->cancel();
107
-    }
108
-    private function nextCoroutine($yielded) : void
109
-    {
110
-        $this->currentPromise = Create::promiseFor($yielded)->then([$this, '_handleSuccess'], [$this, '_handleFailure']);
111
-    }
112
-    /**
113
-     * @internal
114
-     */
115
-    public function _handleSuccess($value) : void
116
-    {
117
-        unset($this->currentPromise);
118
-        try {
119
-            $next = $this->generator->send($value);
120
-            if ($this->generator->valid()) {
121
-                $this->nextCoroutine($next);
122
-            } else {
123
-                $this->result->resolve($value);
124
-            }
125
-        } catch (Throwable $throwable) {
126
-            $this->result->reject($throwable);
127
-        }
128
-    }
129
-    /**
130
-     * @internal
131
-     */
132
-    public function _handleFailure($reason) : void
133
-    {
134
-        unset($this->currentPromise);
135
-        try {
136
-            $nextYield = $this->generator->throw(Create::exceptionFor($reason));
137
-            // The throw was caught, so keep iterating on the coroutine
138
-            $this->nextCoroutine($nextYield);
139
-        } catch (Throwable $throwable) {
140
-            $this->result->reject($throwable);
141
-        }
142
-    }
46
+	/**
47
+	 * @var PromiseInterface|null
48
+	 */
49
+	private $currentPromise;
50
+	/**
51
+	 * @var Generator
52
+	 */
53
+	private $generator;
54
+	/**
55
+	 * @var Promise
56
+	 */
57
+	private $result;
58
+	public function __construct(callable $generatorFn)
59
+	{
60
+		$this->generator = $generatorFn();
61
+		$this->result = new Promise(function () : void {
62
+			while (isset($this->currentPromise)) {
63
+				$this->currentPromise->wait();
64
+			}
65
+		});
66
+		try {
67
+			$this->nextCoroutine($this->generator->current());
68
+		} catch (Throwable $throwable) {
69
+			$this->result->reject($throwable);
70
+		}
71
+	}
72
+	/**
73
+	 * Create a new coroutine.
74
+	 */
75
+	public static function of(callable $generatorFn) : self
76
+	{
77
+		return new self($generatorFn);
78
+	}
79
+	public function then(?callable $onFulfilled = null, ?callable $onRejected = null) : PromiseInterface
80
+	{
81
+		return $this->result->then($onFulfilled, $onRejected);
82
+	}
83
+	public function otherwise(callable $onRejected) : PromiseInterface
84
+	{
85
+		return $this->result->otherwise($onRejected);
86
+	}
87
+	public function wait(bool $unwrap = \true)
88
+	{
89
+		return $this->result->wait($unwrap);
90
+	}
91
+	public function getState() : string
92
+	{
93
+		return $this->result->getState();
94
+	}
95
+	public function resolve($value) : void
96
+	{
97
+		$this->result->resolve($value);
98
+	}
99
+	public function reject($reason) : void
100
+	{
101
+		$this->result->reject($reason);
102
+	}
103
+	public function cancel() : void
104
+	{
105
+		$this->currentPromise->cancel();
106
+		$this->result->cancel();
107
+	}
108
+	private function nextCoroutine($yielded) : void
109
+	{
110
+		$this->currentPromise = Create::promiseFor($yielded)->then([$this, '_handleSuccess'], [$this, '_handleFailure']);
111
+	}
112
+	/**
113
+	 * @internal
114
+	 */
115
+	public function _handleSuccess($value) : void
116
+	{
117
+		unset($this->currentPromise);
118
+		try {
119
+			$next = $this->generator->send($value);
120
+			if ($this->generator->valid()) {
121
+				$this->nextCoroutine($next);
122
+			} else {
123
+				$this->result->resolve($value);
124
+			}
125
+		} catch (Throwable $throwable) {
126
+			$this->result->reject($throwable);
127
+		}
128
+	}
129
+	/**
130
+	 * @internal
131
+	 */
132
+	public function _handleFailure($reason) : void
133
+	{
134
+		unset($this->currentPromise);
135
+		try {
136
+			$nextYield = $this->generator->throw(Create::exceptionFor($reason));
137
+			// The throw was caught, so keep iterating on the coroutine
138
+			$this->nextCoroutine($nextYield);
139
+		} catch (Throwable $throwable) {
140
+			$this->result->reject($throwable);
141
+		}
142
+	}
143 143
 }
Please login to merge, or discard this patch.
lib/Vendor/GuzzleHttp/Promise/Utils.php 2 patches
Indentation   +211 added lines, -211 removed lines patch added patch discarded remove patch
@@ -5,215 +5,215 @@
 block discarded – undo
5 5
 
6 6
 final class Utils
7 7
 {
8
-    /**
9
-     * Get the global task queue used for promise resolution.
10
-     *
11
-     * This task queue MUST be run in an event loop in order for promises to be
12
-     * settled asynchronously. It will be automatically run when synchronously
13
-     * waiting on a promise.
14
-     *
15
-     * <code>
16
-     * while ($eventLoop->isRunning()) {
17
-     *     GuzzleHttp\Promise\Utils::queue()->run();
18
-     * }
19
-     * </code>
20
-     *
21
-     * @param TaskQueueInterface|null $assign Optionally specify a new queue instance.
22
-     */
23
-    public static function queue(?TaskQueueInterface $assign = null) : TaskQueueInterface
24
-    {
25
-        static $queue;
26
-        if ($assign) {
27
-            $queue = $assign;
28
-        } elseif (!$queue) {
29
-            $queue = new TaskQueue();
30
-        }
31
-        return $queue;
32
-    }
33
-    /**
34
-     * Adds a function to run in the task queue when it is next `run()` and
35
-     * returns a promise that is fulfilled or rejected with the result.
36
-     *
37
-     * @param callable $task Task function to run.
38
-     */
39
-    public static function task(callable $task) : PromiseInterface
40
-    {
41
-        $queue = self::queue();
42
-        $promise = new Promise([$queue, 'run']);
43
-        $queue->add(function () use($task, $promise) : void {
44
-            try {
45
-                if (Is::pending($promise)) {
46
-                    $promise->resolve($task());
47
-                }
48
-            } catch (\Throwable $e) {
49
-                $promise->reject($e);
50
-            }
51
-        });
52
-        return $promise;
53
-    }
54
-    /**
55
-     * Synchronously waits on a promise to resolve and returns an inspection
56
-     * state array.
57
-     *
58
-     * Returns a state associative array containing a "state" key mapping to a
59
-     * valid promise state. If the state of the promise is "fulfilled", the
60
-     * array will contain a "value" key mapping to the fulfilled value of the
61
-     * promise. If the promise is rejected, the array will contain a "reason"
62
-     * key mapping to the rejection reason of the promise.
63
-     *
64
-     * @param PromiseInterface $promise Promise or value.
65
-     */
66
-    public static function inspect(PromiseInterface $promise) : array
67
-    {
68
-        try {
69
-            return ['state' => PromiseInterface::FULFILLED, 'value' => $promise->wait()];
70
-        } catch (RejectionException $e) {
71
-            return ['state' => PromiseInterface::REJECTED, 'reason' => $e->getReason()];
72
-        } catch (\Throwable $e) {
73
-            return ['state' => PromiseInterface::REJECTED, 'reason' => $e];
74
-        }
75
-    }
76
-    /**
77
-     * Waits on all of the provided promises, but does not unwrap rejected
78
-     * promises as thrown exception.
79
-     *
80
-     * Returns an array of inspection state arrays.
81
-     *
82
-     * @see inspect for the inspection state array format.
83
-     *
84
-     * @param PromiseInterface[] $promises Traversable of promises to wait upon.
85
-     */
86
-    public static function inspectAll($promises) : array
87
-    {
88
-        $results = [];
89
-        foreach ($promises as $key => $promise) {
90
-            $results[$key] = self::inspect($promise);
91
-        }
92
-        return $results;
93
-    }
94
-    /**
95
-     * Waits on all of the provided promises and returns the fulfilled values.
96
-     *
97
-     * Returns an array that contains the value of each promise (in the same
98
-     * order the promises were provided). An exception is thrown if any of the
99
-     * promises are rejected.
100
-     *
101
-     * @param iterable<PromiseInterface> $promises Iterable of PromiseInterface objects to wait on.
102
-     *
103
-     * @throws \Throwable on error
104
-     */
105
-    public static function unwrap($promises) : array
106
-    {
107
-        $results = [];
108
-        foreach ($promises as $key => $promise) {
109
-            $results[$key] = $promise->wait();
110
-        }
111
-        return $results;
112
-    }
113
-    /**
114
-     * Given an array of promises, return a promise that is fulfilled when all
115
-     * the items in the array are fulfilled.
116
-     *
117
-     * The promise's fulfillment value is an array with fulfillment values at
118
-     * respective positions to the original array. If any promise in the array
119
-     * rejects, the returned promise is rejected with the rejection reason.
120
-     *
121
-     * @param mixed $promises  Promises or values.
122
-     * @param bool  $recursive If true, resolves new promises that might have been added to the stack during its own resolution.
123
-     */
124
-    public static function all($promises, bool $recursive = \false) : PromiseInterface
125
-    {
126
-        $results = [];
127
-        $promise = Each::of($promises, function ($value, $idx) use(&$results) : void {
128
-            $results[$idx] = $value;
129
-        }, function ($reason, $idx, Promise $aggregate) : void {
130
-            if (Is::pending($aggregate)) {
131
-                $aggregate->reject($reason);
132
-            }
133
-        })->then(function () use(&$results) {
134
-            \ksort($results);
135
-            return $results;
136
-        });
137
-        if (\true === $recursive) {
138
-            $promise = $promise->then(function ($results) use($recursive, &$promises) {
139
-                foreach ($promises as $promise) {
140
-                    if (Is::pending($promise)) {
141
-                        return self::all($promises, $recursive);
142
-                    }
143
-                }
144
-                return $results;
145
-            });
146
-        }
147
-        return $promise;
148
-    }
149
-    /**
150
-     * Initiate a competitive race between multiple promises or values (values
151
-     * will become immediately fulfilled promises).
152
-     *
153
-     * When count amount of promises have been fulfilled, the returned promise
154
-     * is fulfilled with an array that contains the fulfillment values of the
155
-     * winners in order of resolution.
156
-     *
157
-     * This promise is rejected with a {@see AggregateException} if the number
158
-     * of fulfilled promises is less than the desired $count.
159
-     *
160
-     * @param int   $count    Total number of promises.
161
-     * @param mixed $promises Promises or values.
162
-     */
163
-    public static function some(int $count, $promises) : PromiseInterface
164
-    {
165
-        $results = [];
166
-        $rejections = [];
167
-        return Each::of($promises, function ($value, $idx, PromiseInterface $p) use(&$results, $count) : void {
168
-            if (Is::settled($p)) {
169
-                return;
170
-            }
171
-            $results[$idx] = $value;
172
-            if (\count($results) >= $count) {
173
-                $p->resolve(null);
174
-            }
175
-        }, function ($reason) use(&$rejections) : void {
176
-            $rejections[] = $reason;
177
-        })->then(function () use(&$results, &$rejections, $count) {
178
-            if (\count($results) !== $count) {
179
-                throw new AggregateException('Not enough promises to fulfill count', $rejections);
180
-            }
181
-            \ksort($results);
182
-            return \array_values($results);
183
-        });
184
-    }
185
-    /**
186
-     * Like some(), with 1 as count. However, if the promise fulfills, the
187
-     * fulfillment value is not an array of 1 but the value directly.
188
-     *
189
-     * @param mixed $promises Promises or values.
190
-     */
191
-    public static function any($promises) : PromiseInterface
192
-    {
193
-        return self::some(1, $promises)->then(function ($values) {
194
-            return $values[0];
195
-        });
196
-    }
197
-    /**
198
-     * Returns a promise that is fulfilled when all of the provided promises have
199
-     * been fulfilled or rejected.
200
-     *
201
-     * The returned promise is fulfilled with an array of inspection state arrays.
202
-     *
203
-     * @see inspect for the inspection state array format.
204
-     *
205
-     * @param mixed $promises Promises or values.
206
-     */
207
-    public static function settle($promises) : PromiseInterface
208
-    {
209
-        $results = [];
210
-        return Each::of($promises, function ($value, $idx) use(&$results) : void {
211
-            $results[$idx] = ['state' => PromiseInterface::FULFILLED, 'value' => $value];
212
-        }, function ($reason, $idx) use(&$results) : void {
213
-            $results[$idx] = ['state' => PromiseInterface::REJECTED, 'reason' => $reason];
214
-        })->then(function () use(&$results) {
215
-            \ksort($results);
216
-            return $results;
217
-        });
218
-    }
8
+	/**
9
+	 * Get the global task queue used for promise resolution.
10
+	 *
11
+	 * This task queue MUST be run in an event loop in order for promises to be
12
+	 * settled asynchronously. It will be automatically run when synchronously
13
+	 * waiting on a promise.
14
+	 *
15
+	 * <code>
16
+	 * while ($eventLoop->isRunning()) {
17
+	 *     GuzzleHttp\Promise\Utils::queue()->run();
18
+	 * }
19
+	 * </code>
20
+	 *
21
+	 * @param TaskQueueInterface|null $assign Optionally specify a new queue instance.
22
+	 */
23
+	public static function queue(?TaskQueueInterface $assign = null) : TaskQueueInterface
24
+	{
25
+		static $queue;
26
+		if ($assign) {
27
+			$queue = $assign;
28
+		} elseif (!$queue) {
29
+			$queue = new TaskQueue();
30
+		}
31
+		return $queue;
32
+	}
33
+	/**
34
+	 * Adds a function to run in the task queue when it is next `run()` and
35
+	 * returns a promise that is fulfilled or rejected with the result.
36
+	 *
37
+	 * @param callable $task Task function to run.
38
+	 */
39
+	public static function task(callable $task) : PromiseInterface
40
+	{
41
+		$queue = self::queue();
42
+		$promise = new Promise([$queue, 'run']);
43
+		$queue->add(function () use($task, $promise) : void {
44
+			try {
45
+				if (Is::pending($promise)) {
46
+					$promise->resolve($task());
47
+				}
48
+			} catch (\Throwable $e) {
49
+				$promise->reject($e);
50
+			}
51
+		});
52
+		return $promise;
53
+	}
54
+	/**
55
+	 * Synchronously waits on a promise to resolve and returns an inspection
56
+	 * state array.
57
+	 *
58
+	 * Returns a state associative array containing a "state" key mapping to a
59
+	 * valid promise state. If the state of the promise is "fulfilled", the
60
+	 * array will contain a "value" key mapping to the fulfilled value of the
61
+	 * promise. If the promise is rejected, the array will contain a "reason"
62
+	 * key mapping to the rejection reason of the promise.
63
+	 *
64
+	 * @param PromiseInterface $promise Promise or value.
65
+	 */
66
+	public static function inspect(PromiseInterface $promise) : array
67
+	{
68
+		try {
69
+			return ['state' => PromiseInterface::FULFILLED, 'value' => $promise->wait()];
70
+		} catch (RejectionException $e) {
71
+			return ['state' => PromiseInterface::REJECTED, 'reason' => $e->getReason()];
72
+		} catch (\Throwable $e) {
73
+			return ['state' => PromiseInterface::REJECTED, 'reason' => $e];
74
+		}
75
+	}
76
+	/**
77
+	 * Waits on all of the provided promises, but does not unwrap rejected
78
+	 * promises as thrown exception.
79
+	 *
80
+	 * Returns an array of inspection state arrays.
81
+	 *
82
+	 * @see inspect for the inspection state array format.
83
+	 *
84
+	 * @param PromiseInterface[] $promises Traversable of promises to wait upon.
85
+	 */
86
+	public static function inspectAll($promises) : array
87
+	{
88
+		$results = [];
89
+		foreach ($promises as $key => $promise) {
90
+			$results[$key] = self::inspect($promise);
91
+		}
92
+		return $results;
93
+	}
94
+	/**
95
+	 * Waits on all of the provided promises and returns the fulfilled values.
96
+	 *
97
+	 * Returns an array that contains the value of each promise (in the same
98
+	 * order the promises were provided). An exception is thrown if any of the
99
+	 * promises are rejected.
100
+	 *
101
+	 * @param iterable<PromiseInterface> $promises Iterable of PromiseInterface objects to wait on.
102
+	 *
103
+	 * @throws \Throwable on error
104
+	 */
105
+	public static function unwrap($promises) : array
106
+	{
107
+		$results = [];
108
+		foreach ($promises as $key => $promise) {
109
+			$results[$key] = $promise->wait();
110
+		}
111
+		return $results;
112
+	}
113
+	/**
114
+	 * Given an array of promises, return a promise that is fulfilled when all
115
+	 * the items in the array are fulfilled.
116
+	 *
117
+	 * The promise's fulfillment value is an array with fulfillment values at
118
+	 * respective positions to the original array. If any promise in the array
119
+	 * rejects, the returned promise is rejected with the rejection reason.
120
+	 *
121
+	 * @param mixed $promises  Promises or values.
122
+	 * @param bool  $recursive If true, resolves new promises that might have been added to the stack during its own resolution.
123
+	 */
124
+	public static function all($promises, bool $recursive = \false) : PromiseInterface
125
+	{
126
+		$results = [];
127
+		$promise = Each::of($promises, function ($value, $idx) use(&$results) : void {
128
+			$results[$idx] = $value;
129
+		}, function ($reason, $idx, Promise $aggregate) : void {
130
+			if (Is::pending($aggregate)) {
131
+				$aggregate->reject($reason);
132
+			}
133
+		})->then(function () use(&$results) {
134
+			\ksort($results);
135
+			return $results;
136
+		});
137
+		if (\true === $recursive) {
138
+			$promise = $promise->then(function ($results) use($recursive, &$promises) {
139
+				foreach ($promises as $promise) {
140
+					if (Is::pending($promise)) {
141
+						return self::all($promises, $recursive);
142
+					}
143
+				}
144
+				return $results;
145
+			});
146
+		}
147
+		return $promise;
148
+	}
149
+	/**
150
+	 * Initiate a competitive race between multiple promises or values (values
151
+	 * will become immediately fulfilled promises).
152
+	 *
153
+	 * When count amount of promises have been fulfilled, the returned promise
154
+	 * is fulfilled with an array that contains the fulfillment values of the
155
+	 * winners in order of resolution.
156
+	 *
157
+	 * This promise is rejected with a {@see AggregateException} if the number
158
+	 * of fulfilled promises is less than the desired $count.
159
+	 *
160
+	 * @param int   $count    Total number of promises.
161
+	 * @param mixed $promises Promises or values.
162
+	 */
163
+	public static function some(int $count, $promises) : PromiseInterface
164
+	{
165
+		$results = [];
166
+		$rejections = [];
167
+		return Each::of($promises, function ($value, $idx, PromiseInterface $p) use(&$results, $count) : void {
168
+			if (Is::settled($p)) {
169
+				return;
170
+			}
171
+			$results[$idx] = $value;
172
+			if (\count($results) >= $count) {
173
+				$p->resolve(null);
174
+			}
175
+		}, function ($reason) use(&$rejections) : void {
176
+			$rejections[] = $reason;
177
+		})->then(function () use(&$results, &$rejections, $count) {
178
+			if (\count($results) !== $count) {
179
+				throw new AggregateException('Not enough promises to fulfill count', $rejections);
180
+			}
181
+			\ksort($results);
182
+			return \array_values($results);
183
+		});
184
+	}
185
+	/**
186
+	 * Like some(), with 1 as count. However, if the promise fulfills, the
187
+	 * fulfillment value is not an array of 1 but the value directly.
188
+	 *
189
+	 * @param mixed $promises Promises or values.
190
+	 */
191
+	public static function any($promises) : PromiseInterface
192
+	{
193
+		return self::some(1, $promises)->then(function ($values) {
194
+			return $values[0];
195
+		});
196
+	}
197
+	/**
198
+	 * Returns a promise that is fulfilled when all of the provided promises have
199
+	 * been fulfilled or rejected.
200
+	 *
201
+	 * The returned promise is fulfilled with an array of inspection state arrays.
202
+	 *
203
+	 * @see inspect for the inspection state array format.
204
+	 *
205
+	 * @param mixed $promises Promises or values.
206
+	 */
207
+	public static function settle($promises) : PromiseInterface
208
+	{
209
+		$results = [];
210
+		return Each::of($promises, function ($value, $idx) use(&$results) : void {
211
+			$results[$idx] = ['state' => PromiseInterface::FULFILLED, 'value' => $value];
212
+		}, function ($reason, $idx) use(&$results) : void {
213
+			$results[$idx] = ['state' => PromiseInterface::REJECTED, 'reason' => $reason];
214
+		})->then(function () use(&$results) {
215
+			\ksort($results);
216
+			return $results;
217
+		});
218
+	}
219 219
 }
Please login to merge, or discard this patch.
Spacing   +13 added lines, -13 removed lines patch added patch discarded remove patch
@@ -1,6 +1,6 @@  discard block
 block discarded – undo
1 1
 <?php
2 2
 
3
-declare (strict_types=1);
3
+declare(strict_types=1);
4 4
 namespace OCA\FullTextSearch_Elasticsearch\Vendor\GuzzleHttp\Promise;
5 5
 
6 6
 final class Utils
@@ -40,7 +40,7 @@  discard block
 block discarded – undo
40 40
     {
41 41
         $queue = self::queue();
42 42
         $promise = new Promise([$queue, 'run']);
43
-        $queue->add(function () use($task, $promise) : void {
43
+        $queue->add(function() use($task, $promise) : void {
44 44
             try {
45 45
                 if (Is::pending($promise)) {
46 46
                     $promise->resolve($task());
@@ -124,18 +124,18 @@  discard block
 block discarded – undo
124 124
     public static function all($promises, bool $recursive = \false) : PromiseInterface
125 125
     {
126 126
         $results = [];
127
-        $promise = Each::of($promises, function ($value, $idx) use(&$results) : void {
127
+        $promise = Each::of($promises, function($value, $idx) use(&$results) : void {
128 128
             $results[$idx] = $value;
129
-        }, function ($reason, $idx, Promise $aggregate) : void {
129
+        }, function($reason, $idx, Promise $aggregate) : void {
130 130
             if (Is::pending($aggregate)) {
131 131
                 $aggregate->reject($reason);
132 132
             }
133
-        })->then(function () use(&$results) {
133
+        })->then(function() use(&$results) {
134 134
             \ksort($results);
135 135
             return $results;
136 136
         });
137 137
         if (\true === $recursive) {
138
-            $promise = $promise->then(function ($results) use($recursive, &$promises) {
138
+            $promise = $promise->then(function($results) use($recursive, &$promises) {
139 139
                 foreach ($promises as $promise) {
140 140
                     if (Is::pending($promise)) {
141 141
                         return self::all($promises, $recursive);
@@ -164,7 +164,7 @@  discard block
 block discarded – undo
164 164
     {
165 165
         $results = [];
166 166
         $rejections = [];
167
-        return Each::of($promises, function ($value, $idx, PromiseInterface $p) use(&$results, $count) : void {
167
+        return Each::of($promises, function($value, $idx, PromiseInterface $p) use(&$results, $count) : void {
168 168
             if (Is::settled($p)) {
169 169
                 return;
170 170
             }
@@ -172,9 +172,9 @@  discard block
 block discarded – undo
172 172
             if (\count($results) >= $count) {
173 173
                 $p->resolve(null);
174 174
             }
175
-        }, function ($reason) use(&$rejections) : void {
175
+        }, function($reason) use(&$rejections) : void {
176 176
             $rejections[] = $reason;
177
-        })->then(function () use(&$results, &$rejections, $count) {
177
+        })->then(function() use(&$results, &$rejections, $count) {
178 178
             if (\count($results) !== $count) {
179 179
                 throw new AggregateException('Not enough promises to fulfill count', $rejections);
180 180
             }
@@ -190,7 +190,7 @@  discard block
 block discarded – undo
190 190
      */
191 191
     public static function any($promises) : PromiseInterface
192 192
     {
193
-        return self::some(1, $promises)->then(function ($values) {
193
+        return self::some(1, $promises)->then(function($values) {
194 194
             return $values[0];
195 195
         });
196 196
     }
@@ -207,11 +207,11 @@  discard block
 block discarded – undo
207 207
     public static function settle($promises) : PromiseInterface
208 208
     {
209 209
         $results = [];
210
-        return Each::of($promises, function ($value, $idx) use(&$results) : void {
210
+        return Each::of($promises, function($value, $idx) use(&$results) : void {
211 211
             $results[$idx] = ['state' => PromiseInterface::FULFILLED, 'value' => $value];
212
-        }, function ($reason, $idx) use(&$results) : void {
212
+        }, function($reason, $idx) use(&$results) : void {
213 213
             $results[$idx] = ['state' => PromiseInterface::REJECTED, 'reason' => $reason];
214
-        })->then(function () use(&$results) {
214
+        })->then(function() use(&$results) {
215 215
             \ksort($results);
216 216
             return $results;
217 217
         });
Please login to merge, or discard this patch.
lib/Vendor/GuzzleHttp/Promise/Promise.php 1 patch
Indentation   +216 added lines, -216 removed lines patch added patch discarded remove patch
@@ -12,225 +12,225 @@
 block discarded – undo
12 12
  */
13 13
 class Promise implements PromiseInterface
14 14
 {
15
-    private $state = self::PENDING;
16
-    private $result;
17
-    private $cancelFn;
18
-    private $waitFn;
19
-    private $waitList;
20
-    private $handlers = [];
21
-    /**
22
-     * @param callable $waitFn   Fn that when invoked resolves the promise.
23
-     * @param callable $cancelFn Fn that when invoked cancels the promise.
24
-     */
25
-    public function __construct(?callable $waitFn = null, ?callable $cancelFn = null)
26
-    {
27
-        $this->waitFn = $waitFn;
28
-        $this->cancelFn = $cancelFn;
29
-    }
30
-    public function then(?callable $onFulfilled = null, ?callable $onRejected = null) : PromiseInterface
31
-    {
32
-        if ($this->state === self::PENDING) {
33
-            $p = new Promise(null, [$this, 'cancel']);
34
-            $this->handlers[] = [$p, $onFulfilled, $onRejected];
35
-            $p->waitList = $this->waitList;
36
-            $p->waitList[] = $this;
37
-            return $p;
38
-        }
39
-        // Return a fulfilled promise and immediately invoke any callbacks.
40
-        if ($this->state === self::FULFILLED) {
41
-            $promise = Create::promiseFor($this->result);
42
-            return $onFulfilled ? $promise->then($onFulfilled) : $promise;
43
-        }
44
-        // It's either cancelled or rejected, so return a rejected promise
45
-        // and immediately invoke any callbacks.
46
-        $rejection = Create::rejectionFor($this->result);
47
-        return $onRejected ? $rejection->then(null, $onRejected) : $rejection;
48
-    }
49
-    public function otherwise(callable $onRejected) : PromiseInterface
50
-    {
51
-        return $this->then(null, $onRejected);
52
-    }
53
-    public function wait(bool $unwrap = \true)
54
-    {
55
-        $this->waitIfPending();
56
-        if ($this->result instanceof PromiseInterface) {
57
-            return $this->result->wait($unwrap);
58
-        }
59
-        if ($unwrap) {
60
-            if ($this->state === self::FULFILLED) {
61
-                return $this->result;
62
-            }
63
-            // It's rejected so "unwrap" and throw an exception.
64
-            throw Create::exceptionFor($this->result);
65
-        }
66
-    }
67
-    public function getState() : string
68
-    {
69
-        return $this->state;
70
-    }
71
-    public function cancel() : void
72
-    {
73
-        if ($this->state !== self::PENDING) {
74
-            return;
75
-        }
76
-        $this->waitFn = $this->waitList = null;
77
-        if ($this->cancelFn) {
78
-            $fn = $this->cancelFn;
79
-            $this->cancelFn = null;
80
-            try {
81
-                $fn();
82
-            } catch (\Throwable $e) {
83
-                $this->reject($e);
84
-            }
85
-        }
86
-        // Reject the promise only if it wasn't rejected in a then callback.
87
-        /** @psalm-suppress RedundantCondition */
88
-        if ($this->state === self::PENDING) {
89
-            $this->reject(new CancellationException('Promise has been cancelled'));
90
-        }
91
-    }
92
-    public function resolve($value) : void
93
-    {
94
-        $this->settle(self::FULFILLED, $value);
95
-    }
96
-    public function reject($reason) : void
97
-    {
98
-        $this->settle(self::REJECTED, $reason);
99
-    }
100
-    private function settle(string $state, $value) : void
101
-    {
102
-        if ($this->state !== self::PENDING) {
103
-            // Ignore calls with the same resolution.
104
-            if ($state === $this->state && $value === $this->result) {
105
-                return;
106
-            }
107
-            throw $this->state === $state ? new \LogicException("The promise is already {$state}.") : new \LogicException("Cannot change a {$this->state} promise to {$state}");
108
-        }
109
-        if ($value === $this) {
110
-            throw new \LogicException('Cannot fulfill or reject a promise with itself');
111
-        }
112
-        // Clear out the state of the promise but stash the handlers.
113
-        $this->state = $state;
114
-        $this->result = $value;
115
-        $handlers = $this->handlers;
116
-        $this->handlers = null;
117
-        $this->waitList = $this->waitFn = null;
118
-        $this->cancelFn = null;
119
-        if (!$handlers) {
120
-            return;
121
-        }
122
-        // If the value was not a settled promise or a thenable, then resolve
123
-        // it in the task queue using the correct ID.
124
-        if (!\is_object($value) || !\method_exists($value, 'then')) {
125
-            $id = $state === self::FULFILLED ? 1 : 2;
126
-            // It's a success, so resolve the handlers in the queue.
127
-            Utils::queue()->add(static function () use($id, $value, $handlers) : void {
128
-                foreach ($handlers as $handler) {
129
-                    self::callHandler($id, $value, $handler);
130
-                }
131
-            });
132
-        } elseif ($value instanceof Promise && Is::pending($value)) {
133
-            // We can just merge our handlers onto the next promise.
134
-            $value->handlers = \array_merge($value->handlers, $handlers);
135
-        } else {
136
-            // Resolve the handlers when the forwarded promise is resolved.
137
-            $value->then(static function ($value) use($handlers) : void {
138
-                foreach ($handlers as $handler) {
139
-                    self::callHandler(1, $value, $handler);
140
-                }
141
-            }, static function ($reason) use($handlers) : void {
142
-                foreach ($handlers as $handler) {
143
-                    self::callHandler(2, $reason, $handler);
144
-                }
145
-            });
146
-        }
147
-    }
148
-    /**
149
-     * Call a stack of handlers using a specific callback index and value.
150
-     *
151
-     * @param int   $index   1 (resolve) or 2 (reject).
152
-     * @param mixed $value   Value to pass to the callback.
153
-     * @param array $handler Array of handler data (promise and callbacks).
154
-     */
155
-    private static function callHandler(int $index, $value, array $handler) : void
156
-    {
157
-        /** @var PromiseInterface $promise */
158
-        $promise = $handler[0];
159
-        // The promise may have been cancelled or resolved before placing
160
-        // this thunk in the queue.
161
-        if (Is::settled($promise)) {
162
-            return;
163
-        }
164
-        try {
165
-            if (isset($handler[$index])) {
166
-                /*
15
+	private $state = self::PENDING;
16
+	private $result;
17
+	private $cancelFn;
18
+	private $waitFn;
19
+	private $waitList;
20
+	private $handlers = [];
21
+	/**
22
+	 * @param callable $waitFn   Fn that when invoked resolves the promise.
23
+	 * @param callable $cancelFn Fn that when invoked cancels the promise.
24
+	 */
25
+	public function __construct(?callable $waitFn = null, ?callable $cancelFn = null)
26
+	{
27
+		$this->waitFn = $waitFn;
28
+		$this->cancelFn = $cancelFn;
29
+	}
30
+	public function then(?callable $onFulfilled = null, ?callable $onRejected = null) : PromiseInterface
31
+	{
32
+		if ($this->state === self::PENDING) {
33
+			$p = new Promise(null, [$this, 'cancel']);
34
+			$this->handlers[] = [$p, $onFulfilled, $onRejected];
35
+			$p->waitList = $this->waitList;
36
+			$p->waitList[] = $this;
37
+			return $p;
38
+		}
39
+		// Return a fulfilled promise and immediately invoke any callbacks.
40
+		if ($this->state === self::FULFILLED) {
41
+			$promise = Create::promiseFor($this->result);
42
+			return $onFulfilled ? $promise->then($onFulfilled) : $promise;
43
+		}
44
+		// It's either cancelled or rejected, so return a rejected promise
45
+		// and immediately invoke any callbacks.
46
+		$rejection = Create::rejectionFor($this->result);
47
+		return $onRejected ? $rejection->then(null, $onRejected) : $rejection;
48
+	}
49
+	public function otherwise(callable $onRejected) : PromiseInterface
50
+	{
51
+		return $this->then(null, $onRejected);
52
+	}
53
+	public function wait(bool $unwrap = \true)
54
+	{
55
+		$this->waitIfPending();
56
+		if ($this->result instanceof PromiseInterface) {
57
+			return $this->result->wait($unwrap);
58
+		}
59
+		if ($unwrap) {
60
+			if ($this->state === self::FULFILLED) {
61
+				return $this->result;
62
+			}
63
+			// It's rejected so "unwrap" and throw an exception.
64
+			throw Create::exceptionFor($this->result);
65
+		}
66
+	}
67
+	public function getState() : string
68
+	{
69
+		return $this->state;
70
+	}
71
+	public function cancel() : void
72
+	{
73
+		if ($this->state !== self::PENDING) {
74
+			return;
75
+		}
76
+		$this->waitFn = $this->waitList = null;
77
+		if ($this->cancelFn) {
78
+			$fn = $this->cancelFn;
79
+			$this->cancelFn = null;
80
+			try {
81
+				$fn();
82
+			} catch (\Throwable $e) {
83
+				$this->reject($e);
84
+			}
85
+		}
86
+		// Reject the promise only if it wasn't rejected in a then callback.
87
+		/** @psalm-suppress RedundantCondition */
88
+		if ($this->state === self::PENDING) {
89
+			$this->reject(new CancellationException('Promise has been cancelled'));
90
+		}
91
+	}
92
+	public function resolve($value) : void
93
+	{
94
+		$this->settle(self::FULFILLED, $value);
95
+	}
96
+	public function reject($reason) : void
97
+	{
98
+		$this->settle(self::REJECTED, $reason);
99
+	}
100
+	private function settle(string $state, $value) : void
101
+	{
102
+		if ($this->state !== self::PENDING) {
103
+			// Ignore calls with the same resolution.
104
+			if ($state === $this->state && $value === $this->result) {
105
+				return;
106
+			}
107
+			throw $this->state === $state ? new \LogicException("The promise is already {$state}.") : new \LogicException("Cannot change a {$this->state} promise to {$state}");
108
+		}
109
+		if ($value === $this) {
110
+			throw new \LogicException('Cannot fulfill or reject a promise with itself');
111
+		}
112
+		// Clear out the state of the promise but stash the handlers.
113
+		$this->state = $state;
114
+		$this->result = $value;
115
+		$handlers = $this->handlers;
116
+		$this->handlers = null;
117
+		$this->waitList = $this->waitFn = null;
118
+		$this->cancelFn = null;
119
+		if (!$handlers) {
120
+			return;
121
+		}
122
+		// If the value was not a settled promise or a thenable, then resolve
123
+		// it in the task queue using the correct ID.
124
+		if (!\is_object($value) || !\method_exists($value, 'then')) {
125
+			$id = $state === self::FULFILLED ? 1 : 2;
126
+			// It's a success, so resolve the handlers in the queue.
127
+			Utils::queue()->add(static function () use($id, $value, $handlers) : void {
128
+				foreach ($handlers as $handler) {
129
+					self::callHandler($id, $value, $handler);
130
+				}
131
+			});
132
+		} elseif ($value instanceof Promise && Is::pending($value)) {
133
+			// We can just merge our handlers onto the next promise.
134
+			$value->handlers = \array_merge($value->handlers, $handlers);
135
+		} else {
136
+			// Resolve the handlers when the forwarded promise is resolved.
137
+			$value->then(static function ($value) use($handlers) : void {
138
+				foreach ($handlers as $handler) {
139
+					self::callHandler(1, $value, $handler);
140
+				}
141
+			}, static function ($reason) use($handlers) : void {
142
+				foreach ($handlers as $handler) {
143
+					self::callHandler(2, $reason, $handler);
144
+				}
145
+			});
146
+		}
147
+	}
148
+	/**
149
+	 * Call a stack of handlers using a specific callback index and value.
150
+	 *
151
+	 * @param int   $index   1 (resolve) or 2 (reject).
152
+	 * @param mixed $value   Value to pass to the callback.
153
+	 * @param array $handler Array of handler data (promise and callbacks).
154
+	 */
155
+	private static function callHandler(int $index, $value, array $handler) : void
156
+	{
157
+		/** @var PromiseInterface $promise */
158
+		$promise = $handler[0];
159
+		// The promise may have been cancelled or resolved before placing
160
+		// this thunk in the queue.
161
+		if (Is::settled($promise)) {
162
+			return;
163
+		}
164
+		try {
165
+			if (isset($handler[$index])) {
166
+				/*
167 167
                  * If $f throws an exception, then $handler will be in the exception
168 168
                  * stack trace. Since $handler contains a reference to the callable
169 169
                  * itself we get a circular reference. We clear the $handler
170 170
                  * here to avoid that memory leak.
171 171
                  */
172
-                $f = $handler[$index];
173
-                unset($handler);
174
-                $promise->resolve($f($value));
175
-            } elseif ($index === 1) {
176
-                // Forward resolution values as-is.
177
-                $promise->resolve($value);
178
-            } else {
179
-                // Forward rejections down the chain.
180
-                $promise->reject($value);
181
-            }
182
-        } catch (\Throwable $reason) {
183
-            $promise->reject($reason);
184
-        }
185
-    }
186
-    private function waitIfPending() : void
187
-    {
188
-        if ($this->state !== self::PENDING) {
189
-            return;
190
-        } elseif ($this->waitFn) {
191
-            $this->invokeWaitFn();
192
-        } elseif ($this->waitList) {
193
-            $this->invokeWaitList();
194
-        } else {
195
-            // If there's no wait function, then reject the promise.
196
-            $this->reject('Cannot wait on a promise that has ' . 'no internal wait function. You must provide a wait ' . 'function when constructing the promise to be able to ' . 'wait on a promise.');
197
-        }
198
-        Utils::queue()->run();
199
-        /** @psalm-suppress RedundantCondition */
200
-        if ($this->state === self::PENDING) {
201
-            $this->reject('Invoking the wait callback did not resolve the promise');
202
-        }
203
-    }
204
-    private function invokeWaitFn() : void
205
-    {
206
-        try {
207
-            $wfn = $this->waitFn;
208
-            $this->waitFn = null;
209
-            $wfn(\true);
210
-        } catch (\Throwable $reason) {
211
-            if ($this->state === self::PENDING) {
212
-                // The promise has not been resolved yet, so reject the promise
213
-                // with the exception.
214
-                $this->reject($reason);
215
-            } else {
216
-                // The promise was already resolved, so there's a problem in
217
-                // the application.
218
-                throw $reason;
219
-            }
220
-        }
221
-    }
222
-    private function invokeWaitList() : void
223
-    {
224
-        $waitList = $this->waitList;
225
-        $this->waitList = null;
226
-        foreach ($waitList as $result) {
227
-            do {
228
-                $result->waitIfPending();
229
-                $result = $result->result;
230
-            } while ($result instanceof Promise);
231
-            if ($result instanceof PromiseInterface) {
232
-                $result->wait(\false);
233
-            }
234
-        }
235
-    }
172
+				$f = $handler[$index];
173
+				unset($handler);
174
+				$promise->resolve($f($value));
175
+			} elseif ($index === 1) {
176
+				// Forward resolution values as-is.
177
+				$promise->resolve($value);
178
+			} else {
179
+				// Forward rejections down the chain.
180
+				$promise->reject($value);
181
+			}
182
+		} catch (\Throwable $reason) {
183
+			$promise->reject($reason);
184
+		}
185
+	}
186
+	private function waitIfPending() : void
187
+	{
188
+		if ($this->state !== self::PENDING) {
189
+			return;
190
+		} elseif ($this->waitFn) {
191
+			$this->invokeWaitFn();
192
+		} elseif ($this->waitList) {
193
+			$this->invokeWaitList();
194
+		} else {
195
+			// If there's no wait function, then reject the promise.
196
+			$this->reject('Cannot wait on a promise that has ' . 'no internal wait function. You must provide a wait ' . 'function when constructing the promise to be able to ' . 'wait on a promise.');
197
+		}
198
+		Utils::queue()->run();
199
+		/** @psalm-suppress RedundantCondition */
200
+		if ($this->state === self::PENDING) {
201
+			$this->reject('Invoking the wait callback did not resolve the promise');
202
+		}
203
+	}
204
+	private function invokeWaitFn() : void
205
+	{
206
+		try {
207
+			$wfn = $this->waitFn;
208
+			$this->waitFn = null;
209
+			$wfn(\true);
210
+		} catch (\Throwable $reason) {
211
+			if ($this->state === self::PENDING) {
212
+				// The promise has not been resolved yet, so reject the promise
213
+				// with the exception.
214
+				$this->reject($reason);
215
+			} else {
216
+				// The promise was already resolved, so there's a problem in
217
+				// the application.
218
+				throw $reason;
219
+			}
220
+		}
221
+	}
222
+	private function invokeWaitList() : void
223
+	{
224
+		$waitList = $this->waitList;
225
+		$this->waitList = null;
226
+		foreach ($waitList as $result) {
227
+			do {
228
+				$result->waitIfPending();
229
+				$result = $result->result;
230
+			} while ($result instanceof Promise);
231
+			if ($result instanceof PromiseInterface) {
232
+				$result->wait(\false);
233
+			}
234
+		}
235
+	}
236 236
 }
Please login to merge, or discard this patch.