From 3050dc248aad76315bba483f09037ec597c33137 Mon Sep 17 00:00:00 2001 From: Dmitrii Metelkin Date: Tue, 3 Sep 2024 13:24:03 +1000 Subject: [PATCH 1/6] issue #223: remove guzzle --- guzzle/GuzzleHttp/Client.php | 414 --------- guzzle/GuzzleHttp/ClientInterface.php | 84 -- guzzle/GuzzleHttp/Cookie/CookieJar.php | 314 ------- .../GuzzleHttp/Cookie/CookieJarInterface.php | 84 -- guzzle/GuzzleHttp/Cookie/FileCookieJar.php | 90 -- guzzle/GuzzleHttp/Cookie/SessionCookieJar.php | 71 -- guzzle/GuzzleHttp/Cookie/SetCookie.php | 404 --------- .../Exception/BadResponseException.php | 27 - .../GuzzleHttp/Exception/ClientException.php | 7 - .../GuzzleHttp/Exception/ConnectException.php | 37 - .../GuzzleHttp/Exception/GuzzleException.php | 4 - .../GuzzleHttp/Exception/RequestException.php | 217 ----- guzzle/GuzzleHttp/Exception/SeekException.php | 27 - .../GuzzleHttp/Exception/ServerException.php | 7 - .../Exception/TooManyRedirectsException.php | 4 - .../Exception/TransferException.php | 4 - guzzle/GuzzleHttp/Handler/CurlFactory.php | 559 ------------ .../Handler/CurlFactoryInterface.php | 27 - guzzle/GuzzleHttp/Handler/CurlHandler.php | 45 - .../GuzzleHttp/Handler/CurlMultiHandler.php | 197 ----- guzzle/GuzzleHttp/Handler/EasyHandle.php | 92 -- guzzle/GuzzleHttp/Handler/MockHandler.php | 189 ---- guzzle/GuzzleHttp/Handler/Proxy.php | 55 -- guzzle/GuzzleHttp/Handler/StreamHandler.php | 533 ----------- guzzle/GuzzleHttp/HandlerStack.php | 273 ------ guzzle/GuzzleHttp/MessageFormatter.php | 182 ---- guzzle/GuzzleHttp/Middleware.php | 254 ------ guzzle/GuzzleHttp/Pool.php | 123 --- guzzle/GuzzleHttp/PrepareBodyMiddleware.php | 106 --- .../GuzzleHttp/Promise/AggregateException.php | 16 - .../Promise/CancellationException.php | 9 - guzzle/GuzzleHttp/Promise/Coroutine.php | 151 ---- guzzle/GuzzleHttp/Promise/EachPromise.php | 229 ----- .../GuzzleHttp/Promise/FulfilledPromise.php | 82 -- guzzle/GuzzleHttp/Promise/Promise.php | 280 ------ .../GuzzleHttp/Promise/PromiseInterface.php | 93 -- .../GuzzleHttp/Promise/PromisorInterface.php | 15 - guzzle/GuzzleHttp/Promise/RejectedPromise.php | 87 -- .../GuzzleHttp/Promise/RejectionException.php | 47 - guzzle/GuzzleHttp/Promise/TaskQueue.php | 66 -- .../GuzzleHttp/Promise/TaskQueueInterface.php | 25 - guzzle/GuzzleHttp/Promise/functions.php | 457 ---------- .../GuzzleHttp/Promise/functions_include.php | 6 - guzzle/GuzzleHttp/Psr7/AppendStream.php | 233 ----- guzzle/GuzzleHttp/Psr7/BufferStream.php | 137 --- guzzle/GuzzleHttp/Psr7/CachingStream.php | 138 --- guzzle/GuzzleHttp/Psr7/DroppingStream.php | 42 - guzzle/GuzzleHttp/Psr7/FnStream.php | 149 ---- guzzle/GuzzleHttp/Psr7/InflateStream.php | 52 -- guzzle/GuzzleHttp/Psr7/LazyOpenStream.php | 39 - guzzle/GuzzleHttp/Psr7/LimitStream.php | 155 ---- guzzle/GuzzleHttp/Psr7/MessageTrait.php | 183 ---- guzzle/GuzzleHttp/Psr7/MultipartStream.php | 153 ---- guzzle/GuzzleHttp/Psr7/NoSeekStream.php | 22 - guzzle/GuzzleHttp/Psr7/PumpStream.php | 165 ---- guzzle/GuzzleHttp/Psr7/Request.php | 142 --- guzzle/GuzzleHttp/Psr7/Response.php | 132 --- guzzle/GuzzleHttp/Psr7/ServerRequest.php | 358 -------- guzzle/GuzzleHttp/Psr7/Stream.php | 257 ------ .../GuzzleHttp/Psr7/StreamDecoratorTrait.php | 149 ---- guzzle/GuzzleHttp/Psr7/StreamWrapper.php | 121 --- guzzle/GuzzleHttp/Psr7/UploadedFile.php | 316 ------- guzzle/GuzzleHttp/Psr7/Uri.php | 702 --------------- guzzle/GuzzleHttp/Psr7/UriNormalizer.php | 216 ----- guzzle/GuzzleHttp/Psr7/UriResolver.php | 219 ----- guzzle/GuzzleHttp/Psr7/functions.php | 828 ------------------ guzzle/GuzzleHttp/Psr7/functions_include.php | 6 - guzzle/GuzzleHttp/RedirectMiddleware.php | 237 ----- guzzle/GuzzleHttp/RequestOptions.php | 255 ------ guzzle/GuzzleHttp/RetryMiddleware.php | 112 --- guzzle/GuzzleHttp/TransferStats.php | 126 --- guzzle/GuzzleHttp/UriTemplate.php | 241 ----- guzzle/GuzzleHttp/functions.php | 331 ------- guzzle/GuzzleHttp/functions_include.php | 6 - guzzle/LICENSE | 19 - guzzle/Psr/Http/Message/MessageInterface.php | 187 ---- guzzle/Psr/Http/Message/RequestInterface.php | 129 --- guzzle/Psr/Http/Message/ResponseInterface.php | 68 -- .../Http/Message/ServerRequestInterface.php | 261 ------ guzzle/Psr/Http/Message/StreamInterface.php | 158 ---- .../Http/Message/UploadedFileInterface.php | 123 --- guzzle/Psr/Http/Message/UriInterface.php | 323 ------- guzzle/README.md | 89 -- guzzle/autoloader.php | 95 -- guzzle/readme_moodle.txt | 22 - tests/steps_form_test.php | 1 + thirdpartylibs.xml | 10 - 87 files changed, 1 insertion(+), 13699 deletions(-) delete mode 100644 guzzle/GuzzleHttp/Client.php delete mode 100644 guzzle/GuzzleHttp/ClientInterface.php delete mode 100644 guzzle/GuzzleHttp/Cookie/CookieJar.php delete mode 100644 guzzle/GuzzleHttp/Cookie/CookieJarInterface.php delete mode 100644 guzzle/GuzzleHttp/Cookie/FileCookieJar.php delete mode 100644 guzzle/GuzzleHttp/Cookie/SessionCookieJar.php delete mode 100644 guzzle/GuzzleHttp/Cookie/SetCookie.php delete mode 100644 guzzle/GuzzleHttp/Exception/BadResponseException.php delete mode 100644 guzzle/GuzzleHttp/Exception/ClientException.php delete mode 100644 guzzle/GuzzleHttp/Exception/ConnectException.php delete mode 100644 guzzle/GuzzleHttp/Exception/GuzzleException.php delete mode 100644 guzzle/GuzzleHttp/Exception/RequestException.php delete mode 100644 guzzle/GuzzleHttp/Exception/SeekException.php delete mode 100644 guzzle/GuzzleHttp/Exception/ServerException.php delete mode 100644 guzzle/GuzzleHttp/Exception/TooManyRedirectsException.php delete mode 100644 guzzle/GuzzleHttp/Exception/TransferException.php delete mode 100644 guzzle/GuzzleHttp/Handler/CurlFactory.php delete mode 100644 guzzle/GuzzleHttp/Handler/CurlFactoryInterface.php delete mode 100644 guzzle/GuzzleHttp/Handler/CurlHandler.php delete mode 100644 guzzle/GuzzleHttp/Handler/CurlMultiHandler.php delete mode 100644 guzzle/GuzzleHttp/Handler/EasyHandle.php delete mode 100644 guzzle/GuzzleHttp/Handler/MockHandler.php delete mode 100644 guzzle/GuzzleHttp/Handler/Proxy.php delete mode 100644 guzzle/GuzzleHttp/Handler/StreamHandler.php delete mode 100644 guzzle/GuzzleHttp/HandlerStack.php delete mode 100644 guzzle/GuzzleHttp/MessageFormatter.php delete mode 100644 guzzle/GuzzleHttp/Middleware.php delete mode 100644 guzzle/GuzzleHttp/Pool.php delete mode 100644 guzzle/GuzzleHttp/PrepareBodyMiddleware.php delete mode 100644 guzzle/GuzzleHttp/Promise/AggregateException.php delete mode 100644 guzzle/GuzzleHttp/Promise/CancellationException.php delete mode 100644 guzzle/GuzzleHttp/Promise/Coroutine.php delete mode 100644 guzzle/GuzzleHttp/Promise/EachPromise.php delete mode 100644 guzzle/GuzzleHttp/Promise/FulfilledPromise.php delete mode 100644 guzzle/GuzzleHttp/Promise/Promise.php delete mode 100644 guzzle/GuzzleHttp/Promise/PromiseInterface.php delete mode 100644 guzzle/GuzzleHttp/Promise/PromisorInterface.php delete mode 100644 guzzle/GuzzleHttp/Promise/RejectedPromise.php delete mode 100644 guzzle/GuzzleHttp/Promise/RejectionException.php delete mode 100644 guzzle/GuzzleHttp/Promise/TaskQueue.php delete mode 100644 guzzle/GuzzleHttp/Promise/TaskQueueInterface.php delete mode 100644 guzzle/GuzzleHttp/Promise/functions.php delete mode 100644 guzzle/GuzzleHttp/Promise/functions_include.php delete mode 100644 guzzle/GuzzleHttp/Psr7/AppendStream.php delete mode 100644 guzzle/GuzzleHttp/Psr7/BufferStream.php delete mode 100644 guzzle/GuzzleHttp/Psr7/CachingStream.php delete mode 100644 guzzle/GuzzleHttp/Psr7/DroppingStream.php delete mode 100644 guzzle/GuzzleHttp/Psr7/FnStream.php delete mode 100644 guzzle/GuzzleHttp/Psr7/InflateStream.php delete mode 100644 guzzle/GuzzleHttp/Psr7/LazyOpenStream.php delete mode 100644 guzzle/GuzzleHttp/Psr7/LimitStream.php delete mode 100644 guzzle/GuzzleHttp/Psr7/MessageTrait.php delete mode 100644 guzzle/GuzzleHttp/Psr7/MultipartStream.php delete mode 100644 guzzle/GuzzleHttp/Psr7/NoSeekStream.php delete mode 100644 guzzle/GuzzleHttp/Psr7/PumpStream.php delete mode 100644 guzzle/GuzzleHttp/Psr7/Request.php delete mode 100644 guzzle/GuzzleHttp/Psr7/Response.php delete mode 100644 guzzle/GuzzleHttp/Psr7/ServerRequest.php delete mode 100644 guzzle/GuzzleHttp/Psr7/Stream.php delete mode 100644 guzzle/GuzzleHttp/Psr7/StreamDecoratorTrait.php delete mode 100644 guzzle/GuzzleHttp/Psr7/StreamWrapper.php delete mode 100644 guzzle/GuzzleHttp/Psr7/UploadedFile.php delete mode 100644 guzzle/GuzzleHttp/Psr7/Uri.php delete mode 100644 guzzle/GuzzleHttp/Psr7/UriNormalizer.php delete mode 100644 guzzle/GuzzleHttp/Psr7/UriResolver.php delete mode 100644 guzzle/GuzzleHttp/Psr7/functions.php delete mode 100644 guzzle/GuzzleHttp/Psr7/functions_include.php delete mode 100644 guzzle/GuzzleHttp/RedirectMiddleware.php delete mode 100644 guzzle/GuzzleHttp/RequestOptions.php delete mode 100644 guzzle/GuzzleHttp/RetryMiddleware.php delete mode 100644 guzzle/GuzzleHttp/TransferStats.php delete mode 100644 guzzle/GuzzleHttp/UriTemplate.php delete mode 100644 guzzle/GuzzleHttp/functions.php delete mode 100644 guzzle/GuzzleHttp/functions_include.php delete mode 100644 guzzle/LICENSE delete mode 100644 guzzle/Psr/Http/Message/MessageInterface.php delete mode 100644 guzzle/Psr/Http/Message/RequestInterface.php delete mode 100644 guzzle/Psr/Http/Message/ResponseInterface.php delete mode 100644 guzzle/Psr/Http/Message/ServerRequestInterface.php delete mode 100644 guzzle/Psr/Http/Message/StreamInterface.php delete mode 100644 guzzle/Psr/Http/Message/UploadedFileInterface.php delete mode 100644 guzzle/Psr/Http/Message/UriInterface.php delete mode 100644 guzzle/README.md delete mode 100644 guzzle/autoloader.php delete mode 100755 guzzle/readme_moodle.txt delete mode 100644 thirdpartylibs.xml diff --git a/guzzle/GuzzleHttp/Client.php b/guzzle/GuzzleHttp/Client.php deleted file mode 100644 index de4df8a..0000000 --- a/guzzle/GuzzleHttp/Client.php +++ /dev/null @@ -1,414 +0,0 @@ - 'http://www.foo.com/1.0/', - * 'timeout' => 0, - * 'allow_redirects' => false, - * 'proxy' => '192.168.16.1:10' - * ]); - * - * Client configuration settings include the following options: - * - * - handler: (callable) Function that transfers HTTP requests over the - * wire. The function is called with a Psr7\Http\Message\RequestInterface - * and array of transfer options, and must return a - * GuzzleHttp\Promise\PromiseInterface that is fulfilled with a - * Psr7\Http\Message\ResponseInterface on success. "handler" is a - * constructor only option that cannot be overridden in per/request - * options. If no handler is provided, a default handler will be created - * that enables all of the request options below by attaching all of the - * default middleware to the handler. - * - base_uri: (string|UriInterface) Base URI of the client that is merged - * into relative URIs. Can be a string or instance of UriInterface. - * - **: any request option - * - * @param array $config Client configuration settings. - * - * @see \GuzzleHttp\RequestOptions for a list of available request options. - */ - public function __construct(array $config = []) - { - if (!isset($config['handler'])) { - $config['handler'] = HandlerStack::create(); - } elseif (!is_callable($config['handler'])) { - throw new \InvalidArgumentException('handler must be a callable'); - } - - // Convert the base_uri to a UriInterface - if (isset($config['base_uri'])) { - $config['base_uri'] = Psr7\uri_for($config['base_uri']); - } - - $this->configureDefaults($config); - } - - public function __call($method, $args) - { - if (count($args) < 1) { - throw new \InvalidArgumentException('Magic request methods require a URI and optional options array'); - } - - $uri = $args[0]; - $opts = isset($args[1]) ? $args[1] : []; - - return substr($method, -5) === 'Async' - ? $this->requestAsync(substr($method, 0, -5), $uri, $opts) - : $this->request($method, $uri, $opts); - } - - public function sendAsync(RequestInterface $request, array $options = []) - { - // Merge the base URI into the request URI if needed. - $options = $this->prepareDefaults($options); - - return $this->transfer( - $request->withUri($this->buildUri($request->getUri(), $options), $request->hasHeader('Host')), - $options - ); - } - - public function send(RequestInterface $request, array $options = []) - { - $options[RequestOptions::SYNCHRONOUS] = true; - return $this->sendAsync($request, $options)->wait(); - } - - public function requestAsync($method, $uri = '', array $options = []) - { - $options = $this->prepareDefaults($options); - // Remove request modifying parameter because it can be done up-front. - $headers = isset($options['headers']) ? $options['headers'] : []; - $body = isset($options['body']) ? $options['body'] : null; - $version = isset($options['version']) ? $options['version'] : '1.1'; - // Merge the URI into the base URI. - $uri = $this->buildUri($uri, $options); - if (is_array($body)) { - $this->invalidBody(); - } - $request = new Psr7\Request($method, $uri, $headers, $body, $version); - // Remove the option so that they are not doubly-applied. - unset($options['headers'], $options['body'], $options['version']); - - return $this->transfer($request, $options); - } - - public function request($method, $uri = '', array $options = []) - { - $options[RequestOptions::SYNCHRONOUS] = true; - return $this->requestAsync($method, $uri, $options)->wait(); - } - - public function getConfig($option = null) - { - return $option === null - ? $this->config - : (isset($this->config[$option]) ? $this->config[$option] : null); - } - - private function buildUri($uri, array $config) - { - // for BC we accept null which would otherwise fail in uri_for - $uri = Psr7\uri_for($uri === null ? '' : $uri); - - if (isset($config['base_uri'])) { - $uri = Psr7\UriResolver::resolve(Psr7\uri_for($config['base_uri']), $uri); - } - - return $uri->getScheme() === '' && $uri->getHost() !== '' ? $uri->withScheme('http') : $uri; - } - - /** - * Configures the default options for a client. - * - * @param array $config - */ - private function configureDefaults(array $config) - { - $defaults = [ - 'allow_redirects' => RedirectMiddleware::$defaultSettings, - 'http_errors' => true, - 'decode_content' => true, - 'verify' => true, - 'cookies' => false - ]; - - // Use the standard Linux HTTP_PROXY and HTTPS_PROXY if set. - - // We can only trust the HTTP_PROXY environment variable in a CLI - // process due to the fact that PHP has no reliable mechanism to - // get environment variables that start with "HTTP_". - if (php_sapi_name() == 'cli' && getenv('HTTP_PROXY')) { - $defaults['proxy']['http'] = getenv('HTTP_PROXY'); - } - - if ($proxy = getenv('HTTPS_PROXY')) { - $defaults['proxy']['https'] = $proxy; - } - - if ($noProxy = getenv('NO_PROXY')) { - $cleanedNoProxy = str_replace(' ', '', $noProxy); - $defaults['proxy']['no'] = explode(',', $cleanedNoProxy); - } - - $this->config = $config + $defaults; - - if (!empty($config['cookies']) && $config['cookies'] === true) { - $this->config['cookies'] = new CookieJar(); - } - - // Add the default user-agent header. - if (!isset($this->config['headers'])) { - $this->config['headers'] = ['User-Agent' => default_user_agent()]; - } else { - // Add the User-Agent header if one was not already set. - foreach (array_keys($this->config['headers']) as $name) { - if (strtolower($name) === 'user-agent') { - return; - } - } - $this->config['headers']['User-Agent'] = default_user_agent(); - } - } - - /** - * Merges default options into the array. - * - * @param array $options Options to modify by reference - * - * @return array - */ - private function prepareDefaults($options) - { - $defaults = $this->config; - - if (!empty($defaults['headers'])) { - // Default headers are only added if they are not present. - $defaults['_conditional'] = $defaults['headers']; - unset($defaults['headers']); - } - - // Special handling for headers is required as they are added as - // conditional headers and as headers passed to a request ctor. - if (array_key_exists('headers', $options)) { - // Allows default headers to be unset. - if ($options['headers'] === null) { - $defaults['_conditional'] = null; - unset($options['headers']); - } elseif (!is_array($options['headers'])) { - throw new \InvalidArgumentException('headers must be an array'); - } - } - - // Shallow merge defaults underneath options. - $result = $options + $defaults; - - // Remove null values. - foreach ($result as $k => $v) { - if ($v === null) { - unset($result[$k]); - } - } - - return $result; - } - - /** - * Transfers the given request and applies request options. - * - * The URI of the request is not modified and the request options are used - * as-is without merging in default options. - * - * @param RequestInterface $request - * @param array $options - * - * @return Promise\PromiseInterface - */ - private function transfer(RequestInterface $request, array $options) - { - // save_to -> sink - if (isset($options['save_to'])) { - $options['sink'] = $options['save_to']; - unset($options['save_to']); - } - - // exceptions -> http_errors - if (isset($options['exceptions'])) { - $options['http_errors'] = $options['exceptions']; - unset($options['exceptions']); - } - - $request = $this->applyOptions($request, $options); - $handler = $options['handler']; - - try { - return Promise\promise_for($handler($request, $options)); - } catch (\Exception $e) { - return Promise\rejection_for($e); - } - } - - /** - * Applies the array of request options to a request. - * - * @param RequestInterface $request - * @param array $options - * - * @return RequestInterface - */ - private function applyOptions(RequestInterface $request, array &$options) - { - $modify = []; - - if (isset($options['form_params'])) { - if (isset($options['multipart'])) { - throw new \InvalidArgumentException('You cannot use ' - . 'form_params and multipart at the same time. Use the ' - . 'form_params option if you want to send application/' - . 'x-www-form-urlencoded requests, and the multipart ' - . 'option to send multipart/form-data requests.'); - } - $options['body'] = http_build_query($options['form_params'], '', '&'); - unset($options['form_params']); - $options['_conditional']['Content-Type'] = 'application/x-www-form-urlencoded'; - } - - if (isset($options['multipart'])) { - $options['body'] = new Psr7\MultipartStream($options['multipart']); - unset($options['multipart']); - } - - if (isset($options['json'])) { - $options['body'] = \GuzzleHttp\json_encode($options['json']); - unset($options['json']); - $options['_conditional']['Content-Type'] = 'application/json'; - } - - if (!empty($options['decode_content']) - && $options['decode_content'] !== true - ) { - $modify['set_headers']['Accept-Encoding'] = $options['decode_content']; - } - - if (isset($options['headers'])) { - if (isset($modify['set_headers'])) { - $modify['set_headers'] = $options['headers'] + $modify['set_headers']; - } else { - $modify['set_headers'] = $options['headers']; - } - unset($options['headers']); - } - - if (isset($options['body'])) { - if (is_array($options['body'])) { - $this->invalidBody(); - } - $modify['body'] = Psr7\stream_for($options['body']); - unset($options['body']); - } - - if (!empty($options['auth']) && is_array($options['auth'])) { - $value = $options['auth']; - $type = isset($value[2]) ? strtolower($value[2]) : 'basic'; - switch ($type) { - case 'basic': - $modify['set_headers']['Authorization'] = 'Basic ' - . base64_encode("$value[0]:$value[1]"); - break; - case 'digest': - // @todo: Do not rely on curl - $options['curl'][CURLOPT_HTTPAUTH] = CURLAUTH_DIGEST; - $options['curl'][CURLOPT_USERPWD] = "$value[0]:$value[1]"; - break; - case 'ntlm': - $options['curl'][CURLOPT_HTTPAUTH] = CURLAUTH_NTLM; - $options['curl'][CURLOPT_USERPWD] = "$value[0]:$value[1]"; - break; - } - } - - if (isset($options['query'])) { - $value = $options['query']; - if (is_array($value)) { - $value = http_build_query($value, null, '&', PHP_QUERY_RFC3986); - } - if (!is_string($value)) { - throw new \InvalidArgumentException('query must be a string or array'); - } - $modify['query'] = $value; - unset($options['query']); - } - - // Ensure that sink is not an invalid value. - if (isset($options['sink'])) { - // TODO: Add more sink validation? - if (is_bool($options['sink'])) { - throw new \InvalidArgumentException('sink must not be a boolean'); - } - } - - $request = Psr7\modify_request($request, $modify); - if ($request->getBody() instanceof Psr7\MultipartStream) { - // Use a multipart/form-data POST if a Content-Type is not set. - $options['_conditional']['Content-Type'] = 'multipart/form-data; boundary=' - . $request->getBody()->getBoundary(); - } - - // Merge in conditional headers if they are not present. - if (isset($options['_conditional'])) { - // Build up the changes so it's in a single clone of the message. - $modify = []; - foreach ($options['_conditional'] as $k => $v) { - if (!$request->hasHeader($k)) { - $modify['set_headers'][$k] = $v; - } - } - $request = Psr7\modify_request($request, $modify); - // Don't pass this internal value along to middleware/handlers. - unset($options['_conditional']); - } - - return $request; - } - - private function invalidBody() - { - throw new \InvalidArgumentException('Passing in the "body" request ' - . 'option as an array to send a POST request has been deprecated. ' - . 'Please use the "form_params" request option to send a ' - . 'application/x-www-form-urlencoded request, or the "multipart" ' - . 'request option to send a multipart/form-data request.'); - } -} diff --git a/guzzle/GuzzleHttp/ClientInterface.php b/guzzle/GuzzleHttp/ClientInterface.php deleted file mode 100644 index 5a67b66..0000000 --- a/guzzle/GuzzleHttp/ClientInterface.php +++ /dev/null @@ -1,84 +0,0 @@ -strictMode = $strictMode; - - foreach ($cookieArray as $cookie) { - if (!($cookie instanceof SetCookie)) { - $cookie = new SetCookie($cookie); - } - $this->setCookie($cookie); - } - } - - /** - * Create a new Cookie jar from an associative array and domain. - * - * @param array $cookies Cookies to create the jar from - * @param string $domain Domain to set the cookies to - * - * @return self - */ - public static function fromArray(array $cookies, $domain) - { - $cookieJar = new self(); - foreach ($cookies as $name => $value) { - $cookieJar->setCookie(new SetCookie([ - 'Domain' => $domain, - 'Name' => $name, - 'Value' => $value, - 'Discard' => true - ])); - } - - return $cookieJar; - } - - /** - * @deprecated - */ - public static function getCookieValue($value) - { - return $value; - } - - /** - * Evaluate if this cookie should be persisted to storage - * that survives between requests. - * - * @param SetCookie $cookie Being evaluated. - * @param bool $allowSessionCookies If we should persist session cookies - * @return bool - */ - public static function shouldPersist( - SetCookie $cookie, - $allowSessionCookies = false - ) { - if ($cookie->getExpires() || $allowSessionCookies) { - if (!$cookie->getDiscard()) { - return true; - } - } - - return false; - } - - /** - * Finds and returns the cookie based on the name - * - * @param string $name cookie name to search for - * @return SetCookie|null cookie that was found or null if not found - */ - public function getCookieByName($name) - { - // don't allow a null name - if($name === null) { - return null; - } - foreach($this->cookies as $cookie) { - if($cookie->getName() !== null && strcasecmp($cookie->getName(), $name) === 0) { - return $cookie; - } - } - } - - public function toArray() - { - return array_map(function (SetCookie $cookie) { - return $cookie->toArray(); - }, $this->getIterator()->getArrayCopy()); - } - - public function clear($domain = null, $path = null, $name = null) - { - if (!$domain) { - $this->cookies = []; - return; - } elseif (!$path) { - $this->cookies = array_filter( - $this->cookies, - function (SetCookie $cookie) use ($path, $domain) { - return !$cookie->matchesDomain($domain); - } - ); - } elseif (!$name) { - $this->cookies = array_filter( - $this->cookies, - function (SetCookie $cookie) use ($path, $domain) { - return !($cookie->matchesPath($path) && - $cookie->matchesDomain($domain)); - } - ); - } else { - $this->cookies = array_filter( - $this->cookies, - function (SetCookie $cookie) use ($path, $domain, $name) { - return !($cookie->getName() == $name && - $cookie->matchesPath($path) && - $cookie->matchesDomain($domain)); - } - ); - } - } - - public function clearSessionCookies() - { - $this->cookies = array_filter( - $this->cookies, - function (SetCookie $cookie) { - return !$cookie->getDiscard() && $cookie->getExpires(); - } - ); - } - - public function setCookie(SetCookie $cookie) - { - // If the name string is empty (but not 0), ignore the set-cookie - // string entirely. - $name = $cookie->getName(); - if (!$name && $name !== '0') { - return false; - } - - // Only allow cookies with set and valid domain, name, value - $result = $cookie->validate(); - if ($result !== true) { - if ($this->strictMode) { - throw new \RuntimeException('Invalid cookie: ' . $result); - } else { - $this->removeCookieIfEmpty($cookie); - return false; - } - } - - // Resolve conflicts with previously set cookies - foreach ($this->cookies as $i => $c) { - - // Two cookies are identical, when their path, and domain are - // identical. - if ($c->getPath() != $cookie->getPath() || - $c->getDomain() != $cookie->getDomain() || - $c->getName() != $cookie->getName() - ) { - continue; - } - - // The previously set cookie is a discard cookie and this one is - // not so allow the new cookie to be set - if (!$cookie->getDiscard() && $c->getDiscard()) { - unset($this->cookies[$i]); - continue; - } - - // If the new cookie's expiration is further into the future, then - // replace the old cookie - if ($cookie->getExpires() > $c->getExpires()) { - unset($this->cookies[$i]); - continue; - } - - // If the value has changed, we better change it - if ($cookie->getValue() !== $c->getValue()) { - unset($this->cookies[$i]); - continue; - } - - // The cookie exists, so no need to continue - return false; - } - - $this->cookies[] = $cookie; - - return true; - } - - public function count() - { - return count($this->cookies); - } - - public function getIterator() - { - return new \ArrayIterator(array_values($this->cookies)); - } - - public function extractCookies( - RequestInterface $request, - ResponseInterface $response - ) { - if ($cookieHeader = $response->getHeader('Set-Cookie')) { - foreach ($cookieHeader as $cookie) { - $sc = SetCookie::fromString($cookie); - if (!$sc->getDomain()) { - $sc->setDomain($request->getUri()->getHost()); - } - if (0 !== strpos($sc->getPath(), '/')) { - $sc->setPath($this->getCookiePathFromRequest($request)); - } - $this->setCookie($sc); - } - } - } - - /** - * Computes cookie path following RFC 6265 section 5.1.4 - * - * @link https://tools.ietf.org/html/rfc6265#section-5.1.4 - * - * @param RequestInterface $request - * @return string - */ - private function getCookiePathFromRequest(RequestInterface $request) - { - $uriPath = $request->getUri()->getPath(); - if ('' === $uriPath) { - return '/'; - } - if (0 !== strpos($uriPath, '/')) { - return '/'; - } - if ('/' === $uriPath) { - return '/'; - } - if (0 === $lastSlashPos = strrpos($uriPath, '/')) { - return '/'; - } - - return substr($uriPath, 0, $lastSlashPos); - } - - public function withCookieHeader(RequestInterface $request) - { - $values = []; - $uri = $request->getUri(); - $scheme = $uri->getScheme(); - $host = $uri->getHost(); - $path = $uri->getPath() ?: '/'; - - foreach ($this->cookies as $cookie) { - if ($cookie->matchesPath($path) && - $cookie->matchesDomain($host) && - !$cookie->isExpired() && - (!$cookie->getSecure() || $scheme === 'https') - ) { - $values[] = $cookie->getName() . '=' - . $cookie->getValue(); - } - } - - return $values - ? $request->withHeader('Cookie', implode('; ', $values)) - : $request; - } - - /** - * If a cookie already exists and the server asks to set it again with a - * null value, the cookie must be deleted. - * - * @param SetCookie $cookie - */ - private function removeCookieIfEmpty(SetCookie $cookie) - { - $cookieValue = $cookie->getValue(); - if ($cookieValue === null || $cookieValue === '') { - $this->clear( - $cookie->getDomain(), - $cookie->getPath(), - $cookie->getName() - ); - } - } -} diff --git a/guzzle/GuzzleHttp/Cookie/CookieJarInterface.php b/guzzle/GuzzleHttp/Cookie/CookieJarInterface.php deleted file mode 100644 index 2cf298a..0000000 --- a/guzzle/GuzzleHttp/Cookie/CookieJarInterface.php +++ /dev/null @@ -1,84 +0,0 @@ -filename = $cookieFile; - $this->storeSessionCookies = $storeSessionCookies; - - if (file_exists($cookieFile)) { - $this->load($cookieFile); - } - } - - /** - * Saves the file when shutting down - */ - public function __destruct() - { - $this->save($this->filename); - } - - /** - * Saves the cookies to a file. - * - * @param string $filename File to save - * @throws \RuntimeException if the file cannot be found or created - */ - public function save($filename) - { - $json = []; - foreach ($this as $cookie) { - /** @var SetCookie $cookie */ - if (CookieJar::shouldPersist($cookie, $this->storeSessionCookies)) { - $json[] = $cookie->toArray(); - } - } - - $jsonStr = \GuzzleHttp\json_encode($json); - if (false === file_put_contents($filename, $jsonStr)) { - throw new \RuntimeException("Unable to save file {$filename}"); - } - } - - /** - * Load cookies from a JSON formatted file. - * - * Old cookies are kept unless overwritten by newly loaded ones. - * - * @param string $filename Cookie file to load. - * @throws \RuntimeException if the file cannot be loaded. - */ - public function load($filename) - { - $json = file_get_contents($filename); - if (false === $json) { - throw new \RuntimeException("Unable to load file {$filename}"); - } elseif ($json === '') { - return; - } - - $data = \GuzzleHttp\json_decode($json, true); - if (is_array($data)) { - foreach (json_decode($json, true) as $cookie) { - $this->setCookie(new SetCookie($cookie)); - } - } elseif (strlen($data)) { - throw new \RuntimeException("Invalid cookie file: {$filename}"); - } - } -} diff --git a/guzzle/GuzzleHttp/Cookie/SessionCookieJar.php b/guzzle/GuzzleHttp/Cookie/SessionCookieJar.php deleted file mode 100644 index e4bfafd..0000000 --- a/guzzle/GuzzleHttp/Cookie/SessionCookieJar.php +++ /dev/null @@ -1,71 +0,0 @@ -sessionKey = $sessionKey; - $this->storeSessionCookies = $storeSessionCookies; - $this->load(); - } - - /** - * Saves cookies to session when shutting down - */ - public function __destruct() - { - $this->save(); - } - - /** - * Save cookies to the client session - */ - public function save() - { - $json = []; - foreach ($this as $cookie) { - /** @var SetCookie $cookie */ - if (CookieJar::shouldPersist($cookie, $this->storeSessionCookies)) { - $json[] = $cookie->toArray(); - } - } - - $_SESSION[$this->sessionKey] = json_encode($json); - } - - /** - * Load the contents of the client session into the data array - */ - protected function load() - { - if (!isset($_SESSION[$this->sessionKey])) { - return; - } - $data = json_decode($_SESSION[$this->sessionKey], true); - if (is_array($data)) { - foreach ($data as $cookie) { - $this->setCookie(new SetCookie($cookie)); - } - } elseif (strlen($data)) { - throw new \RuntimeException("Invalid cookie data"); - } - } -} diff --git a/guzzle/GuzzleHttp/Cookie/SetCookie.php b/guzzle/GuzzleHttp/Cookie/SetCookie.php deleted file mode 100644 index c911e2a..0000000 --- a/guzzle/GuzzleHttp/Cookie/SetCookie.php +++ /dev/null @@ -1,404 +0,0 @@ - null, - 'Value' => null, - 'Domain' => null, - 'Path' => '/', - 'Max-Age' => null, - 'Expires' => null, - 'Secure' => false, - 'Discard' => false, - 'HttpOnly' => false - ]; - - /** @var array Cookie data */ - private $data; - - /** - * Create a new SetCookie object from a string - * - * @param string $cookie Set-Cookie header string - * - * @return self - */ - public static function fromString($cookie) - { - // Create the default return array - $data = self::$defaults; - // Explode the cookie string using a series of semicolons - $pieces = array_filter(array_map('trim', explode(';', $cookie))); - // The name of the cookie (first kvp) must include an equal sign. - if (empty($pieces) || !strpos($pieces[0], '=')) { - return new self($data); - } - - // Add the cookie pieces into the parsed data array - foreach ($pieces as $part) { - - $cookieParts = explode('=', $part, 2); - $key = trim($cookieParts[0]); - $value = isset($cookieParts[1]) - ? trim($cookieParts[1], " \n\r\t\0\x0B") - : true; - - // Only check for non-cookies when cookies have been found - if (empty($data['Name'])) { - $data['Name'] = $key; - $data['Value'] = $value; - } else { - foreach (array_keys(self::$defaults) as $search) { - if (!strcasecmp($search, $key)) { - $data[$search] = $value; - continue 2; - } - } - $data[$key] = $value; - } - } - - return new self($data); - } - - /** - * @param array $data Array of cookie data provided by a Cookie parser - */ - public function __construct(array $data = []) - { - $this->data = array_replace(self::$defaults, $data); - // Extract the Expires value and turn it into a UNIX timestamp if needed - if (!$this->getExpires() && $this->getMaxAge()) { - // Calculate the Expires date - $this->setExpires(time() + $this->getMaxAge()); - } elseif ($this->getExpires() && !is_numeric($this->getExpires())) { - $this->setExpires($this->getExpires()); - } - } - - public function __toString() - { - $str = $this->data['Name'] . '=' . $this->data['Value'] . '; '; - foreach ($this->data as $k => $v) { - if ($k !== 'Name' && $k !== 'Value' && $v !== null && $v !== false) { - if ($k === 'Expires') { - $str .= 'Expires=' . gmdate('D, d M Y H:i:s \G\M\T', $v) . '; '; - } else { - $str .= ($v === true ? $k : "{$k}={$v}") . '; '; - } - } - } - - return rtrim($str, '; '); - } - - public function toArray() - { - return $this->data; - } - - /** - * Get the cookie name - * - * @return string - */ - public function getName() - { - return $this->data['Name']; - } - - /** - * Set the cookie name - * - * @param string $name Cookie name - */ - public function setName($name) - { - $this->data['Name'] = $name; - } - - /** - * Get the cookie value - * - * @return string - */ - public function getValue() - { - return $this->data['Value']; - } - - /** - * Set the cookie value - * - * @param string $value Cookie value - */ - public function setValue($value) - { - $this->data['Value'] = $value; - } - - /** - * Get the domain - * - * @return string|null - */ - public function getDomain() - { - return $this->data['Domain']; - } - - /** - * Set the domain of the cookie - * - * @param string $domain - */ - public function setDomain($domain) - { - $this->data['Domain'] = $domain; - } - - /** - * Get the path - * - * @return string - */ - public function getPath() - { - return $this->data['Path']; - } - - /** - * Set the path of the cookie - * - * @param string $path Path of the cookie - */ - public function setPath($path) - { - $this->data['Path'] = $path; - } - - /** - * Maximum lifetime of the cookie in seconds - * - * @return int|null - */ - public function getMaxAge() - { - return $this->data['Max-Age']; - } - - /** - * Set the max-age of the cookie - * - * @param int $maxAge Max age of the cookie in seconds - */ - public function setMaxAge($maxAge) - { - $this->data['Max-Age'] = $maxAge; - } - - /** - * The UNIX timestamp when the cookie Expires - * - * @return mixed - */ - public function getExpires() - { - return $this->data['Expires']; - } - - /** - * Set the unix timestamp for which the cookie will expire - * - * @param int $timestamp Unix timestamp - */ - public function setExpires($timestamp) - { - $this->data['Expires'] = is_numeric($timestamp) - ? (int) $timestamp - : strtotime($timestamp); - } - - /** - * Get whether or not this is a secure cookie - * - * @return null|bool - */ - public function getSecure() - { - return $this->data['Secure']; - } - - /** - * Set whether or not the cookie is secure - * - * @param bool $secure Set to true or false if secure - */ - public function setSecure($secure) - { - $this->data['Secure'] = $secure; - } - - /** - * Get whether or not this is a session cookie - * - * @return null|bool - */ - public function getDiscard() - { - return $this->data['Discard']; - } - - /** - * Set whether or not this is a session cookie - * - * @param bool $discard Set to true or false if this is a session cookie - */ - public function setDiscard($discard) - { - $this->data['Discard'] = $discard; - } - - /** - * Get whether or not this is an HTTP only cookie - * - * @return bool - */ - public function getHttpOnly() - { - return $this->data['HttpOnly']; - } - - /** - * Set whether or not this is an HTTP only cookie - * - * @param bool $httpOnly Set to true or false if this is HTTP only - */ - public function setHttpOnly($httpOnly) - { - $this->data['HttpOnly'] = $httpOnly; - } - - /** - * Check if the cookie matches a path value. - * - * A request-path path-matches a given cookie-path if at least one of - * the following conditions holds: - * - * - The cookie-path and the request-path are identical. - * - The cookie-path is a prefix of the request-path, and the last - * character of the cookie-path is %x2F ("/"). - * - The cookie-path is a prefix of the request-path, and the first - * character of the request-path that is not included in the cookie- - * path is a %x2F ("/") character. - * - * @param string $requestPath Path to check against - * - * @return bool - */ - public function matchesPath($requestPath) - { - $cookiePath = $this->getPath(); - - // Match on exact matches or when path is the default empty "/" - if ($cookiePath === '/' || $cookiePath == $requestPath) { - return true; - } - - // Ensure that the cookie-path is a prefix of the request path. - if (0 !== strpos($requestPath, $cookiePath)) { - return false; - } - - // Match if the last character of the cookie-path is "/" - if (substr($cookiePath, -1, 1) === '/') { - return true; - } - - // Match if the first character not included in cookie path is "/" - return substr($requestPath, strlen($cookiePath), 1) === '/'; - } - - /** - * Check if the cookie matches a domain value - * - * @param string $domain Domain to check against - * - * @return bool - */ - public function matchesDomain($domain) - { - // Remove the leading '.' as per spec in RFC 6265. - // http://tools.ietf.org/html/rfc6265#section-5.2.3 - $cookieDomain = ltrim($this->getDomain(), '.'); - - // Domain not set or exact match. - if (!$cookieDomain || !strcasecmp($domain, $cookieDomain)) { - return true; - } - - // Matching the subdomain according to RFC 6265. - // http://tools.ietf.org/html/rfc6265#section-5.1.3 - if (filter_var($domain, FILTER_VALIDATE_IP)) { - return false; - } - - return (bool) preg_match('/\.' . preg_quote($cookieDomain) . '$/', $domain); - } - - /** - * Check if the cookie is expired - * - * @return bool - */ - public function isExpired() - { - return $this->getExpires() && time() > $this->getExpires(); - } - - /** - * Check if the cookie is valid according to RFC 6265 - * - * @return bool|string Returns true if valid or an error message if invalid - */ - public function validate() - { - // Names must not be empty, but can be 0 - $name = $this->getName(); - if (empty($name) && !is_numeric($name)) { - return 'The cookie name must not be empty'; - } - - // Check if any of the invalid characters are present in the cookie name - if (preg_match( - '/[\x00-\x20\x22\x28-\x29\x2c\x2f\x3a-\x40\x5c\x7b\x7d\x7f]/', - $name) - ) { - return 'Cookie name must not contain invalid characters: ASCII ' - . 'Control characters (0-31;127), space, tab and the ' - . 'following characters: ()<>@,;:\"/?={}'; - } - - // Value must not be empty, but can be 0 - $value = $this->getValue(); - if (empty($value) && !is_numeric($value)) { - return 'The cookie value must not be empty'; - } - - // Domains must not be empty, but can be 0 - // A "0" is not a valid internet domain, but may be used as server name - // in a private network. - $domain = $this->getDomain(); - if (empty($domain) && !is_numeric($domain)) { - return 'The cookie domain must not be empty'; - } - - return true; - } -} diff --git a/guzzle/GuzzleHttp/Exception/BadResponseException.php b/guzzle/GuzzleHttp/Exception/BadResponseException.php deleted file mode 100644 index 427d896..0000000 --- a/guzzle/GuzzleHttp/Exception/BadResponseException.php +++ /dev/null @@ -1,27 +0,0 @@ -getStatusCode() - : 0; - parent::__construct($message, $code, $previous); - $this->request = $request; - $this->response = $response; - $this->handlerContext = $handlerContext; - } - - /** - * Wrap non-RequestExceptions with a RequestException - * - * @param RequestInterface $request - * @param \Exception $e - * - * @return RequestException - */ - public static function wrapException(RequestInterface $request, \Exception $e) - { - return $e instanceof RequestException - ? $e - : new RequestException($e->getMessage(), $request, null, $e); - } - - /** - * Factory method to create a new exception with a normalized error message - * - * @param RequestInterface $request Request - * @param ResponseInterface $response Response received - * @param \Exception $previous Previous exception - * @param array $ctx Optional handler context. - * - * @return self - */ - public static function create( - RequestInterface $request, - ResponseInterface $response = null, - \Exception $previous = null, - array $ctx = [] - ) { - if (!$response) { - return new self( - 'Error completing request', - $request, - null, - $previous, - $ctx - ); - } - - $level = (int) floor($response->getStatusCode() / 100); - if ($level === 4) { - $label = 'Client error'; - $className = ClientException::class; - } elseif ($level === 5) { - $label = 'Server error'; - $className = ServerException::class; - } else { - $label = 'Unsuccessful request'; - $className = __CLASS__; - } - - $uri = $request->getUri(); - $uri = static::obfuscateUri($uri); - - // Client Error: `GET /` resulted in a `404 Not Found` response: - // ... (truncated) - $message = sprintf( - '%s: `%s %s` resulted in a `%s %s` response', - $label, - $request->getMethod(), - $uri, - $response->getStatusCode(), - $response->getReasonPhrase() - ); - - $summary = static::getResponseBodySummary($response); - - if ($summary !== null) { - $message .= ":\n{$summary}\n"; - } - - return new $className($message, $request, $response, $previous, $ctx); - } - - /** - * Get a short summary of the response - * - * Will return `null` if the response is not printable. - * - * @param ResponseInterface $response - * - * @return string|null - */ - public static function getResponseBodySummary(ResponseInterface $response) - { - $body = $response->getBody(); - - if (!$body->isSeekable()) { - return null; - } - - $size = $body->getSize(); - - if ($size === 0) { - return null; - } - - $summary = $body->read(120); - $body->rewind(); - - if ($size > 120) { - $summary .= ' (truncated...)'; - } - - // Matches any printable character, including unicode characters: - // letters, marks, numbers, punctuation, spacing, and separators. - if (preg_match('/[^\pL\pM\pN\pP\pS\pZ\n\r\t]/', $summary)) { - return null; - } - - return $summary; - } - - /** - * Obfuscates URI if there is an username and a password present - * - * @param UriInterface $uri - * - * @return UriInterface - */ - private static function obfuscateUri($uri) - { - $userInfo = $uri->getUserInfo(); - - if (false !== ($pos = strpos($userInfo, ':'))) { - return $uri->withUserInfo(substr($userInfo, 0, $pos), '***'); - } - - return $uri; - } - - /** - * Get the request that caused the exception - * - * @return RequestInterface - */ - public function getRequest() - { - return $this->request; - } - - /** - * Get the associated response - * - * @return ResponseInterface|null - */ - public function getResponse() - { - return $this->response; - } - - /** - * Check if a response was received - * - * @return bool - */ - public function hasResponse() - { - return $this->response !== null; - } - - /** - * Get contextual information about the error from the underlying handler. - * - * The contents of this array will vary depending on which handler you are - * using. It may also be just an empty array. Relying on this data will - * couple you to a specific handler, but can give more debug information - * when needed. - * - * @return array - */ - public function getHandlerContext() - { - return $this->handlerContext; - } -} diff --git a/guzzle/GuzzleHttp/Exception/SeekException.php b/guzzle/GuzzleHttp/Exception/SeekException.php deleted file mode 100644 index a77c289..0000000 --- a/guzzle/GuzzleHttp/Exception/SeekException.php +++ /dev/null @@ -1,27 +0,0 @@ -stream = $stream; - $msg = $msg ?: 'Could not seek the stream to position ' . $pos; - parent::__construct($msg); - } - - /** - * @return StreamInterface - */ - public function getStream() - { - return $this->stream; - } -} diff --git a/guzzle/GuzzleHttp/Exception/ServerException.php b/guzzle/GuzzleHttp/Exception/ServerException.php deleted file mode 100644 index 7cdd340..0000000 --- a/guzzle/GuzzleHttp/Exception/ServerException.php +++ /dev/null @@ -1,7 +0,0 @@ -maxHandles = $maxHandles; - } - - public function create(RequestInterface $request, array $options) - { - if (isset($options['curl']['body_as_string'])) { - $options['_body_as_string'] = $options['curl']['body_as_string']; - unset($options['curl']['body_as_string']); - } - - $easy = new EasyHandle; - $easy->request = $request; - $easy->options = $options; - $conf = $this->getDefaultConf($easy); - $this->applyMethod($easy, $conf); - $this->applyHandlerOptions($easy, $conf); - $this->applyHeaders($easy, $conf); - unset($conf['_headers']); - - // Add handler options from the request configuration options - if (isset($options['curl'])) { - $conf = array_replace($conf, $options['curl']); - } - - $conf[CURLOPT_HEADERFUNCTION] = $this->createHeaderFn($easy); - $easy->handle = $this->handles - ? array_pop($this->handles) - : curl_init(); - curl_setopt_array($easy->handle, $conf); - - return $easy; - } - - public function release(EasyHandle $easy) - { - $resource = $easy->handle; - unset($easy->handle); - - if (count($this->handles) >= $this->maxHandles) { - curl_close($resource); - } else { - // Remove all callback functions as they can hold onto references - // and are not cleaned up by curl_reset. Using curl_setopt_array - // does not work for some reason, so removing each one - // individually. - curl_setopt($resource, CURLOPT_HEADERFUNCTION, null); - curl_setopt($resource, CURLOPT_READFUNCTION, null); - curl_setopt($resource, CURLOPT_WRITEFUNCTION, null); - curl_setopt($resource, CURLOPT_PROGRESSFUNCTION, null); - curl_reset($resource); - $this->handles[] = $resource; - } - } - - /** - * Completes a cURL transaction, either returning a response promise or a - * rejected promise. - * - * @param callable $handler - * @param EasyHandle $easy - * @param CurlFactoryInterface $factory Dictates how the handle is released - * - * @return \GuzzleHttp\Promise\PromiseInterface - */ - public static function finish( - callable $handler, - EasyHandle $easy, - CurlFactoryInterface $factory - ) { - if (isset($easy->options['on_stats'])) { - self::invokeStats($easy); - } - - if (!$easy->response || $easy->errno) { - return self::finishError($handler, $easy, $factory); - } - - // Return the response if it is present and there is no error. - $factory->release($easy); - - // Rewind the body of the response if possible. - $body = $easy->response->getBody(); - if ($body->isSeekable()) { - $body->rewind(); - } - - return new FulfilledPromise($easy->response); - } - - private static function invokeStats(EasyHandle $easy) - { - $curlStats = curl_getinfo($easy->handle); - $stats = new TransferStats( - $easy->request, - $easy->response, - $curlStats['total_time'], - $easy->errno, - $curlStats - ); - call_user_func($easy->options['on_stats'], $stats); - } - - private static function finishError( - callable $handler, - EasyHandle $easy, - CurlFactoryInterface $factory - ) { - // Get error information and release the handle to the factory. - $ctx = [ - 'errno' => $easy->errno, - 'error' => curl_error($easy->handle), - ] + curl_getinfo($easy->handle); - $factory->release($easy); - - // Retry when nothing is present or when curl failed to rewind. - if (empty($easy->options['_err_message']) - && (!$easy->errno || $easy->errno == 65) - ) { - return self::retryFailedRewind($handler, $easy, $ctx); - } - - return self::createRejection($easy, $ctx); - } - - private static function createRejection(EasyHandle $easy, array $ctx) - { - static $connectionErrors = [ - CURLE_OPERATION_TIMEOUTED => true, - CURLE_COULDNT_RESOLVE_HOST => true, - CURLE_COULDNT_CONNECT => true, - CURLE_SSL_CONNECT_ERROR => true, - CURLE_GOT_NOTHING => true, - ]; - - // If an exception was encountered during the onHeaders event, then - // return a rejected promise that wraps that exception. - if ($easy->onHeadersException) { - return \GuzzleHttp\Promise\rejection_for( - new RequestException( - 'An error was encountered during the on_headers event', - $easy->request, - $easy->response, - $easy->onHeadersException, - $ctx - ) - ); - } - - $message = sprintf( - 'cURL error %s: %s (%s)', - $ctx['errno'], - $ctx['error'], - 'see http://curl.haxx.se/libcurl/c/libcurl-errors.html' - ); - - // Create a connection exception if it was a specific error code. - $error = isset($connectionErrors[$easy->errno]) - ? new ConnectException($message, $easy->request, null, $ctx) - : new RequestException($message, $easy->request, $easy->response, null, $ctx); - - return \GuzzleHttp\Promise\rejection_for($error); - } - - private function getDefaultConf(EasyHandle $easy) - { - $conf = [ - '_headers' => $easy->request->getHeaders(), - CURLOPT_CUSTOMREQUEST => $easy->request->getMethod(), - CURLOPT_URL => (string) $easy->request->getUri()->withFragment(''), - CURLOPT_RETURNTRANSFER => false, - CURLOPT_HEADER => false, - CURLOPT_CONNECTTIMEOUT => 150, - ]; - - if (defined('CURLOPT_PROTOCOLS')) { - $conf[CURLOPT_PROTOCOLS] = CURLPROTO_HTTP | CURLPROTO_HTTPS; - } - - $version = $easy->request->getProtocolVersion(); - if ($version == 1.1) { - $conf[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_1_1; - } elseif ($version == 2.0) { - $conf[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_2_0; - } else { - $conf[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_1_0; - } - - return $conf; - } - - private function applyMethod(EasyHandle $easy, array &$conf) - { - $body = $easy->request->getBody(); - $size = $body->getSize(); - - if ($size === null || $size > 0) { - $this->applyBody($easy->request, $easy->options, $conf); - return; - } - - $method = $easy->request->getMethod(); - if ($method === 'PUT' || $method === 'POST') { - // See http://tools.ietf.org/html/rfc7230#section-3.3.2 - if (!$easy->request->hasHeader('Content-Length')) { - $conf[CURLOPT_HTTPHEADER][] = 'Content-Length: 0'; - } - } elseif ($method === 'HEAD') { - $conf[CURLOPT_NOBODY] = true; - unset( - $conf[CURLOPT_WRITEFUNCTION], - $conf[CURLOPT_READFUNCTION], - $conf[CURLOPT_FILE], - $conf[CURLOPT_INFILE] - ); - } - } - - private function applyBody(RequestInterface $request, array $options, array &$conf) - { - $size = $request->hasHeader('Content-Length') - ? (int) $request->getHeaderLine('Content-Length') - : null; - - // Send the body as a string if the size is less than 1MB OR if the - // [curl][body_as_string] request value is set. - if (($size !== null && $size < 1000000) || - !empty($options['_body_as_string']) - ) { - $conf[CURLOPT_POSTFIELDS] = (string) $request->getBody(); - // Don't duplicate the Content-Length header - $this->removeHeader('Content-Length', $conf); - $this->removeHeader('Transfer-Encoding', $conf); - } else { - $conf[CURLOPT_UPLOAD] = true; - if ($size !== null) { - $conf[CURLOPT_INFILESIZE] = $size; - $this->removeHeader('Content-Length', $conf); - } - $body = $request->getBody(); - if ($body->isSeekable()) { - $body->rewind(); - } - $conf[CURLOPT_READFUNCTION] = function ($ch, $fd, $length) use ($body) { - return $body->read($length); - }; - } - - // If the Expect header is not present, prevent curl from adding it - if (!$request->hasHeader('Expect')) { - $conf[CURLOPT_HTTPHEADER][] = 'Expect:'; - } - - // cURL sometimes adds a content-type by default. Prevent this. - if (!$request->hasHeader('Content-Type')) { - $conf[CURLOPT_HTTPHEADER][] = 'Content-Type:'; - } - } - - private function applyHeaders(EasyHandle $easy, array &$conf) - { - foreach ($conf['_headers'] as $name => $values) { - foreach ($values as $value) { - $conf[CURLOPT_HTTPHEADER][] = "$name: $value"; - } - } - - // Remove the Accept header if one was not set - if (!$easy->request->hasHeader('Accept')) { - $conf[CURLOPT_HTTPHEADER][] = 'Accept:'; - } - } - - /** - * Remove a header from the options array. - * - * @param string $name Case-insensitive header to remove - * @param array $options Array of options to modify - */ - private function removeHeader($name, array &$options) - { - foreach (array_keys($options['_headers']) as $key) { - if (!strcasecmp($key, $name)) { - unset($options['_headers'][$key]); - return; - } - } - } - - private function applyHandlerOptions(EasyHandle $easy, array &$conf) - { - $options = $easy->options; - if (isset($options['verify'])) { - if ($options['verify'] === false) { - unset($conf[CURLOPT_CAINFO]); - $conf[CURLOPT_SSL_VERIFYHOST] = 0; - $conf[CURLOPT_SSL_VERIFYPEER] = false; - } else { - $conf[CURLOPT_SSL_VERIFYHOST] = 2; - $conf[CURLOPT_SSL_VERIFYPEER] = true; - if (is_string($options['verify'])) { - // Throw an error if the file/folder/link path is not valid or doesn't exist. - if (!file_exists($options['verify'])) { - throw new \InvalidArgumentException( - "SSL CA bundle not found: {$options['verify']}" - ); - } - // If it's a directory or a link to a directory use CURLOPT_CAPATH. - // If not, it's probably a file, or a link to a file, so use CURLOPT_CAINFO. - if (is_dir($options['verify']) || - (is_link($options['verify']) && is_dir(readlink($options['verify'])))) { - $conf[CURLOPT_CAPATH] = $options['verify']; - } else { - $conf[CURLOPT_CAINFO] = $options['verify']; - } - } - } - } - - if (!empty($options['decode_content'])) { - $accept = $easy->request->getHeaderLine('Accept-Encoding'); - if ($accept) { - $conf[CURLOPT_ENCODING] = $accept; - } else { - $conf[CURLOPT_ENCODING] = ''; - // Don't let curl send the header over the wire - $conf[CURLOPT_HTTPHEADER][] = 'Accept-Encoding:'; - } - } - - if (isset($options['sink'])) { - $sink = $options['sink']; - if (!is_string($sink)) { - $sink = \GuzzleHttp\Psr7\stream_for($sink); - } elseif (!is_dir(dirname($sink))) { - // Ensure that the directory exists before failing in curl. - throw new \RuntimeException(sprintf( - 'Directory %s does not exist for sink value of %s', - dirname($sink), - $sink - )); - } else { - $sink = new LazyOpenStream($sink, 'w+'); - } - $easy->sink = $sink; - $conf[CURLOPT_WRITEFUNCTION] = function ($ch, $write) use ($sink) { - return $sink->write($write); - }; - } else { - // Use a default temp stream if no sink was set. - $conf[CURLOPT_FILE] = fopen('php://temp', 'w+'); - $easy->sink = Psr7\stream_for($conf[CURLOPT_FILE]); - } - $timeoutRequiresNoSignal = false; - if (isset($options['timeout'])) { - $timeoutRequiresNoSignal |= $options['timeout'] < 1; - $conf[CURLOPT_TIMEOUT_MS] = $options['timeout'] * 1000; - } - - // CURL default value is CURL_IPRESOLVE_WHATEVER - if (isset($options['force_ip_resolve'])) { - if ('v4' === $options['force_ip_resolve']) { - $conf[CURLOPT_IPRESOLVE] = CURL_IPRESOLVE_V4; - } else if ('v6' === $options['force_ip_resolve']) { - $conf[CURLOPT_IPRESOLVE] = CURL_IPRESOLVE_V6; - } - } - - if (isset($options['connect_timeout'])) { - $timeoutRequiresNoSignal |= $options['connect_timeout'] < 1; - $conf[CURLOPT_CONNECTTIMEOUT_MS] = $options['connect_timeout'] * 1000; - } - - if ($timeoutRequiresNoSignal && strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN') { - $conf[CURLOPT_NOSIGNAL] = true; - } - - if (isset($options['proxy'])) { - if (!is_array($options['proxy'])) { - $conf[CURLOPT_PROXY] = $options['proxy']; - } else { - $scheme = $easy->request->getUri()->getScheme(); - if (isset($options['proxy'][$scheme])) { - $host = $easy->request->getUri()->getHost(); - if (!isset($options['proxy']['no']) || - !\GuzzleHttp\is_host_in_noproxy($host, $options['proxy']['no']) - ) { - $conf[CURLOPT_PROXY] = $options['proxy'][$scheme]; - } - } - } - } - - if (isset($options['cert'])) { - $cert = $options['cert']; - if (is_array($cert)) { - $conf[CURLOPT_SSLCERTPASSWD] = $cert[1]; - $cert = $cert[0]; - } - if (!file_exists($cert)) { - throw new \InvalidArgumentException( - "SSL certificate not found: {$cert}" - ); - } - $conf[CURLOPT_SSLCERT] = $cert; - } - - if (isset($options['ssl_key'])) { - $sslKey = $options['ssl_key']; - if (is_array($sslKey)) { - $conf[CURLOPT_SSLKEYPASSWD] = $sslKey[1]; - $sslKey = $sslKey[0]; - } - if (!file_exists($sslKey)) { - throw new \InvalidArgumentException( - "SSL private key not found: {$sslKey}" - ); - } - $conf[CURLOPT_SSLKEY] = $sslKey; - } - - if (isset($options['progress'])) { - $progress = $options['progress']; - if (!is_callable($progress)) { - throw new \InvalidArgumentException( - 'progress client option must be callable' - ); - } - $conf[CURLOPT_NOPROGRESS] = false; - $conf[CURLOPT_PROGRESSFUNCTION] = function () use ($progress) { - $args = func_get_args(); - // PHP 5.5 pushed the handle onto the start of the args - if (is_resource($args[0])) { - array_shift($args); - } - call_user_func_array($progress, $args); - }; - } - - if (!empty($options['debug'])) { - $conf[CURLOPT_STDERR] = \GuzzleHttp\debug_resource($options['debug']); - $conf[CURLOPT_VERBOSE] = true; - } - } - - /** - * This function ensures that a response was set on a transaction. If one - * was not set, then the request is retried if possible. This error - * typically means you are sending a payload, curl encountered a - * "Connection died, retrying a fresh connect" error, tried to rewind the - * stream, and then encountered a "necessary data rewind wasn't possible" - * error, causing the request to be sent through curl_multi_info_read() - * without an error status. - */ - private static function retryFailedRewind( - callable $handler, - EasyHandle $easy, - array $ctx - ) { - try { - // Only rewind if the body has been read from. - $body = $easy->request->getBody(); - if ($body->tell() > 0) { - $body->rewind(); - } - } catch (\RuntimeException $e) { - $ctx['error'] = 'The connection unexpectedly failed without ' - . 'providing an error. The request would have been retried, ' - . 'but attempting to rewind the request body failed. ' - . 'Exception: ' . $e; - return self::createRejection($easy, $ctx); - } - - // Retry no more than 3 times before giving up. - if (!isset($easy->options['_curl_retries'])) { - $easy->options['_curl_retries'] = 1; - } elseif ($easy->options['_curl_retries'] == 2) { - $ctx['error'] = 'The cURL request was retried 3 times ' - . 'and did not succeed. The most likely reason for the failure ' - . 'is that cURL was unable to rewind the body of the request ' - . 'and subsequent retries resulted in the same error. Turn on ' - . 'the debug option to see what went wrong. See ' - . 'https://bugs.php.net/bug.php?id=47204 for more information.'; - return self::createRejection($easy, $ctx); - } else { - $easy->options['_curl_retries']++; - } - - return $handler($easy->request, $easy->options); - } - - private function createHeaderFn(EasyHandle $easy) - { - if (isset($easy->options['on_headers'])) { - $onHeaders = $easy->options['on_headers']; - - if (!is_callable($onHeaders)) { - throw new \InvalidArgumentException('on_headers must be callable'); - } - } else { - $onHeaders = null; - } - - return function ($ch, $h) use ( - $onHeaders, - $easy, - &$startingResponse - ) { - $value = trim($h); - if ($value === '') { - $startingResponse = true; - $easy->createResponse(); - if ($onHeaders !== null) { - try { - $onHeaders($easy->response); - } catch (\Exception $e) { - // Associate the exception with the handle and trigger - // a curl header write error by returning 0. - $easy->onHeadersException = $e; - return -1; - } - } - } elseif ($startingResponse) { - $startingResponse = false; - $easy->headers = [$value]; - } else { - $easy->headers[] = $value; - } - return strlen($h); - }; - } -} diff --git a/guzzle/GuzzleHttp/Handler/CurlFactoryInterface.php b/guzzle/GuzzleHttp/Handler/CurlFactoryInterface.php deleted file mode 100644 index b0fc236..0000000 --- a/guzzle/GuzzleHttp/Handler/CurlFactoryInterface.php +++ /dev/null @@ -1,27 +0,0 @@ -factory = isset($options['handle_factory']) - ? $options['handle_factory'] - : new CurlFactory(3); - } - - public function __invoke(RequestInterface $request, array $options) - { - if (isset($options['delay'])) { - usleep($options['delay'] * 1000); - } - - $easy = $this->factory->create($request, $options); - curl_exec($easy->handle); - $easy->errno = curl_errno($easy->handle); - - return CurlFactory::finish($this, $easy, $this->factory); - } -} diff --git a/guzzle/GuzzleHttp/Handler/CurlMultiHandler.php b/guzzle/GuzzleHttp/Handler/CurlMultiHandler.php deleted file mode 100644 index 945d06e..0000000 --- a/guzzle/GuzzleHttp/Handler/CurlMultiHandler.php +++ /dev/null @@ -1,197 +0,0 @@ -factory = isset($options['handle_factory']) - ? $options['handle_factory'] : new CurlFactory(50); - $this->selectTimeout = isset($options['select_timeout']) - ? $options['select_timeout'] : 1; - } - - public function __get($name) - { - if ($name === '_mh') { - return $this->_mh = curl_multi_init(); - } - - throw new \BadMethodCallException(); - } - - public function __destruct() - { - if (isset($this->_mh)) { - curl_multi_close($this->_mh); - unset($this->_mh); - } - } - - public function __invoke(RequestInterface $request, array $options) - { - $easy = $this->factory->create($request, $options); - $id = (int) $easy->handle; - - $promise = new Promise( - [$this, 'execute'], - function () use ($id) { return $this->cancel($id); } - ); - - $this->addRequest(['easy' => $easy, 'deferred' => $promise]); - - return $promise; - } - - /** - * Ticks the curl event loop. - */ - public function tick() - { - // Add any delayed handles if needed. - if ($this->delays) { - $currentTime = microtime(true); - foreach ($this->delays as $id => $delay) { - if ($currentTime >= $delay) { - unset($this->delays[$id]); - curl_multi_add_handle( - $this->_mh, - $this->handles[$id]['easy']->handle - ); - } - } - } - - // Step through the task queue which may add additional requests. - P\queue()->run(); - - if ($this->active && - curl_multi_select($this->_mh, $this->selectTimeout) === -1 - ) { - // Perform a usleep if a select returns -1. - // See: https://bugs.php.net/bug.php?id=61141 - usleep(250); - } - - while (curl_multi_exec($this->_mh, $this->active) === CURLM_CALL_MULTI_PERFORM); - - $this->processMessages(); - } - - /** - * Runs until all outstanding connections have completed. - */ - public function execute() - { - $queue = P\queue(); - - while ($this->handles || !$queue->isEmpty()) { - // If there are no transfers, then sleep for the next delay - if (!$this->active && $this->delays) { - usleep($this->timeToNext()); - } - $this->tick(); - } - } - - private function addRequest(array $entry) - { - $easy = $entry['easy']; - $id = (int) $easy->handle; - $this->handles[$id] = $entry; - if (empty($easy->options['delay'])) { - curl_multi_add_handle($this->_mh, $easy->handle); - } else { - $this->delays[$id] = microtime(true) + ($easy->options['delay'] / 1000); - } - } - - /** - * Cancels a handle from sending and removes references to it. - * - * @param int $id Handle ID to cancel and remove. - * - * @return bool True on success, false on failure. - */ - private function cancel($id) - { - // Cannot cancel if it has been processed. - if (!isset($this->handles[$id])) { - return false; - } - - $handle = $this->handles[$id]['easy']->handle; - unset($this->delays[$id], $this->handles[$id]); - curl_multi_remove_handle($this->_mh, $handle); - curl_close($handle); - - return true; - } - - private function processMessages() - { - while ($done = curl_multi_info_read($this->_mh)) { - $id = (int) $done['handle']; - curl_multi_remove_handle($this->_mh, $done['handle']); - - if (!isset($this->handles[$id])) { - // Probably was cancelled. - continue; - } - - $entry = $this->handles[$id]; - unset($this->handles[$id], $this->delays[$id]); - $entry['easy']->errno = $done['result']; - $entry['deferred']->resolve( - CurlFactory::finish( - $this, - $entry['easy'], - $this->factory - ) - ); - } - } - - private function timeToNext() - { - $currentTime = microtime(true); - $nextTime = PHP_INT_MAX; - foreach ($this->delays as $time) { - if ($time < $nextTime) { - $nextTime = $time; - } - } - - return max(0, $nextTime - $currentTime) * 1000000; - } -} diff --git a/guzzle/GuzzleHttp/Handler/EasyHandle.php b/guzzle/GuzzleHttp/Handler/EasyHandle.php deleted file mode 100644 index 7754e91..0000000 --- a/guzzle/GuzzleHttp/Handler/EasyHandle.php +++ /dev/null @@ -1,92 +0,0 @@ -headers)) { - throw new \RuntimeException('No headers have been received'); - } - - // HTTP-version SP status-code SP reason-phrase - $startLine = explode(' ', array_shift($this->headers), 3); - $headers = \GuzzleHttp\headers_from_lines($this->headers); - $normalizedKeys = \GuzzleHttp\normalize_header_keys($headers); - - if (!empty($this->options['decode_content']) - && isset($normalizedKeys['content-encoding']) - ) { - $headers['x-encoded-content-encoding'] - = $headers[$normalizedKeys['content-encoding']]; - unset($headers[$normalizedKeys['content-encoding']]); - if (isset($normalizedKeys['content-length'])) { - $headers['x-encoded-content-length'] - = $headers[$normalizedKeys['content-length']]; - - $bodyLength = (int) $this->sink->getSize(); - if ($bodyLength) { - $headers[$normalizedKeys['content-length']] = $bodyLength; - } else { - unset($headers[$normalizedKeys['content-length']]); - } - } - } - - // Attach a response to the easy handle with the parsed headers. - $this->response = new Response( - $startLine[1], - $headers, - $this->sink, - substr($startLine[0], 5), - isset($startLine[2]) ? (string) $startLine[2] : null - ); - } - - public function __get($name) - { - $msg = $name === 'handle' - ? 'The EasyHandle has been released' - : 'Invalid property: ' . $name; - throw new \BadMethodCallException($msg); - } -} diff --git a/guzzle/GuzzleHttp/Handler/MockHandler.php b/guzzle/GuzzleHttp/Handler/MockHandler.php deleted file mode 100644 index d892061..0000000 --- a/guzzle/GuzzleHttp/Handler/MockHandler.php +++ /dev/null @@ -1,189 +0,0 @@ -onFulfilled = $onFulfilled; - $this->onRejected = $onRejected; - - if ($queue) { - call_user_func_array([$this, 'append'], $queue); - } - } - - public function __invoke(RequestInterface $request, array $options) - { - if (!$this->queue) { - throw new \OutOfBoundsException('Mock queue is empty'); - } - - if (isset($options['delay'])) { - usleep($options['delay'] * 1000); - } - - $this->lastRequest = $request; - $this->lastOptions = $options; - $response = array_shift($this->queue); - - if (isset($options['on_headers'])) { - if (!is_callable($options['on_headers'])) { - throw new \InvalidArgumentException('on_headers must be callable'); - } - try { - $options['on_headers']($response); - } catch (\Exception $e) { - $msg = 'An error was encountered during the on_headers event'; - $response = new RequestException($msg, $request, $response, $e); - } - } - - if (is_callable($response)) { - $response = call_user_func($response, $request, $options); - } - - $response = $response instanceof \Exception - ? \GuzzleHttp\Promise\rejection_for($response) - : \GuzzleHttp\Promise\promise_for($response); - - return $response->then( - function ($value) use ($request, $options) { - $this->invokeStats($request, $options, $value); - if ($this->onFulfilled) { - call_user_func($this->onFulfilled, $value); - } - if (isset($options['sink'])) { - $contents = (string) $value->getBody(); - $sink = $options['sink']; - - if (is_resource($sink)) { - fwrite($sink, $contents); - } elseif (is_string($sink)) { - file_put_contents($sink, $contents); - } elseif ($sink instanceof \Psr\Http\Message\StreamInterface) { - $sink->write($contents); - } - } - - return $value; - }, - function ($reason) use ($request, $options) { - $this->invokeStats($request, $options, null, $reason); - if ($this->onRejected) { - call_user_func($this->onRejected, $reason); - } - return \GuzzleHttp\Promise\rejection_for($reason); - } - ); - } - - /** - * Adds one or more variadic requests, exceptions, callables, or promises - * to the queue. - */ - public function append() - { - foreach (func_get_args() as $value) { - if ($value instanceof ResponseInterface - || $value instanceof \Exception - || $value instanceof PromiseInterface - || is_callable($value) - ) { - $this->queue[] = $value; - } else { - throw new \InvalidArgumentException('Expected a response or ' - . 'exception. Found ' . \GuzzleHttp\describe_type($value)); - } - } - } - - /** - * Get the last received request. - * - * @return RequestInterface - */ - public function getLastRequest() - { - return $this->lastRequest; - } - - /** - * Get the last received request options. - * - * @return array - */ - public function getLastOptions() - { - return $this->lastOptions; - } - - /** - * Returns the number of remaining items in the queue. - * - * @return int - */ - public function count() - { - return count($this->queue); - } - - private function invokeStats( - RequestInterface $request, - array $options, - ResponseInterface $response = null, - $reason = null - ) { - if (isset($options['on_stats'])) { - $stats = new TransferStats($request, $response, 0, $reason); - call_user_func($options['on_stats'], $stats); - } - } -} diff --git a/guzzle/GuzzleHttp/Handler/Proxy.php b/guzzle/GuzzleHttp/Handler/Proxy.php deleted file mode 100644 index f8b00be..0000000 --- a/guzzle/GuzzleHttp/Handler/Proxy.php +++ /dev/null @@ -1,55 +0,0 @@ -withoutHeader('Expect'); - - // Append a content-length header if body size is zero to match - // cURL's behavior. - if (0 === $request->getBody()->getSize()) { - $request = $request->withHeader('Content-Length', 0); - } - - return $this->createResponse( - $request, - $options, - $this->createStream($request, $options), - $startTime - ); - } catch (\InvalidArgumentException $e) { - throw $e; - } catch (\Exception $e) { - // Determine if the error was a networking error. - $message = $e->getMessage(); - // This list can probably get more comprehensive. - if (strpos($message, 'getaddrinfo') // DNS lookup failed - || strpos($message, 'Connection refused') - || strpos($message, "couldn't connect to host") // error on HHVM - ) { - $e = new ConnectException($e->getMessage(), $request, $e); - } - $e = RequestException::wrapException($request, $e); - $this->invokeStats($options, $request, $startTime, null, $e); - - return \GuzzleHttp\Promise\rejection_for($e); - } - } - - private function invokeStats( - array $options, - RequestInterface $request, - $startTime, - ResponseInterface $response = null, - $error = null - ) { - if (isset($options['on_stats'])) { - $stats = new TransferStats( - $request, - $response, - microtime(true) - $startTime, - $error, - [] - ); - call_user_func($options['on_stats'], $stats); - } - } - - private function createResponse( - RequestInterface $request, - array $options, - $stream, - $startTime - ) { - $hdrs = $this->lastHeaders; - $this->lastHeaders = []; - $parts = explode(' ', array_shift($hdrs), 3); - $ver = explode('/', $parts[0])[1]; - $status = $parts[1]; - $reason = isset($parts[2]) ? $parts[2] : null; - $headers = \GuzzleHttp\headers_from_lines($hdrs); - list ($stream, $headers) = $this->checkDecode($options, $headers, $stream); - $stream = Psr7\stream_for($stream); - $sink = $stream; - - if (strcasecmp('HEAD', $request->getMethod())) { - $sink = $this->createSink($stream, $options); - } - - $response = new Psr7\Response($status, $headers, $sink, $ver, $reason); - - if (isset($options['on_headers'])) { - try { - $options['on_headers']($response); - } catch (\Exception $e) { - $msg = 'An error was encountered during the on_headers event'; - $ex = new RequestException($msg, $request, $response, $e); - return \GuzzleHttp\Promise\rejection_for($ex); - } - } - - // Do not drain when the request is a HEAD request because they have - // no body. - if ($sink !== $stream) { - $this->drain( - $stream, - $sink, - $response->getHeaderLine('Content-Length') - ); - } - - $this->invokeStats($options, $request, $startTime, $response, null); - - return new FulfilledPromise($response); - } - - private function createSink(StreamInterface $stream, array $options) - { - if (!empty($options['stream'])) { - return $stream; - } - - $sink = isset($options['sink']) - ? $options['sink'] - : fopen('php://temp', 'r+'); - - return is_string($sink) - ? new Psr7\LazyOpenStream($sink, 'w+') - : Psr7\stream_for($sink); - } - - private function checkDecode(array $options, array $headers, $stream) - { - // Automatically decode responses when instructed. - if (!empty($options['decode_content'])) { - $normalizedKeys = \GuzzleHttp\normalize_header_keys($headers); - if (isset($normalizedKeys['content-encoding'])) { - $encoding = $headers[$normalizedKeys['content-encoding']]; - if ($encoding[0] === 'gzip' || $encoding[0] === 'deflate') { - $stream = new Psr7\InflateStream( - Psr7\stream_for($stream) - ); - $headers['x-encoded-content-encoding'] - = $headers[$normalizedKeys['content-encoding']]; - // Remove content-encoding header - unset($headers[$normalizedKeys['content-encoding']]); - // Fix content-length header - if (isset($normalizedKeys['content-length'])) { - $headers['x-encoded-content-length'] - = $headers[$normalizedKeys['content-length']]; - - $length = (int) $stream->getSize(); - if ($length === 0) { - unset($headers[$normalizedKeys['content-length']]); - } else { - $headers[$normalizedKeys['content-length']] = [$length]; - } - } - } - } - } - - return [$stream, $headers]; - } - - /** - * Drains the source stream into the "sink" client option. - * - * @param StreamInterface $source - * @param StreamInterface $sink - * @param string $contentLength Header specifying the amount of - * data to read. - * - * @return StreamInterface - * @throws \RuntimeException when the sink option is invalid. - */ - private function drain( - StreamInterface $source, - StreamInterface $sink, - $contentLength - ) { - // If a content-length header is provided, then stop reading once - // that number of bytes has been read. This can prevent infinitely - // reading from a stream when dealing with servers that do not honor - // Connection: Close headers. - Psr7\copy_to_stream( - $source, - $sink, - (strlen($contentLength) > 0 && (int) $contentLength > 0) ? (int) $contentLength : -1 - ); - - $sink->seek(0); - $source->close(); - - return $sink; - } - - /** - * Create a resource and check to ensure it was created successfully - * - * @param callable $callback Callable that returns stream resource - * - * @return resource - * @throws \RuntimeException on error - */ - private function createResource(callable $callback) - { - $errors = null; - set_error_handler(function ($_, $msg, $file, $line) use (&$errors) { - $errors[] = [ - 'message' => $msg, - 'file' => $file, - 'line' => $line - ]; - return true; - }); - - $resource = $callback(); - restore_error_handler(); - - if (!$resource) { - $message = 'Error creating resource: '; - foreach ($errors as $err) { - foreach ($err as $key => $value) { - $message .= "[$key] $value" . PHP_EOL; - } - } - throw new \RuntimeException(trim($message)); - } - - return $resource; - } - - private function createStream(RequestInterface $request, array $options) - { - static $methods; - if (!$methods) { - $methods = array_flip(get_class_methods(__CLASS__)); - } - - // HTTP/1.1 streams using the PHP stream wrapper require a - // Connection: close header - if ($request->getProtocolVersion() == '1.1' - && !$request->hasHeader('Connection') - ) { - $request = $request->withHeader('Connection', 'close'); - } - - // Ensure SSL is verified by default - if (!isset($options['verify'])) { - $options['verify'] = true; - } - - $params = []; - $context = $this->getDefaultContext($request, $options); - - if (isset($options['on_headers']) && !is_callable($options['on_headers'])) { - throw new \InvalidArgumentException('on_headers must be callable'); - } - - if (!empty($options)) { - foreach ($options as $key => $value) { - $method = "add_{$key}"; - if (isset($methods[$method])) { - $this->{$method}($request, $context, $value, $params); - } - } - } - - if (isset($options['stream_context'])) { - if (!is_array($options['stream_context'])) { - throw new \InvalidArgumentException('stream_context must be an array'); - } - $context = array_replace_recursive( - $context, - $options['stream_context'] - ); - } - - // Microsoft NTLM authentication only supported with curl handler - if (isset($options['auth']) - && is_array($options['auth']) - && isset($options['auth'][2]) - && 'ntlm' == $options['auth'][2] - ) { - - throw new \InvalidArgumentException('Microsoft NTLM authentication only supported with curl handler'); - } - - $uri = $this->resolveHost($request, $options); - - $context = $this->createResource( - function () use ($context, $params) { - return stream_context_create($context, $params); - } - ); - - return $this->createResource( - function () use ($uri, &$http_response_header, $context, $options) { - $resource = fopen((string) $uri, 'r', null, $context); - $this->lastHeaders = $http_response_header; - - if (isset($options['read_timeout'])) { - $readTimeout = $options['read_timeout']; - $sec = (int) $readTimeout; - $usec = ($readTimeout - $sec) * 100000; - stream_set_timeout($resource, $sec, $usec); - } - - return $resource; - } - ); - } - - private function resolveHost(RequestInterface $request, array $options) - { - $uri = $request->getUri(); - - if (isset($options['force_ip_resolve']) && !filter_var($uri->getHost(), FILTER_VALIDATE_IP)) { - if ('v4' === $options['force_ip_resolve']) { - $records = dns_get_record($uri->getHost(), DNS_A); - if (!isset($records[0]['ip'])) { - throw new ConnectException(sprintf("Could not resolve IPv4 address for host '%s'", $uri->getHost()), $request); - } - $uri = $uri->withHost($records[0]['ip']); - } elseif ('v6' === $options['force_ip_resolve']) { - $records = dns_get_record($uri->getHost(), DNS_AAAA); - if (!isset($records[0]['ipv6'])) { - throw new ConnectException(sprintf("Could not resolve IPv6 address for host '%s'", $uri->getHost()), $request); - } - $uri = $uri->withHost('[' . $records[0]['ipv6'] . ']'); - } - } - - return $uri; - } - - private function getDefaultContext(RequestInterface $request) - { - $headers = ''; - foreach ($request->getHeaders() as $name => $value) { - foreach ($value as $val) { - $headers .= "$name: $val\r\n"; - } - } - - $context = [ - 'http' => [ - 'method' => $request->getMethod(), - 'header' => $headers, - 'protocol_version' => $request->getProtocolVersion(), - 'ignore_errors' => true, - 'follow_location' => 0, - ], - ]; - - $body = (string) $request->getBody(); - - if (!empty($body)) { - $context['http']['content'] = $body; - // Prevent the HTTP handler from adding a Content-Type header. - if (!$request->hasHeader('Content-Type')) { - $context['http']['header'] .= "Content-Type:\r\n"; - } - } - - $context['http']['header'] = rtrim($context['http']['header']); - - return $context; - } - - private function add_proxy(RequestInterface $request, &$options, $value, &$params) - { - if (!is_array($value)) { - $options['http']['proxy'] = $value; - } else { - $scheme = $request->getUri()->getScheme(); - if (isset($value[$scheme])) { - if (!isset($value['no']) - || !\GuzzleHttp\is_host_in_noproxy( - $request->getUri()->getHost(), - $value['no'] - ) - ) { - $options['http']['proxy'] = $value[$scheme]; - } - } - } - } - - private function add_timeout(RequestInterface $request, &$options, $value, &$params) - { - if ($value > 0) { - $options['http']['timeout'] = $value; - } - } - - private function add_verify(RequestInterface $request, &$options, $value, &$params) - { - if ($value === true) { - // PHP 5.6 or greater will find the system cert by default. When - // < 5.6, use the Guzzle bundled cacert. - if (PHP_VERSION_ID < 50600) { - $options['ssl']['cafile'] = \GuzzleHttp\default_ca_bundle(); - } - } elseif (is_string($value)) { - $options['ssl']['cafile'] = $value; - if (!file_exists($value)) { - throw new \RuntimeException("SSL CA bundle not found: $value"); - } - } elseif ($value === false) { - $options['ssl']['verify_peer'] = false; - $options['ssl']['verify_peer_name'] = false; - return; - } else { - throw new \InvalidArgumentException('Invalid verify request option'); - } - - $options['ssl']['verify_peer'] = true; - $options['ssl']['verify_peer_name'] = true; - $options['ssl']['allow_self_signed'] = false; - } - - private function add_cert(RequestInterface $request, &$options, $value, &$params) - { - if (is_array($value)) { - $options['ssl']['passphrase'] = $value[1]; - $value = $value[0]; - } - - if (!file_exists($value)) { - throw new \RuntimeException("SSL certificate not found: {$value}"); - } - - $options['ssl']['local_cert'] = $value; - } - - private function add_progress(RequestInterface $request, &$options, $value, &$params) - { - $this->addNotification( - $params, - function ($code, $a, $b, $c, $transferred, $total) use ($value) { - if ($code == STREAM_NOTIFY_PROGRESS) { - $value($total, $transferred, null, null); - } - } - ); - } - - private function add_debug(RequestInterface $request, &$options, $value, &$params) - { - if ($value === false) { - return; - } - - static $map = [ - STREAM_NOTIFY_CONNECT => 'CONNECT', - STREAM_NOTIFY_AUTH_REQUIRED => 'AUTH_REQUIRED', - STREAM_NOTIFY_AUTH_RESULT => 'AUTH_RESULT', - STREAM_NOTIFY_MIME_TYPE_IS => 'MIME_TYPE_IS', - STREAM_NOTIFY_FILE_SIZE_IS => 'FILE_SIZE_IS', - STREAM_NOTIFY_REDIRECTED => 'REDIRECTED', - STREAM_NOTIFY_PROGRESS => 'PROGRESS', - STREAM_NOTIFY_FAILURE => 'FAILURE', - STREAM_NOTIFY_COMPLETED => 'COMPLETED', - STREAM_NOTIFY_RESOLVE => 'RESOLVE', - ]; - static $args = ['severity', 'message', 'message_code', - 'bytes_transferred', 'bytes_max']; - - $value = \GuzzleHttp\debug_resource($value); - $ident = $request->getMethod() . ' ' . $request->getUri()->withFragment(''); - $this->addNotification( - $params, - function () use ($ident, $value, $map, $args) { - $passed = func_get_args(); - $code = array_shift($passed); - fprintf($value, '<%s> [%s] ', $ident, $map[$code]); - foreach (array_filter($passed) as $i => $v) { - fwrite($value, $args[$i] . ': "' . $v . '" '); - } - fwrite($value, "\n"); - } - ); - } - - private function addNotification(array &$params, callable $notify) - { - // Wrap the existing function if needed. - if (!isset($params['notification'])) { - $params['notification'] = $notify; - } else { - $params['notification'] = $this->callArray([ - $params['notification'], - $notify - ]); - } - } - - private function callArray(array $functions) - { - return function () use ($functions) { - $args = func_get_args(); - foreach ($functions as $fn) { - call_user_func_array($fn, $args); - } - }; - } -} diff --git a/guzzle/GuzzleHttp/HandlerStack.php b/guzzle/GuzzleHttp/HandlerStack.php deleted file mode 100644 index a72e38a..0000000 --- a/guzzle/GuzzleHttp/HandlerStack.php +++ /dev/null @@ -1,273 +0,0 @@ -push(Middleware::httpErrors(), 'http_errors'); - $stack->push(Middleware::redirect(), 'allow_redirects'); - $stack->push(Middleware::cookies(), 'cookies'); - $stack->push(Middleware::prepareBody(), 'prepare_body'); - - return $stack; - } - - /** - * @param callable $handler Underlying HTTP handler. - */ - public function __construct(callable $handler = null) - { - $this->handler = $handler; - } - - /** - * Invokes the handler stack as a composed handler - * - * @param RequestInterface $request - * @param array $options - */ - public function __invoke(RequestInterface $request, array $options) - { - $handler = $this->resolve(); - - return $handler($request, $options); - } - - /** - * Dumps a string representation of the stack. - * - * @return string - */ - public function __toString() - { - $depth = 0; - $stack = []; - if ($this->handler) { - $stack[] = "0) Handler: " . $this->debugCallable($this->handler); - } - - $result = ''; - foreach (array_reverse($this->stack) as $tuple) { - $depth++; - $str = "{$depth}) Name: '{$tuple[1]}', "; - $str .= "Function: " . $this->debugCallable($tuple[0]); - $result = "> {$str}\n{$result}"; - $stack[] = $str; - } - - foreach (array_keys($stack) as $k) { - $result .= "< {$stack[$k]}\n"; - } - - return $result; - } - - /** - * Set the HTTP handler that actually returns a promise. - * - * @param callable $handler Accepts a request and array of options and - * returns a Promise. - */ - public function setHandler(callable $handler) - { - $this->handler = $handler; - $this->cached = null; - } - - /** - * Returns true if the builder has a handler. - * - * @return bool - */ - public function hasHandler() - { - return (bool) $this->handler; - } - - /** - * Unshift a middleware to the bottom of the stack. - * - * @param callable $middleware Middleware function - * @param string $name Name to register for this middleware. - */ - public function unshift(callable $middleware, $name = null) - { - array_unshift($this->stack, [$middleware, $name]); - $this->cached = null; - } - - /** - * Push a middleware to the top of the stack. - * - * @param callable $middleware Middleware function - * @param string $name Name to register for this middleware. - */ - public function push(callable $middleware, $name = '') - { - $this->stack[] = [$middleware, $name]; - $this->cached = null; - } - - /** - * Add a middleware before another middleware by name. - * - * @param string $findName Middleware to find - * @param callable $middleware Middleware function - * @param string $withName Name to register for this middleware. - */ - public function before($findName, callable $middleware, $withName = '') - { - $this->splice($findName, $withName, $middleware, true); - } - - /** - * Add a middleware after another middleware by name. - * - * @param string $findName Middleware to find - * @param callable $middleware Middleware function - * @param string $withName Name to register for this middleware. - */ - public function after($findName, callable $middleware, $withName = '') - { - $this->splice($findName, $withName, $middleware, false); - } - - /** - * Remove a middleware by instance or name from the stack. - * - * @param callable|string $remove Middleware to remove by instance or name. - */ - public function remove($remove) - { - $this->cached = null; - $idx = is_callable($remove) ? 0 : 1; - $this->stack = array_values(array_filter( - $this->stack, - function ($tuple) use ($idx, $remove) { - return $tuple[$idx] !== $remove; - } - )); - } - - /** - * Compose the middleware and handler into a single callable function. - * - * @return callable - */ - public function resolve() - { - if (!$this->cached) { - if (!($prev = $this->handler)) { - throw new \LogicException('No handler has been specified'); - } - - foreach (array_reverse($this->stack) as $fn) { - $prev = $fn[0]($prev); - } - - $this->cached = $prev; - } - - return $this->cached; - } - - /** - * @param $name - * @return int - */ - private function findByName($name) - { - foreach ($this->stack as $k => $v) { - if ($v[1] === $name) { - return $k; - } - } - - throw new \InvalidArgumentException("Middleware not found: $name"); - } - - /** - * Splices a function into the middleware list at a specific position. - * - * @param $findName - * @param $withName - * @param callable $middleware - * @param $before - */ - private function splice($findName, $withName, callable $middleware, $before) - { - $this->cached = null; - $idx = $this->findByName($findName); - $tuple = [$middleware, $withName]; - - if ($before) { - if ($idx === 0) { - array_unshift($this->stack, $tuple); - } else { - $replacement = [$tuple, $this->stack[$idx]]; - array_splice($this->stack, $idx, 1, $replacement); - } - } elseif ($idx === count($this->stack) - 1) { - $this->stack[] = $tuple; - } else { - $replacement = [$this->stack[$idx], $tuple]; - array_splice($this->stack, $idx, 1, $replacement); - } - } - - /** - * Provides a debug string for a given callable. - * - * @param array|callable $fn Function to write as a string. - * - * @return string - */ - private function debugCallable($fn) - { - if (is_string($fn)) { - return "callable({$fn})"; - } - - if (is_array($fn)) { - return is_string($fn[0]) - ? "callable({$fn[0]}::{$fn[1]})" - : "callable(['" . get_class($fn[0]) . "', '{$fn[1]}'])"; - } - - return 'callable(' . spl_object_hash($fn) . ')'; - } -} diff --git a/guzzle/GuzzleHttp/MessageFormatter.php b/guzzle/GuzzleHttp/MessageFormatter.php deleted file mode 100644 index 6b090a9..0000000 --- a/guzzle/GuzzleHttp/MessageFormatter.php +++ /dev/null @@ -1,182 +0,0 @@ ->>>>>>>\n{request}\n<<<<<<<<\n{response}\n--------\n{error}"; - const SHORT = '[{ts}] "{method} {target} HTTP/{version}" {code}'; - - /** @var string Template used to format log messages */ - private $template; - - /** - * @param string $template Log message template - */ - public function __construct($template = self::CLF) - { - $this->template = $template ?: self::CLF; - } - - /** - * Returns a formatted message string. - * - * @param RequestInterface $request Request that was sent - * @param ResponseInterface $response Response that was received - * @param \Exception $error Exception that was received - * - * @return string - */ - public function format( - RequestInterface $request, - ResponseInterface $response = null, - \Exception $error = null - ) { - $cache = []; - - return preg_replace_callback( - '/{\s*([A-Za-z_\-\.0-9]+)\s*}/', - function (array $matches) use ($request, $response, $error, &$cache) { - - if (isset($cache[$matches[1]])) { - return $cache[$matches[1]]; - } - - $result = ''; - switch ($matches[1]) { - case 'request': - $result = Psr7\str($request); - break; - case 'response': - $result = $response ? Psr7\str($response) : ''; - break; - case 'req_headers': - $result = trim($request->getMethod() - . ' ' . $request->getRequestTarget()) - . ' HTTP/' . $request->getProtocolVersion() . "\r\n" - . $this->headers($request); - break; - case 'res_headers': - $result = $response ? - sprintf( - 'HTTP/%s %d %s', - $response->getProtocolVersion(), - $response->getStatusCode(), - $response->getReasonPhrase() - ) . "\r\n" . $this->headers($response) - : 'NULL'; - break; - case 'req_body': - $result = $request->getBody(); - break; - case 'res_body': - $result = $response ? $response->getBody() : 'NULL'; - break; - case 'ts': - case 'date_iso_8601': - $result = gmdate('c'); - break; - case 'date_common_log': - $result = date('d/M/Y:H:i:s O'); - break; - case 'method': - $result = $request->getMethod(); - break; - case 'version': - $result = $request->getProtocolVersion(); - break; - case 'uri': - case 'url': - $result = $request->getUri(); - break; - case 'target': - $result = $request->getRequestTarget(); - break; - case 'req_version': - $result = $request->getProtocolVersion(); - break; - case 'res_version': - $result = $response - ? $response->getProtocolVersion() - : 'NULL'; - break; - case 'host': - $result = $request->getHeaderLine('Host'); - break; - case 'hostname': - $result = gethostname(); - break; - case 'code': - $result = $response ? $response->getStatusCode() : 'NULL'; - break; - case 'phrase': - $result = $response ? $response->getReasonPhrase() : 'NULL'; - break; - case 'error': - $result = $error ? $error->getMessage() : 'NULL'; - break; - default: - // handle prefixed dynamic headers - if (strpos($matches[1], 'req_header_') === 0) { - $result = $request->getHeaderLine(substr($matches[1], 11)); - } elseif (strpos($matches[1], 'res_header_') === 0) { - $result = $response - ? $response->getHeaderLine(substr($matches[1], 11)) - : 'NULL'; - } - } - - $cache[$matches[1]] = $result; - return $result; - }, - $this->template - ); - } - - private function headers(MessageInterface $message) - { - $result = ''; - foreach ($message->getHeaders() as $name => $values) { - $result .= $name . ': ' . implode(', ', $values) . "\r\n"; - } - - return trim($result); - } -} diff --git a/guzzle/GuzzleHttp/Middleware.php b/guzzle/GuzzleHttp/Middleware.php deleted file mode 100644 index 9d79bd2..0000000 --- a/guzzle/GuzzleHttp/Middleware.php +++ /dev/null @@ -1,254 +0,0 @@ -withCookieHeader($request); - return $handler($request, $options) - ->then(function ($response) use ($cookieJar, $request) { - $cookieJar->extractCookies($request, $response); - return $response; - } - ); - }; - }; - } - - /** - * Middleware that throws exceptions for 4xx or 5xx responses when the - * "http_error" request option is set to true. - * - * @return callable Returns a function that accepts the next handler. - */ - public static function httpErrors() - { - return function (callable $handler) { - return function ($request, array $options) use ($handler) { - if (empty($options['http_errors'])) { - return $handler($request, $options); - } - return $handler($request, $options)->then( - function (ResponseInterface $response) use ($request, $handler) { - $code = $response->getStatusCode(); - if ($code < 400) { - return $response; - } - throw RequestException::create($request, $response); - } - ); - }; - }; - } - - /** - * Middleware that pushes history data to an ArrayAccess container. - * - * @param array $container Container to hold the history (by reference). - * - * @return callable Returns a function that accepts the next handler. - * @throws \InvalidArgumentException if container is not an array or ArrayAccess. - */ - public static function history(&$container) - { - if (!is_array($container) && !$container instanceof \ArrayAccess) { - throw new \InvalidArgumentException('history container must be an array or object implementing ArrayAccess'); - } - - return function (callable $handler) use (&$container) { - return function ($request, array $options) use ($handler, &$container) { - return $handler($request, $options)->then( - function ($value) use ($request, &$container, $options) { - $container[] = [ - 'request' => $request, - 'response' => $value, - 'error' => null, - 'options' => $options - ]; - return $value; - }, - function ($reason) use ($request, &$container, $options) { - $container[] = [ - 'request' => $request, - 'response' => null, - 'error' => $reason, - 'options' => $options - ]; - return \GuzzleHttp\Promise\rejection_for($reason); - } - ); - }; - }; - } - - /** - * Middleware that invokes a callback before and after sending a request. - * - * The provided listener cannot modify or alter the response. It simply - * "taps" into the chain to be notified before returning the promise. The - * before listener accepts a request and options array, and the after - * listener accepts a request, options array, and response promise. - * - * @param callable $before Function to invoke before forwarding the request. - * @param callable $after Function invoked after forwarding. - * - * @return callable Returns a function that accepts the next handler. - */ - public static function tap(callable $before = null, callable $after = null) - { - return function (callable $handler) use ($before, $after) { - return function ($request, array $options) use ($handler, $before, $after) { - if ($before) { - $before($request, $options); - } - $response = $handler($request, $options); - if ($after) { - $after($request, $options, $response); - } - return $response; - }; - }; - } - - /** - * Middleware that handles request redirects. - * - * @return callable Returns a function that accepts the next handler. - */ - public static function redirect() - { - return function (callable $handler) { - return new RedirectMiddleware($handler); - }; - } - - /** - * Middleware that retries requests based on the boolean result of - * invoking the provided "decider" function. - * - * If no delay function is provided, a simple implementation of exponential - * backoff will be utilized. - * - * @param callable $decider Function that accepts the number of retries, - * a request, [response], and [exception] and - * returns true if the request is to be retried. - * @param callable $delay Function that accepts the number of retries and - * returns the number of milliseconds to delay. - * - * @return callable Returns a function that accepts the next handler. - */ - public static function retry(callable $decider, callable $delay = null) - { - return function (callable $handler) use ($decider, $delay) { - return new RetryMiddleware($decider, $handler, $delay); - }; - } - - /** - * Middleware that logs requests, responses, and errors using a message - * formatter. - * - * @param LoggerInterface $logger Logs messages. - * @param MessageFormatter $formatter Formatter used to create message strings. - * @param string $logLevel Level at which to log requests. - * - * @return callable Returns a function that accepts the next handler. - */ - public static function log(LoggerInterface $logger, MessageFormatter $formatter, $logLevel = LogLevel::INFO) - { - return function (callable $handler) use ($logger, $formatter, $logLevel) { - return function ($request, array $options) use ($handler, $logger, $formatter, $logLevel) { - return $handler($request, $options)->then( - function ($response) use ($logger, $request, $formatter, $logLevel) { - $message = $formatter->format($request, $response); - $logger->log($logLevel, $message); - return $response; - }, - function ($reason) use ($logger, $request, $formatter) { - $response = $reason instanceof RequestException - ? $reason->getResponse() - : null; - $message = $formatter->format($request, $response, $reason); - $logger->notice($message); - return \GuzzleHttp\Promise\rejection_for($reason); - } - ); - }; - }; - } - - /** - * This middleware adds a default content-type if possible, a default - * content-length or transfer-encoding header, and the expect header. - * - * @return callable - */ - public static function prepareBody() - { - return function (callable $handler) { - return new PrepareBodyMiddleware($handler); - }; - } - - /** - * Middleware that applies a map function to the request before passing to - * the next handler. - * - * @param callable $fn Function that accepts a RequestInterface and returns - * a RequestInterface. - * @return callable - */ - public static function mapRequest(callable $fn) - { - return function (callable $handler) use ($fn) { - return function ($request, array $options) use ($handler, $fn) { - return $handler($fn($request), $options); - }; - }; - } - - /** - * Middleware that applies a map function to the resolved promise's - * response. - * - * @param callable $fn Function that accepts a ResponseInterface and - * returns a ResponseInterface. - * @return callable - */ - public static function mapResponse(callable $fn) - { - return function (callable $handler) use ($fn) { - return function ($request, array $options) use ($handler, $fn) { - return $handler($request, $options)->then($fn); - }; - }; - } -} diff --git a/guzzle/GuzzleHttp/Pool.php b/guzzle/GuzzleHttp/Pool.php deleted file mode 100644 index 8f1be33..0000000 --- a/guzzle/GuzzleHttp/Pool.php +++ /dev/null @@ -1,123 +0,0 @@ - $rfn) { - if ($rfn instanceof RequestInterface) { - yield $key => $client->sendAsync($rfn, $opts); - } elseif (is_callable($rfn)) { - yield $key => $rfn($opts); - } else { - throw new \InvalidArgumentException('Each value yielded by ' - . 'the iterator must be a Psr7\Http\Message\RequestInterface ' - . 'or a callable that returns a promise that fulfills ' - . 'with a Psr7\Message\Http\ResponseInterface object.'); - } - } - }; - - $this->each = new EachPromise($requests(), $config); - } - - public function promise() - { - return $this->each->promise(); - } - - /** - * Sends multiple requests concurrently and returns an array of responses - * and exceptions that uses the same ordering as the provided requests. - * - * IMPORTANT: This method keeps every request and response in memory, and - * as such, is NOT recommended when sending a large number or an - * indeterminate number of requests concurrently. - * - * @param ClientInterface $client Client used to send the requests - * @param array|\Iterator $requests Requests to send concurrently. - * @param array $options Passes through the options available in - * {@see GuzzleHttp\Pool::__construct} - * - * @return array Returns an array containing the response or an exception - * in the same order that the requests were sent. - * @throws \InvalidArgumentException if the event format is incorrect. - */ - public static function batch( - ClientInterface $client, - $requests, - array $options = [] - ) { - $res = []; - self::cmpCallback($options, 'fulfilled', $res); - self::cmpCallback($options, 'rejected', $res); - $pool = new static($client, $requests, $options); - $pool->promise()->wait(); - ksort($res); - - return $res; - } - - private static function cmpCallback(array &$options, $name, array &$results) - { - if (!isset($options[$name])) { - $options[$name] = function ($v, $k) use (&$results) { - $results[$k] = $v; - }; - } else { - $currentFn = $options[$name]; - $options[$name] = function ($v, $k) use (&$results, $currentFn) { - $currentFn($v, $k); - $results[$k] = $v; - }; - } - } -} diff --git a/guzzle/GuzzleHttp/PrepareBodyMiddleware.php b/guzzle/GuzzleHttp/PrepareBodyMiddleware.php deleted file mode 100644 index 2eb95f9..0000000 --- a/guzzle/GuzzleHttp/PrepareBodyMiddleware.php +++ /dev/null @@ -1,106 +0,0 @@ -nextHandler = $nextHandler; - } - - /** - * @param RequestInterface $request - * @param array $options - * - * @return PromiseInterface - */ - public function __invoke(RequestInterface $request, array $options) - { - $fn = $this->nextHandler; - - // Don't do anything if the request has no body. - if ($request->getBody()->getSize() === 0) { - return $fn($request, $options); - } - - $modify = []; - - // Add a default content-type if possible. - if (!$request->hasHeader('Content-Type')) { - if ($uri = $request->getBody()->getMetadata('uri')) { - if ($type = Psr7\mimetype_from_filename($uri)) { - $modify['set_headers']['Content-Type'] = $type; - } - } - } - - // Add a default content-length or transfer-encoding header. - if (!$request->hasHeader('Content-Length') - && !$request->hasHeader('Transfer-Encoding') - ) { - $size = $request->getBody()->getSize(); - if ($size !== null) { - $modify['set_headers']['Content-Length'] = $size; - } else { - $modify['set_headers']['Transfer-Encoding'] = 'chunked'; - } - } - - // Add the expect header if needed. - $this->addExpectHeader($request, $options, $modify); - - return $fn(Psr7\modify_request($request, $modify), $options); - } - - private function addExpectHeader( - RequestInterface $request, - array $options, - array &$modify - ) { - // Determine if the Expect header should be used - if ($request->hasHeader('Expect')) { - return; - } - - $expect = isset($options['expect']) ? $options['expect'] : null; - - // Return if disabled or if you're not using HTTP/1.1 or HTTP/2.0 - if ($expect === false || $request->getProtocolVersion() < 1.1) { - return; - } - - // The expect header is unconditionally enabled - if ($expect === true) { - $modify['set_headers']['Expect'] = '100-Continue'; - return; - } - - // By default, send the expect header when the payload is > 1mb - if ($expect === null) { - $expect = 1048576; - } - - // Always add if the body cannot be rewound, the size cannot be - // determined, or the size is greater than the cutoff threshold - $body = $request->getBody(); - $size = $body->getSize(); - - if ($size === null || $size >= (int) $expect || !$body->isSeekable()) { - $modify['set_headers']['Expect'] = '100-Continue'; - } - } -} diff --git a/guzzle/GuzzleHttp/Promise/AggregateException.php b/guzzle/GuzzleHttp/Promise/AggregateException.php deleted file mode 100644 index 6a5690c..0000000 --- a/guzzle/GuzzleHttp/Promise/AggregateException.php +++ /dev/null @@ -1,16 +0,0 @@ -then(function ($v) { echo $v; }); - * - * @param callable $generatorFn Generator function to wrap into a promise. - * - * @return Promise - * @link https://github.com/petkaantonov/bluebird/blob/master/API.md#generators inspiration - */ -final class Coroutine implements PromiseInterface -{ - /** - * @var PromiseInterface|null - */ - private $currentPromise; - - /** - * @var Generator - */ - private $generator; - - /** - * @var Promise - */ - private $result; - - public function __construct(callable $generatorFn) - { - $this->generator = $generatorFn(); - $this->result = new Promise(function () { - while (isset($this->currentPromise)) { - $this->currentPromise->wait(); - } - }); - $this->nextCoroutine($this->generator->current()); - } - - public function then( - callable $onFulfilled = null, - callable $onRejected = null - ) { - return $this->result->then($onFulfilled, $onRejected); - } - - public function otherwise(callable $onRejected) - { - return $this->result->otherwise($onRejected); - } - - public function wait($unwrap = true) - { - return $this->result->wait($unwrap); - } - - public function getState() - { - return $this->result->getState(); - } - - public function resolve($value) - { - $this->result->resolve($value); - } - - public function reject($reason) - { - $this->result->reject($reason); - } - - public function cancel() - { - $this->currentPromise->cancel(); - $this->result->cancel(); - } - - private function nextCoroutine($yielded) - { - $this->currentPromise = promise_for($yielded) - ->then([$this, '_handleSuccess'], [$this, '_handleFailure']); - } - - /** - * @internal - */ - public function _handleSuccess($value) - { - unset($this->currentPromise); - try { - $next = $this->generator->send($value); - if ($this->generator->valid()) { - $this->nextCoroutine($next); - } else { - $this->result->resolve($value); - } - } catch (Exception $exception) { - $this->result->reject($exception); - } catch (Throwable $throwable) { - $this->result->reject($throwable); - } - } - - /** - * @internal - */ - public function _handleFailure($reason) - { - unset($this->currentPromise); - try { - $nextYield = $this->generator->throw(exception_for($reason)); - // The throw was caught, so keep iterating on the coroutine - $this->nextCoroutine($nextYield); - } catch (Exception $exception) { - $this->result->reject($exception); - } catch (Throwable $throwable) { - $this->result->reject($throwable); - } - } -} diff --git a/guzzle/GuzzleHttp/Promise/EachPromise.php b/guzzle/GuzzleHttp/Promise/EachPromise.php deleted file mode 100644 index d0ddf60..0000000 --- a/guzzle/GuzzleHttp/Promise/EachPromise.php +++ /dev/null @@ -1,229 +0,0 @@ -iterable = iter_for($iterable); - - if (isset($config['concurrency'])) { - $this->concurrency = $config['concurrency']; - } - - if (isset($config['fulfilled'])) { - $this->onFulfilled = $config['fulfilled']; - } - - if (isset($config['rejected'])) { - $this->onRejected = $config['rejected']; - } - } - - public function promise() - { - if ($this->aggregate) { - return $this->aggregate; - } - - try { - $this->createPromise(); - $this->iterable->rewind(); - $this->refillPending(); - } catch (\Throwable $e) { - $this->aggregate->reject($e); - } catch (\Exception $e) { - $this->aggregate->reject($e); - } - - return $this->aggregate; - } - - private function createPromise() - { - $this->mutex = false; - $this->aggregate = new Promise(function () { - reset($this->pending); - if (empty($this->pending) && !$this->iterable->valid()) { - $this->aggregate->resolve(null); - return; - } - - // Consume a potentially fluctuating list of promises while - // ensuring that indexes are maintained (precluding array_shift). - while ($promise = current($this->pending)) { - next($this->pending); - $promise->wait(); - if ($this->aggregate->getState() !== PromiseInterface::PENDING) { - return; - } - } - }); - - // Clear the references when the promise is resolved. - $clearFn = function () { - $this->iterable = $this->concurrency = $this->pending = null; - $this->onFulfilled = $this->onRejected = null; - }; - - $this->aggregate->then($clearFn, $clearFn); - } - - private function refillPending() - { - if (!$this->concurrency) { - // Add all pending promises. - while ($this->addPending() && $this->advanceIterator()); - return; - } - - // Add only up to N pending promises. - $concurrency = is_callable($this->concurrency) - ? call_user_func($this->concurrency, count($this->pending)) - : $this->concurrency; - $concurrency = max($concurrency - count($this->pending), 0); - // Concurrency may be set to 0 to disallow new promises. - if (!$concurrency) { - return; - } - // Add the first pending promise. - $this->addPending(); - // Note this is special handling for concurrency=1 so that we do - // not advance the iterator after adding the first promise. This - // helps work around issues with generators that might not have the - // next value to yield until promise callbacks are called. - while (--$concurrency - && $this->advanceIterator() - && $this->addPending()); - } - - private function addPending() - { - if (!$this->iterable || !$this->iterable->valid()) { - return false; - } - - $promise = promise_for($this->iterable->current()); - $idx = $this->iterable->key(); - - $this->pending[$idx] = $promise->then( - function ($value) use ($idx) { - if ($this->onFulfilled) { - call_user_func( - $this->onFulfilled, $value, $idx, $this->aggregate - ); - } - $this->step($idx); - }, - function ($reason) use ($idx) { - if ($this->onRejected) { - call_user_func( - $this->onRejected, $reason, $idx, $this->aggregate - ); - } - $this->step($idx); - } - ); - - return true; - } - - private function advanceIterator() - { - // Place a lock on the iterator so that we ensure to not recurse, - // preventing fatal generator errors. - if ($this->mutex) { - return false; - } - - $this->mutex = true; - - try { - $this->iterable->next(); - $this->mutex = false; - return true; - } catch (\Throwable $e) { - $this->aggregate->reject($e); - $this->mutex = false; - return false; - } catch (\Exception $e) { - $this->aggregate->reject($e); - $this->mutex = false; - return false; - } - } - - private function step($idx) - { - // If the promise was already resolved, then ignore this step. - if ($this->aggregate->getState() !== PromiseInterface::PENDING) { - return; - } - - unset($this->pending[$idx]); - - // Only refill pending promises if we are not locked, preventing the - // EachPromise to recursively invoke the provided iterator, which - // cause a fatal error: "Cannot resume an already running generator" - if ($this->advanceIterator() && !$this->checkIfFinished()) { - // Add more pending promises if possible. - $this->refillPending(); - } - } - - private function checkIfFinished() - { - if (!$this->pending && !$this->iterable->valid()) { - // Resolve the promise if there's nothing left to do. - $this->aggregate->resolve(null); - return true; - } - - return false; - } -} diff --git a/guzzle/GuzzleHttp/Promise/FulfilledPromise.php b/guzzle/GuzzleHttp/Promise/FulfilledPromise.php deleted file mode 100644 index dbbeeb9..0000000 --- a/guzzle/GuzzleHttp/Promise/FulfilledPromise.php +++ /dev/null @@ -1,82 +0,0 @@ -value = $value; - } - - public function then( - callable $onFulfilled = null, - callable $onRejected = null - ) { - // Return itself if there is no onFulfilled function. - if (!$onFulfilled) { - return $this; - } - - $queue = queue(); - $p = new Promise([$queue, 'run']); - $value = $this->value; - $queue->add(static function () use ($p, $value, $onFulfilled) { - if ($p->getState() === self::PENDING) { - try { - $p->resolve($onFulfilled($value)); - } catch (\Throwable $e) { - $p->reject($e); - } catch (\Exception $e) { - $p->reject($e); - } - } - }); - - return $p; - } - - public function otherwise(callable $onRejected) - { - return $this->then(null, $onRejected); - } - - public function wait($unwrap = true, $defaultDelivery = null) - { - return $unwrap ? $this->value : null; - } - - public function getState() - { - return self::FULFILLED; - } - - public function resolve($value) - { - if ($value !== $this->value) { - throw new \LogicException("Cannot resolve a fulfilled promise"); - } - } - - public function reject($reason) - { - throw new \LogicException("Cannot reject a fulfilled promise"); - } - - public function cancel() - { - // pass - } -} diff --git a/guzzle/GuzzleHttp/Promise/Promise.php b/guzzle/GuzzleHttp/Promise/Promise.php deleted file mode 100644 index 844ada0..0000000 --- a/guzzle/GuzzleHttp/Promise/Promise.php +++ /dev/null @@ -1,280 +0,0 @@ -waitFn = $waitFn; - $this->cancelFn = $cancelFn; - } - - public function then( - callable $onFulfilled = null, - callable $onRejected = null - ) { - if ($this->state === self::PENDING) { - $p = new Promise(null, [$this, 'cancel']); - $this->handlers[] = [$p, $onFulfilled, $onRejected]; - $p->waitList = $this->waitList; - $p->waitList[] = $this; - return $p; - } - - // Return a fulfilled promise and immediately invoke any callbacks. - if ($this->state === self::FULFILLED) { - return $onFulfilled - ? promise_for($this->result)->then($onFulfilled) - : promise_for($this->result); - } - - // It's either cancelled or rejected, so return a rejected promise - // and immediately invoke any callbacks. - $rejection = rejection_for($this->result); - return $onRejected ? $rejection->then(null, $onRejected) : $rejection; - } - - public function otherwise(callable $onRejected) - { - return $this->then(null, $onRejected); - } - - public function wait($unwrap = true) - { - $this->waitIfPending(); - - $inner = $this->result instanceof PromiseInterface - ? $this->result->wait($unwrap) - : $this->result; - - if ($unwrap) { - if ($this->result instanceof PromiseInterface - || $this->state === self::FULFILLED - ) { - return $inner; - } else { - // It's rejected so "unwrap" and throw an exception. - throw exception_for($inner); - } - } - } - - public function getState() - { - return $this->state; - } - - public function cancel() - { - if ($this->state !== self::PENDING) { - return; - } - - $this->waitFn = $this->waitList = null; - - if ($this->cancelFn) { - $fn = $this->cancelFn; - $this->cancelFn = null; - try { - $fn(); - } catch (\Throwable $e) { - $this->reject($e); - } catch (\Exception $e) { - $this->reject($e); - } - } - - // Reject the promise only if it wasn't rejected in a then callback. - if ($this->state === self::PENDING) { - $this->reject(new CancellationException('Promise has been cancelled')); - } - } - - public function resolve($value) - { - $this->settle(self::FULFILLED, $value); - } - - public function reject($reason) - { - $this->settle(self::REJECTED, $reason); - } - - private function settle($state, $value) - { - if ($this->state !== self::PENDING) { - // Ignore calls with the same resolution. - if ($state === $this->state && $value === $this->result) { - return; - } - throw $this->state === $state - ? new \LogicException("The promise is already {$state}.") - : new \LogicException("Cannot change a {$this->state} promise to {$state}"); - } - - if ($value === $this) { - throw new \LogicException('Cannot fulfill or reject a promise with itself'); - } - - // Clear out the state of the promise but stash the handlers. - $this->state = $state; - $this->result = $value; - $handlers = $this->handlers; - $this->handlers = null; - $this->waitList = $this->waitFn = null; - $this->cancelFn = null; - - if (!$handlers) { - return; - } - - // If the value was not a settled promise or a thenable, then resolve - // it in the task queue using the correct ID. - if (!method_exists($value, 'then')) { - $id = $state === self::FULFILLED ? 1 : 2; - // It's a success, so resolve the handlers in the queue. - queue()->add(static function () use ($id, $value, $handlers) { - foreach ($handlers as $handler) { - self::callHandler($id, $value, $handler); - } - }); - } elseif ($value instanceof Promise - && $value->getState() === self::PENDING - ) { - // We can just merge our handlers onto the next promise. - $value->handlers = array_merge($value->handlers, $handlers); - } else { - // Resolve the handlers when the forwarded promise is resolved. - $value->then( - static function ($value) use ($handlers) { - foreach ($handlers as $handler) { - self::callHandler(1, $value, $handler); - } - }, - static function ($reason) use ($handlers) { - foreach ($handlers as $handler) { - self::callHandler(2, $reason, $handler); - } - } - ); - } - } - - /** - * Call a stack of handlers using a specific callback index and value. - * - * @param int $index 1 (resolve) or 2 (reject). - * @param mixed $value Value to pass to the callback. - * @param array $handler Array of handler data (promise and callbacks). - * - * @return array Returns the next group to resolve. - */ - private static function callHandler($index, $value, array $handler) - { - /** @var PromiseInterface $promise */ - $promise = $handler[0]; - - // The promise may have been cancelled or resolved before placing - // this thunk in the queue. - if ($promise->getState() !== self::PENDING) { - return; - } - - try { - if (isset($handler[$index])) { - $promise->resolve($handler[$index]($value)); - } elseif ($index === 1) { - // Forward resolution values as-is. - $promise->resolve($value); - } else { - // Forward rejections down the chain. - $promise->reject($value); - } - } catch (\Throwable $reason) { - $promise->reject($reason); - } catch (\Exception $reason) { - $promise->reject($reason); - } - } - - private function waitIfPending() - { - if ($this->state !== self::PENDING) { - return; - } elseif ($this->waitFn) { - $this->invokeWaitFn(); - } elseif ($this->waitList) { - $this->invokeWaitList(); - } else { - // If there's not wait function, then reject the promise. - $this->reject('Cannot wait on a promise that has ' - . 'no internal wait function. You must provide a wait ' - . 'function when constructing the promise to be able to ' - . 'wait on a promise.'); - } - - queue()->run(); - - if ($this->state === self::PENDING) { - $this->reject('Invoking the wait callback did not resolve the promise'); - } - } - - private function invokeWaitFn() - { - try { - $wfn = $this->waitFn; - $this->waitFn = null; - $wfn(true); - } catch (\Exception $reason) { - if ($this->state === self::PENDING) { - // The promise has not been resolved yet, so reject the promise - // with the exception. - $this->reject($reason); - } else { - // The promise was already resolved, so there's a problem in - // the application. - throw $reason; - } - } - } - - private function invokeWaitList() - { - $waitList = $this->waitList; - $this->waitList = null; - - foreach ($waitList as $result) { - while (true) { - $result->waitIfPending(); - - if ($result->result instanceof Promise) { - $result = $result->result; - } else { - if ($result->result instanceof PromiseInterface) { - $result->result->wait(false); - } - break; - } - } - } - } -} diff --git a/guzzle/GuzzleHttp/Promise/PromiseInterface.php b/guzzle/GuzzleHttp/Promise/PromiseInterface.php deleted file mode 100644 index 8f5f4b9..0000000 --- a/guzzle/GuzzleHttp/Promise/PromiseInterface.php +++ /dev/null @@ -1,93 +0,0 @@ -reason = $reason; - } - - public function then( - callable $onFulfilled = null, - callable $onRejected = null - ) { - // If there's no onRejected callback then just return self. - if (!$onRejected) { - return $this; - } - - $queue = queue(); - $reason = $this->reason; - $p = new Promise([$queue, 'run']); - $queue->add(static function () use ($p, $reason, $onRejected) { - if ($p->getState() === self::PENDING) { - try { - // Return a resolved promise if onRejected does not throw. - $p->resolve($onRejected($reason)); - } catch (\Throwable $e) { - // onRejected threw, so return a rejected promise. - $p->reject($e); - } catch (\Exception $e) { - // onRejected threw, so return a rejected promise. - $p->reject($e); - } - } - }); - - return $p; - } - - public function otherwise(callable $onRejected) - { - return $this->then(null, $onRejected); - } - - public function wait($unwrap = true, $defaultDelivery = null) - { - if ($unwrap) { - throw exception_for($this->reason); - } - } - - public function getState() - { - return self::REJECTED; - } - - public function resolve($value) - { - throw new \LogicException("Cannot resolve a rejected promise"); - } - - public function reject($reason) - { - if ($reason !== $this->reason) { - throw new \LogicException("Cannot reject a rejected promise"); - } - } - - public function cancel() - { - // pass - } -} diff --git a/guzzle/GuzzleHttp/Promise/RejectionException.php b/guzzle/GuzzleHttp/Promise/RejectionException.php deleted file mode 100644 index 07c1136..0000000 --- a/guzzle/GuzzleHttp/Promise/RejectionException.php +++ /dev/null @@ -1,47 +0,0 @@ -reason = $reason; - - $message = 'The promise was rejected'; - - if ($description) { - $message .= ' with reason: ' . $description; - } elseif (is_string($reason) - || (is_object($reason) && method_exists($reason, '__toString')) - ) { - $message .= ' with reason: ' . $this->reason; - } elseif ($reason instanceof \JsonSerializable) { - $message .= ' with reason: ' - . json_encode($this->reason, JSON_PRETTY_PRINT); - } - - parent::__construct($message); - } - - /** - * Returns the rejection reason. - * - * @return mixed - */ - public function getReason() - { - return $this->reason; - } -} diff --git a/guzzle/GuzzleHttp/Promise/TaskQueue.php b/guzzle/GuzzleHttp/Promise/TaskQueue.php deleted file mode 100644 index 6e8a2a0..0000000 --- a/guzzle/GuzzleHttp/Promise/TaskQueue.php +++ /dev/null @@ -1,66 +0,0 @@ -run(); - */ -class TaskQueue implements TaskQueueInterface -{ - private $enableShutdown = true; - private $queue = []; - - public function __construct($withShutdown = true) - { - if ($withShutdown) { - register_shutdown_function(function () { - if ($this->enableShutdown) { - // Only run the tasks if an E_ERROR didn't occur. - $err = error_get_last(); - if (!$err || ($err['type'] ^ E_ERROR)) { - $this->run(); - } - } - }); - } - } - - public function isEmpty() - { - return !$this->queue; - } - - public function add(callable $task) - { - $this->queue[] = $task; - } - - public function run() - { - /** @var callable $task */ - while ($task = array_shift($this->queue)) { - $task(); - } - } - - /** - * The task queue will be run and exhausted by default when the process - * exits IFF the exit is not the result of a PHP E_ERROR error. - * - * You can disable running the automatic shutdown of the queue by calling - * this function. If you disable the task queue shutdown process, then you - * MUST either run the task queue (as a result of running your event loop - * or manually using the run() method) or wait on each outstanding promise. - * - * Note: This shutdown will occur before any destructors are triggered. - */ - public function disableShutdown() - { - $this->enableShutdown = false; - } -} diff --git a/guzzle/GuzzleHttp/Promise/TaskQueueInterface.php b/guzzle/GuzzleHttp/Promise/TaskQueueInterface.php deleted file mode 100644 index ac8306e..0000000 --- a/guzzle/GuzzleHttp/Promise/TaskQueueInterface.php +++ /dev/null @@ -1,25 +0,0 @@ - - * while ($eventLoop->isRunning()) { - * GuzzleHttp\Promise\queue()->run(); - * } - * - * - * @param TaskQueueInterface $assign Optionally specify a new queue instance. - * - * @return TaskQueueInterface - */ -function queue(TaskQueueInterface $assign = null) -{ - static $queue; - - if ($assign) { - $queue = $assign; - } elseif (!$queue) { - $queue = new TaskQueue(); - } - - return $queue; -} - -/** - * Adds a function to run in the task queue when it is next `run()` and returns - * a promise that is fulfilled or rejected with the result. - * - * @param callable $task Task function to run. - * - * @return PromiseInterface - */ -function task(callable $task) -{ - $queue = queue(); - $promise = new Promise([$queue, 'run']); - $queue->add(function () use ($task, $promise) { - try { - $promise->resolve($task()); - } catch (\Throwable $e) { - $promise->reject($e); - } catch (\Exception $e) { - $promise->reject($e); - } - }); - - return $promise; -} - -/** - * Creates a promise for a value if the value is not a promise. - * - * @param mixed $value Promise or value. - * - * @return PromiseInterface - */ -function promise_for($value) -{ - if ($value instanceof PromiseInterface) { - return $value; - } - - // Return a Guzzle promise that shadows the given promise. - if (method_exists($value, 'then')) { - $wfn = method_exists($value, 'wait') ? [$value, 'wait'] : null; - $cfn = method_exists($value, 'cancel') ? [$value, 'cancel'] : null; - $promise = new Promise($wfn, $cfn); - $value->then([$promise, 'resolve'], [$promise, 'reject']); - return $promise; - } - - return new FulfilledPromise($value); -} - -/** - * Creates a rejected promise for a reason if the reason is not a promise. If - * the provided reason is a promise, then it is returned as-is. - * - * @param mixed $reason Promise or reason. - * - * @return PromiseInterface - */ -function rejection_for($reason) -{ - if ($reason instanceof PromiseInterface) { - return $reason; - } - - return new RejectedPromise($reason); -} - -/** - * Create an exception for a rejected promise value. - * - * @param mixed $reason - * - * @return \Exception|\Throwable - */ -function exception_for($reason) -{ - return $reason instanceof \Exception || $reason instanceof \Throwable - ? $reason - : new RejectionException($reason); -} - -/** - * Returns an iterator for the given value. - * - * @param mixed $value - * - * @return \Iterator - */ -function iter_for($value) -{ - if ($value instanceof \Iterator) { - return $value; - } elseif (is_array($value)) { - return new \ArrayIterator($value); - } else { - return new \ArrayIterator([$value]); - } -} - -/** - * Synchronously waits on a promise to resolve and returns an inspection state - * array. - * - * Returns a state associative array containing a "state" key mapping to a - * valid promise state. If the state of the promise is "fulfilled", the array - * will contain a "value" key mapping to the fulfilled value of the promise. If - * the promise is rejected, the array will contain a "reason" key mapping to - * the rejection reason of the promise. - * - * @param PromiseInterface $promise Promise or value. - * - * @return array - */ -function inspect(PromiseInterface $promise) -{ - try { - return [ - 'state' => PromiseInterface::FULFILLED, - 'value' => $promise->wait() - ]; - } catch (RejectionException $e) { - return ['state' => PromiseInterface::REJECTED, 'reason' => $e->getReason()]; - } catch (\Throwable $e) { - return ['state' => PromiseInterface::REJECTED, 'reason' => $e]; - } catch (\Exception $e) { - return ['state' => PromiseInterface::REJECTED, 'reason' => $e]; - } -} - -/** - * Waits on all of the provided promises, but does not unwrap rejected promises - * as thrown exception. - * - * Returns an array of inspection state arrays. - * - * @param PromiseInterface[] $promises Traversable of promises to wait upon. - * - * @return array - * @see GuzzleHttp\Promise\inspect for the inspection state array format. - */ -function inspect_all($promises) -{ - $results = []; - foreach ($promises as $key => $promise) { - $results[$key] = inspect($promise); - } - - return $results; -} - -/** - * Waits on all of the provided promises and returns the fulfilled values. - * - * Returns an array that contains the value of each promise (in the same order - * the promises were provided). An exception is thrown if any of the promises - * are rejected. - * - * @param mixed $promises Iterable of PromiseInterface objects to wait on. - * - * @return array - * @throws \Exception on error - * @throws \Throwable on error in PHP >=7 - */ -function unwrap($promises) -{ - $results = []; - foreach ($promises as $key => $promise) { - $results[$key] = $promise->wait(); - } - - return $results; -} - -/** - * Given an array of promises, return a promise that is fulfilled when all the - * items in the array are fulfilled. - * - * The promise's fulfillment value is an array with fulfillment values at - * respective positions to the original array. If any promise in the array - * rejects, the returned promise is rejected with the rejection reason. - * - * @param mixed $promises Promises or values. - * - * @return PromiseInterface - */ -function all($promises) -{ - $results = []; - return each( - $promises, - function ($value, $idx) use (&$results) { - $results[$idx] = $value; - }, - function ($reason, $idx, Promise $aggregate) { - $aggregate->reject($reason); - } - )->then(function () use (&$results) { - ksort($results); - return $results; - }); -} - -/** - * Initiate a competitive race between multiple promises or values (values will - * become immediately fulfilled promises). - * - * When count amount of promises have been fulfilled, the returned promise is - * fulfilled with an array that contains the fulfillment values of the winners - * in order of resolution. - * - * This prommise is rejected with a {@see GuzzleHttp\Promise\AggregateException} - * if the number of fulfilled promises is less than the desired $count. - * - * @param int $count Total number of promises. - * @param mixed $promises Promises or values. - * - * @return PromiseInterface - */ -function some($count, $promises) -{ - $results = []; - $rejections = []; - - return each( - $promises, - function ($value, $idx, PromiseInterface $p) use (&$results, $count) { - if ($p->getState() !== PromiseInterface::PENDING) { - return; - } - $results[$idx] = $value; - if (count($results) >= $count) { - $p->resolve(null); - } - }, - function ($reason) use (&$rejections) { - $rejections[] = $reason; - } - )->then( - function () use (&$results, &$rejections, $count) { - if (count($results) !== $count) { - throw new AggregateException( - 'Not enough promises to fulfill count', - $rejections - ); - } - ksort($results); - return array_values($results); - } - ); -} - -/** - * Like some(), with 1 as count. However, if the promise fulfills, the - * fulfillment value is not an array of 1 but the value directly. - * - * @param mixed $promises Promises or values. - * - * @return PromiseInterface - */ -function any($promises) -{ - return some(1, $promises)->then(function ($values) { return $values[0]; }); -} - -/** - * Returns a promise that is fulfilled when all of the provided promises have - * been fulfilled or rejected. - * - * The returned promise is fulfilled with an array of inspection state arrays. - * - * @param mixed $promises Promises or values. - * - * @return PromiseInterface - * @see GuzzleHttp\Promise\inspect for the inspection state array format. - */ -function settle($promises) -{ - $results = []; - - return each( - $promises, - function ($value, $idx) use (&$results) { - $results[$idx] = ['state' => PromiseInterface::FULFILLED, 'value' => $value]; - }, - function ($reason, $idx) use (&$results) { - $results[$idx] = ['state' => PromiseInterface::REJECTED, 'reason' => $reason]; - } - )->then(function () use (&$results) { - ksort($results); - return $results; - }); -} - -/** - * Given an iterator that yields promises or values, returns a promise that is - * fulfilled with a null value when the iterator has been consumed or the - * aggregate promise has been fulfilled or rejected. - * - * $onFulfilled is a function that accepts the fulfilled value, iterator - * index, and the aggregate promise. The callback can invoke any necessary side - * effects and choose to resolve or reject the aggregate promise if needed. - * - * $onRejected is a function that accepts the rejection reason, iterator - * index, and the aggregate promise. The callback can invoke any necessary side - * effects and choose to resolve or reject the aggregate promise if needed. - * - * @param mixed $iterable Iterator or array to iterate over. - * @param callable $onFulfilled - * @param callable $onRejected - * - * @return PromiseInterface - */ -function each( - $iterable, - callable $onFulfilled = null, - callable $onRejected = null -) { - return (new EachPromise($iterable, [ - 'fulfilled' => $onFulfilled, - 'rejected' => $onRejected - ]))->promise(); -} - -/** - * Like each, but only allows a certain number of outstanding promises at any - * given time. - * - * $concurrency may be an integer or a function that accepts the number of - * pending promises and returns a numeric concurrency limit value to allow for - * dynamic a concurrency size. - * - * @param mixed $iterable - * @param int|callable $concurrency - * @param callable $onFulfilled - * @param callable $onRejected - * - * @return PromiseInterface - */ -function each_limit( - $iterable, - $concurrency, - callable $onFulfilled = null, - callable $onRejected = null -) { - return (new EachPromise($iterable, [ - 'fulfilled' => $onFulfilled, - 'rejected' => $onRejected, - 'concurrency' => $concurrency - ]))->promise(); -} - -/** - * Like each_limit, but ensures that no promise in the given $iterable argument - * is rejected. If any promise is rejected, then the aggregate promise is - * rejected with the encountered rejection. - * - * @param mixed $iterable - * @param int|callable $concurrency - * @param callable $onFulfilled - * - * @return PromiseInterface - */ -function each_limit_all( - $iterable, - $concurrency, - callable $onFulfilled = null -) { - return each_limit( - $iterable, - $concurrency, - $onFulfilled, - function ($reason, $idx, PromiseInterface $aggregate) { - $aggregate->reject($reason); - } - ); -} - -/** - * Returns true if a promise is fulfilled. - * - * @param PromiseInterface $promise - * - * @return bool - */ -function is_fulfilled(PromiseInterface $promise) -{ - return $promise->getState() === PromiseInterface::FULFILLED; -} - -/** - * Returns true if a promise is rejected. - * - * @param PromiseInterface $promise - * - * @return bool - */ -function is_rejected(PromiseInterface $promise) -{ - return $promise->getState() === PromiseInterface::REJECTED; -} - -/** - * Returns true if a promise is fulfilled or rejected. - * - * @param PromiseInterface $promise - * - * @return bool - */ -function is_settled(PromiseInterface $promise) -{ - return $promise->getState() !== PromiseInterface::PENDING; -} - -/** - * @see Coroutine - * - * @param callable $generatorFn - * - * @return PromiseInterface - */ -function coroutine(callable $generatorFn) -{ - return new Coroutine($generatorFn); -} diff --git a/guzzle/GuzzleHttp/Promise/functions_include.php b/guzzle/GuzzleHttp/Promise/functions_include.php deleted file mode 100644 index 34cd171..0000000 --- a/guzzle/GuzzleHttp/Promise/functions_include.php +++ /dev/null @@ -1,6 +0,0 @@ -addStream($stream); - } - } - - public function __toString() - { - try { - $this->rewind(); - return $this->getContents(); - } catch (\Exception $e) { - return ''; - } - } - - /** - * Add a stream to the AppendStream - * - * @param StreamInterface $stream Stream to append. Must be readable. - * - * @throws \InvalidArgumentException if the stream is not readable - */ - public function addStream(StreamInterface $stream) - { - if (!$stream->isReadable()) { - throw new \InvalidArgumentException('Each stream must be readable'); - } - - // The stream is only seekable if all streams are seekable - if (!$stream->isSeekable()) { - $this->seekable = false; - } - - $this->streams[] = $stream; - } - - public function getContents() - { - return copy_to_string($this); - } - - /** - * Closes each attached stream. - * - * {@inheritdoc} - */ - public function close() - { - $this->pos = $this->current = 0; - - foreach ($this->streams as $stream) { - $stream->close(); - } - - $this->streams = []; - } - - /** - * Detaches each attached stream - * - * {@inheritdoc} - */ - public function detach() - { - $this->close(); - $this->detached = true; - } - - public function tell() - { - return $this->pos; - } - - /** - * Tries to calculate the size by adding the size of each stream. - * - * If any of the streams do not return a valid number, then the size of the - * append stream cannot be determined and null is returned. - * - * {@inheritdoc} - */ - public function getSize() - { - $size = 0; - - foreach ($this->streams as $stream) { - $s = $stream->getSize(); - if ($s === null) { - return null; - } - $size += $s; - } - - return $size; - } - - public function eof() - { - return !$this->streams || - ($this->current >= count($this->streams) - 1 && - $this->streams[$this->current]->eof()); - } - - public function rewind() - { - $this->seek(0); - } - - /** - * Attempts to seek to the given position. Only supports SEEK_SET. - * - * {@inheritdoc} - */ - public function seek($offset, $whence = SEEK_SET) - { - if (!$this->seekable) { - throw new \RuntimeException('This AppendStream is not seekable'); - } elseif ($whence !== SEEK_SET) { - throw new \RuntimeException('The AppendStream can only seek with SEEK_SET'); - } - - $this->pos = $this->current = 0; - - // Rewind each stream - foreach ($this->streams as $i => $stream) { - try { - $stream->rewind(); - } catch (\Exception $e) { - throw new \RuntimeException('Unable to seek stream ' - . $i . ' of the AppendStream', 0, $e); - } - } - - // Seek to the actual position by reading from each stream - while ($this->pos < $offset && !$this->eof()) { - $result = $this->read(min(8096, $offset - $this->pos)); - if ($result === '') { - break; - } - } - } - - /** - * Reads from all of the appended streams until the length is met or EOF. - * - * {@inheritdoc} - */ - public function read($length) - { - $buffer = ''; - $total = count($this->streams) - 1; - $remaining = $length; - $progressToNext = false; - - while ($remaining > 0) { - - // Progress to the next stream if needed. - if ($progressToNext || $this->streams[$this->current]->eof()) { - $progressToNext = false; - if ($this->current === $total) { - break; - } - $this->current++; - } - - $result = $this->streams[$this->current]->read($remaining); - - // Using a loose comparison here to match on '', false, and null - if ($result == null) { - $progressToNext = true; - continue; - } - - $buffer .= $result; - $remaining = $length - strlen($buffer); - } - - $this->pos += strlen($buffer); - - return $buffer; - } - - public function isReadable() - { - return true; - } - - public function isWritable() - { - return false; - } - - public function isSeekable() - { - return $this->seekable; - } - - public function write($string) - { - throw new \RuntimeException('Cannot write to an AppendStream'); - } - - public function getMetadata($key = null) - { - return $key ? null : []; - } -} diff --git a/guzzle/GuzzleHttp/Psr7/BufferStream.php b/guzzle/GuzzleHttp/Psr7/BufferStream.php deleted file mode 100644 index af4d4c2..0000000 --- a/guzzle/GuzzleHttp/Psr7/BufferStream.php +++ /dev/null @@ -1,137 +0,0 @@ -hwm = $hwm; - } - - public function __toString() - { - return $this->getContents(); - } - - public function getContents() - { - $buffer = $this->buffer; - $this->buffer = ''; - - return $buffer; - } - - public function close() - { - $this->buffer = ''; - } - - public function detach() - { - $this->close(); - } - - public function getSize() - { - return strlen($this->buffer); - } - - public function isReadable() - { - return true; - } - - public function isWritable() - { - return true; - } - - public function isSeekable() - { - return false; - } - - public function rewind() - { - $this->seek(0); - } - - public function seek($offset, $whence = SEEK_SET) - { - throw new \RuntimeException('Cannot seek a BufferStream'); - } - - public function eof() - { - return strlen($this->buffer) === 0; - } - - public function tell() - { - throw new \RuntimeException('Cannot determine the position of a BufferStream'); - } - - /** - * Reads data from the buffer. - */ - public function read($length) - { - $currentLength = strlen($this->buffer); - - if ($length >= $currentLength) { - // No need to slice the buffer because we don't have enough data. - $result = $this->buffer; - $this->buffer = ''; - } else { - // Slice up the result to provide a subset of the buffer. - $result = substr($this->buffer, 0, $length); - $this->buffer = substr($this->buffer, $length); - } - - return $result; - } - - /** - * Writes data to the buffer. - */ - public function write($string) - { - $this->buffer .= $string; - - // TODO: What should happen here? - if (strlen($this->buffer) >= $this->hwm) { - return false; - } - - return strlen($string); - } - - public function getMetadata($key = null) - { - if ($key == 'hwm') { - return $this->hwm; - } - - return $key ? null : []; - } -} diff --git a/guzzle/GuzzleHttp/Psr7/CachingStream.php b/guzzle/GuzzleHttp/Psr7/CachingStream.php deleted file mode 100644 index ed68f08..0000000 --- a/guzzle/GuzzleHttp/Psr7/CachingStream.php +++ /dev/null @@ -1,138 +0,0 @@ -remoteStream = $stream; - $this->stream = $target ?: new Stream(fopen('php://temp', 'r+')); - } - - public function getSize() - { - return max($this->stream->getSize(), $this->remoteStream->getSize()); - } - - public function rewind() - { - $this->seek(0); - } - - public function seek($offset, $whence = SEEK_SET) - { - if ($whence == SEEK_SET) { - $byte = $offset; - } elseif ($whence == SEEK_CUR) { - $byte = $offset + $this->tell(); - } elseif ($whence == SEEK_END) { - $size = $this->remoteStream->getSize(); - if ($size === null) { - $size = $this->cacheEntireStream(); - } - $byte = $size + $offset; - } else { - throw new \InvalidArgumentException('Invalid whence'); - } - - $diff = $byte - $this->stream->getSize(); - - if ($diff > 0) { - // Read the remoteStream until we have read in at least the amount - // of bytes requested, or we reach the end of the file. - while ($diff > 0 && !$this->remoteStream->eof()) { - $this->read($diff); - $diff = $byte - $this->stream->getSize(); - } - } else { - // We can just do a normal seek since we've already seen this byte. - $this->stream->seek($byte); - } - } - - public function read($length) - { - // Perform a regular read on any previously read data from the buffer - $data = $this->stream->read($length); - $remaining = $length - strlen($data); - - // More data was requested so read from the remote stream - if ($remaining) { - // If data was written to the buffer in a position that would have - // been filled from the remote stream, then we must skip bytes on - // the remote stream to emulate overwriting bytes from that - // position. This mimics the behavior of other PHP stream wrappers. - $remoteData = $this->remoteStream->read( - $remaining + $this->skipReadBytes - ); - - if ($this->skipReadBytes) { - $len = strlen($remoteData); - $remoteData = substr($remoteData, $this->skipReadBytes); - $this->skipReadBytes = max(0, $this->skipReadBytes - $len); - } - - $data .= $remoteData; - $this->stream->write($remoteData); - } - - return $data; - } - - public function write($string) - { - // When appending to the end of the currently read stream, you'll want - // to skip bytes from being read from the remote stream to emulate - // other stream wrappers. Basically replacing bytes of data of a fixed - // length. - $overflow = (strlen($string) + $this->tell()) - $this->remoteStream->tell(); - if ($overflow > 0) { - $this->skipReadBytes += $overflow; - } - - return $this->stream->write($string); - } - - public function eof() - { - return $this->stream->eof() && $this->remoteStream->eof(); - } - - /** - * Close both the remote stream and buffer stream - */ - public function close() - { - $this->remoteStream->close() && $this->stream->close(); - } - - private function cacheEntireStream() - { - $target = new FnStream(['write' => 'strlen']); - copy_to_stream($this, $target); - - return $this->tell(); - } -} diff --git a/guzzle/GuzzleHttp/Psr7/DroppingStream.php b/guzzle/GuzzleHttp/Psr7/DroppingStream.php deleted file mode 100644 index 8935c80..0000000 --- a/guzzle/GuzzleHttp/Psr7/DroppingStream.php +++ /dev/null @@ -1,42 +0,0 @@ -stream = $stream; - $this->maxLength = $maxLength; - } - - public function write($string) - { - $diff = $this->maxLength - $this->stream->getSize(); - - // Begin returning 0 when the underlying stream is too large. - if ($diff <= 0) { - return 0; - } - - // Write the stream or a subset of the stream if needed. - if (strlen($string) < $diff) { - return $this->stream->write($string); - } - - return $this->stream->write(substr($string, 0, $diff)); - } -} diff --git a/guzzle/GuzzleHttp/Psr7/FnStream.php b/guzzle/GuzzleHttp/Psr7/FnStream.php deleted file mode 100644 index cc9b445..0000000 --- a/guzzle/GuzzleHttp/Psr7/FnStream.php +++ /dev/null @@ -1,149 +0,0 @@ -methods = $methods; - - // Create the functions on the class - foreach ($methods as $name => $fn) { - $this->{'_fn_' . $name} = $fn; - } - } - - /** - * Lazily determine which methods are not implemented. - * @throws \BadMethodCallException - */ - public function __get($name) - { - throw new \BadMethodCallException(str_replace('_fn_', '', $name) - . '() is not implemented in the FnStream'); - } - - /** - * The close method is called on the underlying stream only if possible. - */ - public function __destruct() - { - if (isset($this->_fn_close)) { - call_user_func($this->_fn_close); - } - } - - /** - * Adds custom functionality to an underlying stream by intercepting - * specific method calls. - * - * @param StreamInterface $stream Stream to decorate - * @param array $methods Hash of method name to a closure - * - * @return FnStream - */ - public static function decorate(StreamInterface $stream, array $methods) - { - // If any of the required methods were not provided, then simply - // proxy to the decorated stream. - foreach (array_diff(self::$slots, array_keys($methods)) as $diff) { - $methods[$diff] = [$stream, $diff]; - } - - return new self($methods); - } - - public function __toString() - { - return call_user_func($this->_fn___toString); - } - - public function close() - { - return call_user_func($this->_fn_close); - } - - public function detach() - { - return call_user_func($this->_fn_detach); - } - - public function getSize() - { - return call_user_func($this->_fn_getSize); - } - - public function tell() - { - return call_user_func($this->_fn_tell); - } - - public function eof() - { - return call_user_func($this->_fn_eof); - } - - public function isSeekable() - { - return call_user_func($this->_fn_isSeekable); - } - - public function rewind() - { - call_user_func($this->_fn_rewind); - } - - public function seek($offset, $whence = SEEK_SET) - { - call_user_func($this->_fn_seek, $offset, $whence); - } - - public function isWritable() - { - return call_user_func($this->_fn_isWritable); - } - - public function write($string) - { - return call_user_func($this->_fn_write, $string); - } - - public function isReadable() - { - return call_user_func($this->_fn_isReadable); - } - - public function read($length) - { - return call_user_func($this->_fn_read, $length); - } - - public function getContents() - { - return call_user_func($this->_fn_getContents); - } - - public function getMetadata($key = null) - { - return call_user_func($this->_fn_getMetadata, $key); - } -} diff --git a/guzzle/GuzzleHttp/Psr7/InflateStream.php b/guzzle/GuzzleHttp/Psr7/InflateStream.php deleted file mode 100644 index 0051d3f..0000000 --- a/guzzle/GuzzleHttp/Psr7/InflateStream.php +++ /dev/null @@ -1,52 +0,0 @@ -read(10); - $filenameHeaderLength = $this->getLengthOfPossibleFilenameHeader($stream, $header); - // Skip the header, that is 10 + length of filename + 1 (nil) bytes - $stream = new LimitStream($stream, -1, 10 + $filenameHeaderLength); - $resource = StreamWrapper::getResource($stream); - stream_filter_append($resource, 'zlib.inflate', STREAM_FILTER_READ); - $this->stream = new Stream($resource); - } - - /** - * @param StreamInterface $stream - * @param $header - * @return int - */ - private function getLengthOfPossibleFilenameHeader(StreamInterface $stream, $header) - { - $filename_header_length = 0; - - if (substr(bin2hex($header), 6, 2) === '08') { - // we have a filename, read until nil - $filename_header_length = 1; - while ($stream->read(1) !== chr(0)) { - $filename_header_length++; - } - } - - return $filename_header_length; - } -} diff --git a/guzzle/GuzzleHttp/Psr7/LazyOpenStream.php b/guzzle/GuzzleHttp/Psr7/LazyOpenStream.php deleted file mode 100644 index 02cec3a..0000000 --- a/guzzle/GuzzleHttp/Psr7/LazyOpenStream.php +++ /dev/null @@ -1,39 +0,0 @@ -filename = $filename; - $this->mode = $mode; - } - - /** - * Creates the underlying stream lazily when required. - * - * @return StreamInterface - */ - protected function createStream() - { - return stream_for(try_fopen($this->filename, $this->mode)); - } -} diff --git a/guzzle/GuzzleHttp/Psr7/LimitStream.php b/guzzle/GuzzleHttp/Psr7/LimitStream.php deleted file mode 100644 index 3c13d4f..0000000 --- a/guzzle/GuzzleHttp/Psr7/LimitStream.php +++ /dev/null @@ -1,155 +0,0 @@ -stream = $stream; - $this->setLimit($limit); - $this->setOffset($offset); - } - - public function eof() - { - // Always return true if the underlying stream is EOF - if ($this->stream->eof()) { - return true; - } - - // No limit and the underlying stream is not at EOF - if ($this->limit == -1) { - return false; - } - - return $this->stream->tell() >= $this->offset + $this->limit; - } - - /** - * Returns the size of the limited subset of data - * {@inheritdoc} - */ - public function getSize() - { - if (null === ($length = $this->stream->getSize())) { - return null; - } elseif ($this->limit == -1) { - return $length - $this->offset; - } else { - return min($this->limit, $length - $this->offset); - } - } - - /** - * Allow for a bounded seek on the read limited stream - * {@inheritdoc} - */ - public function seek($offset, $whence = SEEK_SET) - { - if ($whence !== SEEK_SET || $offset < 0) { - throw new \RuntimeException(sprintf( - 'Cannot seek to offset % with whence %s', - $offset, - $whence - )); - } - - $offset += $this->offset; - - if ($this->limit !== -1) { - if ($offset > $this->offset + $this->limit) { - $offset = $this->offset + $this->limit; - } - } - - $this->stream->seek($offset); - } - - /** - * Give a relative tell() - * {@inheritdoc} - */ - public function tell() - { - return $this->stream->tell() - $this->offset; - } - - /** - * Set the offset to start limiting from - * - * @param int $offset Offset to seek to and begin byte limiting from - * - * @throws \RuntimeException if the stream cannot be seeked. - */ - public function setOffset($offset) - { - $current = $this->stream->tell(); - - if ($current !== $offset) { - // If the stream cannot seek to the offset position, then read to it - if ($this->stream->isSeekable()) { - $this->stream->seek($offset); - } elseif ($current > $offset) { - throw new \RuntimeException("Could not seek to stream offset $offset"); - } else { - $this->stream->read($offset - $current); - } - } - - $this->offset = $offset; - } - - /** - * Set the limit of bytes that the decorator allows to be read from the - * stream. - * - * @param int $limit Number of bytes to allow to be read from the stream. - * Use -1 for no limit. - */ - public function setLimit($limit) - { - $this->limit = $limit; - } - - public function read($length) - { - if ($this->limit == -1) { - return $this->stream->read($length); - } - - // Check if the current position is less than the total allowed - // bytes + original offset - $remaining = ($this->offset + $this->limit) - $this->stream->tell(); - if ($remaining > 0) { - // Only return the amount of requested data, ensuring that the byte - // limit is not exceeded - return $this->stream->read(min($remaining, $length)); - } - - return ''; - } -} diff --git a/guzzle/GuzzleHttp/Psr7/MessageTrait.php b/guzzle/GuzzleHttp/Psr7/MessageTrait.php deleted file mode 100644 index 1e4da64..0000000 --- a/guzzle/GuzzleHttp/Psr7/MessageTrait.php +++ /dev/null @@ -1,183 +0,0 @@ - array of values */ - private $headers = []; - - /** @var array Map of lowercase header name => original name at registration */ - private $headerNames = []; - - /** @var string */ - private $protocol = '1.1'; - - /** @var StreamInterface */ - private $stream; - - public function getProtocolVersion() - { - return $this->protocol; - } - - public function withProtocolVersion($version) - { - if ($this->protocol === $version) { - return $this; - } - - $new = clone $this; - $new->protocol = $version; - return $new; - } - - public function getHeaders() - { - return $this->headers; - } - - public function hasHeader($header) - { - return isset($this->headerNames[strtolower($header)]); - } - - public function getHeader($header) - { - $header = strtolower($header); - - if (!isset($this->headerNames[$header])) { - return []; - } - - $header = $this->headerNames[$header]; - - return $this->headers[$header]; - } - - public function getHeaderLine($header) - { - return implode(', ', $this->getHeader($header)); - } - - public function withHeader($header, $value) - { - if (!is_array($value)) { - $value = [$value]; - } - - $value = $this->trimHeaderValues($value); - $normalized = strtolower($header); - - $new = clone $this; - if (isset($new->headerNames[$normalized])) { - unset($new->headers[$new->headerNames[$normalized]]); - } - $new->headerNames[$normalized] = $header; - $new->headers[$header] = $value; - - return $new; - } - - public function withAddedHeader($header, $value) - { - if (!is_array($value)) { - $value = [$value]; - } - - $value = $this->trimHeaderValues($value); - $normalized = strtolower($header); - - $new = clone $this; - if (isset($new->headerNames[$normalized])) { - $header = $this->headerNames[$normalized]; - $new->headers[$header] = array_merge($this->headers[$header], $value); - } else { - $new->headerNames[$normalized] = $header; - $new->headers[$header] = $value; - } - - return $new; - } - - public function withoutHeader($header) - { - $normalized = strtolower($header); - - if (!isset($this->headerNames[$normalized])) { - return $this; - } - - $header = $this->headerNames[$normalized]; - - $new = clone $this; - unset($new->headers[$header], $new->headerNames[$normalized]); - - return $new; - } - - public function getBody() - { - if (!$this->stream) { - $this->stream = stream_for(''); - } - - return $this->stream; - } - - public function withBody(StreamInterface $body) - { - if ($body === $this->stream) { - return $this; - } - - $new = clone $this; - $new->stream = $body; - return $new; - } - - private function setHeaders(array $headers) - { - $this->headerNames = $this->headers = []; - foreach ($headers as $header => $value) { - if (!is_array($value)) { - $value = [$value]; - } - - $value = $this->trimHeaderValues($value); - $normalized = strtolower($header); - if (isset($this->headerNames[$normalized])) { - $header = $this->headerNames[$normalized]; - $this->headers[$header] = array_merge($this->headers[$header], $value); - } else { - $this->headerNames[$normalized] = $header; - $this->headers[$header] = $value; - } - } - } - - /** - * Trims whitespace from the header values. - * - * Spaces and tabs ought to be excluded by parsers when extracting the field value from a header field. - * - * header-field = field-name ":" OWS field-value OWS - * OWS = *( SP / HTAB ) - * - * @param string[] $values Header values - * - * @return string[] Trimmed header values - * - * @see https://tools.ietf.org/html/rfc7230#section-3.2.4 - */ - private function trimHeaderValues(array $values) - { - return array_map(function ($value) { - return trim($value, " \t"); - }, $values); - } -} diff --git a/guzzle/GuzzleHttp/Psr7/MultipartStream.php b/guzzle/GuzzleHttp/Psr7/MultipartStream.php deleted file mode 100644 index c0fd584..0000000 --- a/guzzle/GuzzleHttp/Psr7/MultipartStream.php +++ /dev/null @@ -1,153 +0,0 @@ -boundary = $boundary ?: sha1(uniqid('', true)); - $this->stream = $this->createStream($elements); - } - - /** - * Get the boundary - * - * @return string - */ - public function getBoundary() - { - return $this->boundary; - } - - public function isWritable() - { - return false; - } - - /** - * Get the headers needed before transferring the content of a POST file - */ - private function getHeaders(array $headers) - { - $str = ''; - foreach ($headers as $key => $value) { - $str .= "{$key}: {$value}\r\n"; - } - - return "--{$this->boundary}\r\n" . trim($str) . "\r\n\r\n"; - } - - /** - * Create the aggregate stream that will be used to upload the POST data - */ - protected function createStream(array $elements) - { - $stream = new AppendStream(); - - foreach ($elements as $element) { - $this->addElement($stream, $element); - } - - // Add the trailing boundary with CRLF - $stream->addStream(stream_for("--{$this->boundary}--\r\n")); - - return $stream; - } - - private function addElement(AppendStream $stream, array $element) - { - foreach (['contents', 'name'] as $key) { - if (!array_key_exists($key, $element)) { - throw new \InvalidArgumentException("A '{$key}' key is required"); - } - } - - $element['contents'] = stream_for($element['contents']); - - if (empty($element['filename'])) { - $uri = $element['contents']->getMetadata('uri'); - if (substr($uri, 0, 6) !== 'php://') { - $element['filename'] = $uri; - } - } - - list($body, $headers) = $this->createElement( - $element['name'], - $element['contents'], - isset($element['filename']) ? $element['filename'] : null, - isset($element['headers']) ? $element['headers'] : [] - ); - - $stream->addStream(stream_for($this->getHeaders($headers))); - $stream->addStream($body); - $stream->addStream(stream_for("\r\n")); - } - - /** - * @return array - */ - private function createElement($name, StreamInterface $stream, $filename, array $headers) - { - // Set a default content-disposition header if one was no provided - $disposition = $this->getHeader($headers, 'content-disposition'); - if (!$disposition) { - $headers['Content-Disposition'] = ($filename === '0' || $filename) - ? sprintf('form-data; name="%s"; filename="%s"', - $name, - basename($filename)) - : "form-data; name=\"{$name}\""; - } - - // Set a default content-length header if one was no provided - $length = $this->getHeader($headers, 'content-length'); - if (!$length) { - if ($length = $stream->getSize()) { - $headers['Content-Length'] = (string) $length; - } - } - - // Set a default Content-Type if one was not supplied - $type = $this->getHeader($headers, 'content-type'); - if (!$type && ($filename === '0' || $filename)) { - if ($type = mimetype_from_filename($filename)) { - $headers['Content-Type'] = $type; - } - } - - return [$stream, $headers]; - } - - private function getHeader(array $headers, $key) - { - $lowercaseHeader = strtolower($key); - foreach ($headers as $k => $v) { - if (strtolower($k) === $lowercaseHeader) { - return $v; - } - } - - return null; - } -} diff --git a/guzzle/GuzzleHttp/Psr7/NoSeekStream.php b/guzzle/GuzzleHttp/Psr7/NoSeekStream.php deleted file mode 100644 index 2332218..0000000 --- a/guzzle/GuzzleHttp/Psr7/NoSeekStream.php +++ /dev/null @@ -1,22 +0,0 @@ -source = $source; - $this->size = isset($options['size']) ? $options['size'] : null; - $this->metadata = isset($options['metadata']) ? $options['metadata'] : []; - $this->buffer = new BufferStream(); - } - - public function __toString() - { - try { - return copy_to_string($this); - } catch (\Exception $e) { - return ''; - } - } - - public function close() - { - $this->detach(); - } - - public function detach() - { - $this->tellPos = false; - $this->source = null; - } - - public function getSize() - { - return $this->size; - } - - public function tell() - { - return $this->tellPos; - } - - public function eof() - { - return !$this->source; - } - - public function isSeekable() - { - return false; - } - - public function rewind() - { - $this->seek(0); - } - - public function seek($offset, $whence = SEEK_SET) - { - throw new \RuntimeException('Cannot seek a PumpStream'); - } - - public function isWritable() - { - return false; - } - - public function write($string) - { - throw new \RuntimeException('Cannot write to a PumpStream'); - } - - public function isReadable() - { - return true; - } - - public function read($length) - { - $data = $this->buffer->read($length); - $readLen = strlen($data); - $this->tellPos += $readLen; - $remaining = $length - $readLen; - - if ($remaining) { - $this->pump($remaining); - $data .= $this->buffer->read($remaining); - $this->tellPos += strlen($data) - $readLen; - } - - return $data; - } - - public function getContents() - { - $result = ''; - while (!$this->eof()) { - $result .= $this->read(1000000); - } - - return $result; - } - - public function getMetadata($key = null) - { - if (!$key) { - return $this->metadata; - } - - return isset($this->metadata[$key]) ? $this->metadata[$key] : null; - } - - private function pump($length) - { - if ($this->source) { - do { - $data = call_user_func($this->source, $length); - if ($data === false || $data === null) { - $this->source = null; - return; - } - $this->buffer->write($data); - $length -= strlen($data); - } while ($length > 0); - } - } -} diff --git a/guzzle/GuzzleHttp/Psr7/Request.php b/guzzle/GuzzleHttp/Psr7/Request.php deleted file mode 100644 index 0828548..0000000 --- a/guzzle/GuzzleHttp/Psr7/Request.php +++ /dev/null @@ -1,142 +0,0 @@ -method = strtoupper($method); - $this->uri = $uri; - $this->setHeaders($headers); - $this->protocol = $version; - - if (!$this->hasHeader('Host')) { - $this->updateHostFromUri(); - } - - if ($body !== '' && $body !== null) { - $this->stream = stream_for($body); - } - } - - public function getRequestTarget() - { - if ($this->requestTarget !== null) { - return $this->requestTarget; - } - - $target = $this->uri->getPath(); - if ($target == '') { - $target = '/'; - } - if ($this->uri->getQuery() != '') { - $target .= '?' . $this->uri->getQuery(); - } - - return $target; - } - - public function withRequestTarget($requestTarget) - { - if (preg_match('#\s#', $requestTarget)) { - throw new InvalidArgumentException( - 'Invalid request target provided; cannot contain whitespace' - ); - } - - $new = clone $this; - $new->requestTarget = $requestTarget; - return $new; - } - - public function getMethod() - { - return $this->method; - } - - public function withMethod($method) - { - $new = clone $this; - $new->method = strtoupper($method); - return $new; - } - - public function getUri() - { - return $this->uri; - } - - public function withUri(UriInterface $uri, $preserveHost = false) - { - if ($uri === $this->uri) { - return $this; - } - - $new = clone $this; - $new->uri = $uri; - - if (!$preserveHost) { - $new->updateHostFromUri(); - } - - return $new; - } - - private function updateHostFromUri() - { - $host = $this->uri->getHost(); - - if ($host == '') { - return; - } - - if (($port = $this->uri->getPort()) !== null) { - $host .= ':' . $port; - } - - if (isset($this->headerNames['host'])) { - $header = $this->headerNames['host']; - } else { - $header = 'Host'; - $this->headerNames['host'] = 'Host'; - } - // Ensure Host is the first header. - // See: http://tools.ietf.org/html/rfc7230#section-5.4 - $this->headers = [$header => [$host]] + $this->headers; - } -} diff --git a/guzzle/GuzzleHttp/Psr7/Response.php b/guzzle/GuzzleHttp/Psr7/Response.php deleted file mode 100644 index 2830c6c..0000000 --- a/guzzle/GuzzleHttp/Psr7/Response.php +++ /dev/null @@ -1,132 +0,0 @@ - 'Continue', - 101 => 'Switching Protocols', - 102 => 'Processing', - 200 => 'OK', - 201 => 'Created', - 202 => 'Accepted', - 203 => 'Non-Authoritative Information', - 204 => 'No Content', - 205 => 'Reset Content', - 206 => 'Partial Content', - 207 => 'Multi-status', - 208 => 'Already Reported', - 300 => 'Multiple Choices', - 301 => 'Moved Permanently', - 302 => 'Found', - 303 => 'See Other', - 304 => 'Not Modified', - 305 => 'Use Proxy', - 306 => 'Switch Proxy', - 307 => 'Temporary Redirect', - 400 => 'Bad Request', - 401 => 'Unauthorized', - 402 => 'Payment Required', - 403 => 'Forbidden', - 404 => 'Not Found', - 405 => 'Method Not Allowed', - 406 => 'Not Acceptable', - 407 => 'Proxy Authentication Required', - 408 => 'Request Time-out', - 409 => 'Conflict', - 410 => 'Gone', - 411 => 'Length Required', - 412 => 'Precondition Failed', - 413 => 'Request Entity Too Large', - 414 => 'Request-URI Too Large', - 415 => 'Unsupported Media Type', - 416 => 'Requested range not satisfiable', - 417 => 'Expectation Failed', - 418 => 'I\'m a teapot', - 422 => 'Unprocessable Entity', - 423 => 'Locked', - 424 => 'Failed Dependency', - 425 => 'Unordered Collection', - 426 => 'Upgrade Required', - 428 => 'Precondition Required', - 429 => 'Too Many Requests', - 431 => 'Request Header Fields Too Large', - 451 => 'Unavailable For Legal Reasons', - 500 => 'Internal Server Error', - 501 => 'Not Implemented', - 502 => 'Bad Gateway', - 503 => 'Service Unavailable', - 504 => 'Gateway Time-out', - 505 => 'HTTP Version not supported', - 506 => 'Variant Also Negotiates', - 507 => 'Insufficient Storage', - 508 => 'Loop Detected', - 511 => 'Network Authentication Required', - ]; - - /** @var string */ - private $reasonPhrase = ''; - - /** @var int */ - private $statusCode = 200; - - /** - * @param int $status Status code - * @param array $headers Response headers - * @param string|null|resource|StreamInterface $body Response body - * @param string $version Protocol version - * @param string|null $reason Reason phrase (when empty a default will be used based on the status code) - */ - public function __construct( - $status = 200, - array $headers = [], - $body = null, - $version = '1.1', - $reason = null - ) { - $this->statusCode = (int) $status; - - if ($body !== '' && $body !== null) { - $this->stream = stream_for($body); - } - - $this->setHeaders($headers); - if ($reason == '' && isset(self::$phrases[$this->statusCode])) { - $this->reasonPhrase = self::$phrases[$this->statusCode]; - } else { - $this->reasonPhrase = (string) $reason; - } - - $this->protocol = $version; - } - - public function getStatusCode() - { - return $this->statusCode; - } - - public function getReasonPhrase() - { - return $this->reasonPhrase; - } - - public function withStatus($code, $reasonPhrase = '') - { - $new = clone $this; - $new->statusCode = (int) $code; - if ($reasonPhrase == '' && isset(self::$phrases[$new->statusCode])) { - $reasonPhrase = self::$phrases[$new->statusCode]; - } - $new->reasonPhrase = $reasonPhrase; - return $new; - } -} diff --git a/guzzle/GuzzleHttp/Psr7/ServerRequest.php b/guzzle/GuzzleHttp/Psr7/ServerRequest.php deleted file mode 100644 index 575aab8..0000000 --- a/guzzle/GuzzleHttp/Psr7/ServerRequest.php +++ /dev/null @@ -1,358 +0,0 @@ -serverParams = $serverParams; - - parent::__construct($method, $uri, $headers, $body, $version); - } - - /** - * Return an UploadedFile instance array. - * - * @param array $files A array which respect $_FILES structure - * @throws InvalidArgumentException for unrecognized values - * @return array - */ - public static function normalizeFiles(array $files) - { - $normalized = []; - - foreach ($files as $key => $value) { - if ($value instanceof UploadedFileInterface) { - $normalized[$key] = $value; - } elseif (is_array($value) && isset($value['tmp_name'])) { - $normalized[$key] = self::createUploadedFileFromSpec($value); - } elseif (is_array($value)) { - $normalized[$key] = self::normalizeFiles($value); - continue; - } else { - throw new InvalidArgumentException('Invalid value in files specification'); - } - } - - return $normalized; - } - - /** - * Create and return an UploadedFile instance from a $_FILES specification. - * - * If the specification represents an array of values, this method will - * delegate to normalizeNestedFileSpec() and return that return value. - * - * @param array $value $_FILES struct - * @return array|UploadedFileInterface - */ - private static function createUploadedFileFromSpec(array $value) - { - if (is_array($value['tmp_name'])) { - return self::normalizeNestedFileSpec($value); - } - - return new UploadedFile( - $value['tmp_name'], - (int) $value['size'], - (int) $value['error'], - $value['name'], - $value['type'] - ); - } - - /** - * Normalize an array of file specifications. - * - * Loops through all nested files and returns a normalized array of - * UploadedFileInterface instances. - * - * @param array $files - * @return UploadedFileInterface[] - */ - private static function normalizeNestedFileSpec(array $files = []) - { - $normalizedFiles = []; - - foreach (array_keys($files['tmp_name']) as $key) { - $spec = [ - 'tmp_name' => $files['tmp_name'][$key], - 'size' => $files['size'][$key], - 'error' => $files['error'][$key], - 'name' => $files['name'][$key], - 'type' => $files['type'][$key], - ]; - $normalizedFiles[$key] = self::createUploadedFileFromSpec($spec); - } - - return $normalizedFiles; - } - - /** - * Return a ServerRequest populated with superglobals: - * $_GET - * $_POST - * $_COOKIE - * $_FILES - * $_SERVER - * - * @return ServerRequestInterface - */ - public static function fromGlobals() - { - $method = isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : 'GET'; - $headers = function_exists('getallheaders') ? getallheaders() : []; - $uri = self::getUriFromGlobals(); - $body = new LazyOpenStream('php://input', 'r+'); - $protocol = isset($_SERVER['SERVER_PROTOCOL']) ? str_replace('HTTP/', '', $_SERVER['SERVER_PROTOCOL']) : '1.1'; - - $serverRequest = new ServerRequest($method, $uri, $headers, $body, $protocol, $_SERVER); - - return $serverRequest - ->withCookieParams($_COOKIE) - ->withQueryParams($_GET) - ->withParsedBody($_POST) - ->withUploadedFiles(self::normalizeFiles($_FILES)); - } - - /** - * Get a Uri populated with values from $_SERVER. - * - * @return UriInterface - */ - public static function getUriFromGlobals() { - $uri = new Uri(''); - - $uri = $uri->withScheme(!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' ? 'https' : 'http'); - - $hasPort = false; - if (isset($_SERVER['HTTP_HOST'])) { - $hostHeaderParts = explode(':', $_SERVER['HTTP_HOST']); - $uri = $uri->withHost($hostHeaderParts[0]); - if (isset($hostHeaderParts[1])) { - $hasPort = true; - $uri = $uri->withPort($hostHeaderParts[1]); - } - } elseif (isset($_SERVER['SERVER_NAME'])) { - $uri = $uri->withHost($_SERVER['SERVER_NAME']); - } elseif (isset($_SERVER['SERVER_ADDR'])) { - $uri = $uri->withHost($_SERVER['SERVER_ADDR']); - } - - if (!$hasPort && isset($_SERVER['SERVER_PORT'])) { - $uri = $uri->withPort($_SERVER['SERVER_PORT']); - } - - $hasQuery = false; - if (isset($_SERVER['REQUEST_URI'])) { - $requestUriParts = explode('?', $_SERVER['REQUEST_URI']); - $uri = $uri->withPath($requestUriParts[0]); - if (isset($requestUriParts[1])) { - $hasQuery = true; - $uri = $uri->withQuery($requestUriParts[1]); - } - } - - if (!$hasQuery && isset($_SERVER['QUERY_STRING'])) { - $uri = $uri->withQuery($_SERVER['QUERY_STRING']); - } - - return $uri; - } - - - /** - * {@inheritdoc} - */ - public function getServerParams() - { - return $this->serverParams; - } - - /** - * {@inheritdoc} - */ - public function getUploadedFiles() - { - return $this->uploadedFiles; - } - - /** - * {@inheritdoc} - */ - public function withUploadedFiles(array $uploadedFiles) - { - $new = clone $this; - $new->uploadedFiles = $uploadedFiles; - - return $new; - } - - /** - * {@inheritdoc} - */ - public function getCookieParams() - { - return $this->cookieParams; - } - - /** - * {@inheritdoc} - */ - public function withCookieParams(array $cookies) - { - $new = clone $this; - $new->cookieParams = $cookies; - - return $new; - } - - /** - * {@inheritdoc} - */ - public function getQueryParams() - { - return $this->queryParams; - } - - /** - * {@inheritdoc} - */ - public function withQueryParams(array $query) - { - $new = clone $this; - $new->queryParams = $query; - - return $new; - } - - /** - * {@inheritdoc} - */ - public function getParsedBody() - { - return $this->parsedBody; - } - - /** - * {@inheritdoc} - */ - public function withParsedBody($data) - { - $new = clone $this; - $new->parsedBody = $data; - - return $new; - } - - /** - * {@inheritdoc} - */ - public function getAttributes() - { - return $this->attributes; - } - - /** - * {@inheritdoc} - */ - public function getAttribute($attribute, $default = null) - { - if (false === array_key_exists($attribute, $this->attributes)) { - return $default; - } - - return $this->attributes[$attribute]; - } - - /** - * {@inheritdoc} - */ - public function withAttribute($attribute, $value) - { - $new = clone $this; - $new->attributes[$attribute] = $value; - - return $new; - } - - /** - * {@inheritdoc} - */ - public function withoutAttribute($attribute) - { - if (false === array_key_exists($attribute, $this->attributes)) { - return $this; - } - - $new = clone $this; - unset($new->attributes[$attribute]); - - return $new; - } -} diff --git a/guzzle/GuzzleHttp/Psr7/Stream.php b/guzzle/GuzzleHttp/Psr7/Stream.php deleted file mode 100644 index e336628..0000000 --- a/guzzle/GuzzleHttp/Psr7/Stream.php +++ /dev/null @@ -1,257 +0,0 @@ - [ - 'r' => true, 'w+' => true, 'r+' => true, 'x+' => true, 'c+' => true, - 'rb' => true, 'w+b' => true, 'r+b' => true, 'x+b' => true, - 'c+b' => true, 'rt' => true, 'w+t' => true, 'r+t' => true, - 'x+t' => true, 'c+t' => true, 'a+' => true - ], - 'write' => [ - 'w' => true, 'w+' => true, 'rw' => true, 'r+' => true, 'x+' => true, - 'c+' => true, 'wb' => true, 'w+b' => true, 'r+b' => true, - 'x+b' => true, 'c+b' => true, 'w+t' => true, 'r+t' => true, - 'x+t' => true, 'c+t' => true, 'a' => true, 'a+' => true - ] - ]; - - /** - * This constructor accepts an associative array of options. - * - * - size: (int) If a read stream would otherwise have an indeterminate - * size, but the size is known due to foreknowledge, then you can - * provide that size, in bytes. - * - metadata: (array) Any additional metadata to return when the metadata - * of the stream is accessed. - * - * @param resource $stream Stream resource to wrap. - * @param array $options Associative array of options. - * - * @throws \InvalidArgumentException if the stream is not a stream resource - */ - public function __construct($stream, $options = []) - { - if (!is_resource($stream)) { - throw new \InvalidArgumentException('Stream must be a resource'); - } - - if (isset($options['size'])) { - $this->size = $options['size']; - } - - $this->customMetadata = isset($options['metadata']) - ? $options['metadata'] - : []; - - $this->stream = $stream; - $meta = stream_get_meta_data($this->stream); - $this->seekable = $meta['seekable']; - $this->readable = isset(self::$readWriteHash['read'][$meta['mode']]); - $this->writable = isset(self::$readWriteHash['write'][$meta['mode']]); - $this->uri = $this->getMetadata('uri'); - } - - public function __get($name) - { - if ($name == 'stream') { - throw new \RuntimeException('The stream is detached'); - } - - throw new \BadMethodCallException('No value for ' . $name); - } - - /** - * Closes the stream when the destructed - */ - public function __destruct() - { - $this->close(); - } - - public function __toString() - { - try { - $this->seek(0); - return (string) stream_get_contents($this->stream); - } catch (\Exception $e) { - return ''; - } - } - - public function getContents() - { - $contents = stream_get_contents($this->stream); - - if ($contents === false) { - throw new \RuntimeException('Unable to read stream contents'); - } - - return $contents; - } - - public function close() - { - if (isset($this->stream)) { - if (is_resource($this->stream)) { - fclose($this->stream); - } - $this->detach(); - } - } - - public function detach() - { - if (!isset($this->stream)) { - return null; - } - - $result = $this->stream; - unset($this->stream); - $this->size = $this->uri = null; - $this->readable = $this->writable = $this->seekable = false; - - return $result; - } - - public function getSize() - { - if ($this->size !== null) { - return $this->size; - } - - if (!isset($this->stream)) { - return null; - } - - // Clear the stat cache if the stream has a URI - if ($this->uri) { - clearstatcache(true, $this->uri); - } - - $stats = fstat($this->stream); - if (isset($stats['size'])) { - $this->size = $stats['size']; - return $this->size; - } - - return null; - } - - public function isReadable() - { - return $this->readable; - } - - public function isWritable() - { - return $this->writable; - } - - public function isSeekable() - { - return $this->seekable; - } - - public function eof() - { - return !$this->stream || feof($this->stream); - } - - public function tell() - { - $result = ftell($this->stream); - - if ($result === false) { - throw new \RuntimeException('Unable to determine stream position'); - } - - return $result; - } - - public function rewind() - { - $this->seek(0); - } - - public function seek($offset, $whence = SEEK_SET) - { - if (!$this->seekable) { - throw new \RuntimeException('Stream is not seekable'); - } elseif (fseek($this->stream, $offset, $whence) === -1) { - throw new \RuntimeException('Unable to seek to stream position ' - . $offset . ' with whence ' . var_export($whence, true)); - } - } - - public function read($length) - { - if (!$this->readable) { - throw new \RuntimeException('Cannot read from non-readable stream'); - } - if ($length < 0) { - throw new \RuntimeException('Length parameter cannot be negative'); - } - - if (0 === $length) { - return ''; - } - - $string = fread($this->stream, $length); - if (false === $string) { - throw new \RuntimeException('Unable to read from stream'); - } - - return $string; - } - - public function write($string) - { - if (!$this->writable) { - throw new \RuntimeException('Cannot write to a non-writable stream'); - } - - // We can't know the size after writing anything - $this->size = null; - $result = fwrite($this->stream, $string); - - if ($result === false) { - throw new \RuntimeException('Unable to write to stream'); - } - - return $result; - } - - public function getMetadata($key = null) - { - if (!isset($this->stream)) { - return $key ? null : []; - } elseif (!$key) { - return $this->customMetadata + stream_get_meta_data($this->stream); - } elseif (isset($this->customMetadata[$key])) { - return $this->customMetadata[$key]; - } - - $meta = stream_get_meta_data($this->stream); - - return isset($meta[$key]) ? $meta[$key] : null; - } -} diff --git a/guzzle/GuzzleHttp/Psr7/StreamDecoratorTrait.php b/guzzle/GuzzleHttp/Psr7/StreamDecoratorTrait.php deleted file mode 100644 index daec6f5..0000000 --- a/guzzle/GuzzleHttp/Psr7/StreamDecoratorTrait.php +++ /dev/null @@ -1,149 +0,0 @@ -stream = $stream; - } - - /** - * Magic method used to create a new stream if streams are not added in - * the constructor of a decorator (e.g., LazyOpenStream). - * - * @param string $name Name of the property (allows "stream" only). - * - * @return StreamInterface - */ - public function __get($name) - { - if ($name == 'stream') { - $this->stream = $this->createStream(); - return $this->stream; - } - - throw new \UnexpectedValueException("$name not found on class"); - } - - public function __toString() - { - try { - if ($this->isSeekable()) { - $this->seek(0); - } - return $this->getContents(); - } catch (\Exception $e) { - // Really, PHP? https://bugs.php.net/bug.php?id=53648 - trigger_error('StreamDecorator::__toString exception: ' - . (string) $e, E_USER_ERROR); - return ''; - } - } - - public function getContents() - { - return copy_to_string($this); - } - - /** - * Allow decorators to implement custom methods - * - * @param string $method Missing method name - * @param array $args Method arguments - * - * @return mixed - */ - public function __call($method, array $args) - { - $result = call_user_func_array([$this->stream, $method], $args); - - // Always return the wrapped object if the result is a return $this - return $result === $this->stream ? $this : $result; - } - - public function close() - { - $this->stream->close(); - } - - public function getMetadata($key = null) - { - return $this->stream->getMetadata($key); - } - - public function detach() - { - return $this->stream->detach(); - } - - public function getSize() - { - return $this->stream->getSize(); - } - - public function eof() - { - return $this->stream->eof(); - } - - public function tell() - { - return $this->stream->tell(); - } - - public function isReadable() - { - return $this->stream->isReadable(); - } - - public function isWritable() - { - return $this->stream->isWritable(); - } - - public function isSeekable() - { - return $this->stream->isSeekable(); - } - - public function rewind() - { - $this->seek(0); - } - - public function seek($offset, $whence = SEEK_SET) - { - $this->stream->seek($offset, $whence); - } - - public function read($length) - { - return $this->stream->read($length); - } - - public function write($string) - { - return $this->stream->write($string); - } - - /** - * Implement in subclasses to dynamically create streams when requested. - * - * @return StreamInterface - * @throws \BadMethodCallException - */ - protected function createStream() - { - throw new \BadMethodCallException('Not implemented'); - } -} diff --git a/guzzle/GuzzleHttp/Psr7/StreamWrapper.php b/guzzle/GuzzleHttp/Psr7/StreamWrapper.php deleted file mode 100644 index cf7b223..0000000 --- a/guzzle/GuzzleHttp/Psr7/StreamWrapper.php +++ /dev/null @@ -1,121 +0,0 @@ -isReadable()) { - $mode = $stream->isWritable() ? 'r+' : 'r'; - } elseif ($stream->isWritable()) { - $mode = 'w'; - } else { - throw new \InvalidArgumentException('The stream must be readable, ' - . 'writable, or both.'); - } - - return fopen('guzzle://stream', $mode, null, stream_context_create([ - 'guzzle' => ['stream' => $stream] - ])); - } - - /** - * Registers the stream wrapper if needed - */ - public static function register() - { - if (!in_array('guzzle', stream_get_wrappers())) { - stream_wrapper_register('guzzle', __CLASS__); - } - } - - public function stream_open($path, $mode, $options, &$opened_path) - { - $options = stream_context_get_options($this->context); - - if (!isset($options['guzzle']['stream'])) { - return false; - } - - $this->mode = $mode; - $this->stream = $options['guzzle']['stream']; - - return true; - } - - public function stream_read($count) - { - return $this->stream->read($count); - } - - public function stream_write($data) - { - return (int) $this->stream->write($data); - } - - public function stream_tell() - { - return $this->stream->tell(); - } - - public function stream_eof() - { - return $this->stream->eof(); - } - - public function stream_seek($offset, $whence) - { - $this->stream->seek($offset, $whence); - - return true; - } - - public function stream_stat() - { - static $modeMap = [ - 'r' => 33060, - 'r+' => 33206, - 'w' => 33188 - ]; - - return [ - 'dev' => 0, - 'ino' => 0, - 'mode' => $modeMap[$this->mode], - 'nlink' => 0, - 'uid' => 0, - 'gid' => 0, - 'rdev' => 0, - 'size' => $this->stream->getSize() ?: 0, - 'atime' => 0, - 'mtime' => 0, - 'ctime' => 0, - 'blksize' => 0, - 'blocks' => 0 - ]; - } -} diff --git a/guzzle/GuzzleHttp/Psr7/UploadedFile.php b/guzzle/GuzzleHttp/Psr7/UploadedFile.php deleted file mode 100644 index e62bd5c..0000000 --- a/guzzle/GuzzleHttp/Psr7/UploadedFile.php +++ /dev/null @@ -1,316 +0,0 @@ -setError($errorStatus); - $this->setSize($size); - $this->setClientFilename($clientFilename); - $this->setClientMediaType($clientMediaType); - - if ($this->isOk()) { - $this->setStreamOrFile($streamOrFile); - } - } - - /** - * Depending on the value set file or stream variable - * - * @param mixed $streamOrFile - * @throws InvalidArgumentException - */ - private function setStreamOrFile($streamOrFile) - { - if (is_string($streamOrFile)) { - $this->file = $streamOrFile; - } elseif (is_resource($streamOrFile)) { - $this->stream = new Stream($streamOrFile); - } elseif ($streamOrFile instanceof StreamInterface) { - $this->stream = $streamOrFile; - } else { - throw new InvalidArgumentException( - 'Invalid stream or file provided for UploadedFile' - ); - } - } - - /** - * @param int $error - * @throws InvalidArgumentException - */ - private function setError($error) - { - if (false === is_int($error)) { - throw new InvalidArgumentException( - 'Upload file error status must be an integer' - ); - } - - if (false === in_array($error, UploadedFile::$errors)) { - throw new InvalidArgumentException( - 'Invalid error status for UploadedFile' - ); - } - - $this->error = $error; - } - - /** - * @param int $size - * @throws InvalidArgumentException - */ - private function setSize($size) - { - if (false === is_int($size)) { - throw new InvalidArgumentException( - 'Upload file size must be an integer' - ); - } - - $this->size = $size; - } - - /** - * @param mixed $param - * @return boolean - */ - private function isStringOrNull($param) - { - return in_array(gettype($param), ['string', 'NULL']); - } - - /** - * @param mixed $param - * @return boolean - */ - private function isStringNotEmpty($param) - { - return is_string($param) && false === empty($param); - } - - /** - * @param string|null $clientFilename - * @throws InvalidArgumentException - */ - private function setClientFilename($clientFilename) - { - if (false === $this->isStringOrNull($clientFilename)) { - throw new InvalidArgumentException( - 'Upload file client filename must be a string or null' - ); - } - - $this->clientFilename = $clientFilename; - } - - /** - * @param string|null $clientMediaType - * @throws InvalidArgumentException - */ - private function setClientMediaType($clientMediaType) - { - if (false === $this->isStringOrNull($clientMediaType)) { - throw new InvalidArgumentException( - 'Upload file client media type must be a string or null' - ); - } - - $this->clientMediaType = $clientMediaType; - } - - /** - * Return true if there is no upload error - * - * @return boolean - */ - private function isOk() - { - return $this->error === UPLOAD_ERR_OK; - } - - /** - * @return boolean - */ - public function isMoved() - { - return $this->moved; - } - - /** - * @throws RuntimeException if is moved or not ok - */ - private function validateActive() - { - if (false === $this->isOk()) { - throw new RuntimeException('Cannot retrieve stream due to upload error'); - } - - if ($this->isMoved()) { - throw new RuntimeException('Cannot retrieve stream after it has already been moved'); - } - } - - /** - * {@inheritdoc} - * @throws RuntimeException if the upload was not successful. - */ - public function getStream() - { - $this->validateActive(); - - if ($this->stream instanceof StreamInterface) { - return $this->stream; - } - - return new LazyOpenStream($this->file, 'r+'); - } - - /** - * {@inheritdoc} - * - * @see http://php.net/is_uploaded_file - * @see http://php.net/move_uploaded_file - * @param string $targetPath Path to which to move the uploaded file. - * @throws RuntimeException if the upload was not successful. - * @throws InvalidArgumentException if the $path specified is invalid. - * @throws RuntimeException on any error during the move operation, or on - * the second or subsequent call to the method. - */ - public function moveTo($targetPath) - { - $this->validateActive(); - - if (false === $this->isStringNotEmpty($targetPath)) { - throw new InvalidArgumentException( - 'Invalid path provided for move operation; must be a non-empty string' - ); - } - - if ($this->file) { - $this->moved = php_sapi_name() == 'cli' - ? rename($this->file, $targetPath) - : move_uploaded_file($this->file, $targetPath); - } else { - copy_to_stream( - $this->getStream(), - new LazyOpenStream($targetPath, 'w') - ); - - $this->moved = true; - } - - if (false === $this->moved) { - throw new RuntimeException( - sprintf('Uploaded file could not be moved to %s', $targetPath) - ); - } - } - - /** - * {@inheritdoc} - * - * @return int|null The file size in bytes or null if unknown. - */ - public function getSize() - { - return $this->size; - } - - /** - * {@inheritdoc} - * - * @see http://php.net/manual/en/features.file-upload.errors.php - * @return int One of PHP's UPLOAD_ERR_XXX constants. - */ - public function getError() - { - return $this->error; - } - - /** - * {@inheritdoc} - * - * @return string|null The filename sent by the client or null if none - * was provided. - */ - public function getClientFilename() - { - return $this->clientFilename; - } - - /** - * {@inheritdoc} - */ - public function getClientMediaType() - { - return $this->clientMediaType; - } -} diff --git a/guzzle/GuzzleHttp/Psr7/Uri.php b/guzzle/GuzzleHttp/Psr7/Uri.php deleted file mode 100644 index f46c1db..0000000 --- a/guzzle/GuzzleHttp/Psr7/Uri.php +++ /dev/null @@ -1,702 +0,0 @@ - 80, - 'https' => 443, - 'ftp' => 21, - 'gopher' => 70, - 'nntp' => 119, - 'news' => 119, - 'telnet' => 23, - 'tn3270' => 23, - 'imap' => 143, - 'pop' => 110, - 'ldap' => 389, - ]; - - private static $charUnreserved = 'a-zA-Z0-9_\-\.~'; - private static $charSubDelims = '!\$&\'\(\)\*\+,;='; - private static $replaceQuery = ['=' => '%3D', '&' => '%26']; - - /** @var string Uri scheme. */ - private $scheme = ''; - - /** @var string Uri user info. */ - private $userInfo = ''; - - /** @var string Uri host. */ - private $host = ''; - - /** @var int|null Uri port. */ - private $port; - - /** @var string Uri path. */ - private $path = ''; - - /** @var string Uri query string. */ - private $query = ''; - - /** @var string Uri fragment. */ - private $fragment = ''; - - /** - * @param string $uri URI to parse - */ - public function __construct($uri = '') - { - // weak type check to also accept null until we can add scalar type hints - if ($uri != '') { - $parts = parse_url($uri); - if ($parts === false) { - throw new \InvalidArgumentException("Unable to parse URI: $uri"); - } - $this->applyParts($parts); - } - } - - public function __toString() - { - return self::composeComponents( - $this->scheme, - $this->getAuthority(), - $this->path, - $this->query, - $this->fragment - ); - } - - /** - * Composes a URI reference string from its various components. - * - * Usually this method does not need to be called manually but instead is used indirectly via - * `Psr\Http\Message\UriInterface::__toString`. - * - * PSR-7 UriInterface treats an empty component the same as a missing component as - * getQuery(), getFragment() etc. always return a string. This explains the slight - * difference to RFC 3986 Section 5.3. - * - * Another adjustment is that the authority separator is added even when the authority is missing/empty - * for the "file" scheme. This is because PHP stream functions like `file_get_contents` only work with - * `file:///myfile` but not with `file:/myfile` although they are equivalent according to RFC 3986. But - * `file:///` is the more common syntax for the file scheme anyway (Chrome for example redirects to - * that format). - * - * @param string $scheme - * @param string $authority - * @param string $path - * @param string $query - * @param string $fragment - * - * @return string - * - * @link https://tools.ietf.org/html/rfc3986#section-5.3 - */ - public static function composeComponents($scheme, $authority, $path, $query, $fragment) - { - $uri = ''; - - // weak type checks to also accept null until we can add scalar type hints - if ($scheme != '') { - $uri .= $scheme . ':'; - } - - if ($authority != ''|| $scheme === 'file') { - $uri .= '//' . $authority; - } - - $uri .= $path; - - if ($query != '') { - $uri .= '?' . $query; - } - - if ($fragment != '') { - $uri .= '#' . $fragment; - } - - return $uri; - } - - /** - * Whether the URI has the default port of the current scheme. - * - * `Psr\Http\Message\UriInterface::getPort` may return null or the standard port. This method can be used - * independently of the implementation. - * - * @param UriInterface $uri - * - * @return bool - */ - public static function isDefaultPort(UriInterface $uri) - { - return $uri->getPort() === null - || (isset(self::$defaultPorts[$uri->getScheme()]) && $uri->getPort() === self::$defaultPorts[$uri->getScheme()]); - } - - /** - * Whether the URI is absolute, i.e. it has a scheme. - * - * An instance of UriInterface can either be an absolute URI or a relative reference. This method returns true - * if it is the former. An absolute URI has a scheme. A relative reference is used to express a URI relative - * to another URI, the base URI. Relative references can be divided into several forms: - * - network-path references, e.g. '//example.com/path' - * - absolute-path references, e.g. '/path' - * - relative-path references, e.g. 'subpath' - * - * @param UriInterface $uri - * - * @return bool - * @see Uri::isNetworkPathReference - * @see Uri::isAbsolutePathReference - * @see Uri::isRelativePathReference - * @link https://tools.ietf.org/html/rfc3986#section-4 - */ - public static function isAbsolute(UriInterface $uri) - { - return $uri->getScheme() !== ''; - } - - /** - * Whether the URI is a network-path reference. - * - * A relative reference that begins with two slash characters is termed an network-path reference. - * - * @param UriInterface $uri - * - * @return bool - * @link https://tools.ietf.org/html/rfc3986#section-4.2 - */ - public static function isNetworkPathReference(UriInterface $uri) - { - return $uri->getScheme() === '' && $uri->getAuthority() !== ''; - } - - /** - * Whether the URI is a absolute-path reference. - * - * A relative reference that begins with a single slash character is termed an absolute-path reference. - * - * @param UriInterface $uri - * - * @return bool - * @link https://tools.ietf.org/html/rfc3986#section-4.2 - */ - public static function isAbsolutePathReference(UriInterface $uri) - { - return $uri->getScheme() === '' - && $uri->getAuthority() === '' - && isset($uri->getPath()[0]) - && $uri->getPath()[0] === '/'; - } - - /** - * Whether the URI is a relative-path reference. - * - * A relative reference that does not begin with a slash character is termed a relative-path reference. - * - * @param UriInterface $uri - * - * @return bool - * @link https://tools.ietf.org/html/rfc3986#section-4.2 - */ - public static function isRelativePathReference(UriInterface $uri) - { - return $uri->getScheme() === '' - && $uri->getAuthority() === '' - && (!isset($uri->getPath()[0]) || $uri->getPath()[0] !== '/'); - } - - /** - * Whether the URI is a same-document reference. - * - * A same-document reference refers to a URI that is, aside from its fragment - * component, identical to the base URI. When no base URI is given, only an empty - * URI reference (apart from its fragment) is considered a same-document reference. - * - * @param UriInterface $uri The URI to check - * @param UriInterface|null $base An optional base URI to compare against - * - * @return bool - * @link https://tools.ietf.org/html/rfc3986#section-4.4 - */ - public static function isSameDocumentReference(UriInterface $uri, UriInterface $base = null) - { - if ($base !== null) { - $uri = UriResolver::resolve($base, $uri); - - return ($uri->getScheme() === $base->getScheme()) - && ($uri->getAuthority() === $base->getAuthority()) - && ($uri->getPath() === $base->getPath()) - && ($uri->getQuery() === $base->getQuery()); - } - - return $uri->getScheme() === '' && $uri->getAuthority() === '' && $uri->getPath() === '' && $uri->getQuery() === ''; - } - - /** - * Removes dot segments from a path and returns the new path. - * - * @param string $path - * - * @return string - * - * @deprecated since version 1.4. Use UriResolver::removeDotSegments instead. - * @see UriResolver::removeDotSegments - */ - public static function removeDotSegments($path) - { - return UriResolver::removeDotSegments($path); - } - - /** - * Converts the relative URI into a new URI that is resolved against the base URI. - * - * @param UriInterface $base Base URI - * @param string|UriInterface $rel Relative URI - * - * @return UriInterface - * - * @deprecated since version 1.4. Use UriResolver::resolve instead. - * @see UriResolver::resolve - */ - public static function resolve(UriInterface $base, $rel) - { - if (!($rel instanceof UriInterface)) { - $rel = new self($rel); - } - - return UriResolver::resolve($base, $rel); - } - - /** - * Creates a new URI with a specific query string value removed. - * - * Any existing query string values that exactly match the provided key are - * removed. - * - * @param UriInterface $uri URI to use as a base. - * @param string $key Query string key to remove. - * - * @return UriInterface - */ - public static function withoutQueryValue(UriInterface $uri, $key) - { - $current = $uri->getQuery(); - if ($current === '') { - return $uri; - } - - $decodedKey = rawurldecode($key); - $result = array_filter(explode('&', $current), function ($part) use ($decodedKey) { - return rawurldecode(explode('=', $part)[0]) !== $decodedKey; - }); - - return $uri->withQuery(implode('&', $result)); - } - - /** - * Creates a new URI with a specific query string value. - * - * Any existing query string values that exactly match the provided key are - * removed and replaced with the given key value pair. - * - * A value of null will set the query string key without a value, e.g. "key" - * instead of "key=value". - * - * @param UriInterface $uri URI to use as a base. - * @param string $key Key to set. - * @param string|null $value Value to set - * - * @return UriInterface - */ - public static function withQueryValue(UriInterface $uri, $key, $value) - { - $current = $uri->getQuery(); - - if ($current === '') { - $result = []; - } else { - $decodedKey = rawurldecode($key); - $result = array_filter(explode('&', $current), function ($part) use ($decodedKey) { - return rawurldecode(explode('=', $part)[0]) !== $decodedKey; - }); - } - - // Query string separators ("=", "&") within the key or value need to be encoded - // (while preventing double-encoding) before setting the query string. All other - // chars that need percent-encoding will be encoded by withQuery(). - $key = strtr($key, self::$replaceQuery); - - if ($value !== null) { - $result[] = $key . '=' . strtr($value, self::$replaceQuery); - } else { - $result[] = $key; - } - - return $uri->withQuery(implode('&', $result)); - } - - /** - * Creates a URI from a hash of `parse_url` components. - * - * @param array $parts - * - * @return UriInterface - * @link http://php.net/manual/en/function.parse-url.php - * - * @throws \InvalidArgumentException If the components do not form a valid URI. - */ - public static function fromParts(array $parts) - { - $uri = new self(); - $uri->applyParts($parts); - $uri->validateState(); - - return $uri; - } - - public function getScheme() - { - return $this->scheme; - } - - public function getAuthority() - { - $authority = $this->host; - if ($this->userInfo !== '') { - $authority = $this->userInfo . '@' . $authority; - } - - if ($this->port !== null) { - $authority .= ':' . $this->port; - } - - return $authority; - } - - public function getUserInfo() - { - return $this->userInfo; - } - - public function getHost() - { - return $this->host; - } - - public function getPort() - { - return $this->port; - } - - public function getPath() - { - return $this->path; - } - - public function getQuery() - { - return $this->query; - } - - public function getFragment() - { - return $this->fragment; - } - - public function withScheme($scheme) - { - $scheme = $this->filterScheme($scheme); - - if ($this->scheme === $scheme) { - return $this; - } - - $new = clone $this; - $new->scheme = $scheme; - $new->removeDefaultPort(); - $new->validateState(); - - return $new; - } - - public function withUserInfo($user, $password = null) - { - $info = $user; - if ($password != '') { - $info .= ':' . $password; - } - - if ($this->userInfo === $info) { - return $this; - } - - $new = clone $this; - $new->userInfo = $info; - $new->validateState(); - - return $new; - } - - public function withHost($host) - { - $host = $this->filterHost($host); - - if ($this->host === $host) { - return $this; - } - - $new = clone $this; - $new->host = $host; - $new->validateState(); - - return $new; - } - - public function withPort($port) - { - $port = $this->filterPort($port); - - if ($this->port === $port) { - return $this; - } - - $new = clone $this; - $new->port = $port; - $new->removeDefaultPort(); - $new->validateState(); - - return $new; - } - - public function withPath($path) - { - $path = $this->filterPath($path); - - if ($this->path === $path) { - return $this; - } - - $new = clone $this; - $new->path = $path; - $new->validateState(); - - return $new; - } - - public function withQuery($query) - { - $query = $this->filterQueryAndFragment($query); - - if ($this->query === $query) { - return $this; - } - - $new = clone $this; - $new->query = $query; - - return $new; - } - - public function withFragment($fragment) - { - $fragment = $this->filterQueryAndFragment($fragment); - - if ($this->fragment === $fragment) { - return $this; - } - - $new = clone $this; - $new->fragment = $fragment; - - return $new; - } - - /** - * Apply parse_url parts to a URI. - * - * @param array $parts Array of parse_url parts to apply. - */ - private function applyParts(array $parts) - { - $this->scheme = isset($parts['scheme']) - ? $this->filterScheme($parts['scheme']) - : ''; - $this->userInfo = isset($parts['user']) ? $parts['user'] : ''; - $this->host = isset($parts['host']) - ? $this->filterHost($parts['host']) - : ''; - $this->port = isset($parts['port']) - ? $this->filterPort($parts['port']) - : null; - $this->path = isset($parts['path']) - ? $this->filterPath($parts['path']) - : ''; - $this->query = isset($parts['query']) - ? $this->filterQueryAndFragment($parts['query']) - : ''; - $this->fragment = isset($parts['fragment']) - ? $this->filterQueryAndFragment($parts['fragment']) - : ''; - if (isset($parts['pass'])) { - $this->userInfo .= ':' . $parts['pass']; - } - - $this->removeDefaultPort(); - } - - /** - * @param string $scheme - * - * @return string - * - * @throws \InvalidArgumentException If the scheme is invalid. - */ - private function filterScheme($scheme) - { - if (!is_string($scheme)) { - throw new \InvalidArgumentException('Scheme must be a string'); - } - - return strtolower($scheme); - } - - /** - * @param string $host - * - * @return string - * - * @throws \InvalidArgumentException If the host is invalid. - */ - private function filterHost($host) - { - if (!is_string($host)) { - throw new \InvalidArgumentException('Host must be a string'); - } - - return strtolower($host); - } - - /** - * @param int|null $port - * - * @return int|null - * - * @throws \InvalidArgumentException If the port is invalid. - */ - private function filterPort($port) - { - if ($port === null) { - return null; - } - - $port = (int) $port; - if (1 > $port || 0xffff < $port) { - throw new \InvalidArgumentException( - sprintf('Invalid port: %d. Must be between 1 and 65535', $port) - ); - } - - return $port; - } - - private function removeDefaultPort() - { - if ($this->port !== null && self::isDefaultPort($this)) { - $this->port = null; - } - } - - /** - * Filters the path of a URI - * - * @param string $path - * - * @return string - * - * @throws \InvalidArgumentException If the path is invalid. - */ - private function filterPath($path) - { - if (!is_string($path)) { - throw new \InvalidArgumentException('Path must be a string'); - } - - return preg_replace_callback( - '/(?:[^' . self::$charUnreserved . self::$charSubDelims . '%:@\/]++|%(?![A-Fa-f0-9]{2}))/', - [$this, 'rawurlencodeMatchZero'], - $path - ); - } - - /** - * Filters the query string or fragment of a URI. - * - * @param string $str - * - * @return string - * - * @throws \InvalidArgumentException If the query or fragment is invalid. - */ - private function filterQueryAndFragment($str) - { - if (!is_string($str)) { - throw new \InvalidArgumentException('Query and fragment must be a string'); - } - - return preg_replace_callback( - '/(?:[^' . self::$charUnreserved . self::$charSubDelims . '%:@\/\?]++|%(?![A-Fa-f0-9]{2}))/', - [$this, 'rawurlencodeMatchZero'], - $str - ); - } - - private function rawurlencodeMatchZero(array $match) - { - return rawurlencode($match[0]); - } - - private function validateState() - { - if ($this->host === '' && ($this->scheme === 'http' || $this->scheme === 'https')) { - $this->host = self::HTTP_DEFAULT_HOST; - } - - if ($this->getAuthority() === '') { - if (0 === strpos($this->path, '//')) { - throw new \InvalidArgumentException('The path of a URI without an authority must not start with two slashes "//"'); - } - if ($this->scheme === '' && false !== strpos(explode('/', $this->path, 2)[0], ':')) { - throw new \InvalidArgumentException('A relative URI must not have a path beginning with a segment containing a colon'); - } - } elseif (isset($this->path[0]) && $this->path[0] !== '/') { - @trigger_error( - 'The path of a URI with an authority must start with a slash "/" or be empty. Automagically fixing the URI ' . - 'by adding a leading slash to the path is deprecated since version 1.4 and will throw an exception instead.', - E_USER_DEPRECATED - ); - $this->path = '/'. $this->path; - //throw new \InvalidArgumentException('The path of a URI with an authority must start with a slash "/" or be empty'); - } - } -} diff --git a/guzzle/GuzzleHttp/Psr7/UriNormalizer.php b/guzzle/GuzzleHttp/Psr7/UriNormalizer.php deleted file mode 100644 index 384c29e..0000000 --- a/guzzle/GuzzleHttp/Psr7/UriNormalizer.php +++ /dev/null @@ -1,216 +0,0 @@ -getPath() === '' && - ($uri->getScheme() === 'http' || $uri->getScheme() === 'https') - ) { - $uri = $uri->withPath('/'); - } - - if ($flags & self::REMOVE_DEFAULT_HOST && $uri->getScheme() === 'file' && $uri->getHost() === 'localhost') { - $uri = $uri->withHost(''); - } - - if ($flags & self::REMOVE_DEFAULT_PORT && $uri->getPort() !== null && Uri::isDefaultPort($uri)) { - $uri = $uri->withPort(null); - } - - if ($flags & self::REMOVE_DOT_SEGMENTS && !Uri::isRelativePathReference($uri)) { - $uri = $uri->withPath(UriResolver::removeDotSegments($uri->getPath())); - } - - if ($flags & self::REMOVE_DUPLICATE_SLASHES) { - $uri = $uri->withPath(preg_replace('#//++#', '/', $uri->getPath())); - } - - if ($flags & self::SORT_QUERY_PARAMETERS && $uri->getQuery() !== '') { - $queryKeyValues = explode('&', $uri->getQuery()); - sort($queryKeyValues); - $uri = $uri->withQuery(implode('&', $queryKeyValues)); - } - - return $uri; - } - - /** - * Whether two URIs can be considered equivalent. - * - * Both URIs are normalized automatically before comparison with the given $normalizations bitmask. The method also - * accepts relative URI references and returns true when they are equivalent. This of course assumes they will be - * resolved against the same base URI. If this is not the case, determination of equivalence or difference of - * relative references does not mean anything. - * - * @param UriInterface $uri1 An URI to compare - * @param UriInterface $uri2 An URI to compare - * @param int $normalizations A bitmask of normalizations to apply, see constants - * - * @return bool - * @link https://tools.ietf.org/html/rfc3986#section-6.1 - */ - public static function isEquivalent(UriInterface $uri1, UriInterface $uri2, $normalizations = self::PRESERVING_NORMALIZATIONS) - { - return (string) self::normalize($uri1, $normalizations) === (string) self::normalize($uri2, $normalizations); - } - - private static function capitalizePercentEncoding(UriInterface $uri) - { - $regex = '/(?:%[A-Fa-f0-9]{2})++/'; - - $callback = function (array $match) { - return strtoupper($match[0]); - }; - - return - $uri->withPath( - preg_replace_callback($regex, $callback, $uri->getPath()) - )->withQuery( - preg_replace_callback($regex, $callback, $uri->getQuery()) - ); - } - - private static function decodeUnreservedCharacters(UriInterface $uri) - { - $regex = '/%(?:2D|2E|5F|7E|3[0-9]|[46][1-9A-F]|[57][0-9A])/i'; - - $callback = function (array $match) { - return rawurldecode($match[0]); - }; - - return - $uri->withPath( - preg_replace_callback($regex, $callback, $uri->getPath()) - )->withQuery( - preg_replace_callback($regex, $callback, $uri->getQuery()) - ); - } - - private function __construct() - { - // cannot be instantiated - } -} diff --git a/guzzle/GuzzleHttp/Psr7/UriResolver.php b/guzzle/GuzzleHttp/Psr7/UriResolver.php deleted file mode 100644 index c1cb8a2..0000000 --- a/guzzle/GuzzleHttp/Psr7/UriResolver.php +++ /dev/null @@ -1,219 +0,0 @@ -getScheme() != '') { - return $rel->withPath(self::removeDotSegments($rel->getPath())); - } - - if ($rel->getAuthority() != '') { - $targetAuthority = $rel->getAuthority(); - $targetPath = self::removeDotSegments($rel->getPath()); - $targetQuery = $rel->getQuery(); - } else { - $targetAuthority = $base->getAuthority(); - if ($rel->getPath() === '') { - $targetPath = $base->getPath(); - $targetQuery = $rel->getQuery() != '' ? $rel->getQuery() : $base->getQuery(); - } else { - if ($rel->getPath()[0] === '/') { - $targetPath = $rel->getPath(); - } else { - if ($targetAuthority != '' && $base->getPath() === '') { - $targetPath = '/' . $rel->getPath(); - } else { - $lastSlashPos = strrpos($base->getPath(), '/'); - if ($lastSlashPos === false) { - $targetPath = $rel->getPath(); - } else { - $targetPath = substr($base->getPath(), 0, $lastSlashPos + 1) . $rel->getPath(); - } - } - } - $targetPath = self::removeDotSegments($targetPath); - $targetQuery = $rel->getQuery(); - } - } - - return new Uri(Uri::composeComponents( - $base->getScheme(), - $targetAuthority, - $targetPath, - $targetQuery, - $rel->getFragment() - )); - } - - /** - * Returns the target URI as a relative reference from the base URI. - * - * This method is the counterpart to resolve(): - * - * (string) $target === (string) UriResolver::resolve($base, UriResolver::relativize($base, $target)) - * - * One use-case is to use the current request URI as base URI and then generate relative links in your documents - * to reduce the document size or offer self-contained downloadable document archives. - * - * $base = new Uri('http://example.com/a/b/'); - * echo UriResolver::relativize($base, new Uri('http://example.com/a/b/c')); // prints 'c'. - * echo UriResolver::relativize($base, new Uri('http://example.com/a/x/y')); // prints '../x/y'. - * echo UriResolver::relativize($base, new Uri('http://example.com/a/b/?q')); // prints '?q'. - * echo UriResolver::relativize($base, new Uri('http://example.org/a/b/')); // prints '//example.org/a/b/'. - * - * This method also accepts a target that is already relative and will try to relativize it further. Only a - * relative-path reference will be returned as-is. - * - * echo UriResolver::relativize($base, new Uri('/a/b/c')); // prints 'c' as well - * - * @param UriInterface $base Base URI - * @param UriInterface $target Target URI - * - * @return UriInterface The relative URI reference - */ - public static function relativize(UriInterface $base, UriInterface $target) - { - if ($target->getScheme() !== '' && - ($base->getScheme() !== $target->getScheme() || $target->getAuthority() === '' && $base->getAuthority() !== '') - ) { - return $target; - } - - if (Uri::isRelativePathReference($target)) { - // As the target is already highly relative we return it as-is. It would be possible to resolve - // the target with `$target = self::resolve($base, $target);` and then try make it more relative - // by removing a duplicate query. But let's not do that automatically. - return $target; - } - - if ($target->getAuthority() !== '' && $base->getAuthority() !== $target->getAuthority()) { - return $target->withScheme(''); - } - - // We must remove the path before removing the authority because if the path starts with two slashes, the URI - // would turn invalid. And we also cannot set a relative path before removing the authority, as that is also - // invalid. - $emptyPathUri = $target->withScheme('')->withPath('')->withUserInfo('')->withPort(null)->withHost(''); - - if ($base->getPath() !== $target->getPath()) { - return $emptyPathUri->withPath(self::getRelativePath($base, $target)); - } - - if ($base->getQuery() === $target->getQuery()) { - // Only the target fragment is left. And it must be returned even if base and target fragment are the same. - return $emptyPathUri->withQuery(''); - } - - // If the base URI has a query but the target has none, we cannot return an empty path reference as it would - // inherit the base query component when resolving. - if ($target->getQuery() === '') { - $segments = explode('/', $target->getPath()); - $lastSegment = end($segments); - - return $emptyPathUri->withPath($lastSegment === '' ? './' : $lastSegment); - } - - return $emptyPathUri; - } - - private static function getRelativePath(UriInterface $base, UriInterface $target) - { - $sourceSegments = explode('/', $base->getPath()); - $targetSegments = explode('/', $target->getPath()); - array_pop($sourceSegments); - $targetLastSegment = array_pop($targetSegments); - foreach ($sourceSegments as $i => $segment) { - if (isset($targetSegments[$i]) && $segment === $targetSegments[$i]) { - unset($sourceSegments[$i], $targetSegments[$i]); - } else { - break; - } - } - $targetSegments[] = $targetLastSegment; - $relativePath = str_repeat('../', count($sourceSegments)) . implode('/', $targetSegments); - - // A reference to am empty last segment or an empty first sub-segment must be prefixed with "./". - // This also applies to a segment with a colon character (e.g., "file:colon") that cannot be used - // as the first segment of a relative-path reference, as it would be mistaken for a scheme name. - if ('' === $relativePath || false !== strpos(explode('/', $relativePath, 2)[0], ':')) { - $relativePath = "./$relativePath"; - } elseif ('/' === $relativePath[0]) { - if ($base->getAuthority() != '' && $base->getPath() === '') { - // In this case an extra slash is added by resolve() automatically. So we must not add one here. - $relativePath = ".$relativePath"; - } else { - $relativePath = "./$relativePath"; - } - } - - return $relativePath; - } - - private function __construct() - { - // cannot be instantiated - } -} diff --git a/guzzle/GuzzleHttp/Psr7/functions.php b/guzzle/GuzzleHttp/Psr7/functions.php deleted file mode 100644 index e40348d..0000000 --- a/guzzle/GuzzleHttp/Psr7/functions.php +++ /dev/null @@ -1,828 +0,0 @@ -getMethod() . ' ' - . $message->getRequestTarget()) - . ' HTTP/' . $message->getProtocolVersion(); - if (!$message->hasHeader('host')) { - $msg .= "\r\nHost: " . $message->getUri()->getHost(); - } - } elseif ($message instanceof ResponseInterface) { - $msg = 'HTTP/' . $message->getProtocolVersion() . ' ' - . $message->getStatusCode() . ' ' - . $message->getReasonPhrase(); - } else { - throw new \InvalidArgumentException('Unknown message type'); - } - - foreach ($message->getHeaders() as $name => $values) { - $msg .= "\r\n{$name}: " . implode(', ', $values); - } - - return "{$msg}\r\n\r\n" . $message->getBody(); -} - -/** - * Returns a UriInterface for the given value. - * - * This function accepts a string or {@see Psr\Http\Message\UriInterface} and - * returns a UriInterface for the given value. If the value is already a - * `UriInterface`, it is returned as-is. - * - * @param string|UriInterface $uri - * - * @return UriInterface - * @throws \InvalidArgumentException - */ -function uri_for($uri) -{ - if ($uri instanceof UriInterface) { - return $uri; - } elseif (is_string($uri)) { - return new Uri($uri); - } - - throw new \InvalidArgumentException('URI must be a string or UriInterface'); -} - -/** - * Create a new stream based on the input type. - * - * Options is an associative array that can contain the following keys: - * - metadata: Array of custom metadata. - * - size: Size of the stream. - * - * @param resource|string|null|int|float|bool|StreamInterface|callable $resource Entity body data - * @param array $options Additional options - * - * @return Stream - * @throws \InvalidArgumentException if the $resource arg is not valid. - */ -function stream_for($resource = '', array $options = []) -{ - if (is_scalar($resource)) { - $stream = fopen('php://temp', 'r+'); - if ($resource !== '') { - fwrite($stream, $resource); - fseek($stream, 0); - } - return new Stream($stream, $options); - } - - switch (gettype($resource)) { - case 'resource': - return new Stream($resource, $options); - case 'object': - if ($resource instanceof StreamInterface) { - return $resource; - } elseif ($resource instanceof \Iterator) { - return new PumpStream(function () use ($resource) { - if (!$resource->valid()) { - return false; - } - $result = $resource->current(); - $resource->next(); - return $result; - }, $options); - } elseif (method_exists($resource, '__toString')) { - return stream_for((string) $resource, $options); - } - break; - case 'NULL': - return new Stream(fopen('php://temp', 'r+'), $options); - } - - if (is_callable($resource)) { - return new PumpStream($resource, $options); - } - - throw new \InvalidArgumentException('Invalid resource type: ' . gettype($resource)); -} - -/** - * Parse an array of header values containing ";" separated data into an - * array of associative arrays representing the header key value pair - * data of the header. When a parameter does not contain a value, but just - * contains a key, this function will inject a key with a '' string value. - * - * @param string|array $header Header to parse into components. - * - * @return array Returns the parsed header values. - */ -function parse_header($header) -{ - static $trimmed = "\"' \n\t\r"; - $params = $matches = []; - - foreach (normalize_header($header) as $val) { - $part = []; - foreach (preg_split('/;(?=([^"]*"[^"]*")*[^"]*$)/', $val) as $kvp) { - if (preg_match_all('/<[^>]+>|[^=]+/', $kvp, $matches)) { - $m = $matches[0]; - if (isset($m[1])) { - $part[trim($m[0], $trimmed)] = trim($m[1], $trimmed); - } else { - $part[] = trim($m[0], $trimmed); - } - } - } - if ($part) { - $params[] = $part; - } - } - - return $params; -} - -/** - * Converts an array of header values that may contain comma separated - * headers into an array of headers with no comma separated values. - * - * @param string|array $header Header to normalize. - * - * @return array Returns the normalized header field values. - */ -function normalize_header($header) -{ - if (!is_array($header)) { - return array_map('trim', explode(',', $header)); - } - - $result = []; - foreach ($header as $value) { - foreach ((array) $value as $v) { - if (strpos($v, ',') === false) { - $result[] = $v; - continue; - } - foreach (preg_split('/,(?=([^"]*"[^"]*")*[^"]*$)/', $v) as $vv) { - $result[] = trim($vv); - } - } - } - - return $result; -} - -/** - * Clone and modify a request with the given changes. - * - * The changes can be one of: - * - method: (string) Changes the HTTP method. - * - set_headers: (array) Sets the given headers. - * - remove_headers: (array) Remove the given headers. - * - body: (mixed) Sets the given body. - * - uri: (UriInterface) Set the URI. - * - query: (string) Set the query string value of the URI. - * - version: (string) Set the protocol version. - * - * @param RequestInterface $request Request to clone and modify. - * @param array $changes Changes to apply. - * - * @return RequestInterface - */ -function modify_request(RequestInterface $request, array $changes) -{ - if (!$changes) { - return $request; - } - - $headers = $request->getHeaders(); - - if (!isset($changes['uri'])) { - $uri = $request->getUri(); - } else { - // Remove the host header if one is on the URI - if ($host = $changes['uri']->getHost()) { - $changes['set_headers']['Host'] = $host; - - if ($port = $changes['uri']->getPort()) { - $standardPorts = ['http' => 80, 'https' => 443]; - $scheme = $changes['uri']->getScheme(); - if (isset($standardPorts[$scheme]) && $port != $standardPorts[$scheme]) { - $changes['set_headers']['Host'] .= ':'.$port; - } - } - } - $uri = $changes['uri']; - } - - if (!empty($changes['remove_headers'])) { - $headers = _caseless_remove($changes['remove_headers'], $headers); - } - - if (!empty($changes['set_headers'])) { - $headers = _caseless_remove(array_keys($changes['set_headers']), $headers); - $headers = $changes['set_headers'] + $headers; - } - - if (isset($changes['query'])) { - $uri = $uri->withQuery($changes['query']); - } - - if ($request instanceof ServerRequestInterface) { - return new ServerRequest( - isset($changes['method']) ? $changes['method'] : $request->getMethod(), - $uri, - $headers, - isset($changes['body']) ? $changes['body'] : $request->getBody(), - isset($changes['version']) - ? $changes['version'] - : $request->getProtocolVersion(), - $request->getServerParams() - ); - } - - return new Request( - isset($changes['method']) ? $changes['method'] : $request->getMethod(), - $uri, - $headers, - isset($changes['body']) ? $changes['body'] : $request->getBody(), - isset($changes['version']) - ? $changes['version'] - : $request->getProtocolVersion() - ); -} - -/** - * Attempts to rewind a message body and throws an exception on failure. - * - * The body of the message will only be rewound if a call to `tell()` returns a - * value other than `0`. - * - * @param MessageInterface $message Message to rewind - * - * @throws \RuntimeException - */ -function rewind_body(MessageInterface $message) -{ - $body = $message->getBody(); - - if ($body->tell()) { - $body->rewind(); - } -} - -/** - * Safely opens a PHP stream resource using a filename. - * - * When fopen fails, PHP normally raises a warning. This function adds an - * error handler that checks for errors and throws an exception instead. - * - * @param string $filename File to open - * @param string $mode Mode used to open the file - * - * @return resource - * @throws \RuntimeException if the file cannot be opened - */ -function try_fopen($filename, $mode) -{ - $ex = null; - set_error_handler(function () use ($filename, $mode, &$ex) { - $ex = new \RuntimeException(sprintf( - 'Unable to open %s using mode %s: %s', - $filename, - $mode, - func_get_args()[1] - )); - }); - - $handle = fopen($filename, $mode); - restore_error_handler(); - - if ($ex) { - /** @var $ex \RuntimeException */ - throw $ex; - } - - return $handle; -} - -/** - * Copy the contents of a stream into a string until the given number of - * bytes have been read. - * - * @param StreamInterface $stream Stream to read - * @param int $maxLen Maximum number of bytes to read. Pass -1 - * to read the entire stream. - * @return string - * @throws \RuntimeException on error. - */ -function copy_to_string(StreamInterface $stream, $maxLen = -1) -{ - $buffer = ''; - - if ($maxLen === -1) { - while (!$stream->eof()) { - $buf = $stream->read(1048576); - // Using a loose equality here to match on '' and false. - if ($buf == null) { - break; - } - $buffer .= $buf; - } - return $buffer; - } - - $len = 0; - while (!$stream->eof() && $len < $maxLen) { - $buf = $stream->read($maxLen - $len); - // Using a loose equality here to match on '' and false. - if ($buf == null) { - break; - } - $buffer .= $buf; - $len = strlen($buffer); - } - - return $buffer; -} - -/** - * Copy the contents of a stream into another stream until the given number - * of bytes have been read. - * - * @param StreamInterface $source Stream to read from - * @param StreamInterface $dest Stream to write to - * @param int $maxLen Maximum number of bytes to read. Pass -1 - * to read the entire stream. - * - * @throws \RuntimeException on error. - */ -function copy_to_stream( - StreamInterface $source, - StreamInterface $dest, - $maxLen = -1 -) { - $bufferSize = 8192; - - if ($maxLen === -1) { - while (!$source->eof()) { - if (!$dest->write($source->read($bufferSize))) { - break; - } - } - } else { - $remaining = $maxLen; - while ($remaining > 0 && !$source->eof()) { - $buf = $source->read(min($bufferSize, $remaining)); - $len = strlen($buf); - if (!$len) { - break; - } - $remaining -= $len; - $dest->write($buf); - } - } -} - -/** - * Calculate a hash of a Stream - * - * @param StreamInterface $stream Stream to calculate the hash for - * @param string $algo Hash algorithm (e.g. md5, crc32, etc) - * @param bool $rawOutput Whether or not to use raw output - * - * @return string Returns the hash of the stream - * @throws \RuntimeException on error. - */ -function hash( - StreamInterface $stream, - $algo, - $rawOutput = false -) { - $pos = $stream->tell(); - - if ($pos > 0) { - $stream->rewind(); - } - - $ctx = hash_init($algo); - while (!$stream->eof()) { - hash_update($ctx, $stream->read(1048576)); - } - - $out = hash_final($ctx, (bool) $rawOutput); - $stream->seek($pos); - - return $out; -} - -/** - * Read a line from the stream up to the maximum allowed buffer length - * - * @param StreamInterface $stream Stream to read from - * @param int $maxLength Maximum buffer length - * - * @return string|bool - */ -function readline(StreamInterface $stream, $maxLength = null) -{ - $buffer = ''; - $size = 0; - - while (!$stream->eof()) { - // Using a loose equality here to match on '' and false. - if (null == ($byte = $stream->read(1))) { - return $buffer; - } - $buffer .= $byte; - // Break when a new line is found or the max length - 1 is reached - if ($byte === "\n" || ++$size === $maxLength - 1) { - break; - } - } - - return $buffer; -} - -/** - * Parses a request message string into a request object. - * - * @param string $message Request message string. - * - * @return Request - */ -function parse_request($message) -{ - $data = _parse_message($message); - $matches = []; - if (!preg_match('/^[\S]+\s+([a-zA-Z]+:\/\/|\/).*/', $data['start-line'], $matches)) { - throw new \InvalidArgumentException('Invalid request string'); - } - $parts = explode(' ', $data['start-line'], 3); - $version = isset($parts[2]) ? explode('/', $parts[2])[1] : '1.1'; - - $request = new Request( - $parts[0], - $matches[1] === '/' ? _parse_request_uri($parts[1], $data['headers']) : $parts[1], - $data['headers'], - $data['body'], - $version - ); - - return $matches[1] === '/' ? $request : $request->withRequestTarget($parts[1]); -} - -/** - * Parses a response message string into a response object. - * - * @param string $message Response message string. - * - * @return Response - */ -function parse_response($message) -{ - $data = _parse_message($message); - // According to https://tools.ietf.org/html/rfc7230#section-3.1.2 the space - // between status-code and reason-phrase is required. But browsers accept - // responses without space and reason as well. - if (!preg_match('/^HTTP\/.* [0-9]{3}( .*|$)/', $data['start-line'])) { - throw new \InvalidArgumentException('Invalid response string'); - } - $parts = explode(' ', $data['start-line'], 3); - - return new Response( - $parts[1], - $data['headers'], - $data['body'], - explode('/', $parts[0])[1], - isset($parts[2]) ? $parts[2] : null - ); -} - -/** - * Parse a query string into an associative array. - * - * If multiple values are found for the same key, the value of that key - * value pair will become an array. This function does not parse nested - * PHP style arrays into an associative array (e.g., foo[a]=1&foo[b]=2 will - * be parsed into ['foo[a]' => '1', 'foo[b]' => '2']). - * - * @param string $str Query string to parse - * @param bool|string $urlEncoding How the query string is encoded - * - * @return array - */ -function parse_query($str, $urlEncoding = true) -{ - $result = []; - - if ($str === '') { - return $result; - } - - if ($urlEncoding === true) { - $decoder = function ($value) { - return rawurldecode(str_replace('+', ' ', $value)); - }; - } elseif ($urlEncoding == PHP_QUERY_RFC3986) { - $decoder = 'rawurldecode'; - } elseif ($urlEncoding == PHP_QUERY_RFC1738) { - $decoder = 'urldecode'; - } else { - $decoder = function ($str) { return $str; }; - } - - foreach (explode('&', $str) as $kvp) { - $parts = explode('=', $kvp, 2); - $key = $decoder($parts[0]); - $value = isset($parts[1]) ? $decoder($parts[1]) : null; - if (!isset($result[$key])) { - $result[$key] = $value; - } else { - if (!is_array($result[$key])) { - $result[$key] = [$result[$key]]; - } - $result[$key][] = $value; - } - } - - return $result; -} - -/** - * Build a query string from an array of key value pairs. - * - * This function can use the return value of parse_query() to build a query - * string. This function does not modify the provided keys when an array is - * encountered (like http_build_query would). - * - * @param array $params Query string parameters. - * @param int|false $encoding Set to false to not encode, PHP_QUERY_RFC3986 - * to encode using RFC3986, or PHP_QUERY_RFC1738 - * to encode using RFC1738. - * @return string - */ -function build_query(array $params, $encoding = PHP_QUERY_RFC3986) -{ - if (!$params) { - return ''; - } - - if ($encoding === false) { - $encoder = function ($str) { return $str; }; - } elseif ($encoding === PHP_QUERY_RFC3986) { - $encoder = 'rawurlencode'; - } elseif ($encoding === PHP_QUERY_RFC1738) { - $encoder = 'urlencode'; - } else { - throw new \InvalidArgumentException('Invalid type'); - } - - $qs = ''; - foreach ($params as $k => $v) { - $k = $encoder($k); - if (!is_array($v)) { - $qs .= $k; - if ($v !== null) { - $qs .= '=' . $encoder($v); - } - $qs .= '&'; - } else { - foreach ($v as $vv) { - $qs .= $k; - if ($vv !== null) { - $qs .= '=' . $encoder($vv); - } - $qs .= '&'; - } - } - } - - return $qs ? (string) substr($qs, 0, -1) : ''; -} - -/** - * Determines the mimetype of a file by looking at its extension. - * - * @param $filename - * - * @return null|string - */ -function mimetype_from_filename($filename) -{ - return mimetype_from_extension(pathinfo($filename, PATHINFO_EXTENSION)); -} - -/** - * Maps a file extensions to a mimetype. - * - * @param $extension string The file extension. - * - * @return string|null - * @link http://svn.apache.org/repos/asf/httpd/httpd/branches/1.3.x/conf/mime.types - */ -function mimetype_from_extension($extension) -{ - static $mimetypes = [ - '7z' => 'application/x-7z-compressed', - 'aac' => 'audio/x-aac', - 'ai' => 'application/postscript', - 'aif' => 'audio/x-aiff', - 'asc' => 'text/plain', - 'asf' => 'video/x-ms-asf', - 'atom' => 'application/atom+xml', - 'avi' => 'video/x-msvideo', - 'bmp' => 'image/bmp', - 'bz2' => 'application/x-bzip2', - 'cer' => 'application/pkix-cert', - 'crl' => 'application/pkix-crl', - 'crt' => 'application/x-x509-ca-cert', - 'css' => 'text/css', - 'csv' => 'text/csv', - 'cu' => 'application/cu-seeme', - 'deb' => 'application/x-debian-package', - 'doc' => 'application/msword', - 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', - 'dvi' => 'application/x-dvi', - 'eot' => 'application/vnd.ms-fontobject', - 'eps' => 'application/postscript', - 'epub' => 'application/epub+zip', - 'etx' => 'text/x-setext', - 'flac' => 'audio/flac', - 'flv' => 'video/x-flv', - 'gif' => 'image/gif', - 'gz' => 'application/gzip', - 'htm' => 'text/html', - 'html' => 'text/html', - 'ico' => 'image/x-icon', - 'ics' => 'text/calendar', - 'ini' => 'text/plain', - 'iso' => 'application/x-iso9660-image', - 'jar' => 'application/java-archive', - 'jpe' => 'image/jpeg', - 'jpeg' => 'image/jpeg', - 'jpg' => 'image/jpeg', - 'js' => 'text/javascript', - 'json' => 'application/json', - 'latex' => 'application/x-latex', - 'log' => 'text/plain', - 'm4a' => 'audio/mp4', - 'm4v' => 'video/mp4', - 'mid' => 'audio/midi', - 'midi' => 'audio/midi', - 'mov' => 'video/quicktime', - 'mp3' => 'audio/mpeg', - 'mp4' => 'video/mp4', - 'mp4a' => 'audio/mp4', - 'mp4v' => 'video/mp4', - 'mpe' => 'video/mpeg', - 'mpeg' => 'video/mpeg', - 'mpg' => 'video/mpeg', - 'mpg4' => 'video/mp4', - 'oga' => 'audio/ogg', - 'ogg' => 'audio/ogg', - 'ogv' => 'video/ogg', - 'ogx' => 'application/ogg', - 'pbm' => 'image/x-portable-bitmap', - 'pdf' => 'application/pdf', - 'pgm' => 'image/x-portable-graymap', - 'png' => 'image/png', - 'pnm' => 'image/x-portable-anymap', - 'ppm' => 'image/x-portable-pixmap', - 'ppt' => 'application/vnd.ms-powerpoint', - 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation', - 'ps' => 'application/postscript', - 'qt' => 'video/quicktime', - 'rar' => 'application/x-rar-compressed', - 'ras' => 'image/x-cmu-raster', - 'rss' => 'application/rss+xml', - 'rtf' => 'application/rtf', - 'sgm' => 'text/sgml', - 'sgml' => 'text/sgml', - 'svg' => 'image/svg+xml', - 'swf' => 'application/x-shockwave-flash', - 'tar' => 'application/x-tar', - 'tif' => 'image/tiff', - 'tiff' => 'image/tiff', - 'torrent' => 'application/x-bittorrent', - 'ttf' => 'application/x-font-ttf', - 'txt' => 'text/plain', - 'wav' => 'audio/x-wav', - 'webm' => 'video/webm', - 'wma' => 'audio/x-ms-wma', - 'wmv' => 'video/x-ms-wmv', - 'woff' => 'application/x-font-woff', - 'wsdl' => 'application/wsdl+xml', - 'xbm' => 'image/x-xbitmap', - 'xls' => 'application/vnd.ms-excel', - 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', - 'xml' => 'application/xml', - 'xpm' => 'image/x-xpixmap', - 'xwd' => 'image/x-xwindowdump', - 'yaml' => 'text/yaml', - 'yml' => 'text/yaml', - 'zip' => 'application/zip', - ]; - - $extension = strtolower($extension); - - return isset($mimetypes[$extension]) - ? $mimetypes[$extension] - : null; -} - -/** - * Parses an HTTP message into an associative array. - * - * The array contains the "start-line" key containing the start line of - * the message, "headers" key containing an associative array of header - * array values, and a "body" key containing the body of the message. - * - * @param string $message HTTP request or response to parse. - * - * @return array - * @internal - */ -function _parse_message($message) -{ - if (!$message) { - throw new \InvalidArgumentException('Invalid message'); - } - - // Iterate over each line in the message, accounting for line endings - $lines = preg_split('/(\\r?\\n)/', $message, -1, PREG_SPLIT_DELIM_CAPTURE); - $result = ['start-line' => array_shift($lines), 'headers' => [], 'body' => '']; - array_shift($lines); - - for ($i = 0, $totalLines = count($lines); $i < $totalLines; $i += 2) { - $line = $lines[$i]; - // If two line breaks were encountered, then this is the end of body - if (empty($line)) { - if ($i < $totalLines - 1) { - $result['body'] = implode('', array_slice($lines, $i + 2)); - } - break; - } - if (strpos($line, ':')) { - $parts = explode(':', $line, 2); - $key = trim($parts[0]); - $value = isset($parts[1]) ? trim($parts[1]) : ''; - $result['headers'][$key][] = $value; - } - } - - return $result; -} - -/** - * Constructs a URI for an HTTP request message. - * - * @param string $path Path from the start-line - * @param array $headers Array of headers (each value an array). - * - * @return string - * @internal - */ -function _parse_request_uri($path, array $headers) -{ - $hostKey = array_filter(array_keys($headers), function ($k) { - return strtolower($k) === 'host'; - }); - - // If no host is found, then a full URI cannot be constructed. - if (!$hostKey) { - return $path; - } - - $host = $headers[reset($hostKey)][0]; - $scheme = substr($host, -4) === ':443' ? 'https' : 'http'; - - return $scheme . '://' . $host . '/' . ltrim($path, '/'); -} - -/** @internal */ -function _caseless_remove($keys, array $data) -{ - $result = []; - - foreach ($keys as &$key) { - $key = strtolower($key); - } - - foreach ($data as $k => $v) { - if (!in_array(strtolower($k), $keys)) { - $result[$k] = $v; - } - } - - return $result; -} diff --git a/guzzle/GuzzleHttp/Psr7/functions_include.php b/guzzle/GuzzleHttp/Psr7/functions_include.php deleted file mode 100644 index 96a4a83..0000000 --- a/guzzle/GuzzleHttp/Psr7/functions_include.php +++ /dev/null @@ -1,6 +0,0 @@ - 5, - 'protocols' => ['http', 'https'], - 'strict' => false, - 'referer' => false, - 'track_redirects' => false, - ]; - - /** @var callable */ - private $nextHandler; - - /** - * @param callable $nextHandler Next handler to invoke. - */ - public function __construct(callable $nextHandler) - { - $this->nextHandler = $nextHandler; - } - - /** - * @param RequestInterface $request - * @param array $options - * - * @return PromiseInterface - */ - public function __invoke(RequestInterface $request, array $options) - { - $fn = $this->nextHandler; - - if (empty($options['allow_redirects'])) { - return $fn($request, $options); - } - - if ($options['allow_redirects'] === true) { - $options['allow_redirects'] = self::$defaultSettings; - } elseif (!is_array($options['allow_redirects'])) { - throw new \InvalidArgumentException('allow_redirects must be true, false, or array'); - } else { - // Merge the default settings with the provided settings - $options['allow_redirects'] += self::$defaultSettings; - } - - if (empty($options['allow_redirects']['max'])) { - return $fn($request, $options); - } - - return $fn($request, $options) - ->then(function (ResponseInterface $response) use ($request, $options) { - return $this->checkRedirect($request, $options, $response); - }); - } - - /** - * @param RequestInterface $request - * @param array $options - * @param ResponseInterface|PromiseInterface $response - * - * @return ResponseInterface|PromiseInterface - */ - public function checkRedirect( - RequestInterface $request, - array $options, - ResponseInterface $response - ) { - if (substr($response->getStatusCode(), 0, 1) != '3' - || !$response->hasHeader('Location') - ) { - return $response; - } - - $this->guardMax($request, $options); - $nextRequest = $this->modifyRequest($request, $options, $response); - - if (isset($options['allow_redirects']['on_redirect'])) { - call_user_func( - $options['allow_redirects']['on_redirect'], - $request, - $response, - $nextRequest->getUri() - ); - } - - /** @var PromiseInterface|ResponseInterface $promise */ - $promise = $this($nextRequest, $options); - - // Add headers to be able to track history of redirects. - if (!empty($options['allow_redirects']['track_redirects'])) { - return $this->withTracking( - $promise, - (string) $nextRequest->getUri(), - $response->getStatusCode() - ); - } - - return $promise; - } - - private function withTracking(PromiseInterface $promise, $uri, $statusCode) - { - return $promise->then( - function (ResponseInterface $response) use ($uri, $statusCode) { - // Note that we are pushing to the front of the list as this - // would be an earlier response than what is currently present - // in the history header. - $historyHeader = $response->getHeader(self::HISTORY_HEADER); - $statusHeader = $response->getHeader(self::STATUS_HISTORY_HEADER); - array_unshift($historyHeader, $uri); - array_unshift($statusHeader, $statusCode); - return $response->withHeader(self::HISTORY_HEADER, $historyHeader) - ->withHeader(self::STATUS_HISTORY_HEADER, $statusHeader); - } - ); - } - - private function guardMax(RequestInterface $request, array &$options) - { - $current = isset($options['__redirect_count']) - ? $options['__redirect_count'] - : 0; - $options['__redirect_count'] = $current + 1; - $max = $options['allow_redirects']['max']; - - if ($options['__redirect_count'] > $max) { - throw new TooManyRedirectsException( - "Will not follow more than {$max} redirects", - $request - ); - } - } - - /** - * @param RequestInterface $request - * @param array $options - * @param ResponseInterface $response - * - * @return RequestInterface - */ - public function modifyRequest( - RequestInterface $request, - array $options, - ResponseInterface $response - ) { - // Request modifications to apply. - $modify = []; - $protocols = $options['allow_redirects']['protocols']; - - // Use a GET request if this is an entity enclosing request and we are - // not forcing RFC compliance, but rather emulating what all browsers - // would do. - $statusCode = $response->getStatusCode(); - if ($statusCode == 303 || - ($statusCode <= 302 && $request->getBody() && !$options['allow_redirects']['strict']) - ) { - $modify['method'] = 'GET'; - $modify['body'] = ''; - } - - $modify['uri'] = $this->redirectUri($request, $response, $protocols); - Psr7\rewind_body($request); - - // Add the Referer header if it is told to do so and only - // add the header if we are not redirecting from https to http. - if ($options['allow_redirects']['referer'] - && $modify['uri']->getScheme() === $request->getUri()->getScheme() - ) { - $uri = $request->getUri()->withUserInfo('', ''); - $modify['set_headers']['Referer'] = (string) $uri; - } else { - $modify['remove_headers'][] = 'Referer'; - } - - // Remove Authorization header if host is different. - if ($request->getUri()->getHost() !== $modify['uri']->getHost()) { - $modify['remove_headers'][] = 'Authorization'; - } - - return Psr7\modify_request($request, $modify); - } - - /** - * Set the appropriate URL on the request based on the location header - * - * @param RequestInterface $request - * @param ResponseInterface $response - * @param array $protocols - * - * @return UriInterface - */ - private function redirectUri( - RequestInterface $request, - ResponseInterface $response, - array $protocols - ) { - $location = Psr7\UriResolver::resolve( - $request->getUri(), - new Psr7\Uri($response->getHeaderLine('Location')) - ); - - // Ensure that the redirect URI is allowed based on the protocols. - if (!in_array($location->getScheme(), $protocols)) { - throw new BadResponseException( - sprintf( - 'Redirect URI, %s, does not use one of the allowed redirect protocols: %s', - $location, - implode(', ', $protocols) - ), - $request, - $response - ); - } - - return $location; - } -} diff --git a/guzzle/GuzzleHttp/RequestOptions.php b/guzzle/GuzzleHttp/RequestOptions.php deleted file mode 100644 index c6aacfb..0000000 --- a/guzzle/GuzzleHttp/RequestOptions.php +++ /dev/null @@ -1,255 +0,0 @@ -decider = $decider; - $this->nextHandler = $nextHandler; - $this->delay = $delay ?: __CLASS__ . '::exponentialDelay'; - } - - /** - * Default exponential backoff delay function. - * - * @param $retries - * - * @return int - */ - public static function exponentialDelay($retries) - { - return (int) pow(2, $retries - 1); - } - - /** - * @param RequestInterface $request - * @param array $options - * - * @return PromiseInterface - */ - public function __invoke(RequestInterface $request, array $options) - { - if (!isset($options['retries'])) { - $options['retries'] = 0; - } - - $fn = $this->nextHandler; - return $fn($request, $options) - ->then( - $this->onFulfilled($request, $options), - $this->onRejected($request, $options) - ); - } - - private function onFulfilled(RequestInterface $req, array $options) - { - return function ($value) use ($req, $options) { - if (!call_user_func( - $this->decider, - $options['retries'], - $req, - $value, - null - )) { - return $value; - } - return $this->doRetry($req, $options, $value); - }; - } - - private function onRejected(RequestInterface $req, array $options) - { - return function ($reason) use ($req, $options) { - if (!call_user_func( - $this->decider, - $options['retries'], - $req, - null, - $reason - )) { - return \GuzzleHttp\Promise\rejection_for($reason); - } - return $this->doRetry($req, $options); - }; - } - - private function doRetry(RequestInterface $request, array $options, ResponseInterface $response = null) - { - $options['delay'] = call_user_func($this->delay, ++$options['retries'], $response); - - return $this($request, $options); - } -} diff --git a/guzzle/GuzzleHttp/TransferStats.php b/guzzle/GuzzleHttp/TransferStats.php deleted file mode 100644 index 15f717e..0000000 --- a/guzzle/GuzzleHttp/TransferStats.php +++ /dev/null @@ -1,126 +0,0 @@ -request = $request; - $this->response = $response; - $this->transferTime = $transferTime; - $this->handlerErrorData = $handlerErrorData; - $this->handlerStats = $handlerStats; - } - - /** - * @return RequestInterface - */ - public function getRequest() - { - return $this->request; - } - - /** - * Returns the response that was received (if any). - * - * @return ResponseInterface|null - */ - public function getResponse() - { - return $this->response; - } - - /** - * Returns true if a response was received. - * - * @return bool - */ - public function hasResponse() - { - return $this->response !== null; - } - - /** - * Gets handler specific error data. - * - * This might be an exception, a integer representing an error code, or - * anything else. Relying on this value assumes that you know what handler - * you are using. - * - * @return mixed - */ - public function getHandlerErrorData() - { - return $this->handlerErrorData; - } - - /** - * Get the effective URI the request was sent to. - * - * @return UriInterface - */ - public function getEffectiveUri() - { - return $this->request->getUri(); - } - - /** - * Get the estimated time the request was being transferred by the handler. - * - * @return float Time in seconds. - */ - public function getTransferTime() - { - return $this->transferTime; - } - - /** - * Gets an array of all of the handler specific transfer data. - * - * @return array - */ - public function getHandlerStats() - { - return $this->handlerStats; - } - - /** - * Get a specific handler statistic from the handler by name. - * - * @param string $stat Handler specific transfer stat to retrieve. - * - * @return mixed|null - */ - public function getHandlerStat($stat) - { - return isset($this->handlerStats[$stat]) - ? $this->handlerStats[$stat] - : null; - } -} diff --git a/guzzle/GuzzleHttp/UriTemplate.php b/guzzle/GuzzleHttp/UriTemplate.php deleted file mode 100644 index 0b1623e..0000000 --- a/guzzle/GuzzleHttp/UriTemplate.php +++ /dev/null @@ -1,241 +0,0 @@ - ['prefix' => '', 'joiner' => ',', 'query' => false], - '+' => ['prefix' => '', 'joiner' => ',', 'query' => false], - '#' => ['prefix' => '#', 'joiner' => ',', 'query' => false], - '.' => ['prefix' => '.', 'joiner' => '.', 'query' => false], - '/' => ['prefix' => '/', 'joiner' => '/', 'query' => false], - ';' => ['prefix' => ';', 'joiner' => ';', 'query' => true], - '?' => ['prefix' => '?', 'joiner' => '&', 'query' => true], - '&' => ['prefix' => '&', 'joiner' => '&', 'query' => true] - ]; - - /** @var array Delimiters */ - private static $delims = [':', '/', '?', '#', '[', ']', '@', '!', '$', - '&', '\'', '(', ')', '*', '+', ',', ';', '=']; - - /** @var array Percent encoded delimiters */ - private static $delimsPct = ['%3A', '%2F', '%3F', '%23', '%5B', '%5D', - '%40', '%21', '%24', '%26', '%27', '%28', '%29', '%2A', '%2B', '%2C', - '%3B', '%3D']; - - public function expand($template, array $variables) - { - if (false === strpos($template, '{')) { - return $template; - } - - $this->template = $template; - $this->variables = $variables; - - return preg_replace_callback( - '/\{([^\}]+)\}/', - [$this, 'expandMatch'], - $this->template - ); - } - - /** - * Parse an expression into parts - * - * @param string $expression Expression to parse - * - * @return array Returns an associative array of parts - */ - private function parseExpression($expression) - { - $result = []; - - if (isset(self::$operatorHash[$expression[0]])) { - $result['operator'] = $expression[0]; - $expression = substr($expression, 1); - } else { - $result['operator'] = ''; - } - - foreach (explode(',', $expression) as $value) { - $value = trim($value); - $varspec = []; - if ($colonPos = strpos($value, ':')) { - $varspec['value'] = substr($value, 0, $colonPos); - $varspec['modifier'] = ':'; - $varspec['position'] = (int) substr($value, $colonPos + 1); - } elseif (substr($value, -1) === '*') { - $varspec['modifier'] = '*'; - $varspec['value'] = substr($value, 0, -1); - } else { - $varspec['value'] = (string) $value; - $varspec['modifier'] = ''; - } - $result['values'][] = $varspec; - } - - return $result; - } - - /** - * Process an expansion - * - * @param array $matches Matches met in the preg_replace_callback - * - * @return string Returns the replacement string - */ - private function expandMatch(array $matches) - { - static $rfc1738to3986 = ['+' => '%20', '%7e' => '~']; - - $replacements = []; - $parsed = self::parseExpression($matches[1]); - $prefix = self::$operatorHash[$parsed['operator']]['prefix']; - $joiner = self::$operatorHash[$parsed['operator']]['joiner']; - $useQuery = self::$operatorHash[$parsed['operator']]['query']; - - foreach ($parsed['values'] as $value) { - - if (!isset($this->variables[$value['value']])) { - continue; - } - - $variable = $this->variables[$value['value']]; - $actuallyUseQuery = $useQuery; - $expanded = ''; - - if (is_array($variable)) { - - $isAssoc = $this->isAssoc($variable); - $kvp = []; - foreach ($variable as $key => $var) { - - if ($isAssoc) { - $key = rawurlencode($key); - $isNestedArray = is_array($var); - } else { - $isNestedArray = false; - } - - if (!$isNestedArray) { - $var = rawurlencode($var); - if ($parsed['operator'] === '+' || - $parsed['operator'] === '#' - ) { - $var = $this->decodeReserved($var); - } - } - - if ($value['modifier'] === '*') { - if ($isAssoc) { - if ($isNestedArray) { - // Nested arrays must allow for deeply nested - // structures. - $var = strtr( - http_build_query([$key => $var]), - $rfc1738to3986 - ); - } else { - $var = $key . '=' . $var; - } - } elseif ($key > 0 && $actuallyUseQuery) { - $var = $value['value'] . '=' . $var; - } - } - - $kvp[$key] = $var; - } - - if (empty($variable)) { - $actuallyUseQuery = false; - } elseif ($value['modifier'] === '*') { - $expanded = implode($joiner, $kvp); - if ($isAssoc) { - // Don't prepend the value name when using the explode - // modifier with an associative array. - $actuallyUseQuery = false; - } - } else { - if ($isAssoc) { - // When an associative array is encountered and the - // explode modifier is not set, then the result must be - // a comma separated list of keys followed by their - // respective values. - foreach ($kvp as $k => &$v) { - $v = $k . ',' . $v; - } - } - $expanded = implode(',', $kvp); - } - - } else { - if ($value['modifier'] === ':') { - $variable = substr($variable, 0, $value['position']); - } - $expanded = rawurlencode($variable); - if ($parsed['operator'] === '+' || $parsed['operator'] === '#') { - $expanded = $this->decodeReserved($expanded); - } - } - - if ($actuallyUseQuery) { - if (!$expanded && $joiner !== '&') { - $expanded = $value['value']; - } else { - $expanded = $value['value'] . '=' . $expanded; - } - } - - $replacements[] = $expanded; - } - - $ret = implode($joiner, $replacements); - if ($ret && $prefix) { - return $prefix . $ret; - } - - return $ret; - } - - /** - * Determines if an array is associative. - * - * This makes the assumption that input arrays are sequences or hashes. - * This assumption is a tradeoff for accuracy in favor of speed, but it - * should work in almost every case where input is supplied for a URI - * template. - * - * @param array $array Array to check - * - * @return bool - */ - private function isAssoc(array $array) - { - return $array && array_keys($array)[0] !== 0; - } - - /** - * Removes percent encoding on reserved characters (used with + and # - * modifiers). - * - * @param string $string String to fix - * - * @return string - */ - private function decodeReserved($string) - { - return str_replace(self::$delimsPct, self::$delims, $string); - } -} diff --git a/guzzle/GuzzleHttp/functions.php b/guzzle/GuzzleHttp/functions.php deleted file mode 100644 index 59e212e..0000000 --- a/guzzle/GuzzleHttp/functions.php +++ /dev/null @@ -1,331 +0,0 @@ -expand($template, $variables); -} - -/** - * Debug function used to describe the provided value type and class. - * - * @param mixed $input - * - * @return string Returns a string containing the type of the variable and - * if a class is provided, the class name. - */ -function describe_type($input) -{ - switch (gettype($input)) { - case 'object': - return 'object(' . get_class($input) . ')'; - case 'array': - return 'array(' . count($input) . ')'; - default: - ob_start(); - var_dump($input); - // normalize float vs double - return str_replace('double(', 'float(', rtrim(ob_get_clean())); - } -} - -/** - * Parses an array of header lines into an associative array of headers. - * - * @param array $lines Header lines array of strings in the following - * format: "Name: Value" - * @return array - */ -function headers_from_lines($lines) -{ - $headers = []; - - foreach ($lines as $line) { - $parts = explode(':', $line, 2); - $headers[trim($parts[0])][] = isset($parts[1]) - ? trim($parts[1]) - : null; - } - - return $headers; -} - -/** - * Returns a debug stream based on the provided variable. - * - * @param mixed $value Optional value - * - * @return resource - */ -function debug_resource($value = null) -{ - if (is_resource($value)) { - return $value; - } elseif (defined('STDOUT')) { - return STDOUT; - } - - return fopen('php://output', 'w'); -} - -/** - * Chooses and creates a default handler to use based on the environment. - * - * The returned handler is not wrapped by any default middlewares. - * - * @throws \RuntimeException if no viable Handler is available. - * @return callable Returns the best handler for the given system. - */ -function choose_handler() -{ - $handler = null; - if (function_exists('curl_multi_exec') && function_exists('curl_exec')) { - $handler = Proxy::wrapSync(new CurlMultiHandler(), new CurlHandler()); - } elseif (function_exists('curl_exec')) { - $handler = new CurlHandler(); - } elseif (function_exists('curl_multi_exec')) { - $handler = new CurlMultiHandler(); - } - - if (ini_get('allow_url_fopen')) { - $handler = $handler - ? Proxy::wrapStreaming($handler, new StreamHandler()) - : new StreamHandler(); - } elseif (!$handler) { - throw new \RuntimeException('GuzzleHttp requires cURL, the ' - . 'allow_url_fopen ini setting, or a custom HTTP handler.'); - } - - return $handler; -} - -/** - * Get the default User-Agent string to use with Guzzle - * - * @return string - */ -function default_user_agent() -{ - static $defaultAgent = ''; - - if (!$defaultAgent) { - $defaultAgent = 'GuzzleHttp/' . Client::VERSION; - if (extension_loaded('curl') && function_exists('curl_version')) { - $defaultAgent .= ' curl/' . \curl_version()['version']; - } - $defaultAgent .= ' PHP/' . PHP_VERSION; - } - - return $defaultAgent; -} - -/** - * Returns the default cacert bundle for the current system. - * - * First, the openssl.cafile and curl.cainfo php.ini settings are checked. - * If those settings are not configured, then the common locations for - * bundles found on Red Hat, CentOS, Fedora, Ubuntu, Debian, FreeBSD, OS X - * and Windows are checked. If any of these file locations are found on - * disk, they will be utilized. - * - * Note: the result of this function is cached for subsequent calls. - * - * @return string - * @throws \RuntimeException if no bundle can be found. - */ -function default_ca_bundle() -{ - static $cached = null; - static $cafiles = [ - // Red Hat, CentOS, Fedora (provided by the ca-certificates package) - '/etc/pki/tls/certs/ca-bundle.crt', - // Ubuntu, Debian (provided by the ca-certificates package) - '/etc/ssl/certs/ca-certificates.crt', - // FreeBSD (provided by the ca_root_nss package) - '/usr/local/share/certs/ca-root-nss.crt', - // SLES 12 (provided by the ca-certificates package) - '/var/lib/ca-certificates/ca-bundle.pem', - // OS X provided by homebrew (using the default path) - '/usr/local/etc/openssl/cert.pem', - // Google app engine - '/etc/ca-certificates.crt', - // Windows? - 'C:\\windows\\system32\\curl-ca-bundle.crt', - 'C:\\windows\\curl-ca-bundle.crt', - ]; - - if ($cached) { - return $cached; - } - - if ($ca = ini_get('openssl.cafile')) { - return $cached = $ca; - } - - if ($ca = ini_get('curl.cainfo')) { - return $cached = $ca; - } - - foreach ($cafiles as $filename) { - if (file_exists($filename)) { - return $cached = $filename; - } - } - - throw new \RuntimeException(<<< EOT -No system CA bundle could be found in any of the the common system locations. -PHP versions earlier than 5.6 are not properly configured to use the system's -CA bundle by default. In order to verify peer certificates, you will need to -supply the path on disk to a certificate bundle to the 'verify' request -option: http://docs.guzzlephp.org/en/latest/clients.html#verify. If you do not -need a specific certificate bundle, then Mozilla provides a commonly used CA -bundle which can be downloaded here (provided by the maintainer of cURL): -https://raw.githubusercontent.com/bagder/ca-bundle/master/ca-bundle.crt. Once -you have a CA bundle available on disk, you can set the 'openssl.cafile' PHP -ini setting to point to the path to the file, allowing you to omit the 'verify' -request option. See http://curl.haxx.se/docs/sslcerts.html for more -information. -EOT - ); -} - -/** - * Creates an associative array of lowercase header names to the actual - * header casing. - * - * @param array $headers - * - * @return array - */ -function normalize_header_keys(array $headers) -{ - $result = []; - foreach (array_keys($headers) as $key) { - $result[strtolower($key)] = $key; - } - - return $result; -} - -/** - * Returns true if the provided host matches any of the no proxy areas. - * - * This method will strip a port from the host if it is present. Each pattern - * can be matched with an exact match (e.g., "foo.com" == "foo.com") or a - * partial match: (e.g., "foo.com" == "baz.foo.com" and ".foo.com" == - * "baz.foo.com", but ".foo.com" != "foo.com"). - * - * Areas are matched in the following cases: - * 1. "*" (without quotes) always matches any hosts. - * 2. An exact match. - * 3. The area starts with "." and the area is the last part of the host. e.g. - * '.mit.edu' will match any host that ends with '.mit.edu'. - * - * @param string $host Host to check against the patterns. - * @param array $noProxyArray An array of host patterns. - * - * @return bool - */ -function is_host_in_noproxy($host, array $noProxyArray) -{ - if (strlen($host) === 0) { - throw new \InvalidArgumentException('Empty host provided'); - } - - // Strip port if present. - if (strpos($host, ':')) { - $host = explode($host, ':', 2)[0]; - } - - foreach ($noProxyArray as $area) { - // Always match on wildcards. - if ($area === '*') { - return true; - } elseif (empty($area)) { - // Don't match on empty values. - continue; - } elseif ($area === $host) { - // Exact matches. - return true; - } else { - // Special match if the area when prefixed with ".". Remove any - // existing leading "." and add a new leading ".". - $area = '.' . ltrim($area, '.'); - if (substr($host, -(strlen($area))) === $area) { - return true; - } - } - } - - return false; -} - -/** - * Wrapper for json_decode that throws when an error occurs. - * - * @param string $json JSON data to parse - * @param bool $assoc When true, returned objects will be converted - * into associative arrays. - * @param int $depth User specified recursion depth. - * @param int $options Bitmask of JSON decode options. - * - * @return mixed - * @throws \InvalidArgumentException if the JSON cannot be decoded. - * @link http://www.php.net/manual/en/function.json-decode.php - */ -function json_decode($json, $assoc = false, $depth = 512, $options = 0) -{ - $data = \json_decode($json, $assoc, $depth, $options); - if (JSON_ERROR_NONE !== json_last_error()) { - throw new \InvalidArgumentException( - 'json_decode error: ' . json_last_error_msg()); - } - - return $data; -} - -/** - * Wrapper for JSON encoding that throws when an error occurs. - * - * @param mixed $value The value being encoded - * @param int $options JSON encode option bitmask - * @param int $depth Set the maximum depth. Must be greater than zero. - * - * @return string - * @throws \InvalidArgumentException if the JSON cannot be encoded. - * @link http://www.php.net/manual/en/function.json-encode.php - */ -function json_encode($value, $options = 0, $depth = 512) -{ - $json = \json_encode($value, $options, $depth); - if (JSON_ERROR_NONE !== json_last_error()) { - throw new \InvalidArgumentException( - 'json_encode error: ' . json_last_error_msg()); - } - - return $json; -} diff --git a/guzzle/GuzzleHttp/functions_include.php b/guzzle/GuzzleHttp/functions_include.php deleted file mode 100644 index a93393a..0000000 --- a/guzzle/GuzzleHttp/functions_include.php +++ /dev/null @@ -1,6 +0,0 @@ - - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/guzzle/Psr/Http/Message/MessageInterface.php b/guzzle/Psr/Http/Message/MessageInterface.php deleted file mode 100644 index dd46e5e..0000000 --- a/guzzle/Psr/Http/Message/MessageInterface.php +++ /dev/null @@ -1,187 +0,0 @@ -getHeaders() as $name => $values) { - * echo $name . ": " . implode(", ", $values); - * } - * - * // Emit headers iteratively: - * foreach ($message->getHeaders() as $name => $values) { - * foreach ($values as $value) { - * header(sprintf('%s: %s', $name, $value), false); - * } - * } - * - * While header names are not case-sensitive, getHeaders() will preserve the - * exact case in which headers were originally specified. - * - * @return string[][] Returns an associative array of the message's headers. Each - * key MUST be a header name, and each value MUST be an array of strings - * for that header. - */ - public function getHeaders(); - - /** - * Checks if a header exists by the given case-insensitive name. - * - * @param string $name Case-insensitive header field name. - * @return bool Returns true if any header names match the given header - * name using a case-insensitive string comparison. Returns false if - * no matching header name is found in the message. - */ - public function hasHeader($name); - - /** - * Retrieves a message header value by the given case-insensitive name. - * - * This method returns an array of all the header values of the given - * case-insensitive header name. - * - * If the header does not appear in the message, this method MUST return an - * empty array. - * - * @param string $name Case-insensitive header field name. - * @return string[] An array of string values as provided for the given - * header. If the header does not appear in the message, this method MUST - * return an empty array. - */ - public function getHeader($name); - - /** - * Retrieves a comma-separated string of the values for a single header. - * - * This method returns all of the header values of the given - * case-insensitive header name as a string concatenated together using - * a comma. - * - * NOTE: Not all header values may be appropriately represented using - * comma concatenation. For such headers, use getHeader() instead - * and supply your own delimiter when concatenating. - * - * If the header does not appear in the message, this method MUST return - * an empty string. - * - * @param string $name Case-insensitive header field name. - * @return string A string of values as provided for the given header - * concatenated together using a comma. If the header does not appear in - * the message, this method MUST return an empty string. - */ - public function getHeaderLine($name); - - /** - * Return an instance with the provided value replacing the specified header. - * - * While header names are case-insensitive, the casing of the header will - * be preserved by this function, and returned from getHeaders(). - * - * This method MUST be implemented in such a way as to retain the - * immutability of the message, and MUST return an instance that has the - * new and/or updated header and value. - * - * @param string $name Case-insensitive header field name. - * @param string|string[] $value Header value(s). - * @return static - * @throws \InvalidArgumentException for invalid header names or values. - */ - public function withHeader($name, $value); - - /** - * Return an instance with the specified header appended with the given value. - * - * Existing values for the specified header will be maintained. The new - * value(s) will be appended to the existing list. If the header did not - * exist previously, it will be added. - * - * This method MUST be implemented in such a way as to retain the - * immutability of the message, and MUST return an instance that has the - * new header and/or value. - * - * @param string $name Case-insensitive header field name to add. - * @param string|string[] $value Header value(s). - * @return static - * @throws \InvalidArgumentException for invalid header names or values. - */ - public function withAddedHeader($name, $value); - - /** - * Return an instance without the specified header. - * - * Header resolution MUST be done without case-sensitivity. - * - * This method MUST be implemented in such a way as to retain the - * immutability of the message, and MUST return an instance that removes - * the named header. - * - * @param string $name Case-insensitive header field name to remove. - * @return static - */ - public function withoutHeader($name); - - /** - * Gets the body of the message. - * - * @return StreamInterface Returns the body as a stream. - */ - public function getBody(); - - /** - * Return an instance with the specified message body. - * - * The body MUST be a StreamInterface object. - * - * This method MUST be implemented in such a way as to retain the - * immutability of the message, and MUST return a new instance that has the - * new body stream. - * - * @param StreamInterface $body Body. - * @return static - * @throws \InvalidArgumentException When the body is not valid. - */ - public function withBody(StreamInterface $body); -} diff --git a/guzzle/Psr/Http/Message/RequestInterface.php b/guzzle/Psr/Http/Message/RequestInterface.php deleted file mode 100644 index a96d4fd..0000000 --- a/guzzle/Psr/Http/Message/RequestInterface.php +++ /dev/null @@ -1,129 +0,0 @@ -getQuery()` - * or from the `QUERY_STRING` server param. - * - * @return array - */ - public function getQueryParams(); - - /** - * Return an instance with the specified query string arguments. - * - * These values SHOULD remain immutable over the course of the incoming - * request. They MAY be injected during instantiation, such as from PHP's - * $_GET superglobal, or MAY be derived from some other value such as the - * URI. In cases where the arguments are parsed from the URI, the data - * MUST be compatible with what PHP's parse_str() would return for - * purposes of how duplicate query parameters are handled, and how nested - * sets are handled. - * - * Setting query string arguments MUST NOT change the URI stored by the - * request, nor the values in the server params. - * - * This method MUST be implemented in such a way as to retain the - * immutability of the message, and MUST return an instance that has the - * updated query string arguments. - * - * @param array $query Array of query string arguments, typically from - * $_GET. - * @return static - */ - public function withQueryParams(array $query); - - /** - * Retrieve normalized file upload data. - * - * This method returns upload metadata in a normalized tree, with each leaf - * an instance of Psr\Http\Message\UploadedFileInterface. - * - * These values MAY be prepared from $_FILES or the message body during - * instantiation, or MAY be injected via withUploadedFiles(). - * - * @return array An array tree of UploadedFileInterface instances; an empty - * array MUST be returned if no data is present. - */ - public function getUploadedFiles(); - - /** - * Create a new instance with the specified uploaded files. - * - * This method MUST be implemented in such a way as to retain the - * immutability of the message, and MUST return an instance that has the - * updated body parameters. - * - * @param array $uploadedFiles An array tree of UploadedFileInterface instances. - * @return static - * @throws \InvalidArgumentException if an invalid structure is provided. - */ - public function withUploadedFiles(array $uploadedFiles); - - /** - * Retrieve any parameters provided in the request body. - * - * If the request Content-Type is either application/x-www-form-urlencoded - * or multipart/form-data, and the request method is POST, this method MUST - * return the contents of $_POST. - * - * Otherwise, this method may return any results of deserializing - * the request body content; as parsing returns structured content, the - * potential types MUST be arrays or objects only. A null value indicates - * the absence of body content. - * - * @return null|array|object The deserialized body parameters, if any. - * These will typically be an array or object. - */ - public function getParsedBody(); - - /** - * Return an instance with the specified body parameters. - * - * These MAY be injected during instantiation. - * - * If the request Content-Type is either application/x-www-form-urlencoded - * or multipart/form-data, and the request method is POST, use this method - * ONLY to inject the contents of $_POST. - * - * The data IS NOT REQUIRED to come from $_POST, but MUST be the results of - * deserializing the request body content. Deserialization/parsing returns - * structured data, and, as such, this method ONLY accepts arrays or objects, - * or a null value if nothing was available to parse. - * - * As an example, if content negotiation determines that the request data - * is a JSON payload, this method could be used to create a request - * instance with the deserialized parameters. - * - * This method MUST be implemented in such a way as to retain the - * immutability of the message, and MUST return an instance that has the - * updated body parameters. - * - * @param null|array|object $data The deserialized body data. This will - * typically be in an array or object. - * @return static - * @throws \InvalidArgumentException if an unsupported argument type is - * provided. - */ - public function withParsedBody($data); - - /** - * Retrieve attributes derived from the request. - * - * The request "attributes" may be used to allow injection of any - * parameters derived from the request: e.g., the results of path - * match operations; the results of decrypting cookies; the results of - * deserializing non-form-encoded message bodies; etc. Attributes - * will be application and request specific, and CAN be mutable. - * - * @return array Attributes derived from the request. - */ - public function getAttributes(); - - /** - * Retrieve a single derived request attribute. - * - * Retrieves a single derived request attribute as described in - * getAttributes(). If the attribute has not been previously set, returns - * the default value as provided. - * - * This method obviates the need for a hasAttribute() method, as it allows - * specifying a default value to return if the attribute is not found. - * - * @see getAttributes() - * @param string $name The attribute name. - * @param mixed $default Default value to return if the attribute does not exist. - * @return mixed - */ - public function getAttribute($name, $default = null); - - /** - * Return an instance with the specified derived request attribute. - * - * This method allows setting a single derived request attribute as - * described in getAttributes(). - * - * This method MUST be implemented in such a way as to retain the - * immutability of the message, and MUST return an instance that has the - * updated attribute. - * - * @see getAttributes() - * @param string $name The attribute name. - * @param mixed $value The value of the attribute. - * @return static - */ - public function withAttribute($name, $value); - - /** - * Return an instance that removes the specified derived request attribute. - * - * This method allows removing a single derived request attribute as - * described in getAttributes(). - * - * This method MUST be implemented in such a way as to retain the - * immutability of the message, and MUST return an instance that removes - * the attribute. - * - * @see getAttributes() - * @param string $name The attribute name. - * @return static - */ - public function withoutAttribute($name); -} diff --git a/guzzle/Psr/Http/Message/StreamInterface.php b/guzzle/Psr/Http/Message/StreamInterface.php deleted file mode 100644 index f68f391..0000000 --- a/guzzle/Psr/Http/Message/StreamInterface.php +++ /dev/null @@ -1,158 +0,0 @@ - - * [user-info@]host[:port] - * - * - * If the port component is not set or is the standard port for the current - * scheme, it SHOULD NOT be included. - * - * @see https://tools.ietf.org/html/rfc3986#section-3.2 - * @return string The URI authority, in "[user-info@]host[:port]" format. - */ - public function getAuthority(); - - /** - * Retrieve the user information component of the URI. - * - * If no user information is present, this method MUST return an empty - * string. - * - * If a user is present in the URI, this will return that value; - * additionally, if the password is also present, it will be appended to the - * user value, with a colon (":") separating the values. - * - * The trailing "@" character is not part of the user information and MUST - * NOT be added. - * - * @return string The URI user information, in "username[:password]" format. - */ - public function getUserInfo(); - - /** - * Retrieve the host component of the URI. - * - * If no host is present, this method MUST return an empty string. - * - * The value returned MUST be normalized to lowercase, per RFC 3986 - * Section 3.2.2. - * - * @see http://tools.ietf.org/html/rfc3986#section-3.2.2 - * @return string The URI host. - */ - public function getHost(); - - /** - * Retrieve the port component of the URI. - * - * If a port is present, and it is non-standard for the current scheme, - * this method MUST return it as an integer. If the port is the standard port - * used with the current scheme, this method SHOULD return null. - * - * If no port is present, and no scheme is present, this method MUST return - * a null value. - * - * If no port is present, but a scheme is present, this method MAY return - * the standard port for that scheme, but SHOULD return null. - * - * @return null|int The URI port. - */ - public function getPort(); - - /** - * Retrieve the path component of the URI. - * - * The path can either be empty or absolute (starting with a slash) or - * rootless (not starting with a slash). Implementations MUST support all - * three syntaxes. - * - * Normally, the empty path "" and absolute path "/" are considered equal as - * defined in RFC 7230 Section 2.7.3. But this method MUST NOT automatically - * do this normalization because in contexts with a trimmed base path, e.g. - * the front controller, this difference becomes significant. It's the task - * of the user to handle both "" and "/". - * - * The value returned MUST be percent-encoded, but MUST NOT double-encode - * any characters. To determine what characters to encode, please refer to - * RFC 3986, Sections 2 and 3.3. - * - * As an example, if the value should include a slash ("/") not intended as - * delimiter between path segments, that value MUST be passed in encoded - * form (e.g., "%2F") to the instance. - * - * @see https://tools.ietf.org/html/rfc3986#section-2 - * @see https://tools.ietf.org/html/rfc3986#section-3.3 - * @return string The URI path. - */ - public function getPath(); - - /** - * Retrieve the query string of the URI. - * - * If no query string is present, this method MUST return an empty string. - * - * The leading "?" character is not part of the query and MUST NOT be - * added. - * - * The value returned MUST be percent-encoded, but MUST NOT double-encode - * any characters. To determine what characters to encode, please refer to - * RFC 3986, Sections 2 and 3.4. - * - * As an example, if a value in a key/value pair of the query string should - * include an ampersand ("&") not intended as a delimiter between values, - * that value MUST be passed in encoded form (e.g., "%26") to the instance. - * - * @see https://tools.ietf.org/html/rfc3986#section-2 - * @see https://tools.ietf.org/html/rfc3986#section-3.4 - * @return string The URI query string. - */ - public function getQuery(); - - /** - * Retrieve the fragment component of the URI. - * - * If no fragment is present, this method MUST return an empty string. - * - * The leading "#" character is not part of the fragment and MUST NOT be - * added. - * - * The value returned MUST be percent-encoded, but MUST NOT double-encode - * any characters. To determine what characters to encode, please refer to - * RFC 3986, Sections 2 and 3.5. - * - * @see https://tools.ietf.org/html/rfc3986#section-2 - * @see https://tools.ietf.org/html/rfc3986#section-3.5 - * @return string The URI fragment. - */ - public function getFragment(); - - /** - * Return an instance with the specified scheme. - * - * This method MUST retain the state of the current instance, and return - * an instance that contains the specified scheme. - * - * Implementations MUST support the schemes "http" and "https" case - * insensitively, and MAY accommodate other schemes if required. - * - * An empty scheme is equivalent to removing the scheme. - * - * @param string $scheme The scheme to use with the new instance. - * @return static A new instance with the specified scheme. - * @throws \InvalidArgumentException for invalid or unsupported schemes. - */ - public function withScheme($scheme); - - /** - * Return an instance with the specified user information. - * - * This method MUST retain the state of the current instance, and return - * an instance that contains the specified user information. - * - * Password is optional, but the user information MUST include the - * user; an empty string for the user is equivalent to removing user - * information. - * - * @param string $user The user name to use for authority. - * @param null|string $password The password associated with $user. - * @return static A new instance with the specified user information. - */ - public function withUserInfo($user, $password = null); - - /** - * Return an instance with the specified host. - * - * This method MUST retain the state of the current instance, and return - * an instance that contains the specified host. - * - * An empty host value is equivalent to removing the host. - * - * @param string $host The hostname to use with the new instance. - * @return static A new instance with the specified host. - * @throws \InvalidArgumentException for invalid hostnames. - */ - public function withHost($host); - - /** - * Return an instance with the specified port. - * - * This method MUST retain the state of the current instance, and return - * an instance that contains the specified port. - * - * Implementations MUST raise an exception for ports outside the - * established TCP and UDP port ranges. - * - * A null value provided for the port is equivalent to removing the port - * information. - * - * @param null|int $port The port to use with the new instance; a null value - * removes the port information. - * @return static A new instance with the specified port. - * @throws \InvalidArgumentException for invalid ports. - */ - public function withPort($port); - - /** - * Return an instance with the specified path. - * - * This method MUST retain the state of the current instance, and return - * an instance that contains the specified path. - * - * The path can either be empty or absolute (starting with a slash) or - * rootless (not starting with a slash). Implementations MUST support all - * three syntaxes. - * - * If the path is intended to be domain-relative rather than path relative then - * it must begin with a slash ("/"). Paths not starting with a slash ("/") - * are assumed to be relative to some base path known to the application or - * consumer. - * - * Users can provide both encoded and decoded path characters. - * Implementations ensure the correct encoding as outlined in getPath(). - * - * @param string $path The path to use with the new instance. - * @return static A new instance with the specified path. - * @throws \InvalidArgumentException for invalid paths. - */ - public function withPath($path); - - /** - * Return an instance with the specified query string. - * - * This method MUST retain the state of the current instance, and return - * an instance that contains the specified query string. - * - * Users can provide both encoded and decoded query characters. - * Implementations ensure the correct encoding as outlined in getQuery(). - * - * An empty query string value is equivalent to removing the query string. - * - * @param string $query The query string to use with the new instance. - * @return static A new instance with the specified query string. - * @throws \InvalidArgumentException for invalid query strings. - */ - public function withQuery($query); - - /** - * Return an instance with the specified URI fragment. - * - * This method MUST retain the state of the current instance, and return - * an instance that contains the specified URI fragment. - * - * Users can provide both encoded and decoded fragment characters. - * Implementations ensure the correct encoding as outlined in getFragment(). - * - * An empty fragment value is equivalent to removing the fragment. - * - * @param string $fragment The fragment to use with the new instance. - * @return static A new instance with the specified fragment. - */ - public function withFragment($fragment); - - /** - * Return the string representation as a URI reference. - * - * Depending on which components of the URI are present, the resulting - * string is either a full URI or relative reference according to RFC 3986, - * Section 4.1. The method concatenates the various components of the URI, - * using the appropriate delimiters: - * - * - If a scheme is present, it MUST be suffixed by ":". - * - If an authority is present, it MUST be prefixed by "//". - * - The path can be concatenated without delimiters. But there are two - * cases where the path has to be adjusted to make the URI reference - * valid as PHP does not allow to throw an exception in __toString(): - * - If the path is rootless and an authority is present, the path MUST - * be prefixed by "/". - * - If the path is starting with more than one "/" and no authority is - * present, the starting slashes MUST be reduced to one. - * - If a query is present, it MUST be prefixed by "?". - * - If a fragment is present, it MUST be prefixed by "#". - * - * @see http://tools.ietf.org/html/rfc3986#section-4.1 - * @return string - */ - public function __toString(); -} diff --git a/guzzle/README.md b/guzzle/README.md deleted file mode 100644 index 2f614d6..0000000 --- a/guzzle/README.md +++ /dev/null @@ -1,89 +0,0 @@ -Guzzle, PHP HTTP client -======================= - -[![Build Status](https://travis-ci.org/guzzle/guzzle.svg?branch=master)](https://travis-ci.org/guzzle/guzzle) - -Guzzle is a PHP HTTP client that makes it easy to send HTTP requests and -trivial to integrate with web services. - -- Simple interface for building query strings, POST requests, streaming large - uploads, streaming large downloads, using HTTP cookies, uploading JSON data, - etc... -- Can send both synchronous and asynchronous requests using the same interface. -- Uses PSR-7 interfaces for requests, responses, and streams. This allows you - to utilize other PSR-7 compatible libraries with Guzzle. -- Abstracts away the underlying HTTP transport, allowing you to write - environment and transport agnostic code; i.e., no hard dependency on cURL, - PHP streams, sockets, or non-blocking event loops. -- Middleware system allows you to augment and compose client behavior. - -```php -$client = new \GuzzleHttp\Client(); -$res = $client->request('GET', 'https://api.github.com/repos/guzzle/guzzle'); -echo $res->getStatusCode(); -// 200 -echo $res->getHeaderLine('content-type'); -// 'application/json; charset=utf8' -echo $res->getBody(); -// '{"id": 1420053, "name": "guzzle", ...}' - -// Send an asynchronous request. -$request = new \GuzzleHttp\Psr7\Request('GET', 'http://httpbin.org'); -$promise = $client->sendAsync($request)->then(function ($response) { - echo 'I completed! ' . $response->getBody(); -}); -$promise->wait(); -``` - -## Help and docs - -- [Documentation](http://guzzlephp.org/) -- [Stack Overflow](http://stackoverflow.com/questions/tagged/guzzle) -- [Gitter](https://gitter.im/guzzle/guzzle) - - -## Installing Guzzle - -The recommended way to install Guzzle is through -[Composer](http://getcomposer.org). - -```bash -# Install Composer -curl -sS https://getcomposer.org/installer | php -``` - -Next, run the Composer command to install the latest stable version of Guzzle: - -```bash -php composer.phar require guzzlehttp/guzzle -``` - -After installing, you need to require Composer's autoloader: - -```php -require 'vendor/autoload.php'; -``` - -You can then later update Guzzle using composer: - - ```bash -composer.phar update - ``` - - -## Version Guidance - -| Version | Status | Packagist | Namespace | Repo | Docs | PSR-7 | PHP Version | -|---------|------------|---------------------|--------------|---------------------|---------------------|-------|-------------| -| 3.x | EOL | `guzzle/guzzle` | `Guzzle` | [v3][guzzle-3-repo] | [v3][guzzle-3-docs] | No | >= 5.3.3 | -| 4.x | EOL | `guzzlehttp/guzzle` | `GuzzleHttp` | [v4][guzzle-4-repo] | N/A | No | >= 5.4 | -| 5.x | Maintained | `guzzlehttp/guzzle` | `GuzzleHttp` | [v5][guzzle-5-repo] | [v5][guzzle-5-docs] | No | >= 5.4 | -| 6.x | Latest | `guzzlehttp/guzzle` | `GuzzleHttp` | [v6][guzzle-6-repo] | [v6][guzzle-6-docs] | Yes | >= 5.5 | - -[guzzle-3-repo]: https://github.com/guzzle/guzzle3 -[guzzle-4-repo]: https://github.com/guzzle/guzzle/tree/4.x -[guzzle-5-repo]: https://github.com/guzzle/guzzle/tree/5.3 -[guzzle-6-repo]: https://github.com/guzzle/guzzle -[guzzle-3-docs]: http://guzzle3.readthedocs.org/en/latest/ -[guzzle-5-docs]: http://guzzle.readthedocs.org/en/5.3/ -[guzzle-6-docs]: http://guzzle.readthedocs.org/en/latest/ diff --git a/guzzle/autoloader.php b/guzzle/autoloader.php deleted file mode 100644 index 977d581..0000000 --- a/guzzle/autoloader.php +++ /dev/null @@ -1,95 +0,0 @@ - __DIR__ . '/GuzzleHttp/Client.php', - 'GuzzleHttp\ClientInterface' => __DIR__ . '/GuzzleHttp/ClientInterface.php', - 'GuzzleHttp\Cookie\CookieJar' => __DIR__ . '/GuzzleHttp/Cookie/CookieJar.php', - 'GuzzleHttp\Cookie\CookieJarInterface' => __DIR__ . '/GuzzleHttp/Cookie/CookieJarInterface.php', - 'GuzzleHttp\Cookie\FileCookieJar' => __DIR__ . '/GuzzleHttp/Cookie/FileCookieJar.php', - 'GuzzleHttp\Cookie\SessionCookieJar' => __DIR__ . '/GuzzleHttp/Cookie/SessionCookieJar.php', - 'GuzzleHttp\Cookie\SetCookie' => __DIR__ . '/GuzzleHttp/Cookie/SetCookie.php', - 'GuzzleHttp\Exception\BadResponseException' => __DIR__ . '/GuzzleHttp/Exception/BadResponseException.php', - 'GuzzleHttp\Exception\ClientException' => __DIR__ . '/GuzzleHttp/Exception/ClientException.php', - 'GuzzleHttp\Exception\ConnectException' => __DIR__ . '/GuzzleHttp/Exception/ConnectException.php', - 'GuzzleHttp\Exception\GuzzleException' => __DIR__ . '/GuzzleHttp/Exception/GuzzleException.php', - 'GuzzleHttp\Exception\RequestException' => __DIR__ . '/GuzzleHttp/Exception/RequestException.php', - 'GuzzleHttp\Exception\SeekException' => __DIR__ . '/GuzzleHttp/Exception/SeekException.php', - 'GuzzleHttp\Exception\ServerException' => __DIR__ . '/GuzzleHttp/Exception/ServerException.php', - 'GuzzleHttp\Exception\TooManyRedirectsException' => __DIR__ . '/GuzzleHttp/Exception/TooManyRedirectsException.php', - 'GuzzleHttp\Exception\TransferException' => __DIR__ . '/GuzzleHttp/Exception/TransferException.php', - 'GuzzleHttp\Handler\CurlFactory' => __DIR__ . '/GuzzleHttp/Handler/CurlFactory.php', - 'GuzzleHttp\Handler\CurlFactoryInterface' => __DIR__ . '/GuzzleHttp/Handler/CurlFactoryInterface.php', - 'GuzzleHttp\Handler\CurlHandler' => __DIR__ . '/GuzzleHttp/Handler/CurlHandler.php', - 'GuzzleHttp\Handler\CurlMultiHandler' => __DIR__ . '/GuzzleHttp/Handler/CurlMultiHandler.php', - 'GuzzleHttp\Handler\EasyHandle' => __DIR__ . '/GuzzleHttp/Handler/EasyHandle.php', - 'GuzzleHttp\Handler\MockHandler' => __DIR__ . '/GuzzleHttp/Handler/MockHandler.php', - 'GuzzleHttp\Handler\Proxy' => __DIR__ . '/GuzzleHttp/Handler/Proxy.php', - 'GuzzleHttp\Handler\StreamHandler' => __DIR__ . '/GuzzleHttp/Handler/StreamHandler.php', - 'GuzzleHttp\HandlerStack' => __DIR__ . '/GuzzleHttp/HandlerStack.php', - 'GuzzleHttp\MessageFormatter' => __DIR__ . '/GuzzleHttp/MessageFormatter.php', - 'GuzzleHttp\Middleware' => __DIR__ . '/GuzzleHttp/Middleware.php', - 'GuzzleHttp\Pool' => __DIR__ . '/GuzzleHttp/Pool.php', - 'GuzzleHttp\PrepareBodyMiddleware' => __DIR__ . '/GuzzleHttp/PrepareBodyMiddleware.php', - 'GuzzleHttp\RedirectMiddleware' => __DIR__ . '/GuzzleHttp/RedirectMiddleware.php', - 'GuzzleHttp\RequestOptions' => __DIR__ . '/GuzzleHttp/RequestOptions.php', - 'GuzzleHttp\RetryMiddleware' => __DIR__ . '/GuzzleHttp/RetryMiddleware.php', - 'GuzzleHttp\TransferStats' => __DIR__ . '/GuzzleHttp/TransferStats.php', - 'GuzzleHttp\UriTemplate' => __DIR__ . '/GuzzleHttp/UriTemplate.php', - 'GuzzleHttp\functions' => __DIR__ . '/GuzzleHttp/functions_include.php', - 'GuzzleHttp\functions_include' => __DIR__ . '/GuzzleHttp/functions_include.php', - 'GuzzleHttp\Promise\AggregateException' => __DIR__ . '/GuzzleHttp/Promise/AggregateException.php', - 'GuzzleHttp\Promise\CancellationException' => __DIR__ . '/GuzzleHttp/Promise/CancellationException.php', - 'GuzzleHttp\Promise\Coroutine' => __DIR__ . '/GuzzleHttp/Promise/Coroutine.php', - 'GuzzleHttp\Promise\EachPromise' => __DIR__ . '/GuzzleHttp/Promise/EachPromise.php', - 'GuzzleHttp\Promise\FulfilledPromise' => __DIR__ . '/GuzzleHttp/Promise/FulfilledPromise.php', - 'GuzzleHttp\Promise\Promise' => __DIR__ . '/GuzzleHttp/Promise/Promise.php', - 'GuzzleHttp\Promise\PromiseInterface' => __DIR__ . '/GuzzleHttp/Promise/PromiseInterface.php', - 'GuzzleHttp\Promise\PromisorInterface' => __DIR__ . '/GuzzleHttp/Promise/PromisorInterface.php', - 'GuzzleHttp\Promise\RejectedPromise' => __DIR__ . '/GuzzleHttp/Promise/RejectedPromise.php', - 'GuzzleHttp\Promise\RejectionException' => __DIR__ . '/GuzzleHttp/Promise/RejectionException.php', - 'GuzzleHttp\Promise\TaskQueue' => __DIR__ . '/GuzzleHttp/Promise/TaskQueue.php', - 'GuzzleHttp\Promise\TaskQueueInterface' => __DIR__ . '/GuzzleHttp/Promise/TaskQueueInterface.php', - 'GuzzleHttp\Promise\functions' => __DIR__ . '/GuzzleHttp/Promise/functions_include.php', - 'GuzzleHttp\Promise\functions_include' => __DIR__ . '/GuzzleHttp/Promise/functions_include.php', - 'GuzzleHttp\Psr7\AppendStream' => __DIR__ . '/GuzzleHttp/Psr7/AppendStream.php', - 'GuzzleHttp\Psr7\BufferStream' => __DIR__ . '/GuzzleHttp/Psr7/BufferStream.php', - 'GuzzleHttp\Psr7\CachingStream' => __DIR__ . '/GuzzleHttp/Psr7/CachingStream.php', - 'GuzzleHttp\Psr7\DroppingStream' => __DIR__ . '/GuzzleHttp/Psr7/DroppingStream.php', - 'GuzzleHttp\Psr7\FnStream' => __DIR__ . '/GuzzleHttp/Psr7/FnStream.php', - 'GuzzleHttp\Psr7\InflateStream' => __DIR__ . '/GuzzleHttp/Psr7/InflateStream.php', - 'GuzzleHttp\Psr7\LazyOpenStream' => __DIR__ . '/GuzzleHttp/Psr7/LazyOpenStream.php', - 'GuzzleHttp\Psr7\LimitStream' => __DIR__ . '/GuzzleHttp/Psr7/LimitStream.php', - 'GuzzleHttp\Psr7\MessageTrait' => __DIR__ . '/GuzzleHttp/Psr7/MessageTrait.php', - 'GuzzleHttp\Psr7\MultipartStream' => __DIR__ . '/GuzzleHttp/Psr7/MultipartStream.php', - 'GuzzleHttp\Psr7\NoSeekStream' => __DIR__ . '/GuzzleHttp/Psr7/NoSeekStream.php', - 'GuzzleHttp\Psr7\PumpStream' => __DIR__ . '/GuzzleHttp/Psr7/PumpStream.php', - 'GuzzleHttp\Psr7\Request' => __DIR__ . '/GuzzleHttp/Psr7/Request.php', - 'GuzzleHttp\Psr7\Response' => __DIR__ . '/GuzzleHttp/Psr7/Response.php', - 'GuzzleHttp\Psr7\ServerRequest' => __DIR__ . '/GuzzleHttp/Psr7/ServerRequest.php', - 'GuzzleHttp\Psr7\Stream' => __DIR__ . '/GuzzleHttp/Psr7/Stream.php', - 'GuzzleHttp\Psr7\StreamDecoratorTrait' => __DIR__ . '/GuzzleHttp/Psr7/StreamDecoratorTrait.php', - 'GuzzleHttp\Psr7\StreamWrapper' => __DIR__ . '/GuzzleHttp/Psr7/StreamWrapper.php', - 'GuzzleHttp\Psr7\UploadedFile' => __DIR__ . '/GuzzleHttp/Psr7/UploadedFile.php', - 'GuzzleHttp\Psr7\Uri' => __DIR__ . '/GuzzleHttp/Psr7/Uri.php', - 'GuzzleHttp\Psr7\UriNormalizer' => __DIR__ . '/GuzzleHttp/Psr7/UriNormalizer.php', - 'GuzzleHttp\Psr7\UriResolver' => __DIR__ . '/GuzzleHttp/Psr7/UriResolver.php', - 'GuzzleHttp\Psr7\functions' => __DIR__ . '/GuzzleHttp/Psr7/functions_include.php', - 'GuzzleHttp\Psr7\functions_include' => __DIR__ . '/GuzzleHttp/Psr7/functions_include.php', - 'Psr\Http\Message\MessageInterface' => __DIR__ . '/Psr/Http/Message/MessageInterface.php', - 'Psr\Http\Message\RequestInterface' => __DIR__ . '/Psr/Http/Message/RequestInterface.php', - 'Psr\Http\Message\ResponseInterface' => __DIR__ . '/Psr/Http/Message/ResponseInterface.php', - 'Psr\Http\Message\ServerRequestInterface' => __DIR__ . '/Psr/Http/Message/ServerRequestInterface.php', - 'Psr\Http\Message\StreamInterface' => __DIR__ . '/Psr/Http/Message/StreamInterface.php', - 'Psr\Http\Message\UploadedFileInterface' => __DIR__ . '/Psr/Http/Message/UploadedFileInterface.php', - 'Psr\Http\Message\UriInterface' => __DIR__ . '/Psr/Http/Message/UriInterface.php', -); - -spl_autoload_register(function ($class) use ($mapping) { - if (isset($mapping[$class])) { - require_once $mapping[$class]; - } -}, true); - -require_once __DIR__ . '/GuzzleHttp/functions_include.php'; -require_once __DIR__ . '/GuzzleHttp/Psr7/functions_include.php'; -require_once __DIR__ . '/GuzzleHttp/Promise/functions_include.php'; diff --git a/guzzle/readme_moodle.txt b/guzzle/readme_moodle.txt deleted file mode 100755 index 778862f..0000000 --- a/guzzle/readme_moodle.txt +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash -# Run this script from the guzzle folder to update Guzzle -# Update version.php verion and release -# Manually test that the GUzzle can be used with no issues. - -GUZZLEDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" - -echo Enter version number of Guzzle to update to. e.g. 6.3.0 -read varversion - - -find $GUZZLEDIR -mindepth 1 -maxdepth 1 | grep -v readme_moodle.txt | xargs rm -rf -wget -O $GUZZLEDIR/guzzle.zip "https://github.com/guzzle/guzzle/releases/download/$varversion/guzzle.zip" -unzip $GUZZLEDIR/guzzle.zip -d $GUZZLEDIR -sed -i -e 's/require/require_once/g' $GUZZLEDIR/autoloader.php -sed -i -e 's#GuzzleHttp/functions.php#GuzzleHttp/functions_include.php#g' $GUZZLEDIR/autoloader.php -sed -i -e 's#GuzzleHttp/Psr7/functions.php#GuzzleHttp/Psr7/functions_include.php#g' $GUZZLEDIR/autoloader.php -sed -i -e 's#GuzzleHttp/Promise/functions.php#GuzzleHttp/Promise/functions_include.php#g' $GUZZLEDIR/autoloader.php -rm $GUZZLEDIR/guzzle.zip -echo -echo 'Go update version.php' -echo $GUZZLEDIR diff --git a/tests/steps_form_test.php b/tests/steps_form_test.php index 0c298dc..21d6cbf 100644 --- a/tests/steps_form_test.php +++ b/tests/steps_form_test.php @@ -98,6 +98,7 @@ public function test_base_form() { * @param string $stepclass * * @dataProvider provide_steps + * @runInSeparateProcess */ public function test_step_form($steptype, $stepclass) { global $PAGE; diff --git a/thirdpartylibs.xml b/thirdpartylibs.xml deleted file mode 100644 index 49de517..0000000 --- a/thirdpartylibs.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - guzzle - Guzzle, an extensible PHP HTTP client - 6.3.0 - MIT - 1.0 - - \ No newline at end of file From 745e227e93f0588aae0d99c9b49be931d1a207cc Mon Sep 17 00:00:00 2001 From: Dmitrii Metelkin Date: Tue, 3 Sep 2024 13:44:28 +1000 Subject: [PATCH 2/6] issue #223: update tests for Moodle 4.4 --- tests/course_cat_lookup_step_test.php | 22 ++++++------ tests/course_lookup_step_test.php | 39 +++++++++++++++------ tests/datafield_manager_test.php | 6 ++-- tests/debounce_step_test.php | 16 ++++++--- tests/email_action_step_test.php | 10 +++++- tests/event_processor_test.php | 31 ++++++++++++++--- tests/fail_filter_step_test.php | 6 ++-- tests/fixtures/user_event_fixture.php | 2 +- tests/http_post_action_step_test.php | 43 ++++++++++++++++-------- tests/json_export_test.php | 9 ++--- tests/learn_process_test.php | 16 ++++----- tests/logdump_action_step_test.php | 8 ++--- tests/numcompare_filter_step_test.php | 18 +++++++--- tests/privacy_test.php | 13 +++---- tests/process_workflows_test.php | 34 ++++++++++++++++--- tests/processor_helper_test.php | 8 +++-- tests/role_assign_action_step_test.php | 17 ++++------ tests/role_unassign_action_step_test.php | 17 ++++------ tests/stringcompare_filter_step_test.php | 8 +++-- tests/user_lookup_step_test.php | 4 ++- tests/webservice_action_step_test.php | 22 +++++++----- tests/workflow_manager_test.php | 8 ++--- tests/workflow_process_test.php | 14 ++------ 23 files changed, 232 insertions(+), 139 deletions(-) diff --git a/tests/course_cat_lookup_step_test.php b/tests/course_cat_lookup_step_test.php index 17f94d5..3b06455 100644 --- a/tests/course_cat_lookup_step_test.php +++ b/tests/course_cat_lookup_step_test.php @@ -23,11 +23,9 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -defined('MOODLE_INTERNAL') || die(); +namespace tool_trigger; -global $CFG; - -class tool_trigger_course_cat_lookup_step_testcase extends advanced_testcase { +class course_cat_lookup_step_test extends \advanced_testcase { /** * Test user. @@ -61,11 +59,11 @@ public function setUp():void { $this->event = \core\event\course_category_created::create([ 'objectid' => $this->category->id, - 'context' => context_coursecat::instance($this->category->id), + 'context' => \context_coursecat::instance($this->category->id), ]); // Run as the cron user . - cron_setup_user(); + \core\cron::setup_user(); } /** @@ -105,7 +103,7 @@ public function test_execute_basic() { ); list($status, $stepresults) = $step->execute(null, null, $this->event, []); - $context = context_coursecat::instance($this->category->id); + $context = \context_coursecat::instance($this->category->id); $this->assertTrue($status); $this->assertEquals($this->category->id, $stepresults['category_id']); @@ -191,14 +189,14 @@ public function test_execute_category_id($categoryid, $status, $exception) { ); if ($exception) { - $this->expectException('Error'); - $this->expectExceptionMessageRegExp("/Specified category field not present in the workflow data:*/"); + $this->expectException(\invalid_parameter_exception::class); + $this->expectExceptionMessageMatches("/Specified category field not present in the workflow data:*/"); } list($statusresult, $stepresults) = $step->execute(null, null, $this->event, []); if ($status) { - $context = context_coursecat::instance($this->category->id); + $context = \context_coursecat::instance($this->category->id); $this->assertTrue($statusresult); $this->assertEquals($this->category->id, $stepresults['category_id']); $this->assertEquals($this->category->name, $stepresults['category_name']); @@ -221,7 +219,7 @@ public function test_execute_category_id_integer() { list($status, $stepresults) = $step->execute(null, null, $this->event, []); - $context = context_coursecat::instance($this->category->id); + $context = \context_coursecat::instance($this->category->id); $this->assertTrue($status); $this->assertEquals($this->category->id, $stepresults['category_id']); $this->assertEquals($this->category->name, $stepresults['category_name']); @@ -241,7 +239,7 @@ public function test_execute_category_id_string() { list($status, $stepresults) = $step->execute(null, null, $this->event, []); - $context = context_coursecat::instance($this->category->id); + $context = \context_coursecat::instance($this->category->id); $this->assertTrue($status); $this->assertEquals($this->category->id, $stepresults['category_id']); $this->assertEquals($this->category->name, $stepresults['category_name']); diff --git a/tests/course_lookup_step_test.php b/tests/course_lookup_step_test.php index 4700564..ac21c1c 100644 --- a/tests/course_lookup_step_test.php +++ b/tests/course_lookup_step_test.php @@ -23,11 +23,28 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -defined('MOODLE_INTERNAL') || die(); +namespace tool_trigger; -global $CFG; +class course_lookup_step_test extends \advanced_testcase { + + /** + * Test user. + * @var + */ + protected $user; + + /** + * Test user. + * @var + */ + protected $course; + + /** + * Event for testing. + * @var \core\event\user_graded + */ + private $event; -class tool_trigger_course_lookup_step_testcase extends advanced_testcase { /** * Create a "user_profile_viewed" event, of user1 viewing user2's * profile. And then run everything else as the cron user. @@ -41,7 +58,7 @@ public function setup():void { $this->event = \core\event\course_created::create([ 'objectid' => $this->course->id, - 'context' => context_course::instance($this->course->id), + 'context' => \context_course::instance($this->course->id), 'other' => [ 'shortname' => $this->course->shortname, 'fullname' => $this->course->fullname @@ -49,7 +66,7 @@ public function setup():void { ]); // Run as the cron user . - cron_setup_user(); + \core\cron::setup_user(); } /** @@ -65,7 +82,7 @@ public function test_execute_basic() { ); list($status, $stepresults) = $step->execute(null, null, $this->event, []); - $context = context_course::instance($this->course->id); + $context = \context_course::instance($this->course->id); $this->assertTrue($status); $this->assertEquals($this->course->id, $stepresults['course_id']); @@ -149,14 +166,14 @@ public function test_execute_course_id($courseid, $status, $exception) { ); if ($exception) { - $this->expectException('Error'); - $this->expectExceptionMessageRegExp("/Specified courseid field not present in the workflow data:*/"); + $this->expectException(\invalid_parameter_exception::class); + $this->expectExceptionMessageMatches("/Specified courseid field not present in the workflow data:*/"); } list($statusresult, $stepresults) = $step->execute(null, null, $this->event, []); if ($status) { - $context = context_course::instance($this->course->id); + $context = \context_course::instance($this->course->id); $this->assertTrue($statusresult); $this->assertEquals($this->course->id, $stepresults['course_id']); $this->assertEquals($this->course->fullname, $stepresults['course_fullname']); @@ -179,7 +196,7 @@ public function test_execute_course_id_integer() { list($status, $stepresults) = $step->execute(null, null, $this->event, []); - $context = context_course::instance($this->course->id); + $context = \context_course::instance($this->course->id); $this->assertTrue($status); $this->assertEquals($this->course->id, $stepresults['course_id']); $this->assertEquals($this->course->fullname, $stepresults['course_fullname']); @@ -199,7 +216,7 @@ public function test_execute_course_id_string() { list($status, $stepresults) = $step->execute(null, null, $this->event, []); - $context = context_course::instance($this->course->id); + $context = \context_course::instance($this->course->id); $this->assertTrue($status); $this->assertEquals($this->course->id, $stepresults['course_id']); $this->assertEquals($this->course->fullname, $stepresults['course_fullname']); diff --git a/tests/datafield_manager_test.php b/tests/datafield_manager_test.php index e04826c..f16f917 100644 --- a/tests/datafield_manager_test.php +++ b/tests/datafield_manager_test.php @@ -23,12 +23,14 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +namespace tool_trigger; + defined('MOODLE_INTERNAL') || die(); global $CFG; require_once(__DIR__.'/fixtures/user_event_fixture.php'); -class tool_trigger_datafield_manager_testcase extends advanced_testcase { +class datafield_manager_test extends \advanced_testcase { use \tool_trigger_user_event_fixture; /** @@ -102,7 +104,7 @@ public function test_render_datafields() { 'nullvalue' => null, 'emptyvalue' => '', 'arrayvalue' => [], - 'objectvalue' => new stdClass(), + 'objectvalue' => new \stdClass(), ]; $templatestring = 'Good tag: {tagexists}. diff --git a/tests/debounce_step_test.php b/tests/debounce_step_test.php index a502cb6..9ef4ba9 100644 --- a/tests/debounce_step_test.php +++ b/tests/debounce_step_test.php @@ -23,12 +23,14 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +namespace tool_trigger; + defined('MOODLE_INTERNAL') || die(); global $CFG; require_once("$CFG->libdir/gradelib.php"); -class debounce_step_testcase extends advanced_testcase { +class debounce_step_test extends \advanced_testcase { /** * The step to execute. * @@ -41,6 +43,12 @@ class debounce_step_testcase extends advanced_testcase { */ private $eventid; + /** + * Event for testing. + * @var \core\event\user_graded + */ + private $event; + /** * Create a "user_profile_viewed" event, of user1 viewing user2's * profile. And then run everything else as the cron user. @@ -54,13 +62,13 @@ public function setup():void { $user = $this->getDataGenerator()->create_user(); $this->getDataGenerator()->enrol_user($user->id, $course->id); - $gradecategory = grade_category::fetch_course_category($course->id); + $gradecategory = \grade_category::fetch_course_category($course->id); $gradecategory->load_grade_item(); $gradeitem = $gradecategory->grade_item; $gradeitem->update_final_grade($user->id, 10, 'gradebook'); - $gradegrade = new grade_grade(array('userid' => $user->id, 'itemid' => $gradeitem->id), true); + $gradegrade = new \grade_grade(array('userid' => $user->id, 'itemid' => $gradeitem->id), true); $gradegrade->grade_item = $gradeitem; $this->event = \core\event\user_graded::create_from_grade($gradegrade); @@ -76,7 +84,7 @@ public function setup():void { // Add this step to the events table. $processor = new \tool_trigger\event_processor(); - $entrymethod = new ReflectionMethod($processor, 'prepare_event'); + $entrymethod = new \ReflectionMethod($processor, 'prepare_event'); $entrymethod->setAccessible(true); $entry = $entrymethod->invoke($processor, $this->event); $this->eventid = $DB->insert_record('tool_trigger_events', $entry, true); diff --git a/tests/email_action_step_test.php b/tests/email_action_step_test.php index e6b9ca1..6747ac5 100644 --- a/tests/email_action_step_test.php +++ b/tests/email_action_step_test.php @@ -23,14 +23,22 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +namespace tool_trigger; + defined('MOODLE_INTERNAL') || die(); global $CFG; require_once(__DIR__.'/fixtures/user_event_fixture.php'); -class tool_trigger_email_action_step_testcase extends advanced_testcase { +class email_action_step_test extends \advanced_testcase { use \tool_trigger_user_event_fixture; + /** + * Messages sink for testing. + * @var \phpunit_message_sink + */ + private $sink; + /** * Create a "user_profile_viewed" event, of user1 viewing user2's * profile. And then run everything else as the cron user. diff --git a/tests/event_processor_test.php b/tests/event_processor_test.php index 2d997b0..d9af662 100644 --- a/tests/event_processor_test.php +++ b/tests/event_processor_test.php @@ -22,6 +22,8 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +namespace tool_trigger; + defined('MOODLE_INTERNAL') || die(); global $CFG; @@ -36,7 +38,26 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class tool_trigger_event_processor_testcase extends tool_trigger_testcase { +class event_processor_test extends \tool_trigger_testcase { + + /** + * Event array. + * @var + */ + protected $eventarr; + + /** + * Test user. + * @var + */ + protected $user; + + /** + * Test context. + * @var + */ + protected $context; + public function setup():void { $this->resetAfterTest(true); @@ -60,7 +81,7 @@ public function setup():void { $this->context = $context; // Run as the cron user. - cron_setup_user(); + \core\cron::setup_user(); } public function tearDown():void { @@ -84,7 +105,7 @@ public function test_is_event_ignored() { $event = \core\event\user_loggedin::create($this->eventarr); // We're testing a protected method, so we need to setup reflector magic. - $method = new ReflectionMethod('tool_trigger\event_processor', 'is_event_ignored'); + $method = new \ReflectionMethod('tool_trigger\event_processor', 'is_event_ignored'); $method->setAccessible(true); // Allow accessing of private method. $proxy = $method->invoke(new \tool_trigger\event_processor, $event); // Get result of invoked method. @@ -101,7 +122,7 @@ public function test_is_event_ignored_false() { $event = \core\event\user_loggedin::create($this->eventarr); // We're testing a protected method, so we need to setup reflector magic. - $method = new ReflectionMethod('tool_trigger\event_processor', 'is_event_ignored'); + $method = new \ReflectionMethod('tool_trigger\event_processor', 'is_event_ignored'); $method->setAccessible(true); // Allow accessing of private method. $proxy = $method->invoke(new \tool_trigger\event_processor, $event); // Get result of invoked method. @@ -115,7 +136,7 @@ public function test_prepare_event() { $event = \core\event\user_loggedin::create($this->eventarr); // We're testing a protected method, so we need to setup reflector magic. - $method = new ReflectionMethod('tool_trigger\event_processor', 'prepare_event'); + $method = new \ReflectionMethod('tool_trigger\event_processor', 'prepare_event'); $method->setAccessible(true); // Allow accessing of private method. $proxy = $method->invoke(new \tool_trigger\event_processor, $event); // Get result of invoked method. $expected = unserialize($proxy['other']); diff --git a/tests/fail_filter_step_test.php b/tests/fail_filter_step_test.php index 2d08fba..16b9384 100644 --- a/tests/fail_filter_step_test.php +++ b/tests/fail_filter_step_test.php @@ -23,11 +23,9 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -defined('MOODLE_INTERNAL') || die(); +namespace tool_trigger; -global $CFG; - -class tool_trigger_fail_filter_step_testcase extends basic_testcase { +class fail_filter_step_test extends \basic_testcase { public function test_execute() { $step = new \tool_trigger\steps\filters\fail_filter_step(); list($status) = $step->execute(null, null, null, null); diff --git a/tests/fixtures/user_event_fixture.php b/tests/fixtures/user_event_fixture.php index 7f89be5..4aa0931 100644 --- a/tests/fixtures/user_event_fixture.php +++ b/tests/fixtures/user_event_fixture.php @@ -71,7 +71,7 @@ public function setup_user_event() { $this->event->trigger(); // Run as the cron user . - cron_setup_user(); + \core\cron::setup_user(); } /** diff --git a/tests/http_post_action_step_test.php b/tests/http_post_action_step_test.php index 24add51..35f1876 100644 --- a/tests/http_post_action_step_test.php +++ b/tests/http_post_action_step_test.php @@ -23,22 +23,37 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -defined('MOODLE_INTERNAL') || die(); +namespace tool_trigger; -global $CFG; -require_once($CFG->dirroot . '/admin/tool/trigger/guzzle/autoloader.php'); +class http_post_action_step_test extends \advanced_testcase { -class tool_trigger_http_post_action_step_testcase extends advanced_testcase { + /** + * Test user. + * @var + */ + protected $user; + + /** + * A list of sent requests. + * @var + */ + protected $requestssent; + + /** + * Test event. + * @var + */ + protected $event; public function setup():void { $this->resetAfterTest(true); - $this->requests_sent = []; + $this->requestssent = []; $this->user = \core_user::get_user_by_username('admin'); $this->event = \core\event\user_profile_viewed::create([ 'objectid' => $this->user->id, 'relateduserid' => $this->user->id, - 'context' => context_user::instance($this->user->id), + 'context' => \context_user::instance($this->user->id), 'other' => [ 'courseid' => 1, 'courseshortname' => 'short name', @@ -47,7 +62,7 @@ public function setup():void { ]); // Run as the cron user . - cron_setup_user(); + \core\cron::setup_user(); } private function make_mock_http_handler($response) { @@ -56,7 +71,7 @@ private function make_mock_http_handler($response) { new \GuzzleHttp\Handler\MockHandler([$response]) ); $stack->push( - \GuzzleHttp\Middleware::history($this->requests_sent) + \GuzzleHttp\Middleware::history($this->requestssent) ); return $stack; @@ -133,7 +148,7 @@ public function test_execute_200(string $httpmethod) { list($status, $stepresults) = $step->execute(null, null, $this->event, []); $this->assertTrue($status); - $this->assertEquals(1, count($this->requests_sent)); + $this->assertEquals(1, count($this->requestssent)); $this->assertEquals(200, $stepresults['http_response_status_code']); $this->assertEquals('All good', $stepresults['http_response_status_message']); $this->assertEquals('OK', $stepresults['http_response_body']); @@ -163,7 +178,7 @@ public function test_execute_404(string $httpmethod) { list($status, $stepresults) = $step->execute(null, null, $this->event, []); $this->assertTrue($status); - $this->assertEquals(1, count($this->requests_sent)); + $this->assertEquals(1, count($this->requestssent)); $this->assertEquals(404, $stepresults['http_response_status_code']); $this->assertEquals('Huh?', $stepresults['http_response_status_message']); $this->assertEquals(json_encode(false), $stepresults['http_response_body']); @@ -201,10 +216,10 @@ public function test_execute_with_datafields() { list($status) = $step->execute(null, null, $this->event, $prevstepresults); $this->assertTrue($status); - $this->assertEquals(1, count($this->requests_sent)); + $this->assertEquals(1, count($this->requestssent)); // Inspect the (mock) requests sent, to check that the substitutions were successful. - $request = $this->requests_sent[0]['request']; + $request = $this->requestssent[0]['request']; // The datafield in the header line didn't need to be urlencoded, so it should be exactly the same. $this->assertEquals( @@ -259,10 +274,10 @@ public function test_execute_with_datafields_json() { list($status) = $step->execute(null, null, $this->event, $prevstepresults); $this->assertTrue($status); - $this->assertEquals(1, count($this->requests_sent)); + $this->assertEquals(1, count($this->requestssent)); // Inspect the (mock) requests sent, to check that the substitutions were successful. - $request = $this->requests_sent[0]['request']; + $request = $this->requestssent[0]['request']; // The datafield in the header line didn't need to be urlencoded, so it should be exactly the same. $this->assertEquals( diff --git a/tests/json_export_test.php b/tests/json_export_test.php index 9b997ec..411cfe4 100644 --- a/tests/json_export_test.php +++ b/tests/json_export_test.php @@ -22,9 +22,7 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -defined('MOODLE_INTERNAL') || die(); - -global $CFG; +namespace tool_trigger; /** * JSON export unit tests. @@ -33,8 +31,7 @@ * @copyright Matt Porritt * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ - -class tool_trigger_json_export_testcase extends advanced_testcase { +class json_export_test extends \advanced_testcase { public function setup():void { $this->resetAfterTest(true); @@ -79,7 +76,7 @@ public function test_set_filename() { $jsonclass = new \tool_trigger\json\json_export($workflowobj); // We're testing a private method, so we need to setup reflector magic. - $method = new ReflectionMethod('\tool_trigger\json\json_export', 'get_filename'); + $method = new \ReflectionMethod('\tool_trigger\json\json_export', 'get_filename'); $method->setAccessible(true); // Allow accessing of private method. $proxy = $method->invoke($jsonclass, $workflowobj->name, $now); // Get result of invoked method. diff --git a/tests/learn_process_test.php b/tests/learn_process_test.php index 18057e8..d47b957 100644 --- a/tests/learn_process_test.php +++ b/tests/learn_process_test.php @@ -22,9 +22,7 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -defined('MOODLE_INTERNAL') || die(); - -global $CFG; +namespace tool_trigger; /** * Learn processor unit tests. @@ -34,7 +32,7 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class tool_trigger_learn_process_testcase extends advanced_testcase { +class learn_process_test extends \advanced_testcase { public function setup():void { $this->resetAfterTest(true); @@ -121,7 +119,7 @@ public function test_get_learnt_events() { $expected = array('\core\event\fake_event', '\core\event\user_loggedout'); // Expected result. // We're testing a private method, so we need to setup reflector magic. - $method = new ReflectionMethod('tool_trigger\learn_process', 'get_learnt_events'); + $method = new \ReflectionMethod('tool_trigger\learn_process', 'get_learnt_events'); $method->setAccessible(true); // Allow accessing of private method. $proxy = $method->invoke(new \tool_trigger\learn_process); // Get result of invoked method. @@ -144,7 +142,7 @@ public function test_get_learnt_records() { $expected = array('\core\event\fake_event', '\core\event\fake_event'); // Expected result. // We're testing a private method, so we need to setup reflector magic. - $method = new ReflectionMethod('tool_trigger\learn_process', 'get_learnt_records'); + $method = new \ReflectionMethod('tool_trigger\learn_process', 'get_learnt_records'); $method->setAccessible(true); // Allow accessing of private method. $proxy = $method->invoke(new \tool_trigger\learn_process, '\core\event\fake_event'); // Get result of invoked method. @@ -170,7 +168,7 @@ public function test_convert_record_type() { $expected = $this->get_event_fields(); // Expected result. // We're testing a private method, so we need to setup reflector magic. - $method = new ReflectionMethod('tool_trigger\learn_process', 'convert_record_type'); + $method = new \ReflectionMethod('tool_trigger\learn_process', 'convert_record_type'); $method->setAccessible(true); // Allow accessing of private method. $proxy = $method->invoke(new \tool_trigger\learn_process, $learntevent, false); // Get result of invoked method. @@ -192,7 +190,7 @@ public function test_merge_records() { $expected['oher_foo'] = 'string'; // We're testing a private method, so we need to setup reflector magic. - $method = new ReflectionMethod('tool_trigger\learn_process', 'merge_records'); + $method = new \ReflectionMethod('tool_trigger\learn_process', 'merge_records'); $method->setAccessible(true); // Allow accessing of private method. $proxy = $method->invoke(new \tool_trigger\learn_process, $processedrecords); // Get result of invoked method. @@ -227,7 +225,7 @@ public function test_merge_db_record() { $expected = array_merge($processedrecord, $processedrecord2); // We're testing a private method, so we need to setup reflector magic. - $method = new ReflectionMethod('tool_trigger\learn_process', 'merge_json_fields'); + $method = new \ReflectionMethod('tool_trigger\learn_process', 'merge_json_fields'); $method->setAccessible(true); // Allow accessing of private method. $proxy = $method->invoke(new \tool_trigger\learn_process, $record, $exists); // Get result of invoked method. diff --git a/tests/logdump_action_step_test.php b/tests/logdump_action_step_test.php index e1849e9..4df1092 100644 --- a/tests/logdump_action_step_test.php +++ b/tests/logdump_action_step_test.php @@ -23,18 +23,16 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -defined('MOODLE_INTERNAL') || die(); +namespace tool_trigger; -global $CFG; - -class tool_trigger_logdump_action_step_testcase extends basic_testcase { +class logdump_action_step_test extends \basic_testcase { public function test_execute() { // Don't overload var_dump by xdebug to solve the unit test when we run it with xdebug. ini_set('xdebug.overload_var_dump', 0); $user = \core_user::get_user_by_username('admin'); - $context = context_user::instance($user->id); + $context = \context_user::instance($user->id); $event = \core\event\user_profile_viewed::create([ 'objectid' => $user->id, 'relateduserid' => $user->id, diff --git a/tests/numcompare_filter_step_test.php b/tests/numcompare_filter_step_test.php index cbc295e..80eff6d 100644 --- a/tests/numcompare_filter_step_test.php +++ b/tests/numcompare_filter_step_test.php @@ -23,13 +23,23 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +namespace tool_trigger; + +use tool_trigger\steps\filters\numcompare_filter_step; + defined('MOODLE_INTERNAL') || die(); global $CFG; require_once("$CFG->libdir/gradelib.php"); -use \tool_trigger\steps\filters\numcompare_filter_step; -class tool_trigger_numcompare_filter_step_testcase extends advanced_testcase { +class numcompare_filter_step_test extends \advanced_testcase { + + /** + * Event for testing. + * @var \core\event\user_graded + */ + private $event; + /** * Create a "user_profile_viewed" event, of user1 viewing user2's * profile. And then run everything else as the cron user. @@ -42,13 +52,13 @@ public function setup():void { $user = $this->getDataGenerator()->create_user(); $this->getDataGenerator()->enrol_user($user->id, $course->id); - $gradecategory = grade_category::fetch_course_category($course->id); + $gradecategory = \grade_category::fetch_course_category($course->id); $gradecategory->load_grade_item(); $gradeitem = $gradecategory->grade_item; $gradeitem->update_final_grade($user->id, 10, 'gradebook'); - $gradegrade = new grade_grade(array('userid' => $user->id, 'itemid' => $gradeitem->id), true); + $gradegrade = new \grade_grade(array('userid' => $user->id, 'itemid' => $gradeitem->id), true); $gradegrade->grade_item = $gradeitem; $this->event = \core\event\user_graded::create_from_grade($gradegrade); diff --git a/tests/privacy_test.php b/tests/privacy_test.php index 3d2fb9e..4681fc2 100644 --- a/tests/privacy_test.php +++ b/tests/privacy_test.php @@ -23,9 +23,10 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -use \tool_trigger\privacy\provider; -use \core_privacy\local\request\approved_contextlist; -use \core_privacy\local\request\approved_userlist; +namespace tool_trigger; + +use tool_trigger\privacy\provider; +use core_privacy\local\request\approved_userlist; /** * Privacy test for the event monitor @@ -35,7 +36,7 @@ * @copyright 2019 Matt Porritt * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class tool_trigger_privacy_testcase extends advanced_testcase { +class privacy_test extends \advanced_testcase { /** * Set up method. @@ -65,7 +66,7 @@ public function test_get_users_in_context() { $this->assertEmpty($userlist); // Add test data to database. - $eventrecord = new stdClass(); + $eventrecord = new \stdClass(); $eventrecord->eventname = '\core\event\user_login_failed'; $eventrecord->component = 'core'; $eventrecord->action = 'failed'; @@ -110,7 +111,7 @@ public function test_delete_data_for_users() { $this->setUser($user); // Add test data to database. - $eventrecord = new stdClass(); + $eventrecord = new \stdClass(); $eventrecord->eventname = '\core\event\user_login_failed'; $eventrecord->component = 'core'; $eventrecord->action = 'failed'; diff --git a/tests/process_workflows_test.php b/tests/process_workflows_test.php index 4d8c4c0..d645fe9 100644 --- a/tests/process_workflows_test.php +++ b/tests/process_workflows_test.php @@ -22,9 +22,7 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -defined('MOODLE_INTERNAL') || die(); - -global $CFG; +namespace tool_trigger; /** * Workflow form processing unit tests. @@ -34,7 +32,33 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class tool_trigger_process_workflow_testcase extends advanced_testcase { +class process_workflows_test extends \advanced_testcase { + + /** + * Test user. + * @var + */ + protected $user; + + /** + * Test context. + * @var + */ + protected $context; + + /** + * Test event. + * @var + */ + protected $event; + + /** + * Test event object. + * @var + */ + protected $eventobj; + + public function setup():void { global $DB; @@ -73,7 +97,7 @@ public function setup():void { $this->context = $context; // Run as the cron user . - cron_setup_user(); + \core\cron::setup_user(); } diff --git a/tests/processor_helper_test.php b/tests/processor_helper_test.php index 04f640e..515130b 100644 --- a/tests/processor_helper_test.php +++ b/tests/processor_helper_test.php @@ -22,13 +22,15 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +namespace tool_trigger; + defined('MOODLE_INTERNAL') || die(); global $CFG; require_once('tool_trigger_testcase.php'); -class tool_trigger_processor_helper_testcase extends tool_trigger_testcase { +class processor_helper_test extends \tool_trigger_testcase { /** * Anonymous class for testing. @@ -77,7 +79,7 @@ public function test_restore_event() { ]; // Empty data. - $actual = $this->testclass->restore_event(new stdClass()); + $actual = $this->testclass->restore_event(new \stdClass()); $this->assertNull($actual); // Non-existing event. @@ -120,7 +122,7 @@ public function test_execute_step() { $workflowid = $this->create_workflow(); $steps = $DB->get_records('tool_trigger_steps', ['workflowid' => $workflowid]); foreach ($steps as $step) { - $result = $this->testclass->execute_step($step, new stdClass(), $event, []); + $result = $this->testclass->execute_step($step, new \stdClass(), $event, []); $this->assertCount(2, $result); $this->assertTrue($result[0]); $this->assertTrue(is_array($result[1])); diff --git a/tests/role_assign_action_step_test.php b/tests/role_assign_action_step_test.php index 47c65f4..dccffa6 100644 --- a/tests/role_assign_action_step_test.php +++ b/tests/role_assign_action_step_test.php @@ -14,6 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . +namespace tool_trigger; + /** * Tests for role_assign_action_step. * @@ -22,12 +24,7 @@ * @copyright 2019 Catalyst IT * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ - -defined('MOODLE_INTERNAL') || die(); - -global $CFG; - -class role_assign_action_step_testcase extends advanced_testcase { +class role_assign_action_step_test extends \advanced_testcase { /** * Test user. @@ -69,7 +66,7 @@ public function setUp():void { $this->user = $this->getDataGenerator()->create_user(); $this->course = $this->getDataGenerator()->create_course(); $this->roleid = $this->getDataGenerator()->create_role(); - $this->context = context_course::instance($this->course->id); + $this->context = \context_course::instance($this->course->id); $this->setUser($this->user); @@ -86,7 +83,7 @@ public function setUp():void { ]); // Run as the cron user . - cron_setup_user(); + \core\cron::setup_user(); } /** @@ -154,8 +151,8 @@ public function test_execute_nosuchfield() { ]) ); - $this->expectException('Error'); - $this->expectExceptionMessageRegExp("/Specified userid field not present in the workflow data:*/"); + $this->expectException(\invalid_parameter_exception::class); + $this->expectExceptionMessageMatches("/Specified userid field not present in the workflow data:*/"); $step->execute(null, null, $this->event, []); } } diff --git a/tests/role_unassign_action_step_test.php b/tests/role_unassign_action_step_test.php index 9c5b052..5c289a3 100644 --- a/tests/role_unassign_action_step_test.php +++ b/tests/role_unassign_action_step_test.php @@ -14,6 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . +namespace tool_trigger; + /** * Tests for role_unassign_action_step. * @@ -22,12 +24,7 @@ * @author Nicholas Hoobin * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ - -defined('MOODLE_INTERNAL') || die(); - -global $CFG; - -class role_unassign_action_step_testcase extends advanced_testcase { +class role_unassign_action_step_test extends \advanced_testcase { /** * Test user. @@ -69,7 +66,7 @@ public function setUp():void { $this->user = $this->getDataGenerator()->create_user(); $this->course = $this->getDataGenerator()->create_course(); $this->roleid = $this->getDataGenerator()->create_role(); - $this->context = context_course::instance($this->course->id); + $this->context = \context_course::instance($this->course->id); $this->setUser($this->user); @@ -88,7 +85,7 @@ public function setUp():void { role_assign($this->roleid, $this->user->id, $this->context->id); // Run as the cron user . - cron_setup_user(); + \core\cron::setup_user(); } /** @@ -157,8 +154,8 @@ public function test_execute_nosuchfield() { ]) ); - $this->expectException('Error'); - $this->expectExceptionMessageRegExp("/Specified userid field not present in the workflow data:*/"); + $this->expectException(\invalid_parameter_exception::class); + $this->expectExceptionMessageMatches("/Specified userid field not present in the workflow data:*/"); $step->execute(null, null, $this->event, []); } } diff --git a/tests/stringcompare_filter_step_test.php b/tests/stringcompare_filter_step_test.php index f5f8746..b84fb46 100644 --- a/tests/stringcompare_filter_step_test.php +++ b/tests/stringcompare_filter_step_test.php @@ -23,16 +23,20 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +namespace tool_trigger; + +use tool_trigger\steps\filters\stringcompare_filter_step; + defined('MOODLE_INTERNAL') || die(); global $CFG; require_once(__DIR__.'/fixtures/user_event_fixture.php'); -use \tool_trigger\steps\filters\stringcompare_filter_step; -class tool_trigger_stringcompare_filter_step_testcase extends advanced_testcase { +class stringcompare_filter_step_test extends \advanced_testcase { use \tool_trigger_user_event_fixture; + /** * Create a "user_profile_viewed" event, of user1 viewing user2's * profile. And then run everything else as the cron user. diff --git a/tests/user_lookup_step_test.php b/tests/user_lookup_step_test.php index f59f078..83ed702 100644 --- a/tests/user_lookup_step_test.php +++ b/tests/user_lookup_step_test.php @@ -23,12 +23,14 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +namespace tool_trigger; + defined('MOODLE_INTERNAL') || die(); global $CFG; require_once(__DIR__.'/fixtures/user_event_fixture.php'); -class tool_trigger_user_lookup_testcase extends advanced_testcase { +class user_lookup_step_test extends \advanced_testcase { use \tool_trigger_user_event_fixture; /** diff --git a/tests/webservice_action_step_test.php b/tests/webservice_action_step_test.php index 423ee20..1dc0cda 100644 --- a/tests/webservice_action_step_test.php +++ b/tests/webservice_action_step_test.php @@ -14,6 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . +namespace tool_trigger; + defined('MOODLE_INTERNAL') || die(); global $CFG; @@ -27,7 +29,7 @@ * @copyright Catalyst IT, 2022 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class tool_trigger_webservice_action_step_testcase extends \advanced_testcase { +class webservice_action_step_test extends \advanced_testcase { use \tool_trigger_user_event_fixture; /** @@ -40,6 +42,7 @@ public function setup(): void { /** * Simple test, with a successful result. + * @runInSeparateProcess */ public function test_with_valid_call_to_enrol_user() { global $DB; @@ -58,7 +61,7 @@ public function test_with_valid_call_to_enrol_user() { $this->assertEquals(0, $adminuser->lastlogin); // Check if user is NOT enrolled yet. - $context = context_course::instance($this->course->id); + $context = \context_course::instance($this->course->id); $enrolled = is_enrolled($context, $this->user1->id); $this->assertFalse($enrolled); @@ -70,7 +73,7 @@ public function test_with_valid_call_to_enrol_user() { $this->assertArrayNotHasKey('exception', $stepresults); // Check if user is now enrolled as expected, showing the call did indeed work as expected. - $context = context_course::instance($this->course->id); + $context = \context_course::instance($this->course->id); $enrolled = is_enrolled($context, $this->user1->id); $this->assertTrue($enrolled); @@ -81,6 +84,7 @@ public function test_with_valid_call_to_enrol_user() { /** * Test when the username is not valid, so the step fails with an exception. + * @runInSeparateProcess */ public function test_with_invalid_username() { $stepsettings = [ @@ -90,12 +94,13 @@ public function test_with_invalid_username() { '{"enrolments":{"0":{"roleid":"5","userid":' . $this->user1->id . ',"courseid":' . $this->course->id . '}}}', ]; $step = new \tool_trigger\steps\actions\webservice_action_step(json_encode($stepsettings)); - $this->expectException(dml_missing_record_exception::class); + $this->expectException(\dml_missing_record_exception::class); $step->execute(null, null, $this->event, []); } /** * Test with non_existent function + * @runInSeparateProcess */ public function test_with_non_existent_function() { $adminuser = get_admin(); @@ -108,13 +113,14 @@ public function test_with_non_existent_function() { $step = new \tool_trigger\steps\actions\webservice_action_step(json_encode($stepsettings)); // Manually catch the exception to check the message - $this->expectException('Error'); - $this->expectExceptionMessageRegExp('/external_functions/'); + $this->expectException(\dml_missing_record_exception::class); + $this->expectExceptionMessageMatches('/external_functions/'); $step->execute(null, null, $this->event, []); } /** * Test with invalid function parameters + * @runInSeparateProcess */ public function test_with_invalid_function_parameters() { $adminuser = get_admin(); @@ -126,9 +132,9 @@ public function test_with_invalid_function_parameters() { ]; $step = new \tool_trigger\steps\actions\webservice_action_step(json_encode($stepsettings)); - $this->expectException('Error'); + $this->expectException(\coding_exception::class); // Setup the expectations for exception format. - $this->expectExceptionMessageRegExp('/errorcode.*invalidparameter.*debuginfo.*enrolments/'); + $this->expectExceptionMessageMatches('/errorcode.*invalidparameter.*debuginfo.*enrolments/'); $step->execute(null, null, $this->event, []); } } diff --git a/tests/workflow_manager_test.php b/tests/workflow_manager_test.php index 235556d..491652a 100644 --- a/tests/workflow_manager_test.php +++ b/tests/workflow_manager_test.php @@ -22,9 +22,7 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -defined('MOODLE_INTERNAL') || die(); - -global $CFG; +namespace tool_trigger; /** * Workflow manager unit tests. @@ -33,7 +31,7 @@ * @copyright Matt Porritt * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class tool_trigger_workflow_manager_testcase extends advanced_testcase { +class workflow_manager_test extends \advanced_testcase { /** * Test getting step class names by step type. @@ -66,6 +64,8 @@ public function test_lookup_step_names() { /** * Test getting steps by step type. + * + * @runInSeparateProcess */ public function test_get_steps_by_type() { diff --git a/tests/workflow_process_test.php b/tests/workflow_process_test.php index 6586726..f378b5b 100644 --- a/tests/workflow_process_test.php +++ b/tests/workflow_process_test.php @@ -14,17 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -/** - * Workflow form processing unit tests. - * - * @package tool_trigger - * @copyright Matt Porritt - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -defined('MOODLE_INTERNAL') || die(); - -global $CFG; +namespace tool_trigger; /** * Workflow form processing unit tests. @@ -33,7 +23,7 @@ * @copyright Matt Porritt * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class tool_trigger_workflow_process_testcase extends advanced_testcase { +class workflow_process_test extends \advanced_testcase { /** * Test workflow process form data From bf8fbde4c4c0baed517256db9dd2cb1fa5c7f73c Mon Sep 17 00:00:00 2001 From: Dmitrii Metelkin Date: Tue, 3 Sep 2024 13:45:10 +1000 Subject: [PATCH 3/6] issue #223: update main files for Moodle 4.4 --- classes/event_processor.php | 4 ++-- classes/output/manageworkflows/renderable.php | 1 - classes/output/manageworkflows/renderer.php | 7 +++---- classes/output/workflowhistory/renderer.php | 6 +++--- classes/steps/actions/assign_cohort_action_step.php | 11 ++++++++++- classes/steps/actions/http_post_action_step.php | 9 +++------ classes/steps/filters/numcompare_filter_step.php | 3 +++ classes/steps/filters/stringcompare_filter_step.php | 7 +++++++ classes/steps/lookups/cohort_lookup_step.php | 7 +++++++ classes/workflow.php | 5 +++++ edit.php | 12 +++++++----- export.php | 2 +- exportrun.php | 2 +- manageworkflow.php | 4 ++-- 14 files changed, 54 insertions(+), 26 deletions(-) diff --git a/classes/event_processor.php b/classes/event_processor.php index 322a03f..ea5ed36 100644 --- a/classes/event_processor.php +++ b/classes/event_processor.php @@ -276,7 +276,7 @@ private function process_realtime_workflow($workflow, $evententry) { * history and auditing. * * @param int $workflowid The workflow id to record. - * @param stdClass $event the event that triggered this workflow. + * @param \stdClass $event the event that triggered this workflow. * @param int $attemptnum The number of attempts for this event. * @return int|null the id of the recorded workflow record or null. */ @@ -799,7 +799,7 @@ public static function rerun_all_error_runs($workflow, $historic = false) { * Records a cancelled workflow, used in debouncing. * * @param int $workflowid - * @param stdClass $event + * @param \stdClass $event * @param int $runid * @param boolean $deferred * @return void diff --git a/classes/output/manageworkflows/renderable.php b/classes/output/manageworkflows/renderable.php index 162e032..72d3bc8 100644 --- a/classes/output/manageworkflows/renderable.php +++ b/classes/output/manageworkflows/renderable.php @@ -90,7 +90,6 @@ public function __construct($uniqueid, \moodle_url $url, $perpage = 100) { $this->pageable(true); $this->is_downloadable(false); $this->define_baseurl($url); - $this->workflowid = 0; } /** diff --git a/classes/output/manageworkflows/renderer.php b/classes/output/manageworkflows/renderer.php index 7741dfb..190a149 100644 --- a/classes/output/manageworkflows/renderer.php +++ b/classes/output/manageworkflows/renderer.php @@ -41,7 +41,7 @@ class renderer extends \plugin_renderer_base { * @return string to display on the mangerules page. */ protected function render_renderable(renderable $renderable) { - $o = $this->render_add_button($renderable->workflowid); + $o = $this->render_add_button(); $o .= ' '; $o .= $this->render_import_button(); $o .= $this->render_table($renderable); @@ -69,14 +69,13 @@ protected function render_table(renderable $renderable) { /** * Html to add a button for adding a new workflow. * - * @param int $workflowid The workflow the button applies too. * @return string html for the button. */ - protected function render_add_button($workflowid) { + protected function render_add_button() { global $CFG; $button = \html_writer::tag('button', get_string('addworkflow', 'tool_trigger'), ['class' => 'btn btn-primary']); - $addurl = new \moodle_url($CFG->wwwroot. '/admin/tool/trigger/edit.php', array('workflowid' => $workflowid)); + $addurl = new \moodle_url($CFG->wwwroot. '/admin/tool/trigger/edit.php', array('workflowid' => 0)); return \html_writer::link($addurl, $button); } diff --git a/classes/output/workflowhistory/renderer.php b/classes/output/workflowhistory/renderer.php index d8e5a57..8455a14 100644 --- a/classes/output/workflowhistory/renderer.php +++ b/classes/output/workflowhistory/renderer.php @@ -84,7 +84,7 @@ public function render_workflowhistory_table($workflowid, $searchparams = [], $d $url = new \moodle_url('/admin/tool/trigger/history.php', $searchparams); $renderable = new \tool_trigger\output\workflowhistory\workflowhistory_renderable('triggerhistory', $url, $searchparams, $download, 100); - $namefields = get_all_user_name_fields(true, 'u'); + $namefields = implode(',', \core_user\fields::get_name_fields()); $sqlfields = "tfh.*, {$namefields}"; $sqlfrom = '{tool_trigger_workflow_hist} tfh LEFT JOIN {user} u ON tfh.userid = u.id'; $sqlwhere = 'tfh.workflowid = :workflow'; @@ -274,7 +274,7 @@ public function run_actions_button($run, $statusonly = false, $searchparams = [] private function rerun_all_historic_button($workflowid) { $url = new \moodle_url('/admin/tool/trigger/history.php', ['action' => 'rerunallhist', 'sesskey' => sesskey(), 'id' => $workflowid, 'workflow' => $workflowid]); - $btn = new \single_button($url, get_string('rerunallhist', 'tool_trigger'), 'get', true); + $btn = new \single_button($url, get_string('rerunallhist', 'tool_trigger'), 'get', \single_button::BUTTON_PRIMARY); echo $this->render($btn); } @@ -286,7 +286,7 @@ private function rerun_all_historic_button($workflowid) { private function rerun_all_current_button($workflowid) { $url = new \moodle_url('/admin/tool/trigger/history.php', ['action' => 'rerunallcurr', 'sesskey' => sesskey(), 'id' => $workflowid, 'workflow' => $workflowid]); - $btn = new \single_button($url, get_string('rerunallcurr', 'tool_trigger'), 'get', true); + $btn = new \single_button($url, get_string('rerunallcurr', 'tool_trigger'), 'get', \single_button::BUTTON_PRIMARY); echo $this->render($btn); } } diff --git a/classes/steps/actions/assign_cohort_action_step.php b/classes/steps/actions/assign_cohort_action_step.php index faff968..7097870 100644 --- a/classes/steps/actions/assign_cohort_action_step.php +++ b/classes/steps/actions/assign_cohort_action_step.php @@ -28,9 +28,18 @@ require_once($CFG->dirroot.'/cohort/lib.php'); class assign_cohort_action_step extends base_action_step { + use \tool_trigger\helper\datafield_manager; + /** User field. + * @var int + */ + protected $useridfield; - use \tool_trigger\helper\datafield_manager; + /** + * Cohort field. + * @var int + */ + protected $cohortidfield; /** * The fields supplied by this step. diff --git a/classes/steps/actions/http_post_action_step.php b/classes/steps/actions/http_post_action_step.php index fc1c38b..4cddc4b 100644 --- a/classes/steps/actions/http_post_action_step.php +++ b/classes/steps/actions/http_post_action_step.php @@ -26,7 +26,6 @@ /** * HTTP action step class. - * * @package tool_trigger * @copyright Matt Porritt * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later @@ -51,6 +50,8 @@ class http_post_action_step extends base_action_step { protected $headers; protected $params; private $httphandler = null; + private $expectedresponse; + private $jsonencode; /** * The fields supplied by this step. @@ -127,15 +128,11 @@ public function get_http_client() { * @return array if execution was succesful and the response from the execution. */ public function execute($step, $trigger, $event, $stepresults) { - global $CFG; - require_once($CFG->dirroot . '/admin/tool/trigger/guzzle/autoloader.php'); - $this->update_datafields($event, $stepresults); $headers = $this->render_datafields($this->headers); $headers = explode("\n", str_replace("\r\n", "\n", $headers)); - $headers = \GuzzleHttp\headers_from_lines($headers); - + $headers = \GuzzleHttp\Utils::headersFromLines($headers); // ... urlencode the values of any substitutions being placed into the URL // or the POST params. $urlencodecallback = function($v) { diff --git a/classes/steps/filters/numcompare_filter_step.php b/classes/steps/filters/numcompare_filter_step.php index 62aa1fc..17675e3 100644 --- a/classes/steps/filters/numcompare_filter_step.php +++ b/classes/steps/filters/numcompare_filter_step.php @@ -44,6 +44,9 @@ class numcompare_filter_step extends base_filter_step { const OPERATOR_GTE = '>='; const OPERATOR_GT = '>'; + protected $field1; + protected $field2; + protected $operator; /** diff --git a/classes/steps/filters/stringcompare_filter_step.php b/classes/steps/filters/stringcompare_filter_step.php index 85bf557..79b9986 100644 --- a/classes/steps/filters/stringcompare_filter_step.php +++ b/classes/steps/filters/stringcompare_filter_step.php @@ -101,6 +101,13 @@ class stringcompare_filter_step extends base_filter_step { */ protected $wantmatch = true; + /** + * Error on fail. + * + * @var bool + */ + protected $erroronfail; + /** * {@inheritDoc} * @see \tool_trigger\steps\base\base_step::init() diff --git a/classes/steps/lookups/cohort_lookup_step.php b/classes/steps/lookups/cohort_lookup_step.php index 483076f..d5bcd1c 100644 --- a/classes/steps/lookups/cohort_lookup_step.php +++ b/classes/steps/lookups/cohort_lookup_step.php @@ -43,6 +43,13 @@ class cohort_lookup_step extends base_lookup_step { */ private $outputprefix = null; + /** + * User field. + * + * @var string + */ + private $useridfield; + /** * The fields supplied by this step. * A string containing all the cohorts a user is assigned to. diff --git a/classes/workflow.php b/classes/workflow.php index b5adbff..6dfdbfe 100644 --- a/classes/workflow.php +++ b/classes/workflow.php @@ -83,6 +83,11 @@ class workflow { */ public $numsteps; + /** + * @var int + */ + public $debug; + /** * Constructor. * diff --git a/edit.php b/edit.php index 65b1370..92d8c04 100644 --- a/edit.php +++ b/edit.php @@ -67,11 +67,13 @@ // Group the events by plugin. $pluginlist = \tool_monitor\eventlist::get_plugin_list($eventlist); $plugineventlist = []; -foreach ($pluginlist as $plugin => $pluginname) { - foreach ($eventlist[$plugin] as $event => $eventname) { - // Filter out events which cannot be triggered for some reason. - if (!$event::is_deprecated()) { - $plugineventlist[$event] = "${pluginname}: ${eventname}"; +foreach ($pluginlist as $plugintype) { + foreach ($plugintype as $plugin => $pluginname) { + foreach ($eventlist[$plugin] as $event => $eventname) { + // Filter out events which cannot be triggered for some reason. + if (!$event::is_deprecated()) { + $plugineventlist[$event] = "$pluginname: $eventname"; + } } } } diff --git a/export.php b/export.php index 8a96de2..019c186 100644 --- a/export.php +++ b/export.php @@ -33,7 +33,7 @@ $workflowrecord = \tool_trigger\workflow_manager::get_workflow_data_with_steps($workflowid); if (!$workflowrecord) { - print_error('invaliditemid'); + throw new moodle_exception('invaliditemid'); } $jsonexporter = new \tool_trigger\json\json_export($workflowrecord); diff --git a/exportrun.php b/exportrun.php index 4a2dc9e..ba857e3 100644 --- a/exportrun.php +++ b/exportrun.php @@ -35,7 +35,7 @@ $workflowdata = \tool_trigger\workflow_manager::export_workflow_and_run_history($workflowid, $runid); if (!$workflowdata) { - print_error('$workflowdata'); + throw new moodle_exception('workflowdata'); } $jsonexporter = new \tool_trigger\json\json_export($workflowdata); diff --git a/manageworkflow.php b/manageworkflow.php index 15edc1d..878c91d 100644 --- a/manageworkflow.php +++ b/manageworkflow.php @@ -37,12 +37,12 @@ $status = optional_param('status', 0, PARAM_BOOL); if (!in_array($action, ['delete', 'copy'])) { - print_error('invalidaction'); + throw new moodle_exception('invalidaction'); } $workflow = \tool_trigger\workflow_manager::get_workflow($workflowid); if (!$workflow) { - print_error('invaliditemid'); + throw new moodle_exception('invaliditemid'); } $workflowname = $workflow->get_name($context); From 1968235f41be36d979d3d2f52fe82d9c05933202 Mon Sep 17 00:00:00 2001 From: Dmitrii Metelkin Date: Tue, 3 Sep 2024 13:45:42 +1000 Subject: [PATCH 4/6] issue #223: update readme and versions information --- README.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 7512716..ad687b0 100644 --- a/README.md +++ b/README.md @@ -24,10 +24,12 @@ More Information on Moodle events can be found in the Moodle documentation at th ## Branches ## The following maps the plugin version to use depending on your Moodle version. -| Moodle verion | Branch | -| ------------------ | ------------------ | -| Moodle 3.5 to 3.10 | MOODLE_35_STABLE | -| Moodle 3.11+ | MOODLE_311_STABLE | +| Moodle verion | Branch | +|---------------------------|-------------------| +| Moodle 3.5 to 3.10 | MOODLE_35_STABLE | +| Moodle 3.11 to Moodle 4.1 | MOODLE_311_STABLE | +| Moodle 4.4+ | MOODLE_404_STABLE | + ## Moodle Plugin Installation The following sections outline how to install the Moodle plugin. From f3a776de6caecc06b3fb61dac0b6c2ae9374e081 Mon Sep 17 00:00:00 2001 From: Dmitrii Metelkin Date: Tue, 3 Sep 2024 13:46:00 +1000 Subject: [PATCH 5/6] issue #223: bump version --- version.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/version.php b/version.php index 8029999..cd275c9 100755 --- a/version.php +++ b/version.php @@ -25,8 +25,8 @@ defined('MOODLE_INTERNAL') || die(); $plugin->component = 'tool_trigger'; -$plugin->version = 2024031401; -$plugin->release = 2024031401; // Match release exactly to version. -$plugin->requires = 2021051701; -$plugin->supported = [311, 401]; +$plugin->version = 2024090300; +$plugin->release = 2024090300; // Match release exactly to version. +$plugin->requires = 2024042200; +$plugin->supported = [404, 404]; $plugin->maturity = MATURITY_STABLE; From 87d0125ca2031c96568cb005b867f3b3a5fd37b7 Mon Sep 17 00:00:00 2001 From: Dmitrii Metelkin Date: Wed, 4 Sep 2024 09:52:01 +1000 Subject: [PATCH 6/6] issue #223: fix broken manageworkflow page --- manageworkflow.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/manageworkflow.php b/manageworkflow.php index 878c91d..cb2c7b5 100644 --- a/manageworkflow.php +++ b/manageworkflow.php @@ -40,6 +40,9 @@ throw new moodle_exception('invalidaction'); } +$PAGE->set_context($context); +$PAGE->set_pagelayout('admin'); + $workflow = \tool_trigger\workflow_manager::get_workflow($workflowid); if (!$workflow) { throw new moodle_exception('invaliditemid'); @@ -51,11 +54,10 @@ '/admin/tool/trigger/manageworkflow.php', ['workflowid' => $workflowid] ); -$PAGE->set_context($context); -$PAGE->set_url($url); -$PAGE->set_pagelayout('admin'); + $PAGE->set_title($workflowname); $PAGE->set_heading($workflowname); +$PAGE->set_url($url); require_sesskey();