rebase code on oct-10-2023
This commit is contained in:
@@ -1,23 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace YoastSEO_Vendor\GuzzleHttp;
|
||||
|
||||
use YoastSEO_Vendor\Psr\Http\Message\MessageInterface;
|
||||
final class BodySummarizer implements \YoastSEO_Vendor\GuzzleHttp\BodySummarizerInterface
|
||||
{
|
||||
/**
|
||||
* @var int|null
|
||||
*/
|
||||
private $truncateAt;
|
||||
public function __construct(int $truncateAt = null)
|
||||
{
|
||||
$this->truncateAt = $truncateAt;
|
||||
}
|
||||
/**
|
||||
* Returns a summarized message body.
|
||||
*/
|
||||
public function summarize(\YoastSEO_Vendor\Psr\Http\Message\MessageInterface $message) : ?string
|
||||
{
|
||||
return $this->truncateAt === null ? \YoastSEO_Vendor\GuzzleHttp\Psr7\Message::bodySummary($message) : \YoastSEO_Vendor\GuzzleHttp\Psr7\Message::bodySummary($message, $this->truncateAt);
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace YoastSEO_Vendor\GuzzleHttp;
|
||||
|
||||
use YoastSEO_Vendor\Psr\Http\Message\MessageInterface;
|
||||
interface BodySummarizerInterface
|
||||
{
|
||||
/**
|
||||
* Returns a summarized message body.
|
||||
*/
|
||||
public function summarize(\YoastSEO_Vendor\Psr\Http\Message\MessageInterface $message) : ?string;
|
||||
}
|
||||
@@ -4,21 +4,28 @@ namespace YoastSEO_Vendor\GuzzleHttp;
|
||||
|
||||
use YoastSEO_Vendor\GuzzleHttp\Cookie\CookieJar;
|
||||
use YoastSEO_Vendor\GuzzleHttp\Exception\GuzzleException;
|
||||
use YoastSEO_Vendor\GuzzleHttp\Exception\InvalidArgumentException;
|
||||
use YoastSEO_Vendor\GuzzleHttp\Promise as P;
|
||||
use YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface;
|
||||
use YoastSEO_Vendor\GuzzleHttp\Promise;
|
||||
use YoastSEO_Vendor\GuzzleHttp\Psr7;
|
||||
use YoastSEO_Vendor\Psr\Http\Message\RequestInterface;
|
||||
use YoastSEO_Vendor\Psr\Http\Message\ResponseInterface;
|
||||
use YoastSEO_Vendor\Psr\Http\Message\UriInterface;
|
||||
/**
|
||||
* @final
|
||||
* @method ResponseInterface get(string|UriInterface $uri, array $options = [])
|
||||
* @method ResponseInterface head(string|UriInterface $uri, array $options = [])
|
||||
* @method ResponseInterface put(string|UriInterface $uri, array $options = [])
|
||||
* @method ResponseInterface post(string|UriInterface $uri, array $options = [])
|
||||
* @method ResponseInterface patch(string|UriInterface $uri, array $options = [])
|
||||
* @method ResponseInterface delete(string|UriInterface $uri, array $options = [])
|
||||
* @method Promise\PromiseInterface getAsync(string|UriInterface $uri, array $options = [])
|
||||
* @method Promise\PromiseInterface headAsync(string|UriInterface $uri, array $options = [])
|
||||
* @method Promise\PromiseInterface putAsync(string|UriInterface $uri, array $options = [])
|
||||
* @method Promise\PromiseInterface postAsync(string|UriInterface $uri, array $options = [])
|
||||
* @method Promise\PromiseInterface patchAsync(string|UriInterface $uri, array $options = [])
|
||||
* @method Promise\PromiseInterface deleteAsync(string|UriInterface $uri, array $options = [])
|
||||
*/
|
||||
class Client implements \YoastSEO_Vendor\GuzzleHttp\ClientInterface, \YoastSEO_Vendor\Psr\Http\Client\ClientInterface
|
||||
class Client implements \YoastSEO_Vendor\GuzzleHttp\ClientInterface
|
||||
{
|
||||
use ClientTrait;
|
||||
/**
|
||||
* @var array Default request options
|
||||
*/
|
||||
/** @var array Default request options */
|
||||
private $config;
|
||||
/**
|
||||
* Clients accept an array of constructor parameters.
|
||||
@@ -56,11 +63,11 @@ class Client implements \YoastSEO_Vendor\GuzzleHttp\ClientInterface, \YoastSEO_V
|
||||
if (!isset($config['handler'])) {
|
||||
$config['handler'] = \YoastSEO_Vendor\GuzzleHttp\HandlerStack::create();
|
||||
} elseif (!\is_callable($config['handler'])) {
|
||||
throw new \YoastSEO_Vendor\GuzzleHttp\Exception\InvalidArgumentException('handler must be a callable');
|
||||
throw new \InvalidArgumentException('handler must be a callable');
|
||||
}
|
||||
// Convert the base_uri to a UriInterface
|
||||
if (isset($config['base_uri'])) {
|
||||
$config['base_uri'] = \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::uriFor($config['base_uri']);
|
||||
$config['base_uri'] = \YoastSEO_Vendor\GuzzleHttp\Psr7\uri_for($config['base_uri']);
|
||||
}
|
||||
$this->configureDefaults($config);
|
||||
}
|
||||
@@ -68,17 +75,15 @@ class Client implements \YoastSEO_Vendor\GuzzleHttp\ClientInterface, \YoastSEO_V
|
||||
* @param string $method
|
||||
* @param array $args
|
||||
*
|
||||
* @return PromiseInterface|ResponseInterface
|
||||
*
|
||||
* @deprecated Client::__call will be removed in guzzlehttp/guzzle:8.0.
|
||||
* @return Promise\PromiseInterface
|
||||
*/
|
||||
public function __call($method, $args)
|
||||
{
|
||||
if (\count($args) < 1) {
|
||||
throw new \YoastSEO_Vendor\GuzzleHttp\Exception\InvalidArgumentException('Magic request methods require a URI and optional options array');
|
||||
throw new \InvalidArgumentException('Magic request methods require a URI and optional options array');
|
||||
}
|
||||
$uri = $args[0];
|
||||
$opts = $args[1] ?? [];
|
||||
$opts = isset($args[1]) ? $args[1] : [];
|
||||
return \substr($method, -5) === 'Async' ? $this->requestAsync(\substr($method, 0, -5), $uri, $opts) : $this->request($method, $uri, $opts);
|
||||
}
|
||||
/**
|
||||
@@ -86,8 +91,10 @@ class Client implements \YoastSEO_Vendor\GuzzleHttp\ClientInterface, \YoastSEO_V
|
||||
*
|
||||
* @param array $options Request options to apply to the given
|
||||
* request and to the transfer. See \GuzzleHttp\RequestOptions.
|
||||
*
|
||||
* @return Promise\PromiseInterface
|
||||
*/
|
||||
public function sendAsync(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options = []) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
|
||||
public function sendAsync(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options = [])
|
||||
{
|
||||
// Merge the base URI into the request URI if needed.
|
||||
$options = $this->prepareDefaults($options);
|
||||
@@ -99,25 +106,14 @@ class Client implements \YoastSEO_Vendor\GuzzleHttp\ClientInterface, \YoastSEO_V
|
||||
* @param array $options Request options to apply to the given
|
||||
* request and to the transfer. See \GuzzleHttp\RequestOptions.
|
||||
*
|
||||
* @return ResponseInterface
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function send(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options = []) : \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface
|
||||
public function send(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options = [])
|
||||
{
|
||||
$options[\YoastSEO_Vendor\GuzzleHttp\RequestOptions::SYNCHRONOUS] = \true;
|
||||
return $this->sendAsync($request, $options)->wait();
|
||||
}
|
||||
/**
|
||||
* The HttpClient PSR (PSR-18) specify this method.
|
||||
*
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function sendRequest(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request) : \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface
|
||||
{
|
||||
$options[\YoastSEO_Vendor\GuzzleHttp\RequestOptions::SYNCHRONOUS] = \true;
|
||||
$options[\YoastSEO_Vendor\GuzzleHttp\RequestOptions::ALLOW_REDIRECTS] = \false;
|
||||
$options[\YoastSEO_Vendor\GuzzleHttp\RequestOptions::HTTP_ERRORS] = \false;
|
||||
return $this->sendAsync($request, $options)->wait();
|
||||
}
|
||||
/**
|
||||
* Create and send an asynchronous HTTP request.
|
||||
*
|
||||
@@ -129,18 +125,20 @@ class Client implements \YoastSEO_Vendor\GuzzleHttp\ClientInterface, \YoastSEO_V
|
||||
* @param string $method HTTP method
|
||||
* @param string|UriInterface $uri URI object or string.
|
||||
* @param array $options Request options to apply. See \GuzzleHttp\RequestOptions.
|
||||
*
|
||||
* @return Promise\PromiseInterface
|
||||
*/
|
||||
public function requestAsync(string $method, $uri = '', array $options = []) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
|
||||
public function requestAsync($method, $uri = '', array $options = [])
|
||||
{
|
||||
$options = $this->prepareDefaults($options);
|
||||
// Remove request modifying parameter because it can be done up-front.
|
||||
$headers = $options['headers'] ?? [];
|
||||
$body = $options['body'] ?? null;
|
||||
$version = $options['version'] ?? '1.1';
|
||||
$headers = isset($options['headers']) ? $options['headers'] : [];
|
||||
$body = isset($options['body']) ? $options['body'] : null;
|
||||
$version = isset($options['version']) ? $options['version'] : '1.1';
|
||||
// Merge the URI into the base URI.
|
||||
$uri = $this->buildUri(\YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::uriFor($uri), $options);
|
||||
$uri = $this->buildUri($uri, $options);
|
||||
if (\is_array($body)) {
|
||||
throw $this->invalidBody();
|
||||
$this->invalidBody();
|
||||
}
|
||||
$request = new \YoastSEO_Vendor\GuzzleHttp\Psr7\Request($method, $uri, $headers, $body, $version);
|
||||
// Remove the option so that they are not doubly-applied.
|
||||
@@ -158,9 +156,10 @@ class Client implements \YoastSEO_Vendor\GuzzleHttp\ClientInterface, \YoastSEO_V
|
||||
* @param string|UriInterface $uri URI object or string.
|
||||
* @param array $options Request options to apply. See \GuzzleHttp\RequestOptions.
|
||||
*
|
||||
* @return ResponseInterface
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function request(string $method, $uri = '', array $options = []) : \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface
|
||||
public function request($method, $uri = '', array $options = [])
|
||||
{
|
||||
$options[\YoastSEO_Vendor\GuzzleHttp\RequestOptions::SYNCHRONOUS] = \true;
|
||||
return $this->requestAsync($method, $uri, $options)->wait();
|
||||
@@ -175,17 +174,22 @@ class Client implements \YoastSEO_Vendor\GuzzleHttp\ClientInterface, \YoastSEO_V
|
||||
* @param string|null $option The config option to retrieve.
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @deprecated Client::getConfig will be removed in guzzlehttp/guzzle:8.0.
|
||||
*/
|
||||
public function getConfig(string $option = null)
|
||||
public function getConfig($option = null)
|
||||
{
|
||||
return $option === null ? $this->config : $this->config[$option] ?? null;
|
||||
return $option === null ? $this->config : (isset($this->config[$option]) ? $this->config[$option] : null);
|
||||
}
|
||||
private function buildUri(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri, array $config) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface
|
||||
/**
|
||||
* @param string|null $uri
|
||||
*
|
||||
* @return UriInterface
|
||||
*/
|
||||
private function buildUri($uri, array $config)
|
||||
{
|
||||
// for BC we accept null which would otherwise fail in uri_for
|
||||
$uri = \YoastSEO_Vendor\GuzzleHttp\Psr7\uri_for($uri === null ? '' : $uri);
|
||||
if (isset($config['base_uri'])) {
|
||||
$uri = \YoastSEO_Vendor\GuzzleHttp\Psr7\UriResolver::resolve(\YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::uriFor($config['base_uri']), $uri);
|
||||
$uri = \YoastSEO_Vendor\GuzzleHttp\Psr7\UriResolver::resolve(\YoastSEO_Vendor\GuzzleHttp\Psr7\uri_for($config['base_uri']), $uri);
|
||||
}
|
||||
if (isset($config['idn_conversion']) && $config['idn_conversion'] !== \false) {
|
||||
$idnOptions = $config['idn_conversion'] === \true ? \IDNA_DEFAULT : $config['idn_conversion'];
|
||||
@@ -195,21 +199,24 @@ class Client implements \YoastSEO_Vendor\GuzzleHttp\ClientInterface, \YoastSEO_V
|
||||
}
|
||||
/**
|
||||
* Configures the default options for a client.
|
||||
*
|
||||
* @param array $config
|
||||
* @return void
|
||||
*/
|
||||
private function configureDefaults(array $config) : void
|
||||
private function configureDefaults(array $config)
|
||||
{
|
||||
$defaults = ['allow_redirects' => \YoastSEO_Vendor\GuzzleHttp\RedirectMiddleware::$defaultSettings, 'http_errors' => \true, 'decode_content' => \true, 'verify' => \true, 'cookies' => \false, 'idn_conversion' => \false];
|
||||
// Use the standard Linux HTTP_PROXY and HTTPS_PROXY if set.
|
||||
// We can only trust the HTTP_PROXY environment variable in a CLI
|
||||
// process due to the fact that PHP has no reliable mechanism to
|
||||
// get environment variables that start with "HTTP_".
|
||||
if (\PHP_SAPI === 'cli' && ($proxy = \YoastSEO_Vendor\GuzzleHttp\Utils::getenv('HTTP_PROXY'))) {
|
||||
$defaults['proxy']['http'] = $proxy;
|
||||
if (\php_sapi_name() === 'cli' && \getenv('HTTP_PROXY')) {
|
||||
$defaults['proxy']['http'] = \getenv('HTTP_PROXY');
|
||||
}
|
||||
if ($proxy = \YoastSEO_Vendor\GuzzleHttp\Utils::getenv('HTTPS_PROXY')) {
|
||||
if ($proxy = \getenv('HTTPS_PROXY')) {
|
||||
$defaults['proxy']['https'] = $proxy;
|
||||
}
|
||||
if ($noProxy = \YoastSEO_Vendor\GuzzleHttp\Utils::getenv('NO_PROXY')) {
|
||||
if ($noProxy = \getenv('NO_PROXY')) {
|
||||
$cleanedNoProxy = \str_replace(' ', '', $noProxy);
|
||||
$defaults['proxy']['no'] = \explode(',', $cleanedNoProxy);
|
||||
}
|
||||
@@ -219,7 +226,7 @@ class Client implements \YoastSEO_Vendor\GuzzleHttp\ClientInterface, \YoastSEO_V
|
||||
}
|
||||
// Add the default user-agent header.
|
||||
if (!isset($this->config['headers'])) {
|
||||
$this->config['headers'] = ['User-Agent' => \YoastSEO_Vendor\GuzzleHttp\Utils::defaultUserAgent()];
|
||||
$this->config['headers'] = ['User-Agent' => default_user_agent()];
|
||||
} else {
|
||||
// Add the User-Agent header if one was not already set.
|
||||
foreach (\array_keys($this->config['headers']) as $name) {
|
||||
@@ -227,15 +234,17 @@ class Client implements \YoastSEO_Vendor\GuzzleHttp\ClientInterface, \YoastSEO_V
|
||||
return;
|
||||
}
|
||||
}
|
||||
$this->config['headers']['User-Agent'] = \YoastSEO_Vendor\GuzzleHttp\Utils::defaultUserAgent();
|
||||
$this->config['headers']['User-Agent'] = default_user_agent();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Merges default options into the array.
|
||||
*
|
||||
* @param array $options Options to modify by reference
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function prepareDefaults(array $options) : array
|
||||
private function prepareDefaults(array $options)
|
||||
{
|
||||
$defaults = $this->config;
|
||||
if (!empty($defaults['headers'])) {
|
||||
@@ -251,7 +260,7 @@ class Client implements \YoastSEO_Vendor\GuzzleHttp\ClientInterface, \YoastSEO_V
|
||||
$defaults['_conditional'] = [];
|
||||
unset($options['headers']);
|
||||
} elseif (!\is_array($options['headers'])) {
|
||||
throw new \YoastSEO_Vendor\GuzzleHttp\Exception\InvalidArgumentException('headers must be an array');
|
||||
throw new \InvalidArgumentException('headers must be an array');
|
||||
}
|
||||
}
|
||||
// Shallow merge defaults underneath options.
|
||||
@@ -271,39 +280,53 @@ class Client implements \YoastSEO_Vendor\GuzzleHttp\ClientInterface, \YoastSEO_V
|
||||
* as-is without merging in default options.
|
||||
*
|
||||
* @param array $options See \GuzzleHttp\RequestOptions.
|
||||
*
|
||||
* @return Promise\PromiseInterface
|
||||
*/
|
||||
private function transfer(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
|
||||
private function transfer(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options)
|
||||
{
|
||||
// save_to -> sink
|
||||
if (isset($options['save_to'])) {
|
||||
$options['sink'] = $options['save_to'];
|
||||
unset($options['save_to']);
|
||||
}
|
||||
// exceptions -> http_errors
|
||||
if (isset($options['exceptions'])) {
|
||||
$options['http_errors'] = $options['exceptions'];
|
||||
unset($options['exceptions']);
|
||||
}
|
||||
$request = $this->applyOptions($request, $options);
|
||||
/** @var HandlerStack $handler */
|
||||
$handler = $options['handler'];
|
||||
try {
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Promise\Create::promiseFor($handler($request, $options));
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Promise\promise_for($handler($request, $options));
|
||||
} catch (\Exception $e) {
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Promise\Create::rejectionFor($e);
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Promise\rejection_for($e);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Applies the array of request options to a request.
|
||||
*
|
||||
* @param RequestInterface $request
|
||||
* @param array $options
|
||||
*
|
||||
* @return RequestInterface
|
||||
*/
|
||||
private function applyOptions(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array &$options) : \YoastSEO_Vendor\Psr\Http\Message\RequestInterface
|
||||
private function applyOptions(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array &$options)
|
||||
{
|
||||
$modify = ['set_headers' => []];
|
||||
if (isset($options['headers'])) {
|
||||
if (\array_keys($options['headers']) === \range(0, \count($options['headers']) - 1)) {
|
||||
throw new \YoastSEO_Vendor\GuzzleHttp\Exception\InvalidArgumentException('The headers array must have header name as keys.');
|
||||
}
|
||||
$modify['set_headers'] = $options['headers'];
|
||||
unset($options['headers']);
|
||||
}
|
||||
if (isset($options['form_params'])) {
|
||||
if (isset($options['multipart'])) {
|
||||
throw new \YoastSEO_Vendor\GuzzleHttp\Exception\InvalidArgumentException('You cannot use ' . 'form_params and multipart at the same time. Use the ' . 'form_params option if you want to send application/' . 'x-www-form-urlencoded requests, and the multipart ' . 'option to send multipart/form-data requests.');
|
||||
throw new \InvalidArgumentException('You cannot use ' . 'form_params and multipart at the same time. Use the ' . 'form_params option if you want to send application/' . 'x-www-form-urlencoded requests, and the multipart ' . 'option to send multipart/form-data requests.');
|
||||
}
|
||||
$options['body'] = \http_build_query($options['form_params'], '', '&');
|
||||
unset($options['form_params']);
|
||||
// Ensure that we don't have the header in different case and set the new value.
|
||||
$options['_conditional'] = \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::caselessRemove(['Content-Type'], $options['_conditional']);
|
||||
$options['_conditional'] = \YoastSEO_Vendor\GuzzleHttp\Psr7\_caseless_remove(['Content-Type'], $options['_conditional']);
|
||||
$options['_conditional']['Content-Type'] = 'application/x-www-form-urlencoded';
|
||||
}
|
||||
if (isset($options['multipart'])) {
|
||||
@@ -311,22 +334,22 @@ class Client implements \YoastSEO_Vendor\GuzzleHttp\ClientInterface, \YoastSEO_V
|
||||
unset($options['multipart']);
|
||||
}
|
||||
if (isset($options['json'])) {
|
||||
$options['body'] = \YoastSEO_Vendor\GuzzleHttp\Utils::jsonEncode($options['json']);
|
||||
$options['body'] = \YoastSEO_Vendor\GuzzleHttp\json_encode($options['json']);
|
||||
unset($options['json']);
|
||||
// Ensure that we don't have the header in different case and set the new value.
|
||||
$options['_conditional'] = \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::caselessRemove(['Content-Type'], $options['_conditional']);
|
||||
$options['_conditional'] = \YoastSEO_Vendor\GuzzleHttp\Psr7\_caseless_remove(['Content-Type'], $options['_conditional']);
|
||||
$options['_conditional']['Content-Type'] = 'application/json';
|
||||
}
|
||||
if (!empty($options['decode_content']) && $options['decode_content'] !== \true) {
|
||||
// Ensure that we don't have the header in different case and set the new value.
|
||||
$options['_conditional'] = \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::caselessRemove(['Accept-Encoding'], $options['_conditional']);
|
||||
$options['_conditional'] = \YoastSEO_Vendor\GuzzleHttp\Psr7\_caseless_remove(['Accept-Encoding'], $options['_conditional']);
|
||||
$modify['set_headers']['Accept-Encoding'] = $options['decode_content'];
|
||||
}
|
||||
if (isset($options['body'])) {
|
||||
if (\is_array($options['body'])) {
|
||||
throw $this->invalidBody();
|
||||
$this->invalidBody();
|
||||
}
|
||||
$modify['body'] = \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::streamFor($options['body']);
|
||||
$modify['body'] = \YoastSEO_Vendor\GuzzleHttp\Psr7\stream_for($options['body']);
|
||||
unset($options['body']);
|
||||
}
|
||||
if (!empty($options['auth']) && \is_array($options['auth'])) {
|
||||
@@ -335,7 +358,7 @@ class Client implements \YoastSEO_Vendor\GuzzleHttp\ClientInterface, \YoastSEO_V
|
||||
switch ($type) {
|
||||
case 'basic':
|
||||
// Ensure that we don't have the header in different case and set the new value.
|
||||
$modify['set_headers'] = \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::caselessRemove(['Authorization'], $modify['set_headers']);
|
||||
$modify['set_headers'] = \YoastSEO_Vendor\GuzzleHttp\Psr7\_caseless_remove(['Authorization'], $modify['set_headers']);
|
||||
$modify['set_headers']['Authorization'] = 'Basic ' . \base64_encode("{$value[0]}:{$value[1]}");
|
||||
break;
|
||||
case 'digest':
|
||||
@@ -352,10 +375,10 @@ class Client implements \YoastSEO_Vendor\GuzzleHttp\ClientInterface, \YoastSEO_V
|
||||
if (isset($options['query'])) {
|
||||
$value = $options['query'];
|
||||
if (\is_array($value)) {
|
||||
$value = \http_build_query($value, '', '&', \PHP_QUERY_RFC3986);
|
||||
$value = \http_build_query($value, null, '&', \PHP_QUERY_RFC3986);
|
||||
}
|
||||
if (!\is_string($value)) {
|
||||
throw new \YoastSEO_Vendor\GuzzleHttp\Exception\InvalidArgumentException('query must be a string or array');
|
||||
throw new \InvalidArgumentException('query must be a string or array');
|
||||
}
|
||||
$modify['query'] = $value;
|
||||
unset($options['query']);
|
||||
@@ -364,17 +387,14 @@ class Client implements \YoastSEO_Vendor\GuzzleHttp\ClientInterface, \YoastSEO_V
|
||||
if (isset($options['sink'])) {
|
||||
// TODO: Add more sink validation?
|
||||
if (\is_bool($options['sink'])) {
|
||||
throw new \YoastSEO_Vendor\GuzzleHttp\Exception\InvalidArgumentException('sink must not be a boolean');
|
||||
throw new \InvalidArgumentException('sink must not be a boolean');
|
||||
}
|
||||
}
|
||||
if (isset($options['version'])) {
|
||||
$modify['version'] = $options['version'];
|
||||
}
|
||||
$request = \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::modifyRequest($request, $modify);
|
||||
$request = \YoastSEO_Vendor\GuzzleHttp\Psr7\modify_request($request, $modify);
|
||||
if ($request->getBody() instanceof \YoastSEO_Vendor\GuzzleHttp\Psr7\MultipartStream) {
|
||||
// Use a multipart/form-data POST if a Content-Type is not set.
|
||||
// Ensure that we don't have the header in different case and set the new value.
|
||||
$options['_conditional'] = \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::caselessRemove(['Content-Type'], $options['_conditional']);
|
||||
$options['_conditional'] = \YoastSEO_Vendor\GuzzleHttp\Psr7\_caseless_remove(['Content-Type'], $options['_conditional']);
|
||||
$options['_conditional']['Content-Type'] = 'multipart/form-data; boundary=' . $request->getBody()->getBoundary();
|
||||
}
|
||||
// Merge in conditional headers if they are not present.
|
||||
@@ -386,17 +406,19 @@ class Client implements \YoastSEO_Vendor\GuzzleHttp\ClientInterface, \YoastSEO_V
|
||||
$modify['set_headers'][$k] = $v;
|
||||
}
|
||||
}
|
||||
$request = \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::modifyRequest($request, $modify);
|
||||
$request = \YoastSEO_Vendor\GuzzleHttp\Psr7\modify_request($request, $modify);
|
||||
// Don't pass this internal value along to middleware/handlers.
|
||||
unset($options['_conditional']);
|
||||
}
|
||||
return $request;
|
||||
}
|
||||
/**
|
||||
* Return an InvalidArgumentException with pre-set message.
|
||||
* Throw Exception with pre-set message.
|
||||
* @return void
|
||||
* @throws \InvalidArgumentException Invalid body.
|
||||
*/
|
||||
private function invalidBody() : \YoastSEO_Vendor\GuzzleHttp\Exception\InvalidArgumentException
|
||||
private function invalidBody()
|
||||
{
|
||||
return new \YoastSEO_Vendor\GuzzleHttp\Exception\InvalidArgumentException('Passing in the "body" request ' . 'option as an array to send a request is not supported. ' . 'Please use the "form_params" request option to send a ' . 'application/x-www-form-urlencoded request, or the "multipart" ' . 'request option to send a multipart/form-data request.');
|
||||
throw new \InvalidArgumentException('Passing in the "body" request ' . 'option as an array to send a POST request has been deprecated. ' . 'Please use the "form_params" request option to send a ' . 'application/x-www-form-urlencoded request, or the "multipart" ' . 'request option to send a multipart/form-data request.');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,9 +13,9 @@ use YoastSEO_Vendor\Psr\Http\Message\UriInterface;
|
||||
interface ClientInterface
|
||||
{
|
||||
/**
|
||||
* The Guzzle major version.
|
||||
* @deprecated Will be removed in Guzzle 7.0.0
|
||||
*/
|
||||
public const MAJOR_VERSION = 7;
|
||||
const VERSION = '6.5.5';
|
||||
/**
|
||||
* Send an HTTP request.
|
||||
*
|
||||
@@ -23,17 +23,20 @@ interface ClientInterface
|
||||
* @param array $options Request options to apply to the given
|
||||
* request and to the transfer.
|
||||
*
|
||||
* @return ResponseInterface
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function send(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options = []) : \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface;
|
||||
public function send(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options = []);
|
||||
/**
|
||||
* Asynchronously send an HTTP request.
|
||||
*
|
||||
* @param RequestInterface $request Request to send
|
||||
* @param array $options Request options to apply to the given
|
||||
* request and to the transfer.
|
||||
*
|
||||
* @return PromiseInterface
|
||||
*/
|
||||
public function sendAsync(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options = []) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface;
|
||||
public function sendAsync(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options = []);
|
||||
/**
|
||||
* Create and send an HTTP request.
|
||||
*
|
||||
@@ -45,9 +48,10 @@ interface ClientInterface
|
||||
* @param string|UriInterface $uri URI object or string.
|
||||
* @param array $options Request options to apply.
|
||||
*
|
||||
* @return ResponseInterface
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function request(string $method, $uri, array $options = []) : \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface;
|
||||
public function request($method, $uri, array $options = []);
|
||||
/**
|
||||
* Create and send an asynchronous HTTP request.
|
||||
*
|
||||
@@ -59,8 +63,10 @@ interface ClientInterface
|
||||
* @param string $method HTTP method
|
||||
* @param string|UriInterface $uri URI object or string.
|
||||
* @param array $options Request options to apply.
|
||||
*
|
||||
* @return PromiseInterface
|
||||
*/
|
||||
public function requestAsync(string $method, $uri, array $options = []) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface;
|
||||
public function requestAsync($method, $uri, array $options = []);
|
||||
/**
|
||||
* Get a client configuration option.
|
||||
*
|
||||
@@ -71,8 +77,6 @@ interface ClientInterface
|
||||
* @param string|null $option The config option to retrieve.
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @deprecated ClientInterface::getConfig will be removed in guzzlehttp/guzzle:8.0.
|
||||
*/
|
||||
public function getConfig(string $option = null);
|
||||
public function getConfig($option = null);
|
||||
}
|
||||
|
||||
@@ -1,227 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace YoastSEO_Vendor\GuzzleHttp;
|
||||
|
||||
use YoastSEO_Vendor\GuzzleHttp\Exception\GuzzleException;
|
||||
use YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface;
|
||||
use YoastSEO_Vendor\Psr\Http\Message\ResponseInterface;
|
||||
use YoastSEO_Vendor\Psr\Http\Message\UriInterface;
|
||||
/**
|
||||
* Client interface for sending HTTP requests.
|
||||
*/
|
||||
trait ClientTrait
|
||||
{
|
||||
/**
|
||||
* Create and send an HTTP request.
|
||||
*
|
||||
* Use an absolute path to override the base path of the client, or a
|
||||
* relative path to append to the base path of the client. The URL can
|
||||
* contain the query string as well.
|
||||
*
|
||||
* @param string $method HTTP method.
|
||||
* @param string|UriInterface $uri URI object or string.
|
||||
* @param array $options Request options to apply.
|
||||
*
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public abstract function request(string $method, $uri, array $options = []) : \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface;
|
||||
/**
|
||||
* Create and send an HTTP GET request.
|
||||
*
|
||||
* Use an absolute path to override the base path of the client, or a
|
||||
* relative path to append to the base path of the client. The URL can
|
||||
* contain the query string as well.
|
||||
*
|
||||
* @param string|UriInterface $uri URI object or string.
|
||||
* @param array $options Request options to apply.
|
||||
*
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function get($uri, array $options = []) : \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface
|
||||
{
|
||||
return $this->request('GET', $uri, $options);
|
||||
}
|
||||
/**
|
||||
* Create and send an HTTP HEAD request.
|
||||
*
|
||||
* Use an absolute path to override the base path of the client, or a
|
||||
* relative path to append to the base path of the client. The URL can
|
||||
* contain the query string as well.
|
||||
*
|
||||
* @param string|UriInterface $uri URI object or string.
|
||||
* @param array $options Request options to apply.
|
||||
*
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function head($uri, array $options = []) : \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface
|
||||
{
|
||||
return $this->request('HEAD', $uri, $options);
|
||||
}
|
||||
/**
|
||||
* Create and send an HTTP PUT request.
|
||||
*
|
||||
* Use an absolute path to override the base path of the client, or a
|
||||
* relative path to append to the base path of the client. The URL can
|
||||
* contain the query string as well.
|
||||
*
|
||||
* @param string|UriInterface $uri URI object or string.
|
||||
* @param array $options Request options to apply.
|
||||
*
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function put($uri, array $options = []) : \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface
|
||||
{
|
||||
return $this->request('PUT', $uri, $options);
|
||||
}
|
||||
/**
|
||||
* Create and send an HTTP POST request.
|
||||
*
|
||||
* Use an absolute path to override the base path of the client, or a
|
||||
* relative path to append to the base path of the client. The URL can
|
||||
* contain the query string as well.
|
||||
*
|
||||
* @param string|UriInterface $uri URI object or string.
|
||||
* @param array $options Request options to apply.
|
||||
*
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function post($uri, array $options = []) : \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface
|
||||
{
|
||||
return $this->request('POST', $uri, $options);
|
||||
}
|
||||
/**
|
||||
* Create and send an HTTP PATCH request.
|
||||
*
|
||||
* Use an absolute path to override the base path of the client, or a
|
||||
* relative path to append to the base path of the client. The URL can
|
||||
* contain the query string as well.
|
||||
*
|
||||
* @param string|UriInterface $uri URI object or string.
|
||||
* @param array $options Request options to apply.
|
||||
*
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function patch($uri, array $options = []) : \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface
|
||||
{
|
||||
return $this->request('PATCH', $uri, $options);
|
||||
}
|
||||
/**
|
||||
* Create and send an HTTP DELETE request.
|
||||
*
|
||||
* Use an absolute path to override the base path of the client, or a
|
||||
* relative path to append to the base path of the client. The URL can
|
||||
* contain the query string as well.
|
||||
*
|
||||
* @param string|UriInterface $uri URI object or string.
|
||||
* @param array $options Request options to apply.
|
||||
*
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function delete($uri, array $options = []) : \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface
|
||||
{
|
||||
return $this->request('DELETE', $uri, $options);
|
||||
}
|
||||
/**
|
||||
* Create and send an asynchronous HTTP request.
|
||||
*
|
||||
* Use an absolute path to override the base path of the client, or a
|
||||
* relative path to append to the base path of the client. The URL can
|
||||
* contain the query string as well. Use an array to provide a URL
|
||||
* template and additional variables to use in the URL template expansion.
|
||||
*
|
||||
* @param string $method HTTP method
|
||||
* @param string|UriInterface $uri URI object or string.
|
||||
* @param array $options Request options to apply.
|
||||
*/
|
||||
public abstract function requestAsync(string $method, $uri, array $options = []) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface;
|
||||
/**
|
||||
* Create and send an asynchronous HTTP GET request.
|
||||
*
|
||||
* Use an absolute path to override the base path of the client, or a
|
||||
* relative path to append to the base path of the client. The URL can
|
||||
* contain the query string as well. Use an array to provide a URL
|
||||
* template and additional variables to use in the URL template expansion.
|
||||
*
|
||||
* @param string|UriInterface $uri URI object or string.
|
||||
* @param array $options Request options to apply.
|
||||
*/
|
||||
public function getAsync($uri, array $options = []) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
|
||||
{
|
||||
return $this->requestAsync('GET', $uri, $options);
|
||||
}
|
||||
/**
|
||||
* Create and send an asynchronous HTTP HEAD request.
|
||||
*
|
||||
* Use an absolute path to override the base path of the client, or a
|
||||
* relative path to append to the base path of the client. The URL can
|
||||
* contain the query string as well. Use an array to provide a URL
|
||||
* template and additional variables to use in the URL template expansion.
|
||||
*
|
||||
* @param string|UriInterface $uri URI object or string.
|
||||
* @param array $options Request options to apply.
|
||||
*/
|
||||
public function headAsync($uri, array $options = []) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
|
||||
{
|
||||
return $this->requestAsync('HEAD', $uri, $options);
|
||||
}
|
||||
/**
|
||||
* Create and send an asynchronous HTTP PUT request.
|
||||
*
|
||||
* Use an absolute path to override the base path of the client, or a
|
||||
* relative path to append to the base path of the client. The URL can
|
||||
* contain the query string as well. Use an array to provide a URL
|
||||
* template and additional variables to use in the URL template expansion.
|
||||
*
|
||||
* @param string|UriInterface $uri URI object or string.
|
||||
* @param array $options Request options to apply.
|
||||
*/
|
||||
public function putAsync($uri, array $options = []) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
|
||||
{
|
||||
return $this->requestAsync('PUT', $uri, $options);
|
||||
}
|
||||
/**
|
||||
* Create and send an asynchronous HTTP POST request.
|
||||
*
|
||||
* Use an absolute path to override the base path of the client, or a
|
||||
* relative path to append to the base path of the client. The URL can
|
||||
* contain the query string as well. Use an array to provide a URL
|
||||
* template and additional variables to use in the URL template expansion.
|
||||
*
|
||||
* @param string|UriInterface $uri URI object or string.
|
||||
* @param array $options Request options to apply.
|
||||
*/
|
||||
public function postAsync($uri, array $options = []) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
|
||||
{
|
||||
return $this->requestAsync('POST', $uri, $options);
|
||||
}
|
||||
/**
|
||||
* Create and send an asynchronous HTTP PATCH request.
|
||||
*
|
||||
* Use an absolute path to override the base path of the client, or a
|
||||
* relative path to append to the base path of the client. The URL can
|
||||
* contain the query string as well. Use an array to provide a URL
|
||||
* template and additional variables to use in the URL template expansion.
|
||||
*
|
||||
* @param string|UriInterface $uri URI object or string.
|
||||
* @param array $options Request options to apply.
|
||||
*/
|
||||
public function patchAsync($uri, array $options = []) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
|
||||
{
|
||||
return $this->requestAsync('PATCH', $uri, $options);
|
||||
}
|
||||
/**
|
||||
* Create and send an asynchronous HTTP DELETE request.
|
||||
*
|
||||
* Use an absolute path to override the base path of the client, or a
|
||||
* relative path to append to the base path of the client. The URL can
|
||||
* contain the query string as well. Use an array to provide a URL
|
||||
* template and additional variables to use in the URL template expansion.
|
||||
*
|
||||
* @param string|UriInterface $uri URI object or string.
|
||||
* @param array $options Request options to apply.
|
||||
*/
|
||||
public function deleteAsync($uri, array $options = []) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
|
||||
{
|
||||
return $this->requestAsync('DELETE', $uri, $options);
|
||||
}
|
||||
}
|
||||
@@ -9,22 +9,18 @@ use YoastSEO_Vendor\Psr\Http\Message\ResponseInterface;
|
||||
*/
|
||||
class CookieJar implements \YoastSEO_Vendor\GuzzleHttp\Cookie\CookieJarInterface
|
||||
{
|
||||
/**
|
||||
* @var SetCookie[] Loaded cookie data
|
||||
*/
|
||||
/** @var SetCookie[] Loaded cookie data */
|
||||
private $cookies = [];
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
/** @var bool */
|
||||
private $strictMode;
|
||||
/**
|
||||
* @param bool $strictMode Set to true to throw exceptions when invalid
|
||||
* @param bool $strictMode Set to true to throw exceptions when invalid
|
||||
* cookies are added to the cookie jar.
|
||||
* @param array $cookieArray Array of SetCookie objects or a hash of
|
||||
* arrays that can be used with the SetCookie
|
||||
* constructor
|
||||
*/
|
||||
public function __construct(bool $strictMode = \false, array $cookieArray = [])
|
||||
public function __construct($strictMode = \false, $cookieArray = [])
|
||||
{
|
||||
$this->strictMode = $strictMode;
|
||||
foreach ($cookieArray as $cookie) {
|
||||
@@ -39,8 +35,10 @@ class CookieJar implements \YoastSEO_Vendor\GuzzleHttp\Cookie\CookieJarInterface
|
||||
*
|
||||
* @param array $cookies Cookies to create the jar from
|
||||
* @param string $domain Domain to set the cookies to
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public static function fromArray(array $cookies, string $domain) : self
|
||||
public static function fromArray(array $cookies, $domain)
|
||||
{
|
||||
$cookieJar = new self();
|
||||
foreach ($cookies as $name => $value) {
|
||||
@@ -48,14 +46,22 @@ class CookieJar implements \YoastSEO_Vendor\GuzzleHttp\Cookie\CookieJarInterface
|
||||
}
|
||||
return $cookieJar;
|
||||
}
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
public static function getCookieValue($value)
|
||||
{
|
||||
return $value;
|
||||
}
|
||||
/**
|
||||
* Evaluate if this cookie should be persisted to storage
|
||||
* that survives between requests.
|
||||
*
|
||||
* @param SetCookie $cookie Being evaluated.
|
||||
* @param bool $allowSessionCookies If we should persist session cookies
|
||||
* @param SetCookie $cookie Being evaluated.
|
||||
* @param bool $allowSessionCookies If we should persist session cookies
|
||||
* @return bool
|
||||
*/
|
||||
public static function shouldPersist(\YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie $cookie, bool $allowSessionCookies = \false) : bool
|
||||
public static function shouldPersist(\YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie $cookie, $allowSessionCookies = \false)
|
||||
{
|
||||
if ($cookie->getExpires() || $allowSessionCookies) {
|
||||
if (!$cookie->getDiscard()) {
|
||||
@@ -68,11 +74,14 @@ class CookieJar implements \YoastSEO_Vendor\GuzzleHttp\Cookie\CookieJarInterface
|
||||
* Finds and returns the cookie based on the name
|
||||
*
|
||||
* @param string $name cookie name to search for
|
||||
*
|
||||
* @return SetCookie|null cookie that was found or null if not found
|
||||
*/
|
||||
public function getCookieByName(string $name) : ?\YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie
|
||||
public function getCookieByName($name)
|
||||
{
|
||||
// don't allow a non string name
|
||||
if ($name === null || !\is_scalar($name)) {
|
||||
return null;
|
||||
}
|
||||
foreach ($this->cookies as $cookie) {
|
||||
if ($cookie->getName() !== null && \strcasecmp($cookie->getName(), $name) === 0) {
|
||||
return $cookie;
|
||||
@@ -80,38 +89,38 @@ class CookieJar implements \YoastSEO_Vendor\GuzzleHttp\Cookie\CookieJarInterface
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public function toArray() : array
|
||||
public function toArray()
|
||||
{
|
||||
return \array_map(static function (\YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie $cookie) : array {
|
||||
return \array_map(function (\YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie $cookie) {
|
||||
return $cookie->toArray();
|
||||
}, $this->getIterator()->getArrayCopy());
|
||||
}
|
||||
public function clear(string $domain = null, string $path = null, string $name = null) : void
|
||||
public function clear($domain = null, $path = null, $name = null)
|
||||
{
|
||||
if (!$domain) {
|
||||
$this->cookies = [];
|
||||
return;
|
||||
} elseif (!$path) {
|
||||
$this->cookies = \array_filter($this->cookies, static function (\YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie $cookie) use($domain) : bool {
|
||||
$this->cookies = \array_filter($this->cookies, function (\YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie $cookie) use($domain) {
|
||||
return !$cookie->matchesDomain($domain);
|
||||
});
|
||||
} elseif (!$name) {
|
||||
$this->cookies = \array_filter($this->cookies, static function (\YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie $cookie) use($path, $domain) : bool {
|
||||
$this->cookies = \array_filter($this->cookies, function (\YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie $cookie) use($path, $domain) {
|
||||
return !($cookie->matchesPath($path) && $cookie->matchesDomain($domain));
|
||||
});
|
||||
} else {
|
||||
$this->cookies = \array_filter($this->cookies, static function (\YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie $cookie) use($path, $domain, $name) {
|
||||
$this->cookies = \array_filter($this->cookies, function (\YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie $cookie) use($path, $domain, $name) {
|
||||
return !($cookie->getName() == $name && $cookie->matchesPath($path) && $cookie->matchesDomain($domain));
|
||||
});
|
||||
}
|
||||
}
|
||||
public function clearSessionCookies() : void
|
||||
public function clearSessionCookies()
|
||||
{
|
||||
$this->cookies = \array_filter($this->cookies, static function (\YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie $cookie) : bool {
|
||||
$this->cookies = \array_filter($this->cookies, function (\YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie $cookie) {
|
||||
return !$cookie->getDiscard() && $cookie->getExpires();
|
||||
});
|
||||
}
|
||||
public function setCookie(\YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie $cookie) : bool
|
||||
public function setCookie(\YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie $cookie)
|
||||
{
|
||||
// If the name string is empty (but not 0), ignore the set-cookie
|
||||
// string entirely.
|
||||
@@ -124,9 +133,10 @@ class CookieJar implements \YoastSEO_Vendor\GuzzleHttp\Cookie\CookieJarInterface
|
||||
if ($result !== \true) {
|
||||
if ($this->strictMode) {
|
||||
throw new \RuntimeException('Invalid cookie: ' . $result);
|
||||
} else {
|
||||
$this->removeCookieIfEmpty($cookie);
|
||||
return \false;
|
||||
}
|
||||
$this->removeCookieIfEmpty($cookie);
|
||||
return \false;
|
||||
}
|
||||
// Resolve conflicts with previously set cookies
|
||||
foreach ($this->cookies as $i => $c) {
|
||||
@@ -158,18 +168,15 @@ class CookieJar implements \YoastSEO_Vendor\GuzzleHttp\Cookie\CookieJarInterface
|
||||
$this->cookies[] = $cookie;
|
||||
return \true;
|
||||
}
|
||||
public function count() : int
|
||||
public function count()
|
||||
{
|
||||
return \count($this->cookies);
|
||||
}
|
||||
/**
|
||||
* @return \ArrayIterator<int, SetCookie>
|
||||
*/
|
||||
public function getIterator() : \ArrayIterator
|
||||
public function getIterator()
|
||||
{
|
||||
return new \ArrayIterator(\array_values($this->cookies));
|
||||
}
|
||||
public function extractCookies(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response) : void
|
||||
public function extractCookies(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response)
|
||||
{
|
||||
if ($cookieHeader = $response->getHeader('Set-Cookie')) {
|
||||
foreach ($cookieHeader as $cookie) {
|
||||
@@ -192,9 +199,12 @@ class CookieJar implements \YoastSEO_Vendor\GuzzleHttp\Cookie\CookieJarInterface
|
||||
/**
|
||||
* Computes cookie path following RFC 6265 section 5.1.4
|
||||
*
|
||||
* @see https://tools.ietf.org/html/rfc6265#section-5.1.4
|
||||
* @link https://tools.ietf.org/html/rfc6265#section-5.1.4
|
||||
*
|
||||
* @param RequestInterface $request
|
||||
* @return string
|
||||
*/
|
||||
private function getCookiePathFromRequest(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request) : string
|
||||
private function getCookiePathFromRequest(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request)
|
||||
{
|
||||
$uriPath = $request->getUri()->getPath();
|
||||
if ('' === $uriPath) {
|
||||
@@ -206,13 +216,12 @@ class CookieJar implements \YoastSEO_Vendor\GuzzleHttp\Cookie\CookieJarInterface
|
||||
if ('/' === $uriPath) {
|
||||
return '/';
|
||||
}
|
||||
$lastSlashPos = \strrpos($uriPath, '/');
|
||||
if (0 === $lastSlashPos || \false === $lastSlashPos) {
|
||||
if (0 === ($lastSlashPos = \strrpos($uriPath, '/'))) {
|
||||
return '/';
|
||||
}
|
||||
return \substr($uriPath, 0, $lastSlashPos);
|
||||
}
|
||||
public function withCookieHeader(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request) : \YoastSEO_Vendor\Psr\Http\Message\RequestInterface
|
||||
public function withCookieHeader(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request)
|
||||
{
|
||||
$values = [];
|
||||
$uri = $request->getUri();
|
||||
@@ -229,8 +238,10 @@ class CookieJar implements \YoastSEO_Vendor\GuzzleHttp\Cookie\CookieJarInterface
|
||||
/**
|
||||
* If a cookie already exists and the server asks to set it again with a
|
||||
* null value, the cookie must be deleted.
|
||||
*
|
||||
* @param SetCookie $cookie
|
||||
*/
|
||||
private function removeCookieIfEmpty(\YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie $cookie) : void
|
||||
private function removeCookieIfEmpty(\YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie $cookie)
|
||||
{
|
||||
$cookieValue = $cookie->getValue();
|
||||
if ($cookieValue === null || $cookieValue === '') {
|
||||
|
||||
@@ -12,9 +12,7 @@ use YoastSEO_Vendor\Psr\Http\Message\ResponseInterface;
|
||||
* necessary. Subclasses are also responsible for storing and retrieving
|
||||
* cookies from a file, database, etc.
|
||||
*
|
||||
* @see https://docs.python.org/2/library/cookielib.html Inspiration
|
||||
*
|
||||
* @extends \IteratorAggregate<SetCookie>
|
||||
* @link http://docs.python.org/2/library/cookielib.html Inspiration
|
||||
*/
|
||||
interface CookieJarInterface extends \Countable, \IteratorAggregate
|
||||
{
|
||||
@@ -28,14 +26,14 @@ interface CookieJarInterface extends \Countable, \IteratorAggregate
|
||||
*
|
||||
* @return RequestInterface returns the modified request.
|
||||
*/
|
||||
public function withCookieHeader(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request) : \YoastSEO_Vendor\Psr\Http\Message\RequestInterface;
|
||||
public function withCookieHeader(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request);
|
||||
/**
|
||||
* Extract cookies from an HTTP response and store them in the CookieJar.
|
||||
*
|
||||
* @param RequestInterface $request Request that was sent
|
||||
* @param ResponseInterface $response Response that was received
|
||||
*/
|
||||
public function extractCookies(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response) : void;
|
||||
public function extractCookies(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response);
|
||||
/**
|
||||
* Sets a cookie in the cookie jar.
|
||||
*
|
||||
@@ -43,7 +41,7 @@ interface CookieJarInterface extends \Countable, \IteratorAggregate
|
||||
*
|
||||
* @return bool Returns true on success or false on failure
|
||||
*/
|
||||
public function setCookie(\YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie $cookie) : bool;
|
||||
public function setCookie(\YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie $cookie);
|
||||
/**
|
||||
* Remove cookies currently held in the cookie jar.
|
||||
*
|
||||
@@ -57,8 +55,10 @@ interface CookieJarInterface extends \Countable, \IteratorAggregate
|
||||
* @param string|null $domain Clears cookies matching a domain
|
||||
* @param string|null $path Clears cookies matching a domain and path
|
||||
* @param string|null $name Clears cookies matching a domain, path, and name
|
||||
*
|
||||
* @return CookieJarInterface
|
||||
*/
|
||||
public function clear(string $domain = null, string $path = null, string $name = null) : void;
|
||||
public function clear($domain = null, $path = null, $name = null);
|
||||
/**
|
||||
* Discard all sessions cookies.
|
||||
*
|
||||
@@ -66,9 +66,11 @@ interface CookieJarInterface extends \Countable, \IteratorAggregate
|
||||
* field set to true. To be called when the user agent shuts down according
|
||||
* to RFC 2965.
|
||||
*/
|
||||
public function clearSessionCookies() : void;
|
||||
public function clearSessionCookies();
|
||||
/**
|
||||
* Converts the cookie jar to an array.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function toArray() : array;
|
||||
public function toArray();
|
||||
}
|
||||
|
||||
@@ -2,30 +2,25 @@
|
||||
|
||||
namespace YoastSEO_Vendor\GuzzleHttp\Cookie;
|
||||
|
||||
use YoastSEO_Vendor\GuzzleHttp\Utils;
|
||||
/**
|
||||
* Persists non-session cookies using a JSON formatted file
|
||||
*/
|
||||
class FileCookieJar extends \YoastSEO_Vendor\GuzzleHttp\Cookie\CookieJar
|
||||
{
|
||||
/**
|
||||
* @var string filename
|
||||
*/
|
||||
/** @var string filename */
|
||||
private $filename;
|
||||
/**
|
||||
* @var bool Control whether to persist session cookies or not.
|
||||
*/
|
||||
/** @var bool Control whether to persist session cookies or not. */
|
||||
private $storeSessionCookies;
|
||||
/**
|
||||
* Create a new FileCookieJar object
|
||||
*
|
||||
* @param string $cookieFile File to store the cookie data
|
||||
* @param bool $storeSessionCookies Set to true to store session cookies
|
||||
* in the cookie jar.
|
||||
* @param string $cookieFile File to store the cookie data
|
||||
* @param bool $storeSessionCookies Set to true to store session cookies
|
||||
* in the cookie jar.
|
||||
*
|
||||
* @throws \RuntimeException if the file cannot be found or created
|
||||
*/
|
||||
public function __construct(string $cookieFile, bool $storeSessionCookies = \false)
|
||||
public function __construct($cookieFile, $storeSessionCookies = \false)
|
||||
{
|
||||
parent::__construct();
|
||||
$this->filename = $cookieFile;
|
||||
@@ -45,19 +40,18 @@ class FileCookieJar extends \YoastSEO_Vendor\GuzzleHttp\Cookie\CookieJar
|
||||
* Saves the cookies to a file.
|
||||
*
|
||||
* @param string $filename File to save
|
||||
*
|
||||
* @throws \RuntimeException if the file cannot be found or created
|
||||
*/
|
||||
public function save(string $filename) : void
|
||||
public function save($filename)
|
||||
{
|
||||
$json = [];
|
||||
/** @var SetCookie $cookie */
|
||||
foreach ($this as $cookie) {
|
||||
/** @var SetCookie $cookie */
|
||||
if (\YoastSEO_Vendor\GuzzleHttp\Cookie\CookieJar::shouldPersist($cookie, $this->storeSessionCookies)) {
|
||||
$json[] = $cookie->toArray();
|
||||
}
|
||||
}
|
||||
$jsonStr = \YoastSEO_Vendor\GuzzleHttp\Utils::jsonEncode($json);
|
||||
$jsonStr = \YoastSEO_Vendor\GuzzleHttp\json_encode($json);
|
||||
if (\false === \file_put_contents($filename, $jsonStr, \LOCK_EX)) {
|
||||
throw new \RuntimeException("Unable to save file {$filename}");
|
||||
}
|
||||
@@ -68,24 +62,22 @@ class FileCookieJar extends \YoastSEO_Vendor\GuzzleHttp\Cookie\CookieJar
|
||||
* Old cookies are kept unless overwritten by newly loaded ones.
|
||||
*
|
||||
* @param string $filename Cookie file to load.
|
||||
*
|
||||
* @throws \RuntimeException if the file cannot be loaded.
|
||||
*/
|
||||
public function load(string $filename) : void
|
||||
public function load($filename)
|
||||
{
|
||||
$json = \file_get_contents($filename);
|
||||
if (\false === $json) {
|
||||
throw new \RuntimeException("Unable to load file {$filename}");
|
||||
}
|
||||
if ($json === '') {
|
||||
} elseif ($json === '') {
|
||||
return;
|
||||
}
|
||||
$data = \YoastSEO_Vendor\GuzzleHttp\Utils::jsonDecode($json, \true);
|
||||
$data = \YoastSEO_Vendor\GuzzleHttp\json_decode($json, \true);
|
||||
if (\is_array($data)) {
|
||||
foreach ($data as $cookie) {
|
||||
foreach (\json_decode($json, \true) as $cookie) {
|
||||
$this->setCookie(new \YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie($cookie));
|
||||
}
|
||||
} elseif (\is_scalar($data) && !empty($data)) {
|
||||
} elseif (\strlen($data)) {
|
||||
throw new \RuntimeException("Invalid cookie file: {$filename}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,23 +7,19 @@ namespace YoastSEO_Vendor\GuzzleHttp\Cookie;
|
||||
*/
|
||||
class SessionCookieJar extends \YoastSEO_Vendor\GuzzleHttp\Cookie\CookieJar
|
||||
{
|
||||
/**
|
||||
* @var string session key
|
||||
*/
|
||||
/** @var string session key */
|
||||
private $sessionKey;
|
||||
/**
|
||||
* @var bool Control whether to persist session cookies or not.
|
||||
*/
|
||||
/** @var bool Control whether to persist session cookies or not. */
|
||||
private $storeSessionCookies;
|
||||
/**
|
||||
* Create a new SessionCookieJar object
|
||||
*
|
||||
* @param string $sessionKey Session key name to store the cookie
|
||||
* data in session
|
||||
* @param bool $storeSessionCookies Set to true to store session cookies
|
||||
* in the cookie jar.
|
||||
* @param string $sessionKey Session key name to store the cookie
|
||||
* data in session
|
||||
* @param bool $storeSessionCookies Set to true to store session cookies
|
||||
* in the cookie jar.
|
||||
*/
|
||||
public function __construct(string $sessionKey, bool $storeSessionCookies = \false)
|
||||
public function __construct($sessionKey, $storeSessionCookies = \false)
|
||||
{
|
||||
parent::__construct();
|
||||
$this->sessionKey = $sessionKey;
|
||||
@@ -40,11 +36,11 @@ class SessionCookieJar extends \YoastSEO_Vendor\GuzzleHttp\Cookie\CookieJar
|
||||
/**
|
||||
* Save cookies to the client session
|
||||
*/
|
||||
public function save() : void
|
||||
public function save()
|
||||
{
|
||||
$json = [];
|
||||
/** @var SetCookie $cookie */
|
||||
foreach ($this as $cookie) {
|
||||
/** @var SetCookie $cookie */
|
||||
if (\YoastSEO_Vendor\GuzzleHttp\Cookie\CookieJar::shouldPersist($cookie, $this->storeSessionCookies)) {
|
||||
$json[] = $cookie->toArray();
|
||||
}
|
||||
@@ -54,7 +50,7 @@ class SessionCookieJar extends \YoastSEO_Vendor\GuzzleHttp\Cookie\CookieJar
|
||||
/**
|
||||
* Load the contents of the client session into the data array
|
||||
*/
|
||||
protected function load() : void
|
||||
protected function load()
|
||||
{
|
||||
if (!isset($_SESSION[$this->sessionKey])) {
|
||||
return;
|
||||
@@ -65,7 +61,7 @@ class SessionCookieJar extends \YoastSEO_Vendor\GuzzleHttp\Cookie\CookieJar
|
||||
$this->setCookie(new \YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie($cookie));
|
||||
}
|
||||
} elseif (\strlen($data)) {
|
||||
throw new \RuntimeException('Invalid cookie data');
|
||||
throw new \RuntimeException("Invalid cookie data");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,27 +7,25 @@ namespace YoastSEO_Vendor\GuzzleHttp\Cookie;
|
||||
*/
|
||||
class SetCookie
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
/** @var array */
|
||||
private static $defaults = ['Name' => null, 'Value' => null, 'Domain' => null, 'Path' => '/', 'Max-Age' => null, 'Expires' => null, 'Secure' => \false, 'Discard' => \false, 'HttpOnly' => \false];
|
||||
/**
|
||||
* @var array Cookie data
|
||||
*/
|
||||
/** @var array Cookie data */
|
||||
private $data;
|
||||
/**
|
||||
* Create a new SetCookie object from a string.
|
||||
* Create a new SetCookie object from a string
|
||||
*
|
||||
* @param string $cookie Set-Cookie header string
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public static function fromString(string $cookie) : self
|
||||
public static function fromString($cookie)
|
||||
{
|
||||
// Create the default return array
|
||||
$data = self::$defaults;
|
||||
// Explode the cookie string using a series of semicolons
|
||||
$pieces = \array_filter(\array_map('trim', \explode(';', $cookie)));
|
||||
// The name of the cookie (first kvp) must exist and include an equal sign.
|
||||
if (!isset($pieces[0]) || \strpos($pieces[0], '=') === \false) {
|
||||
if (empty($pieces[0]) || !\strpos($pieces[0], '=')) {
|
||||
return new self($data);
|
||||
}
|
||||
// Add the cookie pieces into the parsed data array
|
||||
@@ -36,19 +34,13 @@ class SetCookie
|
||||
$key = \trim($cookieParts[0]);
|
||||
$value = isset($cookieParts[1]) ? \trim($cookieParts[1], " \n\r\t\x00\v") : \true;
|
||||
// Only check for non-cookies when cookies have been found
|
||||
if (!isset($data['Name'])) {
|
||||
if (empty($data['Name'])) {
|
||||
$data['Name'] = $key;
|
||||
$data['Value'] = $value;
|
||||
} else {
|
||||
foreach (\array_keys(self::$defaults) as $search) {
|
||||
if (!\strcasecmp($search, $key)) {
|
||||
if ($search === 'Max-Age') {
|
||||
if (\is_numeric($value)) {
|
||||
$data[$search] = (int) $value;
|
||||
}
|
||||
} else {
|
||||
$data[$search] = $value;
|
||||
}
|
||||
$data[$search] = $value;
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
@@ -62,49 +54,18 @@ class SetCookie
|
||||
*/
|
||||
public function __construct(array $data = [])
|
||||
{
|
||||
$this->data = self::$defaults;
|
||||
if (isset($data['Name'])) {
|
||||
$this->setName($data['Name']);
|
||||
}
|
||||
if (isset($data['Value'])) {
|
||||
$this->setValue($data['Value']);
|
||||
}
|
||||
if (isset($data['Domain'])) {
|
||||
$this->setDomain($data['Domain']);
|
||||
}
|
||||
if (isset($data['Path'])) {
|
||||
$this->setPath($data['Path']);
|
||||
}
|
||||
if (isset($data['Max-Age'])) {
|
||||
$this->setMaxAge($data['Max-Age']);
|
||||
}
|
||||
if (isset($data['Expires'])) {
|
||||
$this->setExpires($data['Expires']);
|
||||
}
|
||||
if (isset($data['Secure'])) {
|
||||
$this->setSecure($data['Secure']);
|
||||
}
|
||||
if (isset($data['Discard'])) {
|
||||
$this->setDiscard($data['Discard']);
|
||||
}
|
||||
if (isset($data['HttpOnly'])) {
|
||||
$this->setHttpOnly($data['HttpOnly']);
|
||||
}
|
||||
// Set the remaining values that don't have extra validation logic
|
||||
foreach (\array_diff(\array_keys($data), \array_keys(self::$defaults)) as $key) {
|
||||
$this->data[$key] = $data[$key];
|
||||
}
|
||||
$this->data = \array_replace(self::$defaults, $data);
|
||||
// Extract the Expires value and turn it into a UNIX timestamp if needed
|
||||
if (!$this->getExpires() && $this->getMaxAge()) {
|
||||
// Calculate the Expires date
|
||||
$this->setExpires(\time() + $this->getMaxAge());
|
||||
} elseif (null !== ($expires = $this->getExpires()) && !\is_numeric($expires)) {
|
||||
$this->setExpires($expires);
|
||||
} elseif ($this->getExpires() && !\is_numeric($this->getExpires())) {
|
||||
$this->setExpires($this->getExpires());
|
||||
}
|
||||
}
|
||||
public function __toString()
|
||||
{
|
||||
$str = $this->data['Name'] . '=' . ($this->data['Value'] ?? '') . '; ';
|
||||
$str = $this->data['Name'] . '=' . $this->data['Value'] . '; ';
|
||||
foreach ($this->data as $k => $v) {
|
||||
if ($k !== 'Name' && $k !== 'Value' && $v !== null && $v !== \false) {
|
||||
if ($k === 'Expires') {
|
||||
@@ -116,12 +77,12 @@ class SetCookie
|
||||
}
|
||||
return \rtrim($str, '; ');
|
||||
}
|
||||
public function toArray() : array
|
||||
public function toArray()
|
||||
{
|
||||
return $this->data;
|
||||
}
|
||||
/**
|
||||
* Get the cookie name.
|
||||
* Get the cookie name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
@@ -130,40 +91,34 @@ class SetCookie
|
||||
return $this->data['Name'];
|
||||
}
|
||||
/**
|
||||
* Set the cookie name.
|
||||
* Set the cookie name
|
||||
*
|
||||
* @param string $name Cookie name
|
||||
*/
|
||||
public function setName($name) : void
|
||||
public function setName($name)
|
||||
{
|
||||
if (!\is_string($name)) {
|
||||
trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a string to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__);
|
||||
}
|
||||
$this->data['Name'] = (string) $name;
|
||||
$this->data['Name'] = $name;
|
||||
}
|
||||
/**
|
||||
* Get the cookie value.
|
||||
* Get the cookie value
|
||||
*
|
||||
* @return string|null
|
||||
* @return string
|
||||
*/
|
||||
public function getValue()
|
||||
{
|
||||
return $this->data['Value'];
|
||||
}
|
||||
/**
|
||||
* Set the cookie value.
|
||||
* Set the cookie value
|
||||
*
|
||||
* @param string $value Cookie value
|
||||
*/
|
||||
public function setValue($value) : void
|
||||
public function setValue($value)
|
||||
{
|
||||
if (!\is_string($value)) {
|
||||
trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a string to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__);
|
||||
}
|
||||
$this->data['Value'] = (string) $value;
|
||||
$this->data['Value'] = $value;
|
||||
}
|
||||
/**
|
||||
* Get the domain.
|
||||
* Get the domain
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
@@ -172,19 +127,16 @@ class SetCookie
|
||||
return $this->data['Domain'];
|
||||
}
|
||||
/**
|
||||
* Set the domain of the cookie.
|
||||
* Set the domain of the cookie
|
||||
*
|
||||
* @param string|null $domain
|
||||
* @param string $domain
|
||||
*/
|
||||
public function setDomain($domain) : void
|
||||
public function setDomain($domain)
|
||||
{
|
||||
if (!\is_string($domain) && null !== $domain) {
|
||||
trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a string or null to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__);
|
||||
}
|
||||
$this->data['Domain'] = null === $domain ? null : (string) $domain;
|
||||
$this->data['Domain'] = $domain;
|
||||
}
|
||||
/**
|
||||
* Get the path.
|
||||
* Get the path
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
@@ -193,82 +145,70 @@ class SetCookie
|
||||
return $this->data['Path'];
|
||||
}
|
||||
/**
|
||||
* Set the path of the cookie.
|
||||
* Set the path of the cookie
|
||||
*
|
||||
* @param string $path Path of the cookie
|
||||
*/
|
||||
public function setPath($path) : void
|
||||
public function setPath($path)
|
||||
{
|
||||
if (!\is_string($path)) {
|
||||
trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a string to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__);
|
||||
}
|
||||
$this->data['Path'] = (string) $path;
|
||||
$this->data['Path'] = $path;
|
||||
}
|
||||
/**
|
||||
* Maximum lifetime of the cookie in seconds.
|
||||
* Maximum lifetime of the cookie in seconds
|
||||
*
|
||||
* @return int|null
|
||||
*/
|
||||
public function getMaxAge()
|
||||
{
|
||||
return null === $this->data['Max-Age'] ? null : (int) $this->data['Max-Age'];
|
||||
return $this->data['Max-Age'];
|
||||
}
|
||||
/**
|
||||
* Set the max-age of the cookie.
|
||||
* Set the max-age of the cookie
|
||||
*
|
||||
* @param int|null $maxAge Max age of the cookie in seconds
|
||||
* @param int $maxAge Max age of the cookie in seconds
|
||||
*/
|
||||
public function setMaxAge($maxAge) : void
|
||||
public function setMaxAge($maxAge)
|
||||
{
|
||||
if (!\is_int($maxAge) && null !== $maxAge) {
|
||||
trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing an int or null to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__);
|
||||
}
|
||||
$this->data['Max-Age'] = $maxAge === null ? null : (int) $maxAge;
|
||||
$this->data['Max-Age'] = $maxAge;
|
||||
}
|
||||
/**
|
||||
* The UNIX timestamp when the cookie Expires.
|
||||
* The UNIX timestamp when the cookie Expires
|
||||
*
|
||||
* @return string|int|null
|
||||
* @return mixed
|
||||
*/
|
||||
public function getExpires()
|
||||
{
|
||||
return $this->data['Expires'];
|
||||
}
|
||||
/**
|
||||
* Set the unix timestamp for which the cookie will expire.
|
||||
* Set the unix timestamp for which the cookie will expire
|
||||
*
|
||||
* @param int|string|null $timestamp Unix timestamp or any English textual datetime description.
|
||||
* @param int $timestamp Unix timestamp
|
||||
*/
|
||||
public function setExpires($timestamp) : void
|
||||
public function setExpires($timestamp)
|
||||
{
|
||||
if (!\is_int($timestamp) && !\is_string($timestamp) && null !== $timestamp) {
|
||||
trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing an int, string or null to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__);
|
||||
}
|
||||
$this->data['Expires'] = null === $timestamp ? null : (\is_numeric($timestamp) ? (int) $timestamp : \strtotime((string) $timestamp));
|
||||
$this->data['Expires'] = \is_numeric($timestamp) ? (int) $timestamp : \strtotime($timestamp);
|
||||
}
|
||||
/**
|
||||
* Get whether or not this is a secure cookie.
|
||||
* Get whether or not this is a secure cookie
|
||||
*
|
||||
* @return bool
|
||||
* @return bool|null
|
||||
*/
|
||||
public function getSecure()
|
||||
{
|
||||
return $this->data['Secure'];
|
||||
}
|
||||
/**
|
||||
* Set whether or not the cookie is secure.
|
||||
* Set whether or not the cookie is secure
|
||||
*
|
||||
* @param bool $secure Set to true or false if secure
|
||||
*/
|
||||
public function setSecure($secure) : void
|
||||
public function setSecure($secure)
|
||||
{
|
||||
if (!\is_bool($secure)) {
|
||||
trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a bool to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__);
|
||||
}
|
||||
$this->data['Secure'] = (bool) $secure;
|
||||
$this->data['Secure'] = $secure;
|
||||
}
|
||||
/**
|
||||
* Get whether or not this is a session cookie.
|
||||
* Get whether or not this is a session cookie
|
||||
*
|
||||
* @return bool|null
|
||||
*/
|
||||
@@ -277,19 +217,16 @@ class SetCookie
|
||||
return $this->data['Discard'];
|
||||
}
|
||||
/**
|
||||
* Set whether or not this is a session cookie.
|
||||
* Set whether or not this is a session cookie
|
||||
*
|
||||
* @param bool $discard Set to true or false if this is a session cookie
|
||||
*/
|
||||
public function setDiscard($discard) : void
|
||||
public function setDiscard($discard)
|
||||
{
|
||||
if (!\is_bool($discard)) {
|
||||
trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a bool to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__);
|
||||
}
|
||||
$this->data['Discard'] = (bool) $discard;
|
||||
$this->data['Discard'] = $discard;
|
||||
}
|
||||
/**
|
||||
* Get whether or not this is an HTTP only cookie.
|
||||
* Get whether or not this is an HTTP only cookie
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
@@ -298,16 +235,13 @@ class SetCookie
|
||||
return $this->data['HttpOnly'];
|
||||
}
|
||||
/**
|
||||
* Set whether or not this is an HTTP only cookie.
|
||||
* Set whether or not this is an HTTP only cookie
|
||||
*
|
||||
* @param bool $httpOnly Set to true or false if this is HTTP only
|
||||
*/
|
||||
public function setHttpOnly($httpOnly) : void
|
||||
public function setHttpOnly($httpOnly)
|
||||
{
|
||||
if (!\is_bool($httpOnly)) {
|
||||
trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a bool to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__);
|
||||
}
|
||||
$this->data['HttpOnly'] = (bool) $httpOnly;
|
||||
$this->data['HttpOnly'] = $httpOnly;
|
||||
}
|
||||
/**
|
||||
* Check if the cookie matches a path value.
|
||||
@@ -323,8 +257,10 @@ class SetCookie
|
||||
* path is a %x2F ("/") character.
|
||||
*
|
||||
* @param string $requestPath Path to check against
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function matchesPath(string $requestPath) : bool
|
||||
public function matchesPath($requestPath)
|
||||
{
|
||||
$cookiePath = $this->getPath();
|
||||
// Match on exact matches or when path is the default empty "/"
|
||||
@@ -343,18 +279,20 @@ class SetCookie
|
||||
return \substr($requestPath, \strlen($cookiePath), 1) === '/';
|
||||
}
|
||||
/**
|
||||
* Check if the cookie matches a domain value.
|
||||
* Check if the cookie matches a domain value
|
||||
*
|
||||
* @param string $domain Domain to check against
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function matchesDomain(string $domain) : bool
|
||||
public function matchesDomain($domain)
|
||||
{
|
||||
$cookieDomain = $this->getDomain();
|
||||
if (null === $cookieDomain) {
|
||||
return \true;
|
||||
}
|
||||
// Remove the leading '.' as per spec in RFC 6265.
|
||||
// https://tools.ietf.org/html/rfc6265#section-5.2.3
|
||||
// http://tools.ietf.org/html/rfc6265#section-5.2.3
|
||||
$cookieDomain = \ltrim(\strtolower($cookieDomain), '.');
|
||||
$domain = \strtolower($domain);
|
||||
// Domain not set or exact match.
|
||||
@@ -362,44 +300,47 @@ class SetCookie
|
||||
return \true;
|
||||
}
|
||||
// Matching the subdomain according to RFC 6265.
|
||||
// https://tools.ietf.org/html/rfc6265#section-5.1.3
|
||||
// http://tools.ietf.org/html/rfc6265#section-5.1.3
|
||||
if (\filter_var($domain, \FILTER_VALIDATE_IP)) {
|
||||
return \false;
|
||||
}
|
||||
return (bool) \preg_match('/\\.' . \preg_quote($cookieDomain, '/') . '$/', $domain);
|
||||
}
|
||||
/**
|
||||
* Check if the cookie is expired.
|
||||
* Check if the cookie is expired
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isExpired() : bool
|
||||
public function isExpired()
|
||||
{
|
||||
return $this->getExpires() !== null && \time() > $this->getExpires();
|
||||
}
|
||||
/**
|
||||
* Check if the cookie is valid according to RFC 6265.
|
||||
* Check if the cookie is valid according to RFC 6265
|
||||
*
|
||||
* @return bool|string Returns true if valid or an error message if invalid
|
||||
*/
|
||||
public function validate()
|
||||
{
|
||||
// Names must not be empty, but can be 0
|
||||
$name = $this->getName();
|
||||
if ($name === '') {
|
||||
if (empty($name) && !\is_numeric($name)) {
|
||||
return 'The cookie name must not be empty';
|
||||
}
|
||||
// Check if any of the invalid characters are present in the cookie name
|
||||
if (\preg_match('/[\\x00-\\x20\\x22\\x28-\\x29\\x2c\\x2f\\x3a-\\x40\\x5c\\x7b\\x7d\\x7f]/', $name)) {
|
||||
return 'Cookie name must not contain invalid characters: ASCII ' . 'Control characters (0-31;127), space, tab and the ' . 'following characters: ()<>@,;:\\"/?={}';
|
||||
}
|
||||
// Value must not be null. 0 and empty string are valid. Empty strings
|
||||
// are technically against RFC 6265, but known to happen in the wild.
|
||||
// Value must not be empty, but can be 0
|
||||
$value = $this->getValue();
|
||||
if ($value === null) {
|
||||
if (empty($value) && !\is_numeric($value)) {
|
||||
return 'The cookie value must not be empty';
|
||||
}
|
||||
// Domains must not be empty, but can be 0. "0" is not a valid internet
|
||||
// domain, but may be used as server name in a private network.
|
||||
// Domains must not be empty, but can be 0
|
||||
// A "0" is not a valid internet domain, but may be used as server name
|
||||
// in a private network.
|
||||
$domain = $this->getDomain();
|
||||
if ($domain === null || $domain === '') {
|
||||
if (empty($domain) && !\is_numeric($domain)) {
|
||||
return 'The cookie domain must not be empty';
|
||||
}
|
||||
return \true;
|
||||
|
||||
@@ -9,23 +9,11 @@ use YoastSEO_Vendor\Psr\Http\Message\ResponseInterface;
|
||||
*/
|
||||
class BadResponseException extends \YoastSEO_Vendor\GuzzleHttp\Exception\RequestException
|
||||
{
|
||||
public function __construct(string $message, \YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response, \Throwable $previous = null, array $handlerContext = [])
|
||||
public function __construct($message, \YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response = null, \Exception $previous = null, array $handlerContext = [])
|
||||
{
|
||||
if (null === $response) {
|
||||
@\trigger_error('Instantiating the ' . __CLASS__ . ' class without a Response is deprecated since version 6.3 and will be removed in 7.0.', \E_USER_DEPRECATED);
|
||||
}
|
||||
parent::__construct($message, $request, $response, $previous, $handlerContext);
|
||||
}
|
||||
/**
|
||||
* Current exception and the ones that extend it will always have a response.
|
||||
*/
|
||||
public function hasResponse() : bool
|
||||
{
|
||||
return \true;
|
||||
}
|
||||
/**
|
||||
* This function narrows the return type from the parent class and does not allow it to be nullable.
|
||||
*/
|
||||
public function getResponse() : \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface
|
||||
{
|
||||
/** @var ResponseInterface */
|
||||
return parent::getResponse();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,46 +2,30 @@
|
||||
|
||||
namespace YoastSEO_Vendor\GuzzleHttp\Exception;
|
||||
|
||||
use YoastSEO_Vendor\Psr\Http\Client\NetworkExceptionInterface;
|
||||
use YoastSEO_Vendor\Psr\Http\Message\RequestInterface;
|
||||
/**
|
||||
* Exception thrown when a connection cannot be established.
|
||||
*
|
||||
* Note that no response is present for a ConnectException
|
||||
*/
|
||||
class ConnectException extends \YoastSEO_Vendor\GuzzleHttp\Exception\TransferException implements \YoastSEO_Vendor\Psr\Http\Client\NetworkExceptionInterface
|
||||
class ConnectException extends \YoastSEO_Vendor\GuzzleHttp\Exception\RequestException
|
||||
{
|
||||
/**
|
||||
* @var RequestInterface
|
||||
*/
|
||||
private $request;
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $handlerContext;
|
||||
public function __construct(string $message, \YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, \Throwable $previous = null, array $handlerContext = [])
|
||||
public function __construct($message, \YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, \Exception $previous = null, array $handlerContext = [])
|
||||
{
|
||||
parent::__construct($message, 0, $previous);
|
||||
$this->request = $request;
|
||||
$this->handlerContext = $handlerContext;
|
||||
parent::__construct($message, $request, null, $previous, $handlerContext);
|
||||
}
|
||||
/**
|
||||
* Get the request that caused the exception
|
||||
* @return null
|
||||
*/
|
||||
public function getRequest() : \YoastSEO_Vendor\Psr\Http\Message\RequestInterface
|
||||
public function getResponse()
|
||||
{
|
||||
return $this->request;
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* Get contextual information about the error from the underlying handler.
|
||||
*
|
||||
* The contents of this array will vary depending on which handler you are
|
||||
* using. It may also be just an empty array. Relying on this data will
|
||||
* couple you to a specific handler, but can give more debug information
|
||||
* when needed.
|
||||
* @return bool
|
||||
*/
|
||||
public function getHandlerContext() : array
|
||||
public function hasResponse()
|
||||
{
|
||||
return $this->handlerContext;
|
||||
return \false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,22 @@
|
||||
|
||||
namespace YoastSEO_Vendor\GuzzleHttp\Exception;
|
||||
|
||||
use YoastSEO_Vendor\Psr\Http\Client\ClientExceptionInterface;
|
||||
interface GuzzleException extends \YoastSEO_Vendor\Psr\Http\Client\ClientExceptionInterface
|
||||
{
|
||||
use Throwable;
|
||||
if (\interface_exists(\Throwable::class)) {
|
||||
interface GuzzleException extends \Throwable
|
||||
{
|
||||
}
|
||||
} else {
|
||||
/**
|
||||
* @method string getMessage()
|
||||
* @method \Throwable|null getPrevious()
|
||||
* @method mixed getCode()
|
||||
* @method string getFile()
|
||||
* @method int getLine()
|
||||
* @method array getTrace()
|
||||
* @method string getTraceAsString()
|
||||
*/
|
||||
interface GuzzleException
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,33 +2,25 @@
|
||||
|
||||
namespace YoastSEO_Vendor\GuzzleHttp\Exception;
|
||||
|
||||
use YoastSEO_Vendor\GuzzleHttp\BodySummarizer;
|
||||
use YoastSEO_Vendor\GuzzleHttp\BodySummarizerInterface;
|
||||
use YoastSEO_Vendor\Psr\Http\Client\RequestExceptionInterface;
|
||||
use YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface;
|
||||
use YoastSEO_Vendor\Psr\Http\Message\RequestInterface;
|
||||
use YoastSEO_Vendor\Psr\Http\Message\ResponseInterface;
|
||||
use YoastSEO_Vendor\Psr\Http\Message\UriInterface;
|
||||
/**
|
||||
* HTTP Request exception
|
||||
*/
|
||||
class RequestException extends \YoastSEO_Vendor\GuzzleHttp\Exception\TransferException implements \YoastSEO_Vendor\Psr\Http\Client\RequestExceptionInterface
|
||||
class RequestException extends \YoastSEO_Vendor\GuzzleHttp\Exception\TransferException
|
||||
{
|
||||
/**
|
||||
* @var RequestInterface
|
||||
*/
|
||||
/** @var RequestInterface */
|
||||
private $request;
|
||||
/**
|
||||
* @var ResponseInterface|null
|
||||
*/
|
||||
/** @var ResponseInterface|null */
|
||||
private $response;
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
/** @var array */
|
||||
private $handlerContext;
|
||||
public function __construct(string $message, \YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response = null, \Throwable $previous = null, array $handlerContext = [])
|
||||
public function __construct($message, \YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response = null, \Exception $previous = null, array $handlerContext = [])
|
||||
{
|
||||
// Set the code of the exception if the response is set and not future.
|
||||
$code = $response ? $response->getStatusCode() : 0;
|
||||
$code = $response && !$response instanceof \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface ? $response->getStatusCode() : 0;
|
||||
parent::__construct($message, $code, $previous);
|
||||
$this->request = $request;
|
||||
$this->response = $response;
|
||||
@@ -36,24 +28,30 @@ class RequestException extends \YoastSEO_Vendor\GuzzleHttp\Exception\TransferExc
|
||||
}
|
||||
/**
|
||||
* Wrap non-RequestExceptions with a RequestException
|
||||
*
|
||||
* @param RequestInterface $request
|
||||
* @param \Exception $e
|
||||
*
|
||||
* @return RequestException
|
||||
*/
|
||||
public static function wrapException(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, \Throwable $e) : \YoastSEO_Vendor\GuzzleHttp\Exception\RequestException
|
||||
public static function wrapException(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, \Exception $e)
|
||||
{
|
||||
return $e instanceof \YoastSEO_Vendor\GuzzleHttp\Exception\RequestException ? $e : new \YoastSEO_Vendor\GuzzleHttp\Exception\RequestException($e->getMessage(), $request, null, $e);
|
||||
}
|
||||
/**
|
||||
* Factory method to create a new exception with a normalized error message
|
||||
*
|
||||
* @param RequestInterface $request Request sent
|
||||
* @param ResponseInterface $response Response received
|
||||
* @param \Throwable|null $previous Previous exception
|
||||
* @param array $handlerContext Optional handler context
|
||||
* @param BodySummarizerInterface|null $bodySummarizer Optional body summarizer
|
||||
* @param RequestInterface $request Request
|
||||
* @param ResponseInterface $response Response received
|
||||
* @param \Exception $previous Previous exception
|
||||
* @param array $ctx Optional handler context.
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public static function create(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response = null, \Throwable $previous = null, array $handlerContext = [], \YoastSEO_Vendor\GuzzleHttp\BodySummarizerInterface $bodySummarizer = null) : self
|
||||
public static function create(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response = null, \Exception $previous = null, array $ctx = [])
|
||||
{
|
||||
if (!$response) {
|
||||
return new self('Error completing request', $request, null, $previous, $handlerContext);
|
||||
return new self('Error completing request', $request, null, $previous, $ctx);
|
||||
}
|
||||
$level = (int) \floor($response->getStatusCode() / 100);
|
||||
if ($level === 4) {
|
||||
@@ -70,17 +68,34 @@ class RequestException extends \YoastSEO_Vendor\GuzzleHttp\Exception\TransferExc
|
||||
$uri = static::obfuscateUri($uri);
|
||||
// Client Error: `GET /` resulted in a `404 Not Found` response:
|
||||
// <html> ... (truncated)
|
||||
$message = \sprintf('%s: `%s %s` resulted in a `%s %s` response', $label, $request->getMethod(), $uri->__toString(), $response->getStatusCode(), $response->getReasonPhrase());
|
||||
$summary = ($bodySummarizer ?? new \YoastSEO_Vendor\GuzzleHttp\BodySummarizer())->summarize($response);
|
||||
$message = \sprintf('%s: `%s %s` resulted in a `%s %s` response', $label, $request->getMethod(), $uri, $response->getStatusCode(), $response->getReasonPhrase());
|
||||
$summary = static::getResponseBodySummary($response);
|
||||
if ($summary !== null) {
|
||||
$message .= ":\n{$summary}\n";
|
||||
}
|
||||
return new $className($message, $request, $response, $previous, $handlerContext);
|
||||
return new $className($message, $request, $response, $previous, $ctx);
|
||||
}
|
||||
/**
|
||||
* Get a short summary of the response
|
||||
*
|
||||
* Will return `null` if the response is not printable.
|
||||
*
|
||||
* @param ResponseInterface $response
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public static function getResponseBodySummary(\YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response)
|
||||
{
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Psr7\get_message_body_summary($response);
|
||||
}
|
||||
/**
|
||||
* Obfuscates URI if there is a username and a password present
|
||||
*
|
||||
* @param UriInterface $uri
|
||||
*
|
||||
* @return UriInterface
|
||||
*/
|
||||
private static function obfuscateUri(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface
|
||||
private static function obfuscateUri(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri)
|
||||
{
|
||||
$userInfo = $uri->getUserInfo();
|
||||
if (\false !== ($pos = \strpos($userInfo, ':'))) {
|
||||
@@ -90,22 +105,28 @@ class RequestException extends \YoastSEO_Vendor\GuzzleHttp\Exception\TransferExc
|
||||
}
|
||||
/**
|
||||
* Get the request that caused the exception
|
||||
*
|
||||
* @return RequestInterface
|
||||
*/
|
||||
public function getRequest() : \YoastSEO_Vendor\Psr\Http\Message\RequestInterface
|
||||
public function getRequest()
|
||||
{
|
||||
return $this->request;
|
||||
}
|
||||
/**
|
||||
* Get the associated response
|
||||
*
|
||||
* @return ResponseInterface|null
|
||||
*/
|
||||
public function getResponse() : ?\YoastSEO_Vendor\Psr\Http\Message\ResponseInterface
|
||||
public function getResponse()
|
||||
{
|
||||
return $this->response;
|
||||
}
|
||||
/**
|
||||
* Check if a response was received
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasResponse() : bool
|
||||
public function hasResponse()
|
||||
{
|
||||
return $this->response !== null;
|
||||
}
|
||||
@@ -116,8 +137,10 @@ class RequestException extends \YoastSEO_Vendor\GuzzleHttp\Exception\TransferExc
|
||||
* using. It may also be just an empty array. Relying on this data will
|
||||
* couple you to a specific handler, but can give more debug information
|
||||
* when needed.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getHandlerContext() : array
|
||||
public function getHandlerContext()
|
||||
{
|
||||
return $this->handlerContext;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace YoastSEO_Vendor\GuzzleHttp\Exception;
|
||||
|
||||
use YoastSEO_Vendor\Psr\Http\Message\StreamInterface;
|
||||
/**
|
||||
* Exception thrown when a seek fails on a stream.
|
||||
*/
|
||||
class SeekException extends \RuntimeException implements \YoastSEO_Vendor\GuzzleHttp\Exception\GuzzleException
|
||||
{
|
||||
private $stream;
|
||||
public function __construct(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $stream, $pos = 0, $msg = '')
|
||||
{
|
||||
$this->stream = $stream;
|
||||
$msg = $msg ?: 'Could not seek the stream to position ' . $pos;
|
||||
parent::__construct($msg);
|
||||
}
|
||||
/**
|
||||
* @return StreamInterface
|
||||
*/
|
||||
public function getStream()
|
||||
{
|
||||
return $this->stream;
|
||||
}
|
||||
}
|
||||
@@ -4,41 +4,30 @@ namespace YoastSEO_Vendor\GuzzleHttp\Handler;
|
||||
|
||||
use YoastSEO_Vendor\GuzzleHttp\Exception\ConnectException;
|
||||
use YoastSEO_Vendor\GuzzleHttp\Exception\RequestException;
|
||||
use YoastSEO_Vendor\GuzzleHttp\Promise as P;
|
||||
use YoastSEO_Vendor\GuzzleHttp\Promise\FulfilledPromise;
|
||||
use YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface;
|
||||
use YoastSEO_Vendor\GuzzleHttp\Psr7;
|
||||
use YoastSEO_Vendor\GuzzleHttp\Psr7\LazyOpenStream;
|
||||
use YoastSEO_Vendor\GuzzleHttp\TransferStats;
|
||||
use YoastSEO_Vendor\GuzzleHttp\Utils;
|
||||
use YoastSEO_Vendor\Psr\Http\Message\RequestInterface;
|
||||
/**
|
||||
* Creates curl resources from a request
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class CurlFactory implements \YoastSEO_Vendor\GuzzleHttp\Handler\CurlFactoryInterface
|
||||
{
|
||||
public const CURL_VERSION_STR = 'curl_version';
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
public const LOW_CURL_VERSION_NUMBER = '7.21.2';
|
||||
/**
|
||||
* @var resource[]|\CurlHandle[]
|
||||
*/
|
||||
const CURL_VERSION_STR = 'curl_version';
|
||||
const LOW_CURL_VERSION_NUMBER = '7.21.2';
|
||||
/** @var array */
|
||||
private $handles = [];
|
||||
/**
|
||||
* @var int Total number of idle handles to keep in cache
|
||||
*/
|
||||
/** @var int Total number of idle handles to keep in cache */
|
||||
private $maxHandles;
|
||||
/**
|
||||
* @param int $maxHandles Maximum number of idle handles.
|
||||
*/
|
||||
public function __construct(int $maxHandles)
|
||||
public function __construct($maxHandles)
|
||||
{
|
||||
$this->maxHandles = $maxHandles;
|
||||
}
|
||||
public function create(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options) : \YoastSEO_Vendor\GuzzleHttp\Handler\EasyHandle
|
||||
public function create(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options)
|
||||
{
|
||||
if (isset($options['curl']['body_as_string'])) {
|
||||
$options['_body_as_string'] = $options['curl']['body_as_string'];
|
||||
@@ -61,7 +50,7 @@ class CurlFactory implements \YoastSEO_Vendor\GuzzleHttp\Handler\CurlFactoryInte
|
||||
\curl_setopt_array($easy->handle, $conf);
|
||||
return $easy;
|
||||
}
|
||||
public function release(\YoastSEO_Vendor\GuzzleHttp\Handler\EasyHandle $easy) : void
|
||||
public function release(\YoastSEO_Vendor\GuzzleHttp\Handler\EasyHandle $easy)
|
||||
{
|
||||
$resource = $easy->handle;
|
||||
unset($easy->handle);
|
||||
@@ -84,10 +73,13 @@ class CurlFactory implements \YoastSEO_Vendor\GuzzleHttp\Handler\CurlFactoryInte
|
||||
* Completes a cURL transaction, either returning a response promise or a
|
||||
* rejected promise.
|
||||
*
|
||||
* @param callable(RequestInterface, array): PromiseInterface $handler
|
||||
* @param CurlFactoryInterface $factory Dictates how the handle is released
|
||||
* @param callable $handler
|
||||
* @param EasyHandle $easy
|
||||
* @param CurlFactoryInterface $factory Dictates how the handle is released
|
||||
*
|
||||
* @return \GuzzleHttp\Promise\PromiseInterface
|
||||
*/
|
||||
public static function finish(callable $handler, \YoastSEO_Vendor\GuzzleHttp\Handler\EasyHandle $easy, \YoastSEO_Vendor\GuzzleHttp\Handler\CurlFactoryInterface $factory) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
|
||||
public static function finish(callable $handler, \YoastSEO_Vendor\GuzzleHttp\Handler\EasyHandle $easy, \YoastSEO_Vendor\GuzzleHttp\Handler\CurlFactoryInterface $factory)
|
||||
{
|
||||
if (isset($easy->options['on_stats'])) {
|
||||
self::invokeStats($easy);
|
||||
@@ -104,17 +96,14 @@ class CurlFactory implements \YoastSEO_Vendor\GuzzleHttp\Handler\CurlFactoryInte
|
||||
}
|
||||
return new \YoastSEO_Vendor\GuzzleHttp\Promise\FulfilledPromise($easy->response);
|
||||
}
|
||||
private static function invokeStats(\YoastSEO_Vendor\GuzzleHttp\Handler\EasyHandle $easy) : void
|
||||
private static function invokeStats(\YoastSEO_Vendor\GuzzleHttp\Handler\EasyHandle $easy)
|
||||
{
|
||||
$curlStats = \curl_getinfo($easy->handle);
|
||||
$curlStats['appconnect_time'] = \curl_getinfo($easy->handle, \CURLINFO_APPCONNECT_TIME);
|
||||
$stats = new \YoastSEO_Vendor\GuzzleHttp\TransferStats($easy->request, $easy->response, $curlStats['total_time'], $easy->errno, $curlStats);
|
||||
$easy->options['on_stats']($stats);
|
||||
\call_user_func($easy->options['on_stats'], $stats);
|
||||
}
|
||||
/**
|
||||
* @param callable(RequestInterface, array): PromiseInterface $handler
|
||||
*/
|
||||
private static function finishError(callable $handler, \YoastSEO_Vendor\GuzzleHttp\Handler\EasyHandle $easy, \YoastSEO_Vendor\GuzzleHttp\Handler\CurlFactoryInterface $factory) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
|
||||
private static function finishError(callable $handler, \YoastSEO_Vendor\GuzzleHttp\Handler\EasyHandle $easy, \YoastSEO_Vendor\GuzzleHttp\Handler\CurlFactoryInterface $factory)
|
||||
{
|
||||
// Get error information and release the handle to the factory.
|
||||
$ctx = ['errno' => $easy->errno, 'error' => \curl_error($easy->handle), 'appconnect_time' => \curl_getinfo($easy->handle, \CURLINFO_APPCONNECT_TIME)] + \curl_getinfo($easy->handle);
|
||||
@@ -126,32 +115,26 @@ class CurlFactory implements \YoastSEO_Vendor\GuzzleHttp\Handler\CurlFactoryInte
|
||||
}
|
||||
return self::createRejection($easy, $ctx);
|
||||
}
|
||||
private static function createRejection(\YoastSEO_Vendor\GuzzleHttp\Handler\EasyHandle $easy, array $ctx) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
|
||||
private static function createRejection(\YoastSEO_Vendor\GuzzleHttp\Handler\EasyHandle $easy, array $ctx)
|
||||
{
|
||||
static $connectionErrors = [\CURLE_OPERATION_TIMEOUTED => \true, \CURLE_COULDNT_RESOLVE_HOST => \true, \CURLE_COULDNT_CONNECT => \true, \CURLE_SSL_CONNECT_ERROR => \true, \CURLE_GOT_NOTHING => \true];
|
||||
if ($easy->createResponseException) {
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Promise\Create::rejectionFor(new \YoastSEO_Vendor\GuzzleHttp\Exception\RequestException('An error was encountered while creating the response', $easy->request, $easy->response, $easy->createResponseException, $ctx));
|
||||
}
|
||||
// If an exception was encountered during the onHeaders event, then
|
||||
// return a rejected promise that wraps that exception.
|
||||
if ($easy->onHeadersException) {
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Promise\Create::rejectionFor(new \YoastSEO_Vendor\GuzzleHttp\Exception\RequestException('An error was encountered during the on_headers event', $easy->request, $easy->response, $easy->onHeadersException, $ctx));
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Promise\rejection_for(new \YoastSEO_Vendor\GuzzleHttp\Exception\RequestException('An error was encountered during the on_headers event', $easy->request, $easy->response, $easy->onHeadersException, $ctx));
|
||||
}
|
||||
$message = \sprintf('cURL error %s: %s (%s)', $ctx['errno'], $ctx['error'], 'see https://curl.haxx.se/libcurl/c/libcurl-errors.html');
|
||||
$uriString = (string) $easy->request->getUri();
|
||||
if ($uriString !== '' && \false === \strpos($ctx['error'], $uriString)) {
|
||||
$message .= \sprintf(' for %s', $uriString);
|
||||
if (\version_compare($ctx[self::CURL_VERSION_STR], self::LOW_CURL_VERSION_NUMBER)) {
|
||||
$message = \sprintf('cURL error %s: %s (%s)', $ctx['errno'], $ctx['error'], 'see https://curl.haxx.se/libcurl/c/libcurl-errors.html');
|
||||
} else {
|
||||
$message = \sprintf('cURL error %s: %s (%s) for %s', $ctx['errno'], $ctx['error'], 'see https://curl.haxx.se/libcurl/c/libcurl-errors.html', $easy->request->getUri());
|
||||
}
|
||||
// Create a connection exception if it was a specific error code.
|
||||
$error = isset($connectionErrors[$easy->errno]) ? new \YoastSEO_Vendor\GuzzleHttp\Exception\ConnectException($message, $easy->request, null, $ctx) : new \YoastSEO_Vendor\GuzzleHttp\Exception\RequestException($message, $easy->request, $easy->response, null, $ctx);
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Promise\Create::rejectionFor($error);
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Promise\rejection_for($error);
|
||||
}
|
||||
/**
|
||||
* @return array<int|string, mixed>
|
||||
*/
|
||||
private function getDefaultConf(\YoastSEO_Vendor\GuzzleHttp\Handler\EasyHandle $easy) : array
|
||||
private function getDefaultConf(\YoastSEO_Vendor\GuzzleHttp\Handler\EasyHandle $easy)
|
||||
{
|
||||
$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];
|
||||
$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 => 150];
|
||||
if (\defined('CURLOPT_PROTOCOLS')) {
|
||||
$conf[\CURLOPT_PROTOCOLS] = \CURLPROTO_HTTP | \CURLPROTO_HTTPS;
|
||||
}
|
||||
@@ -165,7 +148,7 @@ class CurlFactory implements \YoastSEO_Vendor\GuzzleHttp\Handler\CurlFactoryInte
|
||||
}
|
||||
return $conf;
|
||||
}
|
||||
private function applyMethod(\YoastSEO_Vendor\GuzzleHttp\Handler\EasyHandle $easy, array &$conf) : void
|
||||
private function applyMethod(\YoastSEO_Vendor\GuzzleHttp\Handler\EasyHandle $easy, array &$conf)
|
||||
{
|
||||
$body = $easy->request->getBody();
|
||||
$size = $body->getSize();
|
||||
@@ -175,7 +158,7 @@ class CurlFactory implements \YoastSEO_Vendor\GuzzleHttp\Handler\CurlFactoryInte
|
||||
}
|
||||
$method = $easy->request->getMethod();
|
||||
if ($method === 'PUT' || $method === 'POST') {
|
||||
// See https://tools.ietf.org/html/rfc7230#section-3.3.2
|
||||
// See http://tools.ietf.org/html/rfc7230#section-3.3.2
|
||||
if (!$easy->request->hasHeader('Content-Length')) {
|
||||
$conf[\CURLOPT_HTTPHEADER][] = 'Content-Length: 0';
|
||||
}
|
||||
@@ -184,7 +167,7 @@ class CurlFactory implements \YoastSEO_Vendor\GuzzleHttp\Handler\CurlFactoryInte
|
||||
unset($conf[\CURLOPT_WRITEFUNCTION], $conf[\CURLOPT_READFUNCTION], $conf[\CURLOPT_FILE], $conf[\CURLOPT_INFILE]);
|
||||
}
|
||||
}
|
||||
private function applyBody(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options, array &$conf) : void
|
||||
private function applyBody(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options, array &$conf)
|
||||
{
|
||||
$size = $request->hasHeader('Content-Length') ? (int) $request->getHeaderLine('Content-Length') : null;
|
||||
// Send the body as a string if the size is less than 1MB OR if the
|
||||
@@ -204,7 +187,7 @@ class CurlFactory implements \YoastSEO_Vendor\GuzzleHttp\Handler\CurlFactoryInte
|
||||
if ($body->isSeekable()) {
|
||||
$body->rewind();
|
||||
}
|
||||
$conf[\CURLOPT_READFUNCTION] = static function ($ch, $fd, $length) use($body) {
|
||||
$conf[\CURLOPT_READFUNCTION] = function ($ch, $fd, $length) use($body) {
|
||||
return $body->read($length);
|
||||
};
|
||||
}
|
||||
@@ -217,7 +200,7 @@ class CurlFactory implements \YoastSEO_Vendor\GuzzleHttp\Handler\CurlFactoryInte
|
||||
$conf[\CURLOPT_HTTPHEADER][] = 'Content-Type:';
|
||||
}
|
||||
}
|
||||
private function applyHeaders(\YoastSEO_Vendor\GuzzleHttp\Handler\EasyHandle $easy, array &$conf) : void
|
||||
private function applyHeaders(\YoastSEO_Vendor\GuzzleHttp\Handler\EasyHandle $easy, array &$conf)
|
||||
{
|
||||
foreach ($conf['_headers'] as $name => $values) {
|
||||
foreach ($values as $value) {
|
||||
@@ -242,7 +225,7 @@ class CurlFactory implements \YoastSEO_Vendor\GuzzleHttp\Handler\CurlFactoryInte
|
||||
* @param string $name Case-insensitive header to remove
|
||||
* @param array $options Array of options to modify
|
||||
*/
|
||||
private function removeHeader(string $name, array &$options) : void
|
||||
private function removeHeader($name, array &$options)
|
||||
{
|
||||
foreach (\array_keys($options['_headers']) as $key) {
|
||||
if (!\strcasecmp($key, $name)) {
|
||||
@@ -251,7 +234,7 @@ class CurlFactory implements \YoastSEO_Vendor\GuzzleHttp\Handler\CurlFactoryInte
|
||||
}
|
||||
}
|
||||
}
|
||||
private function applyHandlerOptions(\YoastSEO_Vendor\GuzzleHttp\Handler\EasyHandle $easy, array &$conf) : void
|
||||
private function applyHandlerOptions(\YoastSEO_Vendor\GuzzleHttp\Handler\EasyHandle $easy, array &$conf)
|
||||
{
|
||||
$options = $easy->options;
|
||||
if (isset($options['verify'])) {
|
||||
@@ -269,7 +252,7 @@ class CurlFactory implements \YoastSEO_Vendor\GuzzleHttp\Handler\CurlFactoryInte
|
||||
}
|
||||
// If it's a directory or a link to a directory use CURLOPT_CAPATH.
|
||||
// If not, it's probably a file, or a link to a file, so use CURLOPT_CAINFO.
|
||||
if (\is_dir($options['verify']) || \is_link($options['verify']) === \true && ($verifyLink = \readlink($options['verify'])) !== \false && \is_dir($verifyLink)) {
|
||||
if (\is_dir($options['verify']) || \is_link($options['verify']) && \is_dir(\readlink($options['verify']))) {
|
||||
$conf[\CURLOPT_CAPATH] = $options['verify'];
|
||||
} else {
|
||||
$conf[\CURLOPT_CAINFO] = $options['verify'];
|
||||
@@ -277,36 +260,35 @@ class CurlFactory implements \YoastSEO_Vendor\GuzzleHttp\Handler\CurlFactoryInte
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!isset($options['curl'][\CURLOPT_ENCODING]) && !empty($options['decode_content'])) {
|
||||
if (!empty($options['decode_content'])) {
|
||||
$accept = $easy->request->getHeaderLine('Accept-Encoding');
|
||||
if ($accept) {
|
||||
$conf[\CURLOPT_ENCODING] = $accept;
|
||||
} else {
|
||||
// The empty string enables all available decoders and implicitly
|
||||
// sets a matching 'Accept-Encoding' header.
|
||||
$conf[\CURLOPT_ENCODING] = '';
|
||||
// But as the user did not specify any acceptable encodings we need
|
||||
// to overwrite this implicit header with an empty one.
|
||||
// Don't let curl send the header over the wire
|
||||
$conf[\CURLOPT_HTTPHEADER][] = 'Accept-Encoding:';
|
||||
}
|
||||
}
|
||||
if (!isset($options['sink'])) {
|
||||
// Use a default temp stream if no sink was set.
|
||||
$options['sink'] = \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::tryFopen('php://temp', 'w+');
|
||||
}
|
||||
$sink = $options['sink'];
|
||||
if (!\is_string($sink)) {
|
||||
$sink = \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::streamFor($sink);
|
||||
} elseif (!\is_dir(\dirname($sink))) {
|
||||
// Ensure that the directory exists before failing in curl.
|
||||
throw new \RuntimeException(\sprintf('Directory %s does not exist for sink value of %s', \dirname($sink), $sink));
|
||||
if (isset($options['sink'])) {
|
||||
$sink = $options['sink'];
|
||||
if (!\is_string($sink)) {
|
||||
$sink = \YoastSEO_Vendor\GuzzleHttp\Psr7\stream_for($sink);
|
||||
} elseif (!\is_dir(\dirname($sink))) {
|
||||
// Ensure that the directory exists before failing in curl.
|
||||
throw new \RuntimeException(\sprintf('Directory %s does not exist for sink value of %s', \dirname($sink), $sink));
|
||||
} else {
|
||||
$sink = new \YoastSEO_Vendor\GuzzleHttp\Psr7\LazyOpenStream($sink, 'w+');
|
||||
}
|
||||
$easy->sink = $sink;
|
||||
$conf[\CURLOPT_WRITEFUNCTION] = function ($ch, $write) use($sink) {
|
||||
return $sink->write($write);
|
||||
};
|
||||
} else {
|
||||
$sink = new \YoastSEO_Vendor\GuzzleHttp\Psr7\LazyOpenStream($sink, 'w+');
|
||||
// Use a default temp stream if no sink was set.
|
||||
$conf[\CURLOPT_FILE] = \fopen('php://temp', 'w+');
|
||||
$easy->sink = \YoastSEO_Vendor\GuzzleHttp\Psr7\stream_for($conf[\CURLOPT_FILE]);
|
||||
}
|
||||
$easy->sink = $sink;
|
||||
$conf[\CURLOPT_WRITEFUNCTION] = static function ($ch, $write) use($sink) : int {
|
||||
return $sink->write($write);
|
||||
};
|
||||
$timeoutRequiresNoSignal = \false;
|
||||
if (isset($options['timeout'])) {
|
||||
$timeoutRequiresNoSignal |= $options['timeout'] < 1;
|
||||
@@ -334,39 +316,12 @@ class CurlFactory implements \YoastSEO_Vendor\GuzzleHttp\Handler\CurlFactoryInte
|
||||
$scheme = $easy->request->getUri()->getScheme();
|
||||
if (isset($options['proxy'][$scheme])) {
|
||||
$host = $easy->request->getUri()->getHost();
|
||||
if (isset($options['proxy']['no']) && \YoastSEO_Vendor\GuzzleHttp\Utils::isHostInNoProxy($host, $options['proxy']['no'])) {
|
||||
unset($conf[\CURLOPT_PROXY]);
|
||||
} else {
|
||||
if (!isset($options['proxy']['no']) || !\YoastSEO_Vendor\GuzzleHttp\is_host_in_noproxy($host, $options['proxy']['no'])) {
|
||||
$conf[\CURLOPT_PROXY] = $options['proxy'][$scheme];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isset($options['crypto_method'])) {
|
||||
if (\STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT === $options['crypto_method']) {
|
||||
if (!\defined('CURL_SSLVERSION_TLSv1_0')) {
|
||||
throw new \InvalidArgumentException('Invalid crypto_method request option: TLS 1.0 not supported by your version of cURL');
|
||||
}
|
||||
$conf[\CURLOPT_SSLVERSION] = \CURL_SSLVERSION_TLSv1_0;
|
||||
} elseif (\STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT === $options['crypto_method']) {
|
||||
if (!\defined('CURL_SSLVERSION_TLSv1_1')) {
|
||||
throw new \InvalidArgumentException('Invalid crypto_method request option: TLS 1.1 not supported by your version of cURL');
|
||||
}
|
||||
$conf[\CURLOPT_SSLVERSION] = \CURL_SSLVERSION_TLSv1_1;
|
||||
} elseif (\STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT === $options['crypto_method']) {
|
||||
if (!\defined('CURL_SSLVERSION_TLSv1_2')) {
|
||||
throw new \InvalidArgumentException('Invalid crypto_method request option: TLS 1.2 not supported by your version of cURL');
|
||||
}
|
||||
$conf[\CURLOPT_SSLVERSION] = \CURL_SSLVERSION_TLSv1_2;
|
||||
} elseif (\defined('STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT') && \STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT === $options['crypto_method']) {
|
||||
if (!\defined('CURL_SSLVERSION_TLSv1_3')) {
|
||||
throw new \InvalidArgumentException('Invalid crypto_method request option: TLS 1.3 not supported by your version of cURL');
|
||||
}
|
||||
$conf[\CURLOPT_SSLVERSION] = \CURL_SSLVERSION_TLSv1_3;
|
||||
} else {
|
||||
throw new \InvalidArgumentException('Invalid crypto_method request option: unknown version provided');
|
||||
}
|
||||
}
|
||||
if (isset($options['cert'])) {
|
||||
$cert = $options['cert'];
|
||||
if (\is_array($cert)) {
|
||||
@@ -376,23 +331,17 @@ class CurlFactory implements \YoastSEO_Vendor\GuzzleHttp\Handler\CurlFactoryInte
|
||||
if (!\file_exists($cert)) {
|
||||
throw new \InvalidArgumentException("SSL certificate not found: {$cert}");
|
||||
}
|
||||
// OpenSSL (versions 0.9.3 and later) also support "P12" for PKCS#12-encoded files.
|
||||
// see https://curl.se/libcurl/c/CURLOPT_SSLCERTTYPE.html
|
||||
$ext = \pathinfo($cert, \PATHINFO_EXTENSION);
|
||||
if (\preg_match('#^(der|p12)$#i', $ext)) {
|
||||
$conf[\CURLOPT_SSLCERTTYPE] = \strtoupper($ext);
|
||||
}
|
||||
$conf[\CURLOPT_SSLCERT] = $cert;
|
||||
}
|
||||
if (isset($options['ssl_key'])) {
|
||||
if (\is_array($options['ssl_key'])) {
|
||||
if (\count($options['ssl_key']) === 2) {
|
||||
[$sslKey, $conf[\CURLOPT_SSLKEYPASSWD]] = $options['ssl_key'];
|
||||
list($sslKey, $conf[\CURLOPT_SSLKEYPASSWD]) = $options['ssl_key'];
|
||||
} else {
|
||||
[$sslKey] = $options['ssl_key'];
|
||||
list($sslKey) = $options['ssl_key'];
|
||||
}
|
||||
}
|
||||
$sslKey = $sslKey ?? $options['ssl_key'];
|
||||
$sslKey = isset($sslKey) ? $sslKey : $options['ssl_key'];
|
||||
if (!\file_exists($sslKey)) {
|
||||
throw new \InvalidArgumentException("SSL private key not found: {$sslKey}");
|
||||
}
|
||||
@@ -404,12 +353,17 @@ class CurlFactory implements \YoastSEO_Vendor\GuzzleHttp\Handler\CurlFactoryInte
|
||||
throw new \InvalidArgumentException('progress client option must be callable');
|
||||
}
|
||||
$conf[\CURLOPT_NOPROGRESS] = \false;
|
||||
$conf[\CURLOPT_PROGRESSFUNCTION] = static function ($resource, int $downloadSize, int $downloaded, int $uploadSize, int $uploaded) use($progress) {
|
||||
$progress($downloadSize, $downloaded, $uploadSize, $uploaded);
|
||||
$conf[\CURLOPT_PROGRESSFUNCTION] = function () use($progress) {
|
||||
$args = \func_get_args();
|
||||
// PHP 5.5 pushed the handle onto the start of the args
|
||||
if (\is_resource($args[0])) {
|
||||
\array_shift($args);
|
||||
}
|
||||
\call_user_func_array($progress, $args);
|
||||
};
|
||||
}
|
||||
if (!empty($options['debug'])) {
|
||||
$conf[\CURLOPT_STDERR] = \YoastSEO_Vendor\GuzzleHttp\Utils::debugResource($options['debug']);
|
||||
$conf[\CURLOPT_STDERR] = \YoastSEO_Vendor\GuzzleHttp\debug_resource($options['debug']);
|
||||
$conf[\CURLOPT_VERBOSE] = \true;
|
||||
}
|
||||
}
|
||||
@@ -421,10 +375,8 @@ class CurlFactory implements \YoastSEO_Vendor\GuzzleHttp\Handler\CurlFactoryInte
|
||||
* stream, and then encountered a "necessary data rewind wasn't possible"
|
||||
* error, causing the request to be sent through curl_multi_info_read()
|
||||
* without an error status.
|
||||
*
|
||||
* @param callable(RequestInterface, array): PromiseInterface $handler
|
||||
*/
|
||||
private static function retryFailedRewind(callable $handler, \YoastSEO_Vendor\GuzzleHttp\Handler\EasyHandle $easy, array $ctx) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
|
||||
private static function retryFailedRewind(callable $handler, \YoastSEO_Vendor\GuzzleHttp\Handler\EasyHandle $easy, array $ctx)
|
||||
{
|
||||
try {
|
||||
// Only rewind if the body has been read from.
|
||||
@@ -443,11 +395,11 @@ class CurlFactory implements \YoastSEO_Vendor\GuzzleHttp\Handler\CurlFactoryInte
|
||||
$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.';
|
||||
return self::createRejection($easy, $ctx);
|
||||
} else {
|
||||
++$easy->options['_curl_retries'];
|
||||
$easy->options['_curl_retries']++;
|
||||
}
|
||||
return $handler($easy->request, $easy->options);
|
||||
}
|
||||
private function createHeaderFn(\YoastSEO_Vendor\GuzzleHttp\Handler\EasyHandle $easy) : callable
|
||||
private function createHeaderFn(\YoastSEO_Vendor\GuzzleHttp\Handler\EasyHandle $easy)
|
||||
{
|
||||
if (isset($easy->options['on_headers'])) {
|
||||
$onHeaders = $easy->options['on_headers'];
|
||||
@@ -457,16 +409,11 @@ class CurlFactory implements \YoastSEO_Vendor\GuzzleHttp\Handler\CurlFactoryInte
|
||||
} else {
|
||||
$onHeaders = null;
|
||||
}
|
||||
return static function ($ch, $h) use($onHeaders, $easy, &$startingResponse) {
|
||||
return function ($ch, $h) use($onHeaders, $easy, &$startingResponse) {
|
||||
$value = \trim($h);
|
||||
if ($value === '') {
|
||||
$startingResponse = \true;
|
||||
try {
|
||||
$easy->createResponse();
|
||||
} catch (\Exception $e) {
|
||||
$easy->createResponseException = $e;
|
||||
return -1;
|
||||
}
|
||||
$easy->createResponse();
|
||||
if ($onHeaders !== null) {
|
||||
try {
|
||||
$onHeaders($easy->response);
|
||||
@@ -486,11 +433,4 @@ class CurlFactory implements \YoastSEO_Vendor\GuzzleHttp\Handler\CurlFactoryInte
|
||||
return \strlen($h);
|
||||
};
|
||||
}
|
||||
public function __destruct()
|
||||
{
|
||||
foreach ($this->handles as $id => $handle) {
|
||||
\curl_close($handle);
|
||||
unset($this->handles[$id]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,13 +11,16 @@ interface CurlFactoryInterface
|
||||
* @param RequestInterface $request Request
|
||||
* @param array $options Transfer options
|
||||
*
|
||||
* @return EasyHandle
|
||||
* @throws \RuntimeException when an option cannot be applied
|
||||
*/
|
||||
public function create(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options) : \YoastSEO_Vendor\GuzzleHttp\Handler\EasyHandle;
|
||||
public function create(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options);
|
||||
/**
|
||||
* Release an easy handle, allowing it to be reused or closed.
|
||||
*
|
||||
* This function must call unset on the easy handle's "handle" property.
|
||||
*
|
||||
* @param EasyHandle $easy
|
||||
*/
|
||||
public function release(\YoastSEO_Vendor\GuzzleHttp\Handler\EasyHandle $easy) : void;
|
||||
public function release(\YoastSEO_Vendor\GuzzleHttp\Handler\EasyHandle $easy);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace YoastSEO_Vendor\GuzzleHttp\Handler;
|
||||
|
||||
use YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface;
|
||||
use YoastSEO_Vendor\GuzzleHttp\Psr7;
|
||||
use YoastSEO_Vendor\Psr\Http\Message\RequestInterface;
|
||||
/**
|
||||
* HTTP handler that uses cURL easy handles as a transport layer.
|
||||
@@ -10,27 +10,23 @@ use YoastSEO_Vendor\Psr\Http\Message\RequestInterface;
|
||||
* When using the CurlHandler, custom curl options can be specified as an
|
||||
* associative array of curl option constants mapping to values in the
|
||||
* **curl** key of the "client" key of the request.
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class CurlHandler
|
||||
{
|
||||
/**
|
||||
* @var CurlFactoryInterface
|
||||
*/
|
||||
/** @var CurlFactoryInterface */
|
||||
private $factory;
|
||||
/**
|
||||
* Accepts an associative array of options:
|
||||
*
|
||||
* - handle_factory: Optional curl factory used to create cURL handles.
|
||||
* - factory: Optional curl factory used to create cURL handles.
|
||||
*
|
||||
* @param array{handle_factory?: ?CurlFactoryInterface} $options Array of options to use with the handler
|
||||
* @param array $options Array of options to use with the handler
|
||||
*/
|
||||
public function __construct(array $options = [])
|
||||
{
|
||||
$this->factory = $options['handle_factory'] ?? new \YoastSEO_Vendor\GuzzleHttp\Handler\CurlFactory(3);
|
||||
$this->factory = isset($options['handle_factory']) ? $options['handle_factory'] : new \YoastSEO_Vendor\GuzzleHttp\Handler\CurlFactory(3);
|
||||
}
|
||||
public function __invoke(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
|
||||
public function __invoke(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options)
|
||||
{
|
||||
if (isset($options['delay'])) {
|
||||
\usleep($options['delay'] * 1000);
|
||||
|
||||
@@ -4,7 +4,6 @@ namespace YoastSEO_Vendor\GuzzleHttp\Handler;
|
||||
|
||||
use YoastSEO_Vendor\GuzzleHttp\Promise as P;
|
||||
use YoastSEO_Vendor\GuzzleHttp\Promise\Promise;
|
||||
use YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface;
|
||||
use YoastSEO_Vendor\GuzzleHttp\Utils;
|
||||
use YoastSEO_Vendor\Psr\Http\Message\RequestInterface;
|
||||
/**
|
||||
@@ -14,40 +13,17 @@ use YoastSEO_Vendor\Psr\Http\Message\RequestInterface;
|
||||
* associative array of curl option constants mapping to values in the
|
||||
* **curl** key of the provided request options.
|
||||
*
|
||||
* @final
|
||||
* @property resource $_mh Internal use only. Lazy loaded multi-handle.
|
||||
*/
|
||||
class CurlMultiHandler
|
||||
{
|
||||
/**
|
||||
* @var CurlFactoryInterface
|
||||
*/
|
||||
/** @var CurlFactoryInterface */
|
||||
private $factory;
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $selectTimeout;
|
||||
/**
|
||||
* @var int Will be higher than 0 when `curl_multi_exec` is still running.
|
||||
*/
|
||||
private $active = 0;
|
||||
/**
|
||||
* @var array Request entry handles, indexed by handle id in `addRequest`.
|
||||
*
|
||||
* @see CurlMultiHandler::addRequest
|
||||
*/
|
||||
private $active;
|
||||
private $handles = [];
|
||||
/**
|
||||
* @var array<int, float> An array of delay times, indexed by handle id in `addRequest`.
|
||||
*
|
||||
* @see CurlMultiHandler::addRequest
|
||||
*/
|
||||
private $delays = [];
|
||||
/**
|
||||
* @var array<mixed> An associative array of CURLMOPT_* options and corresponding values for curl_multi_setopt()
|
||||
*/
|
||||
private $options = [];
|
||||
/** @var resource|\CurlMultiHandle */
|
||||
private $_mh;
|
||||
/**
|
||||
* This handler accepts the following options:
|
||||
*
|
||||
@@ -56,46 +32,34 @@ class CurlMultiHandler
|
||||
* out while selecting curl handles. Defaults to 1 second.
|
||||
* - options: An associative array of CURLMOPT_* options and
|
||||
* corresponding values for curl_multi_setopt()
|
||||
*
|
||||
* @param array $options
|
||||
*/
|
||||
public function __construct(array $options = [])
|
||||
{
|
||||
$this->factory = $options['handle_factory'] ?? new \YoastSEO_Vendor\GuzzleHttp\Handler\CurlFactory(50);
|
||||
$this->factory = isset($options['handle_factory']) ? $options['handle_factory'] : new \YoastSEO_Vendor\GuzzleHttp\Handler\CurlFactory(50);
|
||||
if (isset($options['select_timeout'])) {
|
||||
$this->selectTimeout = $options['select_timeout'];
|
||||
} elseif ($selectTimeout = \YoastSEO_Vendor\GuzzleHttp\Utils::getenv('GUZZLE_CURL_SELECT_TIMEOUT')) {
|
||||
@\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);
|
||||
$this->selectTimeout = (int) $selectTimeout;
|
||||
} elseif ($selectTimeout = \getenv('GUZZLE_CURL_SELECT_TIMEOUT')) {
|
||||
$this->selectTimeout = $selectTimeout;
|
||||
} else {
|
||||
$this->selectTimeout = 1;
|
||||
}
|
||||
$this->options = $options['options'] ?? [];
|
||||
// unsetting the property forces the first access to go through
|
||||
// __get().
|
||||
unset($this->_mh);
|
||||
$this->options = isset($options['options']) ? $options['options'] : [];
|
||||
}
|
||||
/**
|
||||
* @param string $name
|
||||
*
|
||||
* @return resource|\CurlMultiHandle
|
||||
*
|
||||
* @throws \BadMethodCallException when another field as `_mh` will be gotten
|
||||
* @throws \RuntimeException when curl can not initialize a multi handle
|
||||
*/
|
||||
public function __get($name)
|
||||
{
|
||||
if ($name !== '_mh') {
|
||||
throw new \BadMethodCallException("Can not get other property as '_mh'.");
|
||||
if ($name === '_mh') {
|
||||
$this->_mh = \curl_multi_init();
|
||||
foreach ($this->options as $option => $value) {
|
||||
// A warning is raised in case of a wrong option.
|
||||
\curl_multi_setopt($this->_mh, $option, $value);
|
||||
}
|
||||
// Further calls to _mh will return the value directly, without entering the
|
||||
// __get() method at all.
|
||||
return $this->_mh;
|
||||
}
|
||||
$multiHandle = \curl_multi_init();
|
||||
if (\false === $multiHandle) {
|
||||
throw new \RuntimeException('Can not initialize curl multi handle.');
|
||||
}
|
||||
$this->_mh = $multiHandle;
|
||||
foreach ($this->options as $option => $value) {
|
||||
// A warning is raised in case of a wrong option.
|
||||
\curl_multi_setopt($this->_mh, $option, $value);
|
||||
}
|
||||
return $this->_mh;
|
||||
throw new \BadMethodCallException();
|
||||
}
|
||||
public function __destruct()
|
||||
{
|
||||
@@ -104,7 +68,7 @@ class CurlMultiHandler
|
||||
unset($this->_mh);
|
||||
}
|
||||
}
|
||||
public function __invoke(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
|
||||
public function __invoke(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options)
|
||||
{
|
||||
$easy = $this->factory->create($request, $options);
|
||||
$id = (int) $easy->handle;
|
||||
@@ -117,7 +81,7 @@ class CurlMultiHandler
|
||||
/**
|
||||
* Ticks the curl event loop.
|
||||
*/
|
||||
public function tick() : void
|
||||
public function tick()
|
||||
{
|
||||
// Add any delayed handles if needed.
|
||||
if ($this->delays) {
|
||||
@@ -130,7 +94,7 @@ class CurlMultiHandler
|
||||
}
|
||||
}
|
||||
// Step through the task queue which may add additional requests.
|
||||
\YoastSEO_Vendor\GuzzleHttp\Promise\Utils::queue()->run();
|
||||
\YoastSEO_Vendor\GuzzleHttp\Promise\queue()->run();
|
||||
if ($this->active && \curl_multi_select($this->_mh, $this->selectTimeout) === -1) {
|
||||
// Perform a usleep if a select returns -1.
|
||||
// See: https://bugs.php.net/bug.php?id=61141
|
||||
@@ -143,9 +107,9 @@ class CurlMultiHandler
|
||||
/**
|
||||
* Runs until all outstanding connections have completed.
|
||||
*/
|
||||
public function execute() : void
|
||||
public function execute()
|
||||
{
|
||||
$queue = \YoastSEO_Vendor\GuzzleHttp\Promise\Utils::queue();
|
||||
$queue = \YoastSEO_Vendor\GuzzleHttp\Promise\queue();
|
||||
while ($this->handles || !$queue->isEmpty()) {
|
||||
// If there are no transfers, then sleep for the next delay
|
||||
if (!$this->active && $this->delays) {
|
||||
@@ -154,7 +118,7 @@ class CurlMultiHandler
|
||||
$this->tick();
|
||||
}
|
||||
}
|
||||
private function addRequest(array $entry) : void
|
||||
private function addRequest(array $entry)
|
||||
{
|
||||
$easy = $entry['easy'];
|
||||
$id = (int) $easy->handle;
|
||||
@@ -172,11 +136,8 @@ class CurlMultiHandler
|
||||
*
|
||||
* @return bool True on success, false on failure.
|
||||
*/
|
||||
private function cancel($id) : bool
|
||||
private function cancel($id)
|
||||
{
|
||||
if (!\is_int($id)) {
|
||||
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__);
|
||||
}
|
||||
// Cannot cancel if it has been processed.
|
||||
if (!isset($this->handles[$id])) {
|
||||
return \false;
|
||||
@@ -187,13 +148,9 @@ class CurlMultiHandler
|
||||
\curl_close($handle);
|
||||
return \true;
|
||||
}
|
||||
private function processMessages() : void
|
||||
private function processMessages()
|
||||
{
|
||||
while ($done = \curl_multi_info_read($this->_mh)) {
|
||||
if ($done['msg'] !== \CURLMSG_DONE) {
|
||||
// if it's not done, then it would be premature to remove the handle. ref https://github.com/guzzle/guzzle/pull/2892#issuecomment-945150216
|
||||
continue;
|
||||
}
|
||||
$id = (int) $done['handle'];
|
||||
\curl_multi_remove_handle($this->_mh, $done['handle']);
|
||||
if (!isset($this->handles[$id])) {
|
||||
@@ -206,7 +163,7 @@ class CurlMultiHandler
|
||||
$entry['deferred']->resolve(\YoastSEO_Vendor\GuzzleHttp\Handler\CurlFactory::finish($this, $entry['easy'], $this->factory));
|
||||
}
|
||||
}
|
||||
private function timeToNext() : int
|
||||
private function timeToNext()
|
||||
{
|
||||
$currentTime = \YoastSEO_Vendor\GuzzleHttp\Utils::currentTime();
|
||||
$nextTime = \PHP_INT_MAX;
|
||||
@@ -215,6 +172,6 @@ class CurlMultiHandler
|
||||
$nextTime = $time;
|
||||
}
|
||||
}
|
||||
return (int) \max(0, $nextTime - $currentTime) * 1000000;
|
||||
return \max(0, $nextTime - $currentTime) * 1000000;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
namespace YoastSEO_Vendor\GuzzleHttp\Handler;
|
||||
|
||||
use YoastSEO_Vendor\GuzzleHttp\Psr7\Response;
|
||||
use YoastSEO_Vendor\GuzzleHttp\Utils;
|
||||
use YoastSEO_Vendor\Psr\Http\Message\RequestInterface;
|
||||
use YoastSEO_Vendor\Psr\Http\Message\ResponseInterface;
|
||||
use YoastSEO_Vendor\Psr\Http\Message\StreamInterface;
|
||||
@@ -14,52 +13,36 @@ use YoastSEO_Vendor\Psr\Http\Message\StreamInterface;
|
||||
*/
|
||||
final class EasyHandle
|
||||
{
|
||||
/**
|
||||
* @var resource|\CurlHandle cURL resource
|
||||
*/
|
||||
/** @var resource cURL resource */
|
||||
public $handle;
|
||||
/**
|
||||
* @var StreamInterface Where data is being written
|
||||
*/
|
||||
/** @var StreamInterface Where data is being written */
|
||||
public $sink;
|
||||
/**
|
||||
* @var array Received HTTP headers so far
|
||||
*/
|
||||
/** @var array Received HTTP headers so far */
|
||||
public $headers = [];
|
||||
/**
|
||||
* @var ResponseInterface|null Received response (if any)
|
||||
*/
|
||||
/** @var ResponseInterface Received response (if any) */
|
||||
public $response;
|
||||
/**
|
||||
* @var RequestInterface Request being sent
|
||||
*/
|
||||
/** @var RequestInterface Request being sent */
|
||||
public $request;
|
||||
/**
|
||||
* @var array Request options
|
||||
*/
|
||||
/** @var array Request options */
|
||||
public $options = [];
|
||||
/**
|
||||
* @var int cURL error number (if any)
|
||||
*/
|
||||
/** @var int cURL error number (if any) */
|
||||
public $errno = 0;
|
||||
/**
|
||||
* @var \Throwable|null Exception during on_headers (if any)
|
||||
*/
|
||||
/** @var \Exception Exception during on_headers (if any) */
|
||||
public $onHeadersException;
|
||||
/**
|
||||
* @var \Exception|null Exception during createResponse (if any)
|
||||
*/
|
||||
public $createResponseException;
|
||||
/**
|
||||
* Attach a response to the easy handle based on the received headers.
|
||||
*
|
||||
* @throws \RuntimeException if no headers have been received or the first
|
||||
* header line is invalid.
|
||||
* @throws \RuntimeException if no headers have been received.
|
||||
*/
|
||||
public function createResponse() : void
|
||||
public function createResponse()
|
||||
{
|
||||
[$ver, $status, $reason, $headers] = \YoastSEO_Vendor\GuzzleHttp\Handler\HeaderProcessor::parseHeaders($this->headers);
|
||||
$normalizedKeys = \YoastSEO_Vendor\GuzzleHttp\Utils::normalizeHeaderKeys($headers);
|
||||
if (empty($this->headers)) {
|
||||
throw new \RuntimeException('No headers have been received');
|
||||
}
|
||||
// HTTP-version SP status-code SP reason-phrase
|
||||
$startLine = \explode(' ', \array_shift($this->headers), 3);
|
||||
$headers = \YoastSEO_Vendor\GuzzleHttp\headers_from_lines($this->headers);
|
||||
$normalizedKeys = \YoastSEO_Vendor\GuzzleHttp\normalize_header_keys($headers);
|
||||
if (!empty($this->options['decode_content']) && isset($normalizedKeys['content-encoding'])) {
|
||||
$headers['x-encoded-content-encoding'] = $headers[$normalizedKeys['content-encoding']];
|
||||
unset($headers[$normalizedKeys['content-encoding']]);
|
||||
@@ -74,15 +57,8 @@ final class EasyHandle
|
||||
}
|
||||
}
|
||||
// Attach a response to the easy handle with the parsed headers.
|
||||
$this->response = new \YoastSEO_Vendor\GuzzleHttp\Psr7\Response($status, $headers, $this->sink, $ver, $reason);
|
||||
$this->response = new \YoastSEO_Vendor\GuzzleHttp\Psr7\Response($startLine[1], $headers, $this->sink, \substr($startLine[0], 5), isset($startLine[2]) ? (string) $startLine[2] : null);
|
||||
}
|
||||
/**
|
||||
* @param string $name
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws \BadMethodCallException
|
||||
*/
|
||||
public function __get($name)
|
||||
{
|
||||
$msg = $name === 'handle' ? 'The EasyHandle has been released' : 'Invalid property: ' . $name;
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace YoastSEO_Vendor\GuzzleHttp\Handler;
|
||||
|
||||
use YoastSEO_Vendor\GuzzleHttp\Utils;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class HeaderProcessor
|
||||
{
|
||||
/**
|
||||
* Returns the HTTP version, status code, reason phrase, and headers.
|
||||
*
|
||||
* @param string[] $headers
|
||||
*
|
||||
* @return array{0:string, 1:int, 2:?string, 3:array}
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public static function parseHeaders(array $headers) : array
|
||||
{
|
||||
if ($headers === []) {
|
||||
throw new \RuntimeException('Expected a non-empty array of header data');
|
||||
}
|
||||
$parts = \explode(' ', \array_shift($headers), 3);
|
||||
$version = \explode('/', $parts[0])[1] ?? null;
|
||||
if ($version === null) {
|
||||
throw new \RuntimeException('HTTP version missing from header data');
|
||||
}
|
||||
$status = $parts[1] ?? null;
|
||||
if ($status === null) {
|
||||
throw new \RuntimeException('HTTP status code missing from header data');
|
||||
}
|
||||
return [$version, (int) $status, $parts[2] ?? null, \YoastSEO_Vendor\GuzzleHttp\Utils::headersFromLines($headers)];
|
||||
}
|
||||
}
|
||||
@@ -4,77 +4,59 @@ namespace YoastSEO_Vendor\GuzzleHttp\Handler;
|
||||
|
||||
use YoastSEO_Vendor\GuzzleHttp\Exception\RequestException;
|
||||
use YoastSEO_Vendor\GuzzleHttp\HandlerStack;
|
||||
use YoastSEO_Vendor\GuzzleHttp\Promise as P;
|
||||
use YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface;
|
||||
use YoastSEO_Vendor\GuzzleHttp\Promise\RejectedPromise;
|
||||
use YoastSEO_Vendor\GuzzleHttp\TransferStats;
|
||||
use YoastSEO_Vendor\GuzzleHttp\Utils;
|
||||
use YoastSEO_Vendor\Psr\Http\Message\RequestInterface;
|
||||
use YoastSEO_Vendor\Psr\Http\Message\ResponseInterface;
|
||||
use YoastSEO_Vendor\Psr\Http\Message\StreamInterface;
|
||||
/**
|
||||
* Handler that returns responses or throw exceptions from a queue.
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class MockHandler implements \Countable
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $queue = [];
|
||||
/**
|
||||
* @var RequestInterface|null
|
||||
*/
|
||||
private $lastRequest;
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $lastOptions = [];
|
||||
/**
|
||||
* @var callable|null
|
||||
*/
|
||||
private $lastOptions;
|
||||
private $onFulfilled;
|
||||
/**
|
||||
* @var callable|null
|
||||
*/
|
||||
private $onRejected;
|
||||
/**
|
||||
* Creates a new MockHandler that uses the default handler stack list of
|
||||
* middlewares.
|
||||
*
|
||||
* @param array|null $queue Array of responses, callables, or exceptions.
|
||||
* @param callable|null $onFulfilled Callback to invoke when the return value is fulfilled.
|
||||
* @param callable|null $onRejected Callback to invoke when the return value is rejected.
|
||||
* @param array $queue Array of responses, callables, or exceptions.
|
||||
* @param callable $onFulfilled Callback to invoke when the return value is fulfilled.
|
||||
* @param callable $onRejected Callback to invoke when the return value is rejected.
|
||||
*
|
||||
* @return HandlerStack
|
||||
*/
|
||||
public static function createWithMiddleware(array $queue = null, callable $onFulfilled = null, callable $onRejected = null) : \YoastSEO_Vendor\GuzzleHttp\HandlerStack
|
||||
public static function createWithMiddleware(array $queue = null, callable $onFulfilled = null, callable $onRejected = null)
|
||||
{
|
||||
return \YoastSEO_Vendor\GuzzleHttp\HandlerStack::create(new self($queue, $onFulfilled, $onRejected));
|
||||
}
|
||||
/**
|
||||
* The passed in value must be an array of
|
||||
* {@see \Psr\Http\Message\ResponseInterface} objects, Exceptions,
|
||||
* {@see Psr7\Http\Message\ResponseInterface} objects, Exceptions,
|
||||
* callables, or Promises.
|
||||
*
|
||||
* @param array<int, mixed>|null $queue The parameters to be passed to the append function, as an indexed array.
|
||||
* @param callable|null $onFulfilled Callback to invoke when the return value is fulfilled.
|
||||
* @param callable|null $onRejected Callback to invoke when the return value is rejected.
|
||||
* @param array $queue
|
||||
* @param callable $onFulfilled Callback to invoke when the return value is fulfilled.
|
||||
* @param callable $onRejected Callback to invoke when the return value is rejected.
|
||||
*/
|
||||
public function __construct(array $queue = null, callable $onFulfilled = null, callable $onRejected = null)
|
||||
{
|
||||
$this->onFulfilled = $onFulfilled;
|
||||
$this->onRejected = $onRejected;
|
||||
if ($queue) {
|
||||
// array_values included for BC
|
||||
$this->append(...\array_values($queue));
|
||||
\call_user_func_array([$this, 'append'], $queue);
|
||||
}
|
||||
}
|
||||
public function __invoke(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
|
||||
public function __invoke(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options)
|
||||
{
|
||||
if (!$this->queue) {
|
||||
throw new \OutOfBoundsException('Mock queue is empty');
|
||||
}
|
||||
if (isset($options['delay']) && \is_numeric($options['delay'])) {
|
||||
\usleep((int) $options['delay'] * 1000);
|
||||
\usleep($options['delay'] * 1000);
|
||||
}
|
||||
$this->lastRequest = $request;
|
||||
$this->lastOptions = $options;
|
||||
@@ -91,15 +73,15 @@ class MockHandler implements \Countable
|
||||
}
|
||||
}
|
||||
if (\is_callable($response)) {
|
||||
$response = $response($request, $options);
|
||||
$response = \call_user_func($response, $request, $options);
|
||||
}
|
||||
$response = $response instanceof \Throwable ? \YoastSEO_Vendor\GuzzleHttp\Promise\Create::rejectionFor($response) : \YoastSEO_Vendor\GuzzleHttp\Promise\Create::promiseFor($response);
|
||||
return $response->then(function (?\YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $value) use($request, $options) {
|
||||
$response = $response instanceof \Exception ? \YoastSEO_Vendor\GuzzleHttp\Promise\rejection_for($response) : \YoastSEO_Vendor\GuzzleHttp\Promise\promise_for($response);
|
||||
return $response->then(function ($value) use($request, $options) {
|
||||
$this->invokeStats($request, $options, $value);
|
||||
if ($this->onFulfilled) {
|
||||
($this->onFulfilled)($value);
|
||||
\call_user_func($this->onFulfilled, $value);
|
||||
}
|
||||
if ($value !== null && isset($options['sink'])) {
|
||||
if (isset($options['sink'])) {
|
||||
$contents = (string) $value->getBody();
|
||||
$sink = $options['sink'];
|
||||
if (\is_resource($sink)) {
|
||||
@@ -114,61 +96,62 @@ class MockHandler implements \Countable
|
||||
}, function ($reason) use($request, $options) {
|
||||
$this->invokeStats($request, $options, null, $reason);
|
||||
if ($this->onRejected) {
|
||||
($this->onRejected)($reason);
|
||||
\call_user_func($this->onRejected, $reason);
|
||||
}
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Promise\Create::rejectionFor($reason);
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Promise\rejection_for($reason);
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Adds one or more variadic requests, exceptions, callables, or promises
|
||||
* to the queue.
|
||||
*
|
||||
* @param mixed ...$values
|
||||
*/
|
||||
public function append(...$values) : void
|
||||
public function append()
|
||||
{
|
||||
foreach ($values as $value) {
|
||||
if ($value instanceof \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface || $value instanceof \Throwable || $value instanceof \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface || \is_callable($value)) {
|
||||
foreach (\func_get_args() as $value) {
|
||||
if ($value instanceof \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface || $value instanceof \Exception || $value instanceof \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface || \is_callable($value)) {
|
||||
$this->queue[] = $value;
|
||||
} else {
|
||||
throw new \TypeError('Expected a Response, Promise, Throwable or callable. Found ' . \YoastSEO_Vendor\GuzzleHttp\Utils::describeType($value));
|
||||
throw new \InvalidArgumentException('Expected a response or ' . 'exception. Found ' . \YoastSEO_Vendor\GuzzleHttp\describe_type($value));
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Get the last received request.
|
||||
*
|
||||
* @return RequestInterface
|
||||
*/
|
||||
public function getLastRequest() : ?\YoastSEO_Vendor\Psr\Http\Message\RequestInterface
|
||||
public function getLastRequest()
|
||||
{
|
||||
return $this->lastRequest;
|
||||
}
|
||||
/**
|
||||
* Get the last received request options.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getLastOptions() : array
|
||||
public function getLastOptions()
|
||||
{
|
||||
return $this->lastOptions;
|
||||
}
|
||||
/**
|
||||
* Returns the number of remaining items in the queue.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function count() : int
|
||||
public function count()
|
||||
{
|
||||
return \count($this->queue);
|
||||
}
|
||||
public function reset() : void
|
||||
public function reset()
|
||||
{
|
||||
$this->queue = [];
|
||||
}
|
||||
/**
|
||||
* @param mixed $reason Promise or reason.
|
||||
*/
|
||||
private function invokeStats(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options, \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response = null, $reason = null) : void
|
||||
private function invokeStats(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options, \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response = null, $reason = null)
|
||||
{
|
||||
if (isset($options['on_stats'])) {
|
||||
$transferTime = $options['transfer_time'] ?? 0;
|
||||
$transferTime = isset($options['transfer_time']) ? $options['transfer_time'] : 0;
|
||||
$stats = new \YoastSEO_Vendor\GuzzleHttp\TransferStats($request, $response, $transferTime, $reason);
|
||||
$options['on_stats']($stats);
|
||||
\call_user_func($options['on_stats'], $stats);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,13 +2,10 @@
|
||||
|
||||
namespace YoastSEO_Vendor\GuzzleHttp\Handler;
|
||||
|
||||
use YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface;
|
||||
use YoastSEO_Vendor\GuzzleHttp\RequestOptions;
|
||||
use YoastSEO_Vendor\Psr\Http\Message\RequestInterface;
|
||||
/**
|
||||
* Provides basic proxies for handlers.
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class Proxy
|
||||
{
|
||||
@@ -16,14 +13,14 @@ class Proxy
|
||||
* Sends synchronous requests to a specific handler while sending all other
|
||||
* requests to another handler.
|
||||
*
|
||||
* @param callable(\Psr\Http\Message\RequestInterface, array): \GuzzleHttp\Promise\PromiseInterface $default Handler used for normal responses
|
||||
* @param callable(\Psr\Http\Message\RequestInterface, array): \GuzzleHttp\Promise\PromiseInterface $sync Handler used for synchronous responses.
|
||||
* @param callable $default Handler used for normal responses
|
||||
* @param callable $sync Handler used for synchronous responses.
|
||||
*
|
||||
* @return callable(\Psr\Http\Message\RequestInterface, array): \GuzzleHttp\Promise\PromiseInterface Returns the composed handler.
|
||||
* @return callable Returns the composed handler.
|
||||
*/
|
||||
public static function wrapSync(callable $default, callable $sync) : callable
|
||||
public static function wrapSync(callable $default, callable $sync)
|
||||
{
|
||||
return static function (\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options) use($default, $sync) : PromiseInterface {
|
||||
return function (\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options) use($default, $sync) {
|
||||
return empty($options[\YoastSEO_Vendor\GuzzleHttp\RequestOptions::SYNCHRONOUS]) ? $default($request, $options) : $sync($request, $options);
|
||||
};
|
||||
}
|
||||
@@ -35,14 +32,14 @@ class Proxy
|
||||
* performance benefits of curl while still supporting true streaming
|
||||
* through the StreamHandler.
|
||||
*
|
||||
* @param callable(\Psr\Http\Message\RequestInterface, array): \GuzzleHttp\Promise\PromiseInterface $default Handler used for non-streaming responses
|
||||
* @param callable(\Psr\Http\Message\RequestInterface, array): \GuzzleHttp\Promise\PromiseInterface $streaming Handler used for streaming responses
|
||||
* @param callable $default Handler used for non-streaming responses
|
||||
* @param callable $streaming Handler used for streaming responses
|
||||
*
|
||||
* @return callable(\Psr\Http\Message\RequestInterface, array): \GuzzleHttp\Promise\PromiseInterface Returns the composed handler.
|
||||
* @return callable Returns the composed handler.
|
||||
*/
|
||||
public static function wrapStreaming(callable $default, callable $streaming) : callable
|
||||
public static function wrapStreaming(callable $default, callable $streaming)
|
||||
{
|
||||
return static function (\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options) use($default, $streaming) : PromiseInterface {
|
||||
return function (\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options) use($default, $streaming) {
|
||||
return empty($options['stream']) ? $default($request, $options) : $streaming($request, $options);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ namespace YoastSEO_Vendor\GuzzleHttp\Handler;
|
||||
|
||||
use YoastSEO_Vendor\GuzzleHttp\Exception\ConnectException;
|
||||
use YoastSEO_Vendor\GuzzleHttp\Exception\RequestException;
|
||||
use YoastSEO_Vendor\GuzzleHttp\Promise as P;
|
||||
use YoastSEO_Vendor\GuzzleHttp\Promise\FulfilledPromise;
|
||||
use YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface;
|
||||
use YoastSEO_Vendor\GuzzleHttp\Psr7;
|
||||
@@ -13,25 +12,21 @@ use YoastSEO_Vendor\GuzzleHttp\Utils;
|
||||
use YoastSEO_Vendor\Psr\Http\Message\RequestInterface;
|
||||
use YoastSEO_Vendor\Psr\Http\Message\ResponseInterface;
|
||||
use YoastSEO_Vendor\Psr\Http\Message\StreamInterface;
|
||||
use YoastSEO_Vendor\Psr\Http\Message\UriInterface;
|
||||
/**
|
||||
* HTTP handler that uses PHP's HTTP stream wrapper.
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class StreamHandler
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $lastHeaders = [];
|
||||
/**
|
||||
* Sends an HTTP request.
|
||||
*
|
||||
* @param RequestInterface $request Request to send.
|
||||
* @param array $options Request transfer options.
|
||||
*
|
||||
* @return PromiseInterface
|
||||
*/
|
||||
public function __invoke(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
|
||||
public function __invoke(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options)
|
||||
{
|
||||
// Sleep if there is a delay specified.
|
||||
if (isset($options['delay'])) {
|
||||
@@ -53,50 +48,44 @@ class StreamHandler
|
||||
// Determine if the error was a networking error.
|
||||
$message = $e->getMessage();
|
||||
// This list can probably get more comprehensive.
|
||||
if (\false !== \strpos($message, 'getaddrinfo') || \false !== \strpos($message, 'Connection refused') || \false !== \strpos($message, "couldn't connect to host") || \false !== \strpos($message, 'connection attempt failed')) {
|
||||
if (\strpos($message, 'getaddrinfo') || \strpos($message, 'Connection refused') || \strpos($message, "couldn't connect to host") || \strpos($message, "connection attempt failed")) {
|
||||
$e = new \YoastSEO_Vendor\GuzzleHttp\Exception\ConnectException($e->getMessage(), $request, $e);
|
||||
} else {
|
||||
$e = \YoastSEO_Vendor\GuzzleHttp\Exception\RequestException::wrapException($request, $e);
|
||||
}
|
||||
$e = \YoastSEO_Vendor\GuzzleHttp\Exception\RequestException::wrapException($request, $e);
|
||||
$this->invokeStats($options, $request, $startTime, null, $e);
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Promise\Create::rejectionFor($e);
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Promise\rejection_for($e);
|
||||
}
|
||||
}
|
||||
private function invokeStats(array $options, \YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, ?float $startTime, \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response = null, \Throwable $error = null) : void
|
||||
private function invokeStats(array $options, \YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, $startTime, \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response = null, $error = null)
|
||||
{
|
||||
if (isset($options['on_stats'])) {
|
||||
$stats = new \YoastSEO_Vendor\GuzzleHttp\TransferStats($request, $response, \YoastSEO_Vendor\GuzzleHttp\Utils::currentTime() - $startTime, $error, []);
|
||||
$options['on_stats']($stats);
|
||||
\call_user_func($options['on_stats'], $stats);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @param resource $stream
|
||||
*/
|
||||
private function createResponse(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options, $stream, ?float $startTime) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
|
||||
private function createResponse(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options, $stream, $startTime)
|
||||
{
|
||||
$hdrs = $this->lastHeaders;
|
||||
$this->lastHeaders = [];
|
||||
try {
|
||||
[$ver, $status, $reason, $headers] = \YoastSEO_Vendor\GuzzleHttp\Handler\HeaderProcessor::parseHeaders($hdrs);
|
||||
} catch (\Exception $e) {
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Promise\Create::rejectionFor(new \YoastSEO_Vendor\GuzzleHttp\Exception\RequestException('An error was encountered while creating the response', $request, null, $e));
|
||||
}
|
||||
[$stream, $headers] = $this->checkDecode($options, $headers, $stream);
|
||||
$stream = \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::streamFor($stream);
|
||||
$parts = \explode(' ', \array_shift($hdrs), 3);
|
||||
$ver = \explode('/', $parts[0])[1];
|
||||
$status = $parts[1];
|
||||
$reason = isset($parts[2]) ? $parts[2] : null;
|
||||
$headers = \YoastSEO_Vendor\GuzzleHttp\headers_from_lines($hdrs);
|
||||
list($stream, $headers) = $this->checkDecode($options, $headers, $stream);
|
||||
$stream = \YoastSEO_Vendor\GuzzleHttp\Psr7\stream_for($stream);
|
||||
$sink = $stream;
|
||||
if (\strcasecmp('HEAD', $request->getMethod())) {
|
||||
$sink = $this->createSink($stream, $options);
|
||||
}
|
||||
try {
|
||||
$response = new \YoastSEO_Vendor\GuzzleHttp\Psr7\Response($status, $headers, $sink, $ver, $reason);
|
||||
} catch (\Exception $e) {
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Promise\Create::rejectionFor(new \YoastSEO_Vendor\GuzzleHttp\Exception\RequestException('An error was encountered while creating the response', $request, null, $e));
|
||||
}
|
||||
$response = new \YoastSEO_Vendor\GuzzleHttp\Psr7\Response($status, $headers, $sink, $ver, $reason);
|
||||
if (isset($options['on_headers'])) {
|
||||
try {
|
||||
$options['on_headers']($response);
|
||||
} catch (\Exception $e) {
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Promise\Create::rejectionFor(new \YoastSEO_Vendor\GuzzleHttp\Exception\RequestException('An error was encountered during the on_headers event', $request, $response, $e));
|
||||
$msg = 'An error was encountered during the on_headers event';
|
||||
$ex = new \YoastSEO_Vendor\GuzzleHttp\Exception\RequestException($msg, $request, $response, $e);
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Promise\rejection_for($ex);
|
||||
}
|
||||
}
|
||||
// Do not drain when the request is a HEAD request because they have
|
||||
@@ -107,26 +96,23 @@ class StreamHandler
|
||||
$this->invokeStats($options, $request, $startTime, $response, null);
|
||||
return new \YoastSEO_Vendor\GuzzleHttp\Promise\FulfilledPromise($response);
|
||||
}
|
||||
private function createSink(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $stream, array $options) : \YoastSEO_Vendor\Psr\Http\Message\StreamInterface
|
||||
private function createSink(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $stream, array $options)
|
||||
{
|
||||
if (!empty($options['stream'])) {
|
||||
return $stream;
|
||||
}
|
||||
$sink = $options['sink'] ?? \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::tryFopen('php://temp', 'r+');
|
||||
return \is_string($sink) ? new \YoastSEO_Vendor\GuzzleHttp\Psr7\LazyOpenStream($sink, 'w+') : \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::streamFor($sink);
|
||||
$sink = isset($options['sink']) ? $options['sink'] : \fopen('php://temp', 'r+');
|
||||
return \is_string($sink) ? new \YoastSEO_Vendor\GuzzleHttp\Psr7\LazyOpenStream($sink, 'w+') : \YoastSEO_Vendor\GuzzleHttp\Psr7\stream_for($sink);
|
||||
}
|
||||
/**
|
||||
* @param resource $stream
|
||||
*/
|
||||
private function checkDecode(array $options, array $headers, $stream) : array
|
||||
private function checkDecode(array $options, array $headers, $stream)
|
||||
{
|
||||
// Automatically decode responses when instructed.
|
||||
if (!empty($options['decode_content'])) {
|
||||
$normalizedKeys = \YoastSEO_Vendor\GuzzleHttp\Utils::normalizeHeaderKeys($headers);
|
||||
$normalizedKeys = \YoastSEO_Vendor\GuzzleHttp\normalize_header_keys($headers);
|
||||
if (isset($normalizedKeys['content-encoding'])) {
|
||||
$encoding = $headers[$normalizedKeys['content-encoding']];
|
||||
if ($encoding[0] === 'gzip' || $encoding[0] === 'deflate') {
|
||||
$stream = new \YoastSEO_Vendor\GuzzleHttp\Psr7\InflateStream(\YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::streamFor($stream));
|
||||
$stream = new \YoastSEO_Vendor\GuzzleHttp\Psr7\InflateStream(\YoastSEO_Vendor\GuzzleHttp\Psr7\stream_for($stream));
|
||||
$headers['x-encoded-content-encoding'] = $headers[$normalizedKeys['content-encoding']];
|
||||
// Remove content-encoding header
|
||||
unset($headers[$normalizedKeys['content-encoding']]);
|
||||
@@ -148,18 +134,21 @@ class StreamHandler
|
||||
/**
|
||||
* Drains the source stream into the "sink" client option.
|
||||
*
|
||||
* @param string $contentLength Header specifying the amount of
|
||||
* data to read.
|
||||
* @param StreamInterface $source
|
||||
* @param StreamInterface $sink
|
||||
* @param string $contentLength Header specifying the amount of
|
||||
* data to read.
|
||||
*
|
||||
* @return StreamInterface
|
||||
* @throws \RuntimeException when the sink option is invalid.
|
||||
*/
|
||||
private function drain(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $source, \YoastSEO_Vendor\Psr\Http\Message\StreamInterface $sink, string $contentLength) : \YoastSEO_Vendor\Psr\Http\Message\StreamInterface
|
||||
private function drain(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $source, \YoastSEO_Vendor\Psr\Http\Message\StreamInterface $sink, $contentLength)
|
||||
{
|
||||
// If a content-length header is provided, then stop reading once
|
||||
// that number of bytes has been read. This can prevent infinitely
|
||||
// reading from a stream when dealing with servers that do not honor
|
||||
// Connection: Close headers.
|
||||
\YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::copyToStream($source, $sink, \strlen($contentLength) > 0 && (int) $contentLength > 0 ? (int) $contentLength : -1);
|
||||
\YoastSEO_Vendor\GuzzleHttp\Psr7\copy_to_stream($source, $sink, \strlen($contentLength) > 0 && (int) $contentLength > 0 ? (int) $contentLength : -1);
|
||||
$sink->seek(0);
|
||||
$source->close();
|
||||
return $sink;
|
||||
@@ -170,21 +159,17 @@ class StreamHandler
|
||||
* @param callable $callback Callable that returns stream resource
|
||||
*
|
||||
* @return resource
|
||||
*
|
||||
* @throws \RuntimeException on error
|
||||
*/
|
||||
private function createResource(callable $callback)
|
||||
{
|
||||
$errors = [];
|
||||
\set_error_handler(static function ($_, $msg, $file, $line) use(&$errors) : bool {
|
||||
$errors = null;
|
||||
\set_error_handler(function ($_, $msg, $file, $line) use(&$errors) {
|
||||
$errors[] = ['message' => $msg, 'file' => $file, 'line' => $line];
|
||||
return \true;
|
||||
});
|
||||
try {
|
||||
$resource = $callback();
|
||||
} finally {
|
||||
\restore_error_handler();
|
||||
}
|
||||
$resource = $callback();
|
||||
\restore_error_handler();
|
||||
if (!$resource) {
|
||||
$message = 'Error creating resource: ';
|
||||
foreach ($errors as $err) {
|
||||
@@ -196,18 +181,12 @@ class StreamHandler
|
||||
}
|
||||
return $resource;
|
||||
}
|
||||
/**
|
||||
* @return resource
|
||||
*/
|
||||
private function createStream(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options)
|
||||
{
|
||||
static $methods;
|
||||
if (!$methods) {
|
||||
$methods = \array_flip(\get_class_methods(__CLASS__));
|
||||
}
|
||||
if (!\in_array($request->getUri()->getScheme(), ['http', 'https'])) {
|
||||
throw new \YoastSEO_Vendor\GuzzleHttp\Exception\RequestException(\sprintf("The scheme '%s' is not supported.", $request->getUri()->getScheme()), $request);
|
||||
}
|
||||
// HTTP/1.1 streams using the PHP stream wrapper require a
|
||||
// Connection: close header
|
||||
if ($request->getProtocolVersion() == '1.1' && !$request->hasHeader('Connection')) {
|
||||
@@ -237,19 +216,16 @@ class StreamHandler
|
||||
$context = \array_replace_recursive($context, $options['stream_context']);
|
||||
}
|
||||
// Microsoft NTLM authentication only supported with curl handler
|
||||
if (isset($options['auth'][2]) && 'ntlm' === $options['auth'][2]) {
|
||||
if (isset($options['auth']) && \is_array($options['auth']) && isset($options['auth'][2]) && 'ntlm' == $options['auth'][2]) {
|
||||
throw new \InvalidArgumentException('Microsoft NTLM authentication only supported with curl handler');
|
||||
}
|
||||
$uri = $this->resolveHost($request, $options);
|
||||
$contextResource = $this->createResource(static function () use($context, $params) {
|
||||
$context = $this->createResource(function () use($context, $params) {
|
||||
return \stream_context_create($context, $params);
|
||||
});
|
||||
return $this->createResource(function () use($uri, &$http_response_header, $contextResource, $context, $options, $request) {
|
||||
$resource = @\fopen((string) $uri, 'r', \false, $contextResource);
|
||||
$this->lastHeaders = $http_response_header ?? [];
|
||||
if (\false === $resource) {
|
||||
throw new \YoastSEO_Vendor\GuzzleHttp\Exception\ConnectException(\sprintf('Connection refused for URI %s', $uri), $request, null, $context);
|
||||
}
|
||||
return $this->createResource(function () use($uri, &$http_response_header, $context, $options) {
|
||||
$resource = \fopen((string) $uri, 'r', null, $context);
|
||||
$this->lastHeaders = $http_response_header;
|
||||
if (isset($options['read_timeout'])) {
|
||||
$readTimeout = $options['read_timeout'];
|
||||
$sec = (int) $readTimeout;
|
||||
@@ -259,28 +235,27 @@ class StreamHandler
|
||||
return $resource;
|
||||
});
|
||||
}
|
||||
private function resolveHost(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface
|
||||
private function resolveHost(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options)
|
||||
{
|
||||
$uri = $request->getUri();
|
||||
if (isset($options['force_ip_resolve']) && !\filter_var($uri->getHost(), \FILTER_VALIDATE_IP)) {
|
||||
if ('v4' === $options['force_ip_resolve']) {
|
||||
$records = \dns_get_record($uri->getHost(), \DNS_A);
|
||||
if (\false === $records || !isset($records[0]['ip'])) {
|
||||
if (!isset($records[0]['ip'])) {
|
||||
throw new \YoastSEO_Vendor\GuzzleHttp\Exception\ConnectException(\sprintf("Could not resolve IPv4 address for host '%s'", $uri->getHost()), $request);
|
||||
}
|
||||
return $uri->withHost($records[0]['ip']);
|
||||
}
|
||||
if ('v6' === $options['force_ip_resolve']) {
|
||||
$uri = $uri->withHost($records[0]['ip']);
|
||||
} elseif ('v6' === $options['force_ip_resolve']) {
|
||||
$records = \dns_get_record($uri->getHost(), \DNS_AAAA);
|
||||
if (\false === $records || !isset($records[0]['ipv6'])) {
|
||||
if (!isset($records[0]['ipv6'])) {
|
||||
throw new \YoastSEO_Vendor\GuzzleHttp\Exception\ConnectException(\sprintf("Could not resolve IPv6 address for host '%s'", $uri->getHost()), $request);
|
||||
}
|
||||
return $uri->withHost('[' . $records[0]['ipv6'] . ']');
|
||||
$uri = $uri->withHost('[' . $records[0]['ipv6'] . ']');
|
||||
}
|
||||
}
|
||||
return $uri;
|
||||
}
|
||||
private function getDefaultContext(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request) : array
|
||||
private function getDefaultContext(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request)
|
||||
{
|
||||
$headers = '';
|
||||
foreach ($request->getHeaders() as $name => $value) {
|
||||
@@ -288,9 +263,9 @@ class StreamHandler
|
||||
$headers .= "{$name}: {$val}\r\n";
|
||||
}
|
||||
}
|
||||
$context = ['http' => ['method' => $request->getMethod(), 'header' => $headers, 'protocol_version' => $request->getProtocolVersion(), 'ignore_errors' => \true, 'follow_location' => 0], 'ssl' => ['peer_name' => $request->getUri()->getHost()]];
|
||||
$context = ['http' => ['method' => $request->getMethod(), 'header' => $headers, 'protocol_version' => $request->getProtocolVersion(), 'ignore_errors' => \true, 'follow_location' => 0]];
|
||||
$body = (string) $request->getBody();
|
||||
if ('' !== $body) {
|
||||
if (!empty($body)) {
|
||||
$context['http']['content'] = $body;
|
||||
// Prevent the HTTP handler from adding a Content-Type header.
|
||||
if (!$request->hasHeader('Content-Type')) {
|
||||
@@ -300,98 +275,50 @@ class StreamHandler
|
||||
$context['http']['header'] = \rtrim($context['http']['header']);
|
||||
return $context;
|
||||
}
|
||||
/**
|
||||
* @param mixed $value as passed via Request transfer options.
|
||||
*/
|
||||
private function add_proxy(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array &$options, $value, array &$params) : void
|
||||
private function add_proxy(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, &$options, $value, &$params)
|
||||
{
|
||||
$uri = null;
|
||||
if (!\is_array($value)) {
|
||||
$uri = $value;
|
||||
$options['http']['proxy'] = $value;
|
||||
} else {
|
||||
$scheme = $request->getUri()->getScheme();
|
||||
if (isset($value[$scheme])) {
|
||||
if (!isset($value['no']) || !\YoastSEO_Vendor\GuzzleHttp\Utils::isHostInNoProxy($request->getUri()->getHost(), $value['no'])) {
|
||||
$uri = $value[$scheme];
|
||||
if (!isset($value['no']) || !\YoastSEO_Vendor\GuzzleHttp\is_host_in_noproxy($request->getUri()->getHost(), $value['no'])) {
|
||||
$options['http']['proxy'] = $value[$scheme];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!$uri) {
|
||||
return;
|
||||
}
|
||||
$parsed = $this->parse_proxy($uri);
|
||||
$options['http']['proxy'] = $parsed['proxy'];
|
||||
if ($parsed['auth']) {
|
||||
if (!isset($options['http']['header'])) {
|
||||
$options['http']['header'] = [];
|
||||
}
|
||||
$options['http']['header'] .= "\r\nProxy-Authorization: {$parsed['auth']}";
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Parses the given proxy URL to make it compatible with the format PHP's stream context expects.
|
||||
*/
|
||||
private function parse_proxy(string $url) : array
|
||||
{
|
||||
$parsed = \parse_url($url);
|
||||
if ($parsed !== \false && isset($parsed['scheme']) && $parsed['scheme'] === 'http') {
|
||||
if (isset($parsed['host']) && isset($parsed['port'])) {
|
||||
$auth = null;
|
||||
if (isset($parsed['user']) && isset($parsed['pass'])) {
|
||||
$auth = \base64_encode("{$parsed['user']}:{$parsed['pass']}");
|
||||
}
|
||||
return ['proxy' => "tcp://{$parsed['host']}:{$parsed['port']}", 'auth' => $auth ? "Basic {$auth}" : null];
|
||||
}
|
||||
}
|
||||
// Return proxy as-is.
|
||||
return ['proxy' => $url, 'auth' => null];
|
||||
}
|
||||
/**
|
||||
* @param mixed $value as passed via Request transfer options.
|
||||
*/
|
||||
private function add_timeout(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array &$options, $value, array &$params) : void
|
||||
private function add_timeout(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, &$options, $value, &$params)
|
||||
{
|
||||
if ($value > 0) {
|
||||
$options['http']['timeout'] = $value;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @param mixed $value as passed via Request transfer options.
|
||||
*/
|
||||
private function add_crypto_method(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array &$options, $value, array &$params) : void
|
||||
private function add_verify(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, &$options, $value, &$params)
|
||||
{
|
||||
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) {
|
||||
$options['http']['crypto_method'] = $value;
|
||||
return;
|
||||
}
|
||||
throw new \InvalidArgumentException('Invalid crypto_method request option: unknown version provided');
|
||||
}
|
||||
/**
|
||||
* @param mixed $value as passed via Request transfer options.
|
||||
*/
|
||||
private function add_verify(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array &$options, $value, array &$params) : void
|
||||
{
|
||||
if ($value === \false) {
|
||||
$options['ssl']['verify_peer'] = \false;
|
||||
$options['ssl']['verify_peer_name'] = \false;
|
||||
return;
|
||||
}
|
||||
if (\is_string($value)) {
|
||||
if ($value === \true) {
|
||||
// PHP 5.6 or greater will find the system cert by default. When
|
||||
// < 5.6, use the Guzzle bundled cacert.
|
||||
if (\PHP_VERSION_ID < 50600) {
|
||||
$options['ssl']['cafile'] = \YoastSEO_Vendor\GuzzleHttp\default_ca_bundle();
|
||||
}
|
||||
} elseif (\is_string($value)) {
|
||||
$options['ssl']['cafile'] = $value;
|
||||
if (!\file_exists($value)) {
|
||||
throw new \RuntimeException("SSL CA bundle not found: {$value}");
|
||||
}
|
||||
} elseif ($value !== \true) {
|
||||
} elseif ($value === \false) {
|
||||
$options['ssl']['verify_peer'] = \false;
|
||||
$options['ssl']['verify_peer_name'] = \false;
|
||||
return;
|
||||
} else {
|
||||
throw new \InvalidArgumentException('Invalid verify request option');
|
||||
}
|
||||
$options['ssl']['verify_peer'] = \true;
|
||||
$options['ssl']['verify_peer_name'] = \true;
|
||||
$options['ssl']['allow_self_signed'] = \false;
|
||||
}
|
||||
/**
|
||||
* @param mixed $value as passed via Request transfer options.
|
||||
*/
|
||||
private function add_cert(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array &$options, $value, array &$params) : void
|
||||
private function add_cert(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, &$options, $value, &$params)
|
||||
{
|
||||
if (\is_array($value)) {
|
||||
$options['ssl']['passphrase'] = $value[1];
|
||||
@@ -402,32 +329,26 @@ class StreamHandler
|
||||
}
|
||||
$options['ssl']['local_cert'] = $value;
|
||||
}
|
||||
/**
|
||||
* @param mixed $value as passed via Request transfer options.
|
||||
*/
|
||||
private function add_progress(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array &$options, $value, array &$params) : void
|
||||
private function add_progress(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, &$options, $value, &$params)
|
||||
{
|
||||
self::addNotification($params, static function ($code, $a, $b, $c, $transferred, $total) use($value) {
|
||||
$this->addNotification($params, function ($code, $a, $b, $c, $transferred, $total) use($value) {
|
||||
if ($code == \STREAM_NOTIFY_PROGRESS) {
|
||||
// The upload progress cannot be determined. Use 0 for cURL compatibility:
|
||||
// https://curl.se/libcurl/c/CURLOPT_PROGRESSFUNCTION.html
|
||||
$value($total, $transferred, 0, 0);
|
||||
$value($total, $transferred, null, null);
|
||||
}
|
||||
});
|
||||
}
|
||||
/**
|
||||
* @param mixed $value as passed via Request transfer options.
|
||||
*/
|
||||
private function add_debug(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array &$options, $value, array &$params) : void
|
||||
private function add_debug(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, &$options, $value, &$params)
|
||||
{
|
||||
if ($value === \false) {
|
||||
return;
|
||||
}
|
||||
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'];
|
||||
static $args = ['severity', 'message', 'message_code', 'bytes_transferred', 'bytes_max'];
|
||||
$value = \YoastSEO_Vendor\GuzzleHttp\Utils::debugResource($value);
|
||||
$value = \YoastSEO_Vendor\GuzzleHttp\debug_resource($value);
|
||||
$ident = $request->getMethod() . ' ' . $request->getUri()->withFragment('');
|
||||
self::addNotification($params, static function (int $code, ...$passed) use($ident, $value, $map, $args) : void {
|
||||
$this->addNotification($params, function () use($ident, $value, $map, $args) {
|
||||
$passed = \func_get_args();
|
||||
$code = \array_shift($passed);
|
||||
\fprintf($value, '<%s> [%s] ', $ident, $map[$code]);
|
||||
foreach (\array_filter($passed) as $i => $v) {
|
||||
\fwrite($value, $args[$i] . ': "' . $v . '" ');
|
||||
@@ -435,20 +356,21 @@ class StreamHandler
|
||||
\fwrite($value, "\n");
|
||||
});
|
||||
}
|
||||
private static function addNotification(array &$params, callable $notify) : void
|
||||
private function addNotification(array &$params, callable $notify)
|
||||
{
|
||||
// Wrap the existing function if needed.
|
||||
if (!isset($params['notification'])) {
|
||||
$params['notification'] = $notify;
|
||||
} else {
|
||||
$params['notification'] = self::callArray([$params['notification'], $notify]);
|
||||
$params['notification'] = $this->callArray([$params['notification'], $notify]);
|
||||
}
|
||||
}
|
||||
private static function callArray(array $functions) : callable
|
||||
private function callArray(array $functions)
|
||||
{
|
||||
return static function (...$args) use($functions) {
|
||||
return function () use($functions) {
|
||||
$args = \func_get_args();
|
||||
foreach ($functions as $fn) {
|
||||
$fn(...$args);
|
||||
\call_user_func_array($fn, $args);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -8,22 +8,14 @@ use YoastSEO_Vendor\Psr\Http\Message\ResponseInterface;
|
||||
/**
|
||||
* Creates a composed Guzzle handler function by stacking middlewares on top of
|
||||
* an HTTP handler function.
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class HandlerStack
|
||||
{
|
||||
/**
|
||||
* @var (callable(RequestInterface, array): PromiseInterface)|null
|
||||
*/
|
||||
/** @var callable|null */
|
||||
private $handler;
|
||||
/**
|
||||
* @var array{(callable(callable(RequestInterface, array): PromiseInterface): callable), (string|null)}[]
|
||||
*/
|
||||
/** @var array */
|
||||
private $stack = [];
|
||||
/**
|
||||
* @var (callable(RequestInterface, array): PromiseInterface)|null
|
||||
*/
|
||||
/** @var callable|null */
|
||||
private $cached;
|
||||
/**
|
||||
* Creates a default handler stack that can be used by clients.
|
||||
@@ -36,13 +28,15 @@ class HandlerStack
|
||||
* The returned handler stack can be passed to a client in the "handler"
|
||||
* option.
|
||||
*
|
||||
* @param (callable(RequestInterface, array): PromiseInterface)|null $handler HTTP handler function to use with the stack. If no
|
||||
* handler is provided, the best handler for your
|
||||
* system will be utilized.
|
||||
* @param callable $handler HTTP handler function to use with the stack. If no
|
||||
* handler is provided, the best handler for your
|
||||
* system will be utilized.
|
||||
*
|
||||
* @return HandlerStack
|
||||
*/
|
||||
public static function create(callable $handler = null) : self
|
||||
public static function create(callable $handler = null)
|
||||
{
|
||||
$stack = new self($handler ?: \YoastSEO_Vendor\GuzzleHttp\Utils::chooseHandler());
|
||||
$stack = new self($handler ?: choose_handler());
|
||||
$stack->push(\YoastSEO_Vendor\GuzzleHttp\Middleware::httpErrors(), 'http_errors');
|
||||
$stack->push(\YoastSEO_Vendor\GuzzleHttp\Middleware::redirect(), 'allow_redirects');
|
||||
$stack->push(\YoastSEO_Vendor\GuzzleHttp\Middleware::cookies(), 'cookies');
|
||||
@@ -50,7 +44,7 @@ class HandlerStack
|
||||
return $stack;
|
||||
}
|
||||
/**
|
||||
* @param (callable(RequestInterface, array): PromiseInterface)|null $handler Underlying HTTP handler.
|
||||
* @param callable $handler Underlying HTTP handler.
|
||||
*/
|
||||
public function __construct(callable $handler = null)
|
||||
{
|
||||
@@ -59,6 +53,9 @@ class HandlerStack
|
||||
/**
|
||||
* Invokes the handler stack as a composed handler
|
||||
*
|
||||
* @param RequestInterface $request
|
||||
* @param array $options
|
||||
*
|
||||
* @return ResponseInterface|PromiseInterface
|
||||
*/
|
||||
public function __invoke(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options)
|
||||
@@ -75,14 +72,14 @@ class HandlerStack
|
||||
{
|
||||
$depth = 0;
|
||||
$stack = [];
|
||||
if ($this->handler !== null) {
|
||||
$stack[] = '0) Handler: ' . $this->debugCallable($this->handler);
|
||||
if ($this->handler) {
|
||||
$stack[] = "0) Handler: " . $this->debugCallable($this->handler);
|
||||
}
|
||||
$result = '';
|
||||
foreach (\array_reverse($this->stack) as $tuple) {
|
||||
++$depth;
|
||||
$depth++;
|
||||
$str = "{$depth}) Name: '{$tuple[1]}', ";
|
||||
$str .= 'Function: ' . $this->debugCallable($tuple[0]);
|
||||
$str .= "Function: " . $this->debugCallable($tuple[0]);
|
||||
$result = "> {$str}\n{$result}";
|
||||
$stack[] = $str;
|
||||
}
|
||||
@@ -94,28 +91,30 @@ class HandlerStack
|
||||
/**
|
||||
* Set the HTTP handler that actually returns a promise.
|
||||
*
|
||||
* @param callable(RequestInterface, array): PromiseInterface $handler Accepts a request and array of options and
|
||||
* returns a Promise.
|
||||
* @param callable $handler Accepts a request and array of options and
|
||||
* returns a Promise.
|
||||
*/
|
||||
public function setHandler(callable $handler) : void
|
||||
public function setHandler(callable $handler)
|
||||
{
|
||||
$this->handler = $handler;
|
||||
$this->cached = null;
|
||||
}
|
||||
/**
|
||||
* Returns true if the builder has a handler.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasHandler() : bool
|
||||
public function hasHandler()
|
||||
{
|
||||
return $this->handler !== null;
|
||||
return (bool) $this->handler;
|
||||
}
|
||||
/**
|
||||
* Unshift a middleware to the bottom of the stack.
|
||||
*
|
||||
* @param callable(callable): callable $middleware Middleware function
|
||||
* @param string $name Name to register for this middleware.
|
||||
* @param callable $middleware Middleware function
|
||||
* @param string $name Name to register for this middleware.
|
||||
*/
|
||||
public function unshift(callable $middleware, string $name = null) : void
|
||||
public function unshift(callable $middleware, $name = null)
|
||||
{
|
||||
\array_unshift($this->stack, [$middleware, $name]);
|
||||
$this->cached = null;
|
||||
@@ -123,10 +122,10 @@ class HandlerStack
|
||||
/**
|
||||
* Push a middleware to the top of the stack.
|
||||
*
|
||||
* @param callable(callable): callable $middleware Middleware function
|
||||
* @param string $name Name to register for this middleware.
|
||||
* @param callable $middleware Middleware function
|
||||
* @param string $name Name to register for this middleware.
|
||||
*/
|
||||
public function push(callable $middleware, string $name = '') : void
|
||||
public function push(callable $middleware, $name = '')
|
||||
{
|
||||
$this->stack[] = [$middleware, $name];
|
||||
$this->cached = null;
|
||||
@@ -134,22 +133,22 @@ class HandlerStack
|
||||
/**
|
||||
* Add a middleware before another middleware by name.
|
||||
*
|
||||
* @param string $findName Middleware to find
|
||||
* @param callable(callable): callable $middleware Middleware function
|
||||
* @param string $withName Name to register for this middleware.
|
||||
* @param string $findName Middleware to find
|
||||
* @param callable $middleware Middleware function
|
||||
* @param string $withName Name to register for this middleware.
|
||||
*/
|
||||
public function before(string $findName, callable $middleware, string $withName = '') : void
|
||||
public function before($findName, callable $middleware, $withName = '')
|
||||
{
|
||||
$this->splice($findName, $withName, $middleware, \true);
|
||||
}
|
||||
/**
|
||||
* Add a middleware after another middleware by name.
|
||||
*
|
||||
* @param string $findName Middleware to find
|
||||
* @param callable(callable): callable $middleware Middleware function
|
||||
* @param string $withName Name to register for this middleware.
|
||||
* @param string $findName Middleware to find
|
||||
* @param callable $middleware Middleware function
|
||||
* @param string $withName Name to register for this middleware.
|
||||
*/
|
||||
public function after(string $findName, callable $middleware, string $withName = '') : void
|
||||
public function after($findName, callable $middleware, $withName = '')
|
||||
{
|
||||
$this->splice($findName, $withName, $middleware, \false);
|
||||
}
|
||||
@@ -158,37 +157,37 @@ class HandlerStack
|
||||
*
|
||||
* @param callable|string $remove Middleware to remove by instance or name.
|
||||
*/
|
||||
public function remove($remove) : void
|
||||
public function remove($remove)
|
||||
{
|
||||
if (!\is_string($remove) && !\is_callable($remove)) {
|
||||
trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a callable or string to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__);
|
||||
}
|
||||
$this->cached = null;
|
||||
$idx = \is_callable($remove) ? 0 : 1;
|
||||
$this->stack = \array_values(\array_filter($this->stack, static function ($tuple) use($idx, $remove) {
|
||||
$this->stack = \array_values(\array_filter($this->stack, function ($tuple) use($idx, $remove) {
|
||||
return $tuple[$idx] !== $remove;
|
||||
}));
|
||||
}
|
||||
/**
|
||||
* Compose the middleware and handler into a single callable function.
|
||||
*
|
||||
* @return callable(RequestInterface, array): PromiseInterface
|
||||
* @return callable
|
||||
*/
|
||||
public function resolve() : callable
|
||||
public function resolve()
|
||||
{
|
||||
if ($this->cached === null) {
|
||||
if (($prev = $this->handler) === null) {
|
||||
if (!$this->cached) {
|
||||
if (!($prev = $this->handler)) {
|
||||
throw new \LogicException('No handler has been specified');
|
||||
}
|
||||
foreach (\array_reverse($this->stack) as $fn) {
|
||||
/** @var callable(RequestInterface, array): PromiseInterface $prev */
|
||||
$prev = $fn[0]($prev);
|
||||
}
|
||||
$this->cached = $prev;
|
||||
}
|
||||
return $this->cached;
|
||||
}
|
||||
private function findByName(string $name) : int
|
||||
/**
|
||||
* @param string $name
|
||||
* @return int
|
||||
*/
|
||||
private function findByName($name)
|
||||
{
|
||||
foreach ($this->stack as $k => $v) {
|
||||
if ($v[1] === $name) {
|
||||
@@ -199,8 +198,13 @@ class HandlerStack
|
||||
}
|
||||
/**
|
||||
* Splices a function into the middleware list at a specific position.
|
||||
*
|
||||
* @param string $findName
|
||||
* @param string $withName
|
||||
* @param callable $middleware
|
||||
* @param bool $before
|
||||
*/
|
||||
private function splice(string $findName, string $withName, callable $middleware, bool $before) : void
|
||||
private function splice($findName, $withName, callable $middleware, $before)
|
||||
{
|
||||
$this->cached = null;
|
||||
$idx = $this->findByName($findName);
|
||||
@@ -222,9 +226,11 @@ class HandlerStack
|
||||
/**
|
||||
* Provides a debug string for a given callable.
|
||||
*
|
||||
* @param callable|string $fn Function to write as a string.
|
||||
* @param array|callable $fn Function to write as a string.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function debugCallable($fn) : string
|
||||
private function debugCallable($fn)
|
||||
{
|
||||
if (\is_string($fn)) {
|
||||
return "callable({$fn})";
|
||||
@@ -232,7 +238,6 @@ class HandlerStack
|
||||
if (\is_array($fn)) {
|
||||
return \is_string($fn[0]) ? "callable({$fn[0]}::{$fn[1]})" : "callable(['" . \get_class($fn[0]) . "', '{$fn[1]}'])";
|
||||
}
|
||||
/** @var object $fn */
|
||||
return 'callable(' . \spl_object_hash($fn) . ')';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,43 +31,38 @@ use YoastSEO_Vendor\Psr\Http\Message\ResponseInterface;
|
||||
* - {res_headers}: Response headers
|
||||
* - {req_body}: Request body
|
||||
* - {res_body}: Response body
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class MessageFormatter implements \YoastSEO_Vendor\GuzzleHttp\MessageFormatterInterface
|
||||
class MessageFormatter
|
||||
{
|
||||
/**
|
||||
* Apache Common Log Format.
|
||||
*
|
||||
* @see https://httpd.apache.org/docs/2.4/logs.html#common
|
||||
*
|
||||
* @link http://httpd.apache.org/docs/2.4/logs.html#common
|
||||
* @var string
|
||||
*/
|
||||
public const CLF = '{hostname} {req_header_User-Agent} - [{date_common_log}] "{method} {target} HTTP/{version}" {code} {res_header_Content-Length}';
|
||||
public const DEBUG = ">>>>>>>>\n{request}\n<<<<<<<<\n{response}\n--------\n{error}";
|
||||
public const SHORT = '[{ts}] "{method} {target} HTTP/{version}" {code}';
|
||||
/**
|
||||
* @var string Template used to format log messages
|
||||
*/
|
||||
const CLF = "{hostname} {req_header_User-Agent} - [{date_common_log}] \"{method} {target} HTTP/{version}\" {code} {res_header_Content-Length}";
|
||||
const DEBUG = ">>>>>>>>\n{request}\n<<<<<<<<\n{response}\n--------\n{error}";
|
||||
const SHORT = '[{ts}] "{method} {target} HTTP/{version}" {code}';
|
||||
/** @var string Template used to format log messages */
|
||||
private $template;
|
||||
/**
|
||||
* @param string $template Log message template
|
||||
*/
|
||||
public function __construct(?string $template = self::CLF)
|
||||
public function __construct($template = self::CLF)
|
||||
{
|
||||
$this->template = $template ?: self::CLF;
|
||||
}
|
||||
/**
|
||||
* Returns a formatted message string.
|
||||
*
|
||||
* @param RequestInterface $request Request that was sent
|
||||
* @param ResponseInterface|null $response Response that was received
|
||||
* @param \Throwable|null $error Exception that was received
|
||||
* @param RequestInterface $request Request that was sent
|
||||
* @param ResponseInterface $response Response that was received
|
||||
* @param \Exception $error Exception that was received
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function format(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response = null, \Throwable $error = null) : string
|
||||
public function format(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response = null, \Exception $error = null)
|
||||
{
|
||||
$cache = [];
|
||||
/** @var string */
|
||||
return \preg_replace_callback('/{\\s*([A-Za-z_\\-\\.0-9]+)\\s*}/', function (array $matches) use($request, $response, $error, &$cache) {
|
||||
if (isset($cache[$matches[1]])) {
|
||||
return $cache[$matches[1]];
|
||||
@@ -75,10 +70,10 @@ class MessageFormatter implements \YoastSEO_Vendor\GuzzleHttp\MessageFormatterIn
|
||||
$result = '';
|
||||
switch ($matches[1]) {
|
||||
case 'request':
|
||||
$result = \YoastSEO_Vendor\GuzzleHttp\Psr7\Message::toString($request);
|
||||
$result = \YoastSEO_Vendor\GuzzleHttp\Psr7\str($request);
|
||||
break;
|
||||
case 'response':
|
||||
$result = $response ? \YoastSEO_Vendor\GuzzleHttp\Psr7\Message::toString($response) : '';
|
||||
$result = $response ? \YoastSEO_Vendor\GuzzleHttp\Psr7\str($response) : '';
|
||||
break;
|
||||
case 'req_headers':
|
||||
$result = \trim($request->getMethod() . ' ' . $request->getRequestTarget()) . ' HTTP/' . $request->getProtocolVersion() . "\r\n" . $this->headers($request);
|
||||
@@ -87,19 +82,10 @@ class MessageFormatter implements \YoastSEO_Vendor\GuzzleHttp\MessageFormatterIn
|
||||
$result = $response ? \sprintf('HTTP/%s %d %s', $response->getProtocolVersion(), $response->getStatusCode(), $response->getReasonPhrase()) . "\r\n" . $this->headers($response) : 'NULL';
|
||||
break;
|
||||
case 'req_body':
|
||||
$result = $request->getBody()->__toString();
|
||||
$result = $request->getBody();
|
||||
break;
|
||||
case 'res_body':
|
||||
if (!$response instanceof \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface) {
|
||||
$result = 'NULL';
|
||||
break;
|
||||
}
|
||||
$body = $response->getBody();
|
||||
if (!$body->isSeekable()) {
|
||||
$result = 'RESPONSE_NOT_LOGGEABLE';
|
||||
break;
|
||||
}
|
||||
$result = $response->getBody()->__toString();
|
||||
$result = $response ? $response->getBody() : 'NULL';
|
||||
break;
|
||||
case 'ts':
|
||||
case 'date_iso_8601':
|
||||
@@ -116,7 +102,7 @@ class MessageFormatter implements \YoastSEO_Vendor\GuzzleHttp\MessageFormatterIn
|
||||
break;
|
||||
case 'uri':
|
||||
case 'url':
|
||||
$result = $request->getUri()->__toString();
|
||||
$result = $request->getUri();
|
||||
break;
|
||||
case 'target':
|
||||
$result = $request->getRequestTarget();
|
||||
@@ -156,8 +142,10 @@ class MessageFormatter implements \YoastSEO_Vendor\GuzzleHttp\MessageFormatterIn
|
||||
}
|
||||
/**
|
||||
* Get headers from message as string
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function headers(\YoastSEO_Vendor\Psr\Http\Message\MessageInterface $message) : string
|
||||
private function headers(\YoastSEO_Vendor\Psr\Http\Message\MessageInterface $message)
|
||||
{
|
||||
$result = '';
|
||||
foreach ($message->getHeaders() as $name => $values) {
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace YoastSEO_Vendor\GuzzleHttp;
|
||||
|
||||
use YoastSEO_Vendor\Psr\Http\Message\RequestInterface;
|
||||
use YoastSEO_Vendor\Psr\Http\Message\ResponseInterface;
|
||||
interface MessageFormatterInterface
|
||||
{
|
||||
/**
|
||||
* Returns a formatted message string.
|
||||
*
|
||||
* @param RequestInterface $request Request that was sent
|
||||
* @param ResponseInterface|null $response Response that was received
|
||||
* @param \Throwable|null $error Exception that was received
|
||||
*/
|
||||
public function format(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response = null, \Throwable $error = null) : string;
|
||||
}
|
||||
@@ -4,9 +4,8 @@ namespace YoastSEO_Vendor\GuzzleHttp;
|
||||
|
||||
use YoastSEO_Vendor\GuzzleHttp\Cookie\CookieJarInterface;
|
||||
use YoastSEO_Vendor\GuzzleHttp\Exception\RequestException;
|
||||
use YoastSEO_Vendor\GuzzleHttp\Promise as P;
|
||||
use YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface;
|
||||
use YoastSEO_Vendor\Psr\Http\Message\RequestInterface;
|
||||
use YoastSEO_Vendor\GuzzleHttp\Promise\RejectedPromise;
|
||||
use YoastSEO_Vendor\GuzzleHttp\Psr7;
|
||||
use YoastSEO_Vendor\Psr\Http\Message\ResponseInterface;
|
||||
use YoastSEO_Vendor\Psr\Log\LoggerInterface;
|
||||
/**
|
||||
@@ -22,10 +21,10 @@ final class Middleware
|
||||
*
|
||||
* @return callable Returns a function that accepts the next handler.
|
||||
*/
|
||||
public static function cookies() : callable
|
||||
public static function cookies()
|
||||
{
|
||||
return static function (callable $handler) : callable {
|
||||
return static function ($request, array $options) use($handler) {
|
||||
return function (callable $handler) {
|
||||
return function ($request, array $options) use($handler) {
|
||||
if (empty($options['cookies'])) {
|
||||
return $handler($request, $options);
|
||||
} elseif (!$options['cookies'] instanceof \YoastSEO_Vendor\GuzzleHttp\Cookie\CookieJarInterface) {
|
||||
@@ -33,7 +32,7 @@ final class Middleware
|
||||
}
|
||||
$cookieJar = $options['cookies'];
|
||||
$request = $cookieJar->withCookieHeader($request);
|
||||
return $handler($request, $options)->then(static function (\YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response) use($cookieJar, $request) : ResponseInterface {
|
||||
return $handler($request, $options)->then(function ($response) use($cookieJar, $request) {
|
||||
$cookieJar->extractCookies($request, $response);
|
||||
return $response;
|
||||
});
|
||||
@@ -42,25 +41,23 @@ final class Middleware
|
||||
}
|
||||
/**
|
||||
* Middleware that throws exceptions for 4xx or 5xx responses when the
|
||||
* "http_errors" request option is set to true.
|
||||
* "http_error" request option is set to true.
|
||||
*
|
||||
* @param BodySummarizerInterface|null $bodySummarizer The body summarizer to use in exception messages.
|
||||
*
|
||||
* @return callable(callable): callable Returns a function that accepts the next handler.
|
||||
* @return callable Returns a function that accepts the next handler.
|
||||
*/
|
||||
public static function httpErrors(\YoastSEO_Vendor\GuzzleHttp\BodySummarizerInterface $bodySummarizer = null) : callable
|
||||
public static function httpErrors()
|
||||
{
|
||||
return static function (callable $handler) use($bodySummarizer) : callable {
|
||||
return static function ($request, array $options) use($handler, $bodySummarizer) {
|
||||
return function (callable $handler) {
|
||||
return function ($request, array $options) use($handler) {
|
||||
if (empty($options['http_errors'])) {
|
||||
return $handler($request, $options);
|
||||
}
|
||||
return $handler($request, $options)->then(static function (\YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response) use($request, $bodySummarizer) {
|
||||
return $handler($request, $options)->then(function (\YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response) use($request) {
|
||||
$code = $response->getStatusCode();
|
||||
if ($code < 400) {
|
||||
return $response;
|
||||
}
|
||||
throw \YoastSEO_Vendor\GuzzleHttp\Exception\RequestException::create($request, $response, null, [], $bodySummarizer);
|
||||
throw \YoastSEO_Vendor\GuzzleHttp\Exception\RequestException::create($request, $response);
|
||||
});
|
||||
};
|
||||
};
|
||||
@@ -68,25 +65,24 @@ final class Middleware
|
||||
/**
|
||||
* Middleware that pushes history data to an ArrayAccess container.
|
||||
*
|
||||
* @param array|\ArrayAccess<int, array> $container Container to hold the history (by reference).
|
||||
*
|
||||
* @return callable(callable): callable Returns a function that accepts the next handler.
|
||||
* @param array|\ArrayAccess $container Container to hold the history (by reference).
|
||||
*
|
||||
* @return callable Returns a function that accepts the next handler.
|
||||
* @throws \InvalidArgumentException if container is not an array or ArrayAccess.
|
||||
*/
|
||||
public static function history(&$container) : callable
|
||||
public static function history(&$container)
|
||||
{
|
||||
if (!\is_array($container) && !$container instanceof \ArrayAccess) {
|
||||
throw new \InvalidArgumentException('history container must be an array or object implementing ArrayAccess');
|
||||
}
|
||||
return static function (callable $handler) use(&$container) : callable {
|
||||
return static function (\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options) use($handler, &$container) {
|
||||
return $handler($request, $options)->then(static function ($value) use($request, &$container, $options) {
|
||||
return function (callable $handler) use(&$container) {
|
||||
return function ($request, array $options) use($handler, &$container) {
|
||||
return $handler($request, $options)->then(function ($value) use($request, &$container, $options) {
|
||||
$container[] = ['request' => $request, 'response' => $value, 'error' => null, 'options' => $options];
|
||||
return $value;
|
||||
}, static function ($reason) use($request, &$container, $options) {
|
||||
}, function ($reason) use($request, &$container, $options) {
|
||||
$container[] = ['request' => $request, 'response' => null, 'error' => $reason, 'options' => $options];
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Promise\Create::rejectionFor($reason);
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Promise\rejection_for($reason);
|
||||
});
|
||||
};
|
||||
};
|
||||
@@ -104,10 +100,10 @@ final class Middleware
|
||||
*
|
||||
* @return callable Returns a function that accepts the next handler.
|
||||
*/
|
||||
public static function tap(callable $before = null, callable $after = null) : callable
|
||||
public static function tap(callable $before = null, callable $after = null)
|
||||
{
|
||||
return static function (callable $handler) use($before, $after) : callable {
|
||||
return static function (\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options) use($handler, $before, $after) {
|
||||
return function (callable $handler) use($before, $after) {
|
||||
return function ($request, array $options) use($handler, $before, $after) {
|
||||
if ($before) {
|
||||
$before($request, $options);
|
||||
}
|
||||
@@ -124,9 +120,9 @@ final class Middleware
|
||||
*
|
||||
* @return callable Returns a function that accepts the next handler.
|
||||
*/
|
||||
public static function redirect() : callable
|
||||
public static function redirect()
|
||||
{
|
||||
return static function (callable $handler) : RedirectMiddleware {
|
||||
return function (callable $handler) {
|
||||
return new \YoastSEO_Vendor\GuzzleHttp\RedirectMiddleware($handler);
|
||||
};
|
||||
}
|
||||
@@ -145,9 +141,9 @@ final class Middleware
|
||||
*
|
||||
* @return callable Returns a function that accepts the next handler.
|
||||
*/
|
||||
public static function retry(callable $decider, callable $delay = null) : callable
|
||||
public static function retry(callable $decider, callable $delay = null)
|
||||
{
|
||||
return static function (callable $handler) use($decider, $delay) : RetryMiddleware {
|
||||
return function (callable $handler) use($decider, $delay) {
|
||||
return new \YoastSEO_Vendor\GuzzleHttp\RetryMiddleware($decider, $handler, $delay);
|
||||
};
|
||||
}
|
||||
@@ -155,31 +151,25 @@ final class Middleware
|
||||
* Middleware that logs requests, responses, and errors using a message
|
||||
* formatter.
|
||||
*
|
||||
* @phpstan-param \Psr\Log\LogLevel::* $logLevel Level at which to log requests.
|
||||
*
|
||||
* @param LoggerInterface $logger Logs messages.
|
||||
* @param MessageFormatterInterface|MessageFormatter $formatter Formatter used to create message strings.
|
||||
* @param string $logLevel Level at which to log requests.
|
||||
* @param LoggerInterface $logger Logs messages.
|
||||
* @param MessageFormatter $formatter Formatter used to create message strings.
|
||||
* @param string $logLevel Level at which to log requests.
|
||||
*
|
||||
* @return callable Returns a function that accepts the next handler.
|
||||
*/
|
||||
public static function log(\YoastSEO_Vendor\Psr\Log\LoggerInterface $logger, $formatter, string $logLevel = 'info') : callable
|
||||
public static function log(\YoastSEO_Vendor\Psr\Log\LoggerInterface $logger, \YoastSEO_Vendor\GuzzleHttp\MessageFormatter $formatter, $logLevel = 'info')
|
||||
{
|
||||
// To be compatible with Guzzle 7.1.x we need to allow users to pass a MessageFormatter
|
||||
if (!$formatter instanceof \YoastSEO_Vendor\GuzzleHttp\MessageFormatter && !$formatter instanceof \YoastSEO_Vendor\GuzzleHttp\MessageFormatterInterface) {
|
||||
throw new \LogicException(\sprintf('Argument 2 to %s::log() must be of type %s', self::class, \YoastSEO_Vendor\GuzzleHttp\MessageFormatterInterface::class));
|
||||
}
|
||||
return static function (callable $handler) use($logger, $formatter, $logLevel) : callable {
|
||||
return static function (\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options = []) use($handler, $logger, $formatter, $logLevel) {
|
||||
return $handler($request, $options)->then(static function ($response) use($logger, $request, $formatter, $logLevel) : ResponseInterface {
|
||||
return function (callable $handler) use($logger, $formatter, $logLevel) {
|
||||
return function ($request, array $options) use($handler, $logger, $formatter, $logLevel) {
|
||||
return $handler($request, $options)->then(function ($response) use($logger, $request, $formatter, $logLevel) {
|
||||
$message = $formatter->format($request, $response);
|
||||
$logger->log($logLevel, $message);
|
||||
return $response;
|
||||
}, static function ($reason) use($logger, $request, $formatter) : PromiseInterface {
|
||||
}, function ($reason) use($logger, $request, $formatter) {
|
||||
$response = $reason instanceof \YoastSEO_Vendor\GuzzleHttp\Exception\RequestException ? $reason->getResponse() : null;
|
||||
$message = $formatter->format($request, $response, \YoastSEO_Vendor\GuzzleHttp\Promise\Create::exceptionFor($reason));
|
||||
$logger->error($message);
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Promise\Create::rejectionFor($reason);
|
||||
$message = $formatter->format($request, $response, $reason);
|
||||
$logger->notice($message);
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Promise\rejection_for($reason);
|
||||
});
|
||||
};
|
||||
};
|
||||
@@ -187,10 +177,12 @@ final class Middleware
|
||||
/**
|
||||
* This middleware adds a default content-type if possible, a default
|
||||
* content-length or transfer-encoding header, and the expect header.
|
||||
*
|
||||
* @return callable
|
||||
*/
|
||||
public static function prepareBody() : callable
|
||||
public static function prepareBody()
|
||||
{
|
||||
return static function (callable $handler) : PrepareBodyMiddleware {
|
||||
return function (callable $handler) {
|
||||
return new \YoastSEO_Vendor\GuzzleHttp\PrepareBodyMiddleware($handler);
|
||||
};
|
||||
}
|
||||
@@ -200,11 +192,12 @@ final class Middleware
|
||||
*
|
||||
* @param callable $fn Function that accepts a RequestInterface and returns
|
||||
* a RequestInterface.
|
||||
* @return callable
|
||||
*/
|
||||
public static function mapRequest(callable $fn) : callable
|
||||
public static function mapRequest(callable $fn)
|
||||
{
|
||||
return static function (callable $handler) use($fn) : callable {
|
||||
return static function (\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options) use($handler, $fn) {
|
||||
return function (callable $handler) use($fn) {
|
||||
return function ($request, array $options) use($handler, $fn) {
|
||||
return $handler($fn($request), $options);
|
||||
};
|
||||
};
|
||||
@@ -215,11 +208,12 @@ final class Middleware
|
||||
*
|
||||
* @param callable $fn Function that accepts a ResponseInterface and
|
||||
* returns a ResponseInterface.
|
||||
* @return callable
|
||||
*/
|
||||
public static function mapResponse(callable $fn) : callable
|
||||
public static function mapResponse(callable $fn)
|
||||
{
|
||||
return static function (callable $handler) use($fn) : callable {
|
||||
return static function (\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options) use($handler, $fn) {
|
||||
return function (callable $handler) use($fn) {
|
||||
return function ($request, array $options) use($handler, $fn) {
|
||||
return $handler($request, $options)->then($fn);
|
||||
};
|
||||
};
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace YoastSEO_Vendor\GuzzleHttp;
|
||||
|
||||
use YoastSEO_Vendor\GuzzleHttp\Promise as P;
|
||||
use YoastSEO_Vendor\GuzzleHttp\Promise\EachPromise;
|
||||
use YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface;
|
||||
use YoastSEO_Vendor\GuzzleHttp\Promise\PromisorInterface;
|
||||
@@ -17,28 +16,27 @@ use YoastSEO_Vendor\Psr\Http\Message\RequestInterface;
|
||||
* When a function is yielded by the iterator, the function is provided the
|
||||
* "request_options" array that should be merged on top of any existing
|
||||
* options, and the function MUST then return a wait-able promise.
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class Pool implements \YoastSEO_Vendor\GuzzleHttp\Promise\PromisorInterface
|
||||
{
|
||||
/**
|
||||
* @var EachPromise
|
||||
*/
|
||||
/** @var EachPromise */
|
||||
private $each;
|
||||
/**
|
||||
* @param ClientInterface $client Client used to send the requests.
|
||||
* @param array|\Iterator $requests Requests or functions that return
|
||||
* requests to send concurrently.
|
||||
* @param array $config Associative array of options
|
||||
* - concurrency: (int) Maximum number of requests to send concurrently
|
||||
* - options: Array of request options to apply to each request.
|
||||
* - fulfilled: (callable) Function to invoke when a request completes.
|
||||
* - rejected: (callable) Function to invoke when a request is rejected.
|
||||
* - concurrency: (int) Maximum number of requests to send concurrently
|
||||
* - options: Array of request options to apply to each request.
|
||||
* - fulfilled: (callable) Function to invoke when a request completes.
|
||||
* - rejected: (callable) Function to invoke when a request is rejected.
|
||||
*/
|
||||
public function __construct(\YoastSEO_Vendor\GuzzleHttp\ClientInterface $client, $requests, array $config = [])
|
||||
{
|
||||
if (!isset($config['concurrency'])) {
|
||||
// Backwards compatibility.
|
||||
if (isset($config['pool_size'])) {
|
||||
$config['concurrency'] = $config['pool_size'];
|
||||
} elseif (!isset($config['concurrency'])) {
|
||||
$config['concurrency'] = 25;
|
||||
}
|
||||
if (isset($config['options'])) {
|
||||
@@ -47,15 +45,15 @@ class Pool implements \YoastSEO_Vendor\GuzzleHttp\Promise\PromisorInterface
|
||||
} else {
|
||||
$opts = [];
|
||||
}
|
||||
$iterable = \YoastSEO_Vendor\GuzzleHttp\Promise\Create::iterFor($requests);
|
||||
$requests = static function () use($iterable, $client, $opts) {
|
||||
$iterable = \YoastSEO_Vendor\GuzzleHttp\Promise\iter_for($requests);
|
||||
$requests = function () use($iterable, $client, $opts) {
|
||||
foreach ($iterable as $key => $rfn) {
|
||||
if ($rfn instanceof \YoastSEO_Vendor\Psr\Http\Message\RequestInterface) {
|
||||
(yield $key => $client->sendAsync($rfn, $opts));
|
||||
} elseif (\is_callable($rfn)) {
|
||||
(yield $key => $rfn($opts));
|
||||
} else {
|
||||
throw new \InvalidArgumentException('Each value yielded by the iterator must be a Psr7\\Http\\Message\\RequestInterface or a callable that returns a promise that fulfills with a Psr7\\Message\\Http\\ResponseInterface object.');
|
||||
throw new \InvalidArgumentException('Each value yielded by ' . 'the iterator must be a Psr7\\Http\\Message\\RequestInterface ' . 'or a callable that returns a promise that fulfills ' . 'with a Psr7\\Message\\Http\\ResponseInterface object.');
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -63,8 +61,10 @@ class Pool implements \YoastSEO_Vendor\GuzzleHttp\Promise\PromisorInterface
|
||||
}
|
||||
/**
|
||||
* Get promise
|
||||
*
|
||||
* @return PromiseInterface
|
||||
*/
|
||||
public function promise() : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
|
||||
public function promise()
|
||||
{
|
||||
return $this->each->promise();
|
||||
}
|
||||
@@ -79,14 +79,13 @@ class Pool implements \YoastSEO_Vendor\GuzzleHttp\Promise\PromisorInterface
|
||||
* @param ClientInterface $client Client used to send the requests
|
||||
* @param array|\Iterator $requests Requests to send concurrently.
|
||||
* @param array $options Passes through the options available in
|
||||
* {@see \GuzzleHttp\Pool::__construct}
|
||||
* {@see GuzzleHttp\Pool::__construct}
|
||||
*
|
||||
* @return array Returns an array containing the response or an exception
|
||||
* in the same order that the requests were sent.
|
||||
*
|
||||
* @throws \InvalidArgumentException if the event format is incorrect.
|
||||
*/
|
||||
public static function batch(\YoastSEO_Vendor\GuzzleHttp\ClientInterface $client, $requests, array $options = []) : array
|
||||
public static function batch(\YoastSEO_Vendor\GuzzleHttp\ClientInterface $client, $requests, array $options = [])
|
||||
{
|
||||
$res = [];
|
||||
self::cmpCallback($options, 'fulfilled', $res);
|
||||
@@ -98,16 +97,18 @@ class Pool implements \YoastSEO_Vendor\GuzzleHttp\Promise\PromisorInterface
|
||||
}
|
||||
/**
|
||||
* Execute callback(s)
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private static function cmpCallback(array &$options, string $name, array &$results) : void
|
||||
private static function cmpCallback(array &$options, $name, array &$results)
|
||||
{
|
||||
if (!isset($options[$name])) {
|
||||
$options[$name] = static function ($v, $k) use(&$results) {
|
||||
$options[$name] = function ($v, $k) use(&$results) {
|
||||
$results[$k] = $v;
|
||||
};
|
||||
} else {
|
||||
$currentFn = $options[$name];
|
||||
$options[$name] = static function ($v, $k) use(&$results, $currentFn) {
|
||||
$options[$name] = function ($v, $k) use(&$results, $currentFn) {
|
||||
$currentFn($v, $k);
|
||||
$results[$k] = $v;
|
||||
};
|
||||
|
||||
@@ -3,27 +3,30 @@
|
||||
namespace YoastSEO_Vendor\GuzzleHttp;
|
||||
|
||||
use YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface;
|
||||
use YoastSEO_Vendor\GuzzleHttp\Psr7;
|
||||
use YoastSEO_Vendor\Psr\Http\Message\RequestInterface;
|
||||
/**
|
||||
* Prepares requests that contain a body, adding the Content-Length,
|
||||
* Content-Type, and Expect headers.
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class PrepareBodyMiddleware
|
||||
{
|
||||
/**
|
||||
* @var callable(RequestInterface, array): PromiseInterface
|
||||
*/
|
||||
/** @var callable */
|
||||
private $nextHandler;
|
||||
/**
|
||||
* @param callable(RequestInterface, array): PromiseInterface $nextHandler Next handler to invoke.
|
||||
* @param callable $nextHandler Next handler to invoke.
|
||||
*/
|
||||
public function __construct(callable $nextHandler)
|
||||
{
|
||||
$this->nextHandler = $nextHandler;
|
||||
}
|
||||
public function __invoke(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
|
||||
/**
|
||||
* @param RequestInterface $request
|
||||
* @param array $options
|
||||
*
|
||||
* @return PromiseInterface
|
||||
*/
|
||||
public function __invoke(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options)
|
||||
{
|
||||
$fn = $this->nextHandler;
|
||||
// Don't do anything if the request has no body.
|
||||
@@ -34,7 +37,7 @@ class PrepareBodyMiddleware
|
||||
// Add a default content-type if possible.
|
||||
if (!$request->hasHeader('Content-Type')) {
|
||||
if ($uri = $request->getBody()->getMetadata('uri')) {
|
||||
if (\is_string($uri) && ($type = \YoastSEO_Vendor\GuzzleHttp\Psr7\MimeType::fromFilename($uri))) {
|
||||
if ($type = \YoastSEO_Vendor\GuzzleHttp\Psr7\mimetype_from_filename($uri)) {
|
||||
$modify['set_headers']['Content-Type'] = $type;
|
||||
}
|
||||
}
|
||||
@@ -50,18 +53,20 @@ class PrepareBodyMiddleware
|
||||
}
|
||||
// Add the expect header if needed.
|
||||
$this->addExpectHeader($request, $options, $modify);
|
||||
return $fn(\YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::modifyRequest($request, $modify), $options);
|
||||
return $fn(\YoastSEO_Vendor\GuzzleHttp\Psr7\modify_request($request, $modify), $options);
|
||||
}
|
||||
/**
|
||||
* Add expect header
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function addExpectHeader(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options, array &$modify) : void
|
||||
private function addExpectHeader(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options, array &$modify)
|
||||
{
|
||||
// Determine if the Expect header should be used
|
||||
if ($request->hasHeader('Expect')) {
|
||||
return;
|
||||
}
|
||||
$expect = $options['expect'] ?? null;
|
||||
$expect = isset($options['expect']) ? $options['expect'] : null;
|
||||
// Return if disabled or if you're not using HTTP/1.1 or HTTP/2.0
|
||||
if ($expect === \false || $request->getProtocolVersion() < 1.1) {
|
||||
return;
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace YoastSEO_Vendor\GuzzleHttp;
|
||||
use YoastSEO_Vendor\GuzzleHttp\Exception\BadResponseException;
|
||||
use YoastSEO_Vendor\GuzzleHttp\Exception\TooManyRedirectsException;
|
||||
use YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface;
|
||||
use YoastSEO_Vendor\GuzzleHttp\Psr7;
|
||||
use YoastSEO_Vendor\Psr\Http\Message\RequestInterface;
|
||||
use YoastSEO_Vendor\Psr\Http\Message\ResponseInterface;
|
||||
use YoastSEO_Vendor\Psr\Http\Message\UriInterface;
|
||||
@@ -13,29 +14,28 @@ use YoastSEO_Vendor\Psr\Http\Message\UriInterface;
|
||||
*
|
||||
* Apply this middleware like other middleware using
|
||||
* {@see \GuzzleHttp\Middleware::redirect()}.
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class RedirectMiddleware
|
||||
{
|
||||
public const HISTORY_HEADER = 'X-Guzzle-Redirect-History';
|
||||
public const STATUS_HISTORY_HEADER = 'X-Guzzle-Redirect-Status-History';
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
const HISTORY_HEADER = 'X-Guzzle-Redirect-History';
|
||||
const STATUS_HISTORY_HEADER = 'X-Guzzle-Redirect-Status-History';
|
||||
public static $defaultSettings = ['max' => 5, 'protocols' => ['http', 'https'], 'strict' => \false, 'referer' => \false, 'track_redirects' => \false];
|
||||
/**
|
||||
* @var callable(RequestInterface, array): PromiseInterface
|
||||
*/
|
||||
/** @var callable */
|
||||
private $nextHandler;
|
||||
/**
|
||||
* @param callable(RequestInterface, array): PromiseInterface $nextHandler Next handler to invoke.
|
||||
* @param callable $nextHandler Next handler to invoke.
|
||||
*/
|
||||
public function __construct(callable $nextHandler)
|
||||
{
|
||||
$this->nextHandler = $nextHandler;
|
||||
}
|
||||
public function __invoke(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
|
||||
/**
|
||||
* @param RequestInterface $request
|
||||
* @param array $options
|
||||
*
|
||||
* @return PromiseInterface
|
||||
*/
|
||||
public function __invoke(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options)
|
||||
{
|
||||
$fn = $this->nextHandler;
|
||||
if (empty($options['allow_redirects'])) {
|
||||
@@ -57,22 +57,27 @@ class RedirectMiddleware
|
||||
});
|
||||
}
|
||||
/**
|
||||
* @param RequestInterface $request
|
||||
* @param array $options
|
||||
* @param ResponseInterface $response
|
||||
*
|
||||
* @return ResponseInterface|PromiseInterface
|
||||
*/
|
||||
public function checkRedirect(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options, \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response)
|
||||
{
|
||||
if (\strpos((string) $response->getStatusCode(), '3') !== 0 || !$response->hasHeader('Location')) {
|
||||
if (\substr($response->getStatusCode(), 0, 1) != '3' || !$response->hasHeader('Location')) {
|
||||
return $response;
|
||||
}
|
||||
$this->guardMax($request, $response, $options);
|
||||
$this->guardMax($request, $options);
|
||||
$nextRequest = $this->modifyRequest($request, $options, $response);
|
||||
// If authorization is handled by curl, unset it if URI is cross-origin.
|
||||
if (\YoastSEO_Vendor\GuzzleHttp\Psr7\UriComparator::isCrossOrigin($request->getUri(), $nextRequest->getUri()) && \defined('\\CURLOPT_HTTPAUTH')) {
|
||||
unset($options['curl'][\CURLOPT_HTTPAUTH], $options['curl'][\CURLOPT_USERPWD]);
|
||||
}
|
||||
if (isset($options['allow_redirects']['on_redirect'])) {
|
||||
$options['allow_redirects']['on_redirect']($request, $response, $nextRequest->getUri());
|
||||
\call_user_func($options['allow_redirects']['on_redirect'], $request, $response, $nextRequest->getUri());
|
||||
}
|
||||
/** @var PromiseInterface|ResponseInterface $promise */
|
||||
$promise = $this($nextRequest, $options);
|
||||
// Add headers to be able to track history of redirects.
|
||||
if (!empty($options['allow_redirects']['track_redirects'])) {
|
||||
@@ -82,35 +87,46 @@ class RedirectMiddleware
|
||||
}
|
||||
/**
|
||||
* Enable tracking on promise.
|
||||
*
|
||||
* @return PromiseInterface
|
||||
*/
|
||||
private function withTracking(\YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface $promise, string $uri, int $statusCode) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
|
||||
private function withTracking(\YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface $promise, $uri, $statusCode)
|
||||
{
|
||||
return $promise->then(static function (\YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response) use($uri, $statusCode) {
|
||||
return $promise->then(function (\YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response) use($uri, $statusCode) {
|
||||
// Note that we are pushing to the front of the list as this
|
||||
// would be an earlier response than what is currently present
|
||||
// in the history header.
|
||||
$historyHeader = $response->getHeader(self::HISTORY_HEADER);
|
||||
$statusHeader = $response->getHeader(self::STATUS_HISTORY_HEADER);
|
||||
\array_unshift($historyHeader, $uri);
|
||||
\array_unshift($statusHeader, (string) $statusCode);
|
||||
\array_unshift($statusHeader, $statusCode);
|
||||
return $response->withHeader(self::HISTORY_HEADER, $historyHeader)->withHeader(self::STATUS_HISTORY_HEADER, $statusHeader);
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Check for too many redirects.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws TooManyRedirectsException Too many redirects.
|
||||
*/
|
||||
private function guardMax(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response, array &$options) : void
|
||||
private function guardMax(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array &$options)
|
||||
{
|
||||
$current = $options['__redirect_count'] ?? 0;
|
||||
$current = isset($options['__redirect_count']) ? $options['__redirect_count'] : 0;
|
||||
$options['__redirect_count'] = $current + 1;
|
||||
$max = $options['allow_redirects']['max'];
|
||||
if ($options['__redirect_count'] > $max) {
|
||||
throw new \YoastSEO_Vendor\GuzzleHttp\Exception\TooManyRedirectsException("Will not follow more than {$max} redirects", $request, $response);
|
||||
throw new \YoastSEO_Vendor\GuzzleHttp\Exception\TooManyRedirectsException("Will not follow more than {$max} redirects", $request);
|
||||
}
|
||||
}
|
||||
public function modifyRequest(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options, \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response) : \YoastSEO_Vendor\Psr\Http\Message\RequestInterface
|
||||
/**
|
||||
* @param RequestInterface $request
|
||||
* @param array $options
|
||||
* @param ResponseInterface $response
|
||||
*
|
||||
* @return RequestInterface
|
||||
*/
|
||||
public function modifyRequest(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options, \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response)
|
||||
{
|
||||
// Request modifications to apply.
|
||||
$modify = [];
|
||||
@@ -120,9 +136,7 @@ class RedirectMiddleware
|
||||
// would do.
|
||||
$statusCode = $response->getStatusCode();
|
||||
if ($statusCode == 303 || $statusCode <= 302 && !$options['allow_redirects']['strict']) {
|
||||
$safeMethods = ['GET', 'HEAD', 'OPTIONS'];
|
||||
$requestMethod = $request->getMethod();
|
||||
$modify['method'] = \in_array($requestMethod, $safeMethods) ? $requestMethod : 'GET';
|
||||
$modify['method'] = 'GET';
|
||||
$modify['body'] = '';
|
||||
}
|
||||
$uri = self::redirectUri($request, $response, $protocols);
|
||||
@@ -131,7 +145,7 @@ class RedirectMiddleware
|
||||
$uri = \YoastSEO_Vendor\GuzzleHttp\Utils::idnUriConvert($uri, $idnOptions);
|
||||
}
|
||||
$modify['uri'] = $uri;
|
||||
\YoastSEO_Vendor\GuzzleHttp\Psr7\Message::rewindBody($request);
|
||||
\YoastSEO_Vendor\GuzzleHttp\Psr7\rewind_body($request);
|
||||
// Add the Referer header if it is told to do so and only
|
||||
// add the header if we are not redirecting from https to http.
|
||||
if ($options['allow_redirects']['referer'] && $modify['uri']->getScheme() === $request->getUri()->getScheme()) {
|
||||
@@ -145,12 +159,18 @@ class RedirectMiddleware
|
||||
$modify['remove_headers'][] = 'Authorization';
|
||||
$modify['remove_headers'][] = 'Cookie';
|
||||
}
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::modifyRequest($request, $modify);
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Psr7\modify_request($request, $modify);
|
||||
}
|
||||
/**
|
||||
* Set the appropriate URL on the request based on the location header.
|
||||
*
|
||||
* @param RequestInterface $request
|
||||
* @param ResponseInterface $response
|
||||
* @param array $protocols
|
||||
*
|
||||
* @return UriInterface
|
||||
*/
|
||||
private static function redirectUri(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response, array $protocols) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface
|
||||
private static function redirectUri(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response, array $protocols)
|
||||
{
|
||||
$location = \YoastSEO_Vendor\GuzzleHttp\Psr7\UriResolver::resolve($request->getUri(), new \YoastSEO_Vendor\GuzzleHttp\Psr7\Uri($response->getHeaderLine('Location')));
|
||||
// Ensure that the redirect URI is allowed based on the protocols.
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace YoastSEO_Vendor\GuzzleHttp;
|
||||
*
|
||||
* More documentation for each option can be found at http://guzzlephp.org/.
|
||||
*
|
||||
* @see http://docs.guzzlephp.org/en/v6/request-options.html
|
||||
* @link http://docs.guzzlephp.org/en/v6/request-options.html
|
||||
*/
|
||||
final class RequestOptions
|
||||
{
|
||||
@@ -32,7 +32,7 @@ final class RequestOptions
|
||||
* response that was received, and the effective URI. Any return value
|
||||
* from the on_redirect function is ignored.
|
||||
*/
|
||||
public const ALLOW_REDIRECTS = 'allow_redirects';
|
||||
const ALLOW_REDIRECTS = 'allow_redirects';
|
||||
/**
|
||||
* auth: (array) Pass an array of HTTP authentication parameters to use
|
||||
* with the request. The array must contain the username in index [0],
|
||||
@@ -40,12 +40,12 @@ final class RequestOptions
|
||||
* authentication type in index [2]. Pass null to disable authentication
|
||||
* for a request.
|
||||
*/
|
||||
public const AUTH = 'auth';
|
||||
const AUTH = 'auth';
|
||||
/**
|
||||
* body: (resource|string|null|int|float|StreamInterface|callable|\Iterator)
|
||||
* Body to send in the request.
|
||||
*/
|
||||
public const BODY = 'body';
|
||||
const BODY = 'body';
|
||||
/**
|
||||
* cert: (string|array) Set to a string to specify the path to a file
|
||||
* containing a PEM formatted SSL client side certificate. If a password
|
||||
@@ -53,48 +53,37 @@ final class RequestOptions
|
||||
* file in the first array element followed by the certificate password
|
||||
* in the second array element.
|
||||
*/
|
||||
public const CERT = 'cert';
|
||||
const CERT = 'cert';
|
||||
/**
|
||||
* cookies: (bool|GuzzleHttp\Cookie\CookieJarInterface, default=false)
|
||||
* Specifies whether or not cookies are used in a request or what cookie
|
||||
* jar to use or what cookies to send. This option only works if your
|
||||
* handler has the `cookie` middleware. Valid values are `false` and
|
||||
* an instance of {@see \GuzzleHttp\Cookie\CookieJarInterface}.
|
||||
* an instance of {@see GuzzleHttp\Cookie\CookieJarInterface}.
|
||||
*/
|
||||
public const COOKIES = 'cookies';
|
||||
const COOKIES = 'cookies';
|
||||
/**
|
||||
* connect_timeout: (float, default=0) Float describing the number of
|
||||
* seconds to wait while trying to connect to a server. Use 0 to wait
|
||||
* 300 seconds (the default behavior).
|
||||
* indefinitely (the default behavior).
|
||||
*/
|
||||
public const CONNECT_TIMEOUT = 'connect_timeout';
|
||||
/**
|
||||
* crypto_method: (int) A value describing the minimum TLS protocol
|
||||
* version to use.
|
||||
*
|
||||
* This setting must be set to one of the
|
||||
* ``STREAM_CRYPTO_METHOD_TLS*_CLIENT`` constants. PHP 7.4 or higher is
|
||||
* required in order to use TLS 1.3, and cURL 7.34.0 or higher is required
|
||||
* in order to specify a crypto method, with cURL 7.52.0 or higher being
|
||||
* required to use TLS 1.3.
|
||||
*/
|
||||
public const CRYPTO_METHOD = 'crypto_method';
|
||||
const CONNECT_TIMEOUT = 'connect_timeout';
|
||||
/**
|
||||
* debug: (bool|resource) Set to true or set to a PHP stream returned by
|
||||
* fopen() enable debug output with the HTTP handler used to send a
|
||||
* request.
|
||||
*/
|
||||
public const DEBUG = 'debug';
|
||||
const DEBUG = 'debug';
|
||||
/**
|
||||
* decode_content: (bool, default=true) Specify whether or not
|
||||
* Content-Encoding responses (gzip, deflate, etc.) are automatically
|
||||
* decoded.
|
||||
*/
|
||||
public const DECODE_CONTENT = 'decode_content';
|
||||
const DECODE_CONTENT = 'decode_content';
|
||||
/**
|
||||
* delay: (int) The amount of time to delay before sending in milliseconds.
|
||||
*/
|
||||
public const DELAY = 'delay';
|
||||
const DELAY = 'delay';
|
||||
/**
|
||||
* expect: (bool|integer) Controls the behavior of the
|
||||
* "Expect: 100-Continue" header.
|
||||
@@ -111,39 +100,39 @@ final class RequestOptions
|
||||
* size of the body of a request is greater than 1 MB and a request is
|
||||
* using HTTP/1.1.
|
||||
*/
|
||||
public const EXPECT = 'expect';
|
||||
const EXPECT = 'expect';
|
||||
/**
|
||||
* form_params: (array) Associative array of form field names to values
|
||||
* where each value is a string or array of strings. Sets the Content-Type
|
||||
* header to application/x-www-form-urlencoded when no Content-Type header
|
||||
* is already present.
|
||||
*/
|
||||
public const FORM_PARAMS = 'form_params';
|
||||
const FORM_PARAMS = 'form_params';
|
||||
/**
|
||||
* headers: (array) Associative array of HTTP headers. Each value MUST be
|
||||
* a string or array of strings.
|
||||
*/
|
||||
public const HEADERS = 'headers';
|
||||
const HEADERS = 'headers';
|
||||
/**
|
||||
* http_errors: (bool, default=true) Set to false to disable exceptions
|
||||
* when a non- successful HTTP response is received. By default,
|
||||
* exceptions will be thrown for 4xx and 5xx responses. This option only
|
||||
* works if your handler has the `httpErrors` middleware.
|
||||
*/
|
||||
public const HTTP_ERRORS = 'http_errors';
|
||||
const HTTP_ERRORS = 'http_errors';
|
||||
/**
|
||||
* idn: (bool|int, default=true) A combination of IDNA_* constants for
|
||||
* idn_to_ascii() PHP's function (see "options" parameter). Set to false to
|
||||
* disable IDN support completely, or to true to use the default
|
||||
* configuration (IDNA_DEFAULT constant).
|
||||
*/
|
||||
public const IDN_CONVERSION = 'idn_conversion';
|
||||
const IDN_CONVERSION = 'idn_conversion';
|
||||
/**
|
||||
* json: (mixed) Adds JSON data to a request. The provided value is JSON
|
||||
* encoded and a Content-Type header of application/json will be added to
|
||||
* the request if no Content-Type header is already present.
|
||||
*/
|
||||
public const JSON = 'json';
|
||||
const JSON = 'json';
|
||||
/**
|
||||
* multipart: (array) Array of associative arrays, each containing a
|
||||
* required "name" key mapping to the form field, name, a required
|
||||
@@ -153,13 +142,13 @@ final class RequestOptions
|
||||
* the part. If no "filename" key is present, then no "filename" attribute
|
||||
* will be added to the part.
|
||||
*/
|
||||
public const MULTIPART = 'multipart';
|
||||
const MULTIPART = 'multipart';
|
||||
/**
|
||||
* on_headers: (callable) A callable that is invoked when the HTTP headers
|
||||
* of the response have been received but the body has not yet begun to
|
||||
* download.
|
||||
*/
|
||||
public const ON_HEADERS = 'on_headers';
|
||||
const ON_HEADERS = 'on_headers';
|
||||
/**
|
||||
* on_stats: (callable) allows you to get access to transfer statistics of
|
||||
* a request and access the lower level transfer details of the handler
|
||||
@@ -169,7 +158,7 @@ final class RequestOptions
|
||||
* the error encountered. Included in the data is the total amount of time
|
||||
* taken to send the request.
|
||||
*/
|
||||
public const ON_STATS = 'on_stats';
|
||||
const ON_STATS = 'on_stats';
|
||||
/**
|
||||
* progress: (callable) Defines a function to invoke when transfer
|
||||
* progress is made. The function accepts the following positional
|
||||
@@ -177,45 +166,45 @@ final class RequestOptions
|
||||
* number of bytes downloaded so far, the number of bytes expected to be
|
||||
* uploaded, the number of bytes uploaded so far.
|
||||
*/
|
||||
public const PROGRESS = 'progress';
|
||||
const PROGRESS = 'progress';
|
||||
/**
|
||||
* proxy: (string|array) Pass a string to specify an HTTP proxy, or an
|
||||
* array to specify different proxies for different protocols (where the
|
||||
* key is the protocol and the value is a proxy string).
|
||||
*/
|
||||
public const PROXY = 'proxy';
|
||||
const PROXY = 'proxy';
|
||||
/**
|
||||
* query: (array|string) Associative array of query string values to add
|
||||
* to the request. This option uses PHP's http_build_query() to create
|
||||
* the string representation. Pass a string value if you need more
|
||||
* control than what this method provides
|
||||
*/
|
||||
public const QUERY = 'query';
|
||||
const QUERY = 'query';
|
||||
/**
|
||||
* sink: (resource|string|StreamInterface) Where the data of the
|
||||
* response is written to. Defaults to a PHP temp stream. Providing a
|
||||
* string will write data to a file by the given name.
|
||||
*/
|
||||
public const SINK = 'sink';
|
||||
const SINK = 'sink';
|
||||
/**
|
||||
* synchronous: (bool) Set to true to inform HTTP handlers that you intend
|
||||
* on waiting on the response. This can be useful for optimizations. Note
|
||||
* that a promise is still returned if you are using one of the async
|
||||
* client methods.
|
||||
*/
|
||||
public const SYNCHRONOUS = 'synchronous';
|
||||
const SYNCHRONOUS = 'synchronous';
|
||||
/**
|
||||
* ssl_key: (array|string) Specify the path to a file containing a private
|
||||
* SSL key in PEM format. If a password is required, then set to an array
|
||||
* containing the path to the SSL key in the first array element followed
|
||||
* by the password required for the certificate in the second element.
|
||||
*/
|
||||
public const SSL_KEY = 'ssl_key';
|
||||
const SSL_KEY = 'ssl_key';
|
||||
/**
|
||||
* stream: Set to true to attempt to stream a response rather than
|
||||
* download it all up-front.
|
||||
*/
|
||||
public const STREAM = 'stream';
|
||||
const STREAM = 'stream';
|
||||
/**
|
||||
* verify: (bool|string, default=true) Describes the SSL certificate
|
||||
* verification behavior of a request. Set to true to enable SSL
|
||||
@@ -224,23 +213,23 @@ final class RequestOptions
|
||||
* is insecure!). Set to a string to provide the path to a CA bundle on
|
||||
* disk to enable verification using a custom certificate.
|
||||
*/
|
||||
public const VERIFY = 'verify';
|
||||
const VERIFY = 'verify';
|
||||
/**
|
||||
* timeout: (float, default=0) Float describing the timeout of the
|
||||
* request in seconds. Use 0 to wait indefinitely (the default behavior).
|
||||
*/
|
||||
public const TIMEOUT = 'timeout';
|
||||
const TIMEOUT = 'timeout';
|
||||
/**
|
||||
* read_timeout: (float, default=default_socket_timeout ini setting) Float describing
|
||||
* the body read timeout, for stream requests.
|
||||
*/
|
||||
public const READ_TIMEOUT = 'read_timeout';
|
||||
const READ_TIMEOUT = 'read_timeout';
|
||||
/**
|
||||
* version: (float) Specifies the HTTP protocol version to attempt to use.
|
||||
*/
|
||||
public const VERSION = 'version';
|
||||
const VERSION = 'version';
|
||||
/**
|
||||
* force_ip_resolve: (bool) Force client to use only ipv4 or ipv6 protocol
|
||||
*/
|
||||
public const FORCE_IP_RESOLVE = 'force_ip_resolve';
|
||||
const FORCE_IP_RESOLVE = 'force_ip_resolve';
|
||||
}
|
||||
|
||||
@@ -2,39 +2,32 @@
|
||||
|
||||
namespace YoastSEO_Vendor\GuzzleHttp;
|
||||
|
||||
use YoastSEO_Vendor\GuzzleHttp\Promise as P;
|
||||
use YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface;
|
||||
use YoastSEO_Vendor\GuzzleHttp\Promise\RejectedPromise;
|
||||
use YoastSEO_Vendor\GuzzleHttp\Psr7;
|
||||
use YoastSEO_Vendor\Psr\Http\Message\RequestInterface;
|
||||
use YoastSEO_Vendor\Psr\Http\Message\ResponseInterface;
|
||||
/**
|
||||
* Middleware that retries requests based on the boolean result of
|
||||
* invoking the provided "decider" function.
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class RetryMiddleware
|
||||
{
|
||||
/**
|
||||
* @var callable(RequestInterface, array): PromiseInterface
|
||||
*/
|
||||
/** @var callable */
|
||||
private $nextHandler;
|
||||
/**
|
||||
* @var callable
|
||||
*/
|
||||
/** @var callable */
|
||||
private $decider;
|
||||
/**
|
||||
* @var callable(int)
|
||||
*/
|
||||
/** @var callable */
|
||||
private $delay;
|
||||
/**
|
||||
* @param callable $decider Function that accepts the number of retries,
|
||||
* a request, [response], and [exception] and
|
||||
* returns true if the request is to be
|
||||
* retried.
|
||||
* @param callable(RequestInterface, array): PromiseInterface $nextHandler Next handler to invoke.
|
||||
* @param (callable(int): int)|null $delay Function that accepts the number of retries
|
||||
* and returns the number of
|
||||
* milliseconds to delay.
|
||||
* @param callable $decider Function that accepts the number of retries,
|
||||
* a request, [response], and [exception] and
|
||||
* returns true if the request is to be
|
||||
* retried.
|
||||
* @param callable $nextHandler Next handler to invoke.
|
||||
* @param callable $delay Function that accepts the number of retries
|
||||
* and [response] and returns the number of
|
||||
* milliseconds to delay.
|
||||
*/
|
||||
public function __construct(callable $decider, callable $nextHandler, callable $delay = null)
|
||||
{
|
||||
@@ -45,13 +38,21 @@ class RetryMiddleware
|
||||
/**
|
||||
* Default exponential backoff delay function.
|
||||
*
|
||||
* @param int $retries
|
||||
*
|
||||
* @return int milliseconds.
|
||||
*/
|
||||
public static function exponentialDelay(int $retries) : int
|
||||
public static function exponentialDelay($retries)
|
||||
{
|
||||
return (int) 2 ** ($retries - 1) * 1000;
|
||||
return (int) \pow(2, $retries - 1) * 1000;
|
||||
}
|
||||
public function __invoke(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
|
||||
/**
|
||||
* @param RequestInterface $request
|
||||
* @param array $options
|
||||
*
|
||||
* @return PromiseInterface
|
||||
*/
|
||||
public function __invoke(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options)
|
||||
{
|
||||
if (!isset($options['retries'])) {
|
||||
$options['retries'] = 0;
|
||||
@@ -61,31 +62,38 @@ class RetryMiddleware
|
||||
}
|
||||
/**
|
||||
* Execute fulfilled closure
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
private function onFulfilled(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options) : callable
|
||||
private function onFulfilled(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $req, array $options)
|
||||
{
|
||||
return function ($value) use($request, $options) {
|
||||
if (!($this->decider)($options['retries'], $request, $value, null)) {
|
||||
return function ($value) use($req, $options) {
|
||||
if (!\call_user_func($this->decider, $options['retries'], $req, $value, null)) {
|
||||
return $value;
|
||||
}
|
||||
return $this->doRetry($request, $options, $value);
|
||||
return $this->doRetry($req, $options, $value);
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Execute rejected closure
|
||||
*
|
||||
* @return callable
|
||||
*/
|
||||
private function onRejected(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $req, array $options) : callable
|
||||
private function onRejected(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $req, array $options)
|
||||
{
|
||||
return function ($reason) use($req, $options) {
|
||||
if (!($this->decider)($options['retries'], $req, null, $reason)) {
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Promise\Create::rejectionFor($reason);
|
||||
if (!\call_user_func($this->decider, $options['retries'], $req, null, $reason)) {
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Promise\rejection_for($reason);
|
||||
}
|
||||
return $this->doRetry($req, $options);
|
||||
};
|
||||
}
|
||||
private function doRetry(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options, \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response = null) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
|
||||
/**
|
||||
* @return self
|
||||
*/
|
||||
private function doRetry(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options, \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response = null)
|
||||
{
|
||||
$options['delay'] = ($this->delay)(++$options['retries'], $response, $request);
|
||||
$options['delay'] = \call_user_func($this->delay, ++$options['retries'], $response);
|
||||
return $this($request, $options);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,25 +11,10 @@ use YoastSEO_Vendor\Psr\Http\Message\UriInterface;
|
||||
*/
|
||||
final class TransferStats
|
||||
{
|
||||
/**
|
||||
* @var RequestInterface
|
||||
*/
|
||||
private $request;
|
||||
/**
|
||||
* @var ResponseInterface|null
|
||||
*/
|
||||
private $response;
|
||||
/**
|
||||
* @var float|null
|
||||
*/
|
||||
private $transferTime;
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $handlerStats;
|
||||
/**
|
||||
* @var mixed|null
|
||||
*/
|
||||
private $handlerErrorData;
|
||||
/**
|
||||
* @param RequestInterface $request Request that was sent.
|
||||
@@ -38,7 +23,7 @@ final class TransferStats
|
||||
* @param mixed $handlerErrorData Handler error data.
|
||||
* @param array $handlerStats Handler specific stats.
|
||||
*/
|
||||
public function __construct(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response = null, float $transferTime = null, $handlerErrorData = null, array $handlerStats = [])
|
||||
public function __construct(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response = null, $transferTime = null, $handlerErrorData = null, $handlerStats = [])
|
||||
{
|
||||
$this->request = $request;
|
||||
$this->response = $response;
|
||||
@@ -46,21 +31,28 @@ final class TransferStats
|
||||
$this->handlerErrorData = $handlerErrorData;
|
||||
$this->handlerStats = $handlerStats;
|
||||
}
|
||||
public function getRequest() : \YoastSEO_Vendor\Psr\Http\Message\RequestInterface
|
||||
/**
|
||||
* @return RequestInterface
|
||||
*/
|
||||
public function getRequest()
|
||||
{
|
||||
return $this->request;
|
||||
}
|
||||
/**
|
||||
* Returns the response that was received (if any).
|
||||
*
|
||||
* @return ResponseInterface|null
|
||||
*/
|
||||
public function getResponse() : ?\YoastSEO_Vendor\Psr\Http\Message\ResponseInterface
|
||||
public function getResponse()
|
||||
{
|
||||
return $this->response;
|
||||
}
|
||||
/**
|
||||
* Returns true if a response was received.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasResponse() : bool
|
||||
public function hasResponse()
|
||||
{
|
||||
return $this->response !== null;
|
||||
}
|
||||
@@ -79,8 +71,10 @@ final class TransferStats
|
||||
}
|
||||
/**
|
||||
* Get the effective URI the request was sent to.
|
||||
*
|
||||
* @return UriInterface
|
||||
*/
|
||||
public function getEffectiveUri() : \YoastSEO_Vendor\Psr\Http\Message\UriInterface
|
||||
public function getEffectiveUri()
|
||||
{
|
||||
return $this->request->getUri();
|
||||
}
|
||||
@@ -89,14 +83,16 @@ final class TransferStats
|
||||
*
|
||||
* @return float|null Time in seconds.
|
||||
*/
|
||||
public function getTransferTime() : ?float
|
||||
public function getTransferTime()
|
||||
{
|
||||
return $this->transferTime;
|
||||
}
|
||||
/**
|
||||
* Gets an array of all of the handler specific transfer data.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getHandlerStats() : array
|
||||
public function getHandlerStats()
|
||||
{
|
||||
return $this->handlerStats;
|
||||
}
|
||||
@@ -107,8 +103,8 @@ final class TransferStats
|
||||
*
|
||||
* @return mixed|null
|
||||
*/
|
||||
public function getHandlerStat(string $stat)
|
||||
public function getHandlerStat($stat)
|
||||
{
|
||||
return $this->handlerStats[$stat] ?? null;
|
||||
return isset($this->handlerStats[$stat]) ? $this->handlerStats[$stat] : null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,191 @@
|
||||
<?php
|
||||
|
||||
namespace YoastSEO_Vendor\GuzzleHttp;
|
||||
|
||||
/**
|
||||
* Expands URI templates. Userland implementation of PECL uri_template.
|
||||
*
|
||||
* @link http://tools.ietf.org/html/rfc6570
|
||||
*/
|
||||
class UriTemplate
|
||||
{
|
||||
/** @var string URI template */
|
||||
private $template;
|
||||
/** @var array Variables to use in the template expansion */
|
||||
private $variables;
|
||||
/** @var array Hash for quick operator lookups */
|
||||
private static $operatorHash = ['' => ['prefix' => '', 'joiner' => ',', 'query' => \false], '+' => ['prefix' => '', 'joiner' => ',', 'query' => \false], '#' => ['prefix' => '#', 'joiner' => ',', 'query' => \false], '.' => ['prefix' => '.', 'joiner' => '.', 'query' => \false], '/' => ['prefix' => '/', 'joiner' => '/', 'query' => \false], ';' => ['prefix' => ';', 'joiner' => ';', 'query' => \true], '?' => ['prefix' => '?', 'joiner' => '&', 'query' => \true], '&' => ['prefix' => '&', 'joiner' => '&', 'query' => \true]];
|
||||
/** @var array Delimiters */
|
||||
private static $delims = [':', '/', '?', '#', '[', ']', '@', '!', '$', '&', '\'', '(', ')', '*', '+', ',', ';', '='];
|
||||
/** @var array Percent encoded delimiters */
|
||||
private static $delimsPct = ['%3A', '%2F', '%3F', '%23', '%5B', '%5D', '%40', '%21', '%24', '%26', '%27', '%28', '%29', '%2A', '%2B', '%2C', '%3B', '%3D'];
|
||||
public function expand($template, array $variables)
|
||||
{
|
||||
if (\false === \strpos($template, '{')) {
|
||||
return $template;
|
||||
}
|
||||
$this->template = $template;
|
||||
$this->variables = $variables;
|
||||
return \preg_replace_callback('/\\{([^\\}]+)\\}/', [$this, 'expandMatch'], $this->template);
|
||||
}
|
||||
/**
|
||||
* Parse an expression into parts
|
||||
*
|
||||
* @param string $expression Expression to parse
|
||||
*
|
||||
* @return array Returns an associative array of parts
|
||||
*/
|
||||
private function parseExpression($expression)
|
||||
{
|
||||
$result = [];
|
||||
if (isset(self::$operatorHash[$expression[0]])) {
|
||||
$result['operator'] = $expression[0];
|
||||
$expression = \substr($expression, 1);
|
||||
} else {
|
||||
$result['operator'] = '';
|
||||
}
|
||||
foreach (\explode(',', $expression) as $value) {
|
||||
$value = \trim($value);
|
||||
$varspec = [];
|
||||
if ($colonPos = \strpos($value, ':')) {
|
||||
$varspec['value'] = \substr($value, 0, $colonPos);
|
||||
$varspec['modifier'] = ':';
|
||||
$varspec['position'] = (int) \substr($value, $colonPos + 1);
|
||||
} elseif (\substr($value, -1) === '*') {
|
||||
$varspec['modifier'] = '*';
|
||||
$varspec['value'] = \substr($value, 0, -1);
|
||||
} else {
|
||||
$varspec['value'] = (string) $value;
|
||||
$varspec['modifier'] = '';
|
||||
}
|
||||
$result['values'][] = $varspec;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
/**
|
||||
* Process an expansion
|
||||
*
|
||||
* @param array $matches Matches met in the preg_replace_callback
|
||||
*
|
||||
* @return string Returns the replacement string
|
||||
*/
|
||||
private function expandMatch(array $matches)
|
||||
{
|
||||
static $rfc1738to3986 = ['+' => '%20', '%7e' => '~'];
|
||||
$replacements = [];
|
||||
$parsed = self::parseExpression($matches[1]);
|
||||
$prefix = self::$operatorHash[$parsed['operator']]['prefix'];
|
||||
$joiner = self::$operatorHash[$parsed['operator']]['joiner'];
|
||||
$useQuery = self::$operatorHash[$parsed['operator']]['query'];
|
||||
foreach ($parsed['values'] as $value) {
|
||||
if (!isset($this->variables[$value['value']])) {
|
||||
continue;
|
||||
}
|
||||
$variable = $this->variables[$value['value']];
|
||||
$actuallyUseQuery = $useQuery;
|
||||
$expanded = '';
|
||||
if (\is_array($variable)) {
|
||||
$isAssoc = $this->isAssoc($variable);
|
||||
$kvp = [];
|
||||
foreach ($variable as $key => $var) {
|
||||
if ($isAssoc) {
|
||||
$key = \rawurlencode($key);
|
||||
$isNestedArray = \is_array($var);
|
||||
} else {
|
||||
$isNestedArray = \false;
|
||||
}
|
||||
if (!$isNestedArray) {
|
||||
$var = \rawurlencode($var);
|
||||
if ($parsed['operator'] === '+' || $parsed['operator'] === '#') {
|
||||
$var = $this->decodeReserved($var);
|
||||
}
|
||||
}
|
||||
if ($value['modifier'] === '*') {
|
||||
if ($isAssoc) {
|
||||
if ($isNestedArray) {
|
||||
// Nested arrays must allow for deeply nested
|
||||
// structures.
|
||||
$var = \strtr(\http_build_query([$key => $var]), $rfc1738to3986);
|
||||
} else {
|
||||
$var = $key . '=' . $var;
|
||||
}
|
||||
} elseif ($key > 0 && $actuallyUseQuery) {
|
||||
$var = $value['value'] . '=' . $var;
|
||||
}
|
||||
}
|
||||
$kvp[$key] = $var;
|
||||
}
|
||||
if (empty($variable)) {
|
||||
$actuallyUseQuery = \false;
|
||||
} elseif ($value['modifier'] === '*') {
|
||||
$expanded = \implode($joiner, $kvp);
|
||||
if ($isAssoc) {
|
||||
// Don't prepend the value name when using the explode
|
||||
// modifier with an associative array.
|
||||
$actuallyUseQuery = \false;
|
||||
}
|
||||
} else {
|
||||
if ($isAssoc) {
|
||||
// When an associative array is encountered and the
|
||||
// explode modifier is not set, then the result must be
|
||||
// a comma separated list of keys followed by their
|
||||
// respective values.
|
||||
foreach ($kvp as $k => &$v) {
|
||||
$v = $k . ',' . $v;
|
||||
}
|
||||
}
|
||||
$expanded = \implode(',', $kvp);
|
||||
}
|
||||
} else {
|
||||
if ($value['modifier'] === ':') {
|
||||
$variable = \substr($variable, 0, $value['position']);
|
||||
}
|
||||
$expanded = \rawurlencode($variable);
|
||||
if ($parsed['operator'] === '+' || $parsed['operator'] === '#') {
|
||||
$expanded = $this->decodeReserved($expanded);
|
||||
}
|
||||
}
|
||||
if ($actuallyUseQuery) {
|
||||
if (!$expanded && $joiner !== '&') {
|
||||
$expanded = $value['value'];
|
||||
} else {
|
||||
$expanded = $value['value'] . '=' . $expanded;
|
||||
}
|
||||
}
|
||||
$replacements[] = $expanded;
|
||||
}
|
||||
$ret = \implode($joiner, $replacements);
|
||||
if ($ret && $prefix) {
|
||||
return $prefix . $ret;
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
/**
|
||||
* Determines if an array is associative.
|
||||
*
|
||||
* This makes the assumption that input arrays are sequences or hashes.
|
||||
* This assumption is a tradeoff for accuracy in favor of speed, but it
|
||||
* should work in almost every case where input is supplied for a URI
|
||||
* template.
|
||||
*
|
||||
* @param array $array Array to check
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function isAssoc(array $array)
|
||||
{
|
||||
return $array && \array_keys($array)[0] !== 0;
|
||||
}
|
||||
/**
|
||||
* Removes percent encoding on reserved characters (used with + and #
|
||||
* modifiers).
|
||||
*
|
||||
* @param string $string String to fix
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function decodeReserved($string)
|
||||
{
|
||||
return \str_replace(self::$delimsPct, self::$delims, $string);
|
||||
}
|
||||
}
|
||||
@@ -3,296 +3,37 @@
|
||||
namespace YoastSEO_Vendor\GuzzleHttp;
|
||||
|
||||
use YoastSEO_Vendor\GuzzleHttp\Exception\InvalidArgumentException;
|
||||
use YoastSEO_Vendor\GuzzleHttp\Handler\CurlHandler;
|
||||
use YoastSEO_Vendor\GuzzleHttp\Handler\CurlMultiHandler;
|
||||
use YoastSEO_Vendor\GuzzleHttp\Handler\Proxy;
|
||||
use YoastSEO_Vendor\GuzzleHttp\Handler\StreamHandler;
|
||||
use YoastSEO_Vendor\Psr\Http\Message\UriInterface;
|
||||
use YoastSEO_Vendor\Symfony\Polyfill\Intl\Idn\Idn;
|
||||
final class Utils
|
||||
{
|
||||
/**
|
||||
* Debug function used to describe the provided value type and class.
|
||||
*
|
||||
* @param mixed $input
|
||||
*
|
||||
* @return string Returns a string containing the type of the variable and
|
||||
* if a class is provided, the class name.
|
||||
*/
|
||||
public static function describeType($input) : string
|
||||
{
|
||||
switch (\gettype($input)) {
|
||||
case 'object':
|
||||
return 'object(' . \get_class($input) . ')';
|
||||
case 'array':
|
||||
return 'array(' . \count($input) . ')';
|
||||
default:
|
||||
\ob_start();
|
||||
\var_dump($input);
|
||||
// normalize float vs double
|
||||
/** @var string $varDumpContent */
|
||||
$varDumpContent = \ob_get_clean();
|
||||
return \str_replace('double(', 'float(', \rtrim($varDumpContent));
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Parses an array of header lines into an associative array of headers.
|
||||
*
|
||||
* @param iterable $lines Header lines array of strings in the following
|
||||
* format: "Name: Value"
|
||||
*/
|
||||
public static function headersFromLines(iterable $lines) : array
|
||||
{
|
||||
$headers = [];
|
||||
foreach ($lines as $line) {
|
||||
$parts = \explode(':', $line, 2);
|
||||
$headers[\trim($parts[0])][] = isset($parts[1]) ? \trim($parts[1]) : null;
|
||||
}
|
||||
return $headers;
|
||||
}
|
||||
/**
|
||||
* Returns a debug stream based on the provided variable.
|
||||
*
|
||||
* @param mixed $value Optional value
|
||||
*
|
||||
* @return resource
|
||||
*/
|
||||
public static function debugResource($value = null)
|
||||
{
|
||||
if (\is_resource($value)) {
|
||||
return $value;
|
||||
}
|
||||
if (\defined('STDOUT')) {
|
||||
return \STDOUT;
|
||||
}
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::tryFopen('php://output', 'w');
|
||||
}
|
||||
/**
|
||||
* Chooses and creates a default handler to use based on the environment.
|
||||
*
|
||||
* The returned handler is not wrapped by any default middlewares.
|
||||
*
|
||||
* @return callable(\Psr\Http\Message\RequestInterface, array): \GuzzleHttp\Promise\PromiseInterface Returns the best handler for the given system.
|
||||
*
|
||||
* @throws \RuntimeException if no viable Handler is available.
|
||||
*/
|
||||
public static function chooseHandler() : callable
|
||||
{
|
||||
$handler = null;
|
||||
if (\defined('CURLOPT_CUSTOMREQUEST')) {
|
||||
if (\function_exists('curl_multi_exec') && \function_exists('curl_exec')) {
|
||||
$handler = \YoastSEO_Vendor\GuzzleHttp\Handler\Proxy::wrapSync(new \YoastSEO_Vendor\GuzzleHttp\Handler\CurlMultiHandler(), new \YoastSEO_Vendor\GuzzleHttp\Handler\CurlHandler());
|
||||
} elseif (\function_exists('curl_exec')) {
|
||||
$handler = new \YoastSEO_Vendor\GuzzleHttp\Handler\CurlHandler();
|
||||
} elseif (\function_exists('curl_multi_exec')) {
|
||||
$handler = new \YoastSEO_Vendor\GuzzleHttp\Handler\CurlMultiHandler();
|
||||
}
|
||||
}
|
||||
if (\ini_get('allow_url_fopen')) {
|
||||
$handler = $handler ? \YoastSEO_Vendor\GuzzleHttp\Handler\Proxy::wrapStreaming($handler, new \YoastSEO_Vendor\GuzzleHttp\Handler\StreamHandler()) : new \YoastSEO_Vendor\GuzzleHttp\Handler\StreamHandler();
|
||||
} elseif (!$handler) {
|
||||
throw new \RuntimeException('GuzzleHttp requires cURL, the allow_url_fopen ini setting, or a custom HTTP handler.');
|
||||
}
|
||||
return $handler;
|
||||
}
|
||||
/**
|
||||
* Get the default User-Agent string to use with Guzzle.
|
||||
*/
|
||||
public static function defaultUserAgent() : string
|
||||
{
|
||||
return \sprintf('GuzzleHttp/%d', \YoastSEO_Vendor\GuzzleHttp\ClientInterface::MAJOR_VERSION);
|
||||
}
|
||||
/**
|
||||
* Returns the default cacert bundle for the current system.
|
||||
*
|
||||
* First, the openssl.cafile and curl.cainfo php.ini settings are checked.
|
||||
* If those settings are not configured, then the common locations for
|
||||
* bundles found on Red Hat, CentOS, Fedora, Ubuntu, Debian, FreeBSD, OS X
|
||||
* and Windows are checked. If any of these file locations are found on
|
||||
* disk, they will be utilized.
|
||||
*
|
||||
* Note: the result of this function is cached for subsequent calls.
|
||||
*
|
||||
* @throws \RuntimeException if no bundle can be found.
|
||||
*
|
||||
* @deprecated Utils::defaultCaBundle will be removed in guzzlehttp/guzzle:8.0. This method is not needed in PHP 5.6+.
|
||||
*/
|
||||
public static function defaultCaBundle() : string
|
||||
{
|
||||
static $cached = null;
|
||||
static $cafiles = [
|
||||
// Red Hat, CentOS, Fedora (provided by the ca-certificates package)
|
||||
'/etc/pki/tls/certs/ca-bundle.crt',
|
||||
// Ubuntu, Debian (provided by the ca-certificates package)
|
||||
'/etc/ssl/certs/ca-certificates.crt',
|
||||
// FreeBSD (provided by the ca_root_nss package)
|
||||
'/usr/local/share/certs/ca-root-nss.crt',
|
||||
// SLES 12 (provided by the ca-certificates package)
|
||||
'/var/lib/ca-certificates/ca-bundle.pem',
|
||||
// OS X provided by homebrew (using the default path)
|
||||
'/usr/local/etc/openssl/cert.pem',
|
||||
// Google app engine
|
||||
'/etc/ca-certificates.crt',
|
||||
// Windows?
|
||||
'C:\\windows\\system32\\curl-ca-bundle.crt',
|
||||
'C:\\windows\\curl-ca-bundle.crt',
|
||||
];
|
||||
if ($cached) {
|
||||
return $cached;
|
||||
}
|
||||
if ($ca = \ini_get('openssl.cafile')) {
|
||||
return $cached = $ca;
|
||||
}
|
||||
if ($ca = \ini_get('curl.cainfo')) {
|
||||
return $cached = $ca;
|
||||
}
|
||||
foreach ($cafiles as $filename) {
|
||||
if (\file_exists($filename)) {
|
||||
return $cached = $filename;
|
||||
}
|
||||
}
|
||||
throw new \RuntimeException(<<<EOT
|
||||
No system CA bundle could be found in any of the the common system locations.
|
||||
PHP versions earlier than 5.6 are not properly configured to use the system's
|
||||
CA bundle by default. In order to verify peer certificates, you will need to
|
||||
supply the path on disk to a certificate bundle to the 'verify' request
|
||||
option: http://docs.guzzlephp.org/en/latest/clients.html#verify. If you do not
|
||||
need a specific certificate bundle, then Mozilla provides a commonly used CA
|
||||
bundle which can be downloaded here (provided by the maintainer of cURL):
|
||||
https://curl.haxx.se/ca/cacert.pem. Once
|
||||
you have a CA bundle available on disk, you can set the 'openssl.cafile' PHP
|
||||
ini setting to point to the path to the file, allowing you to omit the 'verify'
|
||||
request option. See https://curl.haxx.se/docs/sslcerts.html for more
|
||||
information.
|
||||
EOT
|
||||
);
|
||||
}
|
||||
/**
|
||||
* Creates an associative array of lowercase header names to the actual
|
||||
* header casing.
|
||||
*/
|
||||
public static function normalizeHeaderKeys(array $headers) : array
|
||||
{
|
||||
$result = [];
|
||||
foreach (\array_keys($headers) as $key) {
|
||||
$result[\strtolower($key)] = $key;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
/**
|
||||
* Returns true if the provided host matches any of the no proxy areas.
|
||||
*
|
||||
* This method will strip a port from the host if it is present. Each pattern
|
||||
* can be matched with an exact match (e.g., "foo.com" == "foo.com") or a
|
||||
* partial match: (e.g., "foo.com" == "baz.foo.com" and ".foo.com" ==
|
||||
* "baz.foo.com", but ".foo.com" != "foo.com").
|
||||
*
|
||||
* Areas are matched in the following cases:
|
||||
* 1. "*" (without quotes) always matches any hosts.
|
||||
* 2. An exact match.
|
||||
* 3. The area starts with "." and the area is the last part of the host. e.g.
|
||||
* '.mit.edu' will match any host that ends with '.mit.edu'.
|
||||
*
|
||||
* @param string $host Host to check against the patterns.
|
||||
* @param string[] $noProxyArray An array of host patterns.
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public static function isHostInNoProxy(string $host, array $noProxyArray) : bool
|
||||
{
|
||||
if (\strlen($host) === 0) {
|
||||
throw new \YoastSEO_Vendor\GuzzleHttp\Exception\InvalidArgumentException('Empty host provided');
|
||||
}
|
||||
// Strip port if present.
|
||||
[$host] = \explode(':', $host, 2);
|
||||
foreach ($noProxyArray as $area) {
|
||||
// Always match on wildcards.
|
||||
if ($area === '*') {
|
||||
return \true;
|
||||
}
|
||||
if (empty($area)) {
|
||||
// Don't match on empty values.
|
||||
continue;
|
||||
}
|
||||
if ($area === $host) {
|
||||
// Exact matches.
|
||||
return \true;
|
||||
}
|
||||
// Special match if the area when prefixed with ".". Remove any
|
||||
// existing leading "." and add a new leading ".".
|
||||
$area = '.' . \ltrim($area, '.');
|
||||
if (\substr($host, -\strlen($area)) === $area) {
|
||||
return \true;
|
||||
}
|
||||
}
|
||||
return \false;
|
||||
}
|
||||
/**
|
||||
* Wrapper for json_decode that throws when an error occurs.
|
||||
*
|
||||
* @param string $json JSON data to parse
|
||||
* @param bool $assoc When true, returned objects will be converted
|
||||
* into associative arrays.
|
||||
* @param int $depth User specified recursion depth.
|
||||
* @param int $options Bitmask of JSON decode options.
|
||||
*
|
||||
* @return object|array|string|int|float|bool|null
|
||||
*
|
||||
* @throws InvalidArgumentException if the JSON cannot be decoded.
|
||||
*
|
||||
* @see https://www.php.net/manual/en/function.json-decode.php
|
||||
*/
|
||||
public static function jsonDecode(string $json, bool $assoc = \false, int $depth = 512, int $options = 0)
|
||||
{
|
||||
$data = \json_decode($json, $assoc, $depth, $options);
|
||||
if (\JSON_ERROR_NONE !== \json_last_error()) {
|
||||
throw new \YoastSEO_Vendor\GuzzleHttp\Exception\InvalidArgumentException('json_decode error: ' . \json_last_error_msg());
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
/**
|
||||
* Wrapper for JSON encoding that throws when an error occurs.
|
||||
*
|
||||
* @param mixed $value The value being encoded
|
||||
* @param int $options JSON encode option bitmask
|
||||
* @param int $depth Set the maximum depth. Must be greater than zero.
|
||||
*
|
||||
* @throws InvalidArgumentException if the JSON cannot be encoded.
|
||||
*
|
||||
* @see https://www.php.net/manual/en/function.json-encode.php
|
||||
*/
|
||||
public static function jsonEncode($value, int $options = 0, int $depth = 512) : string
|
||||
{
|
||||
$json = \json_encode($value, $options, $depth);
|
||||
if (\JSON_ERROR_NONE !== \json_last_error()) {
|
||||
throw new \YoastSEO_Vendor\GuzzleHttp\Exception\InvalidArgumentException('json_encode error: ' . \json_last_error_msg());
|
||||
}
|
||||
/** @var string */
|
||||
return $json;
|
||||
}
|
||||
/**
|
||||
* Wrapper for the hrtime() or microtime() functions
|
||||
* (depending on the PHP version, one of the two is used)
|
||||
*
|
||||
* @return float UNIX timestamp
|
||||
* @return float|mixed UNIX timestamp
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
public static function currentTime() : float
|
||||
public static function currentTime()
|
||||
{
|
||||
return (float) \function_exists('hrtime') ? \hrtime(\true) / 1000000000.0 : \microtime(\true);
|
||||
return \function_exists('hrtime') ? \hrtime(\true) / 1000000000.0 : \microtime(\true);
|
||||
}
|
||||
/**
|
||||
* @param int $options
|
||||
*
|
||||
* @return UriInterface
|
||||
* @throws InvalidArgumentException
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
public static function idnUriConvert(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri, int $options = 0) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface
|
||||
public static function idnUriConvert(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri, $options = 0)
|
||||
{
|
||||
if ($uri->getHost()) {
|
||||
$asciiHost = self::idnToAsci($uri->getHost(), $options, $info);
|
||||
if ($asciiHost === \false) {
|
||||
$errorBitSet = $info['errors'] ?? 0;
|
||||
$errorConstants = \array_filter(\array_keys(\get_defined_constants()), static function (string $name) : bool {
|
||||
$errorBitSet = isset($info['errors']) ? $info['errors'] : 0;
|
||||
$errorConstants = \array_filter(\array_keys(\get_defined_constants()), function ($name) {
|
||||
return \substr($name, 0, 11) === 'IDNA_ERROR_';
|
||||
});
|
||||
$errors = [];
|
||||
@@ -306,35 +47,36 @@ EOT
|
||||
$errorMessage .= ' (errors: ' . \implode(', ', $errors) . ')';
|
||||
}
|
||||
throw new \YoastSEO_Vendor\GuzzleHttp\Exception\InvalidArgumentException($errorMessage);
|
||||
}
|
||||
if ($uri->getHost() !== $asciiHost) {
|
||||
// Replace URI only if the ASCII version is different
|
||||
$uri = $uri->withHost($asciiHost);
|
||||
} else {
|
||||
if ($uri->getHost() !== $asciiHost) {
|
||||
// Replace URI only if the ASCII version is different
|
||||
$uri = $uri->withHost($asciiHost);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $uri;
|
||||
}
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public static function getenv(string $name) : ?string
|
||||
{
|
||||
if (isset($_SERVER[$name])) {
|
||||
return (string) $_SERVER[$name];
|
||||
}
|
||||
if (\PHP_SAPI === 'cli' && ($value = \getenv($name)) !== \false && $value !== null) {
|
||||
return (string) $value;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* @param string $domain
|
||||
* @param int $options
|
||||
* @param array $info
|
||||
*
|
||||
* @return string|false
|
||||
*/
|
||||
private static function idnToAsci(string $domain, int $options, ?array &$info = [])
|
||||
private static function idnToAsci($domain, $options, &$info = [])
|
||||
{
|
||||
if (\function_exists('idn_to_ascii') && \defined('INTL_IDNA_VARIANT_UTS46')) {
|
||||
if (\preg_match('%^[ -~]+$%', $domain) === 1) {
|
||||
return $domain;
|
||||
}
|
||||
if (\extension_loaded('intl') && \defined('INTL_IDNA_VARIANT_UTS46')) {
|
||||
return \idn_to_ascii($domain, $options, \INTL_IDNA_VARIANT_UTS46, $info);
|
||||
}
|
||||
throw new \Error('ext-idn or symfony/polyfill-intl-idn not loaded or too old');
|
||||
/*
|
||||
* The Idn class is marked as @internal. Verify that class and method exists.
|
||||
*/
|
||||
if (\method_exists(\YoastSEO_Vendor\Symfony\Polyfill\Intl\Idn\Idn::class, 'idn_to_ascii')) {
|
||||
return \YoastSEO_Vendor\Symfony\Polyfill\Intl\Idn\Idn::idn_to_ascii($domain, $options, \YoastSEO_Vendor\Symfony\Polyfill\Intl\Idn\Idn::INTL_IDNA_VARIANT_UTS46, $info);
|
||||
}
|
||||
throw new \RuntimeException('ext-intl or symfony/polyfill-intl-idn not loaded or too old');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,32 +2,68 @@
|
||||
|
||||
namespace YoastSEO_Vendor\GuzzleHttp;
|
||||
|
||||
use YoastSEO_Vendor\GuzzleHttp\Handler\CurlHandler;
|
||||
use YoastSEO_Vendor\GuzzleHttp\Handler\CurlMultiHandler;
|
||||
use YoastSEO_Vendor\GuzzleHttp\Handler\Proxy;
|
||||
use YoastSEO_Vendor\GuzzleHttp\Handler\StreamHandler;
|
||||
/**
|
||||
* Expands a URI template
|
||||
*
|
||||
* @param string $template URI template
|
||||
* @param array $variables Template variables
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function uri_template($template, array $variables)
|
||||
{
|
||||
if (\extension_loaded('uri_template')) {
|
||||
// @codeCoverageIgnoreStart
|
||||
return \YoastSEO_Vendor\uri_template($template, $variables);
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
static $uriTemplate;
|
||||
if (!$uriTemplate) {
|
||||
$uriTemplate = new \YoastSEO_Vendor\GuzzleHttp\UriTemplate();
|
||||
}
|
||||
return $uriTemplate->expand($template, $variables);
|
||||
}
|
||||
/**
|
||||
* Debug function used to describe the provided value type and class.
|
||||
*
|
||||
* @param mixed $input Any type of variable to describe the type of. This
|
||||
* parameter misses a typehint because of that.
|
||||
* @param mixed $input
|
||||
*
|
||||
* @return string Returns a string containing the type of the variable and
|
||||
* if a class is provided, the class name.
|
||||
*
|
||||
* @deprecated describe_type will be removed in guzzlehttp/guzzle:8.0. Use Utils::describeType instead.
|
||||
*/
|
||||
function describe_type($input) : string
|
||||
function describe_type($input)
|
||||
{
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Utils::describeType($input);
|
||||
switch (\gettype($input)) {
|
||||
case 'object':
|
||||
return 'object(' . \get_class($input) . ')';
|
||||
case 'array':
|
||||
return 'array(' . \count($input) . ')';
|
||||
default:
|
||||
\ob_start();
|
||||
\var_dump($input);
|
||||
// normalize float vs double
|
||||
return \str_replace('double(', 'float(', \rtrim(\ob_get_clean()));
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Parses an array of header lines into an associative array of headers.
|
||||
*
|
||||
* @param iterable $lines Header lines array of strings in the following
|
||||
* format: "Name: Value"
|
||||
*
|
||||
* @deprecated headers_from_lines will be removed in guzzlehttp/guzzle:8.0. Use Utils::headersFromLines instead.
|
||||
* format: "Name: Value"
|
||||
* @return array
|
||||
*/
|
||||
function headers_from_lines(iterable $lines) : array
|
||||
function headers_from_lines($lines)
|
||||
{
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Utils::headersFromLines($lines);
|
||||
$headers = [];
|
||||
foreach ($lines as $line) {
|
||||
$parts = \explode(':', $line, 2);
|
||||
$headers[\trim($parts[0])][] = isset($parts[1]) ? \trim($parts[1]) : null;
|
||||
}
|
||||
return $headers;
|
||||
}
|
||||
/**
|
||||
* Returns a debug stream based on the provided variable.
|
||||
@@ -35,36 +71,57 @@ function headers_from_lines(iterable $lines) : array
|
||||
* @param mixed $value Optional value
|
||||
*
|
||||
* @return resource
|
||||
*
|
||||
* @deprecated debug_resource will be removed in guzzlehttp/guzzle:8.0. Use Utils::debugResource instead.
|
||||
*/
|
||||
function debug_resource($value = null)
|
||||
{
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Utils::debugResource($value);
|
||||
if (\is_resource($value)) {
|
||||
return $value;
|
||||
} elseif (\defined('STDOUT')) {
|
||||
return \STDOUT;
|
||||
}
|
||||
return \fopen('php://output', 'w');
|
||||
}
|
||||
/**
|
||||
* Chooses and creates a default handler to use based on the environment.
|
||||
*
|
||||
* The returned handler is not wrapped by any default middlewares.
|
||||
*
|
||||
* @return callable(\Psr\Http\Message\RequestInterface, array): \GuzzleHttp\Promise\PromiseInterface Returns the best handler for the given system.
|
||||
*
|
||||
* @return callable Returns the best handler for the given system.
|
||||
* @throws \RuntimeException if no viable Handler is available.
|
||||
*
|
||||
* @deprecated choose_handler will be removed in guzzlehttp/guzzle:8.0. Use Utils::chooseHandler instead.
|
||||
*/
|
||||
function choose_handler() : callable
|
||||
function choose_handler()
|
||||
{
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Utils::chooseHandler();
|
||||
$handler = null;
|
||||
if (\function_exists('curl_multi_exec') && \function_exists('curl_exec')) {
|
||||
$handler = \YoastSEO_Vendor\GuzzleHttp\Handler\Proxy::wrapSync(new \YoastSEO_Vendor\GuzzleHttp\Handler\CurlMultiHandler(), new \YoastSEO_Vendor\GuzzleHttp\Handler\CurlHandler());
|
||||
} elseif (\function_exists('curl_exec')) {
|
||||
$handler = new \YoastSEO_Vendor\GuzzleHttp\Handler\CurlHandler();
|
||||
} elseif (\function_exists('curl_multi_exec')) {
|
||||
$handler = new \YoastSEO_Vendor\GuzzleHttp\Handler\CurlMultiHandler();
|
||||
}
|
||||
if (\ini_get('allow_url_fopen')) {
|
||||
$handler = $handler ? \YoastSEO_Vendor\GuzzleHttp\Handler\Proxy::wrapStreaming($handler, new \YoastSEO_Vendor\GuzzleHttp\Handler\StreamHandler()) : new \YoastSEO_Vendor\GuzzleHttp\Handler\StreamHandler();
|
||||
} elseif (!$handler) {
|
||||
throw new \RuntimeException('GuzzleHttp requires cURL, the ' . 'allow_url_fopen ini setting, or a custom HTTP handler.');
|
||||
}
|
||||
return $handler;
|
||||
}
|
||||
/**
|
||||
* Get the default User-Agent string to use with Guzzle.
|
||||
* Get the default User-Agent string to use with Guzzle
|
||||
*
|
||||
* @deprecated default_user_agent will be removed in guzzlehttp/guzzle:8.0. Use Utils::defaultUserAgent instead.
|
||||
* @return string
|
||||
*/
|
||||
function default_user_agent() : string
|
||||
function default_user_agent()
|
||||
{
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Utils::defaultUserAgent();
|
||||
static $defaultAgent = '';
|
||||
if (!$defaultAgent) {
|
||||
$defaultAgent = 'GuzzleHttp/' . \YoastSEO_Vendor\GuzzleHttp\Client::VERSION;
|
||||
if (\extension_loaded('curl') && \function_exists('curl_version')) {
|
||||
$defaultAgent .= ' curl/' . \curl_version()['version'];
|
||||
}
|
||||
$defaultAgent .= ' PHP/' . \PHP_VERSION;
|
||||
}
|
||||
return $defaultAgent;
|
||||
}
|
||||
/**
|
||||
* Returns the default cacert bundle for the current system.
|
||||
@@ -77,23 +134,74 @@ function default_user_agent() : string
|
||||
*
|
||||
* Note: the result of this function is cached for subsequent calls.
|
||||
*
|
||||
* @return string
|
||||
* @throws \RuntimeException if no bundle can be found.
|
||||
*
|
||||
* @deprecated default_ca_bundle will be removed in guzzlehttp/guzzle:8.0. This function is not needed in PHP 5.6+.
|
||||
*/
|
||||
function default_ca_bundle() : string
|
||||
function default_ca_bundle()
|
||||
{
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Utils::defaultCaBundle();
|
||||
static $cached = null;
|
||||
static $cafiles = [
|
||||
// Red Hat, CentOS, Fedora (provided by the ca-certificates package)
|
||||
'/etc/pki/tls/certs/ca-bundle.crt',
|
||||
// Ubuntu, Debian (provided by the ca-certificates package)
|
||||
'/etc/ssl/certs/ca-certificates.crt',
|
||||
// FreeBSD (provided by the ca_root_nss package)
|
||||
'/usr/local/share/certs/ca-root-nss.crt',
|
||||
// SLES 12 (provided by the ca-certificates package)
|
||||
'/var/lib/ca-certificates/ca-bundle.pem',
|
||||
// OS X provided by homebrew (using the default path)
|
||||
'/usr/local/etc/openssl/cert.pem',
|
||||
// Google app engine
|
||||
'/etc/ca-certificates.crt',
|
||||
// Windows?
|
||||
'C:\\windows\\system32\\curl-ca-bundle.crt',
|
||||
'C:\\windows\\curl-ca-bundle.crt',
|
||||
];
|
||||
if ($cached) {
|
||||
return $cached;
|
||||
}
|
||||
if ($ca = \ini_get('openssl.cafile')) {
|
||||
return $cached = $ca;
|
||||
}
|
||||
if ($ca = \ini_get('curl.cainfo')) {
|
||||
return $cached = $ca;
|
||||
}
|
||||
foreach ($cafiles as $filename) {
|
||||
if (\file_exists($filename)) {
|
||||
return $cached = $filename;
|
||||
}
|
||||
}
|
||||
throw new \RuntimeException(<<<EOT
|
||||
No system CA bundle could be found in any of the the common system locations.
|
||||
PHP versions earlier than 5.6 are not properly configured to use the system's
|
||||
CA bundle by default. In order to verify peer certificates, you will need to
|
||||
supply the path on disk to a certificate bundle to the 'verify' request
|
||||
option: http://docs.guzzlephp.org/en/latest/clients.html#verify. If you do not
|
||||
need a specific certificate bundle, then Mozilla provides a commonly used CA
|
||||
bundle which can be downloaded here (provided by the maintainer of cURL):
|
||||
https://raw.githubusercontent.com/bagder/ca-bundle/master/ca-bundle.crt. Once
|
||||
you have a CA bundle available on disk, you can set the 'openssl.cafile' PHP
|
||||
ini setting to point to the path to the file, allowing you to omit the 'verify'
|
||||
request option. See http://curl.haxx.se/docs/sslcerts.html for more
|
||||
information.
|
||||
EOT
|
||||
);
|
||||
}
|
||||
/**
|
||||
* Creates an associative array of lowercase header names to the actual
|
||||
* header casing.
|
||||
*
|
||||
* @deprecated normalize_header_keys will be removed in guzzlehttp/guzzle:8.0. Use Utils::normalizeHeaderKeys instead.
|
||||
* @param array $headers
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function normalize_header_keys(array $headers) : array
|
||||
function normalize_header_keys(array $headers)
|
||||
{
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Utils::normalizeHeaderKeys($headers);
|
||||
$result = [];
|
||||
foreach (\array_keys($headers) as $key) {
|
||||
$result[\strtolower($key)] = $key;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
/**
|
||||
* Returns true if the provided host matches any of the no proxy areas.
|
||||
@@ -109,50 +217,78 @@ function normalize_header_keys(array $headers) : array
|
||||
* 3. The area starts with "." and the area is the last part of the host. e.g.
|
||||
* '.mit.edu' will match any host that ends with '.mit.edu'.
|
||||
*
|
||||
* @param string $host Host to check against the patterns.
|
||||
* @param string[] $noProxyArray An array of host patterns.
|
||||
* @param string $host Host to check against the patterns.
|
||||
* @param array $noProxyArray An array of host patterns.
|
||||
*
|
||||
* @throws Exception\InvalidArgumentException
|
||||
*
|
||||
* @deprecated is_host_in_noproxy will be removed in guzzlehttp/guzzle:8.0. Use Utils::isHostInNoProxy instead.
|
||||
* @return bool
|
||||
*/
|
||||
function is_host_in_noproxy(string $host, array $noProxyArray) : bool
|
||||
function is_host_in_noproxy($host, array $noProxyArray)
|
||||
{
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Utils::isHostInNoProxy($host, $noProxyArray);
|
||||
if (\strlen($host) === 0) {
|
||||
throw new \InvalidArgumentException('Empty host provided');
|
||||
}
|
||||
// Strip port if present.
|
||||
if (\strpos($host, ':')) {
|
||||
$host = \explode($host, ':', 2)[0];
|
||||
}
|
||||
foreach ($noProxyArray as $area) {
|
||||
// Always match on wildcards.
|
||||
if ($area === '*') {
|
||||
return \true;
|
||||
} elseif (empty($area)) {
|
||||
// Don't match on empty values.
|
||||
continue;
|
||||
} elseif ($area === $host) {
|
||||
// Exact matches.
|
||||
return \true;
|
||||
} else {
|
||||
// Special match if the area when prefixed with ".". Remove any
|
||||
// existing leading "." and add a new leading ".".
|
||||
$area = '.' . \ltrim($area, '.');
|
||||
if (\substr($host, -\strlen($area)) === $area) {
|
||||
return \true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return \false;
|
||||
}
|
||||
/**
|
||||
* Wrapper for json_decode that throws when an error occurs.
|
||||
*
|
||||
* @param string $json JSON data to parse
|
||||
* @param bool $assoc When true, returned objects will be converted
|
||||
* @param bool $assoc When true, returned objects will be converted
|
||||
* into associative arrays.
|
||||
* @param int $depth User specified recursion depth.
|
||||
* @param int $options Bitmask of JSON decode options.
|
||||
*
|
||||
* @return object|array|string|int|float|bool|null
|
||||
*
|
||||
* @return mixed
|
||||
* @throws Exception\InvalidArgumentException if the JSON cannot be decoded.
|
||||
*
|
||||
* @see https://www.php.net/manual/en/function.json-decode.php
|
||||
* @deprecated json_decode will be removed in guzzlehttp/guzzle:8.0. Use Utils::jsonDecode instead.
|
||||
* @link http://www.php.net/manual/en/function.json-decode.php
|
||||
*/
|
||||
function json_decode(string $json, bool $assoc = \false, int $depth = 512, int $options = 0)
|
||||
function json_decode($json, $assoc = \false, $depth = 512, $options = 0)
|
||||
{
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Utils::jsonDecode($json, $assoc, $depth, $options);
|
||||
$data = \json_decode($json, $assoc, $depth, $options);
|
||||
if (\JSON_ERROR_NONE !== \json_last_error()) {
|
||||
throw new \YoastSEO_Vendor\GuzzleHttp\Exception\InvalidArgumentException('json_decode error: ' . \json_last_error_msg());
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
/**
|
||||
* Wrapper for JSON encoding that throws when an error occurs.
|
||||
*
|
||||
* @param mixed $value The value being encoded
|
||||
* @param int $options JSON encode option bitmask
|
||||
* @param int $depth Set the maximum depth. Must be greater than zero.
|
||||
* @param int $options JSON encode option bitmask
|
||||
* @param int $depth Set the maximum depth. Must be greater than zero.
|
||||
*
|
||||
* @return string
|
||||
* @throws Exception\InvalidArgumentException if the JSON cannot be encoded.
|
||||
*
|
||||
* @see https://www.php.net/manual/en/function.json-encode.php
|
||||
* @deprecated json_encode will be removed in guzzlehttp/guzzle:8.0. Use Utils::jsonEncode instead.
|
||||
* @link http://www.php.net/manual/en/function.json-encode.php
|
||||
*/
|
||||
function json_encode($value, int $options = 0, int $depth = 512) : string
|
||||
function json_encode($value, $options = 0, $depth = 512)
|
||||
{
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Utils::jsonEncode($value, $options, $depth);
|
||||
$json = \json_encode($value, $options, $depth);
|
||||
if (\JSON_ERROR_NONE !== \json_last_error()) {
|
||||
throw new \YoastSEO_Vendor\GuzzleHttp\Exception\InvalidArgumentException('json_encode error: ' . \json_last_error_msg());
|
||||
}
|
||||
return $json;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
namespace YoastSEO_Vendor;
|
||||
|
||||
// Don't redefine the functions if included multiple times.
|
||||
if (!\function_exists('YoastSEO_Vendor\\GuzzleHttp\\describe_type')) {
|
||||
if (!\function_exists('YoastSEO_Vendor\\GuzzleHttp\\uri_template')) {
|
||||
require __DIR__ . '/functions.php';
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare (strict_types=1);
|
||||
namespace YoastSEO_Vendor\GuzzleHttp\Promise;
|
||||
|
||||
/**
|
||||
@@ -8,7 +7,7 @@ namespace YoastSEO_Vendor\GuzzleHttp\Promise;
|
||||
*/
|
||||
class AggregateException extends \YoastSEO_Vendor\GuzzleHttp\Promise\RejectionException
|
||||
{
|
||||
public function __construct(string $msg, array $reasons)
|
||||
public function __construct($msg, array $reasons)
|
||||
{
|
||||
parent::__construct($reasons, \sprintf('%s; %d rejected promises', $msg, \count($reasons)));
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare (strict_types=1);
|
||||
namespace YoastSEO_Vendor\GuzzleHttp\Promise;
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare (strict_types=1);
|
||||
namespace YoastSEO_Vendor\GuzzleHttp\Promise;
|
||||
|
||||
use Exception;
|
||||
use Generator;
|
||||
use Throwable;
|
||||
/**
|
||||
@@ -26,7 +26,7 @@ use Throwable;
|
||||
* $value = (yield createPromise('a'));
|
||||
* try {
|
||||
* $value = (yield createPromise($value . 'b'));
|
||||
* } catch (\Throwable $e) {
|
||||
* } catch (\Exception $e) {
|
||||
* // The promise was rejected.
|
||||
* }
|
||||
* yield $value . 'c';
|
||||
@@ -39,7 +39,7 @@ use Throwable;
|
||||
*
|
||||
* @return Promise
|
||||
*
|
||||
* @see https://github.com/petkaantonov/bluebird/blob/master/API.md#generators inspiration
|
||||
* @link https://github.com/petkaantonov/bluebird/blob/master/API.md#generators inspiration
|
||||
*/
|
||||
final class Coroutine implements \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
|
||||
{
|
||||
@@ -58,61 +58,65 @@ final class Coroutine implements \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInte
|
||||
public function __construct(callable $generatorFn)
|
||||
{
|
||||
$this->generator = $generatorFn();
|
||||
$this->result = new \YoastSEO_Vendor\GuzzleHttp\Promise\Promise(function () : void {
|
||||
$this->result = new \YoastSEO_Vendor\GuzzleHttp\Promise\Promise(function () {
|
||||
while (isset($this->currentPromise)) {
|
||||
$this->currentPromise->wait();
|
||||
}
|
||||
});
|
||||
try {
|
||||
$this->nextCoroutine($this->generator->current());
|
||||
} catch (\Exception $exception) {
|
||||
$this->result->reject($exception);
|
||||
} catch (\Throwable $throwable) {
|
||||
$this->result->reject($throwable);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Create a new coroutine.
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public static function of(callable $generatorFn) : self
|
||||
public static function of(callable $generatorFn)
|
||||
{
|
||||
return new self($generatorFn);
|
||||
}
|
||||
public function then(callable $onFulfilled = null, callable $onRejected = null) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
|
||||
public function then(callable $onFulfilled = null, callable $onRejected = null)
|
||||
{
|
||||
return $this->result->then($onFulfilled, $onRejected);
|
||||
}
|
||||
public function otherwise(callable $onRejected) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
|
||||
public function otherwise(callable $onRejected)
|
||||
{
|
||||
return $this->result->otherwise($onRejected);
|
||||
}
|
||||
public function wait(bool $unwrap = \true)
|
||||
public function wait($unwrap = \true)
|
||||
{
|
||||
return $this->result->wait($unwrap);
|
||||
}
|
||||
public function getState() : string
|
||||
public function getState()
|
||||
{
|
||||
return $this->result->getState();
|
||||
}
|
||||
public function resolve($value) : void
|
||||
public function resolve($value)
|
||||
{
|
||||
$this->result->resolve($value);
|
||||
}
|
||||
public function reject($reason) : void
|
||||
public function reject($reason)
|
||||
{
|
||||
$this->result->reject($reason);
|
||||
}
|
||||
public function cancel() : void
|
||||
public function cancel()
|
||||
{
|
||||
$this->currentPromise->cancel();
|
||||
$this->result->cancel();
|
||||
}
|
||||
private function nextCoroutine($yielded) : void
|
||||
private function nextCoroutine($yielded)
|
||||
{
|
||||
$this->currentPromise = \YoastSEO_Vendor\GuzzleHttp\Promise\Create::promiseFor($yielded)->then([$this, '_handleSuccess'], [$this, '_handleFailure']);
|
||||
}
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public function _handleSuccess($value) : void
|
||||
public function _handleSuccess($value)
|
||||
{
|
||||
unset($this->currentPromise);
|
||||
try {
|
||||
@@ -122,6 +126,8 @@ final class Coroutine implements \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInte
|
||||
} else {
|
||||
$this->result->resolve($value);
|
||||
}
|
||||
} catch (\Exception $exception) {
|
||||
$this->result->reject($exception);
|
||||
} catch (\Throwable $throwable) {
|
||||
$this->result->reject($throwable);
|
||||
}
|
||||
@@ -129,13 +135,15 @@ final class Coroutine implements \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInte
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public function _handleFailure($reason) : void
|
||||
public function _handleFailure($reason)
|
||||
{
|
||||
unset($this->currentPromise);
|
||||
try {
|
||||
$nextYield = $this->generator->throw(\YoastSEO_Vendor\GuzzleHttp\Promise\Create::exceptionFor($reason));
|
||||
// The throw was caught, so keep iterating on the coroutine
|
||||
$this->nextCoroutine($nextYield);
|
||||
} catch (\Exception $exception) {
|
||||
$this->result->reject($exception);
|
||||
} catch (\Throwable $throwable) {
|
||||
$this->result->reject($throwable);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare (strict_types=1);
|
||||
namespace YoastSEO_Vendor\GuzzleHttp\Promise;
|
||||
|
||||
final class Create
|
||||
@@ -9,8 +8,10 @@ final class Create
|
||||
* Creates a promise for a value if the value is not a promise.
|
||||
*
|
||||
* @param mixed $value Promise or value.
|
||||
*
|
||||
* @return PromiseInterface
|
||||
*/
|
||||
public static function promiseFor($value) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
|
||||
public static function promiseFor($value)
|
||||
{
|
||||
if ($value instanceof \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface) {
|
||||
return $value;
|
||||
@@ -30,8 +31,10 @@ final class Create
|
||||
* If the provided reason is a promise, then it is returned as-is.
|
||||
*
|
||||
* @param mixed $reason Promise or reason.
|
||||
*
|
||||
* @return PromiseInterface
|
||||
*/
|
||||
public static function rejectionFor($reason) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
|
||||
public static function rejectionFor($reason)
|
||||
{
|
||||
if ($reason instanceof \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface) {
|
||||
return $reason;
|
||||
@@ -42,10 +45,12 @@ final class Create
|
||||
* Create an exception for a rejected promise value.
|
||||
*
|
||||
* @param mixed $reason
|
||||
*
|
||||
* @return \Exception|\Throwable
|
||||
*/
|
||||
public static function exceptionFor($reason) : \Throwable
|
||||
public static function exceptionFor($reason)
|
||||
{
|
||||
if ($reason instanceof \Throwable) {
|
||||
if ($reason instanceof \Exception || $reason instanceof \Throwable) {
|
||||
return $reason;
|
||||
}
|
||||
return new \YoastSEO_Vendor\GuzzleHttp\Promise\RejectionException($reason);
|
||||
@@ -54,8 +59,10 @@ final class Create
|
||||
* Returns an iterator for the given value.
|
||||
*
|
||||
* @param mixed $value
|
||||
*
|
||||
* @return \Iterator
|
||||
*/
|
||||
public static function iterFor($value) : \Iterator
|
||||
public static function iterFor($value)
|
||||
{
|
||||
if ($value instanceof \Iterator) {
|
||||
return $value;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare (strict_types=1);
|
||||
namespace YoastSEO_Vendor\GuzzleHttp\Promise;
|
||||
|
||||
final class Each
|
||||
@@ -21,8 +20,10 @@ final class Each
|
||||
* @param mixed $iterable Iterator or array to iterate over.
|
||||
* @param callable $onFulfilled
|
||||
* @param callable $onRejected
|
||||
*
|
||||
* @return PromiseInterface
|
||||
*/
|
||||
public static function of($iterable, callable $onFulfilled = null, callable $onRejected = null) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
|
||||
public static function of($iterable, callable $onFulfilled = null, callable $onRejected = null)
|
||||
{
|
||||
return (new \YoastSEO_Vendor\GuzzleHttp\Promise\EachPromise($iterable, ['fulfilled' => $onFulfilled, 'rejected' => $onRejected]))->promise();
|
||||
}
|
||||
@@ -38,8 +39,10 @@ final class Each
|
||||
* @param int|callable $concurrency
|
||||
* @param callable $onFulfilled
|
||||
* @param callable $onRejected
|
||||
*
|
||||
* @return PromiseInterface
|
||||
*/
|
||||
public static function ofLimit($iterable, $concurrency, callable $onFulfilled = null, callable $onRejected = null) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
|
||||
public static function ofLimit($iterable, $concurrency, callable $onFulfilled = null, callable $onRejected = null)
|
||||
{
|
||||
return (new \YoastSEO_Vendor\GuzzleHttp\Promise\EachPromise($iterable, ['fulfilled' => $onFulfilled, 'rejected' => $onRejected, 'concurrency' => $concurrency]))->promise();
|
||||
}
|
||||
@@ -51,10 +54,12 @@ final class Each
|
||||
* @param mixed $iterable
|
||||
* @param int|callable $concurrency
|
||||
* @param callable $onFulfilled
|
||||
*
|
||||
* @return PromiseInterface
|
||||
*/
|
||||
public static function ofLimitAll($iterable, $concurrency, callable $onFulfilled = null) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
|
||||
public static function ofLimitAll($iterable, $concurrency, callable $onFulfilled = null)
|
||||
{
|
||||
return self::ofLimit($iterable, $concurrency, $onFulfilled, function ($reason, $idx, \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface $aggregate) : void {
|
||||
return each_limit($iterable, $concurrency, $onFulfilled, function ($reason, $idx, \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface $aggregate) {
|
||||
$aggregate->reject($reason);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
<?php
|
||||
|
||||
declare (strict_types=1);
|
||||
namespace YoastSEO_Vendor\GuzzleHttp\Promise;
|
||||
|
||||
/**
|
||||
* Represents a promise that iterates over many promises and invokes
|
||||
* side-effect functions in the process.
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class EachPromise implements \YoastSEO_Vendor\GuzzleHttp\Promise\PromisorInterface
|
||||
{
|
||||
@@ -60,7 +57,7 @@ class EachPromise implements \YoastSEO_Vendor\GuzzleHttp\Promise\PromisorInterfa
|
||||
}
|
||||
}
|
||||
/** @psalm-suppress InvalidNullableReturnType */
|
||||
public function promise() : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
|
||||
public function promise()
|
||||
{
|
||||
if ($this->aggregate) {
|
||||
return $this->aggregate;
|
||||
@@ -71,17 +68,28 @@ class EachPromise implements \YoastSEO_Vendor\GuzzleHttp\Promise\PromisorInterfa
|
||||
$this->iterable->rewind();
|
||||
$this->refillPending();
|
||||
} catch (\Throwable $e) {
|
||||
/**
|
||||
* @psalm-suppress NullReference
|
||||
* @phpstan-ignore-next-line
|
||||
*/
|
||||
$this->aggregate->reject($e);
|
||||
} catch (\Exception $e) {
|
||||
/**
|
||||
* @psalm-suppress NullReference
|
||||
* @phpstan-ignore-next-line
|
||||
*/
|
||||
$this->aggregate->reject($e);
|
||||
}
|
||||
/**
|
||||
* @psalm-suppress NullableReturnStatement
|
||||
* @phpstan-ignore-next-line
|
||||
*/
|
||||
return $this->aggregate;
|
||||
}
|
||||
private function createPromise() : void
|
||||
private function createPromise()
|
||||
{
|
||||
$this->mutex = \false;
|
||||
$this->aggregate = new \YoastSEO_Vendor\GuzzleHttp\Promise\Promise(function () : void {
|
||||
$this->aggregate = new \YoastSEO_Vendor\GuzzleHttp\Promise\Promise(function () {
|
||||
if ($this->checkIfFinished()) {
|
||||
return;
|
||||
}
|
||||
@@ -97,14 +105,14 @@ class EachPromise implements \YoastSEO_Vendor\GuzzleHttp\Promise\PromisorInterfa
|
||||
}
|
||||
});
|
||||
// Clear the references when the promise is resolved.
|
||||
$clearFn = function () : void {
|
||||
$clearFn = function () {
|
||||
$this->iterable = $this->concurrency = $this->pending = null;
|
||||
$this->onFulfilled = $this->onRejected = null;
|
||||
$this->nextPendingIndex = 0;
|
||||
};
|
||||
$this->aggregate->then($clearFn, $clearFn);
|
||||
}
|
||||
private function refillPending() : void
|
||||
private function refillPending()
|
||||
{
|
||||
if (!$this->concurrency) {
|
||||
// Add all pending promises.
|
||||
@@ -128,7 +136,7 @@ class EachPromise implements \YoastSEO_Vendor\GuzzleHttp\Promise\PromisorInterfa
|
||||
while (--$concurrency && $this->advanceIterator() && $this->addPending()) {
|
||||
}
|
||||
}
|
||||
private function addPending() : bool
|
||||
private function addPending()
|
||||
{
|
||||
if (!$this->iterable || !$this->iterable->valid()) {
|
||||
return \false;
|
||||
@@ -138,12 +146,12 @@ class EachPromise implements \YoastSEO_Vendor\GuzzleHttp\Promise\PromisorInterfa
|
||||
// Iterable keys may not be unique, so we use a counter to
|
||||
// guarantee uniqueness
|
||||
$idx = $this->nextPendingIndex++;
|
||||
$this->pending[$idx] = $promise->then(function ($value) use($idx, $key) : void {
|
||||
$this->pending[$idx] = $promise->then(function ($value) use($idx, $key) {
|
||||
if ($this->onFulfilled) {
|
||||
\call_user_func($this->onFulfilled, $value, $key, $this->aggregate);
|
||||
}
|
||||
$this->step($idx);
|
||||
}, function ($reason) use($idx, $key) : void {
|
||||
}, function ($reason) use($idx, $key) {
|
||||
if ($this->onRejected) {
|
||||
\call_user_func($this->onRejected, $reason, $key, $this->aggregate);
|
||||
}
|
||||
@@ -151,7 +159,7 @@ class EachPromise implements \YoastSEO_Vendor\GuzzleHttp\Promise\PromisorInterfa
|
||||
});
|
||||
return \true;
|
||||
}
|
||||
private function advanceIterator() : bool
|
||||
private function advanceIterator()
|
||||
{
|
||||
// Place a lock on the iterator so that we ensure to not recurse,
|
||||
// preventing fatal generator errors.
|
||||
@@ -167,9 +175,13 @@ class EachPromise implements \YoastSEO_Vendor\GuzzleHttp\Promise\PromisorInterfa
|
||||
$this->aggregate->reject($e);
|
||||
$this->mutex = \false;
|
||||
return \false;
|
||||
} catch (\Exception $e) {
|
||||
$this->aggregate->reject($e);
|
||||
$this->mutex = \false;
|
||||
return \false;
|
||||
}
|
||||
}
|
||||
private function step(int $idx) : void
|
||||
private function step($idx)
|
||||
{
|
||||
// If the promise was already resolved, then ignore this step.
|
||||
if (\YoastSEO_Vendor\GuzzleHttp\Promise\Is::settled($this->aggregate)) {
|
||||
@@ -184,7 +196,7 @@ class EachPromise implements \YoastSEO_Vendor\GuzzleHttp\Promise\PromisorInterfa
|
||||
$this->refillPending();
|
||||
}
|
||||
}
|
||||
private function checkIfFinished() : bool
|
||||
private function checkIfFinished()
|
||||
{
|
||||
if (!$this->pending && !$this->iterable->valid()) {
|
||||
// Resolve the promise if there's nothing left to do.
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare (strict_types=1);
|
||||
namespace YoastSEO_Vendor\GuzzleHttp\Promise;
|
||||
|
||||
/**
|
||||
@@ -8,15 +7,10 @@ namespace YoastSEO_Vendor\GuzzleHttp\Promise;
|
||||
*
|
||||
* Thenning off of this promise will invoke the onFulfilled callback
|
||||
* immediately and ignore other callbacks.
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class FulfilledPromise implements \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
|
||||
{
|
||||
private $value;
|
||||
/**
|
||||
* @param mixed $value
|
||||
*/
|
||||
public function __construct($value)
|
||||
{
|
||||
if (\is_object($value) && \method_exists($value, 'then')) {
|
||||
@@ -24,7 +18,7 @@ class FulfilledPromise implements \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInt
|
||||
}
|
||||
$this->value = $value;
|
||||
}
|
||||
public function then(callable $onFulfilled = null, callable $onRejected = null) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
|
||||
public function then(callable $onFulfilled = null, callable $onRejected = null)
|
||||
{
|
||||
// Return itself if there is no onFulfilled function.
|
||||
if (!$onFulfilled) {
|
||||
@@ -33,40 +27,42 @@ class FulfilledPromise implements \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInt
|
||||
$queue = \YoastSEO_Vendor\GuzzleHttp\Promise\Utils::queue();
|
||||
$p = new \YoastSEO_Vendor\GuzzleHttp\Promise\Promise([$queue, 'run']);
|
||||
$value = $this->value;
|
||||
$queue->add(static function () use($p, $value, $onFulfilled) : void {
|
||||
$queue->add(static function () use($p, $value, $onFulfilled) {
|
||||
if (\YoastSEO_Vendor\GuzzleHttp\Promise\Is::pending($p)) {
|
||||
try {
|
||||
$p->resolve($onFulfilled($value));
|
||||
} catch (\Throwable $e) {
|
||||
$p->reject($e);
|
||||
} catch (\Exception $e) {
|
||||
$p->reject($e);
|
||||
}
|
||||
}
|
||||
});
|
||||
return $p;
|
||||
}
|
||||
public function otherwise(callable $onRejected) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
|
||||
public function otherwise(callable $onRejected)
|
||||
{
|
||||
return $this->then(null, $onRejected);
|
||||
}
|
||||
public function wait(bool $unwrap = \true)
|
||||
public function wait($unwrap = \true, $defaultDelivery = null)
|
||||
{
|
||||
return $unwrap ? $this->value : null;
|
||||
}
|
||||
public function getState() : string
|
||||
public function getState()
|
||||
{
|
||||
return self::FULFILLED;
|
||||
}
|
||||
public function resolve($value) : void
|
||||
public function resolve($value)
|
||||
{
|
||||
if ($value !== $this->value) {
|
||||
throw new \LogicException('Cannot resolve a fulfilled promise');
|
||||
throw new \LogicException("Cannot resolve a fulfilled promise");
|
||||
}
|
||||
}
|
||||
public function reject($reason) : void
|
||||
public function reject($reason)
|
||||
{
|
||||
throw new \LogicException('Cannot reject a fulfilled promise');
|
||||
throw new \LogicException("Cannot reject a fulfilled promise");
|
||||
}
|
||||
public function cancel() : void
|
||||
public function cancel()
|
||||
{
|
||||
// pass
|
||||
}
|
||||
|
||||
@@ -1,35 +1,42 @@
|
||||
<?php
|
||||
|
||||
declare (strict_types=1);
|
||||
namespace YoastSEO_Vendor\GuzzleHttp\Promise;
|
||||
|
||||
final class Is
|
||||
{
|
||||
/**
|
||||
* Returns true if a promise is pending.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function pending(\YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface $promise) : bool
|
||||
public static function pending(\YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface $promise)
|
||||
{
|
||||
return $promise->getState() === \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface::PENDING;
|
||||
}
|
||||
/**
|
||||
* Returns true if a promise is fulfilled or rejected.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function settled(\YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface $promise) : bool
|
||||
public static function settled(\YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface $promise)
|
||||
{
|
||||
return $promise->getState() !== \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface::PENDING;
|
||||
}
|
||||
/**
|
||||
* Returns true if a promise is fulfilled.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function fulfilled(\YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface $promise) : bool
|
||||
public static function fulfilled(\YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface $promise)
|
||||
{
|
||||
return $promise->getState() === \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface::FULFILLED;
|
||||
}
|
||||
/**
|
||||
* Returns true if a promise is rejected.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function rejected(\YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface $promise) : bool
|
||||
public static function rejected(\YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface $promise)
|
||||
{
|
||||
return $promise->getState() === \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface::REJECTED;
|
||||
}
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
<?php
|
||||
|
||||
declare (strict_types=1);
|
||||
namespace YoastSEO_Vendor\GuzzleHttp\Promise;
|
||||
|
||||
/**
|
||||
* Promises/A+ implementation that avoids recursion when possible.
|
||||
*
|
||||
* @see https://promisesaplus.com/
|
||||
*
|
||||
* @final
|
||||
* @link https://promisesaplus.com/
|
||||
*/
|
||||
class Promise implements \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
|
||||
{
|
||||
@@ -27,7 +24,7 @@ class Promise implements \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
|
||||
$this->waitFn = $waitFn;
|
||||
$this->cancelFn = $cancelFn;
|
||||
}
|
||||
public function then(callable $onFulfilled = null, callable $onRejected = null) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
|
||||
public function then(callable $onFulfilled = null, callable $onRejected = null)
|
||||
{
|
||||
if ($this->state === self::PENDING) {
|
||||
$p = new \YoastSEO_Vendor\GuzzleHttp\Promise\Promise(null, [$this, 'cancel']);
|
||||
@@ -46,11 +43,11 @@ class Promise implements \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
|
||||
$rejection = \YoastSEO_Vendor\GuzzleHttp\Promise\Create::rejectionFor($this->result);
|
||||
return $onRejected ? $rejection->then(null, $onRejected) : $rejection;
|
||||
}
|
||||
public function otherwise(callable $onRejected) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
|
||||
public function otherwise(callable $onRejected)
|
||||
{
|
||||
return $this->then(null, $onRejected);
|
||||
}
|
||||
public function wait(bool $unwrap = \true)
|
||||
public function wait($unwrap = \true)
|
||||
{
|
||||
$this->waitIfPending();
|
||||
if ($this->result instanceof \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface) {
|
||||
@@ -64,11 +61,11 @@ class Promise implements \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
|
||||
throw \YoastSEO_Vendor\GuzzleHttp\Promise\Create::exceptionFor($this->result);
|
||||
}
|
||||
}
|
||||
public function getState() : string
|
||||
public function getState()
|
||||
{
|
||||
return $this->state;
|
||||
}
|
||||
public function cancel() : void
|
||||
public function cancel()
|
||||
{
|
||||
if ($this->state !== self::PENDING) {
|
||||
return;
|
||||
@@ -81,6 +78,8 @@ class Promise implements \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
|
||||
$fn();
|
||||
} catch (\Throwable $e) {
|
||||
$this->reject($e);
|
||||
} catch (\Exception $e) {
|
||||
$this->reject($e);
|
||||
}
|
||||
}
|
||||
// Reject the promise only if it wasn't rejected in a then callback.
|
||||
@@ -89,15 +88,15 @@ class Promise implements \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
|
||||
$this->reject(new \YoastSEO_Vendor\GuzzleHttp\Promise\CancellationException('Promise has been cancelled'));
|
||||
}
|
||||
}
|
||||
public function resolve($value) : void
|
||||
public function resolve($value)
|
||||
{
|
||||
$this->settle(self::FULFILLED, $value);
|
||||
}
|
||||
public function reject($reason) : void
|
||||
public function reject($reason)
|
||||
{
|
||||
$this->settle(self::REJECTED, $reason);
|
||||
}
|
||||
private function settle(string $state, $value) : void
|
||||
private function settle($state, $value)
|
||||
{
|
||||
if ($this->state !== self::PENDING) {
|
||||
// Ignore calls with the same resolution.
|
||||
@@ -124,7 +123,7 @@ class Promise implements \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
|
||||
if (!\is_object($value) || !\method_exists($value, 'then')) {
|
||||
$id = $state === self::FULFILLED ? 1 : 2;
|
||||
// It's a success, so resolve the handlers in the queue.
|
||||
\YoastSEO_Vendor\GuzzleHttp\Promise\Utils::queue()->add(static function () use($id, $value, $handlers) : void {
|
||||
\YoastSEO_Vendor\GuzzleHttp\Promise\Utils::queue()->add(static function () use($id, $value, $handlers) {
|
||||
foreach ($handlers as $handler) {
|
||||
self::callHandler($id, $value, $handler);
|
||||
}
|
||||
@@ -134,11 +133,11 @@ class Promise implements \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
|
||||
$value->handlers = \array_merge($value->handlers, $handlers);
|
||||
} else {
|
||||
// Resolve the handlers when the forwarded promise is resolved.
|
||||
$value->then(static function ($value) use($handlers) : void {
|
||||
$value->then(static function ($value) use($handlers) {
|
||||
foreach ($handlers as $handler) {
|
||||
self::callHandler(1, $value, $handler);
|
||||
}
|
||||
}, static function ($reason) use($handlers) : void {
|
||||
}, static function ($reason) use($handlers) {
|
||||
foreach ($handlers as $handler) {
|
||||
self::callHandler(2, $reason, $handler);
|
||||
}
|
||||
@@ -152,7 +151,7 @@ class Promise implements \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
|
||||
* @param mixed $value Value to pass to the callback.
|
||||
* @param array $handler Array of handler data (promise and callbacks).
|
||||
*/
|
||||
private static function callHandler(int $index, $value, array $handler) : void
|
||||
private static function callHandler($index, $value, array $handler)
|
||||
{
|
||||
/** @var PromiseInterface $promise */
|
||||
$promise = $handler[0];
|
||||
@@ -181,9 +180,11 @@ class Promise implements \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
|
||||
}
|
||||
} catch (\Throwable $reason) {
|
||||
$promise->reject($reason);
|
||||
} catch (\Exception $reason) {
|
||||
$promise->reject($reason);
|
||||
}
|
||||
}
|
||||
private function waitIfPending() : void
|
||||
private function waitIfPending()
|
||||
{
|
||||
if ($this->state !== self::PENDING) {
|
||||
return;
|
||||
@@ -201,13 +202,13 @@ class Promise implements \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
|
||||
$this->reject('Invoking the wait callback did not resolve the promise');
|
||||
}
|
||||
}
|
||||
private function invokeWaitFn() : void
|
||||
private function invokeWaitFn()
|
||||
{
|
||||
try {
|
||||
$wfn = $this->waitFn;
|
||||
$this->waitFn = null;
|
||||
$wfn(\true);
|
||||
} catch (\Throwable $reason) {
|
||||
} catch (\Exception $reason) {
|
||||
if ($this->state === self::PENDING) {
|
||||
// The promise has not been resolved yet, so reject the promise
|
||||
// with the exception.
|
||||
@@ -219,7 +220,7 @@ class Promise implements \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
|
||||
}
|
||||
}
|
||||
}
|
||||
private function invokeWaitList() : void
|
||||
private function invokeWaitList()
|
||||
{
|
||||
$waitList = $this->waitList;
|
||||
$this->waitList = null;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare (strict_types=1);
|
||||
namespace YoastSEO_Vendor\GuzzleHttp\Promise;
|
||||
|
||||
/**
|
||||
@@ -10,21 +9,23 @@ namespace YoastSEO_Vendor\GuzzleHttp\Promise;
|
||||
* which registers callbacks to receive either a promise’s eventual value or
|
||||
* the reason why the promise cannot be fulfilled.
|
||||
*
|
||||
* @see https://promisesaplus.com/
|
||||
* @link https://promisesaplus.com/
|
||||
*/
|
||||
interface PromiseInterface
|
||||
{
|
||||
public const PENDING = 'pending';
|
||||
public const FULFILLED = 'fulfilled';
|
||||
public const REJECTED = 'rejected';
|
||||
const PENDING = 'pending';
|
||||
const FULFILLED = 'fulfilled';
|
||||
const REJECTED = 'rejected';
|
||||
/**
|
||||
* Appends fulfillment and rejection handlers to the promise, and returns
|
||||
* a new promise resolving to the return value of the called handler.
|
||||
*
|
||||
* @param callable $onFulfilled Invoked when the promise fulfills.
|
||||
* @param callable $onRejected Invoked when the promise is rejected.
|
||||
*
|
||||
* @return PromiseInterface
|
||||
*/
|
||||
public function then(callable $onFulfilled = null, callable $onRejected = null) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface;
|
||||
public function then(callable $onFulfilled = null, callable $onRejected = null);
|
||||
/**
|
||||
* Appends a rejection handler callback to the promise, and returns a new
|
||||
* promise resolving to the return value of the callback if it is called,
|
||||
@@ -32,15 +33,19 @@ interface PromiseInterface
|
||||
* fulfilled.
|
||||
*
|
||||
* @param callable $onRejected Invoked when the promise is rejected.
|
||||
*
|
||||
* @return PromiseInterface
|
||||
*/
|
||||
public function otherwise(callable $onRejected) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface;
|
||||
public function otherwise(callable $onRejected);
|
||||
/**
|
||||
* Get the state of the promise ("pending", "rejected", or "fulfilled").
|
||||
*
|
||||
* The three states can be checked against the constants defined on
|
||||
* PromiseInterface: PENDING, FULFILLED, and REJECTED.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getState() : string;
|
||||
public function getState();
|
||||
/**
|
||||
* Resolve the promise with the given value.
|
||||
*
|
||||
@@ -48,7 +53,7 @@ interface PromiseInterface
|
||||
*
|
||||
* @throws \RuntimeException if the promise is already resolved.
|
||||
*/
|
||||
public function resolve($value) : void;
|
||||
public function resolve($value);
|
||||
/**
|
||||
* Reject the promise with the given reason.
|
||||
*
|
||||
@@ -56,13 +61,13 @@ interface PromiseInterface
|
||||
*
|
||||
* @throws \RuntimeException if the promise is already resolved.
|
||||
*/
|
||||
public function reject($reason) : void;
|
||||
public function reject($reason);
|
||||
/**
|
||||
* Cancels the promise if possible.
|
||||
*
|
||||
* @see https://github.com/promises-aplus/cancellation-spec/issues/7
|
||||
* @link https://github.com/promises-aplus/cancellation-spec/issues/7
|
||||
*/
|
||||
public function cancel() : void;
|
||||
public function cancel();
|
||||
/**
|
||||
* Waits until the promise completes if possible.
|
||||
*
|
||||
@@ -71,10 +76,12 @@ interface PromiseInterface
|
||||
*
|
||||
* If the promise cannot be waited on, then the promise will be rejected.
|
||||
*
|
||||
* @param bool $unwrap
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \LogicException if the promise has no wait function or if the
|
||||
* promise does not settle after waiting.
|
||||
*/
|
||||
public function wait(bool $unwrap = \true);
|
||||
public function wait($unwrap = \true);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare (strict_types=1);
|
||||
namespace YoastSEO_Vendor\GuzzleHttp\Promise;
|
||||
|
||||
/**
|
||||
@@ -10,6 +9,8 @@ interface PromisorInterface
|
||||
{
|
||||
/**
|
||||
* Returns a promise.
|
||||
*
|
||||
* @return PromiseInterface
|
||||
*/
|
||||
public function promise() : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface;
|
||||
public function promise();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare (strict_types=1);
|
||||
namespace YoastSEO_Vendor\GuzzleHttp\Promise;
|
||||
|
||||
/**
|
||||
@@ -8,15 +7,10 @@ namespace YoastSEO_Vendor\GuzzleHttp\Promise;
|
||||
*
|
||||
* Thenning off of this promise will invoke the onRejected callback
|
||||
* immediately and ignore other callbacks.
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class RejectedPromise implements \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
|
||||
{
|
||||
private $reason;
|
||||
/**
|
||||
* @param mixed $reason
|
||||
*/
|
||||
public function __construct($reason)
|
||||
{
|
||||
if (\is_object($reason) && \method_exists($reason, 'then')) {
|
||||
@@ -24,7 +18,7 @@ class RejectedPromise implements \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInte
|
||||
}
|
||||
$this->reason = $reason;
|
||||
}
|
||||
public function then(callable $onFulfilled = null, callable $onRejected = null) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
|
||||
public function then(callable $onFulfilled = null, callable $onRejected = null)
|
||||
{
|
||||
// If there's no onRejected callback then just return self.
|
||||
if (!$onRejected) {
|
||||
@@ -33,7 +27,7 @@ class RejectedPromise implements \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInte
|
||||
$queue = \YoastSEO_Vendor\GuzzleHttp\Promise\Utils::queue();
|
||||
$reason = $this->reason;
|
||||
$p = new \YoastSEO_Vendor\GuzzleHttp\Promise\Promise([$queue, 'run']);
|
||||
$queue->add(static function () use($p, $reason, $onRejected) : void {
|
||||
$queue->add(static function () use($p, $reason, $onRejected) {
|
||||
if (\YoastSEO_Vendor\GuzzleHttp\Promise\Is::pending($p)) {
|
||||
try {
|
||||
// Return a resolved promise if onRejected does not throw.
|
||||
@@ -41,37 +35,40 @@ class RejectedPromise implements \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInte
|
||||
} catch (\Throwable $e) {
|
||||
// onRejected threw, so return a rejected promise.
|
||||
$p->reject($e);
|
||||
} catch (\Exception $e) {
|
||||
// onRejected threw, so return a rejected promise.
|
||||
$p->reject($e);
|
||||
}
|
||||
}
|
||||
});
|
||||
return $p;
|
||||
}
|
||||
public function otherwise(callable $onRejected) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
|
||||
public function otherwise(callable $onRejected)
|
||||
{
|
||||
return $this->then(null, $onRejected);
|
||||
}
|
||||
public function wait(bool $unwrap = \true)
|
||||
public function wait($unwrap = \true, $defaultDelivery = null)
|
||||
{
|
||||
if ($unwrap) {
|
||||
throw \YoastSEO_Vendor\GuzzleHttp\Promise\Create::exceptionFor($this->reason);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public function getState() : string
|
||||
public function getState()
|
||||
{
|
||||
return self::REJECTED;
|
||||
}
|
||||
public function resolve($value) : void
|
||||
public function resolve($value)
|
||||
{
|
||||
throw new \LogicException('Cannot resolve a rejected promise');
|
||||
throw new \LogicException("Cannot resolve a rejected promise");
|
||||
}
|
||||
public function reject($reason) : void
|
||||
public function reject($reason)
|
||||
{
|
||||
if ($reason !== $this->reason) {
|
||||
throw new \LogicException('Cannot reject a rejected promise');
|
||||
throw new \LogicException("Cannot reject a rejected promise");
|
||||
}
|
||||
}
|
||||
public function cancel() : void
|
||||
public function cancel()
|
||||
{
|
||||
// pass
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare (strict_types=1);
|
||||
namespace YoastSEO_Vendor\GuzzleHttp\Promise;
|
||||
|
||||
/**
|
||||
@@ -13,10 +12,10 @@ class RejectionException extends \RuntimeException
|
||||
/** @var mixed Rejection reason. */
|
||||
private $reason;
|
||||
/**
|
||||
* @param mixed $reason Rejection reason.
|
||||
* @param string|null $description Optional description.
|
||||
* @param mixed $reason Rejection reason.
|
||||
* @param string $description Optional description
|
||||
*/
|
||||
public function __construct($reason, ?string $description = null)
|
||||
public function __construct($reason, $description = null)
|
||||
{
|
||||
$this->reason = $reason;
|
||||
$message = 'The promise was rejected';
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare (strict_types=1);
|
||||
namespace YoastSEO_Vendor\GuzzleHttp\Promise;
|
||||
|
||||
/**
|
||||
@@ -11,17 +10,15 @@ namespace YoastSEO_Vendor\GuzzleHttp\Promise;
|
||||
* by calling the `run()` function of the global task queue in an event loop.
|
||||
*
|
||||
* GuzzleHttp\Promise\Utils::queue()->run();
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class TaskQueue implements \YoastSEO_Vendor\GuzzleHttp\Promise\TaskQueueInterface
|
||||
{
|
||||
private $enableShutdown = \true;
|
||||
private $queue = [];
|
||||
public function __construct(bool $withShutdown = \true)
|
||||
public function __construct($withShutdown = \true)
|
||||
{
|
||||
if ($withShutdown) {
|
||||
\register_shutdown_function(function () : void {
|
||||
\register_shutdown_function(function () {
|
||||
if ($this->enableShutdown) {
|
||||
// Only run the tasks if an E_ERROR didn't occur.
|
||||
$err = \error_get_last();
|
||||
@@ -32,15 +29,15 @@ class TaskQueue implements \YoastSEO_Vendor\GuzzleHttp\Promise\TaskQueueInterfac
|
||||
});
|
||||
}
|
||||
}
|
||||
public function isEmpty() : bool
|
||||
public function isEmpty()
|
||||
{
|
||||
return !$this->queue;
|
||||
}
|
||||
public function add(callable $task) : void
|
||||
public function add(callable $task)
|
||||
{
|
||||
$this->queue[] = $task;
|
||||
}
|
||||
public function run() : void
|
||||
public function run()
|
||||
{
|
||||
while ($task = \array_shift($this->queue)) {
|
||||
/** @var callable $task */
|
||||
@@ -58,7 +55,7 @@ class TaskQueue implements \YoastSEO_Vendor\GuzzleHttp\Promise\TaskQueueInterfac
|
||||
*
|
||||
* Note: This shutdown will occur before any destructors are triggered.
|
||||
*/
|
||||
public function disableShutdown() : void
|
||||
public function disableShutdown()
|
||||
{
|
||||
$this->enableShutdown = \false;
|
||||
}
|
||||
|
||||
@@ -1,21 +1,22 @@
|
||||
<?php
|
||||
|
||||
declare (strict_types=1);
|
||||
namespace YoastSEO_Vendor\GuzzleHttp\Promise;
|
||||
|
||||
interface TaskQueueInterface
|
||||
{
|
||||
/**
|
||||
* Returns true if the queue is empty.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isEmpty() : bool;
|
||||
public function isEmpty();
|
||||
/**
|
||||
* Adds a task to the queue that will be executed the next time run is
|
||||
* called.
|
||||
*/
|
||||
public function add(callable $task) : void;
|
||||
public function add(callable $task);
|
||||
/**
|
||||
* Execute all of the pending task in the queue.
|
||||
*/
|
||||
public function run() : void;
|
||||
public function run();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare (strict_types=1);
|
||||
namespace YoastSEO_Vendor\GuzzleHttp\Promise;
|
||||
|
||||
final class Utils
|
||||
@@ -18,9 +17,11 @@ final class Utils
|
||||
* }
|
||||
* </code>
|
||||
*
|
||||
* @param TaskQueueInterface|null $assign Optionally specify a new queue instance.
|
||||
* @param TaskQueueInterface $assign Optionally specify a new queue instance.
|
||||
*
|
||||
* @return TaskQueueInterface
|
||||
*/
|
||||
public static function queue(\YoastSEO_Vendor\GuzzleHttp\Promise\TaskQueueInterface $assign = null) : \YoastSEO_Vendor\GuzzleHttp\Promise\TaskQueueInterface
|
||||
public static function queue(\YoastSEO_Vendor\GuzzleHttp\Promise\TaskQueueInterface $assign = null)
|
||||
{
|
||||
static $queue;
|
||||
if ($assign) {
|
||||
@@ -35,18 +36,22 @@ final class Utils
|
||||
* returns a promise that is fulfilled or rejected with the result.
|
||||
*
|
||||
* @param callable $task Task function to run.
|
||||
*
|
||||
* @return PromiseInterface
|
||||
*/
|
||||
public static function task(callable $task) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
|
||||
public static function task(callable $task)
|
||||
{
|
||||
$queue = self::queue();
|
||||
$promise = new \YoastSEO_Vendor\GuzzleHttp\Promise\Promise([$queue, 'run']);
|
||||
$queue->add(function () use($task, $promise) : void {
|
||||
$queue->add(function () use($task, $promise) {
|
||||
try {
|
||||
if (\YoastSEO_Vendor\GuzzleHttp\Promise\Is::pending($promise)) {
|
||||
$promise->resolve($task());
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
$promise->reject($e);
|
||||
} catch (\Exception $e) {
|
||||
$promise->reject($e);
|
||||
}
|
||||
});
|
||||
return $promise;
|
||||
@@ -62,8 +67,10 @@ final class Utils
|
||||
* key mapping to the rejection reason of the promise.
|
||||
*
|
||||
* @param PromiseInterface $promise Promise or value.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function inspect(\YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface $promise) : array
|
||||
public static function inspect(\YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface $promise)
|
||||
{
|
||||
try {
|
||||
return ['state' => \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface::FULFILLED, 'value' => $promise->wait()];
|
||||
@@ -71,6 +78,8 @@ final class Utils
|
||||
return ['state' => \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface::REJECTED, 'reason' => $e->getReason()];
|
||||
} catch (\Throwable $e) {
|
||||
return ['state' => \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface::REJECTED, 'reason' => $e];
|
||||
} catch (\Exception $e) {
|
||||
return ['state' => \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface::REJECTED, 'reason' => $e];
|
||||
}
|
||||
}
|
||||
/**
|
||||
@@ -82,12 +91,14 @@ final class Utils
|
||||
* @see inspect for the inspection state array format.
|
||||
*
|
||||
* @param PromiseInterface[] $promises Traversable of promises to wait upon.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function inspectAll($promises) : array
|
||||
public static function inspectAll($promises)
|
||||
{
|
||||
$results = [];
|
||||
foreach ($promises as $key => $promise) {
|
||||
$results[$key] = self::inspect($promise);
|
||||
$results[$key] = inspect($promise);
|
||||
}
|
||||
return $results;
|
||||
}
|
||||
@@ -100,9 +111,12 @@ final class Utils
|
||||
*
|
||||
* @param iterable<PromiseInterface> $promises Iterable of PromiseInterface objects to wait on.
|
||||
*
|
||||
* @throws \Throwable on error
|
||||
* @return array
|
||||
*
|
||||
* @throws \Exception on error
|
||||
* @throws \Throwable on error in PHP >=7
|
||||
*/
|
||||
public static function unwrap($promises) : array
|
||||
public static function unwrap($promises)
|
||||
{
|
||||
$results = [];
|
||||
foreach ($promises as $key => $promise) {
|
||||
@@ -120,13 +134,15 @@ final class Utils
|
||||
*
|
||||
* @param mixed $promises Promises or values.
|
||||
* @param bool $recursive If true, resolves new promises that might have been added to the stack during its own resolution.
|
||||
*
|
||||
* @return PromiseInterface
|
||||
*/
|
||||
public static function all($promises, bool $recursive = \false) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
|
||||
public static function all($promises, $recursive = \false)
|
||||
{
|
||||
$results = [];
|
||||
$promise = \YoastSEO_Vendor\GuzzleHttp\Promise\Each::of($promises, function ($value, $idx) use(&$results) : void {
|
||||
$promise = \YoastSEO_Vendor\GuzzleHttp\Promise\Each::of($promises, function ($value, $idx) use(&$results) {
|
||||
$results[$idx] = $value;
|
||||
}, function ($reason, $idx, \YoastSEO_Vendor\GuzzleHttp\Promise\Promise $aggregate) : void {
|
||||
}, function ($reason, $idx, \YoastSEO_Vendor\GuzzleHttp\Promise\Promise $aggregate) {
|
||||
$aggregate->reject($reason);
|
||||
})->then(function () use(&$results) {
|
||||
\ksort($results);
|
||||
@@ -157,12 +173,14 @@ final class Utils
|
||||
*
|
||||
* @param int $count Total number of promises.
|
||||
* @param mixed $promises Promises or values.
|
||||
*
|
||||
* @return PromiseInterface
|
||||
*/
|
||||
public static function some(int $count, $promises) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
|
||||
public static function some($count, $promises)
|
||||
{
|
||||
$results = [];
|
||||
$rejections = [];
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Promise\Each::of($promises, function ($value, $idx, \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface $p) use(&$results, $count) : void {
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Promise\Each::of($promises, function ($value, $idx, \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface $p) use(&$results, $count) {
|
||||
if (\YoastSEO_Vendor\GuzzleHttp\Promise\Is::settled($p)) {
|
||||
return;
|
||||
}
|
||||
@@ -170,7 +188,7 @@ final class Utils
|
||||
if (\count($results) >= $count) {
|
||||
$p->resolve(null);
|
||||
}
|
||||
}, function ($reason) use(&$rejections) : void {
|
||||
}, function ($reason) use(&$rejections) {
|
||||
$rejections[] = $reason;
|
||||
})->then(function () use(&$results, &$rejections, $count) {
|
||||
if (\count($results) !== $count) {
|
||||
@@ -185,8 +203,10 @@ final class Utils
|
||||
* fulfillment value is not an array of 1 but the value directly.
|
||||
*
|
||||
* @param mixed $promises Promises or values.
|
||||
*
|
||||
* @return PromiseInterface
|
||||
*/
|
||||
public static function any($promises) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
|
||||
public static function any($promises)
|
||||
{
|
||||
return self::some(1, $promises)->then(function ($values) {
|
||||
return $values[0];
|
||||
@@ -201,13 +221,15 @@ final class Utils
|
||||
* @see inspect for the inspection state array format.
|
||||
*
|
||||
* @param mixed $promises Promises or values.
|
||||
*
|
||||
* @return PromiseInterface
|
||||
*/
|
||||
public static function settle($promises) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface
|
||||
public static function settle($promises)
|
||||
{
|
||||
$results = [];
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Promise\Each::of($promises, function ($value, $idx) use(&$results) : void {
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Promise\Each::of($promises, function ($value, $idx) use(&$results) {
|
||||
$results[$idx] = ['state' => \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface::FULFILLED, 'value' => $value];
|
||||
}, function ($reason, $idx) use(&$results) : void {
|
||||
}, function ($reason, $idx) use(&$results) {
|
||||
$results[$idx] = ['state' => \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface::REJECTED, 'reason' => $reason];
|
||||
})->then(function () use(&$results) {
|
||||
\ksort($results);
|
||||
|
||||
@@ -0,0 +1,334 @@
|
||||
<?php
|
||||
|
||||
namespace YoastSEO_Vendor\GuzzleHttp\Promise;
|
||||
|
||||
/**
|
||||
* Get the global task queue used for promise resolution.
|
||||
*
|
||||
* This task queue MUST be run in an event loop in order for promises to be
|
||||
* settled asynchronously. It will be automatically run when synchronously
|
||||
* waiting on a promise.
|
||||
*
|
||||
* <code>
|
||||
* while ($eventLoop->isRunning()) {
|
||||
* GuzzleHttp\Promise\queue()->run();
|
||||
* }
|
||||
* </code>
|
||||
*
|
||||
* @param TaskQueueInterface $assign Optionally specify a new queue instance.
|
||||
*
|
||||
* @return TaskQueueInterface
|
||||
*
|
||||
* @deprecated queue will be removed in guzzlehttp/promises:2.0. Use Utils::queue instead.
|
||||
*/
|
||||
function queue(\YoastSEO_Vendor\GuzzleHttp\Promise\TaskQueueInterface $assign = null)
|
||||
{
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Promise\Utils::queue($assign);
|
||||
}
|
||||
/**
|
||||
* Adds a function to run in the task queue when it is next `run()` and returns
|
||||
* a promise that is fulfilled or rejected with the result.
|
||||
*
|
||||
* @param callable $task Task function to run.
|
||||
*
|
||||
* @return PromiseInterface
|
||||
*
|
||||
* @deprecated task will be removed in guzzlehttp/promises:2.0. Use Utils::task instead.
|
||||
*/
|
||||
function task(callable $task)
|
||||
{
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Promise\Utils::task($task);
|
||||
}
|
||||
/**
|
||||
* Creates a promise for a value if the value is not a promise.
|
||||
*
|
||||
* @param mixed $value Promise or value.
|
||||
*
|
||||
* @return PromiseInterface
|
||||
*
|
||||
* @deprecated promise_for will be removed in guzzlehttp/promises:2.0. Use Create::promiseFor instead.
|
||||
*/
|
||||
function promise_for($value)
|
||||
{
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Promise\Create::promiseFor($value);
|
||||
}
|
||||
/**
|
||||
* Creates a rejected promise for a reason if the reason is not a promise. If
|
||||
* the provided reason is a promise, then it is returned as-is.
|
||||
*
|
||||
* @param mixed $reason Promise or reason.
|
||||
*
|
||||
* @return PromiseInterface
|
||||
*
|
||||
* @deprecated rejection_for will be removed in guzzlehttp/promises:2.0. Use Create::rejectionFor instead.
|
||||
*/
|
||||
function rejection_for($reason)
|
||||
{
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Promise\Create::rejectionFor($reason);
|
||||
}
|
||||
/**
|
||||
* Create an exception for a rejected promise value.
|
||||
*
|
||||
* @param mixed $reason
|
||||
*
|
||||
* @return \Exception|\Throwable
|
||||
*
|
||||
* @deprecated exception_for will be removed in guzzlehttp/promises:2.0. Use Create::exceptionFor instead.
|
||||
*/
|
||||
function exception_for($reason)
|
||||
{
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Promise\Create::exceptionFor($reason);
|
||||
}
|
||||
/**
|
||||
* Returns an iterator for the given value.
|
||||
*
|
||||
* @param mixed $value
|
||||
*
|
||||
* @return \Iterator
|
||||
*
|
||||
* @deprecated iter_for will be removed in guzzlehttp/promises:2.0. Use Create::iterFor instead.
|
||||
*/
|
||||
function iter_for($value)
|
||||
{
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Promise\Create::iterFor($value);
|
||||
}
|
||||
/**
|
||||
* Synchronously waits on a promise to resolve and returns an inspection state
|
||||
* array.
|
||||
*
|
||||
* Returns a state associative array containing a "state" key mapping to a
|
||||
* valid promise state. If the state of the promise is "fulfilled", the array
|
||||
* will contain a "value" key mapping to the fulfilled value of the promise. If
|
||||
* the promise is rejected, the array will contain a "reason" key mapping to
|
||||
* the rejection reason of the promise.
|
||||
*
|
||||
* @param PromiseInterface $promise Promise or value.
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @deprecated inspect will be removed in guzzlehttp/promises:2.0. Use Utils::inspect instead.
|
||||
*/
|
||||
function inspect(\YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface $promise)
|
||||
{
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Promise\Utils::inspect($promise);
|
||||
}
|
||||
/**
|
||||
* Waits on all of the provided promises, but does not unwrap rejected promises
|
||||
* as thrown exception.
|
||||
*
|
||||
* Returns an array of inspection state arrays.
|
||||
*
|
||||
* @see inspect for the inspection state array format.
|
||||
*
|
||||
* @param PromiseInterface[] $promises Traversable of promises to wait upon.
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @deprecated inspect will be removed in guzzlehttp/promises:2.0. Use Utils::inspectAll instead.
|
||||
*/
|
||||
function inspect_all($promises)
|
||||
{
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Promise\Utils::inspectAll($promises);
|
||||
}
|
||||
/**
|
||||
* Waits on all of the provided promises and returns the fulfilled values.
|
||||
*
|
||||
* Returns an array that contains the value of each promise (in the same order
|
||||
* the promises were provided). An exception is thrown if any of the promises
|
||||
* are rejected.
|
||||
*
|
||||
* @param iterable<PromiseInterface> $promises Iterable of PromiseInterface objects to wait on.
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \Exception on error
|
||||
* @throws \Throwable on error in PHP >=7
|
||||
*
|
||||
* @deprecated unwrap will be removed in guzzlehttp/promises:2.0. Use Utils::unwrap instead.
|
||||
*/
|
||||
function unwrap($promises)
|
||||
{
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Promise\Utils::unwrap($promises);
|
||||
}
|
||||
/**
|
||||
* Given an array of promises, return a promise that is fulfilled when all the
|
||||
* items in the array are fulfilled.
|
||||
*
|
||||
* The promise's fulfillment value is an array with fulfillment values at
|
||||
* respective positions to the original array. If any promise in the array
|
||||
* rejects, the returned promise is rejected with the rejection reason.
|
||||
*
|
||||
* @param mixed $promises Promises or values.
|
||||
* @param bool $recursive If true, resolves new promises that might have been added to the stack during its own resolution.
|
||||
*
|
||||
* @return PromiseInterface
|
||||
*
|
||||
* @deprecated all will be removed in guzzlehttp/promises:2.0. Use Utils::all instead.
|
||||
*/
|
||||
function all($promises, $recursive = \false)
|
||||
{
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Promise\Utils::all($promises, $recursive);
|
||||
}
|
||||
/**
|
||||
* Initiate a competitive race between multiple promises or values (values will
|
||||
* become immediately fulfilled promises).
|
||||
*
|
||||
* When count amount of promises have been fulfilled, the returned promise is
|
||||
* fulfilled with an array that contains the fulfillment values of the winners
|
||||
* in order of resolution.
|
||||
*
|
||||
* This promise is rejected with a {@see AggregateException} if the number of
|
||||
* fulfilled promises is less than the desired $count.
|
||||
*
|
||||
* @param int $count Total number of promises.
|
||||
* @param mixed $promises Promises or values.
|
||||
*
|
||||
* @return PromiseInterface
|
||||
*
|
||||
* @deprecated some will be removed in guzzlehttp/promises:2.0. Use Utils::some instead.
|
||||
*/
|
||||
function some($count, $promises)
|
||||
{
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Promise\Utils::some($count, $promises);
|
||||
}
|
||||
/**
|
||||
* Like some(), with 1 as count. However, if the promise fulfills, the
|
||||
* fulfillment value is not an array of 1 but the value directly.
|
||||
*
|
||||
* @param mixed $promises Promises or values.
|
||||
*
|
||||
* @return PromiseInterface
|
||||
*
|
||||
* @deprecated any will be removed in guzzlehttp/promises:2.0. Use Utils::any instead.
|
||||
*/
|
||||
function any($promises)
|
||||
{
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Promise\Utils::any($promises);
|
||||
}
|
||||
/**
|
||||
* Returns a promise that is fulfilled when all of the provided promises have
|
||||
* been fulfilled or rejected.
|
||||
*
|
||||
* The returned promise is fulfilled with an array of inspection state arrays.
|
||||
*
|
||||
* @see inspect for the inspection state array format.
|
||||
*
|
||||
* @param mixed $promises Promises or values.
|
||||
*
|
||||
* @return PromiseInterface
|
||||
*
|
||||
* @deprecated settle will be removed in guzzlehttp/promises:2.0. Use Utils::settle instead.
|
||||
*/
|
||||
function settle($promises)
|
||||
{
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Promise\Utils::settle($promises);
|
||||
}
|
||||
/**
|
||||
* Given an iterator that yields promises or values, returns a promise that is
|
||||
* fulfilled with a null value when the iterator has been consumed or the
|
||||
* aggregate promise has been fulfilled or rejected.
|
||||
*
|
||||
* $onFulfilled is a function that accepts the fulfilled value, iterator index,
|
||||
* and the aggregate promise. The callback can invoke any necessary side
|
||||
* effects and choose to resolve or reject the aggregate if needed.
|
||||
*
|
||||
* $onRejected is a function that accepts the rejection reason, iterator index,
|
||||
* and the aggregate promise. The callback can invoke any necessary side
|
||||
* effects and choose to resolve or reject the aggregate if needed.
|
||||
*
|
||||
* @param mixed $iterable Iterator or array to iterate over.
|
||||
* @param callable $onFulfilled
|
||||
* @param callable $onRejected
|
||||
*
|
||||
* @return PromiseInterface
|
||||
*
|
||||
* @deprecated each will be removed in guzzlehttp/promises:2.0. Use Each::of instead.
|
||||
*/
|
||||
function each($iterable, callable $onFulfilled = null, callable $onRejected = null)
|
||||
{
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Promise\Each::of($iterable, $onFulfilled, $onRejected);
|
||||
}
|
||||
/**
|
||||
* Like each, but only allows a certain number of outstanding promises at any
|
||||
* given time.
|
||||
*
|
||||
* $concurrency may be an integer or a function that accepts the number of
|
||||
* pending promises and returns a numeric concurrency limit value to allow for
|
||||
* dynamic a concurrency size.
|
||||
*
|
||||
* @param mixed $iterable
|
||||
* @param int|callable $concurrency
|
||||
* @param callable $onFulfilled
|
||||
* @param callable $onRejected
|
||||
*
|
||||
* @return PromiseInterface
|
||||
*
|
||||
* @deprecated each_limit will be removed in guzzlehttp/promises:2.0. Use Each::ofLimit instead.
|
||||
*/
|
||||
function each_limit($iterable, $concurrency, callable $onFulfilled = null, callable $onRejected = null)
|
||||
{
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Promise\Each::ofLimit($iterable, $concurrency, $onFulfilled, $onRejected);
|
||||
}
|
||||
/**
|
||||
* Like each_limit, but ensures that no promise in the given $iterable argument
|
||||
* is rejected. If any promise is rejected, then the aggregate promise is
|
||||
* rejected with the encountered rejection.
|
||||
*
|
||||
* @param mixed $iterable
|
||||
* @param int|callable $concurrency
|
||||
* @param callable $onFulfilled
|
||||
*
|
||||
* @return PromiseInterface
|
||||
*
|
||||
* @deprecated each_limit_all will be removed in guzzlehttp/promises:2.0. Use Each::ofLimitAll instead.
|
||||
*/
|
||||
function each_limit_all($iterable, $concurrency, callable $onFulfilled = null)
|
||||
{
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Promise\Each::ofLimitAll($iterable, $concurrency, $onFulfilled);
|
||||
}
|
||||
/**
|
||||
* Returns true if a promise is fulfilled.
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @deprecated is_fulfilled will be removed in guzzlehttp/promises:2.0. Use Is::fulfilled instead.
|
||||
*/
|
||||
function is_fulfilled(\YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface $promise)
|
||||
{
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Promise\Is::fulfilled($promise);
|
||||
}
|
||||
/**
|
||||
* Returns true if a promise is rejected.
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @deprecated is_rejected will be removed in guzzlehttp/promises:2.0. Use Is::rejected instead.
|
||||
*/
|
||||
function is_rejected(\YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface $promise)
|
||||
{
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Promise\Is::rejected($promise);
|
||||
}
|
||||
/**
|
||||
* Returns true if a promise is fulfilled or rejected.
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @deprecated is_settled will be removed in guzzlehttp/promises:2.0. Use Is::settled instead.
|
||||
*/
|
||||
function is_settled(\YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface $promise)
|
||||
{
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Promise\Is::settled($promise);
|
||||
}
|
||||
/**
|
||||
* Create a new coroutine.
|
||||
*
|
||||
* @see Coroutine
|
||||
*
|
||||
* @return PromiseInterface
|
||||
*
|
||||
* @deprecated coroutine will be removed in guzzlehttp/promises:2.0. Use Coroutine::of instead.
|
||||
*/
|
||||
function coroutine(callable $generatorFn)
|
||||
{
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Promise\Coroutine::of($generatorFn);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace YoastSEO_Vendor;
|
||||
|
||||
// Don't redefine the functions if included multiple times.
|
||||
if (!\function_exists('YoastSEO_Vendor\\GuzzleHttp\\Promise\\promise_for')) {
|
||||
require __DIR__ . '/functions.php';
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare (strict_types=1);
|
||||
namespace YoastSEO_Vendor\GuzzleHttp\Psr7;
|
||||
|
||||
use YoastSEO_Vendor\Psr\Http\Message\StreamInterface;
|
||||
@@ -8,16 +7,15 @@ use YoastSEO_Vendor\Psr\Http\Message\StreamInterface;
|
||||
* Reads from multiple streams, one after the other.
|
||||
*
|
||||
* This is a read-only stream decorator.
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
final class AppendStream implements \YoastSEO_Vendor\Psr\Http\Message\StreamInterface
|
||||
class AppendStream implements \YoastSEO_Vendor\Psr\Http\Message\StreamInterface
|
||||
{
|
||||
/** @var StreamInterface[] Streams being decorated */
|
||||
private $streams = [];
|
||||
/** @var bool */
|
||||
private $seekable = \true;
|
||||
/** @var int */
|
||||
private $current = 0;
|
||||
/** @var int */
|
||||
private $pos = 0;
|
||||
/**
|
||||
* @param StreamInterface[] $streams Streams to decorate. Each stream must
|
||||
@@ -29,16 +27,12 @@ final class AppendStream implements \YoastSEO_Vendor\Psr\Http\Message\StreamInte
|
||||
$this->addStream($stream);
|
||||
}
|
||||
}
|
||||
public function __toString() : string
|
||||
public function __toString()
|
||||
{
|
||||
try {
|
||||
$this->rewind();
|
||||
return $this->getContents();
|
||||
} catch (\Throwable $e) {
|
||||
if (\PHP_VERSION_ID >= 70400) {
|
||||
throw $e;
|
||||
}
|
||||
\trigger_error(\sprintf('%s::__toString exception: %s', self::class, (string) $e), \E_USER_ERROR);
|
||||
} catch (\Exception $e) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
@@ -49,7 +43,7 @@ final class AppendStream implements \YoastSEO_Vendor\Psr\Http\Message\StreamInte
|
||||
*
|
||||
* @throws \InvalidArgumentException if the stream is not readable
|
||||
*/
|
||||
public function addStream(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $stream) : void
|
||||
public function addStream(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $stream)
|
||||
{
|
||||
if (!$stream->isReadable()) {
|
||||
throw new \InvalidArgumentException('Each stream must be readable');
|
||||
@@ -60,14 +54,16 @@ final class AppendStream implements \YoastSEO_Vendor\Psr\Http\Message\StreamInte
|
||||
}
|
||||
$this->streams[] = $stream;
|
||||
}
|
||||
public function getContents() : string
|
||||
public function getContents()
|
||||
{
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::copyToString($this);
|
||||
}
|
||||
/**
|
||||
* Closes each attached stream.
|
||||
*
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function close() : void
|
||||
public function close()
|
||||
{
|
||||
$this->pos = $this->current = 0;
|
||||
$this->seekable = \true;
|
||||
@@ -80,6 +76,8 @@ final class AppendStream implements \YoastSEO_Vendor\Psr\Http\Message\StreamInte
|
||||
* Detaches each attached stream.
|
||||
*
|
||||
* Returns null as it's not clear which underlying stream resource to return.
|
||||
*
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function detach()
|
||||
{
|
||||
@@ -91,7 +89,7 @@ final class AppendStream implements \YoastSEO_Vendor\Psr\Http\Message\StreamInte
|
||||
$this->streams = [];
|
||||
return null;
|
||||
}
|
||||
public function tell() : int
|
||||
public function tell()
|
||||
{
|
||||
return $this->pos;
|
||||
}
|
||||
@@ -100,8 +98,10 @@ final class AppendStream implements \YoastSEO_Vendor\Psr\Http\Message\StreamInte
|
||||
*
|
||||
* If any of the streams do not return a valid number, then the size of the
|
||||
* append stream cannot be determined and null is returned.
|
||||
*
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getSize() : ?int
|
||||
public function getSize()
|
||||
{
|
||||
$size = 0;
|
||||
foreach ($this->streams as $stream) {
|
||||
@@ -113,18 +113,20 @@ final class AppendStream implements \YoastSEO_Vendor\Psr\Http\Message\StreamInte
|
||||
}
|
||||
return $size;
|
||||
}
|
||||
public function eof() : bool
|
||||
public function eof()
|
||||
{
|
||||
return !$this->streams || $this->current >= \count($this->streams) - 1 && $this->streams[$this->current]->eof();
|
||||
}
|
||||
public function rewind() : void
|
||||
public function rewind()
|
||||
{
|
||||
$this->seek(0);
|
||||
}
|
||||
/**
|
||||
* Attempts to seek to the given position. Only supports SEEK_SET.
|
||||
*
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function seek($offset, $whence = \SEEK_SET) : void
|
||||
public function seek($offset, $whence = \SEEK_SET)
|
||||
{
|
||||
if (!$this->seekable) {
|
||||
throw new \RuntimeException('This AppendStream is not seekable');
|
||||
@@ -150,8 +152,10 @@ final class AppendStream implements \YoastSEO_Vendor\Psr\Http\Message\StreamInte
|
||||
}
|
||||
/**
|
||||
* Reads from all of the appended streams until the length is met or EOF.
|
||||
*
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function read($length) : string
|
||||
public function read($length)
|
||||
{
|
||||
$buffer = '';
|
||||
$total = \count($this->streams) - 1;
|
||||
@@ -164,10 +168,11 @@ final class AppendStream implements \YoastSEO_Vendor\Psr\Http\Message\StreamInte
|
||||
if ($this->current === $total) {
|
||||
break;
|
||||
}
|
||||
++$this->current;
|
||||
$this->current++;
|
||||
}
|
||||
$result = $this->streams[$this->current]->read($remaining);
|
||||
if ($result === '') {
|
||||
// Using a loose comparison here to match on '', false, and null
|
||||
if ($result == null) {
|
||||
$progressToNext = \true;
|
||||
continue;
|
||||
}
|
||||
@@ -177,25 +182,22 @@ final class AppendStream implements \YoastSEO_Vendor\Psr\Http\Message\StreamInte
|
||||
$this->pos += \strlen($buffer);
|
||||
return $buffer;
|
||||
}
|
||||
public function isReadable() : bool
|
||||
public function isReadable()
|
||||
{
|
||||
return \true;
|
||||
}
|
||||
public function isWritable() : bool
|
||||
public function isWritable()
|
||||
{
|
||||
return \false;
|
||||
}
|
||||
public function isSeekable() : bool
|
||||
public function isSeekable()
|
||||
{
|
||||
return $this->seekable;
|
||||
}
|
||||
public function write($string) : int
|
||||
public function write($string)
|
||||
{
|
||||
throw new \RuntimeException('Cannot write to an AppendStream');
|
||||
}
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getMetadata($key = null)
|
||||
{
|
||||
return $key ? null : [];
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare (strict_types=1);
|
||||
namespace YoastSEO_Vendor\GuzzleHttp\Psr7;
|
||||
|
||||
use YoastSEO_Vendor\Psr\Http\Message\StreamInterface;
|
||||
@@ -11,35 +10,35 @@ use YoastSEO_Vendor\Psr\Http\Message\StreamInterface;
|
||||
* This stream returns a "hwm" metadata value that tells upstream consumers
|
||||
* what the configured high water mark of the stream is, or the maximum
|
||||
* preferred size of the buffer.
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
final class BufferStream implements \YoastSEO_Vendor\Psr\Http\Message\StreamInterface
|
||||
class BufferStream implements \YoastSEO_Vendor\Psr\Http\Message\StreamInterface
|
||||
{
|
||||
/** @var int */
|
||||
private $hwm;
|
||||
/** @var string */
|
||||
private $buffer = '';
|
||||
/**
|
||||
* @param int $hwm High water mark, representing the preferred maximum
|
||||
* buffer size. If the size of the buffer exceeds the high
|
||||
* water mark, then calls to write will continue to succeed
|
||||
* but will return 0 to inform writers to slow down
|
||||
* but will return false to inform writers to slow down
|
||||
* until the buffer has been drained by reading from it.
|
||||
*/
|
||||
public function __construct(int $hwm = 16384)
|
||||
public function __construct($hwm = 16384)
|
||||
{
|
||||
$this->hwm = $hwm;
|
||||
}
|
||||
public function __toString() : string
|
||||
public function __toString()
|
||||
{
|
||||
return $this->getContents();
|
||||
}
|
||||
public function getContents() : string
|
||||
public function getContents()
|
||||
{
|
||||
$buffer = $this->buffer;
|
||||
$this->buffer = '';
|
||||
return $buffer;
|
||||
}
|
||||
public function close() : void
|
||||
public function close()
|
||||
{
|
||||
$this->buffer = '';
|
||||
}
|
||||
@@ -48,42 +47,42 @@ final class BufferStream implements \YoastSEO_Vendor\Psr\Http\Message\StreamInte
|
||||
$this->close();
|
||||
return null;
|
||||
}
|
||||
public function getSize() : ?int
|
||||
public function getSize()
|
||||
{
|
||||
return \strlen($this->buffer);
|
||||
}
|
||||
public function isReadable() : bool
|
||||
public function isReadable()
|
||||
{
|
||||
return \true;
|
||||
}
|
||||
public function isWritable() : bool
|
||||
public function isWritable()
|
||||
{
|
||||
return \true;
|
||||
}
|
||||
public function isSeekable() : bool
|
||||
public function isSeekable()
|
||||
{
|
||||
return \false;
|
||||
}
|
||||
public function rewind() : void
|
||||
public function rewind()
|
||||
{
|
||||
$this->seek(0);
|
||||
}
|
||||
public function seek($offset, $whence = \SEEK_SET) : void
|
||||
public function seek($offset, $whence = \SEEK_SET)
|
||||
{
|
||||
throw new \RuntimeException('Cannot seek a BufferStream');
|
||||
}
|
||||
public function eof() : bool
|
||||
public function eof()
|
||||
{
|
||||
return \strlen($this->buffer) === 0;
|
||||
}
|
||||
public function tell() : int
|
||||
public function tell()
|
||||
{
|
||||
throw new \RuntimeException('Cannot determine the position of a BufferStream');
|
||||
}
|
||||
/**
|
||||
* Reads data from the buffer.
|
||||
*/
|
||||
public function read($length) : string
|
||||
public function read($length)
|
||||
{
|
||||
$currentLength = \strlen($this->buffer);
|
||||
if ($length >= $currentLength) {
|
||||
@@ -100,20 +99,18 @@ final class BufferStream implements \YoastSEO_Vendor\Psr\Http\Message\StreamInte
|
||||
/**
|
||||
* Writes data to the buffer.
|
||||
*/
|
||||
public function write($string) : int
|
||||
public function write($string)
|
||||
{
|
||||
$this->buffer .= $string;
|
||||
// TODO: What should happen here?
|
||||
if (\strlen($this->buffer) >= $this->hwm) {
|
||||
return 0;
|
||||
return \false;
|
||||
}
|
||||
return \strlen($string);
|
||||
}
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getMetadata($key = null)
|
||||
{
|
||||
if ($key === 'hwm') {
|
||||
if ($key == 'hwm') {
|
||||
return $this->hwm;
|
||||
}
|
||||
return $key ? null : [];
|
||||
|
||||
@@ -1,24 +1,21 @@
|
||||
<?php
|
||||
|
||||
declare (strict_types=1);
|
||||
namespace YoastSEO_Vendor\GuzzleHttp\Psr7;
|
||||
|
||||
use YoastSEO_Vendor\Psr\Http\Message\StreamInterface;
|
||||
/**
|
||||
* Stream decorator that can cache previously read bytes from a sequentially
|
||||
* read stream.
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
final class CachingStream implements \YoastSEO_Vendor\Psr\Http\Message\StreamInterface
|
||||
class CachingStream implements \YoastSEO_Vendor\Psr\Http\Message\StreamInterface
|
||||
{
|
||||
use StreamDecoratorTrait;
|
||||
/** @var StreamInterface Stream being wrapped */
|
||||
private $remoteStream;
|
||||
/** @var int Number of bytes to skip reading due to a write on the buffer */
|
||||
private $skipReadBytes = 0;
|
||||
/**
|
||||
* @var StreamInterface
|
||||
*/
|
||||
private $stream;
|
||||
/**
|
||||
* We will treat the buffer object as the body of the stream
|
||||
*
|
||||
@@ -30,7 +27,7 @@ final class CachingStream implements \YoastSEO_Vendor\Psr\Http\Message\StreamInt
|
||||
$this->remoteStream = $stream;
|
||||
$this->stream = $target ?: new \YoastSEO_Vendor\GuzzleHttp\Psr7\Stream(\YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::tryFopen('php://temp', 'r+'));
|
||||
}
|
||||
public function getSize() : ?int
|
||||
public function getSize()
|
||||
{
|
||||
$remoteSize = $this->remoteStream->getSize();
|
||||
if (null === $remoteSize) {
|
||||
@@ -38,17 +35,17 @@ final class CachingStream implements \YoastSEO_Vendor\Psr\Http\Message\StreamInt
|
||||
}
|
||||
return \max($this->stream->getSize(), $remoteSize);
|
||||
}
|
||||
public function rewind() : void
|
||||
public function rewind()
|
||||
{
|
||||
$this->seek(0);
|
||||
}
|
||||
public function seek($offset, $whence = \SEEK_SET) : void
|
||||
public function seek($offset, $whence = \SEEK_SET)
|
||||
{
|
||||
if ($whence === \SEEK_SET) {
|
||||
if ($whence == \SEEK_SET) {
|
||||
$byte = $offset;
|
||||
} elseif ($whence === \SEEK_CUR) {
|
||||
} elseif ($whence == \SEEK_CUR) {
|
||||
$byte = $offset + $this->tell();
|
||||
} elseif ($whence === \SEEK_END) {
|
||||
} elseif ($whence == \SEEK_END) {
|
||||
$size = $this->remoteStream->getSize();
|
||||
if ($size === null) {
|
||||
$size = $this->cacheEntireStream();
|
||||
@@ -70,7 +67,7 @@ final class CachingStream implements \YoastSEO_Vendor\Psr\Http\Message\StreamInt
|
||||
$this->stream->seek($byte);
|
||||
}
|
||||
}
|
||||
public function read($length) : string
|
||||
public function read($length)
|
||||
{
|
||||
// Perform a regular read on any previously read data from the buffer
|
||||
$data = $this->stream->read($length);
|
||||
@@ -92,7 +89,7 @@ final class CachingStream implements \YoastSEO_Vendor\Psr\Http\Message\StreamInt
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
public function write($string) : int
|
||||
public function write($string)
|
||||
{
|
||||
// When appending to the end of the currently read stream, you'll want
|
||||
// to skip bytes from being read from the remote stream to emulate
|
||||
@@ -104,19 +101,18 @@ final class CachingStream implements \YoastSEO_Vendor\Psr\Http\Message\StreamInt
|
||||
}
|
||||
return $this->stream->write($string);
|
||||
}
|
||||
public function eof() : bool
|
||||
public function eof()
|
||||
{
|
||||
return $this->stream->eof() && $this->remoteStream->eof();
|
||||
}
|
||||
/**
|
||||
* Close both the remote stream and buffer stream
|
||||
*/
|
||||
public function close() : void
|
||||
public function close()
|
||||
{
|
||||
$this->remoteStream->close();
|
||||
$this->stream->close();
|
||||
$this->remoteStream->close() && $this->stream->close();
|
||||
}
|
||||
private function cacheEntireStream() : int
|
||||
private function cacheEntireStream()
|
||||
{
|
||||
$target = new \YoastSEO_Vendor\GuzzleHttp\Psr7\FnStream(['write' => 'strlen']);
|
||||
\YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::copyToStream($this, $target);
|
||||
|
||||
@@ -1,30 +1,28 @@
|
||||
<?php
|
||||
|
||||
declare (strict_types=1);
|
||||
namespace YoastSEO_Vendor\GuzzleHttp\Psr7;
|
||||
|
||||
use YoastSEO_Vendor\Psr\Http\Message\StreamInterface;
|
||||
/**
|
||||
* Stream decorator that begins dropping data once the size of the underlying
|
||||
* stream becomes too full.
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
final class DroppingStream implements \YoastSEO_Vendor\Psr\Http\Message\StreamInterface
|
||||
class DroppingStream implements \YoastSEO_Vendor\Psr\Http\Message\StreamInterface
|
||||
{
|
||||
use StreamDecoratorTrait;
|
||||
/** @var int */
|
||||
private $maxLength;
|
||||
/** @var StreamInterface */
|
||||
private $stream;
|
||||
/**
|
||||
* @param StreamInterface $stream Underlying stream to decorate.
|
||||
* @param int $maxLength Maximum size before dropping data.
|
||||
*/
|
||||
public function __construct(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $stream, int $maxLength)
|
||||
public function __construct(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $stream, $maxLength)
|
||||
{
|
||||
$this->stream = $stream;
|
||||
$this->maxLength = $maxLength;
|
||||
}
|
||||
public function write($string) : int
|
||||
public function write($string)
|
||||
{
|
||||
$diff = $this->maxLength - $this->stream->getSize();
|
||||
// Begin returning 0 when the underlying stream is too large.
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare (strict_types=1);
|
||||
namespace YoastSEO_Vendor\GuzzleHttp\Psr7\Exception;
|
||||
|
||||
use InvalidArgumentException;
|
||||
/**
|
||||
* Exception thrown if a URI cannot be parsed because it's malformed.
|
||||
*/
|
||||
class MalformedUriException extends \InvalidArgumentException
|
||||
{
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare (strict_types=1);
|
||||
namespace YoastSEO_Vendor\GuzzleHttp\Psr7;
|
||||
|
||||
use YoastSEO_Vendor\Psr\Http\Message\StreamInterface;
|
||||
@@ -9,15 +8,17 @@ use YoastSEO_Vendor\Psr\Http\Message\StreamInterface;
|
||||
*
|
||||
* Allows for easy testing and extension of a provided stream without needing
|
||||
* to create a concrete class for a simple extension point.
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
#[\AllowDynamicProperties]
|
||||
final class FnStream implements \YoastSEO_Vendor\Psr\Http\Message\StreamInterface
|
||||
class FnStream implements \YoastSEO_Vendor\Psr\Http\Message\StreamInterface
|
||||
{
|
||||
private const SLOTS = ['__toString', 'close', 'detach', 'rewind', 'getSize', 'tell', 'eof', 'isSeekable', 'seek', 'isWritable', 'write', 'isReadable', 'read', 'getContents', 'getMetadata'];
|
||||
/** @var array<string, callable> */
|
||||
/** @var array */
|
||||
private $methods;
|
||||
/** @var array Methods that must be implemented in the given array */
|
||||
private static $slots = ['__toString', 'close', 'detach', 'rewind', 'getSize', 'tell', 'eof', 'isSeekable', 'seek', 'isWritable', 'write', 'isReadable', 'read', 'getContents', 'getMetadata'];
|
||||
/**
|
||||
* @param array<string, callable> $methods Hash of method name to a callable.
|
||||
* @param array $methods Hash of method name to a callable.
|
||||
*/
|
||||
public function __construct(array $methods)
|
||||
{
|
||||
@@ -32,7 +33,7 @@ final class FnStream implements \YoastSEO_Vendor\Psr\Http\Message\StreamInterfac
|
||||
*
|
||||
* @throws \BadMethodCallException
|
||||
*/
|
||||
public function __get(string $name) : void
|
||||
public function __get($name)
|
||||
{
|
||||
throw new \BadMethodCallException(\str_replace('_fn_', '', $name) . '() is not implemented in the FnStream');
|
||||
}
|
||||
@@ -50,7 +51,7 @@ final class FnStream implements \YoastSEO_Vendor\Psr\Http\Message\StreamInterfac
|
||||
*
|
||||
* @throws \LogicException
|
||||
*/
|
||||
public function __wakeup() : void
|
||||
public function __wakeup()
|
||||
{
|
||||
throw new \LogicException('FnStream should never be unserialized');
|
||||
}
|
||||
@@ -58,8 +59,8 @@ final class FnStream implements \YoastSEO_Vendor\Psr\Http\Message\StreamInterfac
|
||||
* Adds custom functionality to an underlying stream by intercepting
|
||||
* specific method calls.
|
||||
*
|
||||
* @param StreamInterface $stream Stream to decorate
|
||||
* @param array<string, callable> $methods Hash of method name to a closure
|
||||
* @param StreamInterface $stream Stream to decorate
|
||||
* @param array $methods Hash of method name to a closure
|
||||
*
|
||||
* @return FnStream
|
||||
*/
|
||||
@@ -67,80 +68,67 @@ final class FnStream implements \YoastSEO_Vendor\Psr\Http\Message\StreamInterfac
|
||||
{
|
||||
// If any of the required methods were not provided, then simply
|
||||
// proxy to the decorated stream.
|
||||
foreach (\array_diff(self::SLOTS, \array_keys($methods)) as $diff) {
|
||||
/** @var callable $callable */
|
||||
$callable = [$stream, $diff];
|
||||
$methods[$diff] = $callable;
|
||||
foreach (\array_diff(self::$slots, \array_keys($methods)) as $diff) {
|
||||
$methods[$diff] = [$stream, $diff];
|
||||
}
|
||||
return new self($methods);
|
||||
}
|
||||
public function __toString() : string
|
||||
public function __toString()
|
||||
{
|
||||
try {
|
||||
return \call_user_func($this->_fn___toString);
|
||||
} catch (\Throwable $e) {
|
||||
if (\PHP_VERSION_ID >= 70400) {
|
||||
throw $e;
|
||||
}
|
||||
\trigger_error(\sprintf('%s::__toString exception: %s', self::class, (string) $e), \E_USER_ERROR);
|
||||
return '';
|
||||
}
|
||||
return \call_user_func($this->_fn___toString);
|
||||
}
|
||||
public function close() : void
|
||||
public function close()
|
||||
{
|
||||
\call_user_func($this->_fn_close);
|
||||
return \call_user_func($this->_fn_close);
|
||||
}
|
||||
public function detach()
|
||||
{
|
||||
return \call_user_func($this->_fn_detach);
|
||||
}
|
||||
public function getSize() : ?int
|
||||
public function getSize()
|
||||
{
|
||||
return \call_user_func($this->_fn_getSize);
|
||||
}
|
||||
public function tell() : int
|
||||
public function tell()
|
||||
{
|
||||
return \call_user_func($this->_fn_tell);
|
||||
}
|
||||
public function eof() : bool
|
||||
public function eof()
|
||||
{
|
||||
return \call_user_func($this->_fn_eof);
|
||||
}
|
||||
public function isSeekable() : bool
|
||||
public function isSeekable()
|
||||
{
|
||||
return \call_user_func($this->_fn_isSeekable);
|
||||
}
|
||||
public function rewind() : void
|
||||
public function rewind()
|
||||
{
|
||||
\call_user_func($this->_fn_rewind);
|
||||
}
|
||||
public function seek($offset, $whence = \SEEK_SET) : void
|
||||
public function seek($offset, $whence = \SEEK_SET)
|
||||
{
|
||||
\call_user_func($this->_fn_seek, $offset, $whence);
|
||||
}
|
||||
public function isWritable() : bool
|
||||
public function isWritable()
|
||||
{
|
||||
return \call_user_func($this->_fn_isWritable);
|
||||
}
|
||||
public function write($string) : int
|
||||
public function write($string)
|
||||
{
|
||||
return \call_user_func($this->_fn_write, $string);
|
||||
}
|
||||
public function isReadable() : bool
|
||||
public function isReadable()
|
||||
{
|
||||
return \call_user_func($this->_fn_isReadable);
|
||||
}
|
||||
public function read($length) : string
|
||||
public function read($length)
|
||||
{
|
||||
return \call_user_func($this->_fn_read, $length);
|
||||
}
|
||||
public function getContents() : string
|
||||
public function getContents()
|
||||
{
|
||||
return \call_user_func($this->_fn_getContents);
|
||||
}
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getMetadata($key = null)
|
||||
{
|
||||
return \call_user_func($this->_fn_getMetadata, $key);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare (strict_types=1);
|
||||
namespace YoastSEO_Vendor\GuzzleHttp\Psr7;
|
||||
|
||||
final class Header
|
||||
@@ -12,27 +11,27 @@ final class Header
|
||||
* contains a key, this function will inject a key with a '' string value.
|
||||
*
|
||||
* @param string|array $header Header to parse into components.
|
||||
*
|
||||
* @return array Returns the parsed header values.
|
||||
*/
|
||||
public static function parse($header) : array
|
||||
public static function parse($header)
|
||||
{
|
||||
static $trimmed = "\"' \n\t\r";
|
||||
$params = $matches = [];
|
||||
foreach ((array) $header as $value) {
|
||||
foreach (self::splitList($value) as $val) {
|
||||
$part = [];
|
||||
foreach (\preg_split('/;(?=([^"]*"[^"]*")*[^"]*$)/', $val) as $kvp) {
|
||||
if (\preg_match_all('/<[^>]+>|[^=]+/', $kvp, $matches)) {
|
||||
$m = $matches[0];
|
||||
if (isset($m[1])) {
|
||||
$part[\trim($m[0], $trimmed)] = \trim($m[1], $trimmed);
|
||||
} else {
|
||||
$part[] = \trim($m[0], $trimmed);
|
||||
}
|
||||
foreach (self::normalize($header) as $val) {
|
||||
$part = [];
|
||||
foreach (\preg_split('/;(?=([^"]*"[^"]*")*[^"]*$)/', $val) as $kvp) {
|
||||
if (\preg_match_all('/<[^>]+>|[^=]+/', $kvp, $matches)) {
|
||||
$m = $matches[0];
|
||||
if (isset($m[1])) {
|
||||
$part[\trim($m[0], $trimmed)] = \trim($m[1], $trimmed);
|
||||
} else {
|
||||
$part[] = \trim($m[0], $trimmed);
|
||||
}
|
||||
}
|
||||
if ($part) {
|
||||
$params[] = $part;
|
||||
}
|
||||
}
|
||||
if ($part) {
|
||||
$params[] = $part;
|
||||
}
|
||||
}
|
||||
return $params;
|
||||
@@ -43,73 +42,23 @@ final class Header
|
||||
*
|
||||
* @param string|array $header Header to normalize.
|
||||
*
|
||||
* @deprecated Use self::splitList() instead.
|
||||
* @return array Returns the normalized header field values.
|
||||
*/
|
||||
public static function normalize($header) : array
|
||||
public static function normalize($header)
|
||||
{
|
||||
$result = [];
|
||||
foreach ((array) $header as $value) {
|
||||
foreach (self::splitList($value) as $parsed) {
|
||||
$result[] = $parsed;
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
/**
|
||||
* Splits a HTTP header defined to contain a comma-separated list into
|
||||
* each individual value. Empty values will be removed.
|
||||
*
|
||||
* Example headers include 'accept', 'cache-control' and 'if-none-match'.
|
||||
*
|
||||
* This method must not be used to parse headers that are not defined as
|
||||
* a list, such as 'user-agent' or 'set-cookie'.
|
||||
*
|
||||
* @param string|string[] $values Header value as returned by MessageInterface::getHeader()
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public static function splitList($values) : array
|
||||
{
|
||||
if (!\is_array($values)) {
|
||||
$values = [$values];
|
||||
if (!\is_array($header)) {
|
||||
return \array_map('trim', \explode(',', $header));
|
||||
}
|
||||
$result = [];
|
||||
foreach ($values as $value) {
|
||||
if (!\is_string($value)) {
|
||||
throw new \TypeError('$header must either be a string or an array containing strings.');
|
||||
}
|
||||
$v = '';
|
||||
$isQuoted = \false;
|
||||
$isEscaped = \false;
|
||||
for ($i = 0, $max = \strlen($value); $i < $max; ++$i) {
|
||||
if ($isEscaped) {
|
||||
$v .= $value[$i];
|
||||
$isEscaped = \false;
|
||||
foreach ($header as $value) {
|
||||
foreach ((array) $value as $v) {
|
||||
if (\strpos($v, ',') === \false) {
|
||||
$result[] = $v;
|
||||
continue;
|
||||
}
|
||||
if (!$isQuoted && $value[$i] === ',') {
|
||||
$v = \trim($v);
|
||||
if ($v !== '') {
|
||||
$result[] = $v;
|
||||
}
|
||||
$v = '';
|
||||
continue;
|
||||
foreach (\preg_split('/,(?=([^"]*"[^"]*")*[^"]*$)/', $v) as $vv) {
|
||||
$result[] = \trim($vv);
|
||||
}
|
||||
if ($isQuoted && $value[$i] === '\\') {
|
||||
$isEscaped = \true;
|
||||
$v .= $value[$i];
|
||||
continue;
|
||||
}
|
||||
if ($value[$i] === '"') {
|
||||
$isQuoted = !$isQuoted;
|
||||
$v .= $value[$i];
|
||||
continue;
|
||||
}
|
||||
$v .= $value[$i];
|
||||
}
|
||||
$v = \trim($v);
|
||||
if ($v !== '') {
|
||||
$result[] = $v;
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
|
||||
@@ -1,76 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare (strict_types=1);
|
||||
namespace YoastSEO_Vendor\GuzzleHttp\Psr7;
|
||||
|
||||
use YoastSEO_Vendor\Psr\Http\Message\RequestFactoryInterface;
|
||||
use YoastSEO_Vendor\Psr\Http\Message\RequestInterface;
|
||||
use YoastSEO_Vendor\Psr\Http\Message\ResponseFactoryInterface;
|
||||
use YoastSEO_Vendor\Psr\Http\Message\ResponseInterface;
|
||||
use YoastSEO_Vendor\Psr\Http\Message\ServerRequestFactoryInterface;
|
||||
use YoastSEO_Vendor\Psr\Http\Message\ServerRequestInterface;
|
||||
use YoastSEO_Vendor\Psr\Http\Message\StreamFactoryInterface;
|
||||
use YoastSEO_Vendor\Psr\Http\Message\StreamInterface;
|
||||
use YoastSEO_Vendor\Psr\Http\Message\UploadedFileFactoryInterface;
|
||||
use YoastSEO_Vendor\Psr\Http\Message\UploadedFileInterface;
|
||||
use YoastSEO_Vendor\Psr\Http\Message\UriFactoryInterface;
|
||||
use YoastSEO_Vendor\Psr\Http\Message\UriInterface;
|
||||
/**
|
||||
* Implements all of the PSR-17 interfaces.
|
||||
*
|
||||
* Note: in consuming code it is recommended to require the implemented interfaces
|
||||
* and inject the instance of this class multiple times.
|
||||
*/
|
||||
final class HttpFactory implements \YoastSEO_Vendor\Psr\Http\Message\RequestFactoryInterface, \YoastSEO_Vendor\Psr\Http\Message\ResponseFactoryInterface, \YoastSEO_Vendor\Psr\Http\Message\ServerRequestFactoryInterface, \YoastSEO_Vendor\Psr\Http\Message\StreamFactoryInterface, \YoastSEO_Vendor\Psr\Http\Message\UploadedFileFactoryInterface, \YoastSEO_Vendor\Psr\Http\Message\UriFactoryInterface
|
||||
{
|
||||
public function createUploadedFile(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $stream, int $size = null, int $error = \UPLOAD_ERR_OK, string $clientFilename = null, string $clientMediaType = null) : \YoastSEO_Vendor\Psr\Http\Message\UploadedFileInterface
|
||||
{
|
||||
if ($size === null) {
|
||||
$size = $stream->getSize();
|
||||
}
|
||||
return new \YoastSEO_Vendor\GuzzleHttp\Psr7\UploadedFile($stream, $size, $error, $clientFilename, $clientMediaType);
|
||||
}
|
||||
public function createStream(string $content = '') : \YoastSEO_Vendor\Psr\Http\Message\StreamInterface
|
||||
{
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::streamFor($content);
|
||||
}
|
||||
public function createStreamFromFile(string $file, string $mode = 'r') : \YoastSEO_Vendor\Psr\Http\Message\StreamInterface
|
||||
{
|
||||
try {
|
||||
$resource = \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::tryFopen($file, $mode);
|
||||
} catch (\RuntimeException $e) {
|
||||
if ('' === $mode || \false === \in_array($mode[0], ['r', 'w', 'a', 'x', 'c'], \true)) {
|
||||
throw new \InvalidArgumentException(\sprintf('Invalid file opening mode "%s"', $mode), 0, $e);
|
||||
}
|
||||
throw $e;
|
||||
}
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::streamFor($resource);
|
||||
}
|
||||
public function createStreamFromResource($resource) : \YoastSEO_Vendor\Psr\Http\Message\StreamInterface
|
||||
{
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::streamFor($resource);
|
||||
}
|
||||
public function createServerRequest(string $method, $uri, array $serverParams = []) : \YoastSEO_Vendor\Psr\Http\Message\ServerRequestInterface
|
||||
{
|
||||
if (empty($method)) {
|
||||
if (!empty($serverParams['REQUEST_METHOD'])) {
|
||||
$method = $serverParams['REQUEST_METHOD'];
|
||||
} else {
|
||||
throw new \InvalidArgumentException('Cannot determine HTTP method');
|
||||
}
|
||||
}
|
||||
return new \YoastSEO_Vendor\GuzzleHttp\Psr7\ServerRequest($method, $uri, [], null, '1.1', $serverParams);
|
||||
}
|
||||
public function createResponse(int $code = 200, string $reasonPhrase = '') : \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface
|
||||
{
|
||||
return new \YoastSEO_Vendor\GuzzleHttp\Psr7\Response($code, [], null, '1.1', $reasonPhrase);
|
||||
}
|
||||
public function createRequest(string $method, $uri) : \YoastSEO_Vendor\Psr\Http\Message\RequestInterface
|
||||
{
|
||||
return new \YoastSEO_Vendor\GuzzleHttp\Psr7\Request($method, $uri);
|
||||
}
|
||||
public function createUri(string $uri = '') : \YoastSEO_Vendor\Psr\Http\Message\UriInterface
|
||||
{
|
||||
return new \YoastSEO_Vendor\GuzzleHttp\Psr7\Uri($uri);
|
||||
}
|
||||
}
|
||||
@@ -1,33 +1,51 @@
|
||||
<?php
|
||||
|
||||
declare (strict_types=1);
|
||||
namespace YoastSEO_Vendor\GuzzleHttp\Psr7;
|
||||
|
||||
use YoastSEO_Vendor\Psr\Http\Message\StreamInterface;
|
||||
/**
|
||||
* Uses PHP's zlib.inflate filter to inflate zlib (HTTP deflate, RFC1950) or gzipped (RFC1952) content.
|
||||
* Uses PHP's zlib.inflate filter to inflate deflate or gzipped content.
|
||||
*
|
||||
* This stream decorator converts the provided stream to a PHP stream resource,
|
||||
* This stream decorator skips the first 10 bytes of the given stream to remove
|
||||
* the gzip header, converts the provided stream to a PHP stream resource,
|
||||
* then appends the zlib.inflate filter. The stream is then converted back
|
||||
* to a Guzzle stream resource to be used as a Guzzle stream.
|
||||
*
|
||||
* @see http://tools.ietf.org/html/rfc1950
|
||||
* @see http://tools.ietf.org/html/rfc1952
|
||||
* @see http://php.net/manual/en/filters.compression.php
|
||||
* @link http://tools.ietf.org/html/rfc1952
|
||||
* @link http://php.net/manual/en/filters.compression.php
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
final class InflateStream implements \YoastSEO_Vendor\Psr\Http\Message\StreamInterface
|
||||
class InflateStream implements \YoastSEO_Vendor\Psr\Http\Message\StreamInterface
|
||||
{
|
||||
use StreamDecoratorTrait;
|
||||
/** @var StreamInterface */
|
||||
private $stream;
|
||||
public function __construct(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $stream)
|
||||
{
|
||||
// read the first 10 bytes, ie. gzip header
|
||||
$header = $stream->read(10);
|
||||
$filenameHeaderLength = $this->getLengthOfPossibleFilenameHeader($stream, $header);
|
||||
// Skip the header, that is 10 + length of filename + 1 (nil) bytes
|
||||
$stream = new \YoastSEO_Vendor\GuzzleHttp\Psr7\LimitStream($stream, -1, 10 + $filenameHeaderLength);
|
||||
$resource = \YoastSEO_Vendor\GuzzleHttp\Psr7\StreamWrapper::getResource($stream);
|
||||
// Specify window=15+32, so zlib will use header detection to both gzip (with header) and zlib data
|
||||
// See http://www.zlib.net/manual.html#Advanced definition of inflateInit2
|
||||
// "Add 32 to windowBits to enable zlib and gzip decoding with automatic header detection"
|
||||
// Default window size is 15.
|
||||
\stream_filter_append($resource, 'zlib.inflate', \STREAM_FILTER_READ, ['window' => 15 + 32]);
|
||||
\stream_filter_append($resource, 'zlib.inflate', \STREAM_FILTER_READ);
|
||||
$this->stream = $stream->isSeekable() ? new \YoastSEO_Vendor\GuzzleHttp\Psr7\Stream($resource) : new \YoastSEO_Vendor\GuzzleHttp\Psr7\NoSeekStream(new \YoastSEO_Vendor\GuzzleHttp\Psr7\Stream($resource));
|
||||
}
|
||||
/**
|
||||
* @param StreamInterface $stream
|
||||
* @param $header
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
private function getLengthOfPossibleFilenameHeader(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $stream, $header)
|
||||
{
|
||||
$filename_header_length = 0;
|
||||
if (\substr(\bin2hex($header), 6, 2) === '08') {
|
||||
// we have a filename, read until nil
|
||||
$filename_header_length = 1;
|
||||
while ($stream->read(1) !== \chr(0)) {
|
||||
$filename_header_length++;
|
||||
}
|
||||
}
|
||||
return $filename_header_length;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,40 +1,36 @@
|
||||
<?php
|
||||
|
||||
declare (strict_types=1);
|
||||
namespace YoastSEO_Vendor\GuzzleHttp\Psr7;
|
||||
|
||||
use YoastSEO_Vendor\Psr\Http\Message\StreamInterface;
|
||||
/**
|
||||
* Lazily reads or writes to a file that is opened only after an IO operation
|
||||
* take place on the stream.
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
final class LazyOpenStream implements \YoastSEO_Vendor\Psr\Http\Message\StreamInterface
|
||||
class LazyOpenStream implements \YoastSEO_Vendor\Psr\Http\Message\StreamInterface
|
||||
{
|
||||
use StreamDecoratorTrait;
|
||||
/** @var string */
|
||||
/** @var string File to open */
|
||||
private $filename;
|
||||
/** @var string */
|
||||
private $mode;
|
||||
/**
|
||||
* @var StreamInterface
|
||||
*/
|
||||
private $stream;
|
||||
/**
|
||||
* @param string $filename File to lazily open
|
||||
* @param string $mode fopen mode to use when opening the stream
|
||||
*/
|
||||
public function __construct(string $filename, string $mode)
|
||||
public function __construct($filename, $mode)
|
||||
{
|
||||
$this->filename = $filename;
|
||||
$this->mode = $mode;
|
||||
// unsetting the property forces the first access to go through
|
||||
// __get().
|
||||
unset($this->stream);
|
||||
}
|
||||
/**
|
||||
* Creates the underlying stream lazily when required.
|
||||
*
|
||||
* @return StreamInterface
|
||||
*/
|
||||
protected function createStream() : \YoastSEO_Vendor\Psr\Http\Message\StreamInterface
|
||||
protected function createStream()
|
||||
{
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::streamFor(\YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::tryFopen($this->filename, $this->mode));
|
||||
}
|
||||
|
||||
@@ -1,21 +1,20 @@
|
||||
<?php
|
||||
|
||||
declare (strict_types=1);
|
||||
namespace YoastSEO_Vendor\GuzzleHttp\Psr7;
|
||||
|
||||
use YoastSEO_Vendor\Psr\Http\Message\StreamInterface;
|
||||
/**
|
||||
* Decorator used to return only a subset of a stream.
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
final class LimitStream implements \YoastSEO_Vendor\Psr\Http\Message\StreamInterface
|
||||
class LimitStream implements \YoastSEO_Vendor\Psr\Http\Message\StreamInterface
|
||||
{
|
||||
use StreamDecoratorTrait;
|
||||
/** @var int Offset to start reading from */
|
||||
private $offset;
|
||||
/** @var int Limit the number of bytes that can be read */
|
||||
private $limit;
|
||||
/** @var StreamInterface */
|
||||
private $stream;
|
||||
/**
|
||||
* @param StreamInterface $stream Stream to wrap
|
||||
* @param int $limit Total number of bytes to allow to be read
|
||||
@@ -23,32 +22,33 @@ final class LimitStream implements \YoastSEO_Vendor\Psr\Http\Message\StreamInter
|
||||
* @param int $offset Position to seek to before reading (only
|
||||
* works on seekable streams).
|
||||
*/
|
||||
public function __construct(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $stream, int $limit = -1, int $offset = 0)
|
||||
public function __construct(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $stream, $limit = -1, $offset = 0)
|
||||
{
|
||||
$this->stream = $stream;
|
||||
$this->setLimit($limit);
|
||||
$this->setOffset($offset);
|
||||
}
|
||||
public function eof() : bool
|
||||
public function eof()
|
||||
{
|
||||
// Always return true if the underlying stream is EOF
|
||||
if ($this->stream->eof()) {
|
||||
return \true;
|
||||
}
|
||||
// No limit and the underlying stream is not at EOF
|
||||
if ($this->limit === -1) {
|
||||
if ($this->limit == -1) {
|
||||
return \false;
|
||||
}
|
||||
return $this->stream->tell() >= $this->offset + $this->limit;
|
||||
}
|
||||
/**
|
||||
* Returns the size of the limited subset of data
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getSize() : ?int
|
||||
public function getSize()
|
||||
{
|
||||
if (null === ($length = $this->stream->getSize())) {
|
||||
return null;
|
||||
} elseif ($this->limit === -1) {
|
||||
} elseif ($this->limit == -1) {
|
||||
return $length - $this->offset;
|
||||
} else {
|
||||
return \min($this->limit, $length - $this->offset);
|
||||
@@ -56,8 +56,9 @@ final class LimitStream implements \YoastSEO_Vendor\Psr\Http\Message\StreamInter
|
||||
}
|
||||
/**
|
||||
* Allow for a bounded seek on the read limited stream
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function seek($offset, $whence = \SEEK_SET) : void
|
||||
public function seek($offset, $whence = \SEEK_SET)
|
||||
{
|
||||
if ($whence !== \SEEK_SET || $offset < 0) {
|
||||
throw new \RuntimeException(\sprintf('Cannot seek to offset %s with whence %s', $offset, $whence));
|
||||
@@ -72,8 +73,9 @@ final class LimitStream implements \YoastSEO_Vendor\Psr\Http\Message\StreamInter
|
||||
}
|
||||
/**
|
||||
* Give a relative tell()
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function tell() : int
|
||||
public function tell()
|
||||
{
|
||||
return $this->stream->tell() - $this->offset;
|
||||
}
|
||||
@@ -84,7 +86,7 @@ final class LimitStream implements \YoastSEO_Vendor\Psr\Http\Message\StreamInter
|
||||
*
|
||||
* @throws \RuntimeException if the stream cannot be seeked.
|
||||
*/
|
||||
public function setOffset(int $offset) : void
|
||||
public function setOffset($offset)
|
||||
{
|
||||
$current = $this->stream->tell();
|
||||
if ($current !== $offset) {
|
||||
@@ -106,13 +108,13 @@ final class LimitStream implements \YoastSEO_Vendor\Psr\Http\Message\StreamInter
|
||||
* @param int $limit Number of bytes to allow to be read from the stream.
|
||||
* Use -1 for no limit.
|
||||
*/
|
||||
public function setLimit(int $limit) : void
|
||||
public function setLimit($limit)
|
||||
{
|
||||
$this->limit = $limit;
|
||||
}
|
||||
public function read($length) : string
|
||||
public function read($length)
|
||||
{
|
||||
if ($this->limit === -1) {
|
||||
if ($this->limit == -1) {
|
||||
return $this->stream->read($length);
|
||||
}
|
||||
// Check if the current position is less than the total allowed
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare (strict_types=1);
|
||||
namespace YoastSEO_Vendor\GuzzleHttp\Psr7;
|
||||
|
||||
use YoastSEO_Vendor\Psr\Http\Message\MessageInterface;
|
||||
@@ -12,8 +11,10 @@ final class Message
|
||||
* Returns the string representation of an HTTP message.
|
||||
*
|
||||
* @param MessageInterface $message Message to convert to a string.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function toString(\YoastSEO_Vendor\Psr\Http\Message\MessageInterface $message) : string
|
||||
public static function toString(\YoastSEO_Vendor\Psr\Http\Message\MessageInterface $message)
|
||||
{
|
||||
if ($message instanceof \YoastSEO_Vendor\Psr\Http\Message\RequestInterface) {
|
||||
$msg = \trim($message->getMethod() . ' ' . $message->getRequestTarget()) . ' HTTP/' . $message->getProtocolVersion();
|
||||
@@ -26,7 +27,7 @@ final class Message
|
||||
throw new \InvalidArgumentException('Unknown message type');
|
||||
}
|
||||
foreach ($message->getHeaders() as $name => $values) {
|
||||
if (\is_string($name) && \strtolower($name) === 'set-cookie') {
|
||||
if (\strtolower($name) === 'set-cookie') {
|
||||
foreach ($values as $value) {
|
||||
$msg .= "\r\n{$name}: " . $value;
|
||||
}
|
||||
@@ -43,8 +44,10 @@ final class Message
|
||||
*
|
||||
* @param MessageInterface $message The message to get the body summary
|
||||
* @param int $truncateAt The maximum allowed size of the summary
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public static function bodySummary(\YoastSEO_Vendor\Psr\Http\Message\MessageInterface $message, int $truncateAt = 120) : ?string
|
||||
public static function bodySummary(\YoastSEO_Vendor\Psr\Http\Message\MessageInterface $message, $truncateAt = 120)
|
||||
{
|
||||
$body = $message->getBody();
|
||||
if (!$body->isSeekable() || !$body->isReadable()) {
|
||||
@@ -54,7 +57,6 @@ final class Message
|
||||
if ($size === 0) {
|
||||
return null;
|
||||
}
|
||||
$body->rewind();
|
||||
$summary = $body->read($truncateAt);
|
||||
$body->rewind();
|
||||
if ($size > $truncateAt) {
|
||||
@@ -62,7 +64,7 @@ final class Message
|
||||
}
|
||||
// Matches any printable character, including unicode characters:
|
||||
// letters, marks, numbers, punctuation, spacing, and separators.
|
||||
if (\preg_match('/[^\\pL\\pM\\pN\\pP\\pS\\pZ\\n\\r\\t]/u', $summary) !== 0) {
|
||||
if (\preg_match('/[^\\pL\\pM\\pN\\pP\\pS\\pZ\\n\\r\\t]/u', $summary)) {
|
||||
return null;
|
||||
}
|
||||
return $summary;
|
||||
@@ -77,7 +79,7 @@ final class Message
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public static function rewindBody(\YoastSEO_Vendor\Psr\Http\Message\MessageInterface $message) : void
|
||||
public static function rewindBody(\YoastSEO_Vendor\Psr\Http\Message\MessageInterface $message)
|
||||
{
|
||||
$body = $message->getBody();
|
||||
if ($body->tell()) {
|
||||
@@ -92,8 +94,10 @@ final class Message
|
||||
* array values, and a "body" key containing the body of the message.
|
||||
*
|
||||
* @param string $message HTTP request or response to parse.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function parseMessage(string $message) : array
|
||||
public static function parseMessage($message)
|
||||
{
|
||||
if (!$message) {
|
||||
throw new \InvalidArgumentException('Invalid message');
|
||||
@@ -103,14 +107,14 @@ final class Message
|
||||
if ($messageParts === \false || \count($messageParts) !== 2) {
|
||||
throw new \InvalidArgumentException('Invalid message: Missing header delimiter');
|
||||
}
|
||||
[$rawHeaders, $body] = $messageParts;
|
||||
list($rawHeaders, $body) = $messageParts;
|
||||
$rawHeaders .= "\r\n";
|
||||
// Put back the delimiter we split previously
|
||||
$headerParts = \preg_split("/\r?\n/", $rawHeaders, 2);
|
||||
if ($headerParts === \false || \count($headerParts) !== 2) {
|
||||
throw new \InvalidArgumentException('Invalid message: Missing status line');
|
||||
}
|
||||
[$startLine, $rawHeaders] = $headerParts;
|
||||
list($startLine, $rawHeaders) = $headerParts;
|
||||
if (\preg_match("/(?:^HTTP\\/|^[A-Z]+ \\S+ HTTP\\/)(\\d+(?:\\.\\d+)?)/i", $startLine, $matches) && $matches[1] === '1.0') {
|
||||
// Header folding is deprecated for HTTP/1.1, but allowed in HTTP/1.0
|
||||
$rawHeaders = \preg_replace(\YoastSEO_Vendor\GuzzleHttp\Psr7\Rfc7230::HEADER_FOLD_REGEX, ' ', $rawHeaders);
|
||||
@@ -136,12 +140,12 @@ final class Message
|
||||
*
|
||||
* @param string $path Path from the start-line
|
||||
* @param array $headers Array of headers (each value an array).
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function parseRequestUri(string $path, array $headers) : string
|
||||
public static function parseRequestUri($path, array $headers)
|
||||
{
|
||||
$hostKey = \array_filter(\array_keys($headers), function ($k) {
|
||||
// Numeric array keys are converted to int by PHP.
|
||||
$k = (string) $k;
|
||||
return \strtolower($k) === 'host';
|
||||
});
|
||||
// If no host is found, then a full URI cannot be constructed.
|
||||
@@ -156,8 +160,10 @@ final class Message
|
||||
* Parses a request message string into a request object.
|
||||
*
|
||||
* @param string $message Request message string.
|
||||
*
|
||||
* @return Request
|
||||
*/
|
||||
public static function parseRequest(string $message) : \YoastSEO_Vendor\Psr\Http\Message\RequestInterface
|
||||
public static function parseRequest($message)
|
||||
{
|
||||
$data = self::parseMessage($message);
|
||||
$matches = [];
|
||||
@@ -173,8 +179,10 @@ final class Message
|
||||
* Parses a response message string into a response object.
|
||||
*
|
||||
* @param string $message Response message string.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public static function parseResponse(string $message) : \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface
|
||||
public static function parseResponse($message)
|
||||
{
|
||||
$data = self::parseMessage($message);
|
||||
// According to https://tools.ietf.org/html/rfc7230#section-3.1.2 the space
|
||||
@@ -184,6 +192,6 @@ final class Message
|
||||
throw new \InvalidArgumentException('Invalid response string: ' . $data['start-line']);
|
||||
}
|
||||
$parts = \explode(' ', $data['start-line'], 3);
|
||||
return new \YoastSEO_Vendor\GuzzleHttp\Psr7\Response((int) $parts[1], $data['headers'], $data['body'], \explode('/', $parts[0])[1], $parts[2] ?? null);
|
||||
return new \YoastSEO_Vendor\GuzzleHttp\Psr7\Response((int) $parts[1], $data['headers'], $data['body'], \explode('/', $parts[0])[1], isset($parts[2]) ? $parts[2] : null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,28 +1,26 @@
|
||||
<?php
|
||||
|
||||
declare (strict_types=1);
|
||||
namespace YoastSEO_Vendor\GuzzleHttp\Psr7;
|
||||
|
||||
use YoastSEO_Vendor\Psr\Http\Message\MessageInterface;
|
||||
use YoastSEO_Vendor\Psr\Http\Message\StreamInterface;
|
||||
/**
|
||||
* Trait implementing functionality common to requests and responses.
|
||||
*/
|
||||
trait MessageTrait
|
||||
{
|
||||
/** @var string[][] Map of all registered headers, as original name => array of values */
|
||||
/** @var array Map of all registered headers, as original name => array of values */
|
||||
private $headers = [];
|
||||
/** @var string[] Map of lowercase header name => original name at registration */
|
||||
/** @var array Map of lowercase header name => original name at registration */
|
||||
private $headerNames = [];
|
||||
/** @var string */
|
||||
private $protocol = '1.1';
|
||||
/** @var StreamInterface|null */
|
||||
private $stream;
|
||||
public function getProtocolVersion() : string
|
||||
public function getProtocolVersion()
|
||||
{
|
||||
return $this->protocol;
|
||||
}
|
||||
public function withProtocolVersion($version) : \YoastSEO_Vendor\Psr\Http\Message\MessageInterface
|
||||
public function withProtocolVersion($version)
|
||||
{
|
||||
if ($this->protocol === $version) {
|
||||
return $this;
|
||||
@@ -31,15 +29,15 @@ trait MessageTrait
|
||||
$new->protocol = $version;
|
||||
return $new;
|
||||
}
|
||||
public function getHeaders() : array
|
||||
public function getHeaders()
|
||||
{
|
||||
return $this->headers;
|
||||
}
|
||||
public function hasHeader($header) : bool
|
||||
public function hasHeader($header)
|
||||
{
|
||||
return isset($this->headerNames[\strtolower($header)]);
|
||||
}
|
||||
public function getHeader($header) : array
|
||||
public function getHeader($header)
|
||||
{
|
||||
$header = \strtolower($header);
|
||||
if (!isset($this->headerNames[$header])) {
|
||||
@@ -48,11 +46,11 @@ trait MessageTrait
|
||||
$header = $this->headerNames[$header];
|
||||
return $this->headers[$header];
|
||||
}
|
||||
public function getHeaderLine($header) : string
|
||||
public function getHeaderLine($header)
|
||||
{
|
||||
return \implode(', ', $this->getHeader($header));
|
||||
}
|
||||
public function withHeader($header, $value) : \YoastSEO_Vendor\Psr\Http\Message\MessageInterface
|
||||
public function withHeader($header, $value)
|
||||
{
|
||||
$this->assertHeader($header);
|
||||
$value = $this->normalizeHeaderValue($value);
|
||||
@@ -65,7 +63,7 @@ trait MessageTrait
|
||||
$new->headers[$header] = $value;
|
||||
return $new;
|
||||
}
|
||||
public function withAddedHeader($header, $value) : \YoastSEO_Vendor\Psr\Http\Message\MessageInterface
|
||||
public function withAddedHeader($header, $value)
|
||||
{
|
||||
$this->assertHeader($header);
|
||||
$value = $this->normalizeHeaderValue($value);
|
||||
@@ -80,7 +78,7 @@ trait MessageTrait
|
||||
}
|
||||
return $new;
|
||||
}
|
||||
public function withoutHeader($header) : \YoastSEO_Vendor\Psr\Http\Message\MessageInterface
|
||||
public function withoutHeader($header)
|
||||
{
|
||||
$normalized = \strtolower($header);
|
||||
if (!isset($this->headerNames[$normalized])) {
|
||||
@@ -91,14 +89,14 @@ trait MessageTrait
|
||||
unset($new->headers[$header], $new->headerNames[$normalized]);
|
||||
return $new;
|
||||
}
|
||||
public function getBody() : \YoastSEO_Vendor\Psr\Http\Message\StreamInterface
|
||||
public function getBody()
|
||||
{
|
||||
if (!$this->stream) {
|
||||
$this->stream = \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::streamFor('');
|
||||
}
|
||||
return $this->stream;
|
||||
}
|
||||
public function withBody(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $body) : \YoastSEO_Vendor\Psr\Http\Message\MessageInterface
|
||||
public function withBody(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $body)
|
||||
{
|
||||
if ($body === $this->stream) {
|
||||
return $this;
|
||||
@@ -107,15 +105,15 @@ trait MessageTrait
|
||||
$new->stream = $body;
|
||||
return $new;
|
||||
}
|
||||
/**
|
||||
* @param array<string|int, string|string[]> $headers
|
||||
*/
|
||||
private function setHeaders(array $headers) : void
|
||||
private function setHeaders(array $headers)
|
||||
{
|
||||
$this->headerNames = $this->headers = [];
|
||||
foreach ($headers as $header => $value) {
|
||||
// Numeric array keys are converted to int by PHP.
|
||||
$header = (string) $header;
|
||||
if (\is_int($header)) {
|
||||
// Numeric array keys are converted to int by PHP but having a header name '123' is not forbidden by the spec
|
||||
// and also allowed in withHeader(). So we need to cast it to string again for the following assertion to pass.
|
||||
$header = (string) $header;
|
||||
}
|
||||
$this->assertHeader($header);
|
||||
$value = $this->normalizeHeaderValue($value);
|
||||
$normalized = \strtolower($header);
|
||||
@@ -133,7 +131,7 @@ trait MessageTrait
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
private function normalizeHeaderValue($value) : array
|
||||
private function normalizeHeaderValue($value)
|
||||
{
|
||||
if (!\is_array($value)) {
|
||||
return $this->trimAndValidateHeaderValues([$value]);
|
||||
@@ -157,7 +155,7 @@ trait MessageTrait
|
||||
*
|
||||
* @see https://tools.ietf.org/html/rfc7230#section-3.2.4
|
||||
*/
|
||||
private function trimAndValidateHeaderValues(array $values) : array
|
||||
private function trimAndValidateHeaderValues(array $values)
|
||||
{
|
||||
return \array_map(function ($value) {
|
||||
if (!\is_scalar($value) && null !== $value) {
|
||||
@@ -172,17 +170,26 @@ trait MessageTrait
|
||||
* @see https://tools.ietf.org/html/rfc7230#section-3.2
|
||||
*
|
||||
* @param mixed $header
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function assertHeader($header) : void
|
||||
private function assertHeader($header)
|
||||
{
|
||||
if (!\is_string($header)) {
|
||||
throw new \InvalidArgumentException(\sprintf('Header name must be a string but %s provided.', \is_object($header) ? \get_class($header) : \gettype($header)));
|
||||
}
|
||||
if ($header === '') {
|
||||
throw new \InvalidArgumentException('Header name can not be empty.');
|
||||
}
|
||||
if (!\preg_match('/^[a-zA-Z0-9\'`#$%&*+.^_|~!-]+$/D', $header)) {
|
||||
throw new \InvalidArgumentException(\sprintf('"%s" is not valid header name.', $header));
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @param string $value
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @see https://tools.ietf.org/html/rfc7230#section-3.2
|
||||
*
|
||||
* field-value = *( field-content / obs-fold )
|
||||
@@ -192,7 +199,7 @@ trait MessageTrait
|
||||
* obs-text = %x80-FF
|
||||
* obs-fold = CRLF 1*( SP / HTAB )
|
||||
*/
|
||||
private function assertValue(string $value) : void
|
||||
private function assertValue($value)
|
||||
{
|
||||
// The regular expression intentionally does not support the obs-fold production, because as
|
||||
// per RFC 7230#3.2.4:
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,20 +1,18 @@
|
||||
<?php
|
||||
|
||||
declare (strict_types=1);
|
||||
namespace YoastSEO_Vendor\GuzzleHttp\Psr7;
|
||||
|
||||
use YoastSEO_Vendor\Psr\Http\Message\StreamInterface;
|
||||
/**
|
||||
* Stream that when read returns bytes for a streaming multipart or
|
||||
* multipart/form-data stream.
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
final class MultipartStream implements \YoastSEO_Vendor\Psr\Http\Message\StreamInterface
|
||||
class MultipartStream implements \YoastSEO_Vendor\Psr\Http\Message\StreamInterface
|
||||
{
|
||||
use StreamDecoratorTrait;
|
||||
/** @var string */
|
||||
private $boundary;
|
||||
/** @var StreamInterface */
|
||||
private $stream;
|
||||
/**
|
||||
* @param array $elements Array of associative arrays, each containing a
|
||||
* required "name" key mapping to the form field,
|
||||
@@ -27,25 +25,28 @@ final class MultipartStream implements \YoastSEO_Vendor\Psr\Http\Message\StreamI
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function __construct(array $elements = [], string $boundary = null)
|
||||
public function __construct(array $elements = [], $boundary = null)
|
||||
{
|
||||
$this->boundary = $boundary ?: \bin2hex(\random_bytes(20));
|
||||
$this->boundary = $boundary ?: \sha1(\uniqid('', \true));
|
||||
$this->stream = $this->createStream($elements);
|
||||
}
|
||||
public function getBoundary() : string
|
||||
/**
|
||||
* Get the boundary
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getBoundary()
|
||||
{
|
||||
return $this->boundary;
|
||||
}
|
||||
public function isWritable() : bool
|
||||
public function isWritable()
|
||||
{
|
||||
return \false;
|
||||
}
|
||||
/**
|
||||
* Get the headers needed before transferring the content of a POST file
|
||||
*
|
||||
* @param array<string, string> $headers
|
||||
*/
|
||||
private function getHeaders(array $headers) : string
|
||||
private function getHeaders(array $headers)
|
||||
{
|
||||
$str = '';
|
||||
foreach ($headers as $key => $value) {
|
||||
@@ -56,20 +57,17 @@ final class MultipartStream implements \YoastSEO_Vendor\Psr\Http\Message\StreamI
|
||||
/**
|
||||
* Create the aggregate stream that will be used to upload the POST data
|
||||
*/
|
||||
protected function createStream(array $elements = []) : \YoastSEO_Vendor\Psr\Http\Message\StreamInterface
|
||||
protected function createStream(array $elements)
|
||||
{
|
||||
$stream = new \YoastSEO_Vendor\GuzzleHttp\Psr7\AppendStream();
|
||||
foreach ($elements as $element) {
|
||||
if (!\is_array($element)) {
|
||||
throw new \UnexpectedValueException('An array is expected');
|
||||
}
|
||||
$this->addElement($stream, $element);
|
||||
}
|
||||
// Add the trailing boundary with CRLF
|
||||
$stream->addStream(\YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::streamFor("--{$this->boundary}--\r\n"));
|
||||
return $stream;
|
||||
}
|
||||
private function addElement(\YoastSEO_Vendor\GuzzleHttp\Psr7\AppendStream $stream, array $element) : void
|
||||
private function addElement(\YoastSEO_Vendor\GuzzleHttp\Psr7\AppendStream $stream, array $element)
|
||||
{
|
||||
foreach (['contents', 'name'] as $key) {
|
||||
if (!\array_key_exists($key, $element)) {
|
||||
@@ -79,16 +77,19 @@ final class MultipartStream implements \YoastSEO_Vendor\Psr\Http\Message\StreamI
|
||||
$element['contents'] = \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::streamFor($element['contents']);
|
||||
if (empty($element['filename'])) {
|
||||
$uri = $element['contents']->getMetadata('uri');
|
||||
if ($uri && \is_string($uri) && \substr($uri, 0, 6) !== 'php://' && \substr($uri, 0, 7) !== 'data://') {
|
||||
if (\substr($uri, 0, 6) !== 'php://') {
|
||||
$element['filename'] = $uri;
|
||||
}
|
||||
}
|
||||
[$body, $headers] = $this->createElement($element['name'], $element['contents'], $element['filename'] ?? null, $element['headers'] ?? []);
|
||||
list($body, $headers) = $this->createElement($element['name'], $element['contents'], isset($element['filename']) ? $element['filename'] : null, isset($element['headers']) ? $element['headers'] : []);
|
||||
$stream->addStream(\YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::streamFor($this->getHeaders($headers)));
|
||||
$stream->addStream($body);
|
||||
$stream->addStream(\YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::streamFor("\r\n"));
|
||||
}
|
||||
private function createElement(string $name, \YoastSEO_Vendor\Psr\Http\Message\StreamInterface $stream, ?string $filename, array $headers) : array
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
private function createElement($name, \YoastSEO_Vendor\Psr\Http\Message\StreamInterface $stream, $filename, array $headers)
|
||||
{
|
||||
// Set a default content-disposition header if one was no provided
|
||||
$disposition = $this->getHeader($headers, 'content-disposition');
|
||||
@@ -105,11 +106,13 @@ final class MultipartStream implements \YoastSEO_Vendor\Psr\Http\Message\StreamI
|
||||
// Set a default Content-Type if one was not supplied
|
||||
$type = $this->getHeader($headers, 'content-type');
|
||||
if (!$type && ($filename === '0' || $filename)) {
|
||||
$headers['Content-Type'] = \YoastSEO_Vendor\GuzzleHttp\Psr7\MimeType::fromFilename($filename) ?? 'application/octet-stream';
|
||||
if ($type = \YoastSEO_Vendor\GuzzleHttp\Psr7\MimeType::fromFilename($filename)) {
|
||||
$headers['Content-Type'] = $type;
|
||||
}
|
||||
}
|
||||
return [$stream, $headers];
|
||||
}
|
||||
private function getHeader(array $headers, string $key)
|
||||
private function getHeader(array $headers, $key)
|
||||
{
|
||||
$lowercaseHeader = \strtolower($key);
|
||||
foreach ($headers as $k => $v) {
|
||||
|
||||
@@ -1,22 +1,21 @@
|
||||
<?php
|
||||
|
||||
declare (strict_types=1);
|
||||
namespace YoastSEO_Vendor\GuzzleHttp\Psr7;
|
||||
|
||||
use YoastSEO_Vendor\Psr\Http\Message\StreamInterface;
|
||||
/**
|
||||
* Stream decorator that prevents a stream from being seeked.
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
final class NoSeekStream implements \YoastSEO_Vendor\Psr\Http\Message\StreamInterface
|
||||
class NoSeekStream implements \YoastSEO_Vendor\Psr\Http\Message\StreamInterface
|
||||
{
|
||||
use StreamDecoratorTrait;
|
||||
/** @var StreamInterface */
|
||||
private $stream;
|
||||
public function seek($offset, $whence = \SEEK_SET) : void
|
||||
public function seek($offset, $whence = \SEEK_SET)
|
||||
{
|
||||
throw new \RuntimeException('Cannot seek a NoSeekStream');
|
||||
}
|
||||
public function isSeekable() : bool
|
||||
public function isSeekable()
|
||||
{
|
||||
return \false;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare (strict_types=1);
|
||||
namespace YoastSEO_Vendor\GuzzleHttp\Psr7;
|
||||
|
||||
use YoastSEO_Vendor\Psr\Http\Message\StreamInterface;
|
||||
@@ -13,12 +12,14 @@ use YoastSEO_Vendor\Psr\Http\Message\StreamInterface;
|
||||
* returned by the provided callable is buffered internally until drained using
|
||||
* the read() function of the PumpStream. The provided callable MUST return
|
||||
* false when there is no more data to read.
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
final class PumpStream implements \YoastSEO_Vendor\Psr\Http\Message\StreamInterface
|
||||
class PumpStream implements \YoastSEO_Vendor\Psr\Http\Message\StreamInterface
|
||||
{
|
||||
/** @var callable|null */
|
||||
/** @var callable */
|
||||
private $source;
|
||||
/** @var int|null */
|
||||
/** @var int */
|
||||
private $size;
|
||||
/** @var int */
|
||||
private $tellPos = 0;
|
||||
@@ -27,81 +28,77 @@ final class PumpStream implements \YoastSEO_Vendor\Psr\Http\Message\StreamInterf
|
||||
/** @var BufferStream */
|
||||
private $buffer;
|
||||
/**
|
||||
* @param callable(int): (string|false|null) $source Source of the stream data. The callable MAY
|
||||
* accept an integer argument used to control the
|
||||
* amount of data to return. The callable MUST
|
||||
* return a string when called, or false|null on error
|
||||
* or EOF.
|
||||
* @param array{size?: int, metadata?: array} $options Stream options:
|
||||
* - metadata: Hash of metadata to use with stream.
|
||||
* - size: Size of the stream, if known.
|
||||
* @param callable $source Source of the stream data. The callable MAY
|
||||
* accept an integer argument used to control the
|
||||
* amount of data to return. The callable MUST
|
||||
* return a string when called, or false on error
|
||||
* or EOF.
|
||||
* @param array $options Stream options:
|
||||
* - metadata: Hash of metadata to use with stream.
|
||||
* - size: Size of the stream, if known.
|
||||
*/
|
||||
public function __construct(callable $source, array $options = [])
|
||||
{
|
||||
$this->source = $source;
|
||||
$this->size = $options['size'] ?? null;
|
||||
$this->metadata = $options['metadata'] ?? [];
|
||||
$this->size = isset($options['size']) ? $options['size'] : null;
|
||||
$this->metadata = isset($options['metadata']) ? $options['metadata'] : [];
|
||||
$this->buffer = new \YoastSEO_Vendor\GuzzleHttp\Psr7\BufferStream();
|
||||
}
|
||||
public function __toString() : string
|
||||
public function __toString()
|
||||
{
|
||||
try {
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::copyToString($this);
|
||||
} catch (\Throwable $e) {
|
||||
if (\PHP_VERSION_ID >= 70400) {
|
||||
throw $e;
|
||||
}
|
||||
\trigger_error(\sprintf('%s::__toString exception: %s', self::class, (string) $e), \E_USER_ERROR);
|
||||
} catch (\Exception $e) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
public function close() : void
|
||||
public function close()
|
||||
{
|
||||
$this->detach();
|
||||
}
|
||||
public function detach()
|
||||
{
|
||||
$this->tellPos = 0;
|
||||
$this->tellPos = \false;
|
||||
$this->source = null;
|
||||
return null;
|
||||
}
|
||||
public function getSize() : ?int
|
||||
public function getSize()
|
||||
{
|
||||
return $this->size;
|
||||
}
|
||||
public function tell() : int
|
||||
public function tell()
|
||||
{
|
||||
return $this->tellPos;
|
||||
}
|
||||
public function eof() : bool
|
||||
public function eof()
|
||||
{
|
||||
return $this->source === null;
|
||||
return !$this->source;
|
||||
}
|
||||
public function isSeekable() : bool
|
||||
public function isSeekable()
|
||||
{
|
||||
return \false;
|
||||
}
|
||||
public function rewind() : void
|
||||
public function rewind()
|
||||
{
|
||||
$this->seek(0);
|
||||
}
|
||||
public function seek($offset, $whence = \SEEK_SET) : void
|
||||
public function seek($offset, $whence = \SEEK_SET)
|
||||
{
|
||||
throw new \RuntimeException('Cannot seek a PumpStream');
|
||||
}
|
||||
public function isWritable() : bool
|
||||
public function isWritable()
|
||||
{
|
||||
return \false;
|
||||
}
|
||||
public function write($string) : int
|
||||
public function write($string)
|
||||
{
|
||||
throw new \RuntimeException('Cannot write to a PumpStream');
|
||||
}
|
||||
public function isReadable() : bool
|
||||
public function isReadable()
|
||||
{
|
||||
return \true;
|
||||
}
|
||||
public function read($length) : string
|
||||
public function read($length)
|
||||
{
|
||||
$data = $this->buffer->read($length);
|
||||
$readLen = \strlen($data);
|
||||
@@ -114,7 +111,7 @@ final class PumpStream implements \YoastSEO_Vendor\Psr\Http\Message\StreamInterf
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
public function getContents() : string
|
||||
public function getContents()
|
||||
{
|
||||
$result = '';
|
||||
while (!$this->eof()) {
|
||||
@@ -122,17 +119,14 @@ final class PumpStream implements \YoastSEO_Vendor\Psr\Http\Message\StreamInterf
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getMetadata($key = null)
|
||||
{
|
||||
if (!$key) {
|
||||
return $this->metadata;
|
||||
}
|
||||
return $this->metadata[$key] ?? null;
|
||||
return isset($this->metadata[$key]) ? $this->metadata[$key] : null;
|
||||
}
|
||||
private function pump(int $length) : void
|
||||
private function pump($length)
|
||||
{
|
||||
if ($this->source) {
|
||||
do {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare (strict_types=1);
|
||||
namespace YoastSEO_Vendor\GuzzleHttp\Psr7;
|
||||
|
||||
final class Query
|
||||
@@ -15,8 +14,10 @@ final class Query
|
||||
*
|
||||
* @param string $str Query string to parse
|
||||
* @param int|bool $urlEncoding How the query string is encoded
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function parse(string $str, $urlEncoding = \true) : array
|
||||
public static function parse($str, $urlEncoding = \true)
|
||||
{
|
||||
$result = [];
|
||||
if ($str === '') {
|
||||
@@ -24,7 +25,7 @@ final class Query
|
||||
}
|
||||
if ($urlEncoding === \true) {
|
||||
$decoder = function ($value) {
|
||||
return \rawurldecode(\str_replace('+', ' ', (string) $value));
|
||||
return \rawurldecode(\str_replace('+', ' ', $value));
|
||||
};
|
||||
} elseif ($urlEncoding === \PHP_QUERY_RFC3986) {
|
||||
$decoder = 'rawurldecode';
|
||||
@@ -39,7 +40,7 @@ final class Query
|
||||
$parts = \explode('=', $kvp, 2);
|
||||
$key = $decoder($parts[0]);
|
||||
$value = isset($parts[1]) ? $decoder($parts[1]) : null;
|
||||
if (!\array_key_exists($key, $result)) {
|
||||
if (!isset($result[$key])) {
|
||||
$result[$key] = $value;
|
||||
} else {
|
||||
if (!\is_array($result[$key])) {
|
||||
@@ -61,14 +62,16 @@ final class Query
|
||||
* @param int|false $encoding Set to false to not encode, PHP_QUERY_RFC3986
|
||||
* to encode using RFC3986, or PHP_QUERY_RFC1738
|
||||
* to encode using RFC1738.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function build(array $params, $encoding = \PHP_QUERY_RFC3986) : string
|
||||
public static function build(array $params, $encoding = \PHP_QUERY_RFC3986)
|
||||
{
|
||||
if (!$params) {
|
||||
return '';
|
||||
}
|
||||
if ($encoding === \false) {
|
||||
$encoder = function (string $str) : string {
|
||||
$encoder = function ($str) {
|
||||
return $str;
|
||||
};
|
||||
} elseif ($encoding === \PHP_QUERY_RFC3986) {
|
||||
@@ -80,20 +83,18 @@ final class Query
|
||||
}
|
||||
$qs = '';
|
||||
foreach ($params as $k => $v) {
|
||||
$k = $encoder((string) $k);
|
||||
$k = $encoder($k);
|
||||
if (!\is_array($v)) {
|
||||
$qs .= $k;
|
||||
$v = \is_bool($v) ? (int) $v : $v;
|
||||
if ($v !== null) {
|
||||
$qs .= '=' . $encoder((string) $v);
|
||||
$qs .= '=' . $encoder($v);
|
||||
}
|
||||
$qs .= '&';
|
||||
} else {
|
||||
foreach ($v as $vv) {
|
||||
$qs .= $k;
|
||||
$vv = \is_bool($vv) ? (int) $vv : $vv;
|
||||
if ($vv !== null) {
|
||||
$qs .= '=' . $encoder((string) $vv);
|
||||
$qs .= '=' . $encoder($vv);
|
||||
}
|
||||
$qs .= '&';
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare (strict_types=1);
|
||||
namespace YoastSEO_Vendor\GuzzleHttp\Psr7;
|
||||
|
||||
use InvalidArgumentException;
|
||||
@@ -22,11 +21,11 @@ class Request implements \YoastSEO_Vendor\Psr\Http\Message\RequestInterface
|
||||
/**
|
||||
* @param string $method HTTP method
|
||||
* @param string|UriInterface $uri URI
|
||||
* @param array<string, string|string[]> $headers Request headers
|
||||
* @param array $headers Request headers
|
||||
* @param string|resource|StreamInterface|null $body Request body
|
||||
* @param string $version Protocol version
|
||||
*/
|
||||
public function __construct(string $method, $uri, array $headers = [], $body = null, string $version = '1.1')
|
||||
public function __construct($method, $uri, array $headers = [], $body = null, $version = '1.1')
|
||||
{
|
||||
$this->assertMethod($method);
|
||||
if (!$uri instanceof \YoastSEO_Vendor\Psr\Http\Message\UriInterface) {
|
||||
@@ -43,13 +42,13 @@ class Request implements \YoastSEO_Vendor\Psr\Http\Message\RequestInterface
|
||||
$this->stream = \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::streamFor($body);
|
||||
}
|
||||
}
|
||||
public function getRequestTarget() : string
|
||||
public function getRequestTarget()
|
||||
{
|
||||
if ($this->requestTarget !== null) {
|
||||
return $this->requestTarget;
|
||||
}
|
||||
$target = $this->uri->getPath();
|
||||
if ($target === '') {
|
||||
if ($target == '') {
|
||||
$target = '/';
|
||||
}
|
||||
if ($this->uri->getQuery() != '') {
|
||||
@@ -57,7 +56,7 @@ class Request implements \YoastSEO_Vendor\Psr\Http\Message\RequestInterface
|
||||
}
|
||||
return $target;
|
||||
}
|
||||
public function withRequestTarget($requestTarget) : \YoastSEO_Vendor\Psr\Http\Message\RequestInterface
|
||||
public function withRequestTarget($requestTarget)
|
||||
{
|
||||
if (\preg_match('#\\s#', $requestTarget)) {
|
||||
throw new \InvalidArgumentException('Invalid request target provided; cannot contain whitespace');
|
||||
@@ -66,22 +65,22 @@ class Request implements \YoastSEO_Vendor\Psr\Http\Message\RequestInterface
|
||||
$new->requestTarget = $requestTarget;
|
||||
return $new;
|
||||
}
|
||||
public function getMethod() : string
|
||||
public function getMethod()
|
||||
{
|
||||
return $this->method;
|
||||
}
|
||||
public function withMethod($method) : \YoastSEO_Vendor\Psr\Http\Message\RequestInterface
|
||||
public function withMethod($method)
|
||||
{
|
||||
$this->assertMethod($method);
|
||||
$new = clone $this;
|
||||
$new->method = \strtoupper($method);
|
||||
return $new;
|
||||
}
|
||||
public function getUri() : \YoastSEO_Vendor\Psr\Http\Message\UriInterface
|
||||
public function getUri()
|
||||
{
|
||||
return $this->uri;
|
||||
}
|
||||
public function withUri(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri, $preserveHost = \false) : \YoastSEO_Vendor\Psr\Http\Message\RequestInterface
|
||||
public function withUri(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri, $preserveHost = \false)
|
||||
{
|
||||
if ($uri === $this->uri) {
|
||||
return $this;
|
||||
@@ -93,7 +92,7 @@ class Request implements \YoastSEO_Vendor\Psr\Http\Message\RequestInterface
|
||||
}
|
||||
return $new;
|
||||
}
|
||||
private function updateHostFromUri() : void
|
||||
private function updateHostFromUri()
|
||||
{
|
||||
$host = $this->uri->getHost();
|
||||
if ($host == '') {
|
||||
@@ -112,10 +111,7 @@ class Request implements \YoastSEO_Vendor\Psr\Http\Message\RequestInterface
|
||||
// See: http://tools.ietf.org/html/rfc7230#section-5.4
|
||||
$this->headers = [$header => [$host]] + $this->headers;
|
||||
}
|
||||
/**
|
||||
* @param mixed $method
|
||||
*/
|
||||
private function assertMethod($method) : void
|
||||
private function assertMethod($method)
|
||||
{
|
||||
if (!\is_string($method) || $method === '') {
|
||||
throw new \InvalidArgumentException('Method must be a non-empty string.');
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare (strict_types=1);
|
||||
namespace YoastSEO_Vendor\GuzzleHttp\Psr7;
|
||||
|
||||
use YoastSEO_Vendor\Psr\Http\Message\ResponseInterface;
|
||||
@@ -11,65 +10,64 @@ use YoastSEO_Vendor\Psr\Http\Message\StreamInterface;
|
||||
class Response implements \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface
|
||||
{
|
||||
use MessageTrait;
|
||||
/** Map of standard HTTP status code/reason phrases */
|
||||
private const PHRASES = [100 => 'Continue', 101 => 'Switching Protocols', 102 => 'Processing', 200 => 'OK', 201 => 'Created', 202 => 'Accepted', 203 => 'Non-Authoritative Information', 204 => 'No Content', 205 => 'Reset Content', 206 => 'Partial Content', 207 => 'Multi-status', 208 => 'Already Reported', 300 => 'Multiple Choices', 301 => 'Moved Permanently', 302 => 'Found', 303 => 'See Other', 304 => 'Not Modified', 305 => 'Use Proxy', 306 => 'Switch Proxy', 307 => 'Temporary Redirect', 308 => 'Permanent Redirect', 400 => 'Bad Request', 401 => 'Unauthorized', 402 => 'Payment Required', 403 => 'Forbidden', 404 => 'Not Found', 405 => 'Method Not Allowed', 406 => 'Not Acceptable', 407 => 'Proxy Authentication Required', 408 => 'Request Time-out', 409 => 'Conflict', 410 => 'Gone', 411 => 'Length Required', 412 => 'Precondition Failed', 413 => 'Request Entity Too Large', 414 => 'Request-URI Too Large', 415 => 'Unsupported Media Type', 416 => 'Requested range not satisfiable', 417 => 'Expectation Failed', 418 => 'I\'m a teapot', 422 => 'Unprocessable Entity', 423 => 'Locked', 424 => 'Failed Dependency', 425 => 'Unordered Collection', 426 => 'Upgrade Required', 428 => 'Precondition Required', 429 => 'Too Many Requests', 431 => 'Request Header Fields Too Large', 451 => 'Unavailable For Legal Reasons', 500 => 'Internal Server Error', 501 => 'Not Implemented', 502 => 'Bad Gateway', 503 => 'Service Unavailable', 504 => 'Gateway Time-out', 505 => 'HTTP Version not supported', 506 => 'Variant Also Negotiates', 507 => 'Insufficient Storage', 508 => 'Loop Detected', 510 => 'Not Extended', 511 => 'Network Authentication Required'];
|
||||
/** @var array Map of standard HTTP status code/reason phrases */
|
||||
private static $phrases = [100 => 'Continue', 101 => 'Switching Protocols', 102 => 'Processing', 200 => 'OK', 201 => 'Created', 202 => 'Accepted', 203 => 'Non-Authoritative Information', 204 => 'No Content', 205 => 'Reset Content', 206 => 'Partial Content', 207 => 'Multi-status', 208 => 'Already Reported', 300 => 'Multiple Choices', 301 => 'Moved Permanently', 302 => 'Found', 303 => 'See Other', 304 => 'Not Modified', 305 => 'Use Proxy', 306 => 'Switch Proxy', 307 => 'Temporary Redirect', 400 => 'Bad Request', 401 => 'Unauthorized', 402 => 'Payment Required', 403 => 'Forbidden', 404 => 'Not Found', 405 => 'Method Not Allowed', 406 => 'Not Acceptable', 407 => 'Proxy Authentication Required', 408 => 'Request Time-out', 409 => 'Conflict', 410 => 'Gone', 411 => 'Length Required', 412 => 'Precondition Failed', 413 => 'Request Entity Too Large', 414 => 'Request-URI Too Large', 415 => 'Unsupported Media Type', 416 => 'Requested range not satisfiable', 417 => 'Expectation Failed', 418 => 'I\'m a teapot', 422 => 'Unprocessable Entity', 423 => 'Locked', 424 => 'Failed Dependency', 425 => 'Unordered Collection', 426 => 'Upgrade Required', 428 => 'Precondition Required', 429 => 'Too Many Requests', 431 => 'Request Header Fields Too Large', 451 => 'Unavailable For Legal Reasons', 500 => 'Internal Server Error', 501 => 'Not Implemented', 502 => 'Bad Gateway', 503 => 'Service Unavailable', 504 => 'Gateway Time-out', 505 => 'HTTP Version not supported', 506 => 'Variant Also Negotiates', 507 => 'Insufficient Storage', 508 => 'Loop Detected', 511 => 'Network Authentication Required'];
|
||||
/** @var string */
|
||||
private $reasonPhrase;
|
||||
private $reasonPhrase = '';
|
||||
/** @var int */
|
||||
private $statusCode;
|
||||
private $statusCode = 200;
|
||||
/**
|
||||
* @param int $status Status code
|
||||
* @param array<string, string|string[]> $headers Response headers
|
||||
* @param array $headers Response headers
|
||||
* @param string|resource|StreamInterface|null $body Response body
|
||||
* @param string $version Protocol version
|
||||
* @param string|null $reason Reason phrase (when empty a default will be used based on the status code)
|
||||
*/
|
||||
public function __construct(int $status = 200, array $headers = [], $body = null, string $version = '1.1', string $reason = null)
|
||||
public function __construct($status = 200, array $headers = [], $body = null, $version = '1.1', $reason = null)
|
||||
{
|
||||
$this->assertStatusCodeIsInteger($status);
|
||||
$status = (int) $status;
|
||||
$this->assertStatusCodeRange($status);
|
||||
$this->statusCode = $status;
|
||||
if ($body !== '' && $body !== null) {
|
||||
$this->stream = \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::streamFor($body);
|
||||
}
|
||||
$this->setHeaders($headers);
|
||||
if ($reason == '' && isset(self::PHRASES[$this->statusCode])) {
|
||||
$this->reasonPhrase = self::PHRASES[$this->statusCode];
|
||||
if ($reason == '' && isset(self::$phrases[$this->statusCode])) {
|
||||
$this->reasonPhrase = self::$phrases[$this->statusCode];
|
||||
} else {
|
||||
$this->reasonPhrase = (string) $reason;
|
||||
}
|
||||
$this->protocol = $version;
|
||||
}
|
||||
public function getStatusCode() : int
|
||||
public function getStatusCode()
|
||||
{
|
||||
return $this->statusCode;
|
||||
}
|
||||
public function getReasonPhrase() : string
|
||||
public function getReasonPhrase()
|
||||
{
|
||||
return $this->reasonPhrase;
|
||||
}
|
||||
public function withStatus($code, $reasonPhrase = '') : \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface
|
||||
public function withStatus($code, $reasonPhrase = '')
|
||||
{
|
||||
$this->assertStatusCodeIsInteger($code);
|
||||
$code = (int) $code;
|
||||
$this->assertStatusCodeRange($code);
|
||||
$new = clone $this;
|
||||
$new->statusCode = $code;
|
||||
if ($reasonPhrase == '' && isset(self::PHRASES[$new->statusCode])) {
|
||||
$reasonPhrase = self::PHRASES[$new->statusCode];
|
||||
if ($reasonPhrase == '' && isset(self::$phrases[$new->statusCode])) {
|
||||
$reasonPhrase = self::$phrases[$new->statusCode];
|
||||
}
|
||||
$new->reasonPhrase = (string) $reasonPhrase;
|
||||
return $new;
|
||||
}
|
||||
/**
|
||||
* @param mixed $statusCode
|
||||
*/
|
||||
private function assertStatusCodeIsInteger($statusCode) : void
|
||||
private function assertStatusCodeIsInteger($statusCode)
|
||||
{
|
||||
if (\filter_var($statusCode, \FILTER_VALIDATE_INT) === \false) {
|
||||
throw new \InvalidArgumentException('Status code must be an integer value.');
|
||||
}
|
||||
}
|
||||
private function assertStatusCodeRange(int $statusCode) : void
|
||||
private function assertStatusCodeRange($statusCode)
|
||||
{
|
||||
if ($statusCode < 100 || $statusCode >= 600) {
|
||||
throw new \InvalidArgumentException('Status code must be an integer value between 1xx and 5xx.');
|
||||
|
||||
@@ -1,22 +1,19 @@
|
||||
<?php
|
||||
|
||||
declare (strict_types=1);
|
||||
namespace YoastSEO_Vendor\GuzzleHttp\Psr7;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class Rfc7230
|
||||
{
|
||||
/**
|
||||
* Header related regular expressions (based on amphp/http package)
|
||||
* Header related regular expressions (copied from amphp/http package)
|
||||
* (Note: once we require PHP 7.x we could just depend on the upstream package)
|
||||
*
|
||||
* Note: header delimiter (\r\n) is modified to \r?\n to accept line feed only delimiters for BC reasons.
|
||||
*
|
||||
* @see https://github.com/amphp/http/blob/v1.0.1/src/Rfc7230.php#L12-L15
|
||||
* @link https://github.com/amphp/http/blob/v1.0.1/src/Rfc7230.php#L12-L15
|
||||
*
|
||||
* @license https://github.com/amphp/http/blob/v1.0.1/LICENSE
|
||||
*/
|
||||
public const HEADER_REGEX = "(^([^()<>@,;:\\\"/[\\]?={}\x01- ]++):[ \t]*+((?:[ \t]*+[!-~\x80-\xff]++)*+)[ \t]*+\r?\n)m";
|
||||
public const HEADER_FOLD_REGEX = "(\r?\n[ \t]++)";
|
||||
const HEADER_REGEX = "(^([^()<>@,;:\\\"/[\\]?={}\x01- ]++):[ \t]*+((?:[ \t]*+[!-~\x80-\xff]++)*+)[ \t]*+\r?\n)m";
|
||||
const HEADER_FOLD_REGEX = "(\r?\n[ \t]++)";
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare (strict_types=1);
|
||||
namespace YoastSEO_Vendor\GuzzleHttp\Psr7;
|
||||
|
||||
use InvalidArgumentException;
|
||||
@@ -51,12 +50,12 @@ class ServerRequest extends \YoastSEO_Vendor\GuzzleHttp\Psr7\Request implements
|
||||
/**
|
||||
* @param string $method HTTP method
|
||||
* @param string|UriInterface $uri URI
|
||||
* @param array<string, string|string[]> $headers Request headers
|
||||
* @param array $headers Request headers
|
||||
* @param string|resource|StreamInterface|null $body Request body
|
||||
* @param string $version Protocol version
|
||||
* @param array $serverParams Typically the $_SERVER superglobal
|
||||
*/
|
||||
public function __construct(string $method, $uri, array $headers = [], $body = null, string $version = '1.1', array $serverParams = [])
|
||||
public function __construct($method, $uri, array $headers = [], $body = null, $version = '1.1', array $serverParams = [])
|
||||
{
|
||||
$this->serverParams = $serverParams;
|
||||
parent::__construct($method, $uri, $headers, $body, $version);
|
||||
@@ -64,11 +63,13 @@ class ServerRequest extends \YoastSEO_Vendor\GuzzleHttp\Psr7\Request implements
|
||||
/**
|
||||
* Return an UploadedFile instance array.
|
||||
*
|
||||
* @param array $files An array which respect $_FILES structure
|
||||
* @param array $files A array which respect $_FILES structure
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws InvalidArgumentException for unrecognized values
|
||||
*/
|
||||
public static function normalizeFiles(array $files) : array
|
||||
public static function normalizeFiles(array $files)
|
||||
{
|
||||
$normalized = [];
|
||||
foreach ($files as $key => $value) {
|
||||
@@ -93,7 +94,7 @@ class ServerRequest extends \YoastSEO_Vendor\GuzzleHttp\Psr7\Request implements
|
||||
*
|
||||
* @param array $value $_FILES struct
|
||||
*
|
||||
* @return UploadedFileInterface|UploadedFileInterface[]
|
||||
* @return array|UploadedFileInterface
|
||||
*/
|
||||
private static function createUploadedFileFromSpec(array $value)
|
||||
{
|
||||
@@ -108,13 +109,15 @@ class ServerRequest extends \YoastSEO_Vendor\GuzzleHttp\Psr7\Request implements
|
||||
* Loops through all nested files and returns a normalized array of
|
||||
* UploadedFileInterface instances.
|
||||
*
|
||||
* @param array $files
|
||||
*
|
||||
* @return UploadedFileInterface[]
|
||||
*/
|
||||
private static function normalizeNestedFileSpec(array $files = []) : array
|
||||
private static function normalizeNestedFileSpec(array $files = [])
|
||||
{
|
||||
$normalizedFiles = [];
|
||||
foreach (\array_keys($files['tmp_name']) as $key) {
|
||||
$spec = ['tmp_name' => $files['tmp_name'][$key], 'size' => $files['size'][$key] ?? null, 'error' => $files['error'][$key] ?? null, 'name' => $files['name'][$key] ?? null, 'type' => $files['type'][$key] ?? null];
|
||||
$spec = ['tmp_name' => $files['tmp_name'][$key], 'size' => $files['size'][$key], 'error' => $files['error'][$key], 'name' => $files['name'][$key], 'type' => $files['type'][$key]];
|
||||
$normalizedFiles[$key] = self::createUploadedFileFromSpec($spec);
|
||||
}
|
||||
return $normalizedFiles;
|
||||
@@ -126,10 +129,12 @@ class ServerRequest extends \YoastSEO_Vendor\GuzzleHttp\Psr7\Request implements
|
||||
* $_COOKIE
|
||||
* $_FILES
|
||||
* $_SERVER
|
||||
*
|
||||
* @return ServerRequestInterface
|
||||
*/
|
||||
public static function fromGlobals() : \YoastSEO_Vendor\Psr\Http\Message\ServerRequestInterface
|
||||
public static function fromGlobals()
|
||||
{
|
||||
$method = $_SERVER['REQUEST_METHOD'] ?? 'GET';
|
||||
$method = isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : 'GET';
|
||||
$headers = \getallheaders();
|
||||
$uri = self::getUriFromGlobals();
|
||||
$body = new \YoastSEO_Vendor\GuzzleHttp\Psr7\CachingStream(new \YoastSEO_Vendor\GuzzleHttp\Psr7\LazyOpenStream('php://input', 'r+'));
|
||||
@@ -137,27 +142,29 @@ class ServerRequest extends \YoastSEO_Vendor\GuzzleHttp\Psr7\Request implements
|
||||
$serverRequest = new \YoastSEO_Vendor\GuzzleHttp\Psr7\ServerRequest($method, $uri, $headers, $body, $protocol, $_SERVER);
|
||||
return $serverRequest->withCookieParams($_COOKIE)->withQueryParams($_GET)->withParsedBody($_POST)->withUploadedFiles(self::normalizeFiles($_FILES));
|
||||
}
|
||||
private static function extractHostAndPortFromAuthority(string $authority) : array
|
||||
private static function extractHostAndPortFromAuthority($authority)
|
||||
{
|
||||
$uri = 'http://' . $authority;
|
||||
$parts = \parse_url($uri);
|
||||
if (\false === $parts) {
|
||||
return [null, null];
|
||||
}
|
||||
$host = $parts['host'] ?? null;
|
||||
$port = $parts['port'] ?? null;
|
||||
$host = isset($parts['host']) ? $parts['host'] : null;
|
||||
$port = isset($parts['port']) ? $parts['port'] : null;
|
||||
return [$host, $port];
|
||||
}
|
||||
/**
|
||||
* Get a Uri populated with values from $_SERVER.
|
||||
*
|
||||
* @return UriInterface
|
||||
*/
|
||||
public static function getUriFromGlobals() : \YoastSEO_Vendor\Psr\Http\Message\UriInterface
|
||||
public static function getUriFromGlobals()
|
||||
{
|
||||
$uri = new \YoastSEO_Vendor\GuzzleHttp\Psr7\Uri('');
|
||||
$uri = $uri->withScheme(!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' ? 'https' : 'http');
|
||||
$hasPort = \false;
|
||||
if (isset($_SERVER['HTTP_HOST'])) {
|
||||
[$host, $port] = self::extractHostAndPortFromAuthority($_SERVER['HTTP_HOST']);
|
||||
list($host, $port) = self::extractHostAndPortFromAuthority($_SERVER['HTTP_HOST']);
|
||||
if ($host !== null) {
|
||||
$uri = $uri->withHost($host);
|
||||
}
|
||||
@@ -187,59 +194,86 @@ class ServerRequest extends \YoastSEO_Vendor\GuzzleHttp\Psr7\Request implements
|
||||
}
|
||||
return $uri;
|
||||
}
|
||||
public function getServerParams() : array
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getServerParams()
|
||||
{
|
||||
return $this->serverParams;
|
||||
}
|
||||
public function getUploadedFiles() : array
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getUploadedFiles()
|
||||
{
|
||||
return $this->uploadedFiles;
|
||||
}
|
||||
public function withUploadedFiles(array $uploadedFiles) : \YoastSEO_Vendor\Psr\Http\Message\ServerRequestInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function withUploadedFiles(array $uploadedFiles)
|
||||
{
|
||||
$new = clone $this;
|
||||
$new->uploadedFiles = $uploadedFiles;
|
||||
return $new;
|
||||
}
|
||||
public function getCookieParams() : array
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCookieParams()
|
||||
{
|
||||
return $this->cookieParams;
|
||||
}
|
||||
public function withCookieParams(array $cookies) : \YoastSEO_Vendor\Psr\Http\Message\ServerRequestInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function withCookieParams(array $cookies)
|
||||
{
|
||||
$new = clone $this;
|
||||
$new->cookieParams = $cookies;
|
||||
return $new;
|
||||
}
|
||||
public function getQueryParams() : array
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getQueryParams()
|
||||
{
|
||||
return $this->queryParams;
|
||||
}
|
||||
public function withQueryParams(array $query) : \YoastSEO_Vendor\Psr\Http\Message\ServerRequestInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function withQueryParams(array $query)
|
||||
{
|
||||
$new = clone $this;
|
||||
$new->queryParams = $query;
|
||||
return $new;
|
||||
}
|
||||
/**
|
||||
* @return array|object|null
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getParsedBody()
|
||||
{
|
||||
return $this->parsedBody;
|
||||
}
|
||||
public function withParsedBody($data) : \YoastSEO_Vendor\Psr\Http\Message\ServerRequestInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function withParsedBody($data)
|
||||
{
|
||||
$new = clone $this;
|
||||
$new->parsedBody = $data;
|
||||
return $new;
|
||||
}
|
||||
public function getAttributes() : array
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getAttributes()
|
||||
{
|
||||
return $this->attributes;
|
||||
}
|
||||
/**
|
||||
* @return mixed
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getAttribute($attribute, $default = null)
|
||||
{
|
||||
@@ -248,13 +282,19 @@ class ServerRequest extends \YoastSEO_Vendor\GuzzleHttp\Psr7\Request implements
|
||||
}
|
||||
return $this->attributes[$attribute];
|
||||
}
|
||||
public function withAttribute($attribute, $value) : \YoastSEO_Vendor\Psr\Http\Message\ServerRequestInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function withAttribute($attribute, $value)
|
||||
{
|
||||
$new = clone $this;
|
||||
$new->attributes[$attribute] = $value;
|
||||
return $new;
|
||||
}
|
||||
public function withoutAttribute($attribute) : \YoastSEO_Vendor\Psr\Http\Message\ServerRequestInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function withoutAttribute($attribute)
|
||||
{
|
||||
if (\false === \array_key_exists($attribute, $this->attributes)) {
|
||||
return $this;
|
||||
|
||||
@@ -1,33 +1,31 @@
|
||||
<?php
|
||||
|
||||
declare (strict_types=1);
|
||||
namespace YoastSEO_Vendor\GuzzleHttp\Psr7;
|
||||
|
||||
use YoastSEO_Vendor\Psr\Http\Message\StreamInterface;
|
||||
/**
|
||||
* PHP stream implementation.
|
||||
*
|
||||
* @var $stream
|
||||
*/
|
||||
class Stream implements \YoastSEO_Vendor\Psr\Http\Message\StreamInterface
|
||||
{
|
||||
/**
|
||||
* Resource modes.
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @see http://php.net/manual/function.fopen.php
|
||||
* @see http://php.net/manual/en/function.gzopen.php
|
||||
*/
|
||||
private const READABLE_MODES = '/r|a\\+|ab\\+|w\\+|wb\\+|x\\+|xb\\+|c\\+|cb\\+/';
|
||||
private const WRITABLE_MODES = '/a|w|r\\+|rb\\+|rw|x|c/';
|
||||
/** @var resource */
|
||||
const READABLE_MODES = '/r|a\\+|ab\\+|w\\+|wb\\+|x\\+|xb\\+|c\\+|cb\\+/';
|
||||
const WRITABLE_MODES = '/a|w|r\\+|rb\\+|rw|x|c/';
|
||||
private $stream;
|
||||
/** @var int|null */
|
||||
private $size;
|
||||
/** @var bool */
|
||||
private $seekable;
|
||||
/** @var bool */
|
||||
private $readable;
|
||||
/** @var bool */
|
||||
private $writable;
|
||||
/** @var string|null */
|
||||
private $uri;
|
||||
/** @var mixed[] */
|
||||
private $customMetadata;
|
||||
/**
|
||||
* This constructor accepts an associative array of options.
|
||||
@@ -38,12 +36,12 @@ class Stream implements \YoastSEO_Vendor\Psr\Http\Message\StreamInterface
|
||||
* - metadata: (array) Any additional metadata to return when the metadata
|
||||
* of the stream is accessed.
|
||||
*
|
||||
* @param resource $stream Stream resource to wrap.
|
||||
* @param array{size?: int, metadata?: array} $options Associative array of options.
|
||||
* @param resource $stream Stream resource to wrap.
|
||||
* @param array $options Associative array of options.
|
||||
*
|
||||
* @throws \InvalidArgumentException if the stream is not a stream resource
|
||||
*/
|
||||
public function __construct($stream, array $options = [])
|
||||
public function __construct($stream, $options = [])
|
||||
{
|
||||
if (!\is_resource($stream)) {
|
||||
throw new \InvalidArgumentException('Stream must be a resource');
|
||||
@@ -51,7 +49,7 @@ class Stream implements \YoastSEO_Vendor\Psr\Http\Message\StreamInterface
|
||||
if (isset($options['size'])) {
|
||||
$this->size = $options['size'];
|
||||
}
|
||||
$this->customMetadata = $options['metadata'] ?? [];
|
||||
$this->customMetadata = isset($options['metadata']) ? $options['metadata'] : [];
|
||||
$this->stream = $stream;
|
||||
$meta = \stream_get_meta_data($this->stream);
|
||||
$this->seekable = $meta['seekable'];
|
||||
@@ -66,32 +64,29 @@ class Stream implements \YoastSEO_Vendor\Psr\Http\Message\StreamInterface
|
||||
{
|
||||
$this->close();
|
||||
}
|
||||
public function __toString() : string
|
||||
public function __toString()
|
||||
{
|
||||
try {
|
||||
if ($this->isSeekable()) {
|
||||
$this->seek(0);
|
||||
}
|
||||
return $this->getContents();
|
||||
} catch (\Throwable $e) {
|
||||
if (\PHP_VERSION_ID >= 70400) {
|
||||
throw $e;
|
||||
}
|
||||
\trigger_error(\sprintf('%s::__toString exception: %s', self::class, (string) $e), \E_USER_ERROR);
|
||||
} catch (\Exception $e) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
public function getContents() : string
|
||||
public function getContents()
|
||||
{
|
||||
if (!isset($this->stream)) {
|
||||
throw new \RuntimeException('Stream is detached');
|
||||
}
|
||||
if (!$this->readable) {
|
||||
throw new \RuntimeException('Cannot read from non-readable stream');
|
||||
$contents = \stream_get_contents($this->stream);
|
||||
if ($contents === \false) {
|
||||
throw new \RuntimeException('Unable to read stream contents');
|
||||
}
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::tryGetContents($this->stream);
|
||||
return $contents;
|
||||
}
|
||||
public function close() : void
|
||||
public function close()
|
||||
{
|
||||
if (isset($this->stream)) {
|
||||
if (\is_resource($this->stream)) {
|
||||
@@ -111,7 +106,7 @@ class Stream implements \YoastSEO_Vendor\Psr\Http\Message\StreamInterface
|
||||
$this->readable = $this->writable = $this->seekable = \false;
|
||||
return $result;
|
||||
}
|
||||
public function getSize() : ?int
|
||||
public function getSize()
|
||||
{
|
||||
if ($this->size !== null) {
|
||||
return $this->size;
|
||||
@@ -124,32 +119,32 @@ class Stream implements \YoastSEO_Vendor\Psr\Http\Message\StreamInterface
|
||||
\clearstatcache(\true, $this->uri);
|
||||
}
|
||||
$stats = \fstat($this->stream);
|
||||
if (\is_array($stats) && isset($stats['size'])) {
|
||||
if (isset($stats['size'])) {
|
||||
$this->size = $stats['size'];
|
||||
return $this->size;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public function isReadable() : bool
|
||||
public function isReadable()
|
||||
{
|
||||
return $this->readable;
|
||||
}
|
||||
public function isWritable() : bool
|
||||
public function isWritable()
|
||||
{
|
||||
return $this->writable;
|
||||
}
|
||||
public function isSeekable() : bool
|
||||
public function isSeekable()
|
||||
{
|
||||
return $this->seekable;
|
||||
}
|
||||
public function eof() : bool
|
||||
public function eof()
|
||||
{
|
||||
if (!isset($this->stream)) {
|
||||
throw new \RuntimeException('Stream is detached');
|
||||
}
|
||||
return \feof($this->stream);
|
||||
}
|
||||
public function tell() : int
|
||||
public function tell()
|
||||
{
|
||||
if (!isset($this->stream)) {
|
||||
throw new \RuntimeException('Stream is detached');
|
||||
@@ -160,11 +155,11 @@ class Stream implements \YoastSEO_Vendor\Psr\Http\Message\StreamInterface
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
public function rewind() : void
|
||||
public function rewind()
|
||||
{
|
||||
$this->seek(0);
|
||||
}
|
||||
public function seek($offset, $whence = \SEEK_SET) : void
|
||||
public function seek($offset, $whence = \SEEK_SET)
|
||||
{
|
||||
$whence = (int) $whence;
|
||||
if (!isset($this->stream)) {
|
||||
@@ -177,7 +172,7 @@ class Stream implements \YoastSEO_Vendor\Psr\Http\Message\StreamInterface
|
||||
throw new \RuntimeException('Unable to seek to stream position ' . $offset . ' with whence ' . \var_export($whence, \true));
|
||||
}
|
||||
}
|
||||
public function read($length) : string
|
||||
public function read($length)
|
||||
{
|
||||
if (!isset($this->stream)) {
|
||||
throw new \RuntimeException('Stream is detached');
|
||||
@@ -191,17 +186,13 @@ class Stream implements \YoastSEO_Vendor\Psr\Http\Message\StreamInterface
|
||||
if (0 === $length) {
|
||||
return '';
|
||||
}
|
||||
try {
|
||||
$string = \fread($this->stream, $length);
|
||||
} catch (\Exception $e) {
|
||||
throw new \RuntimeException('Unable to read from stream', 0, $e);
|
||||
}
|
||||
$string = \fread($this->stream, $length);
|
||||
if (\false === $string) {
|
||||
throw new \RuntimeException('Unable to read from stream');
|
||||
}
|
||||
return $string;
|
||||
}
|
||||
public function write($string) : int
|
||||
public function write($string)
|
||||
{
|
||||
if (!isset($this->stream)) {
|
||||
throw new \RuntimeException('Stream is detached');
|
||||
@@ -217,9 +208,6 @@ class Stream implements \YoastSEO_Vendor\Psr\Http\Message\StreamInterface
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getMetadata($key = null)
|
||||
{
|
||||
if (!isset($this->stream)) {
|
||||
@@ -230,6 +218,6 @@ class Stream implements \YoastSEO_Vendor\Psr\Http\Message\StreamInterface
|
||||
return $this->customMetadata[$key];
|
||||
}
|
||||
$meta = \stream_get_meta_data($this->stream);
|
||||
return $meta[$key] ?? null;
|
||||
return isset($meta[$key]) ? $meta[$key] : null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare (strict_types=1);
|
||||
namespace YoastSEO_Vendor\GuzzleHttp\Psr7;
|
||||
|
||||
use YoastSEO_Vendor\Psr\Http\Message\StreamInterface;
|
||||
/**
|
||||
* Stream decorator trait
|
||||
*
|
||||
* @property StreamInterface $stream
|
||||
* @property StreamInterface stream
|
||||
*/
|
||||
trait StreamDecoratorTrait
|
||||
{
|
||||
@@ -22,55 +21,53 @@ trait StreamDecoratorTrait
|
||||
* Magic method used to create a new stream if streams are not added in
|
||||
* the constructor of a decorator (e.g., LazyOpenStream).
|
||||
*
|
||||
* @param string $name Name of the property (allows "stream" only).
|
||||
*
|
||||
* @return StreamInterface
|
||||
*/
|
||||
public function __get(string $name)
|
||||
public function __get($name)
|
||||
{
|
||||
if ($name === 'stream') {
|
||||
if ($name == 'stream') {
|
||||
$this->stream = $this->createStream();
|
||||
return $this->stream;
|
||||
}
|
||||
throw new \UnexpectedValueException("{$name} not found on class");
|
||||
}
|
||||
public function __toString() : string
|
||||
public function __toString()
|
||||
{
|
||||
try {
|
||||
if ($this->isSeekable()) {
|
||||
$this->seek(0);
|
||||
}
|
||||
return $this->getContents();
|
||||
} catch (\Throwable $e) {
|
||||
if (\PHP_VERSION_ID >= 70400) {
|
||||
throw $e;
|
||||
}
|
||||
\trigger_error(\sprintf('%s::__toString exception: %s', self::class, (string) $e), \E_USER_ERROR);
|
||||
} catch (\Exception $e) {
|
||||
// Really, PHP? https://bugs.php.net/bug.php?id=53648
|
||||
\trigger_error('StreamDecorator::__toString exception: ' . (string) $e, \E_USER_ERROR);
|
||||
return '';
|
||||
}
|
||||
}
|
||||
public function getContents() : string
|
||||
public function getContents()
|
||||
{
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::copyToString($this);
|
||||
}
|
||||
/**
|
||||
* Allow decorators to implement custom methods
|
||||
*
|
||||
* @param string $method Missing method name
|
||||
* @param array $args Method arguments
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function __call(string $method, array $args)
|
||||
public function __call($method, array $args)
|
||||
{
|
||||
/** @var callable $callable */
|
||||
$callable = [$this->stream, $method];
|
||||
$result = \call_user_func_array($callable, $args);
|
||||
$result = \call_user_func_array([$this->stream, $method], $args);
|
||||
// Always return the wrapped object if the result is a return $this
|
||||
return $result === $this->stream ? $this : $result;
|
||||
}
|
||||
public function close() : void
|
||||
public function close()
|
||||
{
|
||||
$this->stream->close();
|
||||
}
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getMetadata($key = null)
|
||||
{
|
||||
return $this->stream->getMetadata($key);
|
||||
@@ -79,52 +76,54 @@ trait StreamDecoratorTrait
|
||||
{
|
||||
return $this->stream->detach();
|
||||
}
|
||||
public function getSize() : ?int
|
||||
public function getSize()
|
||||
{
|
||||
return $this->stream->getSize();
|
||||
}
|
||||
public function eof() : bool
|
||||
public function eof()
|
||||
{
|
||||
return $this->stream->eof();
|
||||
}
|
||||
public function tell() : int
|
||||
public function tell()
|
||||
{
|
||||
return $this->stream->tell();
|
||||
}
|
||||
public function isReadable() : bool
|
||||
public function isReadable()
|
||||
{
|
||||
return $this->stream->isReadable();
|
||||
}
|
||||
public function isWritable() : bool
|
||||
public function isWritable()
|
||||
{
|
||||
return $this->stream->isWritable();
|
||||
}
|
||||
public function isSeekable() : bool
|
||||
public function isSeekable()
|
||||
{
|
||||
return $this->stream->isSeekable();
|
||||
}
|
||||
public function rewind() : void
|
||||
public function rewind()
|
||||
{
|
||||
$this->seek(0);
|
||||
}
|
||||
public function seek($offset, $whence = \SEEK_SET) : void
|
||||
public function seek($offset, $whence = \SEEK_SET)
|
||||
{
|
||||
$this->stream->seek($offset, $whence);
|
||||
}
|
||||
public function read($length) : string
|
||||
public function read($length)
|
||||
{
|
||||
return $this->stream->read($length);
|
||||
}
|
||||
public function write($string) : int
|
||||
public function write($string)
|
||||
{
|
||||
return $this->stream->write($string);
|
||||
}
|
||||
/**
|
||||
* Implement in subclasses to dynamically create streams when requested.
|
||||
*
|
||||
* @return StreamInterface
|
||||
*
|
||||
* @throws \BadMethodCallException
|
||||
*/
|
||||
protected function createStream() : \YoastSEO_Vendor\Psr\Http\Message\StreamInterface
|
||||
protected function createStream()
|
||||
{
|
||||
throw new \BadMethodCallException('Not implemented');
|
||||
}
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
<?php
|
||||
|
||||
declare (strict_types=1);
|
||||
namespace YoastSEO_Vendor\GuzzleHttp\Psr7;
|
||||
|
||||
use YoastSEO_Vendor\Psr\Http\Message\StreamInterface;
|
||||
/**
|
||||
* Converts Guzzle streams into PHP stream resources.
|
||||
*
|
||||
* @see https://www.php.net/streamwrapper
|
||||
* @final
|
||||
*/
|
||||
final class StreamWrapper
|
||||
class StreamWrapper
|
||||
{
|
||||
/** @var resource */
|
||||
public $context;
|
||||
@@ -36,11 +35,13 @@ final class StreamWrapper
|
||||
} else {
|
||||
throw new \InvalidArgumentException('The stream must be readable, ' . 'writable, or both.');
|
||||
}
|
||||
return \fopen('guzzle://stream', $mode, \false, self::createStreamContext($stream));
|
||||
return \fopen('guzzle://stream', $mode, null, self::createStreamContext($stream));
|
||||
}
|
||||
/**
|
||||
* Creates a stream context that can be used to open a stream as a php stream resource.
|
||||
*
|
||||
* @param StreamInterface $stream
|
||||
*
|
||||
* @return resource
|
||||
*/
|
||||
public static function createStreamContext(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $stream)
|
||||
@@ -50,13 +51,13 @@ final class StreamWrapper
|
||||
/**
|
||||
* Registers the stream wrapper if needed
|
||||
*/
|
||||
public static function register() : void
|
||||
public static function register()
|
||||
{
|
||||
if (!\in_array('guzzle', \stream_get_wrappers())) {
|
||||
\stream_wrapper_register('guzzle', __CLASS__);
|
||||
}
|
||||
}
|
||||
public function stream_open(string $path, string $mode, int $options, string &$opened_path = null) : bool
|
||||
public function stream_open($path, $mode, $options, &$opened_path)
|
||||
{
|
||||
$options = \stream_context_get_options($this->context);
|
||||
if (!isset($options['guzzle']['stream'])) {
|
||||
@@ -66,48 +67,38 @@ final class StreamWrapper
|
||||
$this->stream = $options['guzzle']['stream'];
|
||||
return \true;
|
||||
}
|
||||
public function stream_read(int $count) : string
|
||||
public function stream_read($count)
|
||||
{
|
||||
return $this->stream->read($count);
|
||||
}
|
||||
public function stream_write(string $data) : int
|
||||
public function stream_write($data)
|
||||
{
|
||||
return $this->stream->write($data);
|
||||
return (int) $this->stream->write($data);
|
||||
}
|
||||
public function stream_tell() : int
|
||||
public function stream_tell()
|
||||
{
|
||||
return $this->stream->tell();
|
||||
}
|
||||
public function stream_eof() : bool
|
||||
public function stream_eof()
|
||||
{
|
||||
return $this->stream->eof();
|
||||
}
|
||||
public function stream_seek(int $offset, int $whence) : bool
|
||||
public function stream_seek($offset, $whence)
|
||||
{
|
||||
$this->stream->seek($offset, $whence);
|
||||
return \true;
|
||||
}
|
||||
/**
|
||||
* @return resource|false
|
||||
*/
|
||||
public function stream_cast(int $cast_as)
|
||||
public function stream_cast($cast_as)
|
||||
{
|
||||
$stream = clone $this->stream;
|
||||
$resource = $stream->detach();
|
||||
return $resource ?? \false;
|
||||
return $stream->detach();
|
||||
}
|
||||
/**
|
||||
* @return array<int|string, int>
|
||||
*/
|
||||
public function stream_stat() : array
|
||||
public function stream_stat()
|
||||
{
|
||||
static $modeMap = ['r' => 33060, 'rb' => 33060, 'r+' => 33206, 'w' => 33188, 'wb' => 33188];
|
||||
return ['dev' => 0, 'ino' => 0, 'mode' => $modeMap[$this->mode], 'nlink' => 0, 'uid' => 0, 'gid' => 0, 'rdev' => 0, 'size' => $this->stream->getSize() ?: 0, 'atime' => 0, 'mtime' => 0, 'ctime' => 0, 'blksize' => 0, 'blocks' => 0];
|
||||
}
|
||||
/**
|
||||
* @return array<int|string, int>
|
||||
*/
|
||||
public function url_stat(string $path, int $flags) : array
|
||||
public function url_stat($path, $flags)
|
||||
{
|
||||
return ['dev' => 0, 'ino' => 0, 'mode' => 0, 'nlink' => 0, 'uid' => 0, 'gid' => 0, 'rdev' => 0, 'size' => 0, 'atime' => 0, 'mtime' => 0, 'ctime' => 0, 'blksize' => 0, 'blocks' => 0];
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare (strict_types=1);
|
||||
namespace YoastSEO_Vendor\GuzzleHttp\Psr7;
|
||||
|
||||
use InvalidArgumentException;
|
||||
@@ -9,13 +8,16 @@ use YoastSEO_Vendor\Psr\Http\Message\UploadedFileInterface;
|
||||
use RuntimeException;
|
||||
class UploadedFile implements \YoastSEO_Vendor\Psr\Http\Message\UploadedFileInterface
|
||||
{
|
||||
private const ERRORS = [\UPLOAD_ERR_OK, \UPLOAD_ERR_INI_SIZE, \UPLOAD_ERR_FORM_SIZE, \UPLOAD_ERR_PARTIAL, \UPLOAD_ERR_NO_FILE, \UPLOAD_ERR_NO_TMP_DIR, \UPLOAD_ERR_CANT_WRITE, \UPLOAD_ERR_EXTENSION];
|
||||
/**
|
||||
* @var string|null
|
||||
* @var int[]
|
||||
*/
|
||||
private static $errors = [\UPLOAD_ERR_OK, \UPLOAD_ERR_INI_SIZE, \UPLOAD_ERR_FORM_SIZE, \UPLOAD_ERR_PARTIAL, \UPLOAD_ERR_NO_FILE, \UPLOAD_ERR_NO_TMP_DIR, \UPLOAD_ERR_CANT_WRITE, \UPLOAD_ERR_EXTENSION];
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $clientFilename;
|
||||
/**
|
||||
* @var string|null
|
||||
* @var string
|
||||
*/
|
||||
private $clientMediaType;
|
||||
/**
|
||||
@@ -31,7 +33,7 @@ class UploadedFile implements \YoastSEO_Vendor\Psr\Http\Message\UploadedFileInte
|
||||
*/
|
||||
private $moved = \false;
|
||||
/**
|
||||
* @var int|null
|
||||
* @var int
|
||||
*/
|
||||
private $size;
|
||||
/**
|
||||
@@ -40,13 +42,17 @@ class UploadedFile implements \YoastSEO_Vendor\Psr\Http\Message\UploadedFileInte
|
||||
private $stream;
|
||||
/**
|
||||
* @param StreamInterface|string|resource $streamOrFile
|
||||
* @param int $size
|
||||
* @param int $errorStatus
|
||||
* @param string|null $clientFilename
|
||||
* @param string|null $clientMediaType
|
||||
*/
|
||||
public function __construct($streamOrFile, ?int $size, int $errorStatus, string $clientFilename = null, string $clientMediaType = null)
|
||||
public function __construct($streamOrFile, $size, $errorStatus, $clientFilename = null, $clientMediaType = null)
|
||||
{
|
||||
$this->setError($errorStatus);
|
||||
$this->size = $size;
|
||||
$this->clientFilename = $clientFilename;
|
||||
$this->clientMediaType = $clientMediaType;
|
||||
$this->setSize($size);
|
||||
$this->setClientFilename($clientFilename);
|
||||
$this->setClientMediaType($clientMediaType);
|
||||
if ($this->isOk()) {
|
||||
$this->setStreamOrFile($streamOrFile);
|
||||
}
|
||||
@@ -54,11 +60,11 @@ class UploadedFile implements \YoastSEO_Vendor\Psr\Http\Message\UploadedFileInte
|
||||
/**
|
||||
* Depending on the value set file or stream variable
|
||||
*
|
||||
* @param StreamInterface|string|resource $streamOrFile
|
||||
* @param mixed $streamOrFile
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
private function setStreamOrFile($streamOrFile) : void
|
||||
private function setStreamOrFile($streamOrFile)
|
||||
{
|
||||
if (\is_string($streamOrFile)) {
|
||||
$this->file = $streamOrFile;
|
||||
@@ -71,34 +77,94 @@ class UploadedFile implements \YoastSEO_Vendor\Psr\Http\Message\UploadedFileInte
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @param int $error
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
private function setError(int $error) : void
|
||||
private function setError($error)
|
||||
{
|
||||
if (\false === \in_array($error, \YoastSEO_Vendor\GuzzleHttp\Psr7\UploadedFile::ERRORS, \true)) {
|
||||
if (\false === \is_int($error)) {
|
||||
throw new \InvalidArgumentException('Upload file error status must be an integer');
|
||||
}
|
||||
if (\false === \in_array($error, \YoastSEO_Vendor\GuzzleHttp\Psr7\UploadedFile::$errors)) {
|
||||
throw new \InvalidArgumentException('Invalid error status for UploadedFile');
|
||||
}
|
||||
$this->error = $error;
|
||||
}
|
||||
private function isStringNotEmpty($param) : bool
|
||||
/**
|
||||
* @param int $size
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
private function setSize($size)
|
||||
{
|
||||
if (\false === \is_int($size)) {
|
||||
throw new \InvalidArgumentException('Upload file size must be an integer');
|
||||
}
|
||||
$this->size = $size;
|
||||
}
|
||||
/**
|
||||
* @param mixed $param
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function isStringOrNull($param)
|
||||
{
|
||||
return \in_array(\gettype($param), ['string', 'NULL']);
|
||||
}
|
||||
/**
|
||||
* @param mixed $param
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function isStringNotEmpty($param)
|
||||
{
|
||||
return \is_string($param) && \false === empty($param);
|
||||
}
|
||||
/**
|
||||
* Return true if there is no upload error
|
||||
* @param string|null $clientFilename
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
private function isOk() : bool
|
||||
private function setClientFilename($clientFilename)
|
||||
{
|
||||
if (\false === $this->isStringOrNull($clientFilename)) {
|
||||
throw new \InvalidArgumentException('Upload file client filename must be a string or null');
|
||||
}
|
||||
$this->clientFilename = $clientFilename;
|
||||
}
|
||||
/**
|
||||
* @param string|null $clientMediaType
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
private function setClientMediaType($clientMediaType)
|
||||
{
|
||||
if (\false === $this->isStringOrNull($clientMediaType)) {
|
||||
throw new \InvalidArgumentException('Upload file client media type must be a string or null');
|
||||
}
|
||||
$this->clientMediaType = $clientMediaType;
|
||||
}
|
||||
/**
|
||||
* Return true if there is no upload error
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function isOk()
|
||||
{
|
||||
return $this->error === \UPLOAD_ERR_OK;
|
||||
}
|
||||
public function isMoved() : bool
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isMoved()
|
||||
{
|
||||
return $this->moved;
|
||||
}
|
||||
/**
|
||||
* @throws RuntimeException if is moved or not ok
|
||||
*/
|
||||
private function validateActive() : void
|
||||
private function validateActive()
|
||||
{
|
||||
if (\false === $this->isOk()) {
|
||||
throw new \RuntimeException('Cannot retrieve stream due to upload error');
|
||||
@@ -107,24 +173,40 @@ class UploadedFile implements \YoastSEO_Vendor\Psr\Http\Message\UploadedFileInte
|
||||
throw new \RuntimeException('Cannot retrieve stream after it has already been moved');
|
||||
}
|
||||
}
|
||||
public function getStream() : \YoastSEO_Vendor\Psr\Http\Message\StreamInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @throws RuntimeException if the upload was not successful.
|
||||
*/
|
||||
public function getStream()
|
||||
{
|
||||
$this->validateActive();
|
||||
if ($this->stream instanceof \YoastSEO_Vendor\Psr\Http\Message\StreamInterface) {
|
||||
return $this->stream;
|
||||
}
|
||||
/** @var string $file */
|
||||
$file = $this->file;
|
||||
return new \YoastSEO_Vendor\GuzzleHttp\Psr7\LazyOpenStream($file, 'r+');
|
||||
return new \YoastSEO_Vendor\GuzzleHttp\Psr7\LazyOpenStream($this->file, 'r+');
|
||||
}
|
||||
public function moveTo($targetPath) : void
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see http://php.net/is_uploaded_file
|
||||
* @see http://php.net/move_uploaded_file
|
||||
*
|
||||
* @param string $targetPath Path to which to move the uploaded file.
|
||||
*
|
||||
* @throws RuntimeException if the upload was not successful.
|
||||
* @throws InvalidArgumentException if the $path specified is invalid.
|
||||
* @throws RuntimeException on any error during the move operation, or on
|
||||
* the second or subsequent call to the method.
|
||||
*/
|
||||
public function moveTo($targetPath)
|
||||
{
|
||||
$this->validateActive();
|
||||
if (\false === $this->isStringNotEmpty($targetPath)) {
|
||||
throw new \InvalidArgumentException('Invalid path provided for move operation; must be a non-empty string');
|
||||
}
|
||||
if ($this->file) {
|
||||
$this->moved = \PHP_SAPI === 'cli' ? \rename($this->file, $targetPath) : \move_uploaded_file($this->file, $targetPath);
|
||||
$this->moved = \php_sapi_name() == 'cli' ? \rename($this->file, $targetPath) : \move_uploaded_file($this->file, $targetPath);
|
||||
} else {
|
||||
\YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::copyToStream($this->getStream(), new \YoastSEO_Vendor\GuzzleHttp\Psr7\LazyOpenStream($targetPath, 'w'));
|
||||
$this->moved = \true;
|
||||
@@ -133,19 +215,40 @@ class UploadedFile implements \YoastSEO_Vendor\Psr\Http\Message\UploadedFileInte
|
||||
throw new \RuntimeException(\sprintf('Uploaded file could not be moved to %s', $targetPath));
|
||||
}
|
||||
}
|
||||
public function getSize() : ?int
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @return int|null The file size in bytes or null if unknown.
|
||||
*/
|
||||
public function getSize()
|
||||
{
|
||||
return $this->size;
|
||||
}
|
||||
public function getError() : int
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see http://php.net/manual/en/features.file-upload.errors.php
|
||||
*
|
||||
* @return int One of PHP's UPLOAD_ERR_XXX constants.
|
||||
*/
|
||||
public function getError()
|
||||
{
|
||||
return $this->error;
|
||||
}
|
||||
public function getClientFilename() : ?string
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @return string|null The filename sent by the client or null if none
|
||||
* was provided.
|
||||
*/
|
||||
public function getClientFilename()
|
||||
{
|
||||
return $this->clientFilename;
|
||||
}
|
||||
public function getClientMediaType() : ?string
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getClientMediaType()
|
||||
{
|
||||
return $this->clientMediaType;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
<?php
|
||||
|
||||
declare (strict_types=1);
|
||||
namespace YoastSEO_Vendor\GuzzleHttp\Psr7;
|
||||
|
||||
use YoastSEO_Vendor\GuzzleHttp\Psr7\Exception\MalformedUriException;
|
||||
use YoastSEO_Vendor\Psr\Http\Message\UriInterface;
|
||||
/**
|
||||
* PSR-7 URI implementation.
|
||||
@@ -12,7 +10,7 @@ use YoastSEO_Vendor\Psr\Http\Message\UriInterface;
|
||||
* @author Tobias Schultze
|
||||
* @author Matthew Weier O'Phinney
|
||||
*/
|
||||
class Uri implements \YoastSEO_Vendor\Psr\Http\Message\UriInterface, \JsonSerializable
|
||||
class Uri implements \YoastSEO_Vendor\Psr\Http\Message\UriInterface
|
||||
{
|
||||
/**
|
||||
* Absolute http and https URIs require a host per RFC 7230 Section 2.7
|
||||
@@ -20,21 +18,11 @@ class Uri implements \YoastSEO_Vendor\Psr\Http\Message\UriInterface, \JsonSerial
|
||||
* we apply this default host when no host is given yet to form a
|
||||
* valid URI.
|
||||
*/
|
||||
private const HTTP_DEFAULT_HOST = 'localhost';
|
||||
private const DEFAULT_PORTS = ['http' => 80, 'https' => 443, 'ftp' => 21, 'gopher' => 70, 'nntp' => 119, 'news' => 119, 'telnet' => 23, 'tn3270' => 23, 'imap' => 143, 'pop' => 110, 'ldap' => 389];
|
||||
/**
|
||||
* Unreserved characters for use in a regex.
|
||||
*
|
||||
* @see https://tools.ietf.org/html/rfc3986#section-2.3
|
||||
*/
|
||||
private const CHAR_UNRESERVED = 'a-zA-Z0-9_\\-\\.~';
|
||||
/**
|
||||
* Sub-delims for use in a regex.
|
||||
*
|
||||
* @see https://tools.ietf.org/html/rfc3986#section-2.2
|
||||
*/
|
||||
private const CHAR_SUB_DELIMS = '!\\$&\'\\(\\)\\*\\+,;=';
|
||||
private const QUERY_SEPARATORS_REPLACEMENT = ['=' => '%3D', '&' => '%26'];
|
||||
const HTTP_DEFAULT_HOST = 'localhost';
|
||||
private static $defaultPorts = ['http' => 80, 'https' => 443, 'ftp' => 21, 'gopher' => 70, 'nntp' => 119, 'news' => 119, 'telnet' => 23, 'tn3270' => 23, 'imap' => 143, 'pop' => 110, 'ldap' => 389];
|
||||
private static $charUnreserved = 'a-zA-Z0-9_\\-\\.~';
|
||||
private static $charSubDelims = '!\\$&\'\\(\\)\\*\\+,;=';
|
||||
private static $replaceQuery = ['=' => '%3D', '&' => '%26'];
|
||||
/** @var string Uri scheme. */
|
||||
private $scheme = '';
|
||||
/** @var string Uri user info. */
|
||||
@@ -49,14 +37,16 @@ class Uri implements \YoastSEO_Vendor\Psr\Http\Message\UriInterface, \JsonSerial
|
||||
private $query = '';
|
||||
/** @var string Uri fragment. */
|
||||
private $fragment = '';
|
||||
/** @var string|null String representation */
|
||||
private $composedComponents;
|
||||
public function __construct(string $uri = '')
|
||||
/**
|
||||
* @param string $uri URI to parse
|
||||
*/
|
||||
public function __construct($uri = '')
|
||||
{
|
||||
if ($uri !== '') {
|
||||
// weak type check to also accept null until we can add scalar type hints
|
||||
if ($uri != '') {
|
||||
$parts = self::parse($uri);
|
||||
if ($parts === \false) {
|
||||
throw new \YoastSEO_Vendor\GuzzleHttp\Psr7\Exception\MalformedUriException("Unable to parse URI: {$uri}");
|
||||
throw new \InvalidArgumentException("Unable to parse URI: {$uri}");
|
||||
}
|
||||
$this->applyParts($parts);
|
||||
}
|
||||
@@ -74,18 +64,18 @@ class Uri implements \YoastSEO_Vendor\Psr\Http\Message\UriInterface, \JsonSerial
|
||||
* @see https://www.php.net/manual/en/function.parse-url.php#114817
|
||||
* @see https://curl.haxx.se/libcurl/c/CURLOPT_URL.html#ENCODING
|
||||
*
|
||||
* @param string $url
|
||||
*
|
||||
* @return array|false
|
||||
*/
|
||||
private static function parse(string $url)
|
||||
private static function parse($url)
|
||||
{
|
||||
// If IPv6
|
||||
$prefix = '';
|
||||
if (\preg_match('%^(.*://\\[[0-9:a-f]+\\])(.*?)$%', $url, $matches)) {
|
||||
/** @var array{0:string, 1:string, 2:string} $matches */
|
||||
$prefix = $matches[1];
|
||||
$url = $matches[2];
|
||||
}
|
||||
/** @var string */
|
||||
$encodedUrl = \preg_replace_callback('%[^:/@?&=#]+%usD', static function ($matches) {
|
||||
return \urlencode($matches[0]);
|
||||
}, $url);
|
||||
@@ -95,12 +85,9 @@ class Uri implements \YoastSEO_Vendor\Psr\Http\Message\UriInterface, \JsonSerial
|
||||
}
|
||||
return \array_map('urldecode', $result);
|
||||
}
|
||||
public function __toString() : string
|
||||
public function __toString()
|
||||
{
|
||||
if ($this->composedComponents === null) {
|
||||
$this->composedComponents = self::composeComponents($this->scheme, $this->getAuthority(), $this->path, $this->query, $this->fragment);
|
||||
}
|
||||
return $this->composedComponents;
|
||||
return self::composeComponents($this->scheme, $this->getAuthority(), $this->path, $this->query, $this->fragment);
|
||||
}
|
||||
/**
|
||||
* Composes a URI reference string from its various components.
|
||||
@@ -118,9 +105,17 @@ class Uri implements \YoastSEO_Vendor\Psr\Http\Message\UriInterface, \JsonSerial
|
||||
* `file:///` is the more common syntax for the file scheme anyway (Chrome for example redirects to
|
||||
* that format).
|
||||
*
|
||||
* @see https://tools.ietf.org/html/rfc3986#section-5.3
|
||||
* @param string $scheme
|
||||
* @param string $authority
|
||||
* @param string $path
|
||||
* @param string $query
|
||||
* @param string $fragment
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @link https://tools.ietf.org/html/rfc3986#section-5.3
|
||||
*/
|
||||
public static function composeComponents(?string $scheme, ?string $authority, string $path, ?string $query, ?string $fragment) : string
|
||||
public static function composeComponents($scheme, $authority, $path, $query, $fragment)
|
||||
{
|
||||
$uri = '';
|
||||
// weak type checks to also accept null until we can add scalar type hints
|
||||
@@ -130,9 +125,6 @@ class Uri implements \YoastSEO_Vendor\Psr\Http\Message\UriInterface, \JsonSerial
|
||||
if ($authority != '' || $scheme === 'file') {
|
||||
$uri .= '//' . $authority;
|
||||
}
|
||||
if ($authority != '' && $path != '' && $path[0] != '/') {
|
||||
$path = '/' . $path;
|
||||
}
|
||||
$uri .= $path;
|
||||
if ($query != '') {
|
||||
$uri .= '?' . $query;
|
||||
@@ -147,10 +139,14 @@ class Uri implements \YoastSEO_Vendor\Psr\Http\Message\UriInterface, \JsonSerial
|
||||
*
|
||||
* `Psr\Http\Message\UriInterface::getPort` may return null or the standard port. This method can be used
|
||||
* independently of the implementation.
|
||||
*
|
||||
* @param UriInterface $uri
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function isDefaultPort(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri) : bool
|
||||
public static function isDefaultPort(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri)
|
||||
{
|
||||
return $uri->getPort() === null || isset(self::DEFAULT_PORTS[$uri->getScheme()]) && $uri->getPort() === self::DEFAULT_PORTS[$uri->getScheme()];
|
||||
return $uri->getPort() === null || isset(self::$defaultPorts[$uri->getScheme()]) && $uri->getPort() === self::$defaultPorts[$uri->getScheme()];
|
||||
}
|
||||
/**
|
||||
* Whether the URI is absolute, i.e. it has a scheme.
|
||||
@@ -162,12 +158,16 @@ class Uri implements \YoastSEO_Vendor\Psr\Http\Message\UriInterface, \JsonSerial
|
||||
* - absolute-path references, e.g. '/path'
|
||||
* - relative-path references, e.g. 'subpath'
|
||||
*
|
||||
* @param UriInterface $uri
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @see Uri::isNetworkPathReference
|
||||
* @see Uri::isAbsolutePathReference
|
||||
* @see Uri::isRelativePathReference
|
||||
* @see https://tools.ietf.org/html/rfc3986#section-4
|
||||
* @link https://tools.ietf.org/html/rfc3986#section-4
|
||||
*/
|
||||
public static function isAbsolute(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri) : bool
|
||||
public static function isAbsolute(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri)
|
||||
{
|
||||
return $uri->getScheme() !== '';
|
||||
}
|
||||
@@ -176,9 +176,13 @@ class Uri implements \YoastSEO_Vendor\Psr\Http\Message\UriInterface, \JsonSerial
|
||||
*
|
||||
* A relative reference that begins with two slash characters is termed an network-path reference.
|
||||
*
|
||||
* @see https://tools.ietf.org/html/rfc3986#section-4.2
|
||||
* @param UriInterface $uri
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @link https://tools.ietf.org/html/rfc3986#section-4.2
|
||||
*/
|
||||
public static function isNetworkPathReference(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri) : bool
|
||||
public static function isNetworkPathReference(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri)
|
||||
{
|
||||
return $uri->getScheme() === '' && $uri->getAuthority() !== '';
|
||||
}
|
||||
@@ -187,9 +191,13 @@ class Uri implements \YoastSEO_Vendor\Psr\Http\Message\UriInterface, \JsonSerial
|
||||
*
|
||||
* A relative reference that begins with a single slash character is termed an absolute-path reference.
|
||||
*
|
||||
* @see https://tools.ietf.org/html/rfc3986#section-4.2
|
||||
* @param UriInterface $uri
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @link https://tools.ietf.org/html/rfc3986#section-4.2
|
||||
*/
|
||||
public static function isAbsolutePathReference(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri) : bool
|
||||
public static function isAbsolutePathReference(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri)
|
||||
{
|
||||
return $uri->getScheme() === '' && $uri->getAuthority() === '' && isset($uri->getPath()[0]) && $uri->getPath()[0] === '/';
|
||||
}
|
||||
@@ -198,9 +206,13 @@ class Uri implements \YoastSEO_Vendor\Psr\Http\Message\UriInterface, \JsonSerial
|
||||
*
|
||||
* A relative reference that does not begin with a slash character is termed a relative-path reference.
|
||||
*
|
||||
* @see https://tools.ietf.org/html/rfc3986#section-4.2
|
||||
* @param UriInterface $uri
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @link https://tools.ietf.org/html/rfc3986#section-4.2
|
||||
*/
|
||||
public static function isRelativePathReference(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri) : bool
|
||||
public static function isRelativePathReference(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri)
|
||||
{
|
||||
return $uri->getScheme() === '' && $uri->getAuthority() === '' && (!isset($uri->getPath()[0]) || $uri->getPath()[0] !== '/');
|
||||
}
|
||||
@@ -214,9 +226,11 @@ class Uri implements \YoastSEO_Vendor\Psr\Http\Message\UriInterface, \JsonSerial
|
||||
* @param UriInterface $uri The URI to check
|
||||
* @param UriInterface|null $base An optional base URI to compare against
|
||||
*
|
||||
* @see https://tools.ietf.org/html/rfc3986#section-4.4
|
||||
* @return bool
|
||||
*
|
||||
* @link https://tools.ietf.org/html/rfc3986#section-4.4
|
||||
*/
|
||||
public static function isSameDocumentReference(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri, \YoastSEO_Vendor\Psr\Http\Message\UriInterface $base = null) : bool
|
||||
public static function isSameDocumentReference(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri, \YoastSEO_Vendor\Psr\Http\Message\UriInterface $base = null)
|
||||
{
|
||||
if ($base !== null) {
|
||||
$uri = \YoastSEO_Vendor\GuzzleHttp\Psr7\UriResolver::resolve($base, $uri);
|
||||
@@ -224,6 +238,38 @@ class Uri implements \YoastSEO_Vendor\Psr\Http\Message\UriInterface, \JsonSerial
|
||||
}
|
||||
return $uri->getScheme() === '' && $uri->getAuthority() === '' && $uri->getPath() === '' && $uri->getQuery() === '';
|
||||
}
|
||||
/**
|
||||
* Removes dot segments from a path and returns the new path.
|
||||
*
|
||||
* @param string $path
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @deprecated since version 1.4. Use UriResolver::removeDotSegments instead.
|
||||
* @see UriResolver::removeDotSegments
|
||||
*/
|
||||
public static function removeDotSegments($path)
|
||||
{
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Psr7\UriResolver::removeDotSegments($path);
|
||||
}
|
||||
/**
|
||||
* Converts the relative URI into a new URI that is resolved against the base URI.
|
||||
*
|
||||
* @param UriInterface $base Base URI
|
||||
* @param string|UriInterface $rel Relative URI
|
||||
*
|
||||
* @return UriInterface
|
||||
*
|
||||
* @deprecated since version 1.4. Use UriResolver::resolve instead.
|
||||
* @see UriResolver::resolve
|
||||
*/
|
||||
public static function resolve(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $base, $rel)
|
||||
{
|
||||
if (!$rel instanceof \YoastSEO_Vendor\Psr\Http\Message\UriInterface) {
|
||||
$rel = new self($rel);
|
||||
}
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Psr7\UriResolver::resolve($base, $rel);
|
||||
}
|
||||
/**
|
||||
* Creates a new URI with a specific query string value removed.
|
||||
*
|
||||
@@ -232,8 +278,10 @@ class Uri implements \YoastSEO_Vendor\Psr\Http\Message\UriInterface, \JsonSerial
|
||||
*
|
||||
* @param UriInterface $uri URI to use as a base.
|
||||
* @param string $key Query string key to remove.
|
||||
*
|
||||
* @return UriInterface
|
||||
*/
|
||||
public static function withoutQueryValue(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri, string $key) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface
|
||||
public static function withoutQueryValue(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri, $key)
|
||||
{
|
||||
$result = self::getFilteredQueryString($uri, [$key]);
|
||||
return $uri->withQuery(\implode('&', $result));
|
||||
@@ -250,8 +298,10 @@ class Uri implements \YoastSEO_Vendor\Psr\Http\Message\UriInterface, \JsonSerial
|
||||
* @param UriInterface $uri URI to use as a base.
|
||||
* @param string $key Key to set.
|
||||
* @param string|null $value Value to set
|
||||
*
|
||||
* @return UriInterface
|
||||
*/
|
||||
public static function withQueryValue(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri, string $key, ?string $value) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface
|
||||
public static function withQueryValue(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri, $key, $value)
|
||||
{
|
||||
$result = self::getFilteredQueryString($uri, [$key]);
|
||||
$result[] = self::generateQueryString($key, $value);
|
||||
@@ -262,36 +312,42 @@ class Uri implements \YoastSEO_Vendor\Psr\Http\Message\UriInterface, \JsonSerial
|
||||
*
|
||||
* It has the same behavior as withQueryValue() but for an associative array of key => value.
|
||||
*
|
||||
* @param UriInterface $uri URI to use as a base.
|
||||
* @param array<string, string|null> $keyValueArray Associative array of key and values
|
||||
* @param UriInterface $uri URI to use as a base.
|
||||
* @param array $keyValueArray Associative array of key and values
|
||||
*
|
||||
* @return UriInterface
|
||||
*/
|
||||
public static function withQueryValues(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri, array $keyValueArray) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface
|
||||
public static function withQueryValues(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri, array $keyValueArray)
|
||||
{
|
||||
$result = self::getFilteredQueryString($uri, \array_keys($keyValueArray));
|
||||
foreach ($keyValueArray as $key => $value) {
|
||||
$result[] = self::generateQueryString((string) $key, $value !== null ? (string) $value : null);
|
||||
$result[] = self::generateQueryString($key, $value);
|
||||
}
|
||||
return $uri->withQuery(\implode('&', $result));
|
||||
}
|
||||
/**
|
||||
* Creates a URI from a hash of `parse_url` components.
|
||||
*
|
||||
* @see http://php.net/manual/en/function.parse-url.php
|
||||
* @param array $parts
|
||||
*
|
||||
* @throws MalformedUriException If the components do not form a valid URI.
|
||||
* @return UriInterface
|
||||
*
|
||||
* @link http://php.net/manual/en/function.parse-url.php
|
||||
*
|
||||
* @throws \InvalidArgumentException If the components do not form a valid URI.
|
||||
*/
|
||||
public static function fromParts(array $parts) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface
|
||||
public static function fromParts(array $parts)
|
||||
{
|
||||
$uri = new self();
|
||||
$uri->applyParts($parts);
|
||||
$uri->validateState();
|
||||
return $uri;
|
||||
}
|
||||
public function getScheme() : string
|
||||
public function getScheme()
|
||||
{
|
||||
return $this->scheme;
|
||||
}
|
||||
public function getAuthority() : string
|
||||
public function getAuthority()
|
||||
{
|
||||
$authority = $this->host;
|
||||
if ($this->userInfo !== '') {
|
||||
@@ -302,31 +358,31 @@ class Uri implements \YoastSEO_Vendor\Psr\Http\Message\UriInterface, \JsonSerial
|
||||
}
|
||||
return $authority;
|
||||
}
|
||||
public function getUserInfo() : string
|
||||
public function getUserInfo()
|
||||
{
|
||||
return $this->userInfo;
|
||||
}
|
||||
public function getHost() : string
|
||||
public function getHost()
|
||||
{
|
||||
return $this->host;
|
||||
}
|
||||
public function getPort() : ?int
|
||||
public function getPort()
|
||||
{
|
||||
return $this->port;
|
||||
}
|
||||
public function getPath() : string
|
||||
public function getPath()
|
||||
{
|
||||
return $this->path;
|
||||
}
|
||||
public function getQuery() : string
|
||||
public function getQuery()
|
||||
{
|
||||
return $this->query;
|
||||
}
|
||||
public function getFragment() : string
|
||||
public function getFragment()
|
||||
{
|
||||
return $this->fragment;
|
||||
}
|
||||
public function withScheme($scheme) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface
|
||||
public function withScheme($scheme)
|
||||
{
|
||||
$scheme = $this->filterScheme($scheme);
|
||||
if ($this->scheme === $scheme) {
|
||||
@@ -334,12 +390,11 @@ class Uri implements \YoastSEO_Vendor\Psr\Http\Message\UriInterface, \JsonSerial
|
||||
}
|
||||
$new = clone $this;
|
||||
$new->scheme = $scheme;
|
||||
$new->composedComponents = null;
|
||||
$new->removeDefaultPort();
|
||||
$new->validateState();
|
||||
return $new;
|
||||
}
|
||||
public function withUserInfo($user, $password = null) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface
|
||||
public function withUserInfo($user, $password = null)
|
||||
{
|
||||
$info = $this->filterUserInfoComponent($user);
|
||||
if ($password !== null) {
|
||||
@@ -350,11 +405,10 @@ class Uri implements \YoastSEO_Vendor\Psr\Http\Message\UriInterface, \JsonSerial
|
||||
}
|
||||
$new = clone $this;
|
||||
$new->userInfo = $info;
|
||||
$new->composedComponents = null;
|
||||
$new->validateState();
|
||||
return $new;
|
||||
}
|
||||
public function withHost($host) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface
|
||||
public function withHost($host)
|
||||
{
|
||||
$host = $this->filterHost($host);
|
||||
if ($this->host === $host) {
|
||||
@@ -362,11 +416,10 @@ class Uri implements \YoastSEO_Vendor\Psr\Http\Message\UriInterface, \JsonSerial
|
||||
}
|
||||
$new = clone $this;
|
||||
$new->host = $host;
|
||||
$new->composedComponents = null;
|
||||
$new->validateState();
|
||||
return $new;
|
||||
}
|
||||
public function withPort($port) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface
|
||||
public function withPort($port)
|
||||
{
|
||||
$port = $this->filterPort($port);
|
||||
if ($this->port === $port) {
|
||||
@@ -374,12 +427,11 @@ class Uri implements \YoastSEO_Vendor\Psr\Http\Message\UriInterface, \JsonSerial
|
||||
}
|
||||
$new = clone $this;
|
||||
$new->port = $port;
|
||||
$new->composedComponents = null;
|
||||
$new->removeDefaultPort();
|
||||
$new->validateState();
|
||||
return $new;
|
||||
}
|
||||
public function withPath($path) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface
|
||||
public function withPath($path)
|
||||
{
|
||||
$path = $this->filterPath($path);
|
||||
if ($this->path === $path) {
|
||||
@@ -387,11 +439,10 @@ class Uri implements \YoastSEO_Vendor\Psr\Http\Message\UriInterface, \JsonSerial
|
||||
}
|
||||
$new = clone $this;
|
||||
$new->path = $path;
|
||||
$new->composedComponents = null;
|
||||
$new->validateState();
|
||||
return $new;
|
||||
}
|
||||
public function withQuery($query) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface
|
||||
public function withQuery($query)
|
||||
{
|
||||
$query = $this->filterQueryAndFragment($query);
|
||||
if ($this->query === $query) {
|
||||
@@ -399,10 +450,9 @@ class Uri implements \YoastSEO_Vendor\Psr\Http\Message\UriInterface, \JsonSerial
|
||||
}
|
||||
$new = clone $this;
|
||||
$new->query = $query;
|
||||
$new->composedComponents = null;
|
||||
return $new;
|
||||
}
|
||||
public function withFragment($fragment) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface
|
||||
public function withFragment($fragment)
|
||||
{
|
||||
$fragment = $this->filterQueryAndFragment($fragment);
|
||||
if ($this->fragment === $fragment) {
|
||||
@@ -410,19 +460,14 @@ class Uri implements \YoastSEO_Vendor\Psr\Http\Message\UriInterface, \JsonSerial
|
||||
}
|
||||
$new = clone $this;
|
||||
$new->fragment = $fragment;
|
||||
$new->composedComponents = null;
|
||||
return $new;
|
||||
}
|
||||
public function jsonSerialize() : string
|
||||
{
|
||||
return $this->__toString();
|
||||
}
|
||||
/**
|
||||
* Apply parse_url parts to a URI.
|
||||
*
|
||||
* @param array $parts Array of parse_url parts to apply.
|
||||
*/
|
||||
private function applyParts(array $parts) : void
|
||||
private function applyParts(array $parts)
|
||||
{
|
||||
$this->scheme = isset($parts['scheme']) ? $this->filterScheme($parts['scheme']) : '';
|
||||
$this->userInfo = isset($parts['user']) ? $this->filterUserInfoComponent($parts['user']) : '';
|
||||
@@ -437,11 +482,13 @@ class Uri implements \YoastSEO_Vendor\Psr\Http\Message\UriInterface, \JsonSerial
|
||||
$this->removeDefaultPort();
|
||||
}
|
||||
/**
|
||||
* @param mixed $scheme
|
||||
* @param string $scheme
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws \InvalidArgumentException If the scheme is invalid.
|
||||
*/
|
||||
private function filterScheme($scheme) : string
|
||||
private function filterScheme($scheme)
|
||||
{
|
||||
if (!\is_string($scheme)) {
|
||||
throw new \InvalidArgumentException('Scheme must be a string');
|
||||
@@ -449,23 +496,27 @@ class Uri implements \YoastSEO_Vendor\Psr\Http\Message\UriInterface, \JsonSerial
|
||||
return \strtr($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz');
|
||||
}
|
||||
/**
|
||||
* @param mixed $component
|
||||
* @param string $component
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws \InvalidArgumentException If the user info is invalid.
|
||||
*/
|
||||
private function filterUserInfoComponent($component) : string
|
||||
private function filterUserInfoComponent($component)
|
||||
{
|
||||
if (!\is_string($component)) {
|
||||
throw new \InvalidArgumentException('User info must be a string');
|
||||
}
|
||||
return \preg_replace_callback('/(?:[^%' . self::CHAR_UNRESERVED . self::CHAR_SUB_DELIMS . ']+|%(?![A-Fa-f0-9]{2}))/', [$this, 'rawurlencodeMatchZero'], $component);
|
||||
return \preg_replace_callback('/(?:[^%' . self::$charUnreserved . self::$charSubDelims . ']+|%(?![A-Fa-f0-9]{2}))/', [$this, 'rawurlencodeMatchZero'], $component);
|
||||
}
|
||||
/**
|
||||
* @param mixed $host
|
||||
* @param string $host
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws \InvalidArgumentException If the host is invalid.
|
||||
*/
|
||||
private function filterHost($host) : string
|
||||
private function filterHost($host)
|
||||
{
|
||||
if (!\is_string($host)) {
|
||||
throw new \InvalidArgumentException('Host must be a string');
|
||||
@@ -473,11 +524,13 @@ class Uri implements \YoastSEO_Vendor\Psr\Http\Message\UriInterface, \JsonSerial
|
||||
return \strtr($host, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz');
|
||||
}
|
||||
/**
|
||||
* @param mixed $port
|
||||
* @param int|null $port
|
||||
*
|
||||
* @return int|null
|
||||
*
|
||||
* @throws \InvalidArgumentException If the port is invalid.
|
||||
*/
|
||||
private function filterPort($port) : ?int
|
||||
private function filterPort($port)
|
||||
{
|
||||
if ($port === null) {
|
||||
return null;
|
||||
@@ -489,11 +542,12 @@ class Uri implements \YoastSEO_Vendor\Psr\Http\Message\UriInterface, \JsonSerial
|
||||
return $port;
|
||||
}
|
||||
/**
|
||||
* @param string[] $keys
|
||||
* @param UriInterface $uri
|
||||
* @param array $keys
|
||||
*
|
||||
* @return string[]
|
||||
* @return array
|
||||
*/
|
||||
private static function getFilteredQueryString(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri, array $keys) : array
|
||||
private static function getFilteredQueryString(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri, array $keys)
|
||||
{
|
||||
$current = $uri->getQuery();
|
||||
if ($current === '') {
|
||||
@@ -504,18 +558,24 @@ class Uri implements \YoastSEO_Vendor\Psr\Http\Message\UriInterface, \JsonSerial
|
||||
return !\in_array(\rawurldecode(\explode('=', $part)[0]), $decodedKeys, \true);
|
||||
});
|
||||
}
|
||||
private static function generateQueryString(string $key, ?string $value) : string
|
||||
/**
|
||||
* @param string $key
|
||||
* @param string|null $value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private static function generateQueryString($key, $value)
|
||||
{
|
||||
// Query string separators ("=", "&") within the key or value need to be encoded
|
||||
// (while preventing double-encoding) before setting the query string. All other
|
||||
// chars that need percent-encoding will be encoded by withQuery().
|
||||
$queryString = \strtr($key, self::QUERY_SEPARATORS_REPLACEMENT);
|
||||
$queryString = \strtr($key, self::$replaceQuery);
|
||||
if ($value !== null) {
|
||||
$queryString .= '=' . \strtr($value, self::QUERY_SEPARATORS_REPLACEMENT);
|
||||
$queryString .= '=' . \strtr($value, self::$replaceQuery);
|
||||
}
|
||||
return $queryString;
|
||||
}
|
||||
private function removeDefaultPort() : void
|
||||
private function removeDefaultPort()
|
||||
{
|
||||
if ($this->port !== null && self::isDefaultPort($this)) {
|
||||
$this->port = null;
|
||||
@@ -524,47 +584,55 @@ class Uri implements \YoastSEO_Vendor\Psr\Http\Message\UriInterface, \JsonSerial
|
||||
/**
|
||||
* Filters the path of a URI
|
||||
*
|
||||
* @param mixed $path
|
||||
* @param string $path
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws \InvalidArgumentException If the path is invalid.
|
||||
*/
|
||||
private function filterPath($path) : string
|
||||
private function filterPath($path)
|
||||
{
|
||||
if (!\is_string($path)) {
|
||||
throw new \InvalidArgumentException('Path must be a string');
|
||||
}
|
||||
return \preg_replace_callback('/(?:[^' . self::CHAR_UNRESERVED . self::CHAR_SUB_DELIMS . '%:@\\/]++|%(?![A-Fa-f0-9]{2}))/', [$this, 'rawurlencodeMatchZero'], $path);
|
||||
return \preg_replace_callback('/(?:[^' . self::$charUnreserved . self::$charSubDelims . '%:@\\/]++|%(?![A-Fa-f0-9]{2}))/', [$this, 'rawurlencodeMatchZero'], $path);
|
||||
}
|
||||
/**
|
||||
* Filters the query string or fragment of a URI.
|
||||
*
|
||||
* @param mixed $str
|
||||
* @param string $str
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws \InvalidArgumentException If the query or fragment is invalid.
|
||||
*/
|
||||
private function filterQueryAndFragment($str) : string
|
||||
private function filterQueryAndFragment($str)
|
||||
{
|
||||
if (!\is_string($str)) {
|
||||
throw new \InvalidArgumentException('Query and fragment must be a string');
|
||||
}
|
||||
return \preg_replace_callback('/(?:[^' . self::CHAR_UNRESERVED . self::CHAR_SUB_DELIMS . '%:@\\/\\?]++|%(?![A-Fa-f0-9]{2}))/', [$this, 'rawurlencodeMatchZero'], $str);
|
||||
return \preg_replace_callback('/(?:[^' . self::$charUnreserved . self::$charSubDelims . '%:@\\/\\?]++|%(?![A-Fa-f0-9]{2}))/', [$this, 'rawurlencodeMatchZero'], $str);
|
||||
}
|
||||
private function rawurlencodeMatchZero(array $match) : string
|
||||
private function rawurlencodeMatchZero(array $match)
|
||||
{
|
||||
return \rawurlencode($match[0]);
|
||||
}
|
||||
private function validateState() : void
|
||||
private function validateState()
|
||||
{
|
||||
if ($this->host === '' && ($this->scheme === 'http' || $this->scheme === 'https')) {
|
||||
$this->host = self::HTTP_DEFAULT_HOST;
|
||||
}
|
||||
if ($this->getAuthority() === '') {
|
||||
if (0 === \strpos($this->path, '//')) {
|
||||
throw new \YoastSEO_Vendor\GuzzleHttp\Psr7\Exception\MalformedUriException('The path of a URI without an authority must not start with two slashes "//"');
|
||||
throw new \InvalidArgumentException('The path of a URI without an authority must not start with two slashes "//"');
|
||||
}
|
||||
if ($this->scheme === '' && \false !== \strpos(\explode('/', $this->path, 2)[0], ':')) {
|
||||
throw new \YoastSEO_Vendor\GuzzleHttp\Psr7\Exception\MalformedUriException('A relative URI must not have a path beginning with a segment containing a colon');
|
||||
throw new \InvalidArgumentException('A relative URI must not have a path beginning with a segment containing a colon');
|
||||
}
|
||||
} elseif (isset($this->path[0]) && $this->path[0] !== '/') {
|
||||
@\trigger_error('The path of a URI with an authority must start with a slash "/" or be empty. Automagically fixing the URI ' . 'by adding a leading slash to the path is deprecated since version 1.4 and will throw an exception instead.', \E_USER_DEPRECATED);
|
||||
$this->path = '/' . $this->path;
|
||||
//throw new \InvalidArgumentException('The path of a URI with an authority must start with a slash "/" or be empty');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare (strict_types=1);
|
||||
namespace YoastSEO_Vendor\GuzzleHttp\Psr7;
|
||||
|
||||
use YoastSEO_Vendor\Psr\Http\Message\UriInterface;
|
||||
@@ -14,8 +13,10 @@ final class UriComparator
|
||||
/**
|
||||
* Determines if a modified URL should be considered cross-origin with
|
||||
* respect to an original URL.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function isCrossOrigin(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $original, \YoastSEO_Vendor\Psr\Http\Message\UriInterface $modified) : bool
|
||||
public static function isCrossOrigin(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $original, \YoastSEO_Vendor\Psr\Http\Message\UriInterface $modified)
|
||||
{
|
||||
if (\strcasecmp($original->getHost(), $modified->getHost()) !== 0) {
|
||||
return \true;
|
||||
@@ -28,7 +29,10 @@ final class UriComparator
|
||||
}
|
||||
return \false;
|
||||
}
|
||||
private static function computePort(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri) : int
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
private static function computePort(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri)
|
||||
{
|
||||
$port = $uri->getPort();
|
||||
if (null !== $port) {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare (strict_types=1);
|
||||
namespace YoastSEO_Vendor\GuzzleHttp\Psr7;
|
||||
|
||||
use YoastSEO_Vendor\Psr\Http\Message\UriInterface;
|
||||
@@ -9,20 +8,23 @@ use YoastSEO_Vendor\Psr\Http\Message\UriInterface;
|
||||
*
|
||||
* @author Tobias Schultze
|
||||
*
|
||||
* @see https://tools.ietf.org/html/rfc3986#section-6
|
||||
* @link https://tools.ietf.org/html/rfc3986#section-6
|
||||
*/
|
||||
final class UriNormalizer
|
||||
{
|
||||
/**
|
||||
* Default normalizations which only include the ones that preserve semantics.
|
||||
*
|
||||
* self::CAPITALIZE_PERCENT_ENCODING | self::DECODE_UNRESERVED_CHARACTERS | self::CONVERT_EMPTY_PATH |
|
||||
* self::REMOVE_DEFAULT_HOST | self::REMOVE_DEFAULT_PORT | self::REMOVE_DOT_SEGMENTS
|
||||
*/
|
||||
public const PRESERVING_NORMALIZATIONS = self::CAPITALIZE_PERCENT_ENCODING | self::DECODE_UNRESERVED_CHARACTERS | self::CONVERT_EMPTY_PATH | self::REMOVE_DEFAULT_HOST | self::REMOVE_DEFAULT_PORT | self::REMOVE_DOT_SEGMENTS;
|
||||
const PRESERVING_NORMALIZATIONS = 63;
|
||||
/**
|
||||
* All letters within a percent-encoding triplet (e.g., "%3A") are case-insensitive, and should be capitalized.
|
||||
*
|
||||
* Example: http://example.org/a%c2%b1b → http://example.org/a%C2%B1b
|
||||
*/
|
||||
public const CAPITALIZE_PERCENT_ENCODING = 1;
|
||||
const CAPITALIZE_PERCENT_ENCODING = 1;
|
||||
/**
|
||||
* Decodes percent-encoded octets of unreserved characters.
|
||||
*
|
||||
@@ -32,13 +34,13 @@ final class UriNormalizer
|
||||
*
|
||||
* Example: http://example.org/%7Eusern%61me/ → http://example.org/~username/
|
||||
*/
|
||||
public const DECODE_UNRESERVED_CHARACTERS = 2;
|
||||
const DECODE_UNRESERVED_CHARACTERS = 2;
|
||||
/**
|
||||
* Converts the empty path to "/" for http and https URIs.
|
||||
*
|
||||
* Example: http://example.org → http://example.org/
|
||||
*/
|
||||
public const CONVERT_EMPTY_PATH = 4;
|
||||
const CONVERT_EMPTY_PATH = 4;
|
||||
/**
|
||||
* Removes the default host of the given URI scheme from the URI.
|
||||
*
|
||||
@@ -50,13 +52,13 @@ final class UriNormalizer
|
||||
*
|
||||
* Example: file://localhost/myfile → file:///myfile
|
||||
*/
|
||||
public const REMOVE_DEFAULT_HOST = 8;
|
||||
const REMOVE_DEFAULT_HOST = 8;
|
||||
/**
|
||||
* Removes the default port of the given URI scheme from the URI.
|
||||
*
|
||||
* Example: http://example.org:80/ → http://example.org/
|
||||
*/
|
||||
public const REMOVE_DEFAULT_PORT = 16;
|
||||
const REMOVE_DEFAULT_PORT = 16;
|
||||
/**
|
||||
* Removes unnecessary dot-segments.
|
||||
*
|
||||
@@ -65,7 +67,7 @@ final class UriNormalizer
|
||||
*
|
||||
* Example: http://example.org/../a/b/../c/./d.html → http://example.org/a/c/d.html
|
||||
*/
|
||||
public const REMOVE_DOT_SEGMENTS = 32;
|
||||
const REMOVE_DOT_SEGMENTS = 32;
|
||||
/**
|
||||
* Paths which include two or more adjacent slashes are converted to one.
|
||||
*
|
||||
@@ -75,7 +77,7 @@ final class UriNormalizer
|
||||
*
|
||||
* Example: http://example.org//foo///bar.html → http://example.org/foo/bar.html
|
||||
*/
|
||||
public const REMOVE_DUPLICATE_SLASHES = 64;
|
||||
const REMOVE_DUPLICATE_SLASHES = 64;
|
||||
/**
|
||||
* Sort query parameters with their values in alphabetical order.
|
||||
*
|
||||
@@ -87,7 +89,7 @@ final class UriNormalizer
|
||||
* Note: The sorting is neither locale nor Unicode aware (the URI query does not get decoded at all) as the
|
||||
* purpose is to be able to compare URIs in a reproducible way, not to have the params sorted perfectly.
|
||||
*/
|
||||
public const SORT_QUERY_PARAMETERS = 128;
|
||||
const SORT_QUERY_PARAMETERS = 128;
|
||||
/**
|
||||
* Returns a normalized URI.
|
||||
*
|
||||
@@ -102,9 +104,11 @@ final class UriNormalizer
|
||||
* @param UriInterface $uri The URI to normalize
|
||||
* @param int $flags A bitmask of normalizations to apply, see constants
|
||||
*
|
||||
* @see https://tools.ietf.org/html/rfc3986#section-6.2
|
||||
* @return UriInterface The normalized URI
|
||||
*
|
||||
* @link https://tools.ietf.org/html/rfc3986#section-6.2
|
||||
*/
|
||||
public static function normalize(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri, int $flags = self::PRESERVING_NORMALIZATIONS) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface
|
||||
public static function normalize(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri, $flags = self::PRESERVING_NORMALIZATIONS)
|
||||
{
|
||||
if ($flags & self::CAPITALIZE_PERCENT_ENCODING) {
|
||||
$uri = self::capitalizePercentEncoding($uri);
|
||||
@@ -146,13 +150,15 @@ final class UriNormalizer
|
||||
* @param UriInterface $uri2 An URI to compare
|
||||
* @param int $normalizations A bitmask of normalizations to apply, see constants
|
||||
*
|
||||
* @see https://tools.ietf.org/html/rfc3986#section-6.1
|
||||
* @return bool
|
||||
*
|
||||
* @link https://tools.ietf.org/html/rfc3986#section-6.1
|
||||
*/
|
||||
public static function isEquivalent(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri1, \YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri2, int $normalizations = self::PRESERVING_NORMALIZATIONS) : bool
|
||||
public static function isEquivalent(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri1, \YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri2, $normalizations = self::PRESERVING_NORMALIZATIONS)
|
||||
{
|
||||
return (string) self::normalize($uri1, $normalizations) === (string) self::normalize($uri2, $normalizations);
|
||||
}
|
||||
private static function capitalizePercentEncoding(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface
|
||||
private static function capitalizePercentEncoding(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri)
|
||||
{
|
||||
$regex = '/(?:%[A-Fa-f0-9]{2})++/';
|
||||
$callback = function (array $match) {
|
||||
@@ -160,7 +166,7 @@ final class UriNormalizer
|
||||
};
|
||||
return $uri->withPath(\preg_replace_callback($regex, $callback, $uri->getPath()))->withQuery(\preg_replace_callback($regex, $callback, $uri->getQuery()));
|
||||
}
|
||||
private static function decodeUnreservedCharacters(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface
|
||||
private static function decodeUnreservedCharacters(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri)
|
||||
{
|
||||
$regex = '/%(?:2D|2E|5F|7E|3[0-9]|[46][1-9A-F]|[57][0-9A])/i';
|
||||
$callback = function (array $match) {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare (strict_types=1);
|
||||
namespace YoastSEO_Vendor\GuzzleHttp\Psr7;
|
||||
|
||||
use YoastSEO_Vendor\Psr\Http\Message\UriInterface;
|
||||
@@ -9,16 +8,20 @@ use YoastSEO_Vendor\Psr\Http\Message\UriInterface;
|
||||
*
|
||||
* @author Tobias Schultze
|
||||
*
|
||||
* @see https://tools.ietf.org/html/rfc3986#section-5
|
||||
* @link https://tools.ietf.org/html/rfc3986#section-5
|
||||
*/
|
||||
final class UriResolver
|
||||
{
|
||||
/**
|
||||
* Removes dot segments from a path and returns the new path.
|
||||
*
|
||||
* @see http://tools.ietf.org/html/rfc3986#section-5.2.4
|
||||
* @param string $path
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @link http://tools.ietf.org/html/rfc3986#section-5.2.4
|
||||
*/
|
||||
public static function removeDotSegments(string $path) : string
|
||||
public static function removeDotSegments($path)
|
||||
{
|
||||
if ($path === '' || $path === '/') {
|
||||
return $path;
|
||||
@@ -46,9 +49,14 @@ final class UriResolver
|
||||
/**
|
||||
* Converts the relative URI into a new URI that is resolved against the base URI.
|
||||
*
|
||||
* @see http://tools.ietf.org/html/rfc3986#section-5.2
|
||||
* @param UriInterface $base Base URI
|
||||
* @param UriInterface $rel Relative URI
|
||||
*
|
||||
* @return UriInterface
|
||||
*
|
||||
* @link http://tools.ietf.org/html/rfc3986#section-5.2
|
||||
*/
|
||||
public static function resolve(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $base, \YoastSEO_Vendor\Psr\Http\Message\UriInterface $rel) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface
|
||||
public static function resolve(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $base, \YoastSEO_Vendor\Psr\Http\Message\UriInterface $rel)
|
||||
{
|
||||
if ((string) $rel === '') {
|
||||
// we can simply return the same base URI instance for this same-document reference
|
||||
@@ -107,8 +115,13 @@ final class UriResolver
|
||||
* relative-path reference will be returned as-is.
|
||||
*
|
||||
* echo UriResolver::relativize($base, new Uri('/a/b/c')); // prints 'c' as well
|
||||
*
|
||||
* @param UriInterface $base Base URI
|
||||
* @param UriInterface $target Target URI
|
||||
*
|
||||
* @return UriInterface The relative URI reference
|
||||
*/
|
||||
public static function relativize(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $base, \YoastSEO_Vendor\Psr\Http\Message\UriInterface $target) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface
|
||||
public static function relativize(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $base, \YoastSEO_Vendor\Psr\Http\Message\UriInterface $target)
|
||||
{
|
||||
if ($target->getScheme() !== '' && ($base->getScheme() !== $target->getScheme() || $target->getAuthority() === '' && $base->getAuthority() !== '')) {
|
||||
return $target;
|
||||
@@ -137,13 +150,12 @@ final class UriResolver
|
||||
// inherit the base query component when resolving.
|
||||
if ($target->getQuery() === '') {
|
||||
$segments = \explode('/', $target->getPath());
|
||||
/** @var string $lastSegment */
|
||||
$lastSegment = \end($segments);
|
||||
return $emptyPathUri->withPath($lastSegment === '' ? './' : $lastSegment);
|
||||
}
|
||||
return $emptyPathUri;
|
||||
}
|
||||
private static function getRelativePath(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $base, \YoastSEO_Vendor\Psr\Http\Message\UriInterface $target) : string
|
||||
private static function getRelativePath(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $base, \YoastSEO_Vendor\Psr\Http\Message\UriInterface $target)
|
||||
{
|
||||
$sourceSegments = \explode('/', $base->getPath());
|
||||
$targetSegments = \explode('/', $target->getPath());
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare (strict_types=1);
|
||||
namespace YoastSEO_Vendor\GuzzleHttp\Psr7;
|
||||
|
||||
use YoastSEO_Vendor\Psr\Http\Message\RequestInterface;
|
||||
@@ -12,16 +11,18 @@ final class Utils
|
||||
/**
|
||||
* Remove the items given by the keys, case insensitively from the data.
|
||||
*
|
||||
* @param string[] $keys
|
||||
* @param iterable<string> $keys
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function caselessRemove(array $keys, array $data) : array
|
||||
public static function caselessRemove($keys, array $data)
|
||||
{
|
||||
$result = [];
|
||||
foreach ($keys as &$key) {
|
||||
$key = \strtolower($key);
|
||||
}
|
||||
foreach ($data as $k => $v) {
|
||||
if (!\is_string($k) || !\in_array(\strtolower($k), $keys)) {
|
||||
if (!\in_array(\strtolower($k), $keys)) {
|
||||
$result[$k] = $v;
|
||||
}
|
||||
}
|
||||
@@ -38,7 +39,7 @@ final class Utils
|
||||
*
|
||||
* @throws \RuntimeException on error.
|
||||
*/
|
||||
public static function copyToStream(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $source, \YoastSEO_Vendor\Psr\Http\Message\StreamInterface $dest, int $maxLen = -1) : void
|
||||
public static function copyToStream(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $source, \YoastSEO_Vendor\Psr\Http\Message\StreamInterface $dest, $maxLen = -1)
|
||||
{
|
||||
$bufferSize = 8192;
|
||||
if ($maxLen === -1) {
|
||||
@@ -68,15 +69,18 @@ final class Utils
|
||||
* @param int $maxLen Maximum number of bytes to read. Pass -1
|
||||
* to read the entire stream.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws \RuntimeException on error.
|
||||
*/
|
||||
public static function copyToString(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $stream, int $maxLen = -1) : string
|
||||
public static function copyToString(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $stream, $maxLen = -1)
|
||||
{
|
||||
$buffer = '';
|
||||
if ($maxLen === -1) {
|
||||
while (!$stream->eof()) {
|
||||
$buf = $stream->read(1048576);
|
||||
if ($buf === '') {
|
||||
// Using a loose equality here to match on '' and false.
|
||||
if ($buf == null) {
|
||||
break;
|
||||
}
|
||||
$buffer .= $buf;
|
||||
@@ -86,7 +90,8 @@ final class Utils
|
||||
$len = 0;
|
||||
while (!$stream->eof() && $len < $maxLen) {
|
||||
$buf = $stream->read($maxLen - $len);
|
||||
if ($buf === '') {
|
||||
// Using a loose equality here to match on '' and false.
|
||||
if ($buf == null) {
|
||||
break;
|
||||
}
|
||||
$buffer .= $buf;
|
||||
@@ -104,9 +109,11 @@ final class Utils
|
||||
* @param string $algo Hash algorithm (e.g. md5, crc32, etc)
|
||||
* @param bool $rawOutput Whether or not to use raw output
|
||||
*
|
||||
* @return string Returns the hash of the stream
|
||||
*
|
||||
* @throws \RuntimeException on error.
|
||||
*/
|
||||
public static function hash(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $stream, string $algo, bool $rawOutput = \false) : string
|
||||
public static function hash(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $stream, $algo, $rawOutput = \false)
|
||||
{
|
||||
$pos = $stream->tell();
|
||||
if ($pos > 0) {
|
||||
@@ -116,7 +123,7 @@ final class Utils
|
||||
while (!$stream->eof()) {
|
||||
\hash_update($ctx, $stream->read(1048576));
|
||||
}
|
||||
$out = \hash_final($ctx, $rawOutput);
|
||||
$out = \hash_final($ctx, (bool) $rawOutput);
|
||||
$stream->seek($pos);
|
||||
return $out;
|
||||
}
|
||||
@@ -137,8 +144,10 @@ final class Utils
|
||||
*
|
||||
* @param RequestInterface $request Request to clone and modify.
|
||||
* @param array $changes Changes to apply.
|
||||
*
|
||||
* @return RequestInterface
|
||||
*/
|
||||
public static function modifyRequest(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $changes) : \YoastSEO_Vendor\Psr\Http\Message\RequestInterface
|
||||
public static function modifyRequest(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $changes)
|
||||
{
|
||||
if (!$changes) {
|
||||
return $request;
|
||||
@@ -171,26 +180,29 @@ final class Utils
|
||||
$uri = $uri->withQuery($changes['query']);
|
||||
}
|
||||
if ($request instanceof \YoastSEO_Vendor\Psr\Http\Message\ServerRequestInterface) {
|
||||
$new = (new \YoastSEO_Vendor\GuzzleHttp\Psr7\ServerRequest($changes['method'] ?? $request->getMethod(), $uri, $headers, $changes['body'] ?? $request->getBody(), $changes['version'] ?? $request->getProtocolVersion(), $request->getServerParams()))->withParsedBody($request->getParsedBody())->withQueryParams($request->getQueryParams())->withCookieParams($request->getCookieParams())->withUploadedFiles($request->getUploadedFiles());
|
||||
$new = (new \YoastSEO_Vendor\GuzzleHttp\Psr7\ServerRequest(isset($changes['method']) ? $changes['method'] : $request->getMethod(), $uri, $headers, isset($changes['body']) ? $changes['body'] : $request->getBody(), isset($changes['version']) ? $changes['version'] : $request->getProtocolVersion(), $request->getServerParams()))->withParsedBody($request->getParsedBody())->withQueryParams($request->getQueryParams())->withCookieParams($request->getCookieParams())->withUploadedFiles($request->getUploadedFiles());
|
||||
foreach ($request->getAttributes() as $key => $value) {
|
||||
$new = $new->withAttribute($key, $value);
|
||||
}
|
||||
return $new;
|
||||
}
|
||||
return new \YoastSEO_Vendor\GuzzleHttp\Psr7\Request($changes['method'] ?? $request->getMethod(), $uri, $headers, $changes['body'] ?? $request->getBody(), $changes['version'] ?? $request->getProtocolVersion());
|
||||
return new \YoastSEO_Vendor\GuzzleHttp\Psr7\Request(isset($changes['method']) ? $changes['method'] : $request->getMethod(), $uri, $headers, isset($changes['body']) ? $changes['body'] : $request->getBody(), isset($changes['version']) ? $changes['version'] : $request->getProtocolVersion());
|
||||
}
|
||||
/**
|
||||
* Read a line from the stream up to the maximum allowed buffer length.
|
||||
*
|
||||
* @param StreamInterface $stream Stream to read from
|
||||
* @param int|null $maxLength Maximum buffer length
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function readLine(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $stream, int $maxLength = null) : string
|
||||
public static function readLine(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $stream, $maxLength = null)
|
||||
{
|
||||
$buffer = '';
|
||||
$size = 0;
|
||||
while (!$stream->eof()) {
|
||||
if ('' === ($byte = $stream->read(1))) {
|
||||
// Using a loose equality here to match on '' and false.
|
||||
if (null == ($byte = $stream->read(1))) {
|
||||
return $buffer;
|
||||
}
|
||||
$buffer .= $byte;
|
||||
@@ -231,16 +243,18 @@ final class Utils
|
||||
* buffered and used in subsequent reads.
|
||||
*
|
||||
* @param resource|string|int|float|bool|StreamInterface|callable|\Iterator|null $resource Entity body data
|
||||
* @param array{size?: int, metadata?: array} $options Additional options
|
||||
* @param array $options Additional options
|
||||
*
|
||||
* @return StreamInterface
|
||||
*
|
||||
* @throws \InvalidArgumentException if the $resource arg is not valid.
|
||||
*/
|
||||
public static function streamFor($resource = '', array $options = []) : \YoastSEO_Vendor\Psr\Http\Message\StreamInterface
|
||||
public static function streamFor($resource = '', array $options = [])
|
||||
{
|
||||
if (\is_scalar($resource)) {
|
||||
$stream = self::tryFopen('php://temp', 'r+');
|
||||
if ($resource !== '') {
|
||||
\fwrite($stream, (string) $resource);
|
||||
\fwrite($stream, $resource);
|
||||
\fseek($stream, 0);
|
||||
}
|
||||
return new \YoastSEO_Vendor\GuzzleHttp\Psr7\Stream($stream, $options);
|
||||
@@ -251,16 +265,15 @@ final class Utils
|
||||
* The 'php://input' is a special stream with quirks and inconsistencies.
|
||||
* We avoid using that stream by reading it into php://temp
|
||||
*/
|
||||
/** @var resource $resource */
|
||||
if ((\stream_get_meta_data($resource)['uri'] ?? '') === 'php://input') {
|
||||
$metaData = \stream_get_meta_data($resource);
|
||||
if (isset($metaData['uri']) && $metaData['uri'] === 'php://input') {
|
||||
$stream = self::tryFopen('php://temp', 'w+');
|
||||
\stream_copy_to_stream($resource, $stream);
|
||||
\fwrite($stream, \stream_get_contents($resource));
|
||||
\fseek($stream, 0);
|
||||
$resource = $stream;
|
||||
}
|
||||
return new \YoastSEO_Vendor\GuzzleHttp\Psr7\Stream($resource, $options);
|
||||
case 'object':
|
||||
/** @var object $resource */
|
||||
if ($resource instanceof \YoastSEO_Vendor\Psr\Http\Message\StreamInterface) {
|
||||
return $resource;
|
||||
} elseif ($resource instanceof \Iterator) {
|
||||
@@ -273,7 +286,7 @@ final class Utils
|
||||
return $result;
|
||||
}, $options);
|
||||
} elseif (\method_exists($resource, '__toString')) {
|
||||
return self::streamFor((string) $resource, $options);
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::streamFor((string) $resource, $options);
|
||||
}
|
||||
break;
|
||||
case 'NULL':
|
||||
@@ -297,15 +310,14 @@ final class Utils
|
||||
*
|
||||
* @throws \RuntimeException if the file cannot be opened
|
||||
*/
|
||||
public static function tryFopen(string $filename, string $mode)
|
||||
public static function tryFopen($filename, $mode)
|
||||
{
|
||||
$ex = null;
|
||||
\set_error_handler(static function (int $errno, string $errstr) use($filename, $mode, &$ex) : bool {
|
||||
$ex = new \RuntimeException(\sprintf('Unable to open "%s" using mode "%s": %s', $filename, $mode, $errstr));
|
||||
\set_error_handler(function () use($filename, $mode, &$ex) {
|
||||
$ex = new \RuntimeException(\sprintf('Unable to open "%s" using mode "%s": %s', $filename, $mode, \func_get_args()[1]));
|
||||
return \true;
|
||||
});
|
||||
try {
|
||||
/** @var resource $handle */
|
||||
$handle = \fopen($filename, $mode);
|
||||
} catch (\Throwable $e) {
|
||||
$ex = new \RuntimeException(\sprintf('Unable to open "%s" using mode "%s": %s', $filename, $mode, $e->getMessage()), 0, $e);
|
||||
@@ -317,40 +329,6 @@ final class Utils
|
||||
}
|
||||
return $handle;
|
||||
}
|
||||
/**
|
||||
* Safely gets the contents of a given stream.
|
||||
*
|
||||
* When stream_get_contents fails, PHP normally raises a warning. This
|
||||
* function adds an error handler that checks for errors and throws an
|
||||
* exception instead.
|
||||
*
|
||||
* @param resource $stream
|
||||
*
|
||||
* @throws \RuntimeException if the stream cannot be read
|
||||
*/
|
||||
public static function tryGetContents($stream) : string
|
||||
{
|
||||
$ex = null;
|
||||
\set_error_handler(static function (int $errno, string $errstr) use(&$ex) : bool {
|
||||
$ex = new \RuntimeException(\sprintf('Unable to read stream contents: %s', $errstr));
|
||||
return \true;
|
||||
});
|
||||
try {
|
||||
/** @var string|false $contents */
|
||||
$contents = \stream_get_contents($stream);
|
||||
if ($contents === \false) {
|
||||
$ex = new \RuntimeException('Unable to read stream contents');
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
$ex = new \RuntimeException(\sprintf('Unable to read stream contents: %s', $e->getMessage()), 0, $e);
|
||||
}
|
||||
\restore_error_handler();
|
||||
if ($ex) {
|
||||
/** @var $ex \RuntimeException */
|
||||
throw $ex;
|
||||
}
|
||||
return $contents;
|
||||
}
|
||||
/**
|
||||
* Returns a UriInterface for the given value.
|
||||
*
|
||||
@@ -360,9 +338,11 @@ final class Utils
|
||||
*
|
||||
* @param string|UriInterface $uri
|
||||
*
|
||||
* @return UriInterface
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public static function uriFor($uri) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface
|
||||
public static function uriFor($uri)
|
||||
{
|
||||
if ($uri instanceof \YoastSEO_Vendor\Psr\Http\Message\UriInterface) {
|
||||
return $uri;
|
||||
|
||||
@@ -0,0 +1,400 @@
|
||||
<?php
|
||||
|
||||
namespace YoastSEO_Vendor\GuzzleHttp\Psr7;
|
||||
|
||||
use YoastSEO_Vendor\Psr\Http\Message\MessageInterface;
|
||||
use YoastSEO_Vendor\Psr\Http\Message\RequestInterface;
|
||||
use YoastSEO_Vendor\Psr\Http\Message\StreamInterface;
|
||||
use YoastSEO_Vendor\Psr\Http\Message\UriInterface;
|
||||
/**
|
||||
* Returns the string representation of an HTTP message.
|
||||
*
|
||||
* @param MessageInterface $message Message to convert to a string.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @deprecated str will be removed in guzzlehttp/psr7:2.0. Use Message::toString instead.
|
||||
*/
|
||||
function str(\YoastSEO_Vendor\Psr\Http\Message\MessageInterface $message)
|
||||
{
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Psr7\Message::toString($message);
|
||||
}
|
||||
/**
|
||||
* Returns a UriInterface for the given value.
|
||||
*
|
||||
* This function accepts a string or UriInterface and returns a
|
||||
* UriInterface for the given value. If the value is already a
|
||||
* UriInterface, it is returned as-is.
|
||||
*
|
||||
* @param string|UriInterface $uri
|
||||
*
|
||||
* @return UriInterface
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*
|
||||
* @deprecated uri_for will be removed in guzzlehttp/psr7:2.0. Use Utils::uriFor instead.
|
||||
*/
|
||||
function uri_for($uri)
|
||||
{
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::uriFor($uri);
|
||||
}
|
||||
/**
|
||||
* Create a new stream based on the input type.
|
||||
*
|
||||
* Options is an associative array that can contain the following keys:
|
||||
* - metadata: Array of custom metadata.
|
||||
* - size: Size of the stream.
|
||||
*
|
||||
* This method accepts the following `$resource` types:
|
||||
* - `Psr\Http\Message\StreamInterface`: Returns the value as-is.
|
||||
* - `string`: Creates a stream object that uses the given string as the contents.
|
||||
* - `resource`: Creates a stream object that wraps the given PHP stream resource.
|
||||
* - `Iterator`: If the provided value implements `Iterator`, then a read-only
|
||||
* stream object will be created that wraps the given iterable. Each time the
|
||||
* stream is read from, data from the iterator will fill a buffer and will be
|
||||
* continuously called until the buffer is equal to the requested read size.
|
||||
* Subsequent read calls will first read from the buffer and then call `next`
|
||||
* on the underlying iterator until it is exhausted.
|
||||
* - `object` with `__toString()`: If the object has the `__toString()` method,
|
||||
* the object will be cast to a string and then a stream will be returned that
|
||||
* uses the string value.
|
||||
* - `NULL`: When `null` is passed, an empty stream object is returned.
|
||||
* - `callable` When a callable is passed, a read-only stream object will be
|
||||
* created that invokes the given callable. The callable is invoked with the
|
||||
* number of suggested bytes to read. The callable can return any number of
|
||||
* bytes, but MUST return `false` when there is no more data to return. The
|
||||
* stream object that wraps the callable will invoke the callable until the
|
||||
* number of requested bytes are available. Any additional bytes will be
|
||||
* buffered and used in subsequent reads.
|
||||
*
|
||||
* @param resource|string|int|float|bool|StreamInterface|callable|\Iterator|null $resource Entity body data
|
||||
* @param array $options Additional options
|
||||
*
|
||||
* @return StreamInterface
|
||||
*
|
||||
* @throws \InvalidArgumentException if the $resource arg is not valid.
|
||||
*
|
||||
* @deprecated stream_for will be removed in guzzlehttp/psr7:2.0. Use Utils::streamFor instead.
|
||||
*/
|
||||
function stream_for($resource = '', array $options = [])
|
||||
{
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::streamFor($resource, $options);
|
||||
}
|
||||
/**
|
||||
* Parse an array of header values containing ";" separated data into an
|
||||
* array of associative arrays representing the header key value pair data
|
||||
* of the header. When a parameter does not contain a value, but just
|
||||
* contains a key, this function will inject a key with a '' string value.
|
||||
*
|
||||
* @param string|array $header Header to parse into components.
|
||||
*
|
||||
* @return array Returns the parsed header values.
|
||||
*
|
||||
* @deprecated parse_header will be removed in guzzlehttp/psr7:2.0. Use Header::parse instead.
|
||||
*/
|
||||
function parse_header($header)
|
||||
{
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Psr7\Header::parse($header);
|
||||
}
|
||||
/**
|
||||
* Converts an array of header values that may contain comma separated
|
||||
* headers into an array of headers with no comma separated values.
|
||||
*
|
||||
* @param string|array $header Header to normalize.
|
||||
*
|
||||
* @return array Returns the normalized header field values.
|
||||
*
|
||||
* @deprecated normalize_header will be removed in guzzlehttp/psr7:2.0. Use Header::normalize instead.
|
||||
*/
|
||||
function normalize_header($header)
|
||||
{
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Psr7\Header::normalize($header);
|
||||
}
|
||||
/**
|
||||
* Clone and modify a request with the given changes.
|
||||
*
|
||||
* This method is useful for reducing the number of clones needed to mutate a
|
||||
* message.
|
||||
*
|
||||
* The changes can be one of:
|
||||
* - method: (string) Changes the HTTP method.
|
||||
* - set_headers: (array) Sets the given headers.
|
||||
* - remove_headers: (array) Remove the given headers.
|
||||
* - body: (mixed) Sets the given body.
|
||||
* - uri: (UriInterface) Set the URI.
|
||||
* - query: (string) Set the query string value of the URI.
|
||||
* - version: (string) Set the protocol version.
|
||||
*
|
||||
* @param RequestInterface $request Request to clone and modify.
|
||||
* @param array $changes Changes to apply.
|
||||
*
|
||||
* @return RequestInterface
|
||||
*
|
||||
* @deprecated modify_request will be removed in guzzlehttp/psr7:2.0. Use Utils::modifyRequest instead.
|
||||
*/
|
||||
function modify_request(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $changes)
|
||||
{
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::modifyRequest($request, $changes);
|
||||
}
|
||||
/**
|
||||
* Attempts to rewind a message body and throws an exception on failure.
|
||||
*
|
||||
* The body of the message will only be rewound if a call to `tell()` returns a
|
||||
* value other than `0`.
|
||||
*
|
||||
* @param MessageInterface $message Message to rewind
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
*
|
||||
* @deprecated rewind_body will be removed in guzzlehttp/psr7:2.0. Use Message::rewindBody instead.
|
||||
*/
|
||||
function rewind_body(\YoastSEO_Vendor\Psr\Http\Message\MessageInterface $message)
|
||||
{
|
||||
\YoastSEO_Vendor\GuzzleHttp\Psr7\Message::rewindBody($message);
|
||||
}
|
||||
/**
|
||||
* Safely opens a PHP stream resource using a filename.
|
||||
*
|
||||
* When fopen fails, PHP normally raises a warning. This function adds an
|
||||
* error handler that checks for errors and throws an exception instead.
|
||||
*
|
||||
* @param string $filename File to open
|
||||
* @param string $mode Mode used to open the file
|
||||
*
|
||||
* @return resource
|
||||
*
|
||||
* @throws \RuntimeException if the file cannot be opened
|
||||
*
|
||||
* @deprecated try_fopen will be removed in guzzlehttp/psr7:2.0. Use Utils::tryFopen instead.
|
||||
*/
|
||||
function try_fopen($filename, $mode)
|
||||
{
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::tryFopen($filename, $mode);
|
||||
}
|
||||
/**
|
||||
* Copy the contents of a stream into a string until the given number of
|
||||
* bytes have been read.
|
||||
*
|
||||
* @param StreamInterface $stream Stream to read
|
||||
* @param int $maxLen Maximum number of bytes to read. Pass -1
|
||||
* to read the entire stream.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws \RuntimeException on error.
|
||||
*
|
||||
* @deprecated copy_to_string will be removed in guzzlehttp/psr7:2.0. Use Utils::copyToString instead.
|
||||
*/
|
||||
function copy_to_string(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $stream, $maxLen = -1)
|
||||
{
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::copyToString($stream, $maxLen);
|
||||
}
|
||||
/**
|
||||
* Copy the contents of a stream into another stream until the given number
|
||||
* of bytes have been read.
|
||||
*
|
||||
* @param StreamInterface $source Stream to read from
|
||||
* @param StreamInterface $dest Stream to write to
|
||||
* @param int $maxLen Maximum number of bytes to read. Pass -1
|
||||
* to read the entire stream.
|
||||
*
|
||||
* @throws \RuntimeException on error.
|
||||
*
|
||||
* @deprecated copy_to_stream will be removed in guzzlehttp/psr7:2.0. Use Utils::copyToStream instead.
|
||||
*/
|
||||
function copy_to_stream(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $source, \YoastSEO_Vendor\Psr\Http\Message\StreamInterface $dest, $maxLen = -1)
|
||||
{
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::copyToStream($source, $dest, $maxLen);
|
||||
}
|
||||
/**
|
||||
* Calculate a hash of a stream.
|
||||
*
|
||||
* This method reads the entire stream to calculate a rolling hash, based on
|
||||
* PHP's `hash_init` functions.
|
||||
*
|
||||
* @param StreamInterface $stream Stream to calculate the hash for
|
||||
* @param string $algo Hash algorithm (e.g. md5, crc32, etc)
|
||||
* @param bool $rawOutput Whether or not to use raw output
|
||||
*
|
||||
* @return string Returns the hash of the stream
|
||||
*
|
||||
* @throws \RuntimeException on error.
|
||||
*
|
||||
* @deprecated hash will be removed in guzzlehttp/psr7:2.0. Use Utils::hash instead.
|
||||
*/
|
||||
function hash(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $stream, $algo, $rawOutput = \false)
|
||||
{
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::hash($stream, $algo, $rawOutput);
|
||||
}
|
||||
/**
|
||||
* Read a line from the stream up to the maximum allowed buffer length.
|
||||
*
|
||||
* @param StreamInterface $stream Stream to read from
|
||||
* @param int|null $maxLength Maximum buffer length
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @deprecated readline will be removed in guzzlehttp/psr7:2.0. Use Utils::readLine instead.
|
||||
*/
|
||||
function readline(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $stream, $maxLength = null)
|
||||
{
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::readLine($stream, $maxLength);
|
||||
}
|
||||
/**
|
||||
* Parses a request message string into a request object.
|
||||
*
|
||||
* @param string $message Request message string.
|
||||
*
|
||||
* @return Request
|
||||
*
|
||||
* @deprecated parse_request will be removed in guzzlehttp/psr7:2.0. Use Message::parseRequest instead.
|
||||
*/
|
||||
function parse_request($message)
|
||||
{
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Psr7\Message::parseRequest($message);
|
||||
}
|
||||
/**
|
||||
* Parses a response message string into a response object.
|
||||
*
|
||||
* @param string $message Response message string.
|
||||
*
|
||||
* @return Response
|
||||
*
|
||||
* @deprecated parse_response will be removed in guzzlehttp/psr7:2.0. Use Message::parseResponse instead.
|
||||
*/
|
||||
function parse_response($message)
|
||||
{
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Psr7\Message::parseResponse($message);
|
||||
}
|
||||
/**
|
||||
* Parse a query string into an associative array.
|
||||
*
|
||||
* If multiple values are found for the same key, the value of that key value
|
||||
* pair will become an array. This function does not parse nested PHP style
|
||||
* arrays into an associative array (e.g., `foo[a]=1&foo[b]=2` will be parsed
|
||||
* into `['foo[a]' => '1', 'foo[b]' => '2'])`.
|
||||
*
|
||||
* @param string $str Query string to parse
|
||||
* @param int|bool $urlEncoding How the query string is encoded
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @deprecated parse_query will be removed in guzzlehttp/psr7:2.0. Use Query::parse instead.
|
||||
*/
|
||||
function parse_query($str, $urlEncoding = \true)
|
||||
{
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Psr7\Query::parse($str, $urlEncoding);
|
||||
}
|
||||
/**
|
||||
* Build a query string from an array of key value pairs.
|
||||
*
|
||||
* This function can use the return value of `parse_query()` to build a query
|
||||
* string. This function does not modify the provided keys when an array is
|
||||
* encountered (like `http_build_query()` would).
|
||||
*
|
||||
* @param array $params Query string parameters.
|
||||
* @param int|false $encoding Set to false to not encode, PHP_QUERY_RFC3986
|
||||
* to encode using RFC3986, or PHP_QUERY_RFC1738
|
||||
* to encode using RFC1738.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @deprecated build_query will be removed in guzzlehttp/psr7:2.0. Use Query::build instead.
|
||||
*/
|
||||
function build_query(array $params, $encoding = \PHP_QUERY_RFC3986)
|
||||
{
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Psr7\Query::build($params, $encoding);
|
||||
}
|
||||
/**
|
||||
* Determines the mimetype of a file by looking at its extension.
|
||||
*
|
||||
* @param string $filename
|
||||
*
|
||||
* @return string|null
|
||||
*
|
||||
* @deprecated mimetype_from_filename will be removed in guzzlehttp/psr7:2.0. Use MimeType::fromFilename instead.
|
||||
*/
|
||||
function mimetype_from_filename($filename)
|
||||
{
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Psr7\MimeType::fromFilename($filename);
|
||||
}
|
||||
/**
|
||||
* Maps a file extensions to a mimetype.
|
||||
*
|
||||
* @param $extension string The file extension.
|
||||
*
|
||||
* @return string|null
|
||||
*
|
||||
* @link http://svn.apache.org/repos/asf/httpd/httpd/branches/1.3.x/conf/mime.types
|
||||
* @deprecated mimetype_from_extension will be removed in guzzlehttp/psr7:2.0. Use MimeType::fromExtension instead.
|
||||
*/
|
||||
function mimetype_from_extension($extension)
|
||||
{
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Psr7\MimeType::fromExtension($extension);
|
||||
}
|
||||
/**
|
||||
* Parses an HTTP message into an associative array.
|
||||
*
|
||||
* The array contains the "start-line" key containing the start line of
|
||||
* the message, "headers" key containing an associative array of header
|
||||
* array values, and a "body" key containing the body of the message.
|
||||
*
|
||||
* @param string $message HTTP request or response to parse.
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* @deprecated _parse_message will be removed in guzzlehttp/psr7:2.0. Use Message::parseMessage instead.
|
||||
*/
|
||||
function _parse_message($message)
|
||||
{
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Psr7\Message::parseMessage($message);
|
||||
}
|
||||
/**
|
||||
* Constructs a URI for an HTTP request message.
|
||||
*
|
||||
* @param string $path Path from the start-line
|
||||
* @param array $headers Array of headers (each value an array).
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* @deprecated _parse_request_uri will be removed in guzzlehttp/psr7:2.0. Use Message::parseRequestUri instead.
|
||||
*/
|
||||
function _parse_request_uri($path, array $headers)
|
||||
{
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Psr7\Message::parseRequestUri($path, $headers);
|
||||
}
|
||||
/**
|
||||
* Get a short summary of the message body.
|
||||
*
|
||||
* Will return `null` if the response is not printable.
|
||||
*
|
||||
* @param MessageInterface $message The message to get the body summary
|
||||
* @param int $truncateAt The maximum allowed size of the summary
|
||||
*
|
||||
* @return string|null
|
||||
*
|
||||
* @deprecated get_message_body_summary will be removed in guzzlehttp/psr7:2.0. Use Message::bodySummary instead.
|
||||
*/
|
||||
function get_message_body_summary(\YoastSEO_Vendor\Psr\Http\Message\MessageInterface $message, $truncateAt = 120)
|
||||
{
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Psr7\Message::bodySummary($message, $truncateAt);
|
||||
}
|
||||
/**
|
||||
* Remove the items given by the keys, case insensitively from the data.
|
||||
*
|
||||
* @param iterable<string> $keys
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* @deprecated _caseless_remove will be removed in guzzlehttp/psr7:2.0. Use Utils::caselessRemove instead.
|
||||
*/
|
||||
function _caseless_remove($keys, array $data)
|
||||
{
|
||||
return \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::caselessRemove($keys, $data);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace YoastSEO_Vendor;
|
||||
|
||||
// Don't redefine the functions if included multiple times.
|
||||
if (!\function_exists('YoastSEO_Vendor\\GuzzleHttp\\Psr7\\str')) {
|
||||
require __DIR__ . '/functions.php';
|
||||
}
|
||||
Reference in New Issue
Block a user