From 654d736df2c46ec2520f73e9089d06a44f2b9c50 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Thu, 9 Jun 2022 23:27:33 +0200 Subject: [PATCH] update to PHP-8.1 --- README.md | 2 +- composer.json | 18 +- examples/amploop.php | 174 +- examples/cache.php | 29 +- examples/cli.php | 5 +- examples/examples.inc | 16 + examples/generator.php | 12 +- examples/gistlog.php | 13 +- examples/hooks.php | 13 +- examples/promise.php | 8 +- examples/readme.php | 5 +- examples/watchowned.php | 16 +- http.stub.php | 3424 ----------------------- lib/API.php | 117 +- lib/API/Call.php | 14 +- lib/API/Call/Cache.php | 32 +- lib/API/Call/Cache/Control.php | 5 +- lib/API/Call/Cache/Service.php | 4 +- lib/API/Call/Cache/Service/Hollow.php | 6 +- lib/API/Call/Cache/Service/ItemPool.php | 17 +- lib/API/Call/Cache/Service/Simple.php | 12 +- lib/API/Call/Deferred.php | 78 +- lib/API/Call/Result.php | 13 +- lib/API/Consumer.php | 64 +- lib/API/ContentType/Handler.php | 10 +- lib/API/ContentType/Handler/Base64.php | 4 +- lib/API/ContentType/Handler/Json.php | 12 +- lib/API/ContentType/Handler/Stream.php | 4 +- lib/API/ContentType/Handler/Text.php | 7 +- lib/API/Future.php | 50 +- lib/API/Future/Amp2.php | 51 + lib/API/Future/Common.php | 52 + lib/API/Future/React2.php | 42 + lib/API/Future/functions.php | 175 +- lib/API/Iterator.php | 89 - lib/API/Links.php | 66 +- lib/API/Links/functions.php | 29 +- lib/Exception/functions.php | 15 +- lib/functions.php | 4 +- tests/CacheTest.php | 39 +- tests/ContentTypeTest.php | 2 +- tests/bootstrap.php | 7 +- 42 files changed, 506 insertions(+), 4249 deletions(-) create mode 100644 examples/examples.inc delete mode 100644 http.stub.php create mode 100644 lib/API/Future/Amp2.php create mode 100644 lib/API/Future/Common.php create mode 100644 lib/API/Future/React2.php delete mode 100644 lib/API/Iterator.php diff --git a/README.md b/README.md index ca82ab3..ffee664 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![Build Status](https://travis-ci.org/m6w6/seekat.svg)](https://travis-ci.org/m6w6/seekat) -Fluent Github API access with PHP-7 and [ext-http](https://github.com/m6w6/ext-http). +Fluent Github API access with [ext-http](https://github.com/m6w6/ext-http). Support for the following promise providers built in: * [ReactPHP](https://github.com/reactphp/promise) diff --git a/composer.json b/composer.json index 0c7dab4..5d07e11 100644 --- a/composer.json +++ b/composer.json @@ -24,20 +24,20 @@ "minimum-stability": "dev", "prefer-stable": true, "require": { - "php": ">=7.2", - "ext-http": ">=3.2", + "php": ">=8.1", + "ext-http": ">=4.2", "ext-json": "*", - "psr/log": "^1.0", - "psr/cache": "^1.0", - "psr/simple-cache": "^1.0", - "rize/uri-template": "^0.3.3" + "psr/log": "^3", + "psr/cache": "^1", + "psr/simple-cache": "^1", + "rize/uri-template": "^0.3.4", + "monolog/monolog": "^3" }, "require-dev": { - "php": "^8", + "php": ">=8.1", "amphp/amp": "^2", "react/promise": "^2", - "monolog/monolog": "*", - "phpunit/phpunit": "*", + "phpunit/phpunit": "^9", "squizlabs/php_codesniffer": "*", "phpcompatibility/php-compatibility": "*" } diff --git a/examples/amploop.php b/examples/amploop.php index 1abbaa1..9afda4c 100755 --- a/examples/amploop.php +++ b/examples/amploop.php @@ -6,107 +6,113 @@ require_once __DIR__."/../vendor/autoload.php"; use seekat\API; use Amp\Loop as AmpLoop; -$log = new Monolog\Logger("seekat"); -$log->pushHandler((new Monolog\Handler\StreamHandler(STDERR))->setLevel(Monolog\Logger::INFO)); +$client = new http\Client("curl", "seekat"); +$client->configure([ + "use_eventloop" => new class($client, AmpLoop::get()) implements http\Client\Curl\User { -$cli = new http\Client("curl", "seekat"); -$cli->configure([ - "use_eventloop" => new class($cli, AmpLoop::get()) implements http\Client\Curl\User { + /** + * Timeout ID + */ + private ?string $timeout = null; + private \Closure $runcb; - private $driver; - private $timeout; - private $client; - private $runcb; + function __construct(private http\Client $client, private AmpLoop\Driver $driver) { + } - function __construct(http\Client $client, AmpLoop\Driver $driver) { - $this->client = $client; - $this->driver = $driver; - } - function init($run) { - $this->runcb = $run; - } - function run($socket = null, int $action = null) { - if ($socket) { - $remaining = ($this->runcb)($this->client, $socket, $action); - } else { - $remaining = ($this->runcb)($this->client); + function init($run) : void { + $this->runcb = $run(...); } - if (!$remaining) { - $this->done(); + /** + * @param resource $socket + */ + function run($socket = null, int $action = null) : void { + if ($socket) { + $remaining = ($this->runcb)($this->client, $socket, $action); + } else { + $remaining = ($this->runcb)($this->client); + } + + if (!$remaining) { + $this->done(); + } } - } - function once() { - if (!$this->driver->getInfo()["running"]) { - $this->driver->run(); + function once() : void { + if (!$this->driver->getInfo()["running"]) { + $this->driver->run(); + } } - } - function send() { - # unused - throw new BadMethodCallException(__FUNCTION__); - } - function wait(int $timeout_ms = null) { - # unused - throw new BadMethodCallException(__FUNCTION__); - } - function timer(int $timeout_ms = null) { - if ($this->timeout) { - $this->driver->cancel($this->timeout); + function send() : never { + # unused + throw new BadMethodCallException(__FUNCTION__); + } + function wait(int $timeout_ms = null) : never { + # unused + throw new BadMethodCallException(__FUNCTION__); } + function timer(int $timeout_ms = null) : void { + if ($this->timeout) { + $this->driver->cancel($this->timeout); + } - $this->timeout = $this->driver->delay($timeout_ms, function() { - $this->run(); - }); - } - function done() { - if ($this->timeout) { - $this->driver->cancel($this->timeout); - $this->timeout = null; + $this->timeout = $this->driver->delay($timeout_ms, function() { + $this->run(); + }); } - } - function socket($socket, int $poll) { - foreach ((array) $this->driver->getState((string) $socket) as $id) { - $this->driver->disable($id); + function done() : void { + if ($this->timeout) { + $this->driver->cancel($this->timeout); + $this->timeout = null; + } } - switch ($poll) { - case self::POLL_NONE: - break; - case self::POLL_IN: - $id = $this->driver->onReadable($socket, function($id, $socket) { - $this->run($socket, self::POLL_IN); - }); - $this->driver->setState((string) $socket, $id); - break; - case self::POLL_OUT: - $id = $this->driver->onWritable($socket, function($id, $socket) { - $this->run($socket, self::POLL_OUT); - }); - $this->driver->setState((string) $socket, $id); - break; - case self::POLL_INOUT: - $id = [ - $this->driver->onReadable($socket, function($id, $socket) { + + /** + * @param resource $socket + */ + function socket($socket, int $poll) : void { + foreach ((array) $this->driver->getState((string) $socket) as $id) { + $this->driver->disable($id); + } + switch ($poll) { + case self::POLL_NONE: + break; + case self::POLL_IN: + $id = $this->driver->onReadable($socket, function($id, $socket) { $this->run($socket, self::POLL_IN); - }), - $this->driver->onWritable($socket, function($id, $socket) { + }); + $this->driver->setState((string) $socket, $id); + break; + case self::POLL_OUT: + $id = $this->driver->onWritable($socket, function($id, $socket) { $this->run($socket, self::POLL_OUT); - }) - ]; - $this->driver->setState((string) $socket, $id); - break; - case self::POLL_REMOVE: - foreach ((array) $this->driver->getState((string) $socket) as $id) { - $this->driver->cancel($id); + }); + $this->driver->setState((string) $socket, $id); + break; + case self::POLL_INOUT: + $id = [ + $this->driver->onReadable($socket, function($id, $socket) { + $this->run($socket, self::POLL_IN); + }), + $this->driver->onWritable($socket, function($id, $socket) { + $this->run($socket, self::POLL_OUT); + }) + ]; + $this->driver->setState((string) $socket, $id); + break; + case self::POLL_REMOVE: + foreach ((array) $this->driver->getState((string) $socket) as $id) { + $this->driver->cancel($id); + } + $this->driver->setState((string) $socket, null); + break; } - $this->driver->setState((string) $socket, null); - break; } } -}]); +]); + +$future = API\Future\amp(); -$api = new API(API\Future\amp(), [ - "Authorization" => "token ".getenv("GITHUB_TOKEN") -], null, $cli, $log); +$api = include "examples.inc"; AmpLoop::run(function() use($api) { list($m6w6, $seekat) = yield [$api->users->m6w6(), $api->repos->m6w6->seekat()]; diff --git a/examples/cache.php b/examples/cache.php index c71af44..dea3ab9 100755 --- a/examples/cache.php +++ b/examples/cache.php @@ -1,25 +1,16 @@ #!/usr/bin/env php pushHandler(new StreamHandler(STDERR, Logger::INFO)); +require_once __DIR__ . "/../vendor/autoload.php"; $redis = new Redis; $redis->connect("localhost"); $redis->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_PHP); $cache = new class($redis) implements \seekat\API\Call\Cache\Service { - private $redis; - function __construct(Redis $redis) { - $this->redis = $redis; + function __construct(private readonly Redis $redis) { } - function clear() { - return $this->redis->flushDB(); + function clear() : void { + $this->redis->flushDB(); } function fetch(string $key, \http\Client\Response &$response = null): bool { list($exists, $response) = $this->redis @@ -32,17 +23,17 @@ $cache = new class($redis) implements \seekat\API\Call\Cache\Service { function store(string $key, \http\Client\Response $response): bool { return $this->redis->set($key, $response); } - function del(string $key) { - return $this->redis->delete($key); + function del(string $key) : void { + $this->redis->del($key); } }; -$api = new seekat\API(seekat\API\Future\react(), [ - "Authorization" => "token ".getenv("GITHUB_TOKEN") -], null, null, $log, $cache); +$log_level = "INFO"; + +$api = include "examples.inc"; $api(function($api) use($cache) { yield $api->users->m6w6(); yield $api->users->m6w6(); - $cache->clear(); + //$cache->clear(); }); diff --git a/examples/cli.php b/examples/cli.php index caae47c..6da8815 100755 --- a/examples/cli.php +++ b/examples/cli.php @@ -1,11 +1,8 @@ #!/usr/bin/env php "token ".getenv("GITHUB_TOKEN") -]); array_shift($argv); ($self = function($api) use(&$self) { diff --git a/examples/examples.inc b/examples/examples.inc new file mode 100644 index 0000000..2d150dc --- /dev/null +++ b/examples/examples.inc @@ -0,0 +1,16 @@ +pushHandler(new Monolog\Handler\StreamHandler(STDERR, $log_level)), + cache: $cache ?? new API\Call\Cache\Service\Hollow +); diff --git a/examples/generator.php b/examples/generator.php index 88b69cd..223c1e3 100755 --- a/examples/generator.php +++ b/examples/generator.php @@ -1,19 +1,9 @@ #!/usr/bin/env php pushHandler((new Monolog\Handler\StreamHandler(STDERR))->setLevel(Monolog\Logger::INFO)); - -$cli = new http\Client("curl", "seekat"); - -$api = new API(API\Future\amp(), [ - "Authorization" => "token ".getenv("GITHUB_TOKEN") -], null, $cli, $log); +$api = include "examples.inc"; $api(function($api) { $count = 0; diff --git a/examples/gistlog.php b/examples/gistlog.php index 6cdbe23..43d4ce1 100755 --- a/examples/gistlog.php +++ b/examples/gistlog.php @@ -1,17 +1,6 @@ #!/usr/bin/env php pushHandler(new Monolog\Handler\StreamHandler(STDERR, Monolog\Logger::WARNING)); - -$api = new seekat\API( - seekat\API\Future\react(), - seekat\API\auth("token", getenv("GITHUB_TOKEN")), - null, null, $log -); +$api = include "examples.inc"; $api(function($api) { $gists = yield $api->users->m6w6->gists(); diff --git a/examples/hooks.php b/examples/hooks.php index 612e6de..fdeca09 100755 --- a/examples/hooks.php +++ b/examples/hooks.php @@ -3,20 +3,15 @@ require_once __DIR__."/../vendor/autoload.php"; -use seekat\{API, API\Future, API\Links}; -use Monolog\{Logger, Handler}; +use seekat\API\Links; -$cli = new http\Client("curl", "seekat"); -$cli->configure([ +$client = new http\Client("curl", "seekat"); +$client->configure([ "max_host_connections" => 10, "max_total_connections" => 50, "use_eventloop" => true, ]); - -$log = new Logger("seekat"); -$log->pushHandler(new Handler\StreamHandler(STDERR, Logger::NOTICE)); - -$api = new API(Future\react(), API\auth("token", getenv("GITHUB_TOKEN")), null, $cli, $log); +$api = include "examples.inc"; $api(function() use($api) { $repos = yield $api->users->m6w6->repos([ diff --git a/examples/promise.php b/examples/promise.php index e1f5b9d..b39890d 100755 --- a/examples/promise.php +++ b/examples/promise.php @@ -1,11 +1,7 @@ #!/usr/bin/env php users->m6w6->gists()->onResolve(function($error, $gists) { $error and die($error); @@ -17,7 +13,7 @@ $api->users->m6w6->gists()->onResolve(function($error, $gists) { printf("\nGist %s, %s:\n", $gist->id, $gist->description ?: ""); } $cs = $commit->change_status; - printf("\t%s: ", substr($commit->version,0,8)); + printf("\t%s: ", substr($commit->version, 0, 8)); printf("-%s+%s=%s\n", $cs->deletions, $cs->additions, $cs->total); } }); diff --git a/examples/readme.php b/examples/readme.php index f7b6b57..0aea554 100755 --- a/examples/readme.php +++ b/examples/readme.php @@ -1,8 +1,7 @@ #!/usr/bin/env php repos->m6w6->seekat->readme->as("raw")->get(); }); diff --git a/examples/watchowned.php b/examples/watchowned.php index d1ff879..cffcc2b 100755 --- a/examples/watchowned.php +++ b/examples/watchowned.php @@ -1,23 +1,9 @@ #!/usr/bin/env php pushHandler((new Monolog\Handler\StreamHandler(STDERR)) - ->setLevel(Monolog\Logger::WARNING)); - -$cli = new http\Client("curl", "seekat"); - -$api = new API(API\Future\amp(), [ - "Authorization" => "token ".getenv("GITHUB_TOKEN") -], null, $cli, $log); +$api = include "examples.inc"; $api(function($api) { $count = 0; diff --git a/http.stub.php b/http.stub.php deleted file mode 100644 index 7a114c9..0000000 --- a/http.stub.php +++ /dev/null @@ -1,3424 +0,0 @@ - ***NOTE:*** - * > This method has been added in v2.3.0. - * - * @param array $configuration Key/value pairs of low level options. - * See f.e. the [configuration options for the Curl driver](http/Client/Curl#Configuration:). - * @throws \http\Exception\InvalidArgumentException - * @throws \http\Exception\UnexpectedValueException - * @return \http\Client self. - */ - function configure(array $configuration) {} - /** - * Implements Countable. Retrieve the number of enqueued requests. - * - * > ***NOTE:*** - * > The enqueued requests are counted without regard whether they are finished or not. - * - * @return int number of enqueued requests. - */ - function count() {} - /** - * Dequeue the http\Client\Request $request. - * - * See http\Client::requeue(), if you want to requeue the request, instead of calling http\Client::dequeue() and then http\Client::enqueue(). - * - * @param \http\Client\Request $request The request to cancel. - * @throws \http\Exception\InvalidArgumentException - * @throws \http\Exception\BadMethodCallException - * @throws \http\Exception\RuntimeException - * @return \http\Client self. - */ - function dequeue(\http\Client\Request $request) {} - /** - * Implements SplSubject. Detach $observer, which has been previously attached. - * - * @param \SplObserver $observer Previously attached instance of SplObserver implementation. - * @throws \http\Exception\InvalidArgumentException - * @throws \http\Exception\UnexpectedValueException - * @return \http\Client self. - */ - function detach(\SplObserver $observer) {} - /** - * Enable usage of an event library like libevent, which might improve performance with big socket sets. - * - * > ***NOTE:*** - * > This method has been deprecated in 2.3.0, please use http\Client::configure() instead. - * - * @param bool $enable Whether to enable libevent usage. - * @throws \http\Exception\InvalidArgumentException - * @throws \http\Exception\UnexpectedValueException - * @return \http\Client self. - * @deprecated - */ - function enableEvents(bool $enable = true) {} - /** - * Enable sending pipelined requests to the same host if the driver supports it. - * - * > ***NOTE:*** - * > This method has been deprecated in 2.3.0, please use http\Client::configure() instead. - * - * @param bool $enable Whether to enable pipelining. - * @throws \http\Exception\InvalidArgumentException - * @throws \http\Exception\UnexpectedValueException - * @return \http\Client self. - * @deprecated - */ - function enablePipelining(bool $enable = true) {} - /** - * Add another http\Client\Request to the request queue. - * If the optional callback $cb returns true, the request will be automatically dequeued. - * - * > ***Note:*** - * > The http\Client\Response object resulting from the request is always stored - * > internally to be retrieved at a later time, __even__ when $cb is used. - * > - * > If you are about to send a lot of requests and do __not__ need the response - * > after executing the callback, you can use http\Client::getResponse() within - * > the callback to keep the memory usage level as low as possible. - * - * See http\Client::dequeue() and http\Client::send(). - * - * @param \http\Client\Request $request The request to enqueue. - * @param callable $cb as function(\http\Response $response) : ?bool - * A callback to automatically call when the request has finished. - * @throws \http\Exception\InvalidArgumentException - * @throws \http\Exception\BadMethodCallException - * @throws \http\Exception\RuntimeException - * @return \http\Client self. - */ - function enqueue(\http\Client\Request $request, callable $cb = NULL) {} - /** - * Get a list of available configuration options and their default values. - * - * See f.e. the [configuration options for the Curl driver](http/Client/Curl#Configuration:). - * - * @throws \http\Exception\InvalidArgumentException - * @return array list of key/value pairs of available configuration options and their default values. - */ - function getAvailableConfiguration() {} - /** - * List available drivers. - * - * @return array list of supported drivers. - */ - function getAvailableDrivers() {} - /** - * Retrieve a list of available request options and their default values. - * - * See f.e. the [request options for the Curl driver](http/Client/Curl#Options:). - * - * @throws \http\Exception\InvalidArgumentException - * @return array list of key/value pairs of available request options and their default values. - */ - function getAvailableOptions() {} - /** - * Get priorly set custom cookies. - * See http\Client::setCookies(). - * - * @return array custom cookies. - */ - function getCookies() {} - /** - * Simply returns the http\Message chain representing the request/response history. - * - * > ***NOTE:*** - * > The history is only recorded while http\Client::$recordHistory is true. - * - * @throws \http\Exception\InvalidArgumentException - * @return \http\Message the request/response message chain representing the client's history. - */ - function getHistory() {} - /** - * Returns the SplObjectStorage holding attached observers. - * - * @throws \http\Exception\InvalidArgumentException - * @throws \http\Exception\UnexpectedValueException - * @return \SplObjectStorage observer storage. - */ - function getObservers() {} - /** - * Get priorly set options. - * See http\Client::setOptions(). - * - * @return array options. - */ - function getOptions() {} - /** - * Retrieve the progress information for $request. - * - * @param \http\Client\Request $request The request to retrieve the current progress information for. - * @throws \http\Exception\InvalidArgumentException - * @throws \http\Exception\UnexpectedValueException - * @return object|NULL object stdClass instance holding progress information. - * or NULL if $request is not enqueued. - */ - function getProgressInfo(\http\Client\Request $request) {} - /** - * Retrieve the corresponding response of an already finished request, or the last received response if $request is not set. - * - * > ***NOTE:*** - * > If $request is NULL, then the response is removed from the internal storage (stack-like operation). - * - * @param \http\Client\Request $request The request to fetch the stored response for. - * @throws \http\Exception\InvalidArgumentException - * @throws \http\Exception\UnexpectedValueException - * @return \http\Client\Response|NULL \http\Client\Response the stored response for the request, or the last that was received. - * or NULL if no more response was available to pop, when no $request was given. - */ - function getResponse(\http\Client\Request $request = NULL) {} - /** - * Retrieve priorly set SSL options. - * See http\Client::getOptions() and http\Client::setSslOptions(). - * - * @return array SSL options. - */ - function getSslOptions() {} - /** - * Get transfer related information for a running or finished request. - * - * @param \http\Client\Request $request The request to probe for transfer info. - * @throws \http\Exception\InvalidArgumentException - * @throws \http\Exception\UnexpectedValueException - * @return object stdClass instance holding transfer related information. - */ - function getTransferInfo(\http\Client\Request $request) {} - /** - * Implements SplSubject. Notify attached observers about progress with $request. - * - * @param \http\Client\Request $request The request to notify about. - * @param object $progress stdClass instance holding progress information. - * @throws \http\Exception\InvalidArgumentException - * @throws \http\Exception\UnexpectedValueException - * @return \http\Client self. - */ - function notify(\http\Client\Request $request = NULL, $progress = NULL) {} - /** - * Perform outstanding transfer actions. - * See http\Client::wait() for the completing interface. - * - * @return bool true if there are more transfers to complete. - */ - function once() {} - /** - * Requeue an http\Client\Request. - * - * The difference simply is, that this method, in contrast to http\Client::enqueue(), does not throw an http\Exception when the request to queue is already enqueued and dequeues it automatically prior enqueueing it again. - * - * @param \http\Client\Request $request The request to queue. - * @param callable $cb as function(\http\Response $response) : ?bool - * A callback to automatically call when the request has finished. - * @throws \http\Exception\InvalidArgumentException - * @throws \http\Exception\RuntimeException - * @return \http\Client self. - */ - function requeue(\http\Client\Request $request, callable $cb = NULL) {} - /** - * Reset the client to the initial state. - * - * @return \http\Client self. - */ - function reset() {} - /** - * Send all enqueued requests. - * See http\Client::once() and http\Client::wait() for a more fine grained interface. - * - * @throws \http\Exception\InvalidArgumentException - * @throws \http\Exception\RuntimeException - * @return \http\Client self. - */ - function send() {} - /** - * Set custom cookies. - * See http\Client::addCookies() and http\Client::getCookies(). - * - * @param array $cookies Set the custom cookies to this array. - * @throws \http\Exception\InvalidArgumentException - * @return \http\Client self. - */ - function setCookies(array $cookies = NULL) {} - /** - * Set client debugging callback. - * - * > ***NOTE:*** - * > This method has been added in v2.6.0, resp. v3.1.0. - * - * @param callable $callback as function(http\Client $c, http\Client\Request $r, int $type, string $data) - * The debug callback. For $type see http\Client::DEBUG_* constants. - * @throws \http\Exception\InvalidArgumentException - * @return \http\Client self. - */ - function setDebug(callable $callback) {} - /** - * Set client options. - * See http\Client\Curl. - * - * > ***NOTE:*** - * > Only options specified prior enqueueing a request are applied to the request. - * - * @param array $options The options to set. - * @throws \http\Exception\InvalidArgumentException - * @return \http\Client self. - */ - function setOptions(array $options = NULL) {} - /** - * Specifically set SSL options. - * See http\Client::setOptions() and http\Client\Curl\$ssl options. - * - * @param array $ssl_options Set SSL options to this array. - * @throws \http\Exception\InvalidArgumentException - * @return \http\Client self. - */ - function setSslOptions(array $ssl_options = NULL) {} - /** - * Wait for $timeout seconds for transfers to provide data. - * This is the completion call to http\Client::once(). - * - * @param float $timeout Seconds to wait for data on open sockets. - * @return bool success. - */ - function wait(float $timeout = 0) {} -} -/** - * A class representing a list of cookies with specific attributes. - */ -class Cookie { - /** - * Do not decode cookie contents. - */ - const PARSE_RAW = 1; - /** - * The cookies' flags have the secure attribute set. - */ - const SECURE = 16; - /** - * The cookies' flags have the httpOnly attribute set. - */ - const HTTPONLY = 32; - /** - * Create a new cookie list. - * - * @param mixed $cookies The string or list of cookies to parse or set. - * @param int $flags Parse flags. See http\Cookie::PARSE_* constants. - * @param array $allowed_extras List of extra attribute names to recognize. - * @throws \http\Exception\InvalidArgumentException - * @throws \http\Exception\RuntimeException - */ - function __construct($cookies = NULL, int $flags = 0, array $allowed_extras = NULL) {} - /** - * String cast handler. Alias of http\Cookie::toString(). - * - * @return string the cookie(s) represented as string. - */ - function __toString() {} - /** - * Add a cookie. - * See http\Cookie::setCookie() and http\Cookie::addCookies(). - * - * @param string $cookie_name The key of the cookie. - * @param string $cookie_value The value of the cookie. - * @throws \http\Exception\InvalidArgumentException - * @return \http\Cookie self. - */ - function addCookie(string $cookie_name, string $cookie_value) {} - /** - * (Re)set the cookies. - * See http\Cookie::setCookies(). - * - * @param array $cookies Add cookies of this array of form ["name" => "value"]. - * @throws \http\Exception\InvalidArgumentException - * @return \http\Cookie self. - */ - function addCookies(array $cookies) {} - /** - * Add an extra attribute to the cookie list. - * See http\Cookie::setExtra(). - * - * @param string $extra_name The key of the extra attribute. - * @param string $extra_value The value of the extra attribute. - * @throws \http\Exception\InvalidArgumentException - * @return \http\Cookie self. - */ - function addExtra(string $extra_name, string $extra_value) {} - /** - * Add several extra attributes. - * See http\Cookie::addExtra(). - * - * @param array $extras A list of extra attributes of the form ["key" => "value"]. - * @throws \http\Exception\InvalidArgumentException - * @return \http\Cookie self. - */ - function addExtras(array $extras) {} - /** - * Retrieve a specific cookie value. - * See http\Cookie::setCookie(). - * - * @param string $cookie_name The key of the cookie to look up. - * @return string|NULL string the cookie value. - * or NULL if $cookie_name could not be found. - */ - function getCookie(string $cookie_name) {} - /** - * Get the list of cookies. - * See http\Cookie::setCookies(). - * - * @return array the list of cookies of form ["name" => "value"]. - */ - function getCookies() {} - /** - * Retrieve the effective domain of the cookie list. - * See http\Cookie::setDomain(). - * - * @return string the effective domain. - */ - function getDomain() {} - /** - * Get the currently set expires attribute. - * See http\Cookie::setExpires(). - * - * > ***NOTE:*** - * > A return value of -1 means that the attribute is not set. - * - * @return int the currently set expires attribute as seconds since the epoch. - */ - function getExpires() {} - /** - * Retrieve an extra attribute. - * See http\Cookie::setExtra(). - * - * @param string $name The key of the extra attribute. - * @return string the value of the extra attribute. - */ - function getExtra(string $name) {} - /** - * Retrieve the list of extra attributes. - * See http\Cookie::setExtras(). - * - * @return array the list of extra attributes of the form ["key" => "value"]. - */ - function getExtras() {} - /** - * Get the currently set flags. - * See http\Cookie::SECURE and http\Cookie::HTTPONLY constants. - * - * @return int the currently set flags bitmask. - */ - function getFlags() {} - /** - * Get the currently set max-age attribute of the cookie list. - * See http\Cookie::setMaxAge(). - * - * > ***NOTE:*** - * > A return value of -1 means that the attribute is not set. - * - * @return int the currently set max-age. - */ - function getMaxAge() {} - /** - * Retrieve the path the cookie(s) of this cookie list are effective at. - * See http\Cookie::setPath(). - * - * @return string the effective path. - */ - function getPath() {} - /** - * (Re)set a cookie. - * See http\Cookie::addCookie() and http\Cookie::setCookies(). - * - * > ***NOTE:*** - * > The cookie will be deleted from the list if $cookie_value is NULL. - * - * @param string $cookie_name The key of the cookie. - * @param string $cookie_value The value of the cookie. - * @throws \http\Exception\InvalidArgumentException - * @return \http\Cookie self. - */ - function setCookie(string $cookie_name, string $cookie_value) {} - /** - * (Re)set the cookies. - * See http\Cookie::addCookies(). - * - * @param array $cookies Set the cookies to this array. - * @throws \http\Exception\InvalidArgumentException - * @return \http\Cookie self. - */ - function setCookies(array $cookies = NULL) {} - /** - * Set the effective domain of the cookie list. - * See http\Cookie::setPath(). - * - * @param string $value The domain the cookie(s) belong to. - * @throws \http\Exception\InvalidArgumentException - * @return \http\Cookie self. - */ - function setDomain(string $value = NULL) {} - /** - * Set the traditional expires timestamp. - * See http\Cookie::setMaxAge() for a safer alternative. - * - * @param int $value The expires timestamp as seconds since the epoch. - * @throws \http\Exception\InvalidArgumentException - * @return \http\Cookie self. - */ - function setExpires(int $value = -1) {} - /** - * (Re)set an extra attribute. - * See http\Cookie::addExtra(). - * - * > ***NOTE:*** - * > The attribute will be removed from the extras list if $extra_value is NULL. - * - * @param string $extra_name The key of the extra attribute. - * @param string $extra_value The value of the extra attribute. - * @throws \http\Exception\InvalidArgumentException - * @return \http\Cookie self. - */ - function setExtra(string $extra_name, string $extra_value = NULL) {} - /** - * (Re)set the extra attributes. - * See http\Cookie::addExtras(). - * - * @param array $extras Set the extra attributes to this array. - * @throws \http\Exception\InvalidArgumentException - * @return \http\Cookie self. - */ - function setExtras(array $extras = NULL) {} - /** - * Set the flags to specified $value. - * See http\Cookie::SECURE and http\Cookie::HTTPONLY constants. - * - * @param int $value The new flags bitmask. - * @throws \http\Exception\InvalidArgumentException - * @return \http\Cookie self. - */ - function setFlags(int $value = 0) {} - /** - * Set the maximum age the cookie may have on the client side. - * This is a client clock departure safe alternative to the "expires" attribute. - * See http\Cookie::setExpires(). - * - * @param int $value The max-age in seconds. - * @throws \http\Exception\InvalidArgumentException - * @return \http\Cookie self. - */ - function setMaxAge(int $value = -1) {} - /** - * Set the path the cookie(s) of this cookie list should be effective at. - * See http\Cookie::setDomain(). - * - * @param string $path The URL path the cookie(s) should take effect within. - * @throws \http\Exception\InvalidArgumentException - * @return \http\Cookie self. - */ - function setPath(string $path = NULL) {} - /** - * Get the cookie list as array. - * - * @return array the cookie list as array. - */ - function toArray() {} - /** - * Retrieve the string representation of the cookie list. - * See http\Cookie::toArray(). - * - * @return string the cookie list as string. - */ - function toString() {} -} -/** - * - */ -namespace http\Encoding; -namespace http; -/** - * The http\Env class provides static methods to manipulate and inspect the server's current request's HTTP environment. - */ -class Env { - /** - * Retrieve the current HTTP request's body. - * - * @param string $body_class_name A user class extending http\Message\Body. - * @throws \http\Exception\InvalidArgumentException - * @throws \http\Exception\UnexpectedValueException - * @return \http\Message\Body instance representing the request body - */ - function getRequestBody(string $body_class_name = NULL) {} - /** - * Retrieve one or all headers of the current HTTP request. - * - * @param string $header_name The key of a header to retrieve. - * @return NULL|string|array NULL if $header_name was not found - * or string the compound header when $header_name was found - * or array of all headers if $header_name was not specified - */ - function getRequestHeader(string $header_name = NULL) {} - /** - * Get the HTTP response code to send. - * - * @return int the HTTP response code. - */ - function getResponseCode() {} - /** - * Get one or all HTTP response headers to be sent. - * - * @param string $header_name The name of the response header to retrieve. - * @return string|NULL|array string the compound value of the response header to send - * or NULL if the header was not found - * or array of all response headers, if $header_name was not specified - */ - function getResponseHeader(string $header_name = NULL) {} - /** - * Retrieve a list of all known HTTP response status. - * - * @return array mapping of the form \[ - * ... - * int $code => string $status - * ... - * \] - */ - function getResponseStatusForAllCodes() {} - /** - * Retrieve the string representation of specified HTTP response code. - * - * @param int $code The HTTP response code to get the string representation for. - * @return string the HTTP response status message (may be empty, if no message for this code was found) - */ - function getResponseStatusForCode(int $code) {} - /** - * Generic negotiator. For specific client negotiation see http\Env::negotiateContentType() and related methods. - * - * > ***NOTE:*** - * > The first element of $supported serves as a default if no operand matches. - * - * @param string $params HTTP header parameter's value to negotiate. - * @param array $supported List of supported negotiation operands. - * @param string $prim_typ_sep A "primary type separator", i.e. that would be a hyphen for content language negotiation (en-US, de-DE, etc.). - * @param array $result Out parameter recording negotiation results. - * @return NULL|string NULL if negotiation fails. - * or string the closest match negotiated, or the default (first entry of $supported). - */ - function negotiate(string $params, array $supported, string $prim_typ_sep = NULL, array &$result = NULL) {} - /** - * Negotiate the client's preferred character set. - * - * > ***NOTE:*** - * > The first element of $supported character sets serves as a default if no character set matches. - * - * @param array $supported List of supported content character sets. - * @param array $result Out parameter recording negotiation results. - * @return NULL|string NULL if negotiation fails. - * or string the negotiated character set. - */ - function negotiateCharset(array $supported, array &$result = NULL) {} - /** - * Negotiate the client's preferred MIME content type. - * - * > ***NOTE:*** - * > The first element of $supported content types serves as a default if no content-type matches. - * - * @param array $supported List of supported MIME content types. - * @param array $result Out parameter recording negotiation results. - * @return NULL|string NULL if negotiation fails. - * or string the negotiated content type. - */ - function negotiateContentType(array $supported, array &$result = NULL) {} - /** - * Negotiate the client's preferred encoding. - * - * > ***NOTE:*** - * > The first element of $supported encodings serves as a default if no encoding matches. - * - * @param array $supported List of supported content encodings. - * @param array $result Out parameter recording negotiation results. - * @return NULL|string NULL if negotiation fails. - * or string the negotiated encoding. - */ - function negotiateEncoding(array $supported, array &$result = NULL) {} - /** - * Negotiate the client's preferred language. - * - * > ***NOTE:*** - * > The first element of $supported languages serves as a default if no language matches. - * - * @param array $supported List of supported content languages. - * @param array $result Out parameter recording negotiation results. - * @return NULL|string NULL if negotiation fails. - * or string the negotiated language. - */ - function negotiateLanguage(array $supported, array &$result = NULL) {} - /** - * Set the HTTP response code to send. - * - * @param int $code The HTTP response status code. - * @return bool Success. - */ - function setResponseCode(int $code) {} - /** - * Set a response header, either replacing a prior set header, or appending the new header value, depending on $replace. - * - * If no $header_value is specified, or $header_value is NULL, then a previously set header with the same key will be deleted from the list. - * - * If $response_code is not 0, the response status code is updated accordingly. - * - * @param string $header_name - * @param mixed $header_value - * @param int $response_code - * @param bool $replace - * @return bool Success. - */ - function setResponseHeader(string $header_name, $header_value = NULL, int $response_code = NULL, bool $replace = NULL) {} -} -/** - * The http extension's Exception interface. - * - * Use it to catch any Exception thrown by pecl/http. - * - * The individual exception classes extend their equally named native PHP extensions, if such exist, and implement this empty interface. For example the http\Exception\BadMethodCallException extends SPL's BadMethodCallException. - */ -interface Exception { -} -/** - * The http\Header class provides methods to manipulate, match, negotiate and serialize HTTP headers. - */ -class Header implements \Serializable { - /** - * None of the following match constraints applies. - */ - const MATCH_LOOSE = 0; - /** - * Perform case sensitive matching. - */ - const MATCH_CASE = 1; - /** - * Match only on word boundaries (according by CType alpha-numeric). - */ - const MATCH_WORD = 16; - /** - * Match the complete string. - */ - const MATCH_FULL = 32; - /** - * Case sensitively match the full string (same as MATCH_CASE|MATCH_FULL). - */ - const MATCH_STRICT = 33; - /** - * The name of the HTTP header. - * - * @public - * @var string - */ - public $name = NULL; - /** - * The value of the HTTP header. - * - * @public - * @var mixed - */ - public $value = NULL; - /** - * Create an http\Header instance for use of simple matching or negotiation. If the value of the header is an array it may be compounded to a single comma separated string. - * - * @param string $name The HTTP header name. - * @param mixed $value The value of the header. - * - * # Throws: - */ - function __construct(string $name = NULL, $value = NULL) {} - /** - * String cast handler. Alias of http\Header::serialize(). - * - * @return string the serialized form of the HTTP header (i.e. "Name: value"). - */ - function __toString() {} - /** - * Create a parameter list out of the HTTP header value. - * - * @param mixed $ps The parameter separator(s). - * @param mixed $as The argument separator(s). - * @param mixed $vs The value separator(s). - * @param int $flags The modus operandi. See http\Params constants. - * @return \http\Params instance - */ - function getParams($ps = NULL, $as = NULL, $vs = NULL, int $flags = NULL) {} - /** - * Match the HTTP header's value against provided $value according to $flags. - * - * @param string $value The comparison value. - * @param int $flags The modus operandi. See http\Header constants. - * @return bool whether $value matches the header value according to $flags. - */ - function match(string $value, int $flags = NULL) {} - /** - * Negotiate the header's value against a list of supported values in $supported. - * Negotiation operation is adopted according to the header name, i.e. if the - * header being negotiated is Accept, then a slash is used as primary type - * separator, and if the header is Accept-Language respectively, a hyphen is - * used instead. - * - * > ***NOTE:*** - * > The first element of $supported serves as a default if no operand matches. - * - * @param array $supported The list of supported values to negotiate. - * @param array $result Out parameter recording the negotiation results. - * @return NULL|string NULL if negotiation fails. - * or string the closest match negotiated, or the default (first entry of $supported). - */ - function negotiate(array $supported, array &$result = NULL) {} - /** - * Parse HTTP headers. - * See also http\Header\Parser. - * - * @param string $header The complete string of headers. - * @param string $header_class A class extending http\Header. - * @return array|false array of parsed headers, where the elements are instances of $header_class if specified. - * or false if parsing fails. - */ - function parse(string $header, string $header_class = NULL) {} - /** - * Implements Serializable. - * - * @return string serialized representation of HTTP header (i.e. "Name: value") - */ - function serialize() {} - /** - * Convenience method. Alias of http\Header::serialize(). - * - * @return string the serialized form of the HTTP header (i.e. "Name: value"). - */ - function toString() {} - /** - * Implements Serializable. - * - * @param string $serialized The serialized HTTP header (i.e. "Name: value") - */ - function unserialize($serialized) {} -} -/** - * The message class builds the foundation for any request and response message. - * - * See http\Client\Request and http\Client\Response, as well as http\Env\Request and http\Env\Response. - */ -class Message implements \Countable, \Serializable, \Iterator { - /** - * No specific type of message. - */ - const TYPE_NONE = 0; - /** - * A request message. - */ - const TYPE_REQUEST = 1; - /** - * A response message. - */ - const TYPE_RESPONSE = 2; - /** - * The message type. See http\Message::TYPE_* constants. - * - * @protected - * @var int - */ - protected $type = \http\Message::TYPE_NONE; - /** - * The message's body. - * - * @protected - * @var \http\Message\Body - */ - protected $body = NULL; - /** - * The request method if the message is of type request. - * - * @protected - * @var string - */ - protected $requestMethod = ""; - /** - * The request url if the message is of type request. - * - * @protected - * @var string - */ - protected $requestUrl = ""; - /** - * The response status phrase if the message is of type response. - * - * @protected - * @var string - */ - protected $responseStatus = ""; - /** - * The response code if the message is of type response. - * - * @protected - * @var int - */ - protected $responseCode = 0; - /** - * A custom HTTP protocol version. - * - * @protected - * @var string - */ - protected $httpVersion = NULL; - /** - * Any message headers. - * - * @protected - * @var array - */ - protected $headers = NULL; - /** - * Any parent message. - * - * @protected - * @var \http\Message - */ - protected $parentMessage; - /** - * Create a new HTTP message. - * - * @param mixed $message Either a resource or a string, representing the HTTP message. - * @param bool $greedy Whether to read from a $message resource until EOF. - * @throws \http\Exception\InvalidArgumentException - * @throws \http\Exception\BadMessageException - */ - function __construct($message = NULL, bool $greedy = true) {} - /** - * Retrieve the message serialized to a string. - * Alias of http\Message::toString(). - * - * @return string the single serialized HTTP message. - */ - function __toString() {} - /** - * Append the data of $body to the message's body. - * See http\Message::setBody() and http\Message\Body::append(). - * - * @param \http\Message\Body $body The message body to add. - * @return \http\Message self. - */ - function addBody(\http\Message\Body $body) {} - /** - * Add an header, appending to already existing headers. - * See http\Message::addHeaders() and http\Message::setHeader(). - * - * @param string $name The header name. - * @param mixed $value The header value. - * @return \http\Message self. - */ - function addHeader(string $name, $value) {} - /** - * Add headers, optionally appending values, if header keys already exist. - * See http\Message::addHeader() and http\Message::setHeaders(). - * - * @param array $headers The HTTP headers to add. - * @param bool $append Whether to append values for existing headers. - * @return \http\Message self. - */ - function addHeaders(array $headers, bool $append = false) {} - /** - * Implements Countable. - * - * @return int the count of messages in the chain above the current message. - */ - function count() {} - /** - * Implements iterator. - * See http\Message::valid() and http\Message::rewind(). - * - * @return \http\Message the current message in the iterated message chain. - */ - function current() {} - /** - * Detach a clone of this message from any message chain. - * - * @throws \http\Exception\InvalidArgumentException - * @return \http\Message clone. - */ - function detach() {} - /** - * Retrieve the message's body. - * See http\Message::setBody(). - * - * @throws \http\Exception\InvalidArgumentException - * @throws \http\Exception\UnexpectedValueException - * @return \http\Message\Body the message body. - */ - function getBody() {} - /** - * Retrieve a single header, optionally hydrated into a http\Header extending class. - * - * @param string $header The header's name. - * @param string $into_class The name of a class extending http\Header. - * @return mixed|\http\Header mixed the header value if $into_class is NULL. - * or \http\Header descendant. - */ - function getHeader(string $header, string $into_class = NULL) {} - /** - * Retrieve all message headers. - * See http\Message::setHeaders() and http\Message::getHeader(). - * - * @return array the message's headers. - */ - function getHeaders() {} - /** - * Retrieve the HTTP protocol version of the message. - * See http\Message::setHttpVersion(). - * - * @return string the HTTP protocol version, e.g. "1.0"; defaults to "1.1". - */ - function getHttpVersion() {} - /** - * Retrieve the first line of a request or response message. - * See http\Message::setInfo and also: - * - * * http\Message::getType() - * * http\Message::getHttpVersion() - * * http\Message::getResponseCode() - * * http\Message::getResponseStatus() - * * http\Message::getRequestMethod() - * * http\Message::getRequestUrl() - * - * @return string|NULL string the HTTP message information. - * or NULL if the message is neither of type request nor response. - */ - function getInfo() {} - /** - * Retrieve any parent message. - * See http\Message::reverse(). - * - * @throws \http\Exception\InvalidArgumentException - * @throws \http\Exception\BadMethodCallException - * @return \http\Message the parent message. - */ - function getParentMessage() {} - /** - * Retrieve the request method of the message. - * See http\Message::setRequestMethod() and http\Message::getRequestUrl(). - * - * @return string|false string the request method. - * or false if the message was not of type request. - */ - function getRequestMethod() {} - /** - * Retrieve the request URL of the message. - * See http\Message::setRequestUrl(). - * - * @return string|false string the request URL; usually the path and the querystring. - * or false if the message was not of type request. - */ - function getRequestUrl() {} - /** - * Retrieve the response code of the message. - * See http\Message::setResponseCode() and http\Message::getResponseStatus(). - * - * @return int|false int the response status code. - * or false if the message is not of type response. - */ - function getResponseCode() {} - /** - * Retrieve the response status of the message. - * See http\Message::setResponseStatus() and http\Message::getResponseCode(). - * - * @return string|false string the response status phrase. - * or false if the message is not of type response. - */ - function getResponseStatus() {} - /** - * Retrieve the type of the message. - * See http\Message::setType() and http\Message::getInfo(). - * - * @return int the message type. See http\Message::TYPE_* constants. - */ - function getType() {} - /** - * Check whether this message is a multipart message based on it's content type. - * If the message is a multipart message and a reference $boundary is given, the boundary string of the multipart message will be stored in $boundary. - * - * See http\Message::splitMultipartBody(). - * - * @param string $boundary A reference where the boundary string will be stored. - * @return bool whether this is a message with a multipart "Content-Type". - */ - function isMultipart(string &$boundary = NULL) {} - /** - * Implements Iterator. - * See http\Message::current() and http\Message::rewind(). - * - * @return int a non-sequential integer key. - */ - function key() {} - /** - * Implements Iterator. - * See http\Message::valid() and http\Message::rewind(). - */ - function next() {} - /** - * Prepend message(s) $message to this message, or the top most message of this message chain. - * - * > ***NOTE:*** - * > The message chains must not overlap. - * - * @param \http\Message $message The message (chain) to prepend as parent messages. - * @param bool $top Whether to prepend to the top-most parent message. - * @throws \http\Exception\InvalidArgumentException - * @throws \http\Exception\UnexpectedValueException - * @return \http\Message self. - */ - function prepend(\http\Message $message, bool $top = true) {} - /** - * Reverse the message chain and return the former top-most message. - * - * > ***NOTE:*** - * > Message chains are ordered in reverse-parsed order by default, i.e. the last parsed message is the message you'll receive from any call parsing HTTP messages. - * > - * > This call re-orders the messages of the chain and returns the message that was parsed first with any later parsed messages re-parentized. - * - * @throws \http\Exception\InvalidArgumentException - * @return \http\Message the other end of the message chain. - */ - function reverse() {} - /** - * Implements Iterator. - */ - function rewind() {} - /** - * Implements Serializable. - * - * @return string the serialized HTTP message. - */ - function serialize() {} - /** - * Set the message's body. - * See http\Message::getBody() and http\Message::addBody(). - * - * @param \http\Message\Body $body The new message body. - * @throws \http\Exception\InvalidArgumentException - * @throws \http\Exception\UnexpectedValueException - * @return \http\Message self. - */ - function setBody(\http\Message\Body $body) {} - /** - * Set a single header. - * See http\Message::getHeader() and http\Message::addHeader(). - * - * > ***NOTE:*** - * > Prior to v2.5.6/v3.1.0 headers with the same name were merged into a single - * > header with values concatenated by comma. - * - * @param string $header The header's name. - * @param mixed $value The header's value. Removes the header if NULL. - * @return \http\Message self. - */ - function setHeader(string $header, $value = NULL) {} - /** - * Set the message headers. - * See http\Message::getHeaders() and http\Message::addHeaders(). - * - * > ***NOTE:*** - * > Prior to v2.5.6/v3.1.0 headers with the same name were merged into a single - * > header with values concatenated by comma. - * - * @param array $headers The message's headers. - * @return \http\Message null. - */ - function setHeaders(array $headers = NULL) {} - /** - * Set the HTTP protocol version of the message. - * See http\Message::getHttpVersion(). - * - * @param string $http_version The protocol version, e.g. "1.1", optionally prefixed by "HTTP/". - * @throws \http\Exception\InvalidArgumentException - * @throws \http\Exception\BadHeaderException - * @return \http\Message self. - */ - function setHttpVersion(string $http_version) {} - /** - * Set the complete message info, i.e. type and response resp. request information, at once. - * See http\Message::getInfo(). - * - * @param string $http_info The message info (first line of an HTTP message). - * @throws \http\Exception\InvalidArgumentException - * @throws \http\Exception\BadHeaderException - * @return \http\Message self. - */ - function setInfo(string $http_info) {} - /** - * Set the request method of the message. - * See http\Message::getRequestMethod() and http\Message::setRequestUrl(). - * - * @param string $method The request method. - * @throws \http\Exception\InvalidArgumentException - * @throws \http\Exception\BadMethodCallException - * @return \http\Message self. - */ - function setRequestMethod(string $method) {} - /** - * Set the request URL of the message. - * See http\Message::getRequestUrl() and http\Message::setRequestMethod(). - * - * @param string $url The request URL. - * @throws \http\Exception\InvalidArgumentException - * @throws \http\Exception\BadMethodCallException - * @return \http\Message self. - */ - function setRequestUrl(string $url) {} - /** - * Set the response status code. - * See http\Message::getResponseCode() and http\Message::setResponseStatus(). - * - * > ***NOTE:*** - * > This method also resets the response status phrase to the default for that code. - * - * @param int $response_code The response code. - * @param bool $strict Whether to check that the response code is between 100 and 599 inclusive. - * @throws \http\Exception\InvalidArgumentException - * @throws \http\Exception\BadMethodCallException - * @return \http\Message self. - */ - function setResponseCode(int $response_code, bool $strict = true) {} - /** - * Set the response status phrase. - * See http\Message::getResponseStatus() and http\Message::setResponseCode(). - * - * @param string $response_status The status phrase. - * @throws \http\Exception\InvalidArgumentException - * @throws \http\Exception\BadMethodCallException - * @return \http\Message self. - */ - function setResponseStatus(string $response_status) {} - /** - * Set the message type and reset the message info. - * See http\Message::getType() and http\Message::setInfo(). - * - * @param int $type The desired message type. See the http\Message::TYPE_* constants. - * @return \http\Message self. - */ - function setType(int $type) {} - /** - * Splits the body of a multipart message. - * See http\Message::isMultipart() and http\Message\Body::addPart(). - * - * @throws \http\Exception\InvalidArgumentException - * @throws \http\Exception\BadMethodCallException - * @throws \http\Exception\BadMessageException - * @return \http\Message a message chain of all messages of the multipart body. - */ - function splitMultipartBody() {} - /** - * Stream the message through a callback. - * - * @param callable $callback The callback of the form function(http\Message $from, string $data). - * @return \http\Message self. - */ - function toCallback(callable $callback) {} - /** - * Stream the message into stream $stream, starting from $offset, streaming $maxlen at most. - * - * @param resource $stream The resource to write to. - * @return \http\Message self. - */ - function toStream($stream) {} - /** - * Retrieve the message serialized to a string. - * - * @param bool $include_parent Whether to include all parent messages. - * @return string the HTTP message chain serialized to a string. - */ - function toString(bool $include_parent = false) {} - /** - * Implements Serializable. - * - * @param string $data The serialized message. - */ - function unserialize($data) {} - /** - * Implements Iterator. - * See http\Message::current() and http\Message::rewind(). - * - * @return bool whether http\Message::current() would not return NULL. - */ - function valid() {} -} -/** - * Parse, interpret and compose HTTP (header) parameters. - */ -class Params implements \ArrayAccess { - /** - * The default parameter separator (","). - */ - const DEF_PARAM_SEP = ','; - /** - * The default argument separator (";"). - */ - const DEF_ARG_SEP = ';'; - /** - * The default value separator ("="). - */ - const DEF_VAL_SEP = '='; - /** - * Empty param separator to parse cookies. - */ - const COOKIE_PARAM_SEP = ''; - /** - * Do not interpret the parsed parameters. - */ - const PARSE_RAW = 0; - /** - * Interpret input as default formatted parameters. - */ - const PARSE_DEFAULT = 17; - /** - * Parse backslash escaped (quoted) strings. - */ - const PARSE_ESCAPED = 1; - /** - * Urldecode single units of parameters, arguments and values. - */ - const PARSE_URLENCODED = 4; - /** - * Parse sub dimensions indicated by square brackets. - */ - const PARSE_DIMENSION = 8; - /** - * Parse URL querystring (same as http\Params::PARSE_URLENCODED|http\Params::PARSE_DIMENSION). - */ - const PARSE_QUERY = 12; - /** - * Parse [RFC5987](http://tools.ietf.org/html/rfc5987) style encoded character set and language information embedded in HTTP header params. - */ - const PARSE_RFC5987 = 16; - /** - * Parse [RFC5988](http://tools.ietf.org/html/rfc5988) (Web Linking) tags of Link headers. - */ - const PARSE_RFC5988 = 32; - /** - * The (parsed) parameters. - * - * @public - * @var array - */ - public $params = NULL; - /** - * The parameter separator(s). - * - * @public - * @var array - */ - public $param_sep = \http\Params::DEF_PARAM_SEP; - /** - * The argument separator(s). - * - * @public - * @var array - */ - public $arg_sep = \http\Params::DEF_ARG_SEP; - /** - * The value separator(s). - * - * @public - * @var array - */ - public $val_sep = \http\Params::DEF_VAL_SEP; - /** - * The modus operandi of the parser. See http\Params::PARSE_* constants. - * - * @public - * @var int - */ - public $flags = \http\Params::PARSE_DEFAULT; - /** - * Instantiate a new HTTP (header) parameter set. - * - * @param mixed $params Pre-parsed parameters or a string to be parsed. - * @param mixed $ps The parameter separator(s). - * @param mixed $as The argument separator(s). - * @param mixed $vs The value separator(s). - * @param int $flags The modus operandi. See http\Params::PARSE_* constants. - * @throws \http\Exception\InvalidArgumentException - * @throws \http\Exception\RuntimeException - */ - function __construct($params = NULL, $ps = NULL, $as = NULL, $vs = NULL, int $flags = NULL) {} - /** - * String cast handler. Alias of http\Params::toString(). - * Returns a stringified version of the parameters. - * - * @return string version of the parameters. - */ - function __toString() {} - /** - * Implements ArrayAccess. - * - * @param string $name The offset to look after. - * @return bool Existence. - */ - function offsetExists($name) {} - /** - * Implements ArrayAccess. - * - * @param string $name The offset to retrieve. - * @return mixed contents at offset. - */ - function offsetGet($name) {} - /** - * Implements ArrayAccess. - * - * @param string $name The offset to modify. - * @param mixed $value The value to set. - */ - function offsetSet($name, $value) {} - /** - * Implements ArrayAccess. - * - * @param string $name The offset to delete. - */ - function offsetUnset($name) {} - /** - * Convenience method that simply returns http\Params::$params. - * - * @return array of parameters. - */ - function toArray() {} - /** - * Returns a stringified version of the parameters. - * - * @return string version of the parameters. - */ - function toString() {} -} -/** - * The http\QueryString class provides versatile facilities to retrieve, use and manipulate query strings and form data. - */ -class QueryString implements \Serializable, \ArrayAccess, \IteratorAggregate { - /** - * Cast requested value to bool. - */ - const TYPE_BOOL = 17; - /** - * Cast requested value to int. - */ - const TYPE_INT = 4; - /** - * Cast requested value to float. - */ - const TYPE_FLOAT = 5; - /** - * Cast requested value to string. - */ - const TYPE_STRING = 6; - /** - * Cast requested value to an array. - */ - const TYPE_ARRAY = 7; - /** - * Cast requested value to an object. - */ - const TYPE_OBJECT = 8; - /** - * The global instance. See http\QueryString::getGlobalInstance(). - * - * @private - * @var \http\QueryString - */ - private $instance = NULL; - /** - * The data. - * - * @private - * @var array - */ - private $queryArray = NULL; - /** - * Create an independent querystring instance. - * - * @param mixed $params The query parameters to use or parse. - * @throws \http\Exception\BadQueryStringException - */ - function __construct($params = NULL) {} - /** - * Get the string representation of the querystring (x-www-form-urlencoded). - * - * @return string the x-www-form-urlencoded querystring. - */ - function __toString() {} - /** - * Retrieve an querystring value. - * - * See http\QueryString::TYPE_* constants. - * - * @param string $name The key to retrieve the value for. - * @param mixed $type The type to cast the value to. See http\QueryString::TYPE_* constants. - * @param mixed $defval The default value to return if the key $name does not exist. - * @param bool $delete Whether to delete the entry from the querystring after retrieval. - * @return \http\QueryString|string|mixed|mixed|string \http\QueryString if called without arguments. - * or string the whole querystring if $name is of zero length. - * or mixed $defval if the key $name does not exist. - * or mixed the querystring value cast to $type if $type was specified and the key $name exists. - * or string the querystring value if the key $name exists and $type is not specified or equals http\QueryString::TYPE_STRING. - */ - function get(string $name = NULL, $type = NULL, $defval = NULL, bool $delete = false) {} - /** - * Retrieve an array value with at offset $name. - * - * @param string $name The key to look up. - * @param mixed $defval The default value to return if the offset $name does not exist. - * @param bool $delete Whether to remove the key and value from the querystring after retrieval. - * @return array|mixed array the (casted) value. - * or mixed $defval if offset $name does not exist. - */ - function getArray(string $name, $defval = NULL, bool $delete = false) {} - /** - * Retrieve a boolean value at offset $name. - * - * @param string $name The key to look up. - * @param mixed $defval The default value to return if the offset $name does not exist. - * @param bool $delete Whether to remove the key and value from the querystring after retrieval. - * @return bool|mixed bool the (casted) value. - * or mixed $defval if offset $name does not exist. - */ - function getBool(string $name, $defval = NULL, bool $delete = false) {} - /** - * Retrieve a float value at offset $name. - * - * @param string $name The key to look up. - * @param mixed $defval The default value to return if the offset $name does not exist. - * @param bool $delete Whether to remove the key and value from the querystring after retrieval. - * @return float|mixed float the (casted) value. - * or mixed $defval if offset $name does not exist. - */ - function getFloat(string $name, $defval = NULL, bool $delete = false) {} - /** - * Retrieve the global querystring instance referencing $_GET. - * - * @throws \http\Exception\UnexpectedValueException - * @return \http\QueryString the http\QueryString::$instance - */ - function getGlobalInstance() {} - /** - * Retrieve a int value at offset $name. - * - * @param string $name The key to look up. - * @param mixed $defval The default value to return if the offset $name does not exist. - * @param bool $delete Whether to remove the key and value from the querystring after retrieval. - * @return int|mixed int the (casted) value. - * or mixed $defval if offset $name does not exist. - */ - function getInt(string $name, $defval = NULL, bool $delete = false) {} - /** - * Implements IteratorAggregate. - * - * @throws \http\Exception\InvalidArgumentException - * @throws \InvalidArgumentException - */ - function getIterator() {} - /** - * Retrieve a object value with at offset $name. - * - * @param string $name The key to look up. - * @param mixed $defval The default value to return if the offset $name does not exist. - * @param bool $delete Whether to remove the key and value from the querystring after retrieval. - * @return object|mixed object the (casted) value. - * or mixed $defval if offset $name does not exist. - */ - function getObject(string $name, $defval = NULL, bool $delete = false) {} - /** - * Retrieve a string value with at offset $name. - * - * @param string $name The key to look up. - * @param mixed $defval The default value to return if the offset $name does not exist. - * @param bool $delete Whether to remove the key and value from the querystring after retrieval. - * @return string|mixed string the (casted) value. - * or mixed $defval if offset $name does not exist. - */ - function getString(string $name, $defval = NULL, bool $delete = false) {} - /** - * Set additional $params to a clone of this instance. - * See http\QueryString::set(). - * - * > ***NOTE:*** - * > This method returns a clone (copy) of this instance. - * - * @param mixed $params Additional params as object, array or string to parse. - * @throws \http\Exception\BadQueryStringException - * @return \http\QueryString clone. - */ - function mod($params = NULL) {} - /** - * Implements ArrayAccess. - * - * @param string $name The offset to look up. - * @return bool whether the key $name isset. - */ - function offsetExists($name) {} - /** - * Implements ArrayAccess. - * - * @param mixed $offset The offset to look up. - * @return mixed|NULL mixed the value locate at offset $name. - * or NULL if key $name could not be found. - */ - function offsetGet($offset) {} - /** - * Implements ArrayAccess. - * - * @param string $name The key to set the value for. - * @param mixed $data The data to place at offset $name. - */ - function offsetSet($name, $data) {} - /** - * Implements ArrayAccess. - * - * @param string $name The offset to look up. - */ - function offsetUnset($name) {} - /** - * Implements Serializable. - * See http\QueryString::toString(). - * - * @return string the x-www-form-urlencoded querystring. - */ - function serialize() {} - /** - * Set additional querystring entries. - * - * @param mixed $params Additional params as object, array or string to parse. - * @return \http\QueryString self. - */ - function set($params) {} - /** - * Simply returns http\QueryString::$queryArray. - * - * @return array the $queryArray property. - */ - function toArray() {} - /** - * Get the string representation of the querystring (x-www-form-urlencoded). - * - * @return string the x-www-form-urlencoded querystring. - */ - function toString() {} - /** - * Implements Serializable. - * - * @param string $serialized The x-www-form-urlencoded querystring. - * @throws \http\Exception - */ - function unserialize($serialized) {} - /** - * Translate character encodings of the querystring with ext/iconv. - * - * > ***NOTE:*** - * > This method is only available when ext/iconv support was enabled at build time. - * - * @param string $from_enc The encoding to convert from. - * @param string $to_enc The encoding to convert to. - * @throws \http\Exception\InvalidArgumentException - * @throws \http\Exception\BadConversionException - * @return \http\QueryString self. - */ - function xlate(string $from_enc, string $to_enc) {} -} -/** - * The http\Url class provides versatile means to parse, construct and manipulate URLs. - */ -class Url { - /** - * Replace parts of the old URL with parts of the new. - */ - const REPLACE = 0; - /** - * Whether a relative path should be joined into the old path. - */ - const JOIN_PATH = 1; - /** - * Whether the querystrings should be joined. - */ - const JOIN_QUERY = 2; - /** - * Strip the user information from the URL. - */ - const STRIP_USER = 4; - /** - * Strip the password from the URL. - */ - const STRIP_PASS = 8; - /** - * Strip user and password information from URL (same as STRIP_USER|STRIP_PASS). - */ - const STRIP_AUTH = 12; - /** - * Do not include the port. - */ - const STRIP_PORT = 32; - /** - * Do not include the URL path. - */ - const STRIP_PATH = 64; - /** - * Do not include the URL querystring. - */ - const STRIP_QUERY = 128; - /** - * Strip the fragment (hash) from the URL. - */ - const STRIP_FRAGMENT = 256; - /** - * Strip everything except scheme and host information. - */ - const STRIP_ALL = 492; - /** - * Import initial URL parts from the SAPI environment. - */ - const FROM_ENV = 4096; - /** - * Whether to sanitize the URL path (consolidate double slashes, directory jumps etc.) - */ - const SANITIZE_PATH = 8192; - /** - * Parse UTF-8 encoded multibyte sequences. - */ - const PARSE_MBUTF8 = 131072; - /** - * Parse locale encoded multibyte sequences (on systems with wide character support). - */ - const PARSE_MBLOC = 65536; - /** - * Parse and convert multibyte hostnames according to IDNA (with IDNA support). - */ - const PARSE_TOIDN = 1048576; - /** - * Explicitly request IDNA2003 implementation if available (libidn, idnkit or ICU). - */ - const PARSE_TOIDN_2003 = 9437184; - /** - * Explicitly request IDNA2008 implementation if available (libidn2, idnkit2 or ICU). - */ - const PARSE_TOIDN_2008 = 5242880; - /** - * Percent encode multibyte sequences in the userinfo, path, query and fragment parts of the URL. - */ - const PARSE_TOPCT = 2097152; - /** - * Continue parsing when encountering errors. - */ - const IGNORE_ERRORS = 268435456; - /** - * Suppress errors/exceptions. - */ - const SILENT_ERRORS = 536870912; - /** - * Standard flags used by default internally for e.g. http\Message::setRequestUrl(). - * Enables joining path and query, sanitizing path, multibyte/unicode, international domain names and transient percent encoding. - */ - const STDFLAGS = 3350531; - /** - * The URL's scheme. - * - * @public - * @var string - */ - public $scheme = NULL; - /** - * Authenticating user. - * - * @public - * @var string - */ - public $user = NULL; - /** - * Authentication password. - * - * @public - * @var string - */ - public $pass = NULL; - /** - * Hostname/domain. - * - * @public - * @var string - */ - public $host = NULL; - /** - * Port. - * - * @public - * @var string - */ - public $port = NULL; - /** - * URL path. - * - * @public - * @var string - */ - public $path = NULL; - /** - * URL querystring. - * - * @public - * @var string - */ - public $query = NULL; - /** - * URL fragment (hash). - * - * @public - * @var string - */ - public $fragment = NULL; - /** - * Create an instance of an http\Url. - * - * > ***NOTE:*** - * > Prior to v3.0.0, the default for the $flags parameter was http\Url::FROM_ENV. - * - * See also http\Env\Url. - * - * @param mixed $old_url Initial URL parts. Either an array, object, http\Url instance or string to parse. - * @param mixed $new_url Overriding URL parts. Either an array, object, http\Url instance or string to parse. - * @param int $flags The modus operandi of constructing the url. See http\Url constants. - * @throws \http\Exception\InvalidArgumentException - * @throws \http\Exception\BadUrlException - */ - function __construct($old_url = NULL, $new_url = NULL, int $flags = 0) {} - /** - * String cast handler. Alias of http\Url::toString(). - * - * @return string the URL as string. - */ - function __toString() {} - /** - * Clone this URL and apply $parts to the cloned URL. - * - * > ***NOTE:*** - * > This method returns a clone (copy) of this instance. - * - * @param mixed $parts New URL parts. - * @param int $flags Modus operandi of URL construction. See http\Url constants. - * @throws \http\Exception\InvalidArgumentException - * @throws \http\Exception\BadUrlException - * @return \http\Url clone. - */ - function mod($parts, int $flags = \http\Url::JOIN_PATH|http\Url::JOIN_QUERY|http\Url::SANITIZE_PATH) {} - /** - * Retrieve the URL parts as array. - * - * @return array the URL parts. - */ - function toArray() {} - /** - * Get the string prepresentation of the URL. - * - * @return string the URL as string. - */ - function toString() {} -} -/** - * The http\Client\Curl namespace holds option value constants specific to the curl driver of the http\Client. - * - * Head down for the [list of available request options](http/Client/Curl#Options:) as well as the - * [list of available client configuration options](http/Client/Curl#Configuration:). - */ -namespace http\Client\Curl; -/** - * Bitmask of available libcurl features. - * See http\Client\Curl\Features namespace. - */ -const FEATURES = 12568477; -/** - * List of library versions of or linked into libcurl, - * e.g. "libcurl/7.50.0 OpenSSL/1.0.2h zlib/1.2.8 libidn/1.32 nghttp2/1.12.0". - * See http\Client\Curl\Versions namespace. - */ -const VERSIONS = 'libcurl/7.68.0 OpenSSL/1.1.1f zlib/1.2.11 brotli/1.0.7 libidn2/2.2.0 libpsl/0.21.0 (+libidn2/2.2.0) libssh/0.9.3/openssl/zlib nghttp2/1.40.0 librtmp/2.3'; -/** - * Use HTTP/1.0 protocol version. - */ -const HTTP_VERSION_1_0 = 1; -/** - * Use HTTP/1.1 protocol version. - */ -const HTTP_VERSION_1_1 = 2; -/** - * Attempt to use HTTP/2 protocol version. Available if libcurl is v7.33.0 or more recent and was built with nghttp2 support. - */ -const HTTP_VERSION_2_0 = 3; -/** - * Attempt to use version 2 for HTTPS, version 1.1 for HTTP. Available if libcurl is v7.47.0 or more recent and was built with http2 support. - */ -const HTTP_VERSION_2TLS = 4; -/** - * Declare prior knowledge that the server supports plain (non-TLS) HTTP/2. Available if libcurl is v7.49.0 or more recent and was built with http2 support. - */ -const HTTP_VERSION_2_PRIOR_KNOWLEDGE = 5; -/** - * Force usage of HTTP/3. See also http\Client\Curl::$altsvc. Available if libcurl is v7.66.0 or more recent. - */ -const HTTP_VERSION_3 = 30; -/** - * Use any HTTP protocol version. - */ -const HTTP_VERSION_ANY = 0; -/** - * Use TLS v1.0 encryption. Available if libcurl is v7.34.0 or more recent. - */ -const SSL_VERSION_TLSv1_0 = 4; -/** - * Use TLS v1.1 encryption. Available if libcurl is v7.34.0 or more recent. - */ -const SSL_VERSION_TLSv1_1 = 5; -/** - * Use TLS v1.2 encryption. Available if libcurl is v7.34.0 or more recent. - */ -const SSL_VERSION_TLSv1_2 = 6; -/** - * Use TLS v1.3 encryption. Available if libcurl is v7.52.0 or more recent. - */ -const SSL_VERSION_TLSv1_3 = 7; -/** - * Use any TLS v1 encryption. - */ -const SSL_VERSION_TLSv1 = 1; -/** - * Use SSL v2 encryption. - */ -const SSL_VERSION_SSLv2 = 2; -/** - * Use SSL v3 encryption. - */ -const SSL_VERSION_SSLv3 = 3; -/** - * Use any encryption. - */ -const SSL_VERSION_ANY = 0; -/** - * Use max default encryption. To be bitwise ORed to a http\Client\Curl\SSL_VERSION_ constant. Available if libcurl is v7.54.0 or more recent. - */ -const SSL_VERSION_MAX_DEFAULT = 65536; -/** - * Use upt to TLS v1.0 encryption. To be bitwise ORed to a http\Client\Curl\SSL_VERSION_ constant. Available if libcurl is v7.54.0 or more recent. - */ -const SSL_VERSION_MAX_TLSv1_0 = 262144; -/** - * Use up to TLS v1.1 encryption. To be bitwise ORed to a http\Client\Curl\SSL_VERSION_ constant. Available if libcurl is v7.54.0 or more recent. - */ -const SSL_VERSION_MAX_TLSv1_1 = 327680; -/** - * Use up to TLS v1.2 encryption. To be bitwise ORed to a http\Client\Curl\SSL_VERSION_ constant. Available if libcurl is v7.54.0 or more recent. - */ -const SSL_VERSION_MAX_TLSv1_2 = 393216; -/** - * Use up to TLS v1.3 encryption. To be bitwise ORed to a http\Client\Curl\SSL_VERSION_ constant. Available if libcurl is v7.54.0 or more recent. - */ -const SSL_VERSION_MAX_TLSv1_3 = 458752; -/** - * Use TLS SRP authentication. Available if libcurl is v7.21.4 or more recent and was built with gnutls or openssl with TLS-SRP support. - */ -const TLSAUTH_SRP = 1; -/** - * Use IPv4 resolver. - */ -const IPRESOLVE_V4 = 1; -/** - * Use IPv6 resolver. - */ -const IPRESOLVE_V6 = 2; -/** - * Use any resolver. - */ -const IPRESOLVE_ANY = 0; -/** - * Don't use authentication. - */ -const AUTH_NONE = 0; -/** - * Use Basic authentication. - */ -const AUTH_BASIC = 1; -/** - * Use Digest authentication. - */ -const AUTH_DIGEST = 2; -/** - * Use IE (lower v7) quirks with Digest authentication. Available if libcurl is v7.19.3 or more recent. - */ -const AUTH_DIGEST_IE = 16; -/** - * Use NTLM authentication. - */ -const AUTH_NTLM = 8; -/** - * Use GSS-Negotiate authentication. - */ -const AUTH_GSSNEG = 4; -/** - * Use HTTP Netgotiate authentication (SPNEGO, RFC4559). Available if libcurl is v7.38.0 or more recent. - */ -const AUTH_SPNEGO = 4; -/** - * Bearer authentication. Set bearer with http\Client\Curl::$xoauth2_bearer request option. Available if libcurl is v7.61.0 or more recent. - */ -const AUTH_BEARER = 64; -/** - * Use AWS SIGv4 authentication. Available if libcurl is v7.75.0 or more recent. - */ -const AUTH_AWS_SIGV4 = NULL; -/** - * Use any authentication. - */ -const AUTH_ANY = -17; -/** - * Use SOCKSv4 proxy protocol. - */ -const PROXY_SOCKS4 = 4; -/** - * Use SOCKSv4a proxy protocol. - */ -const PROXY_SOCKS4A = 6; -/** - * Use SOCKS5h proxy protocol. - */ -const PROXY_SOCKS5_HOSTNAME = 7; -/** - * Use SOCKS5 proxy protoccol. - */ -const PROXY_SOCKS5 = 5; -/** - * Use HTTP/1.1 proxy protocol. - */ -const PROXY_HTTP = 0; -/** - * Use HTTP/1.0 proxy protocol. Available if libcurl is v7.19.4 or more recent. - */ -const PROXY_HTTP_1_0 = 1; -/** - * Keep POSTing on 301 redirects. Available if libcurl is v7.19.1 or more recent. - */ -const POSTREDIR_301 = 1; -/** - * Keep POSTing on 302 redirects. Available if libcurl is v7.19.1 or more recent. - */ -const POSTREDIR_302 = 2; -/** - * Keep POSTing on 303 redirects. Available if libcurl is v7.19.1 or more recent. - */ -const POSTREDIR_303 = 4; -/** - * Keep POSTing on any redirect. Available if libcurl is v7.19.1 or more recent. - */ -const POSTREDIR_ALL = 7; -/** - * Do only read from but not write to the Alt-Svc cache file. Available if libcurl is v7.64.1 or more recent. - */ -const ALTSVC_READONLYFILE = 4; -/** - * Accept alternative services offered over HTTP/1.1. Available if libcurl is v7.64.1 or more recent. - */ -const ALTSVC_H1 = 8; -/** - * Accept alternative services offered over HTTP/2. Available if libcurl is v7.64.1 or more recent. - */ -const ALTSVC_H2 = 16; -/** - * Accept alternative services offered over HTTP/3. Available if libcurl is v7.64.1 or more recent. - */ -const ALTSVC_H3 = 32; -/** - * Enable the cache. Available if libcurl is v7.74.0 or more recent. - */ -const HSTS_ENABLE = NULL; -/** - * Do only read from but not write to the HSTS cache file. Available if libcurl is v7.74.0 or more recent. - */ -const HSTS_READONLYFILE = NULL; -namespace http\Client; -/** - * The http\Client\Request class provides an HTTP message implementation tailored to represent a request message to be sent by the client. - * - * See http\Client::enqueue(). - */ -class Request extends \http\Message { - /** - * Array of options for this request, which override client options. - * - * @protected - * @var array - */ - protected $options = NULL; - /** - * Create a new client request message to be enqueued and sent by http\Client. - * - * @param string $meth The request method. - * @param string $url The request URL. - * @param array $headers HTTP headers. - * @param \http\Message\Body $body Request body. - * @throws \http\Exception\InvalidArgumentException - * @throws \http\Exception\UnexpectedValueException - */ - function __construct(string $meth = NULL, string $url = NULL, array $headers = NULL, \http\Message\Body $body = NULL) {} - /** - * Add querystring data. - * See http\Client\Request::setQuery() and http\Message::setRequestUrl(). - * - * @param mixed $query_data Additional querystring data. - * @throws \http\Exception\InvalidArgumentException - * @throws \http\Exception\BadQueryStringException - * @return \http\Client\Request self. - */ - function addQuery($query_data) {} - /** - * Add specific SSL options. - * See http\Client\Request::setSslOptions(), http\Client\Request::setOptions() and http\Client\Curl\$ssl options. - * - * @param array $ssl_options Add this SSL options. - * @throws \http\Exception\InvalidArgumentException - * @return \http\Client\Request self. - */ - function addSslOptions(array $ssl_options = NULL) {} - /** - * Extract the currently set "Content-Type" header. - * See http\Client\Request::setContentType(). - * - * @return string|NULL string the currently set content type. - * or NULL if no "Content-Type" header is set. - */ - function getContentType() {} - /** - * Get priorly set options. - * See http\Client\Request::setOptions(). - * - * @return array options. - */ - function getOptions() {} - /** - * Retrieve the currently set querystring. - * - * @return string|NULL string the currently set querystring. - * or NULL if no querystring is set. - */ - function getQuery() {} - /** - * Retrieve priorly set SSL options. - * See http\Client\Request::getOptions() and http\Client\Request::setSslOptions(). - * - * @return array SSL options. - */ - function getSslOptions() {} - /** - * Set the MIME content type of the request message. - * - * @param string $content_type The MIME type used as "Content-Type". - * @throws \http\Exception\InvalidArgumentException - * @throws \http\Exception\UnexpectedValueException - * @return \http\Client\Request self. - */ - function setContentType(string $content_type) {} - /** - * Set client options. - * See http\Client::setOptions() and http\Client\Curl. - * - * Request specific options override general options which were set in the client. - * - * > ***NOTE:*** - * > Only options specified prior enqueueing a request are applied to the request. - * - * @param array $options The options to set. - * @throws \http\Exception\InvalidArgumentException - * @return \http\Client\Request self. - */ - function setOptions(array $options = NULL) {} - /** - * (Re)set the querystring. - * See http\Client\Request::addQuery() and http\Message::setRequestUrl(). - * - * @param mixed $query_data - * @throws \http\Exception\InvalidArgumentException - * @throws \http\Exception\BadQueryStringException - * @return \http\Client\Request self. - */ - function setQuery($query_data) {} - /** - * Specifically set SSL options. - * See http\Client\Request::setOptions() and http\Client\Curl\$ssl options. - * - * @param array $ssl_options Set SSL options to this array. - * @throws \http\Exception\InvalidArgumentException - * @return \http\Client\Request self. - */ - function setSslOptions(array $ssl_options = NULL) {} -} -/** - * The http\Client\Response class represents an HTTP message the client returns as answer from a server to an http\Client\Request. - */ -class Response extends \http\Message { - /** - * Extract response cookies. - * Parses any "Set-Cookie" response headers into an http\Cookie list. See http\Cookie::__construct(). - * - * @param int $flags Cookie parser flags. - * @param array $allowed_extras List of keys treated as extras. - * @return array list of http\Cookie instances. - */ - function getCookies(int $flags = 0, array $allowed_extras = NULL) {} - /** - * Retrieve transfer related information after the request has completed. - * See http\Client::getTransferInfo(). - * - * @param string $name A key to retrieve out of the transfer info. - * @throws \http\Exception\InvalidArgumentException - * @throws \http\Exception\BadMethodCallException - * @throws \http\Exception\UnexpectedValueException - * @return object|mixed object stdClass instance with all transfer info if $name was not given. - * or mixed the specific transfer info for $name. - */ - function getTransferInfo(string $name = NULL) {} -} -namespace http\Client\Curl; -/** - * Interface to an user event loop implementation for http\Client::configure()'s $use_eventloop option. - * - * > ***NOTE:*** - * > This interface was added in v2.6.0, resp. v3.1.0. - */ -interface User { - /** - * No action. - */ - const POLL_NONE = 0; - /** - * Poll for read readiness. - */ - const POLL_IN = 1; - /** - * Poll for write readiness. - */ - const POLL_OUT = 2; - /** - * Poll for read/write readiness. - */ - const POLL_INOUT = 3; - /** - * Stop polling for activity on this descriptor. - */ - const POLL_REMOVE = 4; - /** - * Initialize the event loop. - * - * @param callable $run as function(http\Client $c, resource $s = null, int $action = http\Client\Curl\User::POLL_NONE) : int - * Internal callback returning the number of unfinished requests pending. - * - * - * > ***NOTE***: - * > The callback should be run when a timeout occurs or a watched socket needs action. - */ - function init(callable $run); - /** - * Run the loop as long as it does not block. - * - * > ***NOTE:*** - * > This method is called by http\Client::once(), so it does not need to have an actual implementation if http\Client::once() is never called. - */ - function once(); - /** - * Run the loop. - * - * > ***NOTE:*** - * > This method is called by http\Client::send(), so it does not need to have an actual implementation if http\Client::send() is never called. - */ - function send(); - /** - * Register (or deregister) a socket watcher. - * - * @param resource $socket The socket descriptor to watch. - * @param int $poll http\Client\Curl\User::POLL_* constant. - */ - function socket($socket, int $poll); - /** - * Register a timeout watcher. - * - * @param int $timeout_ms Desired maximum timeout in milliseconds. - */ - function timer(int $timeout_ms); - /** - * Wait/poll/select (block the loop) until events fire. - * - * > ***NOTE:*** - * > This method is called by http\Client::wait(), so it does not need to have an actual implementation if http\Client::wait() is never called. - * - * @param int $timeout_ms Block for at most this milliseconds. - */ - function wait(int $timeout_ms = null); -} -/** - * CURL feature constants. - * - * > ***NOTE:*** - * > These constants have been added in v2.6.0, resp. v3.1.0. - */ -namespace http\Client\Curl\Features; -/** - * Whether libcurl supports asynchronous domain name resolution. - */ -const ASYNCHDNS = 128; -/** - * Whether libcurl supports the Generic Security Services Application Program Interface. Available if libcurl is v7.38.0 or more recent. - */ -const GSSAPI = 131072; -/** - * Whether libcurl supports HTTP Generic Security Services negotiation. - */ -const GSSNEGOTIATE = 32; -/** - * Whether libcurl supports the HTTP/2 protocol. Available if libcurl is v7.33.0 or more recent. - */ -const HTTP2 = 65536; -/** - * Whether libcurl supports international domain names. - */ -const IDN = 1024; -/** - * Whether libcurl supports IPv6. - */ -const IPV6 = 1; -/** - * Whether libcurl supports the old Kerberos protocol. - */ -const KERBEROS4 = 2; -/** - * Whether libcurl supports the more recent Kerberos v5 protocol. Available if libcurl is v7.40.0 or more recent. - */ -const KERBEROS5 = 262144; -/** - * Whether libcurl supports large files. - */ -const LARGEFILE = 512; -/** - * Whether libcurl supports gzip/deflate compression. - */ -const LIBZ = 8; -/** - * Whether libcurl supports the NT Lan Manager authentication. - */ -const NTLM = 16; -/** - * Whether libcurl supports NTLM delegation to a winbind helper. Available if libcurl is v7.22.0 or more recent. - */ -const NTLM_WB = 32768; -/** - * Whether libcurl supports the Public Suffix List for cookie host handling. Available if libcurl is v7.47.0 or more recent. - */ -const PSL = 1048576; -/** - * Whether libcurl supports the Simple and Protected GSSAPI Negotiation Mechanism. - */ -const SPNEGO = 256; -/** - * Whether libcurl supports SSL/TLS protocols. - */ -const SSL = 4; -/** - * Whether libcurl supports the Security Support Provider Interface. - */ -const SSPI = 2048; -/** - * Whether libcurl supports TLS Secure Remote Password authentication. Available if libcurl is v7.21.4 or more recent. - */ -const TLSAUTH_SRP = 16384; -/** - * Whether libcurl supports connections to unix sockets. Available if libcurl is v7.40.0 or more recent. - */ -const UNIX_SOCKETS = 524288; -/** - * CURL version constants. - */ -namespace http\Client\Curl\Versions; -/** - * Version string of libcurl, e.g. "7.50.0". - */ -const CURL = '7.68.0'; -/** - * Version string of the SSL/TLS library, e.g. "OpenSSL/1.0.2h". - */ -const SSL = 'OpenSSL/1.1.1f'; -/** - * Version string of the zlib compression library, e.g. "1.2.8". - */ -const LIBZ = '1.2.11'; -/** - * Version string of the c-ares library, e.g. "1.11.0". - */ -const ARES = NULL; -/** - * Version string of the IDN library, e.g. "1.32". - */ -const IDN = '2.2.0'; -/** - * Version string of the iconv library. Added in v4.1.0. - */ -const ICONV = NULL; -/** - * Version string of the brotli library. Added in v4.1.0. Available if libcurl is v7.57.0 or more recent. - */ -const BROTLI = '1.0.7'; -/** - * Version string of nghttp2. Added in v4.1.0. Available if libcurl is v7.66.0 or more recent. - */ -const NGHTTP2 = '1.40.0'; -/** - * Version string of quiche/nghttp3. Added in v4.1.0. Available if libcurl is v7.66.0 or more recent. - */ -const QUIC = NULL; -/** - * Default path to the certificate bundle file. Added in v4.1.0. Available if libcurl is v7.70.0 or more recent. - */ -const CAINFO = NULL; -/** - * Default path to the certificate bundle directory. Added in v4.1.0. Available if libcurl is v7.70.0 or more recent. - */ -const CAPATH = NULL; -/** - * Version string of the zstd library. Added in v4.1.0. Available if libcurl is v7.72.0 or more recent. - */ -const ZSTD = NULL; -/** - * Version string of the hyper library. Added in v4.1.0. Available if libcurl is v7.75.0 or more recent. - */ -const HYPER = NULL; -namespace http\Encoding; -/** - * Base class for encoding stream implementations. - */ -abstract class Stream { - /** - * Do no intermittent flushes. - */ - const FLUSH_NONE = 0; - /** - * Flush at appropriate transfer points. - */ - const FLUSH_SYNC = 1048576; - /** - * Flush at each IO operation. - */ - const FLUSH_FULL = 2097152; - /** - * Base constructor for encoding stream implementations. - * - * @param int $flags See http\Encoding\Stream and implementation specific constants. - * @throws \http\Exception\InvalidArgumentException - * @throws \http\Exception\RuntimeException - */ - function __construct(int $flags = 0) {} - /** - * Check whether the encoding stream is already done. - * - * @return bool whether the encoding stream is completed. - */ - function done() {} - /** - * Finish and reset the encoding stream. - * Returns any pending data. - * - * @return string any pending data. - */ - function finish() {} - /** - * Flush the encoding stream. - * Returns any pending data. - * - * @return string any pending data. - */ - function flush() {} - /** - * Update the encoding stream with more input. - * - * @param string $data The data to pass through the stream. - * @return string processed data. - */ - function update(string $data) {} -} -namespace http\Encoding\Stream; -/** - * A [brotli](https://brotli.org) decoding stream. - * - * > ***NOTE:*** - * > This class has been added in v3.2.0. - */ -class Debrotli extends \http\Encoding\Stream { - /** - * Decode brotli encoded data. - * - * @param string $data The data to uncompress. - * @return string the uncompressed data. - */ - function decode(string $data) {} -} -/** - * A stream decoding data encoded with chunked transfer encoding. - */ -class Dechunk extends \http\Encoding\Stream { - /** - * Decode chunked encoded data. - * - * @param string $data The data to decode. - * @param int $decoded_len Out parameter with the length of $data that's been decoded. - * Should be ```strlen($data)``` if not truncated. - * @return string|string|string|false string the decoded data. - * or string the unencoded data. - * or string the truncated decoded data. - * or false if $data cannot be decoded. - */ - function decode(string $data, int &$decoded_len = 0) {} -} -/** - * A deflate stream supporting deflate, zlib and gzip encodings. - */ -class Deflate extends \http\Encoding\Stream { - /** - * Gzip encoding. RFC1952 - */ - const TYPE_GZIP = 16; - /** - * Zlib encoding. RFC1950 - */ - const TYPE_ZLIB = 0; - /** - * Deflate encoding. RFC1951 - */ - const TYPE_RAW = 32; - /** - * Default compression level. - */ - const LEVEL_DEF = 0; - /** - * Least compression level. - */ - const LEVEL_MIN = 1; - /** - * Greatest compression level. - */ - const LEVEL_MAX = 9; - /** - * Default compression strategy. - */ - const STRATEGY_DEF = 0; - /** - * Filtered compression strategy. - */ - const STRATEGY_FILT = 256; - /** - * Huffman strategy only. - */ - const STRATEGY_HUFF = 512; - /** - * Run-length encoding strategy. - */ - const STRATEGY_RLE = 768; - /** - * Encoding with fixed Huffman codes only. - * - * > **A note on the compression strategy:** - * > - * > The strategy parameter is used to tune the compression algorithm. - * > - * > Use the value DEFAULT_STRATEGY for normal data, FILTERED for data produced by a filter (or predictor), HUFFMAN_ONLY to force Huffman encoding only (no string match), or RLE to limit match distances to one (run-length encoding). - * > - * > Filtered data consists mostly of small values with a somewhat random distribution. In this case, the compression algorithm is tuned to compress them better. The effect of FILTERED is to force more Huffman coding and less string matching; it is somewhat intermediate between DEFAULT_STRATEGY and HUFFMAN_ONLY. - * > - * > RLE is designed to be almost as fast as HUFFMAN_ONLY, but give better compression for PNG image data. - * > - * > FIXED prevents the use of dynamic Huffman codes, allowing for a simpler decoder for special applications. - * > - * > The strategy parameter only affects the compression ratio but not the correctness of the compressed output even if it is not set appropriately. - * > - * >_Source: [zlib Manual](http://www.zlib.net/manual.html)_ - */ - const STRATEGY_FIXED = 1024; - /** - * Encode data with deflate/zlib/gzip encoding. - * - * @param string $data The data to compress. - * @param int $flags Any compression tuning flags. See http\Encoding\Stream\Deflate and http\Encoding\Stream constants. - * @return string the compressed data. - */ - function encode(string $data, int $flags = 0) {} -} -/** - * A [brotli](https://brotli.org) encoding stream. - * - * > ***NOTE:*** - * > This class has been added in v3.2.0. - */ -class Enbrotli extends \http\Encoding\Stream { - /** - * Default compression level. - */ - const LEVEL_DEF = 4; - /** - * Least compression level. - */ - const LEVEL_MIN = 1; - /** - * Greatest compression level. - */ - const LEVEL_MAX = 11; - /** - * Default window bits. - */ - const WBITS_DEF = 352; - /** - * Minimum window bits. - */ - const WBITS_MIN = 160; - /** - * Maximum window bits. - */ - const WBITS_MAX = 384; - /** - * Default compression mode. - */ - const MODE_GENERIC = 0; - /** - * Compression mode for UTF-8 formatted text. - */ - const MODE_TEXT = 4096; - /** - * Compression mode used in WOFF 2.0. - */ - const MODE_FONT = 8192; - /** - * Encode data with brotli encoding. - * - * @param string $data The data to compress. - * @param int $flags Any compression tuning flags. See http\Encoding\Stream\Enbrotli and http\Encoding\Stream constants. - * @return string the compressed data. - */ - function encode(string $data, int $flags = 0) {} -} -/** - * A inflate stream supporting deflate, zlib and gzip encodings. - */ -class Inflate extends \http\Encoding\Stream { - /** - * Decode deflate/zlib/gzip encoded data. - * - * @param string $data The data to uncompress. - * @return string the uncompressed data. - */ - function decode(string $data) {} -} -namespace http\Env; -/** - * The http\Env\Request class' instances represent the server's current HTTP request. - * - * See http\Message for inherited members. - */ -class Request extends \http\Message { - /** - * The request's query parameters. ($_GET) - * - * @protected - * @var \http\QueryString - */ - protected $query = NULL; - /** - * The request's form parameters. ($_POST) - * - * @protected - * @var \http\QueryString - */ - protected $form = NULL; - /** - * The request's form uploads. ($_FILES) - * - * @protected - * @var array - */ - protected $files = NULL; - /** - * The request's cookies. ($_COOKIE) - * - * @protected - * @var array - */ - protected $cookie = NULL; - /** - * Create an instance of the server's current HTTP request. - * - * Upon construction, the http\Env\Request acquires http\QueryString instances of query parameters ($\_GET) and form parameters ($\_POST). - * - * It also compiles an array of uploaded files ($\_FILES) more comprehensive than the original $\_FILES array, see http\Env\Request::getFiles() for that matter. - * - * @throws \http\Exception\InvalidArgumentException - * @throws \http\Exception\UnexpectedValueException - */ - function __construct() {} - /** - * Retrieve an URL query value ($_GET). - * - * See http\QueryString::get() and http\QueryString::TYPE_* constants. - * - * @param string $name The key to retrieve the value for. - * @param mixed $type The type to cast the value to. See http\QueryString::TYPE_* constants. - * @param mixed $defval The default value to return if the key $name does not exist. - * @param bool $delete Whether to delete the entry from the querystring after retrieval. - * @return \http\QueryString|string|mixed|mixed|string \http\QueryString if called without arguments. - * or string the whole querystring if $name is of zero length. - * or mixed $defval if the key $name does not exist. - * or mixed the querystring value cast to $type if $type was specified and the key $name exists. - * or string the querystring value if the key $name exists and $type is not specified or equals http\QueryString::TYPE_STRING. - */ - function getCookie(string $name = NULL, $type = NULL, $defval = NULL, bool $delete = false) {} - /** - * Retrieve the uploaded files list ($_FILES). - * - * @return array the consolidated upload files array. - */ - function getFiles() {} - /** - * Retrieve a form value ($_POST). - * - * See http\QueryString::get() and http\QueryString::TYPE_* constants. - * - * @param string $name The key to retrieve the value for. - * @param mixed $type The type to cast the value to. See http\QueryString::TYPE_* constants. - * @param mixed $defval The default value to return if the key $name does not exist. - * @param bool $delete Whether to delete the entry from the querystring after retrieval. - * @return \http\QueryString|string|mixed|mixed|string \http\QueryString if called without arguments. - * or string the whole querystring if $name is of zero length. - * or mixed $defval if the key $name does not exist. - * or mixed the querystring value cast to $type if $type was specified and the key $name exists. - * or string the querystring value if the key $name exists and $type is not specified or equals http\QueryString::TYPE_STRING. - */ - function getForm(string $name = NULL, $type = NULL, $defval = NULL, bool $delete = false) {} - /** - * Retrieve an URL query value ($_GET). - * - * See http\QueryString::get() and http\QueryString::TYPE_* constants. - * - * @param string $name The key to retrieve the value for. - * @param mixed $type The type to cast the value to. See http\QueryString::TYPE_* constants. - * @param mixed $defval The default value to return if the key $name does not exist. - * @param bool $delete Whether to delete the entry from the querystring after retrieval. - * @return \http\QueryString|string|mixed|mixed|string \http\QueryString if called without arguments. - * or string the whole querystring if $name is of zero length. - * or mixed $defval if the key $name does not exist. - * or mixed the querystring value cast to $type if $type was specified and the key $name exists. - * or string the querystring value if the key $name exists and $type is not specified or equals http\QueryString::TYPE_STRING. - */ - function getQuery(string $name = NULL, $type = NULL, $defval = NULL, bool $delete = false) {} -} -/** - * The http\Env\Response class' instances represent the server's current HTTP response. - * - * See http\Message for inherited members. - */ -class Response extends \http\Message { - /** - * Do not use content encoding. - */ - const CONTENT_ENCODING_NONE = 0; - /** - * Support "Accept-Encoding" requests with gzip and deflate encoding. - */ - const CONTENT_ENCODING_GZIP = 1; - /** - * No caching info available. - */ - const CACHE_NO = 0; - /** - * The cache was hit. - */ - const CACHE_HIT = 1; - /** - * The cache was missed. - */ - const CACHE_MISS = 2; - /** - * A request instance which overrides the environments default request. - * - * @protected - * @var \http\Env\Request - */ - protected $request = NULL; - /** - * The response's MIME content type. - * - * @protected - * @var string - */ - protected $contentType = NULL; - /** - * The response's MIME content disposition. - * - * @protected - * @var string - */ - protected $contentDisposition = NULL; - /** - * See http\Env\Response::CONTENT_ENCODING_* constants. - * - * @protected - * @var int - */ - protected $contentEncoding = NULL; - /** - * How the client should treat this response in regards to caching. - * - * @protected - * @var string - */ - protected $cacheControl = NULL; - /** - * A custom ETag. - * - * @protected - * @var string - */ - protected $etag = NULL; - /** - * A "Last-Modified" time stamp. - * - * @protected - * @var int - */ - protected $lastModified = NULL; - /** - * Any throttling delay. - * - * @protected - * @var int - */ - protected $throttleDelay = NULL; - /** - * The chunk to send every $throttleDelay seconds. - * - * @protected - * @var int - */ - protected $throttleChunk = NULL; - /** - * The response's cookies. - * - * @protected - * @var array - */ - protected $cookies = NULL; - /** - * Create a new env response message instance. - * - * @throws \http\Exception\InvalidArgumentException - * @throws \http\Exception\UnexpectedValueException - */ - function __construct() {} - /** - * Output buffer handler. - * Appends output data to the body. - * - * @param string $data The data output. - * @param int $ob_flags Output buffering flags passed from the output buffering control layer. - * @return bool success. - */ - function __invoke(string $data, int $ob_flags = 0) {} - /** - * Manually test the header $header_name of the environment's request for a cache hit. - * http\Env\Response::send() checks that itself, though. - * - * @param string $header_name The request header to test. - * @return int a http\Env\Response::CACHE_* constant. - */ - function isCachedByEtag(string $header_name = "If-None-Match") {} - /** - * Manually test the header $header_name of the environment's request for a cache hit. - * http\Env\Response::send() checks that itself, though. - * - * @param string $header_name The request header to test. - * @return int a http\Env\Response::CACHE_* constant. - */ - function isCachedByLastModified(string $header_name = "If-Modified-Since") {} - /** - * Send the response through the SAPI or $stream. - * Flushes all output buffers. - * - * @param resource $stream A writable stream to send the response through. - * @return bool success. - */ - function send($stream = NULL) {} - /** - * Make suggestions to the client how it should cache the response. - * - * @param string $cache_control (A) "Cache-Control" header value(s). - * @throws \http\Exception\InvalidArgumentException - * @return \http\Env\Response self. - */ - function setCacheControl(string $cache_control) {} - /** - * Set the reponse's content disposition parameters. - * - * @param array $disposition_params MIME content disposition as http\Params array. - * @throws \http\Exception\InvalidArgumentException - * @return \http\Env\Response self. - */ - function setContentDisposition(array $disposition_params) {} - /** - * Enable support for "Accept-Encoding" requests with deflate or gzip. - * The response will be compressed if the client indicates support and wishes that. - * - * @param int $content_encoding See http\Env\Response::CONTENT_ENCODING_* constants. - * @throws \http\Exception\InvalidArgumentException - * @return \http\Env\Response self. - */ - function setContentEncoding(int $content_encoding) {} - /** - * Set the MIME content type of the response. - * - * @param string $content_type The response's content type. - * @throws \http\Exception\InvalidArgumentException - * @return \http\Env\Response self. - */ - function setContentType(string $content_type) {} - /** - * Add cookies to the response to send. - * - * @param mixed $cookie The cookie to send. - * @throws \http\Exception\InvalidArgumentException - * @throws \http\Exception\UnexpectedValueException - * @return \http\Env\Response self. - */ - function setCookie($cookie) {} - /** - * Override the environment's request. - * - * @param \http\Message $env_request The overriding request message. - * @throws \http\Exception\InvalidArgumentException - * @return \http\Env\Response self. - */ - function setEnvRequest(\http\Message $env_request) {} - /** - * Set a custom ETag. - * - * > ***NOTE:*** - * > This will be used for caching and pre-condition checks. - * - * @param string $etag A ETag. - * @throws \http\Exception\InvalidArgumentException - * @return \http\Env\Response self. - */ - function setEtag(string $etag) {} - /** - * Set a custom last modified time stamp. - * - * > ***NOTE:*** - * > This will be used for caching and pre-condition checks. - * - * @param int $last_modified A unix timestamp. - * @throws \http\Exception\InvalidArgumentException - * @return \http\Env\Response self. - */ - function setLastModified(int $last_modified) {} - /** - * Enable throttling. - * Send $chunk_size bytes every $delay seconds. - * - * > ***NOTE:*** - * > If you need throttling by regular means, check for other options in your stack, because this method blocks the executing process/thread until the response has completely been sent. - * - * @param int $chunk_size Bytes to send. - * @param float $delay Seconds to sleep. - * @return \http\Env\Response self. - */ - function setThrottleRate(int $chunk_size, float $delay = 1) {} -} -/** - * URL class using the HTTP environment by default. - * - * > ***NOTE:*** - * > This class has been added in v3.0.0. - * - * Always adds http\Url::FROM_ENV to the $flags constructor argument. See also http\Url. - */ -class Url extends \http\Url { -} -namespace http\Exception; -/** - * A bad conversion (e.g. character conversion) was encountered. - */ -class BadConversionException extends \DomainException implements \http\Exception { -} -/** - * A bad HTTP header was encountered. - */ -class BadHeaderException extends \DomainException implements \http\Exception { -} -/** - * A bad HTTP message was encountered. - */ -class BadMessageException extends \DomainException implements \http\Exception { -} -/** - * A method was called on an object, which was in an invalid or unexpected state. - */ -class BadMethodCallException extends \BadMethodCallException implements \http\Exception { -} -/** - * A bad querystring was encountered. - */ -class BadQueryStringException extends \DomainException implements \http\Exception { -} -/** - * A bad HTTP URL was encountered. - */ -class BadUrlException extends \DomainException implements \http\Exception { -} -/** - * One or more invalid arguments were passed to a method. - */ -class InvalidArgumentException extends \InvalidArgumentException implements \http\Exception { -} -/** - * A generic runtime exception. - */ -class RuntimeException extends \RuntimeException implements \http\Exception { -} -/** - * An unexpected value was encountered. - */ -class UnexpectedValueException extends \UnexpectedValueException implements \http\Exception { -} -namespace http\Header; -/** - * The parser which is underlying http\Header and http\Message. - * - * > ***NOTE:*** - * > This class has been added in v2.3.0. - */ -class Parser { - /** - * Finish up parser at end of (incomplete) input. - */ - const CLEANUP = 1; - /** - * Parse failure. - */ - const STATE_FAILURE = -1; - /** - * Expecting HTTP info (request/response line) or headers. - */ - const STATE_START = 0; - /** - * Expecting a key or already parsing a key. - */ - const STATE_KEY = 1; - /** - * Expecting a value or already parsing the value. - */ - const STATE_VALUE = 2; - /** - * At EOL of an header, checking whether a folded header line follows. - */ - const STATE_VALUE_EX = 3; - /** - * A header was completed. - */ - const STATE_HEADER_DONE = 4; - /** - * Finished parsing the headers. - * - * > ***NOTE:*** - * > Most of this states won't be returned to the user, because the parser immediately jumps to the next expected state. - */ - const STATE_DONE = 5; - /** - * Retrieve the current state of the parser. - * See http\Header\Parser::STATE_* constants. - * - * @throws \http\Exception\InvalidArgumentException - * @return int http\Header\Parser::STATE_* constant. - */ - function getState() {} - /** - * Parse a string. - * - * @param string $data The (part of the) header to parse. - * @param int $flags Any combination of [parser flags](http/Header/Parser#Parser.flags:). - * @param array $header Successfully parsed headers. - * @throws \http\Exception\InvalidArgumentException - * @return int http\Header\Parser::STATE_* constant. - */ - function parse(string $data, int $flags, array &$header = NULL) {} - /** - * Parse a stream. - * - * @param resource $stream The header stream to parse from. - * @param int $flags Any combination of [parser flags](http/Header/Parser#Parser.flags:). - * @param array $headers The headers parsed. - * @throws \http\Exception\InvalidArgumentException - * @throws \http\Exception\UnexpectedValueException - * @return int http\Header\Parser::STATE_* constant. - */ - function stream($stream, int $flags, array &$headers) {} -} -namespace http\Message; -/** - * The message body, represented as a PHP (temporary) stream. - * - * > ***NOTE:*** - * > Currently, http\Message\Body::addForm() creates multipart/form-data bodies. - */ -class Body implements \Serializable { - /** - * Create a new message body, optionally referencing $stream. - * - * @param resource $stream A stream to be used as message body. - * @throws \http\Exception\InvalidArgumentException - * @throws \http\Exception\UnexpectedValueException - */ - function __construct($stream = NULL) {} - /** - * String cast handler. - * - * @return string the message body. - */ - function __toString() {} - /** - * Add form fields and files to the message body. - * - * > ***NOTE:*** - * > Currently, http\Message\Body::addForm() creates "multipart/form-data" bodies. - * - * @param array $fields List of form fields to add. - * @param array $files List of form files to add. - * - * $fields must look like: - * - * [ - * "field_name" => "value", - * "multi_field" => [ - * "value1", - * "value2" - * ] - * ] - * - * $files must look like: - * - * [ - * [ - * "name" => "field_name", - * "type" => "content/type", - * "file" => "/path/to/file.ext" - * ], [ - * "name" => "field_name2", - * "type" => "text/plain", - * "file" => "file.ext", - * "data" => "string" - * ], [ - * "name" => "field_name3", - * "type" => "image/jpeg", - * "file" => "file.ext", - * "data" => fopen("/home/mike/Pictures/mike.jpg","r") - * ] - * - * As you can see, a file structure must contain a "file" entry, which holds a file path, and an optional "data" entry, which may either contain a resource to read from or the actual data as string. - * @throws \http\Exception\InvalidArgumentException - * @throws \http\Exception\RuntimeException - * @return \http\Message\Body self. - */ - function addForm(array $fields = NULL, array $files = NULL) {} - /** - * Add a part to a multipart body. - * - * @param \http\Message $part The message part. - * @throws \http\Exception\InvalidArgumentException - * @throws \http\Exception\RuntimeException - * @return \http\Message\Body self. - */ - function addPart(\http\Message $part) {} - /** - * Append plain bytes to the message body. - * - * @param string $data The data to append to the body. - * @throws \http\Exception\InvalidArgumentException - * @throws \http\Exception\RuntimeException - * @return \http\Message\Body self. - */ - function append(string $data) {} - /** - * Retrieve the ETag of the body. - * - * @return string|string|false string an Apache style ETag of inode, mtime and size in hex concatenated by hyphens if the message body stream is stat-able. - * or string a content hash (which algorithm is determined by INI http.etag.mode) if the stream is not stat-able. - * or false if http.etag.mode is not a known hash algorithm. - */ - function etag() {} - /** - * Retrieve any boundary of the message body. - * See http\Message::splitMultipartBody(). - * - * @return string|NULL string the message body boundary. - * or NULL if this message body has no boundary. - */ - function getBoundary() {} - /** - * Retrieve the underlying stream resource. - * - * @return resource the underlying stream. - */ - function getResource() {} - /** - * Implements Serializable. - * Alias of http\Message\Body::__toString(). - * - * @return string serialized message body. - */ - function serialize() {} - /** - * Stat size, atime, mtime and/or ctime. - * - * @param string $field A single stat field to retrieve. - * @return int|object int the requested stat field. - * or object stdClass instance holding all four stat fields. - */ - function stat(string $field = NULL) {} - /** - * Stream the message body through a callback. - * - * @param callable $callback The callback of the form function(http\Message\Body $from, string $data). - * @param int $offset Start to stream from this offset. - * @param int $maxlen Stream at most $maxlen bytes, or all if $maxlen is less than 1. - * @return \http\Message\Body self. - */ - function toCallback(callable $callback, int $offset = 0, int $maxlen = 0) {} - /** - * Stream the message body into another stream $stream, starting from $offset, streaming $maxlen at most. - * - * @param resource $stream The resource to write to. - * @param int $offset The starting offset. - * @param int $maxlen The maximum amount of data to stream. All content if less than 1. - * @return \http\Message\Body self. - */ - function toStream($stream, int $offset = 0, int $maxlen = 0) {} - /** - * Retrieve the message body serialized to a string. - * Alias of http\Message\Body::__toString(). - * - * @return string message body. - */ - function toString() {} - /** - * Implements Serializable. - * - * @param string $serialized The serialized message body. - */ - function unserialize($serialized) {} -} -/** - * The parser which is underlying http\Message. - * - * > ***NOTE:*** - * > This class was added in v2.2.0. - */ -class Parser { - /** - * Finish up parser at end of (incomplete) input. - */ - const CLEANUP = 1; - /** - * Soak up the rest of input if no entity length is deducible. - */ - const DUMB_BODIES = 2; - /** - * Redirect messages do not contain any body despite of indication of such. - */ - const EMPTY_REDIRECTS = 4; - /** - * Continue parsing while input is available. - */ - const GREEDY = 8; - /** - * Parse failure. - */ - const STATE_FAILURE = -1; - /** - * Expecting HTTP info (request/response line) or headers. - */ - const STATE_START = 0; - /** - * Parsing headers. - */ - const STATE_HEADER = 1; - /** - * Completed parsing headers. - */ - const STATE_HEADER_DONE = 2; - /** - * Parsing the body. - */ - const STATE_BODY = 3; - /** - * Soaking up all input as body. - */ - const STATE_BODY_DUMB = 4; - /** - * Reading body as indicated by `Content-Length` or `Content-Range`. - */ - const STATE_BODY_LENGTH = 5; - /** - * Parsing `chunked` encoded body. - */ - const STATE_BODY_CHUNKED = 6; - /** - * Finished parsing the body. - */ - const STATE_BODY_DONE = 7; - /** - * Updating Content-Length based on body size. - */ - const STATE_UPDATE_CL = 8; - /** - * Finished parsing the message. - * - * > ***NOTE:*** - * > Most of this states won't be returned to the user, because the parser immediately jumps to the next expected state. - */ - const STATE_DONE = 9; - /** - * Retrieve the current state of the parser. - * See http\Message\Parser::STATE_* constants. - * - * @throws \http\Exception\InvalidArgumentException - * @return int http\Message\Parser::STATE_* constant. - */ - function getState() {} - /** - * Parse a string. - * - * @param string $data The (part of the) message to parse. - * @param int $flags Any combination of [parser flags](http/Message/Parser#Parser.flags:). - * @param \http\Message $message The current state of the message parsed. - * @throws \http\Exception\InvalidArgumentException - * @return int http\Message\Parser::STATE_* constant. - */ - function parse(string $data, int $flags, \http\Message &$message) {} - /** - * Parse a stream. - * - * @param resource $stream The message stream to parse from. - * @param int $flags Any combination of [parser flags](http/Message/Parser#Parser.flags:). - * @param \http\Message $message The current state of the message parsed. - * @throws \http\Exception\InvalidArgumentException - * @throws \http\Exception\UnexpectedValueException - * @return int http\Message\Parser::STATE_* constant. - */ - function stream($stream, int $flags, \http\Message &$message) {} -} diff --git a/lib/API.php b/lib/API.php index 8e4f04c..3ed788a 100644 --- a/lib/API.php +++ b/lib/API.php @@ -14,69 +14,32 @@ use seekat\Exception\InvalidArgumentException; class API implements IteratorAggregate, Countable { /** * API version - * @var int */ - private $version = 3; - - /** - * The current API endpoint URL - * @var Url - */ - private $url; + private int $version = 3; /** * Default headers to send out to the API endpoint - * @var array */ - private $headers; + private array $headers; /** * Current endpoints links - * @var Links */ - private $links; + private ?Links $links = null; /** * Current endpoint data's Content-Type - * @var API\ContentType */ - private $type; + private API\ContentType $type; /** * Current endpoint's data - * @var array|object - */ - private $data; - - /** - * Logger - * @var LoggerInterface - */ - private $logger; - - /** - * Cache - * @var Call\Cache\Service - */ - private $cache; - - /** - * Promisor - * @var Future - */ - private $future; - - /** - * The HTTP client - * @var Client */ - private $client; + private mixed $data = null; /** * Create a new API endpoint root * - * @codeCoverageIgnore - * * @param Future $future pretending to fulfill promises * @param array $headers Standard request headers, defaults to ["Accept" => "application/vnd.github.v3+json"] * @param Url $url The API's endpoint, defaults to https://api.github.com @@ -84,12 +47,12 @@ class API implements IteratorAggregate, Countable { * @param LoggerInterface $log A logger * @param Call\Cache\Service $cache A cache */ - function __construct(Future $future, array $headers = null, Url $url = null, Client $client = null, LoggerInterface $log = null, Call\Cache\Service $cache = null) { - $this->future = $future; - $this->cache = $cache; - $this->logger = $log ?? new NullLogger; - $this->url = $url ?? new Url("https://api.github.com"); - $this->client = $client ?? new Client; + function __construct(private readonly Future $future, + array $headers = null, + private Url $url = new Url("https://api.github.com"), + private readonly Client $client = new Client, + private readonly LoggerInterface $logger = new NullLogger, + private readonly Call\Cache\Service $cache = new Call\Cache\Service\Hollow) { $this->type = new ContentType($this->version, "json"); $this->headers = (array) $headers + [ "Accept" => $this->type->getContentType() @@ -102,8 +65,8 @@ class API implements IteratorAggregate, Countable { * @param string|int $seg The "path" element to ascend into * @return API Endpoint clone referring to {$parent}/{$seg} */ - function __get($seg) : API { - if (substr($seg, -4) === "_url") { + function __get(string|int $seg) : API { + if (str_ends_with($seg, "_url")) { $url = new Url(uri_template($this->data->$seg)); $that = $this->withUrl($url); $seg = basename($that->url->path); @@ -158,8 +121,8 @@ class API implements IteratorAggregate, Countable { * @return mixed The promise of the generator's return value * @throws InvalidArgumentException */ - function __invoke($cbg) { - $this->logger->debug(__FUNCTION__); + function __invoke(callable|Generator $cbg) { + $this->logger->debug(__METHOD__, [$cbg]); $consumer = new Consumer($this->getFuture(), function() { $this->client->send(); @@ -235,38 +198,27 @@ class API implements IteratorAggregate, Countable { return $count; } - /** - * @return Url - */ function getUrl() : Url { return $this->url; } - /** - * @return LoggerInterface - */ function getLogger() : LoggerInterface { return $this->logger; } - /** - * @return Future - */ - function getFuture() { + function getFuture() : Future { return $this->future; } - /** - * @return Client - */ public function getClient(): Client { return $this->client; } - /** - * @return array|object - */ - function getData() { + public function getCache() : Call\Cache\Service { + return $this->cache; + } + + function getData() : mixed { return $this->data; } @@ -275,7 +227,7 @@ class API implements IteratorAggregate, Countable { * * @return null|Links */ - function getLinks() { + function getLinks() : ?Links { return $this->links; } @@ -294,7 +246,7 @@ class API implements IteratorAggregate, Countable { function export() : array { $data = $this->data; $url = clone $this->url; - $type = $this->type ? clone $this->type : null; + $type = clone $this->type; $links = $this->links ? clone $this->links : null; $headers = $this->headers; return compact("url", "data", "type", "links", "headers"); @@ -322,7 +274,7 @@ class API implements IteratorAggregate, Countable { * @param mixed $data * @return API clone */ - function withData($data) : API { + function withData(mixed $data) : API { $that = clone $this; $that->data = $data; return $that; @@ -349,7 +301,7 @@ class API implements IteratorAggregate, Countable { * @param mixed $value * @return API clone */ - function withHeader(string $name, $value) : API { + function withHeader(string $name, mixed $value) : API { $that = clone $this; if (isset($value)) { $that->headers[$name] = $value; @@ -387,8 +339,8 @@ class API implements IteratorAggregate, Countable { * @param array $headers The request's additional HTTP headers * @return mixed promise */ - function head($args = null, array $headers = null, $cache = null) { - return $this->request("HEAD", $args, null, $headers, $cache); + function head($args = null, array $headers = null) { + return $this->request("HEAD", $args, null, $headers); } /** @@ -398,8 +350,8 @@ class API implements IteratorAggregate, Countable { * @param array $headers The request's additional HTTP headers * @return mixed promise */ - function get($args = null, array $headers = null, $cache = null) { - return $this->request("GET", $args, null, $headers, $cache); + function get($args = null, array $headers = null) { + return $this->request("GET", $args, null, $headers); } /** @@ -497,12 +449,11 @@ class API implements IteratorAggregate, Countable { * * @param string $method The HTTP request method * @param mixed $args The HTTP query string parameters - * @param mixed $body Thee HTTP message's body - * @param array $headers The request's additional HTTP headers - * @param Call\Cache\Service $cache + * @param mixed $body The HTTP message's body + * @param ?array $headers The request's additional HTTP headers * @return mixed promise */ - private function request(string $method, $args = null, $body = null, array $headers = null, Call\Cache\Service $cache = null) { + private function request(string $method, $args = null, $body = null, array $headers = null) { if (isset($this->data)) { $this->logger->debug("request -> resolve", [ "method" => $method, @@ -512,7 +463,7 @@ class API implements IteratorAggregate, Countable { "headers" => $headers, ]); - return Future\resolve($this->future, $this); + return $this->future->resolve($this); } $url = $this->url->mod(["query" => new QueryString($args)]); @@ -527,6 +478,6 @@ class API implements IteratorAggregate, Countable { "headers" => $headers, ]); - return (new Call\Deferred($this, $request, $cache ?: $this->cache))(); + return (new Call\Deferred($this, $request, $this->cache))(); } } diff --git a/lib/API/Call.php b/lib/API/Call.php index 38b1559..a913bda 100644 --- a/lib/API/Call.php +++ b/lib/API/Call.php @@ -6,19 +6,7 @@ use http\Url; use seekat\API; final class Call { - /** - * @var API - */ - private $api; - - /** - * @var string - */ - private $call; - - function __construct(API $api, string $call) { - $this->api = $api; - $this->call = $call; + function __construct(private readonly API $api, private readonly string $call) { } function __invoke(array $args) { diff --git a/lib/API/Call/Cache.php b/lib/API/Call/Cache.php index 3947259..1b7e327 100644 --- a/lib/API/Call/Cache.php +++ b/lib/API/Call/Cache.php @@ -4,22 +4,17 @@ namespace seekat\API\Call; use http\Client\Request; use http\Client\Response; +use Psr\Log\LoggerInterface; use seekat\API\Call\Cache\Control; use seekat\API\Call\Cache\Service; use seekat\API\Call\Cache\Service\Hollow; final class Cache { - /** - * @var Service - */ - private $cache; - - /** - * @param Service $cache - */ - public function __construct(Service $cache = null) { - $this->cache = $cache ?? new Hollow; + public function __construct( + private readonly LoggerInterface $logger, + private readonly Service $cache = new Hollow + ) { } /** @@ -31,15 +26,18 @@ final class Cache { public function save(Request $request, Response $response) : bool { $ctl = new Control($request); if (!$ctl->isValid()) { + $this->logger->warning("cache -> save = invalid key", compact("ctl")); return false; } $time = time(); if ($time - 1 <= $response->getHeader("X-Cache-Time")) { + $this->logger->info("cache -> save = no", compact("time")); return true; } $response->setHeader("X-Cache-Time", $time); + $this->logger->info("cache -> save = yes", compact("time")); return $this->cache->store($ctl->getKey(), $response); } @@ -52,10 +50,12 @@ final class Cache { public function load(Request $request, Response &$response = null) : bool { $ctl = new Control($request); if (!$ctl->isValid()) { + $this->logger->warning("cache -> load = invalid key", compact("ctl")); return false; } if (!$this->cache->fetch($ctl->getKey(), $response)) { + $this->logger->info("cache -> load = no"); return false; } if ($ctl->isStale($response)) { @@ -65,9 +65,11 @@ final class Cache { if (($etag = $response->getHeader("ETag"))) { $request->setOptions(["etag" => $etag]); } + $this->logger->info("cache -> load = stale"); return false; } $response->setHeader("X-Cache-Hit", $response->getHeader("X-Cache-Hit") + 1); + $this->logger->info("cache -> load = yes"); return true; } @@ -80,24 +82,30 @@ final class Cache { public function update(Request $request, Response &$response) : bool { $ctl = new Control($request); if (!$ctl->isValid()) { + $this->logger->warning("cache -> update = invalid key", compact("ctl")); return false; } if ($response->getResponseCode() !== 304) { + $this->logger->info("cache -> update = yes"); return $this->save($request, $response); } /** @var Response $cached */ if (!$this->cache->fetch($ctl->getKey(), $cached)) { + $this->logger->info("cache -> update = yes; no-exist"); return $this->save($request, $response); } if ($response->getHeader("ETag") !== $cached->getHeader("ETag")) { + $this->logger->info("cache -> update = yes; etag"); return $this->save($request, $response); } - $cached->setHeader("X-Cache-Update", $cached->getHeader("X-Cache-Update") + 1); $response = $cached; - return true; + $response->setHeader("X-Cache-Update", $cached->getHeader("X-Cache-Update") + 1); + + $this->logger->info("cache -> update = yes; touch"); + return $this->save($request, $response); } } diff --git a/lib/API/Call/Cache/Control.php b/lib/API/Call/Cache/Control.php index 7ebac9d..a6186f2 100644 --- a/lib/API/Call/Cache/Control.php +++ b/lib/API/Call/Cache/Control.php @@ -10,10 +10,7 @@ use http\QueryString; use http\Url; final class Control { - /** - * @var string - */ - private $key; + private string $key; /** * @param Request $request diff --git a/lib/API/Call/Cache/Service.php b/lib/API/Call/Cache/Service.php index 31db9e9..57b9237 100644 --- a/lib/API/Call/Cache/Service.php +++ b/lib/API/Call/Cache/Service.php @@ -7,6 +7,6 @@ use http\Client\Response; interface Service { function fetch(string $key, Response &$response = null) : bool; function store(string $key, Response $response) : bool; - function del(string $key); - function clear(); + function del(string $key) : void; + function clear() : void; } diff --git a/lib/API/Call/Cache/Service/Hollow.php b/lib/API/Call/Cache/Service/Hollow.php index f08d6d6..dd81ba3 100644 --- a/lib/API/Call/Cache/Service/Hollow.php +++ b/lib/API/Call/Cache/Service/Hollow.php @@ -6,7 +6,7 @@ use http\Client\Response; use seekat\API\Call\Cache\Service; final class Hollow implements Service { - private $storage = []; + private array $storage = []; public function fetch(string $key, Response &$response = null) : bool { if (isset($this->storage[$key])) { @@ -21,11 +21,11 @@ final class Hollow implements Service { return true; } - public function del(string $key) { + public function del(string $key) : void { unset($this->storage[$key]); } - public function clear() { + public function clear() : void { $this->storage = []; } diff --git a/lib/API/Call/Cache/Service/ItemPool.php b/lib/API/Call/Cache/Service/ItemPool.php index 264cfbd..fb488ad 100644 --- a/lib/API/Call/Cache/Service/ItemPool.php +++ b/lib/API/Call/Cache/Service/ItemPool.php @@ -8,18 +8,9 @@ use Psr\Cache\CacheItemPoolInterface; use seekat\API\Call\Cache\Service; final class ItemPool implements Service { - /** - * @var CacheItemPoolInterface - */ - private $cache; - - /** - * @var CacheItemInterface - */ - private $item; + private ?CacheItemInterface $item; - public function __construct(CacheItemPoolInterface $cache) { - $this->cache = $cache; + public function __construct(private readonly CacheItemPoolInterface $cache) { } /** @@ -46,11 +37,11 @@ final class ItemPool implements Service { * @param string $key * @throws \Psr\Cache\InvalidArgumentException */ - public function del(string $key) { + public function del(string $key) : void { $this->cache->deleteItem($key); } - public function clear() { + public function clear() : void { $this->cache->clear(); } } diff --git a/lib/API/Call/Cache/Service/Simple.php b/lib/API/Call/Cache/Service/Simple.php index 4358f1f..45bd5fe 100644 --- a/lib/API/Call/Cache/Service/Simple.php +++ b/lib/API/Call/Cache/Service/Simple.php @@ -7,13 +7,7 @@ use Psr\SimpleCache\CacheInterface; use seekat\API\Call\Cache\Service; final class Simple implements Service { - /** - * @var CacheInterface - */ - private $cache; - - public function __construct(CacheInterface $cache) { - $this->cache = $cache; + public function __construct(private readonly CacheInterface $cache) { } public function fetch(string $key, Response &$response = null) : bool { @@ -25,11 +19,11 @@ final class Simple implements Service { return $this->cache->set($key, $response); } - public function del(string $key) { + public function del(string $key) : void { $this->cache->delete($key); } - public function clear() { + public function clear() : void { $this->cache->clear(); } } diff --git a/lib/API/Call/Deferred.php b/lib/API/Call/Deferred.php index bfe8c27..331cc2f 100644 --- a/lib/API/Call/Deferred.php +++ b/lib/API/Call/Deferred.php @@ -7,74 +7,34 @@ use Psr\Log\LoggerInterface; use seekat\API; final class Deferred { - /** - * The response importer - * - * @var Result - */ - private $result; - - /** - * The HTTP client - * - * @var Client - */ - private $client; - - /** - * Request cache - * - * @var callable - */ - private $cache; - - /** - * @var LoggerInterface - */ - private $logger; - - /** - * The executed request - * - * @var Request - */ - private $request; + private Result $result; + private Client $client; + private LoggerInterface $logger; + private Cache $cache; /** * The promised response - * - * @var Response */ - private $response; + private ?Response $response = null; /** * @var mixed */ - private $promise; - - /** - * @var \Closure - */ - private $resolve; - - /** - * @var \Closure - */ - private $reject; + private object $promise; + private \Closure $resolve; + private \Closure $reject; /** * Create a deferred promise for the response of $request * * @param API $api The endpoint of the request * @param Request $request The request to execute - * @param Cache\Service $cache */ - function __construct(API $api, Request $request, Cache\Service $cache = null) { - $this->request = $request; + function __construct(API $api, private readonly Request $request) { + $this->result = new Result($api); $this->client = $api->getClient(); $this->logger = $api->getLogger(); - $this->result = new Result($api); - $this->cache = new Cache($cache); + $this->cache = new Cache($this->logger, $api->getCache()); $future = $api->getFuture(); $context = $future->createContext(function() { @@ -87,8 +47,8 @@ final class Deferred { } }); $this->promise = $future->getPromise($context); - $this->resolve = API\Future\resolver($future, $context); - $this->reject = API\Future\rejecter($future, $context); + $this->resolve = $future->resolver($context); + $this->reject = $future->rejecter($context); } function __invoke() { @@ -133,12 +93,7 @@ final class Deferred { return true; } - /** - * Refresh - * - * @param Response|null $cached - */ - private function refresh(Response $cached = null) { + private function refresh(Response $cached = null) : void { $this->client->enqueue($this->request, function(Response $response) use($cached) { $this->response = $response; $this->complete(); @@ -157,7 +112,9 @@ final class Deferred { /** * Completion callback */ - private function complete(string $by = "enqueued") { + private function complete(string $by = "enqueued") : void { + $this->logger->info("complete -> $by"); + if ($this->response) { $this->logger->info("$by -> response", [ "url" => $this->request->getRequestUrl(), @@ -168,6 +125,7 @@ final class Deferred { $this->cache->update($this->request, $this->response); ($this->resolve)(($this->result)($this->response)); } catch (\Throwable $e) { + $this->logger->warning("$by -> cache", ["exception" => $e]); ($this->reject)($e); } } else { diff --git a/lib/API/Call/Result.php b/lib/API/Call/Result.php index c1cee55..92b7dae 100644 --- a/lib/API/Call/Result.php +++ b/lib/API/Call/Result.php @@ -36,11 +36,9 @@ final class Result { } /** - * @param Response $response - * @return null|API\Links * @throws RequestException */ - private function checkResponseMeta(Response $response) { + private function checkResponseMeta(Response $response) : API\Links { if ($response->getResponseCode() >= 400) { $e = new RequestException($response); @@ -59,11 +57,9 @@ final class Result { } /** - * @param Response $response - * @return API\ContentType * @throws RequestException */ - private function checkResponseType(Response $response) { + private function checkResponseType(Response $response) : API\ContentType { if (!($type = $response->getHeader("Content-Type", Header::class))) { $e = new RequestException($response); @@ -78,12 +74,9 @@ final class Result { } /** - * @param Response $response - * @param API\ContentType $type - * @return mixed * @throws \Exception */ - private function checkResponseBody(Response $response, API\ContentType $type) { + private function checkResponseBody(Response $response, API\ContentType $type) : mixed { try { $data = $type->decode($response->getBody()); } catch (\Exception $e) { diff --git a/lib/API/Consumer.php b/lib/API/Consumer.php index 3af614c..8db2b4d 100644 --- a/lib/API/Consumer.php +++ b/lib/API/Consumer.php @@ -8,64 +8,37 @@ use seekat\API; use seekat\Exception\{function exception}; final class Consumer { - /** - * Loop - * @var callable - */ - private $loop; - /** * The return value of the generator * @var mixed */ - private $result; + private mixed $result = null; /** * Cancellation flag - * @var bool - */ - private $cancelled = false; - - /** - * @var Future - */ - private $future; - - /** - * @var mixed - */ - private $context; - - /** - * @var \Closure */ - private $resolve; + private bool $cancelled = false; /** - * @var \Closure + * Promise */ - private $reject; + private object $promise; - /** - * @var \Closure - */ - private $reduce; + private \Closure $resolve; + private \Closure $reject; + private \Closure $reduce; /** * Create a new generator consumer - * @param Future $future - * @param callable $loop */ - function __construct(Future $future, callable $loop) { - $this->loop = $loop; - - $this->future = $future; - $this->context = $future->createContext(function() { + function __construct(private readonly Future $future, private readonly \Closure $loop) { + $context = $future->createContext(function() { $this->cancelled = true; }); - $this->resolve = API\Future\resolver($future, $this->context); - $this->reject = API\Future\rejecter($future, $this->context); - $this->reduce = API\Future\reducer($future, $this->context); + $this->promise = $future->getPromise($context); + $this->resolve = $future->resolver($context); + $this->reject = $future->rejecter($context); + $this->reduce = $future->reducer(); } /** @@ -74,7 +47,7 @@ final class Consumer { * @param Generator $gen * @return mixed promise */ - function __invoke(Generator $gen) { + function __invoke(Generator $gen) : mixed { $this->cancelled = false; foreach ($gen as $promise) { if ($this->cancelled) { @@ -85,15 +58,16 @@ final class Consumer { if ($this->cancelled) { ($this->reject)("Cancelled"); - } else { + } else if (!$gen->valid()) { try { $this->result = $gen->getReturn(); } catch (Exception $e) { + assert($e->getMessage() === "Cannot get return value of a generator that hasn't returned"); } - ($this->resolve)($this->result); } + ($this->resolve)($this->result); - return $this->context->promise(); + return $this->promise; } /** @@ -102,7 +76,7 @@ final class Consumer { * @param mixed $promise * @param Generator $gen */ - private function give($promise, Generator $gen) { + private function give(mixed $promise, Generator $gen) : void { if ($promise instanceof \Traversable) { $promise = iterator_to_array($promise); } diff --git a/lib/API/ContentType/Handler.php b/lib/API/ContentType/Handler.php index d6cd7c6..7aa1043 100644 --- a/lib/API/ContentType/Handler.php +++ b/lib/API/ContentType/Handler.php @@ -7,21 +7,17 @@ use http\Message\Body; interface Handler { /** * List handled types - * @return array + * @return string[] */ function types() : array; /** * Decode HTTP message body - * @param Body $body - * @return mixed */ - function decode(Body $body); + function decode(Body $body) : mixed; /** * Encode HTTP message body - * @param $data - * @return Body */ - function encode($data) : Body; + function encode(mixed $data) : Body; } diff --git a/lib/API/ContentType/Handler/Base64.php b/lib/API/ContentType/Handler/Base64.php index 979c97d..342719d 100644 --- a/lib/API/ContentType/Handler/Base64.php +++ b/lib/API/ContentType/Handler/Base64.php @@ -20,7 +20,7 @@ final class Base64 implements Handler { * @inheritdoc * @param string $data */ - function encode($data): Body { + function encode(mixed $data): Body { if (!is_scalar($data)) { throw new InvalidArgumentException( "BASE64 encoding argument must be scalar, got ".typeof($data)); @@ -32,7 +32,7 @@ final class Base64 implements Handler { * @inheritdoc * @return string */ - function decode(Body $body) { + function decode(Body $body) : string { $data = base64_decode($body, true); if (false === $data) { diff --git a/lib/API/ContentType/Handler/Json.php b/lib/API/ContentType/Handler/Json.php index d5b6a58..008e7e6 100644 --- a/lib/API/ContentType/Handler/Json.php +++ b/lib/API/ContentType/Handler/Json.php @@ -9,11 +9,6 @@ use seekat\Exception\UnexpectedValueException; use function seekat\typeof; final class Json implements Handler { - /** - * @var int - */ - private $flags; - /** * @inheritdoc */ @@ -24,14 +19,13 @@ final class Json implements Handler { /** * @param int $flags json_encode() flags */ - function __construct(int $flags = 0) { - $this->flags = $flags; + function __construct(private readonly int $flags = 0) { } /** * @inheritdoc */ - function encode($data): Body { + function encode(mixed $data): Body { if (is_scalar($data)) { $json = $data; } else { @@ -49,7 +43,7 @@ final class Json implements Handler { /** * @inheritdoc */ - function decode(Body $body) { + function decode(Body $body) : mixed { $data = json_decode($body); if (!isset($data) && json_last_error()) { throw new UnexpectedValueException("Could not decode JSON: ". diff --git a/lib/API/ContentType/Handler/Stream.php b/lib/API/ContentType/Handler/Stream.php index 6a8535e..3ab587d 100644 --- a/lib/API/ContentType/Handler/Stream.php +++ b/lib/API/ContentType/Handler/Stream.php @@ -17,7 +17,7 @@ final class Stream implements Handler { * @inheritdoc * @param resource $data */ - function encode($data): Body { + function encode(mixed $data): Body { return new Body($data); } @@ -25,7 +25,7 @@ final class Stream implements Handler { * @inheritdoc * @return resource */ - function decode(Body $body) { + function decode(Body $body) : mixed { return $body->getResource(); } } diff --git a/lib/API/ContentType/Handler/Text.php b/lib/API/ContentType/Handler/Text.php index 25e6e80..1f13a61 100644 --- a/lib/API/ContentType/Handler/Text.php +++ b/lib/API/ContentType/Handler/Text.php @@ -17,21 +17,20 @@ final class Text implements Handler { /** * @inheritdoc - * @param string $data */ - function encode($data): Body { + function encode(mixed $data): Body { if (isset($data) && !is_scalar($data)) { throw new InvalidArgumentException( "Text encoding argument must be scalar, got ".typeof($data)); } - return (new Body)->append($data); + return (new Body)->append((string) $data); } /** * @inheritdoc * @return string */ - function decode(Body $body) { + function decode(Body $body) : string { return (string) $body; } } diff --git a/lib/API/Future.php b/lib/API/Future.php index e0d36b7..1ef0b1d 100644 --- a/lib/API/Future.php +++ b/lib/API/Future.php @@ -5,54 +5,52 @@ namespace seekat\API; interface Future { /** * @param callable $onCancel - * @return mixed Promisor providing a promise() method + * @return object Promisor providing a promise() method */ - function createContext(callable $onCancel = null); + function createContext(callable $onCancel = null) : object; /** - * @param object $context Promisor - * @return mixed promise + * @return object promise */ - function getPromise($context); + function getPromise(object $context) : object; + + function isPromise(object $promise) : bool; + + function cancelPromise(object $promise) : void; /** - * @param mixed $promise - * @return bool + * @return object promise */ - function isPromise($promise) : bool; + function handlePromise(object $promise, callable $onResult = null, callable $onError = null) : object; /** - * @param mixed $promise - * @return bool + * Create an immediately resolved promise */ - function cancelPromise($promise); + function resolve(mixed $value) : object; /** - * @param mixed $promise - * @param callable|null $onResult - * @param callable|null $onError - * @return mixed promise + * @param object $context Promisor returned by createContext */ - function handlePromise($promise, callable $onResult = null, callable $onError = null); + function resolver(object $context) : \Closure; /** - * @param object $context Promisor returned by createContext - * @param mixed $value - * @return void + * Create an immediately rejected promise */ - function resolve($context, $value); + function reject(mixed $reason) : object; /** * @param object $context Promisor returned by createContext - * @param mixed $reason - * @return void */ - function reject($context, $reason); + function rejecter(object $context) : \Closure; /** - * @param object $context Promisor returned by createContext * @param array $promises - * @return mixed promise + * @return object promise + */ + function all(array $promises) : object; + + /** + * */ - function all($context, array $promises); + function reducer() : \Closure; } diff --git a/lib/API/Future/Amp2.php b/lib/API/Future/Amp2.php new file mode 100644 index 0000000..51eb8c6 --- /dev/null +++ b/lib/API/Future/Amp2.php @@ -0,0 +1,51 @@ +cancellations[$context->promise()] = $onCancel; + } + return $context; + } + + function handlePromise(object $promise, callable $onResult = null, callable $onError = null) : Amp\Promise { + $promise->onResolve(function($error = null, $result = null) use($onResult, $onError) { + if ($error) { + if ($onError) { + $onError($error); + } + } else { + if ($onResult) { + $onResult($result); + } + } + }); + return $promise; + } + + function reject(mixed $reason) : object { + $this->createContext()->fail(\seekat\Exception\exception($reason)); + } + + function rejecter(object $context) : \Closure { + return function($reason) use($context) { + $context->fail(exception($reason)); + }; + } + + /** + * @param array $promises + */ + function all(array $promises) : Amp\Promise { + return Amp\Promise\all($promises); + } +} diff --git a/lib/API/Future/Common.php b/lib/API/Future/Common.php new file mode 100644 index 0000000..afbc62e --- /dev/null +++ b/lib/API/Future/Common.php @@ -0,0 +1,52 @@ +promiseType)) { + throw new UnexpectedValueException("Promise type must be set in Future implementation"); + } + $this->cancellations = new \WeakMap; + } + + function isPromise(object $promise): bool { + return $promise instanceof $this->promiseType; + } + + function getPromise(object $context) : object { + return $context->promise(); + } + + function cancelPromise(object $promise) : void { + if (isset($this->cancellations[$promise])) { + $this->cancellations[$promise](); + } + } + + function resolve(mixed $value) : object { + $context = $this->createContext(); + $promise = $context->promise(); + $context->resolve($value); + return $promise; + } + + function resolver(object $context) : \Closure { + return function($value) use($context) { + $context->resolve($value); + }; + } + + function reducer() : \Closure { + return function(array $promises) { + return $this->all($promises); + }; + } + +} diff --git a/lib/API/Future/React2.php b/lib/API/Future/React2.php new file mode 100644 index 0000000..6cd27a3 --- /dev/null +++ b/lib/API/Future/React2.php @@ -0,0 +1,42 @@ +cancellations[$context->promise()] = $context->promise()->cancel(...); + } + return $context; + } + + function handlePromise(object $promise, callable $onResult = null, callable $onError = null) : React\Promise\PromiseInterface { + return $promise->then($onResult, $onError); + } + + function reject(mixed $reason) : object { + $context = $this->createContext(); + $context->reject($reason); + return $context->promise(); + } + + function rejecter(object $context) : \Closure { + return function($reason) use($context) { + $context->reject($reason); + }; + } + + /** + * @param array $promises + * @return React\Promise\PromiseInterface + */ + function all(array $promises) : React\Promise\PromiseInterface { + return React\Promise\all($promises); + } +} diff --git a/lib/API/Future/functions.php b/lib/API/Future/functions.php index 3cddb22..d2a9232 100644 --- a/lib/API/Future/functions.php +++ b/lib/API/Future/functions.php @@ -2,173 +2,22 @@ namespace seekat\API\Future; -use Amp\Deferred as AmpDeferred; -use Amp\Promise as AmpPromise; -use React\Promise\Deferred as ReactDeferred; -use React\Promise\PromiseInterface as ReactPromise; use seekat\API\Future; -/** - * @param Future $future - * @param mixed $value - * @return mixed promise - */ -function resolve(Future $future, $value) { - $promisor = $future->createContext(); - $future->resolve($promisor, $value); - return $future->getPromise($promisor); +function react() : React2 { + return new React2; } -/** - * @param Future $future - * @param mixed $reason - * @return mixed promise - */ -function reject(Future $future, $reason) { - $promisor = $future->createContext(); - $future->reject($promisor, $reason); - return $future->getPromise($promisor); +function amp() : Amp2 { + return new Amp2; } -/** - * @param Future $future - * @param mixed $context Promisor - * @return \Closure - */ -function resolver(Future $future, $context) { - return function($value) use($future, $context) { - $future->resolve($context, $value); - }; -} - -/** - * @param Future $future - * @param mixed $context Promisor - * @return \Closure - */ -function rejecter(Future $future, $context) { - return function($reason) use($future, $context) { - $future->reject($context, $reason); - }; -} - -/** - * @param Future $future - * @param mixed $context Promisor - * @return \Closure - */ -function reducer(Future $future, $context) { - return function(array $promises) use($future, $context) { - return $future->all($context, $promises); - }; -} - -/** - * @return Future - */ -function react() { - return new class implements Future { - /** - * @param callable|null $onCancel - * @return ReactDeferred - */ - function createContext(callable $onCancel = null) { - return new ReactDeferred($onCancel); - } - - function getPromise($context) { - /* @var $context ReactDeferred */ - return $context->promise(); - } - - function isPromise($promise) : bool { - return $promise instanceof ReactPromise; - } - - function handlePromise($promise, callable $onResult = null, callable $onError = null) { - return $promise->then($onResult, $onError); - } - - function cancelPromise($promise) { - /* @var $promise \React\Promise\Promise */ - $promise->cancel(); - } - - function resolve($context, $value) { - /* @var $context ReactDeferred */ - $context->resolve($value); - } - - function reject($context, $reason) { - /* @var $context ReactDeferred */ - $context->reject($reason); - } - - function all($context, array $promises) { - return \React\Promise\all($promises); - } - }; -} - -/** - * @return Future - */ -function amp() { - return new class implements Future { - /** - * @return AmpDeferred - */ - function createContext(callable $onCancel = null) { - $context = new AmpDeferred(); - /** @noinspection PhpUndefinedFieldInspection */ - $context->promise()->cancel = function() use($onCancel, $context) { - $onCancel(); - }; - return $context; - } - - function getPromise($context) { - /* @var $context AmpDeferred */ - return $context->promise(); - } - - function isPromise($promise) : bool { - return $promise instanceof AmpPromise; - } - - function handlePromise($promise, callable $onResult = null, callable $onError = null) { - $promise->onResolve(function($error = null, $result = null) use($onResult, $onError) { - if ($error) { - if ($onError) { - $onError($error); - } - } else { - if ($onResult) { - $onResult($result); - } - } - }); - return $promise; - } - - function cancelPromise($promise) { - /** @var $promise AmpPromise */ - /** @noinspection PhpUndefinedFieldInspection */ - ($promise->cancel)(); - } - - function resolve($context, $value) { - /* @var $context AmpDeferred */ - $context->resolve($value); - } - - function reject($context, $reason) { - /* @var $context AmpDeferred */ - $context->fail(\seekat\Exception\exception($reason)); - } - - function all($context, array $promises) { - return \Amp\Promise\all($promises); - } - }; +function any() : Amp2|React2 { + if (interface_exists(\Amp\Promise::class, true)) { + return amp(); + } + if (interface_exists(\React\Promise\PromiseInterface::class, true)) { + return react(); + } + throw new \Exception("Cannot find any promise implementation"); } diff --git a/lib/API/Iterator.php b/lib/API/Iterator.php deleted file mode 100644 index b218747..0000000 --- a/lib/API/Iterator.php +++ /dev/null @@ -1,89 +0,0 @@ -api = $api; - $this->data = (array) $api->export()["data"]; - } - - /** - * Get the current key - * - * @return int|string - */ - function key() { - return $this->key; - } - - /** - * Get the current data entry - * - * @return API - */ - function current() { - return $this->cur; - } - - function next() { - if (list($key, $cur) = each($this->data)) { - $this->key = $key; - if ($this->api->$key->exists("url", $url)) { - $url = new Url($url); - $this->cur = $this->api->withUrl($url)->withData($cur); - } else { - $this->cur = $this->api->$key->withData($cur); - } - } else { - $this->key = null; - $this->cur = null; - } - } - - function valid() { - return isset($this->cur); - } - - function rewind() { - if (is_array($this->data)) { - reset($this->data); - $this->next(); - } - } -} diff --git a/lib/API/Links.php b/lib/API/Links.php index 20fbc6d..9f4f976 100644 --- a/lib/API/Links.php +++ b/lib/API/Links.php @@ -4,25 +4,18 @@ namespace seekat\API; use http\{Header, Params, QueryString, Url}; use seekat\Exception\UnexpectedValueException; -use Serializable; -final class Links implements Serializable { +final class Links { /** * Parsed "Link" relations - * @var Params - */ - private $params; - - /** - * Parsed "Link" relations - * @var array + * @var array */ private $relations = []; /** * Parse the hypermedia link header * - * @param Header $links The Link header + * @param ?Header $links The Link header * @throws UnexpectedValueException */ function __construct(Header $links = null) { @@ -30,33 +23,12 @@ final class Links implements Serializable { if (strcasecmp($links->name, "Link")) { throw new UnexpectedValueException("Expected 'Link' header, got: '{$links->name}'"); } - $this->unserialize($links->value); - } - } - - /** - * @return string - */ - function __toString() : string { - return $this->serialize(); - } - - /** - * @return string - */ - function serialize() { - return (string) $this->params; - } - - /** - * @param string $links - */ - function unserialize($links) { - $this->params = new Params($links, ",", ";", "=", - Params::PARSE_RFC5988 | Params::PARSE_ESCAPED); - if ($this->params->params) { - foreach ($this->params->params as $link => $param) { - $this->relations[$param["arguments"]["rel"]] = new Url($link); + $params = new Params($links->value, ",", ";", "=", + Params::PARSE_RFC5988 | Params::PARSE_ESCAPED); + if ($params->params) { + foreach ($params->params as $link => $param) { + $this->relations[$param["arguments"]["rel"]] = new Url($link); + } } } } @@ -64,7 +36,7 @@ final class Links implements Serializable { /** * Receive the link header's parsed relations * - * @return array + * @return array */ function getRelations() : array { return $this->relations; @@ -74,10 +46,8 @@ final class Links implements Serializable { * Get the URL of the link's "next" relation * * Returns the link's "last" relation if it exists and "next" is not set. - * - * @return Url */ - function getNext() { + function getNext() : ?Url { if (isset($this->relations["next"])) { return $this->relations["next"]; } @@ -91,10 +61,8 @@ final class Links implements Serializable { * Get the URL of the link's "prev" relation * * Returns the link's "first" relation if it exists and "prev" is not set. - * - * @return Url */ - function getPrev() { + function getPrev() : ?Url { if (isset($this->relations["prev"])) { return $this->relations["prev"]; } @@ -106,10 +74,8 @@ final class Links implements Serializable { /** * Get the URL of the link's "last" relation - * - * @return Url */ - function getLast() { + function getLast() : ?Url { if (isset($this->relations["last"])) { return $this->relations["last"]; } @@ -118,10 +84,8 @@ final class Links implements Serializable { /** * Get the URL of the link's "first" relation - * - * @return Url */ - function getFirst() { + function getFirst() : ?Url { if (isset($this->relations["first"])) { return $this->relations["first"]; } @@ -134,7 +98,7 @@ final class Links implements Serializable { * @param string $which The relation of which to extract the page * @return int The current page sequence */ - function getPage($which) { + function getPage($which) : int { if (($link = $this->{"get$which"}())) { $url = new Url($link, null, 0); $qry = new QueryString($url->query); diff --git a/lib/API/Links/functions.php b/lib/API/Links/functions.php index 8b3d4e5..f379125 100644 --- a/lib/API/Links/functions.php +++ b/lib/API/Links/functions.php @@ -11,12 +11,11 @@ use seekat\API\Future; * * @return mixed promise */ -function first(API $api, Cache\Service $cache = null) { - $links = $api->getLinks(); - if ($links && ($first = $links->getFirst())) { - return $api->withUrl($first)->get(null, null, $cache); +function first(API $api) { + if (($first = $api->getLinks()?->getFirst())) { + return $api->withUrl($first)->get(); } - return Future\resolve($api->getFuture(), null); + return $api->getFuture()->resolve(null); } /** @@ -24,12 +23,11 @@ function first(API $api, Cache\Service $cache = null) { * * @return mixed promise */ -function prev(API $api, Cache\Service $cache = null) { - $links = $api->getLinks(); - if ($links && ($prev = $links->getPrev())) { - return $api->withUrl($prev)->get(null, null, $cache); +function prev(API $api) { + if (($prev = $api->getLinks()?->getPrev())) { + return $api->withUrl($prev)->get(); } - return Future\resolve($api->getFuture(), null); + return $api->getFuture()->resolve(null); } /** @@ -37,12 +35,11 @@ function prev(API $api, Cache\Service $cache = null) { * * @return mixed promise */ -function next(API $api, Cache\Service $cache = null) { - $links = $api->getLinks(); - if ($links && ($next = $links->getNext())) { - return $api->withUrl($next)->get(null, null, $cache); +function next(API $api) { + if (($next = $api->getLinks()?->getNext())) { + return $api->withUrl($next)->get(); } - return Future\resolve($api->getFuture(), null); + return $api->getFuture()->resolve(null); } /** @@ -55,6 +52,6 @@ function last(API $api, Cache\Service $cache = null) { if ($links && ($last = $links->getLast())) { return $api->withUrl($last)->get(null, null, $cache); } - return Future\resolve($api->getFuture(), null); + return $api->getFuture()->resolve(null); } diff --git a/lib/Exception/functions.php b/lib/Exception/functions.php index 0c7171a..1930ad0 100644 --- a/lib/Exception/functions.php +++ b/lib/Exception/functions.php @@ -2,12 +2,14 @@ namespace seekat\Exception; +use Throwable; + /** - * @param string|\Throwable $message - * @return \Throwable + * @param string|Throwable $message + * @return Throwable */ -function exception(&$message) : \Throwable { - if ($message instanceof \Throwable){ +function exception(&$message) : Throwable { + if ($message instanceof Throwable){ $exception = $message; $message = $exception->getMessage(); } else { @@ -18,11 +20,10 @@ function exception(&$message) : \Throwable { /** * Canonical error message from a string or Exception - * @param string|\Throwable $error - * @return string + * @param string|Throwable $error */ function message(&$error) : ?string { - if ($error instanceof \Throwable) { + if ($error instanceof Throwable) { $message = $error->getMessage(); } else { $message = $error; diff --git a/lib/functions.php b/lib/functions.php index 9130fd4..8a1615b 100644 --- a/lib/functions.php +++ b/lib/functions.php @@ -11,12 +11,12 @@ namespace { namespace seekat { /** - * Generate a human readable representation of a variable + * Generate a human-readable representation of a variable * @param mixed $arg * @param bool $export whether to var_export the $arg * @return string */ - function typeof($arg, $export = false) { + function typeof($arg, bool $export = false) : string { $type = is_object($arg) ? "instance of ".get_class($arg) : gettype($arg); diff --git a/tests/CacheTest.php b/tests/CacheTest.php index ddf7f54..62632b4 100644 --- a/tests/CacheTest.php +++ b/tests/CacheTest.php @@ -5,30 +5,22 @@ class CacheTest extends BaseTest use ConsumePromise; use AssertSuccess; - /** - * @var seekat\API\Call\Cache\Service - */ - private $cache; - - function setUp() : void { - $this->cache = new seekat\API\Call\Cache\Service\Hollow; - } - /** * @group testdox * @dataProvider provideAPI */ function testCachesSuccessiveCalls($api) { - $m6w6 = $this->assertSuccess($api->users->m6w6, null, null, $this->cache); - $data = $this->cache->getStorage(); - $m6w6_ = $this->assertSuccess($api->users->m6w6, null, null, $this->cache); + $api->getCache()->clear(); + $m6w6 = $this->assertSuccess($api->users->m6w6); + $data = $api->getCache()->getStorage(); + $m6w6_ = $this->assertSuccess($api->users->m6w6); $this->assertEquals("m6w6", $m6w6->login); $this->assertEquals("m6w6", $m6w6_->login); $this->assertIsArray($data); $this->assertCount(1, $data); - $this->assertEquals($data, $this->cache->getStorage()); + $this->assertEquals($data, $api->getCache()->getStorage()); } /** @@ -36,6 +28,25 @@ class CacheTest extends BaseTest * @dataProvider provideAPI */ function testRefreshesStaleCacheEntries($api) { - $this->markTestIncomplete("TODO"); + $api->getCache()->clear(); + $m6w6 = $this->assertSuccess($api->users->m6w6); + + $data = $api->getCache()->getStorage(); + /* @var \http\Header $resp */ + $resp = current($data); + $resp->setHeader("X-Cache-Time", null); + $resp->setHeader("Cache-Control", null); + $resp->setHeader("Expires", 0); + + $m6w6_ = $this->assertSuccess($api->users->m6w6); + + $this->assertEquals("m6w6", $m6w6->login); + $this->assertEquals("m6w6", $m6w6_->login); + + $this->assertIsArray($data); + $this->assertCount(1, $data); + $this->assertEquals($data, $api->getCache()->getStorage()); + + $this->assertIsNumeric($resp->getHeader("X-Cache-Time")); } } diff --git a/tests/ContentTypeTest.php b/tests/ContentTypeTest.php index 3945245..df6e8fa 100644 --- a/tests/ContentTypeTest.php +++ b/tests/ContentTypeTest.php @@ -48,7 +48,7 @@ class ContentTypeTest extends BaseTest function encode($data): Body { return new Body; } - function decode(Body $body) { + function decode(Body $body) : string { return (string) $body; } }); diff --git a/tests/bootstrap.php b/tests/bootstrap.php index e7d7afb..4b04a94 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -44,15 +44,12 @@ function logger() : \Monolog\Logger { class BaseTest extends \PHPUnit\Framework\TestCase { function provideAPI() { - $auth = \seekat\API\auth("token", getenv("GITHUB_TOKEN")); $headers = headers(); - $url = null; - $client = null; $logger = logger(); return [ - "using ReactPHP" => [new \seekat\API(\seekat\API\Future\react(), $headers, $url, $client, $logger)], - "using AmPHP" => [new \seekat\API(\seekat\API\Future\amp(), $headers, $url, $client, $logger)], + "using ReactPHP" => [new \seekat\API(\seekat\API\Future\react(), $headers, logger: $logger)], + "using AmPHP" => [new \seekat\API(\seekat\API\Future\amp(), $headers, logger: $logger)], ]; } } -- 2.30.2