Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • dmj/selbstzeugnisse-hab
  • goermar/selbstzeugnisse-hab
2 results
Show changes
Showing
with 399 additions and 52 deletions
...@@ -66,7 +66,7 @@ class MockHandler implements \Countable ...@@ -66,7 +66,7 @@ class MockHandler implements \Countable
throw new \OutOfBoundsException('Mock queue is empty'); throw new \OutOfBoundsException('Mock queue is empty');
} }
if (isset($options['delay'])) { if (isset($options['delay']) && is_numeric($options['delay'])) {
usleep($options['delay'] * 1000); usleep($options['delay'] * 1000);
} }
...@@ -175,6 +175,11 @@ class MockHandler implements \Countable ...@@ -175,6 +175,11 @@ class MockHandler implements \Countable
return count($this->queue); return count($this->queue);
} }
public function reset()
{
$this->queue = [];
}
private function invokeStats( private function invokeStats(
RequestInterface $request, RequestInterface $request,
array $options, array $options,
...@@ -182,7 +187,8 @@ class MockHandler implements \Countable ...@@ -182,7 +187,8 @@ class MockHandler implements \Countable
$reason = null $reason = null
) { ) {
if (isset($options['on_stats'])) { if (isset($options['on_stats'])) {
$stats = new TransferStats($request, $response, 0, $reason); $transferTime = isset($options['transfer_time']) ? $options['transfer_time'] : 0;
$stats = new TransferStats($request, $response, $transferTime, $reason);
call_user_func($options['on_stats'], $stats); call_user_func($options['on_stats'], $stats);
} }
} }
......
<?php <?php
namespace GuzzleHttp\Handler; namespace GuzzleHttp\Handler;
use GuzzleHttp\Exception\RequestException;
use GuzzleHttp\Exception\ConnectException; use GuzzleHttp\Exception\ConnectException;
use GuzzleHttp\Exception\RequestException;
use GuzzleHttp\Promise\FulfilledPromise; use GuzzleHttp\Promise\FulfilledPromise;
use GuzzleHttp\Promise\PromiseInterface; use GuzzleHttp\Promise\PromiseInterface;
use GuzzleHttp\Psr7; use GuzzleHttp\Psr7;
use GuzzleHttp\TransferStats; use GuzzleHttp\TransferStats;
use GuzzleHttp\Utils;
use Psr\Http\Message\RequestInterface; use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\StreamInterface; use Psr\Http\Message\StreamInterface;
...@@ -33,7 +34,7 @@ class StreamHandler ...@@ -33,7 +34,7 @@ class StreamHandler
usleep($options['delay'] * 1000); usleep($options['delay'] * 1000);
} }
$startTime = isset($options['on_stats']) ? microtime(true) : null; $startTime = isset($options['on_stats']) ? Utils::currentTime() : null;
try { try {
// Does not support the expect header. // Does not support the expect header.
...@@ -42,7 +43,7 @@ class StreamHandler ...@@ -42,7 +43,7 @@ class StreamHandler
// Append a content-length header if body size is zero to match // Append a content-length header if body size is zero to match
// cURL's behavior. // cURL's behavior.
if (0 === $request->getBody()->getSize()) { if (0 === $request->getBody()->getSize()) {
$request = $request->withHeader('Content-Length', 0); $request = $request->withHeader('Content-Length', '0');
} }
return $this->createResponse( return $this->createResponse(
...@@ -82,7 +83,7 @@ class StreamHandler ...@@ -82,7 +83,7 @@ class StreamHandler
$stats = new TransferStats( $stats = new TransferStats(
$request, $request,
$response, $response,
microtime(true) - $startTime, Utils::currentTime() - $startTime,
$error, $error,
[] []
); );
...@@ -343,13 +344,25 @@ class StreamHandler ...@@ -343,13 +344,25 @@ class StreamHandler
if ('v4' === $options['force_ip_resolve']) { if ('v4' === $options['force_ip_resolve']) {
$records = dns_get_record($uri->getHost(), DNS_A); $records = dns_get_record($uri->getHost(), DNS_A);
if (!isset($records[0]['ip'])) { if (!isset($records[0]['ip'])) {
throw new ConnectException(sprintf("Could not resolve IPv4 address for host '%s'", $uri->getHost()), $request); throw new ConnectException(
sprintf(
"Could not resolve IPv4 address for host '%s'",
$uri->getHost()
),
$request
);
} }
$uri = $uri->withHost($records[0]['ip']); $uri = $uri->withHost($records[0]['ip']);
} elseif ('v6' === $options['force_ip_resolve']) { } elseif ('v6' === $options['force_ip_resolve']) {
$records = dns_get_record($uri->getHost(), DNS_AAAA); $records = dns_get_record($uri->getHost(), DNS_AAAA);
if (!isset($records[0]['ipv6'])) { if (!isset($records[0]['ipv6'])) {
throw new ConnectException(sprintf("Could not resolve IPv6 address for host '%s'", $uri->getHost()), $request); throw new ConnectException(
sprintf(
"Could not resolve IPv6 address for host '%s'",
$uri->getHost()
),
$request
);
} }
$uri = $uri->withHost('[' . $records[0]['ipv6'] . ']'); $uri = $uri->withHost('[' . $records[0]['ipv6'] . ']');
} }
......
<?php <?php
namespace GuzzleHttp; namespace GuzzleHttp;
use GuzzleHttp\Promise\PromiseInterface;
use Psr\Http\Message\RequestInterface; use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
/** /**
* Creates a composed Guzzle handler function by stacking middlewares on top of * Creates a composed Guzzle handler function by stacking middlewares on top of
...@@ -9,7 +11,7 @@ use Psr\Http\Message\RequestInterface; ...@@ -9,7 +11,7 @@ use Psr\Http\Message\RequestInterface;
*/ */
class HandlerStack class HandlerStack
{ {
/** @var callable */ /** @var callable|null */
private $handler; private $handler;
/** @var array */ /** @var array */
...@@ -59,6 +61,8 @@ class HandlerStack ...@@ -59,6 +61,8 @@ class HandlerStack
* *
* @param RequestInterface $request * @param RequestInterface $request
* @param array $options * @param array $options
*
* @return ResponseInterface|PromiseInterface
*/ */
public function __invoke(RequestInterface $request, array $options) public function __invoke(RequestInterface $request, array $options)
{ {
...@@ -206,7 +210,7 @@ class HandlerStack ...@@ -206,7 +210,7 @@ class HandlerStack
} }
/** /**
* @param $name * @param string $name
* @return int * @return int
*/ */
private function findByName($name) private function findByName($name)
...@@ -223,10 +227,10 @@ class HandlerStack ...@@ -223,10 +227,10 @@ class HandlerStack
/** /**
* Splices a function into the middleware list at a specific position. * Splices a function into the middleware list at a specific position.
* *
* @param $findName * @param string $findName
* @param $withName * @param string $withName
* @param callable $middleware * @param callable $middleware
* @param $before * @param bool $before
*/ */
private function splice($findName, $withName, callable $middleware, $before) private function splice($findName, $withName, callable $middleware, $before)
{ {
......
...@@ -168,6 +168,11 @@ class MessageFormatter ...@@ -168,6 +168,11 @@ class MessageFormatter
); );
} }
/**
* Get headers from message as string
*
* @return string
*/
private function headers(MessageInterface $message) private function headers(MessageInterface $message)
{ {
$result = ''; $result = '';
......
...@@ -7,7 +7,6 @@ use GuzzleHttp\Promise\RejectedPromise; ...@@ -7,7 +7,6 @@ use GuzzleHttp\Promise\RejectedPromise;
use GuzzleHttp\Psr7; use GuzzleHttp\Psr7;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Psr\Log\LogLevel;
/** /**
* Functions used to create and wrap handlers with handler middleware. * Functions used to create and wrap handlers with handler middleware.
...@@ -39,7 +38,7 @@ final class Middleware ...@@ -39,7 +38,7 @@ final class Middleware
$cookieJar->extractCookies($request, $response); $cookieJar->extractCookies($request, $response);
return $response; return $response;
} }
); );
}; };
}; };
} }
...@@ -58,7 +57,7 @@ final class Middleware ...@@ -58,7 +57,7 @@ final class Middleware
return $handler($request, $options); return $handler($request, $options);
} }
return $handler($request, $options)->then( return $handler($request, $options)->then(
function (ResponseInterface $response) use ($request, $handler) { function (ResponseInterface $response) use ($request) {
$code = $response->getStatusCode(); $code = $response->getStatusCode();
if ($code < 400) { if ($code < 400) {
return $response; return $response;
...@@ -183,7 +182,7 @@ final class Middleware ...@@ -183,7 +182,7 @@ final class Middleware
* *
* @return callable Returns a function that accepts the next handler. * @return callable Returns a function that accepts the next handler.
*/ */
public static function log(LoggerInterface $logger, MessageFormatter $formatter, $logLevel = LogLevel::INFO) public static function log(LoggerInterface $logger, MessageFormatter $formatter, $logLevel = 'info' /* \Psr\Log\LogLevel::INFO */)
{ {
return function (callable $handler) use ($logger, $formatter, $logLevel) { return function (callable $handler) use ($logger, $formatter, $logLevel) {
return function ($request, array $options) use ($handler, $logger, $formatter, $logLevel) { return function ($request, array $options) use ($handler, $logger, $formatter, $logLevel) {
......
<?php <?php
namespace GuzzleHttp; namespace GuzzleHttp;
use GuzzleHttp\Promise\EachPromise;
use GuzzleHttp\Promise\PromiseInterface;
use GuzzleHttp\Promise\PromisorInterface; use GuzzleHttp\Promise\PromisorInterface;
use Psr\Http\Message\RequestInterface; use Psr\Http\Message\RequestInterface;
use GuzzleHttp\Promise\EachPromise;
/** /**
* Sends and iterator of requests concurrently using a capped pool size. * Sends an iterator of requests concurrently using a capped pool size.
* *
* The pool will read from an iterator until it is cancelled or until the * The pool will read from an iterator until it is cancelled or until the
* iterator is consumed. When a request is yielded, the request is sent after * iterator is consumed. When a request is yielded, the request is sent after
...@@ -69,6 +70,11 @@ class Pool implements PromisorInterface ...@@ -69,6 +70,11 @@ class Pool implements PromisorInterface
$this->each = new EachPromise($requests(), $config); $this->each = new EachPromise($requests(), $config);
} }
/**
* Get promise
*
* @return PromiseInterface
*/
public function promise() public function promise()
{ {
return $this->each->promise(); return $this->each->promise();
...@@ -106,6 +112,11 @@ class Pool implements PromisorInterface ...@@ -106,6 +112,11 @@ class Pool implements PromisorInterface
return $res; return $res;
} }
/**
* Execute callback(s)
*
* @return void
*/
private static function cmpCallback(array &$options, $name, array &$results) private static function cmpCallback(array &$options, $name, array &$results)
{ {
if (!isset($options[$name])) { if (!isset($options[$name])) {
......
...@@ -66,6 +66,11 @@ class PrepareBodyMiddleware ...@@ -66,6 +66,11 @@ class PrepareBodyMiddleware
return $fn(Psr7\modify_request($request, $modify), $options); return $fn(Psr7\modify_request($request, $modify), $options);
} }
/**
* Add expect header
*
* @return void
*/
private function addExpectHeader( private function addExpectHeader(
RequestInterface $request, RequestInterface $request,
array $options, array $options,
......
...@@ -13,7 +13,7 @@ use Psr\Http\Message\UriInterface; ...@@ -13,7 +13,7 @@ use Psr\Http\Message\UriInterface;
* Request redirect middleware. * Request redirect middleware.
* *
* Apply this middleware like other middleware using * Apply this middleware like other middleware using
* {@see GuzzleHttp\Middleware::redirect()}. * {@see \GuzzleHttp\Middleware::redirect()}.
*/ */
class RedirectMiddleware class RedirectMiddleware
{ {
...@@ -76,7 +76,7 @@ class RedirectMiddleware ...@@ -76,7 +76,7 @@ class RedirectMiddleware
/** /**
* @param RequestInterface $request * @param RequestInterface $request
* @param array $options * @param array $options
* @param ResponseInterface|PromiseInterface $response * @param ResponseInterface $response
* *
* @return ResponseInterface|PromiseInterface * @return ResponseInterface|PromiseInterface
*/ */
...@@ -118,6 +118,11 @@ class RedirectMiddleware ...@@ -118,6 +118,11 @@ class RedirectMiddleware
return $promise; return $promise;
} }
/**
* Enable tracking on promise.
*
* @return PromiseInterface
*/
private function withTracking(PromiseInterface $promise, $uri, $statusCode) private function withTracking(PromiseInterface $promise, $uri, $statusCode)
{ {
return $promise->then( return $promise->then(
...@@ -135,6 +140,13 @@ class RedirectMiddleware ...@@ -135,6 +140,13 @@ class RedirectMiddleware
); );
} }
/**
* Check for too many redirects
*
* @return void
*
* @throws TooManyRedirectsException Too many redirects.
*/
private function guardMax(RequestInterface $request, array &$options) private function guardMax(RequestInterface $request, array &$options)
{ {
$current = isset($options['__redirect_count']) $current = isset($options['__redirect_count'])
...@@ -172,13 +184,19 @@ class RedirectMiddleware ...@@ -172,13 +184,19 @@ class RedirectMiddleware
// would do. // would do.
$statusCode = $response->getStatusCode(); $statusCode = $response->getStatusCode();
if ($statusCode == 303 || if ($statusCode == 303 ||
($statusCode <= 302 && $request->getBody() && !$options['allow_redirects']['strict']) ($statusCode <= 302 && !$options['allow_redirects']['strict'])
) { ) {
$modify['method'] = 'GET'; $modify['method'] = 'GET';
$modify['body'] = ''; $modify['body'] = '';
} }
$modify['uri'] = $this->redirectUri($request, $response, $protocols); $uri = $this->redirectUri($request, $response, $protocols);
if (isset($options['idn_conversion']) && ($options['idn_conversion'] !== false)) {
$idnOptions = ($options['idn_conversion'] === true) ? IDNA_DEFAULT : $options['idn_conversion'];
$uri = Utils::idnUriConvert($uri, $idnOptions);
}
$modify['uri'] = $uri;
Psr7\rewind_body($request); Psr7\rewind_body($request);
// Add the Referer header if it is told to do so and only // Add the Referer header if it is told to do so and only
...@@ -186,7 +204,7 @@ class RedirectMiddleware ...@@ -186,7 +204,7 @@ class RedirectMiddleware
if ($options['allow_redirects']['referer'] if ($options['allow_redirects']['referer']
&& $modify['uri']->getScheme() === $request->getUri()->getScheme() && $modify['uri']->getScheme() === $request->getUri()->getScheme()
) { ) {
$uri = $request->getUri()->withUserInfo('', ''); $uri = $request->getUri()->withUserInfo('');
$modify['set_headers']['Referer'] = (string) $uri; $modify['set_headers']['Referer'] = (string) $uri;
} else { } else {
$modify['remove_headers'][] = 'Referer'; $modify['remove_headers'][] = 'Referer';
......
...@@ -22,7 +22,7 @@ final class RequestOptions ...@@ -22,7 +22,7 @@ final class RequestOptions
* - strict: (bool, default=false) Set to true to use strict redirects * - strict: (bool, default=false) Set to true to use strict redirects
* meaning redirect POST requests with POST requests vs. doing what most * meaning redirect POST requests with POST requests vs. doing what most
* browsers do which is redirect POST requests with GET requests * browsers do which is redirect POST requests with GET requests
* - referer: (bool, default=true) Set to false to disable the Referer * - referer: (bool, default=false) Set to true to enable the Referer
* header. * header.
* - protocols: (array, default=['http', 'https']) Allowed redirect * - protocols: (array, default=['http', 'https']) Allowed redirect
* protocols. * protocols.
...@@ -132,6 +132,14 @@ final class RequestOptions ...@@ -132,6 +132,14 @@ final class RequestOptions
*/ */
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).
*/
const IDN_CONVERSION = 'idn_conversion';
/** /**
* json: (mixed) Adds JSON data to a request. The provided value is JSON * 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 * encoded and a Content-Type header of application/json will be added to
......
...@@ -19,6 +19,9 @@ class RetryMiddleware ...@@ -19,6 +19,9 @@ class RetryMiddleware
/** @var callable */ /** @var callable */
private $decider; private $decider;
/** @var callable */
private $delay;
/** /**
* @param callable $decider Function that accepts the number of retries, * @param callable $decider Function that accepts the number of retries,
* a request, [response], and [exception] and * a request, [response], and [exception] and
...@@ -42,13 +45,13 @@ class RetryMiddleware ...@@ -42,13 +45,13 @@ class RetryMiddleware
/** /**
* Default exponential backoff delay function. * Default exponential backoff delay function.
* *
* @param $retries * @param int $retries
* *
* @return int * @return int milliseconds.
*/ */
public static function exponentialDelay($retries) public static function exponentialDelay($retries)
{ {
return (int) pow(2, $retries - 1); return (int) pow(2, $retries - 1) * 1000;
} }
/** /**
...@@ -71,6 +74,11 @@ class RetryMiddleware ...@@ -71,6 +74,11 @@ class RetryMiddleware
); );
} }
/**
* Execute fulfilled closure
*
* @return mixed
*/
private function onFulfilled(RequestInterface $req, array $options) private function onFulfilled(RequestInterface $req, array $options)
{ {
return function ($value) use ($req, $options) { return function ($value) use ($req, $options) {
...@@ -87,6 +95,11 @@ class RetryMiddleware ...@@ -87,6 +95,11 @@ class RetryMiddleware
}; };
} }
/**
* Execute rejected closure
*
* @return callable
*/
private function onRejected(RequestInterface $req, array $options) private function onRejected(RequestInterface $req, array $options)
{ {
return function ($reason) use ($req, $options) { return function ($reason) use ($req, $options) {
...@@ -103,6 +116,9 @@ class RetryMiddleware ...@@ -103,6 +116,9 @@ class RetryMiddleware
}; };
} }
/**
* @return self
*/
private function doRetry(RequestInterface $request, array $options, ResponseInterface $response = null) private function doRetry(RequestInterface $request, array $options, ResponseInterface $response = null)
{ {
$options['delay'] = call_user_func($this->delay, ++$options['retries'], $response); $options['delay'] = call_user_func($this->delay, ++$options['retries'], $response);
......
...@@ -18,11 +18,11 @@ final class TransferStats ...@@ -18,11 +18,11 @@ final class TransferStats
private $handlerErrorData; private $handlerErrorData;
/** /**
* @param RequestInterface $request Request that was sent. * @param RequestInterface $request Request that was sent.
* @param ResponseInterface $response Response received (if any) * @param ResponseInterface|null $response Response received (if any)
* @param null $transferTime Total handler transfer time. * @param float|null $transferTime Total handler transfer time.
* @param mixed $handlerErrorData Handler error data. * @param mixed $handlerErrorData Handler error data.
* @param array $handlerStats Handler specific stats. * @param array $handlerStats Handler specific stats.
*/ */
public function __construct( public function __construct(
RequestInterface $request, RequestInterface $request,
...@@ -93,7 +93,7 @@ final class TransferStats ...@@ -93,7 +93,7 @@ final class TransferStats
/** /**
* Get the estimated time the request was being transferred by the handler. * Get the estimated time the request was being transferred by the handler.
* *
* @return float Time in seconds. * @return float|null Time in seconds.
*/ */
public function getTransferTime() public function getTransferTime()
{ {
......
<?php
namespace GuzzleHttp;
use GuzzleHttp\Exception\InvalidArgumentException;
use Psr\Http\Message\UriInterface;
use Symfony\Polyfill\Intl\Idn\Idn;
final class Utils
{
/**
* Wrapper for the hrtime() or microtime() functions
* (depending on the PHP version, one of the two is used)
*
* @return float|mixed UNIX timestamp
*
* @internal
*/
public static function currentTime()
{
return function_exists('hrtime') ? hrtime(true) / 1e9 : microtime(true);
}
/**
* @param int $options
*
* @return UriInterface
* @throws InvalidArgumentException
*
* @internal
*/
public static function idnUriConvert(UriInterface $uri, $options = 0)
{
if ($uri->getHost()) {
$asciiHost = self::idnToAsci($uri->getHost(), $options, $info);
if ($asciiHost === false) {
$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 = [];
foreach ($errorConstants as $errorConstant) {
if ($errorBitSet & constant($errorConstant)) {
$errors[] = $errorConstant;
}
}
$errorMessage = 'IDN conversion failed';
if ($errors) {
$errorMessage .= ' (errors: ' . implode(', ', $errors) . ')';
}
throw new InvalidArgumentException($errorMessage);
} else {
if ($uri->getHost() !== $asciiHost) {
// Replace URI only if the ASCII version is different
$uri = $uri->withHost($asciiHost);
}
}
}
return $uri;
}
/**
* @param string $domain
* @param int $options
* @param array $info
*
* @return string|false
*/
private static function idnToAsci($domain, $options, &$info = [])
{
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);
}
/*
* The Idn class is marked as @internal. Verify that class and method exists.
*/
if (method_exists(Idn::class, 'idn_to_ascii')) {
return Idn::idn_to_ascii($domain, $options, Idn::INTL_IDNA_VARIANT_UTS46, $info);
}
throw new \RuntimeException('ext-intl or symfony/polyfill-intl-idn not loaded or too old');
}
}
...@@ -56,7 +56,7 @@ function describe_type($input) ...@@ -56,7 +56,7 @@ function describe_type($input)
/** /**
* Parses an array of header lines into an associative array of headers. * Parses an array of header lines into an associative array of headers.
* *
* @param array $lines Header lines array of strings in the following * @param iterable $lines Header lines array of strings in the following
* format: "Name: Value" * format: "Name: Value"
* @return array * @return array
*/ */
...@@ -97,8 +97,8 @@ function debug_resource($value = null) ...@@ -97,8 +97,8 @@ function debug_resource($value = null)
* *
* The returned handler is not wrapped by any default middlewares. * The returned handler is not wrapped by any default middlewares.
* *
* @throws \RuntimeException if no viable Handler is available.
* @return callable 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.
*/ */
function choose_handler() function choose_handler()
{ {
...@@ -196,7 +196,8 @@ function default_ca_bundle() ...@@ -196,7 +196,8 @@ function default_ca_bundle()
} }
} }
throw new \RuntimeException(<<< EOT throw new \RuntimeException(
<<< EOT
No system CA bundle could be found in any of the the common system locations. 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 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 CA bundle by default. In order to verify peer certificates, you will need to
...@@ -294,14 +295,14 @@ function is_host_in_noproxy($host, array $noProxyArray) ...@@ -294,14 +295,14 @@ function is_host_in_noproxy($host, array $noProxyArray)
* @param int $options Bitmask of JSON decode options. * @param int $options Bitmask of JSON decode options.
* *
* @return mixed * @return mixed
* @throws \InvalidArgumentException if the JSON cannot be decoded. * @throws Exception\InvalidArgumentException if the JSON cannot be decoded.
* @link http://www.php.net/manual/en/function.json-decode.php * @link http://www.php.net/manual/en/function.json-decode.php
*/ */
function json_decode($json, $assoc = false, $depth = 512, $options = 0) function json_decode($json, $assoc = false, $depth = 512, $options = 0)
{ {
$data = \json_decode($json, $assoc, $depth, $options); $data = \json_decode($json, $assoc, $depth, $options);
if (JSON_ERROR_NONE !== json_last_error()) { if (JSON_ERROR_NONE !== json_last_error()) {
throw new \InvalidArgumentException( throw new Exception\InvalidArgumentException(
'json_decode error: ' . json_last_error_msg() 'json_decode error: ' . json_last_error_msg()
); );
} }
...@@ -317,14 +318,14 @@ function json_decode($json, $assoc = false, $depth = 512, $options = 0) ...@@ -317,14 +318,14 @@ function json_decode($json, $assoc = false, $depth = 512, $options = 0)
* @param int $depth Set the maximum depth. Must be greater than zero. * @param int $depth Set the maximum depth. Must be greater than zero.
* *
* @return string * @return string
* @throws \InvalidArgumentException if the JSON cannot be encoded. * @throws Exception\InvalidArgumentException if the JSON cannot be encoded.
* @link http://www.php.net/manual/en/function.json-encode.php * @link http://www.php.net/manual/en/function.json-encode.php
*/ */
function json_encode($value, $options = 0, $depth = 512) function json_encode($value, $options = 0, $depth = 512)
{ {
$json = \json_encode($value, $options, $depth); $json = \json_encode($value, $options, $depth);
if (JSON_ERROR_NONE !== json_last_error()) { if (JSON_ERROR_NONE !== json_last_error()) {
throw new \InvalidArgumentException( throw new Exception\InvalidArgumentException(
'json_encode error: ' . json_last_error_msg() 'json_encode error: ' . json_last_error_msg()
); );
} }
......
<?php
$config = PhpCsFixer\Config::create()
->setRiskyAllowed(true)
->setRules([
'@PSR2' => true,
'array_syntax' => ['syntax' => 'short'],
'binary_operator_spaces' => ['operators' => ['=>' => null]],
'blank_line_after_opening_tag' => true,
'class_attributes_separation' => ['elements' => ['method']],
'compact_nullable_typehint' => true,
'concat_space' => ['spacing' => 'one'],
'declare_equal_normalize' => ['space' => 'none'],
'declare_strict_types' => false,
'dir_constant' => true,
'final_static_access' => true,
'fully_qualified_strict_types' => true,
'function_to_constant' => true,
'function_typehint_space' => true,
'header_comment' => false,
'is_null' => ['use_yoda_style' => false],
'list_syntax' => ['syntax' => 'short'],
'lowercase_cast' => true,
'magic_method_casing' => true,
'modernize_types_casting' => true,
'multiline_comment_opening_closing' => true,
//'native_constant_invocation' => true,
'no_alias_functions' => true,
'no_alternative_syntax' => true,
'no_blank_lines_after_phpdoc' => true,
'no_empty_comment' => true,
'no_empty_phpdoc' => true,
'no_extra_blank_lines' => true,
'no_leading_import_slash' => true,
'no_leading_namespace_whitespace' => true,
'no_spaces_around_offset' => true,
'no_superfluous_phpdoc_tags' => ['allow_mixed' => true],
'no_trailing_comma_in_singleline_array' => true,
'no_unneeded_control_parentheses' => true,
'no_unset_cast' => true,
'no_unused_imports' => true,
'no_useless_else' => true,
'no_useless_return' => true,
'no_whitespace_in_blank_line' => true,
'normalize_index_brace' => true,
'ordered_imports' => true,
'php_unit_construct' => true,
'php_unit_dedicate_assert' => ['target' => 'newest'],
'php_unit_dedicate_assert_internal_type' => ['target' => 'newest'],
'php_unit_expectation' => ['target' => 'newest'],
'php_unit_mock' => ['target' => 'newest'],
'php_unit_mock_short_will_return' => true,
'php_unit_no_expectation_annotation' => ['target' => 'newest'],
'php_unit_test_annotation' => ['style' => 'prefix'],
//'php_unit_test_case_static_method_calls' => ['call_type' => 'self'],
'phpdoc_align' => ['align' => 'vertical'],
//'phpdoc_line_span' => ['method' => 'multi', 'property' => 'multi'],
'phpdoc_no_package' => true,
'phpdoc_no_useless_inheritdoc' => true,
'phpdoc_scalar' => true,
'phpdoc_separation' => true,
'phpdoc_single_line_var_spacing' => true,
'phpdoc_trim' => true,
'phpdoc_trim_consecutive_blank_line_separation' => true,
'phpdoc_types' => true,
'phpdoc_types_order' => ['null_adjustment' => 'always_last', 'sort_algorithm' => 'none'],
'phpdoc_var_without_name' => true,
'return_assignment' => true,
'short_scalar_cast' => true,
'single_trait_insert_per_statement' => true,
'standardize_not_equals' => true,
//'static_lambda' => true,
'ternary_to_null_coalescing' => true,
'trim_array_spaces' => true,
'visibility_required' => true,
'yoda_style' => false,
// 'native_function_invocation' => true,
'braces' => ['allow_single_line_closure'=>true],
])
->setFinder(
PhpCsFixer\Finder::create()
->in(__DIR__.'/src')
->in(__DIR__.'/tests')
->name('*.php')
)
;
return $config;
# CHANGELOG # CHANGELOG
## 1.4.0 - 2020-09-30
### Added
- Support for PHP 8
- Optional `$recursive` flag to `all`
- Replaced functions by static methods
### Fixed
- Fix empty `each` processing
- Fix promise handling for Iterators of non-unique keys
- Fixed `method_exists` crashes on PHP 8
- Memory leak on exceptions
## 1.3.1 - 2016-12-20 ## 1.3.1 - 2016-12-20
### Fixed ### Fixed
......
...@@ -26,7 +26,7 @@ for a general introduction to promises. ...@@ -26,7 +26,7 @@ for a general introduction to promises.
- Promises can be cancelled. - Promises can be cancelled.
- Works with any object that has a `then` function. - Works with any object that has a `then` function.
- C# style async/await coroutine promises using - C# style async/await coroutine promises using
`GuzzleHttp\Promise\coroutine()`. `GuzzleHttp\Promise\Coroutine::of()`.
# Quick start # Quick start
...@@ -88,7 +88,7 @@ $promise ...@@ -88,7 +88,7 @@ $promise
}); });
// Resolving the promise triggers the $onFulfilled callbacks and outputs // Resolving the promise triggers the $onFulfilled callbacks and outputs
// "Hello, reader". // "Hello, reader."
$promise->resolve('reader.'); $promise->resolve('reader.');
``` ```
...@@ -150,7 +150,7 @@ use GuzzleHttp\Promise\Promise; ...@@ -150,7 +150,7 @@ use GuzzleHttp\Promise\Promise;
$promise = new Promise(); $promise = new Promise();
$promise->then(null, function ($reason) { $promise->then(null, function ($reason) {
throw new \Exception($reason); throw new Exception($reason);
})->then(null, function ($reason) { })->then(null, function ($reason) {
assert($reason->getMessage() === 'Error!'); assert($reason->getMessage() === 'Error!');
}); });
...@@ -182,7 +182,6 @@ invoked using the value returned from the `$onRejected` callback. ...@@ -182,7 +182,6 @@ invoked using the value returned from the `$onRejected` callback.
```php ```php
use GuzzleHttp\Promise\Promise; use GuzzleHttp\Promise\Promise;
use GuzzleHttp\Promise\RejectedPromise;
$promise = new Promise(); $promise = new Promise();
$promise $promise
...@@ -220,7 +219,7 @@ the promise is rejected with the exception and the exception is thrown. ...@@ -220,7 +219,7 @@ the promise is rejected with the exception and the exception is thrown.
```php ```php
$promise = new Promise(function () use (&$promise) { $promise = new Promise(function () use (&$promise) {
throw new \Exception('foo'); throw new Exception('foo');
}); });
$promise->wait(); // throws the exception. $promise->wait(); // throws the exception.
...@@ -397,7 +396,7 @@ $deferred = new React\Promise\Deferred(); ...@@ -397,7 +396,7 @@ $deferred = new React\Promise\Deferred();
$reactPromise = $deferred->promise(); $reactPromise = $deferred->promise();
// Create a Guzzle promise that is fulfilled with a React promise. // Create a Guzzle promise that is fulfilled with a React promise.
$guzzlePromise = new \GuzzleHttp\Promise\Promise(); $guzzlePromise = new GuzzleHttp\Promise\Promise();
$guzzlePromise->then(function ($value) use ($reactPromise) { $guzzlePromise->then(function ($value) use ($reactPromise) {
// Do something something with the value... // Do something something with the value...
// Return the React promise // Return the React promise
...@@ -424,7 +423,7 @@ instance. ...@@ -424,7 +423,7 @@ instance.
```php ```php
// Get the global task queue // Get the global task queue
$queue = \GuzzleHttp\Promise\queue(); $queue = GuzzleHttp\Promise\Utils::queue();
$queue->run(); $queue->run();
``` ```
...@@ -502,3 +501,32 @@ $promise->then(function ($value) { echo $value; }); ...@@ -502,3 +501,32 @@ $promise->then(function ($value) { echo $value; });
$promise->resolve('foo'); $promise->resolve('foo');
// prints "foo" // prints "foo"
``` ```
## Upgrading from Function API
A static API was first introduced in 1.4.0, in order to mitigate problems with functions conflicting between global and local copies of the package. The function API will be removed in 2.0.0. A migration table has been provided here for your convenience:
| Original Function | Replacement Method |
|----------------|----------------|
| `queue` | `Utils::queue` |
| `task` | `Utils::task` |
| `promise_for` | `Create::promiseFor` |
| `rejection_for` | `Create::rejectionFor` |
| `exception_for` | `Create::exceptionFor` |
| `iter_for` | `Create::iterFor` |
| `inspect` | `Utils::inspect` |
| `inspect_all` | `Utils::inspectAll` |
| `unwrap` | `Utils::unwrap` |
| `all` | `Utils::all` |
| `some` | `Utils::some` |
| `any` | `Utils::any` |
| `settle` | `Utils::settle` |
| `each` | `Each::of` |
| `each_limit` | `Each::ofLimit` |
| `each_limit_all` | `Each::ofLimitAll` |
| `!is_fulfilled` | `Is::pending` |
| `is_fulfilled` | `Is::fulfilled` |
| `is_rejected` | `Is::rejected` |
| `is_settled` | `Is::settled` |
| `coroutine` | `Coroutine::of` |
...@@ -11,10 +11,10 @@ ...@@ -11,10 +11,10 @@
} }
], ],
"require": { "require": {
"php": ">=5.5.0" "php": ">=5.5"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "^4.0" "symfony/phpunit-bridge": "^4.4 || ^5.1"
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {
...@@ -22,9 +22,14 @@ ...@@ -22,9 +22,14 @@
}, },
"files": ["src/functions_include.php"] "files": ["src/functions_include.php"]
}, },
"autoload-dev": {
"psr-4": {
"GuzzleHttp\\Promise\\Tests\\": "tests/"
}
},
"scripts": { "scripts": {
"test": "vendor/bin/phpunit", "test": "vendor/bin/simple-phpunit",
"test-ci": "vendor/bin/phpunit --coverage-text" "test-ci": "vendor/bin/simple-phpunit --coverage-text"
}, },
"extra": { "extra": {
"branch-alias": { "branch-alias": {
......
parameters:
ignoreErrors:
-
message: "#^Parameter \\#1 \\$function of function register_shutdown_function expects callable\\(\\)\\: void, Closure\\(\\)\\: mixed given\\.$#"
count: 1
path: src/TaskQueue.php
includes:
- phpstan-baseline.neon
parameters:
level: 5
paths:
- src
ignoreErrors:
- "#^Dead catch - Exception is already caught by Throwable above\\.$#"
<?xml version="1.0"?>
<psalm
errorLevel="4"
resolveFromConfigFile="true"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="https://getpsalm.org/schema/config"
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
>
<projectFiles>
<directory name="src" />
<ignoreFiles>
<directory name="vendor" />
</ignoreFiles>
</projectFiles>
</psalm>