Update to Drupal 8.0.0 beta 14. For more information, see https://drupal.org/node/2544542
This commit is contained in:
parent
3b2511d96d
commit
81ccda77eb
2155 changed files with 54307 additions and 46870 deletions
|
@ -2,6 +2,10 @@ language: php
|
|||
|
||||
php: [5.3, 5.4, 5.5, 5.6, hhvm]
|
||||
|
||||
before_install:
|
||||
# Force using Goutte 2 on HHVM for now because Guzzle 6 is broken there
|
||||
- if [ "hhvm" = "$TRAVIS_PHP_VERSION" ]; then composer require fabpot/goutte '~2' --no-update; fi
|
||||
|
||||
before_script:
|
||||
- export WEB_FIXTURES_HOST=http://localhost
|
||||
|
||||
|
|
25
core/vendor/behat/mink-goutte-driver/README.md
vendored
Executable file → Normal file
25
core/vendor/behat/mink-goutte-driver/README.md
vendored
Executable file → Normal file
|
@ -4,9 +4,9 @@ Mink Goutte Driver
|
|||
[](https://packagist.org/packages/behat/mink-goutte-driver)
|
||||
[](https://packagist.org/packages/behat/mink-goutte-driver)
|
||||
[](https://packagist.org/packages/behat/mink-goutte-driver)
|
||||
[](https://travis-ci.org/Behat/MinkGoutteDriver)
|
||||
[](https://scrutinizer-ci.com/g/Behat/MinkGoutteDriver/)
|
||||
[](https://scrutinizer-ci.com/g/Behat/MinkGoutteDriver/)
|
||||
[](https://travis-ci.org/minkphp/MinkGoutteDriver)
|
||||
[](https://scrutinizer-ci.com/g/minkphp/MinkGoutteDriver/)
|
||||
[](https://scrutinizer-ci.com/g/minkphp/MinkGoutteDriver/)
|
||||
[](https://packagist.org/packages/behat/mink-goutte-driver)
|
||||
|
||||
Usage Example
|
||||
|
@ -15,23 +15,28 @@ Usage Example
|
|||
``` php
|
||||
<?php
|
||||
|
||||
require "vendor/autoload.php";
|
||||
|
||||
use Behat\Mink\Mink,
|
||||
Behat\Mink\Session,
|
||||
Behat\Mink\Driver\GoutteDriver,
|
||||
Behat\Mink\Driver\Goutte\Client as GoutteClient;
|
||||
|
||||
$startUrl = 'http://example.com';
|
||||
|
||||
$mink = new Mink(array(
|
||||
'goutte' => new Session(new GoutteDriver(new GoutteClient($startUrl))),
|
||||
'goutte' => new Session(new GoutteDriver(new GoutteClient())),
|
||||
));
|
||||
|
||||
$mink->getSession('goutte')->getPage()->findLink('Chat')->click();
|
||||
$session = $mink->getSession('goutte');
|
||||
$session->visit("http://php.net/");
|
||||
$session->getPage()->clickLink('Downloads');
|
||||
echo $session->getCurrentUrl() . PHP_EOL;
|
||||
```
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
Add a file composer.json with content:
|
||||
|
||||
``` json
|
||||
{
|
||||
"require": {
|
||||
|
@ -41,6 +46,8 @@ Installation
|
|||
}
|
||||
```
|
||||
|
||||
(or merge the above into your project's existing composer.json file)
|
||||
|
||||
``` bash
|
||||
$> curl -sS https://getcomposer.org/installer | php
|
||||
$> php composer.phar install
|
||||
|
@ -49,5 +56,5 @@ $> php composer.phar install
|
|||
Maintainers
|
||||
-----------
|
||||
|
||||
* Konstantin Kudryashov [everzet](http://github.com/everzet)
|
||||
* Other [awesome developers](https://github.com/Behat/MinkGoutteDriver/graphs/contributors)
|
||||
* Christophe Coevoet [stof](https://github.com/stof)
|
||||
* Other [awesome developers](https://github.com/minkphp/MinkGoutteDriver/graphs/contributors)
|
||||
|
|
|
@ -18,12 +18,12 @@
|
|||
"php": ">=5.3.1",
|
||||
"behat/mink": "~1.6@dev",
|
||||
"behat/mink-browserkit-driver": "~1.2@dev",
|
||||
"fabpot/goutte": "~1.0.4|~2.0"
|
||||
"fabpot/goutte": "~1.0.4|~2.0|~3.1"
|
||||
},
|
||||
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"Behat\\Mink\\Driver": "src/"
|
||||
"psr-4": {
|
||||
"Behat\\Mink\\Driver\\": "src/"
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
<filter>
|
||||
<whitelist>
|
||||
<directory>./src/Behat/Mink/Driver</directory>
|
||||
<directory>./src</directory>
|
||||
</whitelist>
|
||||
</filter>
|
||||
</phpunit>
|
||||
|
|
4
core/vendor/composer/autoload_files.php
vendored
4
core/vendor/composer/autoload_files.php
vendored
|
@ -6,6 +6,8 @@ $vendorDir = dirname(dirname(__FILE__));
|
|||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
$vendorDir . '/react/promise/src/functions_include.php',
|
||||
$vendorDir . '/guzzlehttp/psr7/src/functions.php',
|
||||
$vendorDir . '/guzzlehttp/promises/src/functions.php',
|
||||
$vendorDir . '/guzzlehttp/guzzle/src/functions_include.php',
|
||||
$baseDir . '/lib/Drupal.php',
|
||||
);
|
||||
|
|
3
core/vendor/composer/autoload_namespaces.php
vendored
3
core/vendor/composer/autoload_namespaces.php
vendored
|
@ -12,7 +12,6 @@ return array(
|
|||
'Stack' => array($vendorDir . '/stack/builder/src'),
|
||||
'Psr\\Log\\' => array($vendorDir . '/psr/log'),
|
||||
'Prophecy\\' => array($vendorDir . '/phpspec/prophecy/src'),
|
||||
'Gliph' => array($vendorDir . '/sdboyer/gliph/src'),
|
||||
'Egulias\\' => array($vendorDir . '/egulias/email-validator/src'),
|
||||
'EasyRdf_' => array($vendorDir . '/easyrdf/easyrdf/lib'),
|
||||
'Doctrine\\Instantiator\\' => array($vendorDir . '/doctrine/instantiator/src'),
|
||||
|
@ -22,5 +21,5 @@ return array(
|
|||
'Doctrine\\Common\\Cache\\' => array($vendorDir . '/doctrine/cache/lib'),
|
||||
'Doctrine\\Common\\Annotations\\' => array($vendorDir . '/doctrine/annotations/lib'),
|
||||
'Doctrine\\Common\\' => array($vendorDir . '/doctrine/common/lib'),
|
||||
'Behat\\Mink\\Driver' => array($vendorDir . '/behat/mink-browserkit-driver/src', $vendorDir . '/behat/mink-goutte-driver/src'),
|
||||
'Behat\\Mink\\Driver' => array($vendorDir . '/behat/mink-browserkit-driver/src'),
|
||||
);
|
||||
|
|
9
core/vendor/composer/autoload_psr4.php
vendored
9
core/vendor/composer/autoload_psr4.php
vendored
|
@ -9,6 +9,7 @@ return array(
|
|||
'Zend\\Stdlib\\' => array($vendorDir . '/zendframework/zend-stdlib'),
|
||||
'Zend\\Feed\\' => array($vendorDir . '/zendframework/zend-feed'),
|
||||
'Zend\\Escaper\\' => array($vendorDir . '/zendframework/zend-escaper'),
|
||||
'Zend\\Diactoros\\' => array($vendorDir . '/zendframework/zend-diactoros/src'),
|
||||
'Symfony\\Component\\Yaml\\' => array($vendorDir . '/symfony/yaml'),
|
||||
'Symfony\\Component\\Validator\\' => array($vendorDir . '/symfony/validator'),
|
||||
'Symfony\\Component\\Translation\\' => array($vendorDir . '/symfony/translation'),
|
||||
|
@ -26,14 +27,16 @@ return array(
|
|||
'Symfony\\Component\\ClassLoader\\' => array($vendorDir . '/symfony/class-loader'),
|
||||
'Symfony\\Component\\BrowserKit\\' => array($vendorDir . '/symfony/browser-kit'),
|
||||
'Symfony\\Cmf\\Component\\Routing\\' => array($vendorDir . '/symfony-cmf/routing'),
|
||||
'React\\Promise\\' => array($vendorDir . '/react/promise/src'),
|
||||
'Symfony\\Bridge\\PsrHttpMessage\\' => array($vendorDir . '/symfony/psr-http-message-bridge'),
|
||||
'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-message/src'),
|
||||
'Masterminds\\' => array($vendorDir . '/masterminds/html5/src'),
|
||||
'GuzzleHttp\\Stream\\' => array($vendorDir . '/guzzlehttp/streams/src'),
|
||||
'GuzzleHttp\\Ring\\' => array($vendorDir . '/guzzlehttp/ringphp/src'),
|
||||
'GuzzleHttp\\Psr7\\' => array($vendorDir . '/guzzlehttp/psr7/src'),
|
||||
'GuzzleHttp\\Promise\\' => array($vendorDir . '/guzzlehttp/promises/src'),
|
||||
'GuzzleHttp\\' => array($vendorDir . '/guzzlehttp/guzzle/src'),
|
||||
'Goutte\\' => array($vendorDir . '/fabpot/goutte/Goutte'),
|
||||
'Drupal\\Driver\\' => array($baseDir . '/../drivers/lib/Drupal/Driver'),
|
||||
'Drupal\\Core\\' => array($baseDir . '/lib/Drupal/Core'),
|
||||
'Drupal\\Component\\' => array($baseDir . '/lib/Drupal/Component'),
|
||||
'Behat\\Mink\\Driver\\' => array($vendorDir . '/behat/mink-goutte-driver/src'),
|
||||
'Behat\\Mink\\' => array($vendorDir . '/behat/mink/src'),
|
||||
);
|
||||
|
|
1434
core/vendor/composer/installed.json
vendored
1434
core/vendor/composer/installed.json
vendored
File diff suppressed because it is too large
Load diff
19
core/vendor/doctrine/lexer/LICENSE
vendored
Normal file
19
core/vendor/doctrine/lexer/LICENSE
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
Copyright (c) 2006-2013 Doctrine Project
|
||||
|
||||
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.
|
5
core/vendor/doctrine/lexer/composer.json
vendored
5
core/vendor/doctrine/lexer/composer.json
vendored
|
@ -15,5 +15,10 @@
|
|||
},
|
||||
"autoload": {
|
||||
"psr-0": { "Doctrine\\Common\\Lexer\\": "lib/" }
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0.x-dev"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,35 +22,58 @@ namespace Doctrine\Common\Lexer;
|
|||
/**
|
||||
* Base class for writing simple lexers, i.e. for creating small DSLs.
|
||||
*
|
||||
* @since 2.0
|
||||
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
|
||||
* @author Jonathan Wage <jonwage@gmail.com>
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
* @since 2.0
|
||||
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
|
||||
* @author Jonathan Wage <jonwage@gmail.com>
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
*/
|
||||
abstract class AbstractLexer
|
||||
{
|
||||
/**
|
||||
* @var array Array of scanned tokens
|
||||
* Lexer original input string.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $input;
|
||||
|
||||
/**
|
||||
* Array of scanned tokens.
|
||||
*
|
||||
* Each token is an associative array containing three items:
|
||||
* - 'value' : the string value of the token in the input string
|
||||
* - 'type' : the type of the token (identifier, numeric, string, input
|
||||
* parameter, none)
|
||||
* - 'position' : the position of the token in the input string
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $tokens = array();
|
||||
|
||||
/**
|
||||
* @var integer Current lexer position in input string
|
||||
* Current lexer position in input string.
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
private $position = 0;
|
||||
|
||||
/**
|
||||
* @var integer Current peek of current lexer position
|
||||
* Current peek of current lexer position.
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
private $peek = 0;
|
||||
|
||||
/**
|
||||
* @var array The next token in the input.
|
||||
* The next token in the input.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $lookahead;
|
||||
|
||||
/**
|
||||
* @var array The last matched/seen token.
|
||||
* The last matched/seen token.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $token;
|
||||
|
||||
|
@ -61,16 +84,22 @@ abstract class AbstractLexer
|
|||
* Any unprocessed tokens from any previous input are lost.
|
||||
*
|
||||
* @param string $input The input to be tokenized.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setInput($input)
|
||||
{
|
||||
$this->input = $input;
|
||||
$this->tokens = array();
|
||||
|
||||
$this->reset();
|
||||
$this->scan($input);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the lexer.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function reset()
|
||||
{
|
||||
|
@ -82,6 +111,8 @@ abstract class AbstractLexer
|
|||
|
||||
/**
|
||||
* Resets the peek pointer to 0.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function resetPeek()
|
||||
{
|
||||
|
@ -91,17 +122,32 @@ abstract class AbstractLexer
|
|||
/**
|
||||
* Resets the lexer position on the input to the given position.
|
||||
*
|
||||
* @param integer $position Position to place the lexical scanner
|
||||
* @param integer $position Position to place the lexical scanner.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function resetPosition($position = 0)
|
||||
{
|
||||
$this->position = $position;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the original lexer's input until a given position.
|
||||
*
|
||||
* @param integer $position
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getInputUntilPosition($position)
|
||||
{
|
||||
return substr($this->input, 0, $position);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a given token matches the current lookahead.
|
||||
*
|
||||
* @param integer|string $token
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function isNextToken($token)
|
||||
|
@ -110,9 +156,10 @@ abstract class AbstractLexer
|
|||
}
|
||||
|
||||
/**
|
||||
* Checks whether any of the given tokens matches the current lookahead
|
||||
* Checks whether any of the given tokens matches the current lookahead.
|
||||
*
|
||||
* @param array $tokens
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function isNextTokenAny(array $tokens)
|
||||
|
@ -123,13 +170,7 @@ abstract class AbstractLexer
|
|||
/**
|
||||
* Moves to the next token in the input string.
|
||||
*
|
||||
* A token is an associative array containing three items:
|
||||
* - 'value' : the string value of the token in the input string
|
||||
* - 'type' : the type of the token (identifier, numeric, string, input
|
||||
* parameter, none)
|
||||
* - 'position' : the position of the token in the input string
|
||||
*
|
||||
* @return array|null the next token; null if there is no more tokens left
|
||||
* @return boolean
|
||||
*/
|
||||
public function moveNext()
|
||||
{
|
||||
|
@ -145,6 +186,8 @@ abstract class AbstractLexer
|
|||
* Tells the lexer to skip input tokens until it sees a token with the given value.
|
||||
*
|
||||
* @param string $type The token type to skip until.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function skipUntil($type)
|
||||
{
|
||||
|
@ -154,10 +197,11 @@ abstract class AbstractLexer
|
|||
}
|
||||
|
||||
/**
|
||||
* Checks if given value is identical to the given token
|
||||
* Checks if given value is identical to the given token.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @param mixed $value
|
||||
* @param integer $token
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function isA($value, $token)
|
||||
|
@ -168,7 +212,7 @@ abstract class AbstractLexer
|
|||
/**
|
||||
* Moves the lookahead token forward.
|
||||
*
|
||||
* @return array | null The next token or NULL if there are no more tokens ahead.
|
||||
* @return array|null The next token or NULL if there are no more tokens ahead.
|
||||
*/
|
||||
public function peek()
|
||||
{
|
||||
|
@ -194,15 +238,21 @@ abstract class AbstractLexer
|
|||
/**
|
||||
* Scans the input string for tokens.
|
||||
*
|
||||
* @param string $input a query string
|
||||
* @param string $input A query string.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function scan($input)
|
||||
{
|
||||
static $regex;
|
||||
|
||||
if ( ! isset($regex)) {
|
||||
$regex = '/(' . implode(')|(', $this->getCatchablePatterns()) . ')|'
|
||||
. implode('|', $this->getNonCatchablePatterns()) . '/i';
|
||||
$regex = sprintf(
|
||||
'/(%s)|%s/%s',
|
||||
implode(')|(', $this->getCatchablePatterns()),
|
||||
implode('|', $this->getNonCatchablePatterns()),
|
||||
$this->getModifiers()
|
||||
);
|
||||
}
|
||||
|
||||
$flags = PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_OFFSET_CAPTURE;
|
||||
|
@ -224,6 +274,7 @@ abstract class AbstractLexer
|
|||
* Gets the literal for a given token.
|
||||
*
|
||||
* @param integer $token
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getLiteral($token)
|
||||
|
@ -241,6 +292,16 @@ abstract class AbstractLexer
|
|||
return $token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Regex modifiers
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getModifiers()
|
||||
{
|
||||
return 'i';
|
||||
}
|
||||
|
||||
/**
|
||||
* Lexical catchable patterns.
|
||||
*
|
||||
|
@ -259,6 +320,7 @@ abstract class AbstractLexer
|
|||
* Retrieve token type. Also processes the token value if necessary.
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
abstract protected function getType(&$value);
|
||||
|
|
2
core/vendor/egulias/email-validator/.gitignore
vendored
Normal file
2
core/vendor/egulias/email-validator/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
report/
|
||||
vendor/
|
22
core/vendor/egulias/email-validator/.travis.yml
vendored
22
core/vendor/egulias/email-validator/.travis.yml
vendored
|
@ -1,3 +1,5 @@
|
|||
sudo: false
|
||||
|
||||
language: php
|
||||
|
||||
php:
|
||||
|
@ -5,11 +7,25 @@ php:
|
|||
- 5.4
|
||||
- 5.5
|
||||
- 5.6
|
||||
- 7.0
|
||||
- hhvm
|
||||
|
||||
before_script:
|
||||
- wget http://getcomposer.org/composer.phar
|
||||
- php composer.phar install --dev --no-interaction
|
||||
env:
|
||||
global:
|
||||
- deps=no
|
||||
|
||||
matrix:
|
||||
fast_finish: true
|
||||
include:
|
||||
- php: 5.3
|
||||
env: deps=low
|
||||
- php: 5.6
|
||||
env: deps=high
|
||||
|
||||
install:
|
||||
- if [ "$deps" = "no" ]; then composer install; fi
|
||||
- if [ "$deps" = "low" ]; then composer update --prefer-lowest; fi
|
||||
- if [ "$deps" = "high" ]; then composer update; fi
|
||||
|
||||
script:
|
||||
- mkdir -p build/logs
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
EmailValidator [](https://travis-ci.org/egulias/EmailValidator) [](https://coveralls.io/r/egulias/EmailValidator?branch=master) [](https://insight.sensiolabs.com/projects/22ba6692-9c02-42e5-a65d-1c5696bfffc6)[](https://scrutinizer-ci.com/g/egulias/EmailValidator/?branch=master)
|
||||
#EmailValidator
|
||||
[](https://travis-ci.org/egulias/EmailValidator) [](https://coveralls.io/r/egulias/EmailValidator?branch=master) [](https://scrutinizer-ci.com/g/egulias/EmailValidator/?branch=master) [](https://insight.sensiolabs.com/projects/22ba6692-9c02-42e5-a65d-1c5696bfffc6)
|
||||
=============================
|
||||
With the help of
|
||||
|
||||

|
||||
##Installation##
|
||||
|
||||
Run the command below to install via Composer
|
||||
|
|
|
@ -3,22 +3,23 @@
|
|||
"description": "A library for validating emails",
|
||||
"homepage": "https://github.com/egulias/EmailValidator",
|
||||
"type": "Library",
|
||||
"keywords": ["email", "validation", "validator"],
|
||||
"keywords": ["email", "validation", "validator", "emailvalidation", "emailvalidator"],
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{"name": "Eduardo Gulias Davis"}
|
||||
],
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.3.x-dev"
|
||||
"dev-master": "2.0.x-dev"
|
||||
}
|
||||
},
|
||||
"require": {
|
||||
"php": ">= 5.3.3",
|
||||
"doctrine/lexer": "~1.0"
|
||||
"doctrine/lexer": "~1.0,>=1.0.1"
|
||||
},
|
||||
"require-dev" : {
|
||||
"satooshi/php-coveralls": "dev-master"
|
||||
"satooshi/php-coveralls": "dev-master",
|
||||
"phpunit/phpunit": "~4.4"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
|
|
1160
core/vendor/egulias/email-validator/composer.lock
generated
vendored
1160
core/vendor/egulias/email-validator/composer.lock
generated
vendored
File diff suppressed because it is too large
Load diff
|
@ -75,8 +75,6 @@ class EmailLexer extends AbstractLexer
|
|||
'\0' => self::C_NUL,
|
||||
);
|
||||
|
||||
protected $invalidASCII = array(226 => 1,);
|
||||
|
||||
protected $hasInvalidTokens = false;
|
||||
|
||||
protected $previous;
|
||||
|
@ -138,12 +136,12 @@ class EmailLexer extends AbstractLexer
|
|||
protected function getCatchablePatterns()
|
||||
{
|
||||
return array(
|
||||
'[a-zA-Z_]+[46]?',
|
||||
'[a-zA-Z_]+[46]?', //ASCII and domain literal
|
||||
'[^\x00-\x7F]', //UTF-8
|
||||
'[0-9]+',
|
||||
'\r\n',
|
||||
'::',
|
||||
'\s+',
|
||||
'[\x10-\x1F]+',
|
||||
'\s+?',
|
||||
'.',
|
||||
);
|
||||
}
|
||||
|
@ -155,7 +153,7 @@ class EmailLexer extends AbstractLexer
|
|||
*/
|
||||
protected function getNonCatchablePatterns()
|
||||
{
|
||||
return array('[\x7f-\xff]+');
|
||||
return array('[\xA0-\xff]+');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -167,16 +165,15 @@ class EmailLexer extends AbstractLexer
|
|||
*/
|
||||
protected function getType(&$value)
|
||||
{
|
||||
|
||||
if ($this->isNullType($value)) {
|
||||
return self::C_NUL;
|
||||
}
|
||||
|
||||
if (isset($this->charValue[$value])) {
|
||||
if ($this->isValid($value)) {
|
||||
return $this->charValue[$value];
|
||||
}
|
||||
|
||||
if ($this->isInvalid($value)) {
|
||||
if ($this->isUTF8Invalid($value)) {
|
||||
$this->hasInvalidTokens = true;
|
||||
return self::INVALID;
|
||||
}
|
||||
|
@ -184,8 +181,18 @@ class EmailLexer extends AbstractLexer
|
|||
return self::GENERIC;
|
||||
}
|
||||
|
||||
protected function isValid($value)
|
||||
{
|
||||
if (isset($this->charValue[$value])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
* @param $value
|
||||
* @return bool
|
||||
*/
|
||||
protected function isNullType($value)
|
||||
{
|
||||
|
@ -197,18 +204,20 @@ class EmailLexer extends AbstractLexer
|
|||
}
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
* @param $value
|
||||
* @return bool
|
||||
*/
|
||||
protected function isInvalid($value)
|
||||
protected function isUTF8Invalid($value)
|
||||
{
|
||||
if (preg_match('/[\x10-\x1F]+/', $value)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (isset($this->invalidASCII[ord($value)])) {
|
||||
if (preg_match('/\p{Cc}+/u', $value)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function getModifiers()
|
||||
{
|
||||
return 'iu';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,7 +29,8 @@ class EmailParser
|
|||
}
|
||||
|
||||
/**
|
||||
* @param string $str
|
||||
* @param $str
|
||||
* @return array
|
||||
*/
|
||||
public function parse($str)
|
||||
{
|
||||
|
@ -39,15 +40,16 @@ class EmailParser
|
|||
throw new \InvalidArgumentException('ERR_NOLOCALPART');
|
||||
}
|
||||
|
||||
if ($this->lexer->hasInvalidTokens()) {
|
||||
throw new \InvalidArgumentException('ERR_INVALID_ATEXT');
|
||||
}
|
||||
|
||||
$this->localPartParser->parse($str);
|
||||
$this->domainPartParser->parse($str);
|
||||
|
||||
$this->setParts($str);
|
||||
|
||||
if ($this->lexer->hasInvalidTokens()) {
|
||||
throw new \InvalidArgumentException('ERR_INVALID_ATEXT');
|
||||
}
|
||||
|
||||
return array('local' => $this->localPart, 'domain' => $this->domainPart);
|
||||
}
|
||||
|
||||
|
|
|
@ -104,6 +104,7 @@ class DomainPart extends Parser
|
|||
{
|
||||
$domain = '';
|
||||
do {
|
||||
|
||||
$prev = $this->lexer->getPrevious();
|
||||
|
||||
if ($this->lexer->token['type'] === EmailLexer::S_SLASH) {
|
||||
|
@ -217,9 +218,6 @@ class DomainPart extends Parser
|
|||
return $addressLiteral;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $addressLiteral
|
||||
*/
|
||||
protected function checkIPV4Tag($addressLiteral)
|
||||
{
|
||||
$matchesIP = array();
|
||||
|
@ -245,6 +243,17 @@ class DomainPart extends Parser
|
|||
|
||||
protected function checkDomainPartExceptions($prev)
|
||||
{
|
||||
$invalidDomainTokens = array(
|
||||
EmailLexer::S_DQUOTE => true,
|
||||
EmailLexer::S_SEMICOLON => true,
|
||||
EmailLexer::S_GREATERTHAN => true,
|
||||
EmailLexer::S_LOWERTHAN => true,
|
||||
);
|
||||
|
||||
if (isset($invalidDomainTokens[$this->lexer->token['type']])) {
|
||||
throw new \InvalidArgumentException('ERR_EXPECTING_ATEXT');
|
||||
}
|
||||
|
||||
if ($this->lexer->token['type'] === EmailLexer::S_COMMA) {
|
||||
throw new \InvalidArgumentException('ERR_COMMA_IN_DOMAIN');
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@ use Egulias\EmailValidator\EmailLexer;
|
|||
use Egulias\EmailValidator\EmailValidator;
|
||||
use \InvalidArgumentException;
|
||||
|
||||
|
||||
class LocalPart extends Parser
|
||||
{
|
||||
public function parse($localPart)
|
||||
|
|
|
@ -26,6 +26,73 @@ class EmailLexerTests extends \PHPUnit_Framework_TestCase
|
|||
$this->assertEquals($token, $lexer->token['type']);
|
||||
}
|
||||
|
||||
public function testLexerParsesMultipleSpaces()
|
||||
{
|
||||
$lexer = new EmailLexer();
|
||||
$lexer->setInput(' ');
|
||||
$lexer->moveNext();
|
||||
$lexer->moveNext();
|
||||
$this->assertEquals(EmailLexer::S_SP, $lexer->token['type']);
|
||||
$lexer->moveNext();
|
||||
$this->assertEquals(EmailLexer::S_SP, $lexer->token['type']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider invalidUTF8CharsProvider
|
||||
*/
|
||||
public function testLexerParsesInvalidUTF8($char)
|
||||
{
|
||||
$lexer = new EmailLexer();
|
||||
$lexer->setInput($char);
|
||||
$lexer->moveNext();
|
||||
$lexer->moveNext();
|
||||
|
||||
$this->assertEquals(EmailLexer::INVALID, $lexer->token['type']);
|
||||
}
|
||||
|
||||
public function invalidUTF8CharsProvider()
|
||||
{
|
||||
$chars = array();
|
||||
for ($i = 0; $i < 0x100; ++$i) {
|
||||
$c = $this->utf8Chr($i);
|
||||
if (preg_match('/(?=\p{Cc})(?=[^\t\n\n\r])/u', $c) && !preg_match('/\x{0000}/u', $c)) {
|
||||
$chars[] = array($c);
|
||||
}
|
||||
}
|
||||
|
||||
return $chars;
|
||||
}
|
||||
|
||||
protected function utf8Chr($code_point)
|
||||
{
|
||||
|
||||
if ($code_point < 0 || 0x10FFFF < $code_point || (0xD800 <= $code_point && $code_point <= 0xDFFF)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if ($code_point < 0x80) {
|
||||
$hex[0] = $code_point;
|
||||
$ret = chr($hex[0]);
|
||||
} elseif ($code_point < 0x800) {
|
||||
$hex[0] = 0x1C0 | $code_point >> 6;
|
||||
$hex[1] = 0x80 | $code_point & 0x3F;
|
||||
$ret = chr($hex[0]).chr($hex[1]);
|
||||
} elseif ($code_point < 0x10000) {
|
||||
$hex[0] = 0xE0 | $code_point >> 12;
|
||||
$hex[1] = 0x80 | $code_point >> 6 & 0x3F;
|
||||
$hex[2] = 0x80 | $code_point & 0x3F;
|
||||
$ret = chr($hex[0]).chr($hex[1]).chr($hex[2]);
|
||||
} else {
|
||||
$hex[0] = 0xF0 | $code_point >> 18;
|
||||
$hex[1] = 0x80 | $code_point >> 12 & 0x3F;
|
||||
$hex[2] = 0x80 | $code_point >> 6 & 0x3F;
|
||||
$hex[3] = 0x80 | $code_point & 0x3F;
|
||||
$ret = chr($hex[0]).chr($hex[1]).chr($hex[2]).chr($hex[3]);
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
public function testLexerForTab()
|
||||
{
|
||||
$lexer = new EmailLexer();
|
||||
|
@ -36,6 +103,17 @@ class EmailLexerTests extends \PHPUnit_Framework_TestCase
|
|||
$this->assertEquals(EmailLexer::S_HTAB, $lexer->token['type']);
|
||||
}
|
||||
|
||||
public function testLexerForUTF8()
|
||||
{
|
||||
$lexer = new EmailLexer();
|
||||
$lexer->setInput("áÇ@bar.com");
|
||||
$lexer->moveNext();
|
||||
$lexer->moveNext();
|
||||
$this->assertEquals(EmailLexer::GENERIC, $lexer->token['type']);
|
||||
$lexer->moveNext();
|
||||
$this->assertEquals(EmailLexer::GENERIC, $lexer->token['type']);
|
||||
}
|
||||
|
||||
public function testLexerSearchToken()
|
||||
{
|
||||
$lexer = new EmailLexer();
|
||||
|
@ -44,15 +122,6 @@ class EmailLexerTests extends \PHPUnit_Framework_TestCase
|
|||
$this->assertTrue($lexer->find(EmailLexer::S_HTAB));
|
||||
}
|
||||
|
||||
public function testLexerHasInvalidTokens()
|
||||
{
|
||||
$lexer = new EmailLexer();
|
||||
$lexer->setInput(chr(226));
|
||||
$lexer->moveNext();
|
||||
$lexer->moveNext();
|
||||
$this->assertTrue($lexer->hasInvalidTokens());
|
||||
}
|
||||
|
||||
public function getTokens()
|
||||
{
|
||||
return array(
|
||||
|
@ -85,7 +154,7 @@ class EmailLexerTests extends \PHPUnit_Framework_TestCase
|
|||
array('}', EmailLexer::S_CLOSEQBRACKET),
|
||||
array('', EmailLexer::S_EMPTY),
|
||||
array(chr(31), EmailLexer::INVALID),
|
||||
array(chr(226), EmailLexer::INVALID),
|
||||
array(chr(226), EmailLexer::GENERIC),
|
||||
array(chr(0), EmailLexer::C_NUL)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -26,9 +26,18 @@ class EmailValidatorTest extends \PHPUnit_Framework_TestCase
|
|||
$this->assertTrue($this->validator->isValid($email));
|
||||
}
|
||||
|
||||
public function testInvalidUTF8Email()
|
||||
{
|
||||
$validator = new EmailValidator;
|
||||
$email = "\x80\x81\x82@\x83\x84\x85.\x86\x87\x88";
|
||||
|
||||
$this->assertFalse($validator->isValid($email));
|
||||
}
|
||||
|
||||
public function getValidEmails()
|
||||
{
|
||||
return array(
|
||||
array('â@iana.org'),
|
||||
array('fabien@symfony.com'),
|
||||
array('example@example.co.uk'),
|
||||
array('fabien_potencier@example.fr'),
|
||||
|
@ -47,6 +56,13 @@ class EmailValidatorTest extends \PHPUnit_Framework_TestCase
|
|||
array('"test\ test"@iana.org'),
|
||||
array('""@iana.org'),
|
||||
array('"\""@iana.org'),
|
||||
array('müller@möller.de'),
|
||||
array('test@email*'),
|
||||
array('test@email!'),
|
||||
array('test@email&'),
|
||||
array('test@email^'),
|
||||
array('test@email%'),
|
||||
array('test@email$'),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -61,7 +77,9 @@ class EmailValidatorTest extends \PHPUnit_Framework_TestCase
|
|||
public function getInvalidEmails()
|
||||
{
|
||||
return array(
|
||||
|
||||
array('test@example.com test'),
|
||||
array('user name@example.com'),
|
||||
array('user name@example.com'),
|
||||
array('example.@example.co.uk'),
|
||||
array('example@example@example.co.uk'),
|
||||
array('(test_exampel@example.fr)'),
|
||||
|
@ -98,6 +116,13 @@ class EmailValidatorTest extends \PHPUnit_Framework_TestCase
|
|||
array('test@iana.org \r\n\r\n'),
|
||||
array('test@iana.org \r\n\r\n '),
|
||||
array('test@iana/icann.org'),
|
||||
array('test@foo;bar.com'),
|
||||
array('test;123@foobar.com'),
|
||||
array('test@example..com'),
|
||||
array('email.email@email."'),
|
||||
array('test@email>'),
|
||||
array('test@email<'),
|
||||
array('test@email{'),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -163,13 +188,32 @@ class EmailValidatorTest extends \PHPUnit_Framework_TestCase
|
|||
public function getInvalidEmailsWithWarnings()
|
||||
{
|
||||
return array(
|
||||
array(array( EmailValidator::DEPREC_CFWS_NEAR_AT,), 'example @example.co.uk'),
|
||||
array(array( EmailValidator::DEPREC_CFWS_NEAR_AT,), 'example@ example.co.uk'),
|
||||
array(array( EmailValidator::CFWS_COMMENT,), 'example@example(examplecomment).co.uk'),
|
||||
array(
|
||||
array(
|
||||
EmailValidator::DEPREC_CFWS_NEAR_AT,
|
||||
EmailValidator::DNSWARN_NO_RECORD
|
||||
),
|
||||
'example @example.co.uk'
|
||||
),
|
||||
array(
|
||||
array(
|
||||
EmailValidator::DEPREC_CFWS_NEAR_AT,
|
||||
EmailValidator::DNSWARN_NO_RECORD
|
||||
),
|
||||
'example@ example.co.uk'
|
||||
),
|
||||
array(
|
||||
array(
|
||||
EmailValidator::CFWS_COMMENT,
|
||||
EmailValidator::DNSWARN_NO_RECORD
|
||||
),
|
||||
'example@example(examplecomment).co.uk'
|
||||
),
|
||||
array(
|
||||
array(
|
||||
EmailValidator::CFWS_COMMENT,
|
||||
EmailValidator::DEPREC_CFWS_NEAR_AT,
|
||||
EmailValidator::DNSWARN_NO_RECORD,
|
||||
),
|
||||
'example(examplecomment)@example.co.uk'
|
||||
),
|
||||
|
@ -177,6 +221,7 @@ class EmailValidatorTest extends \PHPUnit_Framework_TestCase
|
|||
array(
|
||||
EmailValidator::RFC5321_QUOTEDSTRING,
|
||||
EmailValidator::CFWS_FWS,
|
||||
EmailValidator::DNSWARN_NO_RECORD,
|
||||
),
|
||||
"\"\t\"@example.co.uk"
|
||||
),
|
||||
|
@ -184,6 +229,7 @@ class EmailValidatorTest extends \PHPUnit_Framework_TestCase
|
|||
array(
|
||||
EmailValidator::RFC5321_QUOTEDSTRING,
|
||||
EmailValidator::CFWS_FWS,
|
||||
EmailValidator::DNSWARN_NO_RECORD
|
||||
),
|
||||
"\"\r\"@example.co.uk"
|
||||
),
|
||||
|
@ -275,12 +321,14 @@ class EmailValidatorTest extends \PHPUnit_Framework_TestCase
|
|||
array(
|
||||
array(
|
||||
EmailValidator::RFC5321_QUOTEDSTRING,
|
||||
EmailValidator::DNSWARN_NO_RECORD
|
||||
),
|
||||
'"example"@example.co.uk'
|
||||
),
|
||||
array(
|
||||
array(
|
||||
EmailValidator::RFC5322_LOCAL_TOOLONG,
|
||||
EmailValidator::DNSWARN_NO_RECORD
|
||||
),
|
||||
'too_long_localpart_too_long_localpart_too_long_localpart_too_long_localpart@example.co.uk'
|
||||
),
|
||||
|
|
3
core/vendor/fabpot/goutte/.travis.yml
vendored
3
core/vendor/fabpot/goutte/.travis.yml
vendored
|
@ -1,9 +1,9 @@
|
|||
language: php
|
||||
|
||||
php:
|
||||
- 7.0
|
||||
- 5.6
|
||||
- 5.5
|
||||
- 5.4
|
||||
- hhvm
|
||||
|
||||
install:
|
||||
|
@ -15,3 +15,4 @@ script:
|
|||
matrix:
|
||||
allow_failures:
|
||||
- php: hhvm
|
||||
- php: 7.0
|
||||
|
|
101
core/vendor/fabpot/goutte/Goutte/Client.php
vendored
101
core/vendor/fabpot/goutte/Goutte/Client.php
vendored
|
@ -13,10 +13,9 @@ namespace Goutte;
|
|||
|
||||
use GuzzleHttp\Client as GuzzleClient;
|
||||
use GuzzleHttp\ClientInterface as GuzzleClientInterface;
|
||||
use GuzzleHttp\Cookie\CookieJar;
|
||||
use GuzzleHttp\Exception\RequestException;
|
||||
use GuzzleHttp\Message\RequestInterface;
|
||||
use GuzzleHttp\Message\Response as GuzzleResponse;
|
||||
use GuzzleHttp\Post\PostFile;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Symfony\Component\BrowserKit\Client as BaseClient;
|
||||
use Symfony\Component\BrowserKit\Response;
|
||||
|
||||
|
@ -25,6 +24,7 @@ use Symfony\Component\BrowserKit\Response;
|
|||
*
|
||||
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
* @author Michael Dowling <michael@guzzlephp.org>
|
||||
* @author Charles Sarrazin <charles@sarraz.in>
|
||||
*/
|
||||
class Client extends BaseClient
|
||||
{
|
||||
|
@ -90,45 +90,46 @@ class Client extends BaseClient
|
|||
}
|
||||
}
|
||||
|
||||
$body = null;
|
||||
if (!in_array($request->getMethod(), array('GET', 'HEAD'))) {
|
||||
if (null !== $request->getContent()) {
|
||||
$body = $request->getContent();
|
||||
} else {
|
||||
$body = $request->getParameters();
|
||||
}
|
||||
}
|
||||
|
||||
$this->getClient()->setDefaultOption('auth', $this->auth);
|
||||
$cookies = CookieJar::fromArray(
|
||||
$this->getCookieJar()->allRawValues($request->getUri()),
|
||||
$request->getServer()['HTTP_HOST']
|
||||
);
|
||||
|
||||
$requestOptions = array(
|
||||
'body' => $body,
|
||||
'cookies' => $this->getCookieJar()->allRawValues($request->getUri()),
|
||||
'cookies' => $cookies,
|
||||
'allow_redirects' => false,
|
||||
'timeout' => 30,
|
||||
'auth' => $this->auth,
|
||||
);
|
||||
|
||||
if (!in_array($request->getMethod(), array('GET', 'HEAD'))) {
|
||||
if (null !== $content = $request->getContent()) {
|
||||
$requestOptions['body'] = $content;
|
||||
} else {
|
||||
if ($files = $request->getFiles()) {
|
||||
$requestOptions['multipart'] = [];
|
||||
|
||||
$this->addPostFields($request->getParameters(), $requestOptions['multipart']);
|
||||
$this->addPostFiles($files, $requestOptions['multipart']);
|
||||
} else {
|
||||
$requestOptions['form_params'] = $request->getParameters();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($headers)) {
|
||||
$requestOptions['headers'] = $headers;
|
||||
}
|
||||
|
||||
$guzzleRequest = $this->getClient()->createRequest(
|
||||
$request->getMethod(),
|
||||
$request->getUri(),
|
||||
$requestOptions
|
||||
);
|
||||
$method = $request->getMethod();
|
||||
$uri = $request->getUri();
|
||||
|
||||
foreach ($this->headers as $name => $value) {
|
||||
$guzzleRequest->setHeader($name, $value);
|
||||
}
|
||||
|
||||
if ('POST' == $request->getMethod() || 'PUT' == $request->getMethod()) {
|
||||
$this->addPostFiles($guzzleRequest, $request->getFiles());
|
||||
$requestOptions['headers'][$name] = $value;
|
||||
}
|
||||
|
||||
// Let BrowserKit handle redirects
|
||||
try {
|
||||
$response = $this->getClient()->send($guzzleRequest);
|
||||
$response = $this->getClient()->request($method, $uri, $requestOptions);
|
||||
} catch (RequestException $e) {
|
||||
$response = $e->getResponse();
|
||||
if (null === $response) {
|
||||
|
@ -139,33 +140,63 @@ class Client extends BaseClient
|
|||
return $this->createResponse($response);
|
||||
}
|
||||
|
||||
protected function addPostFiles(RequestInterface $request, array $files, $arrayName = '')
|
||||
protected function addPostFiles(array $files, array &$multipart, $arrayName = '')
|
||||
{
|
||||
if (empty($files)) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($files as $name => $info) {
|
||||
if (!empty($arrayName)) {
|
||||
$name = $arrayName.'['.$name.']';
|
||||
}
|
||||
|
||||
$file = [
|
||||
'name' => $name,
|
||||
];
|
||||
|
||||
if (is_array($info)) {
|
||||
if (isset($info['tmp_name'])) {
|
||||
if ('' !== $info['tmp_name']) {
|
||||
$request->getBody()->addFile(new PostFile($name, fopen($info['tmp_name'], 'r'), isset($info['name']) ? $info['name'] : null));
|
||||
$file['contents'] = fopen($info['tmp_name'], 'r');
|
||||
if (isset($info['name'])) {
|
||||
$file['filename'] = $info['name'];
|
||||
}
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
$this->addPostFiles($request, $info, $name);
|
||||
$this->addPostFiles($info, $multipart, $name);
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
$request->getBody()->addFile(new PostFile($name, fopen($info, 'r')));
|
||||
$file['contents'] = fopen($info, 'r');
|
||||
}
|
||||
|
||||
$multipart[] = $file;
|
||||
}
|
||||
}
|
||||
|
||||
public function addPostFields(array $formParams, array &$multipart, $arrayName = '')
|
||||
{
|
||||
foreach ($formParams as $name => $value) {
|
||||
if (!empty($arrayName)) {
|
||||
$name = $arrayName.'['.$name.']';
|
||||
}
|
||||
|
||||
if (is_array($value)) {
|
||||
$this->addPostFields($value, $multipart, $name);
|
||||
} else {
|
||||
$multipart[] = [
|
||||
'name' => $name,
|
||||
'contents' => $value,
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function createResponse(GuzzleResponse $response)
|
||||
protected function createResponse(ResponseInterface $response)
|
||||
{
|
||||
$headers = $response->getHeaders();
|
||||
|
||||
return new Response($response->getBody(true), $response->getStatusCode(), $headers);
|
||||
return new Response((string) $response->getBody(), $response->getStatusCode(), $response->getHeaders());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,31 +14,34 @@ namespace Goutte\Tests;
|
|||
use Goutte\Client;
|
||||
use GuzzleHttp\Client as GuzzleClient;
|
||||
use GuzzleHttp\Exception\RequestException;
|
||||
use GuzzleHttp\Message\Response as GuzzleResponse;
|
||||
use GuzzleHttp\Stream\Stream;
|
||||
use GuzzleHttp\Subscriber\History;
|
||||
use GuzzleHttp\Subscriber\Mock;
|
||||
use GuzzleHttp\Post\PostFile;
|
||||
use GuzzleHttp\Handler\MockHandler;
|
||||
use GuzzleHttp\HandlerStack;
|
||||
use GuzzleHttp\Psr7\Response as GuzzleResponse;
|
||||
use GuzzleHttp\Middleware;
|
||||
use Symfony\Component\BrowserKit\Cookie;
|
||||
|
||||
/**
|
||||
* Goutte Client Test
|
||||
* Goutte Client Test.
|
||||
*
|
||||
* @author Michael Dowling <michael@guzzlephp.org>
|
||||
* @author Charles Sarrazin <charles@sarraz.in>
|
||||
*/
|
||||
class ClientTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
protected $history;
|
||||
/** @var MockHandler */
|
||||
protected $mock;
|
||||
|
||||
protected function getGuzzle()
|
||||
protected function getGuzzle(array $responses = [])
|
||||
{
|
||||
$this->history = new History();
|
||||
$this->mock = new Mock();
|
||||
$this->mock->addResponse(new GuzzleResponse(200, array(), Stream::factory('<html><body><p>Hi</p></body></html>')));
|
||||
$guzzle = new GuzzleClient(array('redirect.disable' => true, 'base_url' => ''));
|
||||
$guzzle->getEmitter()->attach($this->mock);
|
||||
$guzzle->getEmitter()->attach($this->history);
|
||||
if (empty($responses)) {
|
||||
$responses = [new GuzzleResponse(200, [], '<html><body><p>Hi</p></body></html>')];
|
||||
}
|
||||
$this->mock = new MockHandler($responses);
|
||||
$handlerStack = HandlerStack::create($this->mock);
|
||||
$this->history = [];
|
||||
$handlerStack->push(Middleware::history($this->history));
|
||||
$guzzle = new GuzzleClient(array('redirect.disable' => true, 'base_uri' => '', 'handler' => $handlerStack));
|
||||
|
||||
return $guzzle;
|
||||
}
|
||||
|
@ -63,8 +66,8 @@ class ClientTest extends \PHPUnit_Framework_TestCase
|
|||
$client = new Client();
|
||||
$client->setClient($guzzle);
|
||||
$client->setHeader('X-Test', 'test');
|
||||
$crawler = $client->request('GET', 'http://www.example.com/');
|
||||
$this->assertEquals('test', $this->history->getLastRequest()->getHeader('X-Test'));
|
||||
$client->request('GET', 'http://www.example.com/');
|
||||
$this->assertEquals('test', end($this->history)['request']->getHeaderLine('X-Test'));
|
||||
}
|
||||
|
||||
public function testCustomUserAgent()
|
||||
|
@ -73,8 +76,8 @@ class ClientTest extends \PHPUnit_Framework_TestCase
|
|||
$client = new Client();
|
||||
$client->setClient($guzzle);
|
||||
$client->setHeader('User-Agent', 'foo');
|
||||
$crawler = $client->request('GET', 'http://www.example.com/');
|
||||
$this->assertEquals('foo', $this->history->getLastRequest()->getHeader('User-Agent'));
|
||||
$client->request('GET', 'http://www.example.com/');
|
||||
$this->assertEquals('Symfony2 BrowserKit, foo', end($this->history)['request']->getHeaderLine('User-Agent'));
|
||||
}
|
||||
|
||||
public function testUsesAuth()
|
||||
|
@ -83,11 +86,9 @@ class ClientTest extends \PHPUnit_Framework_TestCase
|
|||
$client = new Client();
|
||||
$client->setClient($guzzle);
|
||||
$client->setAuth('me', '**');
|
||||
$crawler = $client->request('GET', 'http://www.example.com/');
|
||||
$request = $this->history->getLastRequest();
|
||||
$this->assertEquals('me', $request->getConfig()->get('auth')[0]);
|
||||
$this->assertEquals('**', $request->getConfig()->get('auth')[1]);
|
||||
$this->assertEquals('basic', $request->getConfig()->get('auth')[2]);
|
||||
$client->request('GET', 'http://www.example.com/');
|
||||
$request = end($this->history)['request'];
|
||||
$this->assertEquals('Basic bWU6Kio=', $request->getHeaderLine('Authorization'));
|
||||
}
|
||||
|
||||
public function testResetsAuth()
|
||||
|
@ -97,10 +98,9 @@ class ClientTest extends \PHPUnit_Framework_TestCase
|
|||
$client->setClient($guzzle);
|
||||
$client->setAuth('me', '**');
|
||||
$client->resetAuth();
|
||||
$crawler = $client->request('GET', 'http://www.example.com/');
|
||||
$request = $this->history->getLastRequest();
|
||||
$this->assertNull($request->getConfig()->get('auth')[0]);
|
||||
$this->assertNull($request->getConfig()->get('auth')[1]);
|
||||
$client->request('GET', 'http://www.example.com/');
|
||||
$request = end($this->history)['request'];
|
||||
$this->assertEquals('', $request->getHeaderLine('authorization'));
|
||||
}
|
||||
|
||||
public function testUsesCookies()
|
||||
|
@ -109,9 +109,9 @@ class ClientTest extends \PHPUnit_Framework_TestCase
|
|||
$client = new Client();
|
||||
$client->setClient($guzzle);
|
||||
$client->getCookieJar()->set(new Cookie('test', '123'));
|
||||
$crawler = $client->request('GET', 'http://www.example.com/');
|
||||
$request = $this->history->getLastRequest();
|
||||
$this->assertEquals('test=123', $request->getHeader('Cookie'));
|
||||
$client->request('GET', 'http://www.example.com/');
|
||||
$request = end($this->history)['request'];
|
||||
$this->assertEquals('test=123', $request->getHeaderLine('Cookie'));
|
||||
}
|
||||
|
||||
public function testUsesPostFiles()
|
||||
|
@ -122,18 +122,20 @@ class ClientTest extends \PHPUnit_Framework_TestCase
|
|||
$files = array(
|
||||
'test' => array(
|
||||
'name' => 'test.txt',
|
||||
'tmp_name' => __FILE__,
|
||||
'tmp_name' => __DIR__.'/fixtures.txt',
|
||||
),
|
||||
);
|
||||
|
||||
$crawler = $client->request('POST', 'http://www.example.com/', array(), $files);
|
||||
$request = $this->history->getLastRequest();
|
||||
$client->request('POST', 'http://www.example.com/', array(), $files);
|
||||
$request = end($this->history)['request'];
|
||||
|
||||
$files = $request->getBody()->getFiles();
|
||||
$this->assertFile(reset($files), 'test', 'test.txt', array(
|
||||
'Content-Type' => 'text/plain',
|
||||
'Content-Disposition' => 'form-data; filename="test.txt"; name="test"',
|
||||
));
|
||||
$stream = $request->getBody();
|
||||
$boundary = $stream->getBoundary();
|
||||
$this->assertEquals(
|
||||
"--$boundary\r\nContent-Disposition: form-data; name=\"test\"; filename=\"test.txt\"\r\nContent-Length: 4\r\n"
|
||||
."Content-Type: text/plain\r\n\r\nfoo\n\r\n--$boundary--\r\n",
|
||||
$stream->getContents()
|
||||
);
|
||||
}
|
||||
|
||||
public function testUsesPostNamedFiles()
|
||||
|
@ -142,16 +144,19 @@ class ClientTest extends \PHPUnit_Framework_TestCase
|
|||
$client = new Client();
|
||||
$client->setClient($guzzle);
|
||||
$files = array(
|
||||
'test' => __FILE__,
|
||||
'test' => __DIR__.'/fixtures.txt',
|
||||
);
|
||||
|
||||
$crawler = $client->request('POST', 'http://www.example.com/', array(), $files);
|
||||
$request = $this->history->getLastRequest();
|
||||
$files = $request->getBody()->getFiles();
|
||||
$this->assertFile(reset($files), 'test', __FILE__, array(
|
||||
'Content-Type' => 'text/x-php',
|
||||
'Content-Disposition' => 'form-data; filename="ClientTest.php"; name="test"',
|
||||
));
|
||||
$client->request('POST', 'http://www.example.com/', array(), $files);
|
||||
$request = end($this->history)['request'];
|
||||
|
||||
$stream = $request->getBody();
|
||||
$boundary = $stream->getBoundary();
|
||||
$this->assertEquals(
|
||||
"--$boundary\r\nContent-Disposition: form-data; name=\"test\"; filename=\"fixtures.txt\"\r\nContent-Length: 4\r\n"
|
||||
."Content-Type: text/plain\r\n\r\nfoo\n\r\n--$boundary--\r\n",
|
||||
$stream->getContents()
|
||||
);
|
||||
}
|
||||
|
||||
public function testUsesPostFilesNestedFields()
|
||||
|
@ -163,18 +168,73 @@ class ClientTest extends \PHPUnit_Framework_TestCase
|
|||
'form' => array(
|
||||
'test' => array(
|
||||
'name' => 'test.txt',
|
||||
'tmp_name' => __FILE__,
|
||||
'tmp_name' => __DIR__.'/fixtures.txt',
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
$crawler = $client->request('POST', 'http://www.example.com/', array(), $files);
|
||||
$request = $this->history->getLastRequest();
|
||||
$files = $request->getBody()->getFiles();
|
||||
$this->assertFile(reset($files), 'form[test]', 'test.txt', array(
|
||||
'Content-Type' => 'text/plain',
|
||||
'Content-Disposition' => 'form-data; filename="test.txt"; name="form[test]"',
|
||||
));
|
||||
$client->request('POST', 'http://www.example.com/', array(), $files);
|
||||
$request = end($this->history)['request'];
|
||||
|
||||
$stream = $request->getBody();
|
||||
$boundary = $stream->getBoundary();
|
||||
$this->assertEquals(
|
||||
"--$boundary\r\nContent-Disposition: form-data; name=\"form[test]\"; filename=\"test.txt\"\r\nContent-Length: 4\r\n"
|
||||
."Content-Type: text/plain\r\n\r\nfoo\n\r\n--$boundary--\r\n",
|
||||
$stream->getContents()
|
||||
);
|
||||
}
|
||||
|
||||
public function testPostFormWithFiles()
|
||||
{
|
||||
$guzzle = $this->getGuzzle();
|
||||
$client = new Client();
|
||||
$client->setClient($guzzle);
|
||||
$files = array(
|
||||
'test' => __DIR__.'/fixtures.txt',
|
||||
);
|
||||
$params = array(
|
||||
'foo' => 'bar',
|
||||
);
|
||||
|
||||
$client->request('POST', 'http://www.example.com/', $params, $files);
|
||||
$request = end($this->history)['request'];
|
||||
|
||||
$stream = $request->getBody();
|
||||
$boundary = $stream->getBoundary();
|
||||
$this->assertEquals(
|
||||
"--$boundary\r\nContent-Disposition: form-data; name=\"foo\"\r\nContent-Length: 3\r\n"
|
||||
."\r\nbar\r\n"
|
||||
."--$boundary\r\nContent-Disposition: form-data; name=\"test\"; filename=\"fixtures.txt\"\r\nContent-Length: 4\r\n"
|
||||
."Content-Type: text/plain\r\n\r\nfoo\n\r\n--$boundary--\r\n",
|
||||
$stream->getContents());
|
||||
}
|
||||
|
||||
public function testPostEmbeddedFormWithFiles()
|
||||
{
|
||||
$guzzle = $this->getGuzzle();
|
||||
$client = new Client();
|
||||
$client->setClient($guzzle);
|
||||
$files = array(
|
||||
'test' => __DIR__.'/fixtures.txt',
|
||||
);
|
||||
$params = array(
|
||||
'foo' => array(
|
||||
'bar' => 'baz',
|
||||
),
|
||||
);
|
||||
|
||||
$client->request('POST', 'http://www.example.com/', $params, $files);
|
||||
$request = end($this->history)['request'];
|
||||
|
||||
$stream = $request->getBody();
|
||||
$boundary = $stream->getBoundary();
|
||||
$this->assertEquals(
|
||||
"--$boundary\r\nContent-Disposition: form-data; name=\"foo[bar]\"\r\nContent-Length: 3\r\n"
|
||||
."\r\nbaz\r\n"
|
||||
."--$boundary\r\nContent-Disposition: form-data; name=\"test\"; filename=\"fixtures.txt\"\r\nContent-Length: 4\r\n"
|
||||
."Content-Type: text/plain\r\n\r\nfoo\n\r\n--$boundary--\r\n",
|
||||
$stream->getContents());
|
||||
}
|
||||
|
||||
public function testUsesPostFilesOnClientSide()
|
||||
|
@ -183,16 +243,19 @@ class ClientTest extends \PHPUnit_Framework_TestCase
|
|||
$client = new Client();
|
||||
$client->setClient($guzzle);
|
||||
$files = array(
|
||||
'test' => __FILE__,
|
||||
'test' => __DIR__.'/fixtures.txt',
|
||||
);
|
||||
|
||||
$crawler = $client->request('POST', 'http://www.example.com/', array(), $files);
|
||||
$request = $this->history->getLastRequest();
|
||||
$files = $request->getBody()->getFiles();
|
||||
$this->assertFile(reset($files), 'test', __FILE__, array(
|
||||
'Content-Type' => 'text/x-php',
|
||||
'Content-Disposition' => 'form-data; filename="ClientTest.php"; name="test"',
|
||||
));
|
||||
$client->request('POST', 'http://www.example.com/', array(), $files);
|
||||
$request = end($this->history)['request'];
|
||||
|
||||
$stream = $request->getBody();
|
||||
$boundary = $stream->getBoundary();
|
||||
$this->assertEquals(
|
||||
"--$boundary\r\nContent-Disposition: form-data; name=\"test\"; filename=\"fixtures.txt\"\r\nContent-Length: 4\r\n"
|
||||
."Content-Type: text/plain\r\n\r\nfoo\n\r\n--$boundary--\r\n",
|
||||
$stream->getContents()
|
||||
);
|
||||
}
|
||||
|
||||
public function testUsesPostFilesUploadError()
|
||||
|
@ -210,10 +273,12 @@ class ClientTest extends \PHPUnit_Framework_TestCase
|
|||
),
|
||||
);
|
||||
|
||||
$crawler = $client->request('POST', 'http://www.example.com/', array(), $files);
|
||||
$request = $this->history->getLastRequest();
|
||||
$client->request('POST', 'http://www.example.com/', array(), $files);
|
||||
$request = end($this->history)['request'];
|
||||
$stream = $request->getBody();
|
||||
$boundary = $stream->getBoundary();
|
||||
|
||||
$this->assertEquals(array(), $request->getBody()->getFiles());
|
||||
$this->assertEquals("--$boundary--\r\n", $stream->getContents());
|
||||
}
|
||||
|
||||
public function testCreatesResponse()
|
||||
|
@ -227,13 +292,12 @@ class ClientTest extends \PHPUnit_Framework_TestCase
|
|||
|
||||
public function testHandlesRedirectsCorrectly()
|
||||
{
|
||||
$guzzle = $this->getGuzzle();
|
||||
|
||||
$this->mock->clearQueue();
|
||||
$this->mock->addResponse(new GuzzleResponse(301, array(
|
||||
'Location' => 'http://www.example.com/',
|
||||
)));
|
||||
$this->mock->addResponse(new GuzzleResponse(200, [], Stream::factory('<html><body><p>Test</p></body></html>')));
|
||||
$guzzle = $this->getGuzzle([
|
||||
new GuzzleResponse(301, array(
|
||||
'Location' => 'http://www.example.com/',
|
||||
)),
|
||||
new GuzzleResponse(200, [], '<html><body><p>Test</p></body></html>'),
|
||||
]);
|
||||
|
||||
$client = new Client();
|
||||
$client->setClient($guzzle);
|
||||
|
@ -247,12 +311,11 @@ class ClientTest extends \PHPUnit_Framework_TestCase
|
|||
|
||||
public function testConvertsGuzzleHeadersToArrays()
|
||||
{
|
||||
$guzzle = $this->getGuzzle();
|
||||
|
||||
$this->mock->clearQueue();
|
||||
$this->mock->addResponse(new GuzzleResponse(200, array(
|
||||
'Date' => 'Tue, 04 Jun 2013 13:22:41 GMT',
|
||||
)));
|
||||
$guzzle = $this->getGuzzle([
|
||||
new GuzzleResponse(200, array(
|
||||
'Date' => 'Tue, 04 Jun 2013 13:22:41 GMT',
|
||||
)),
|
||||
]);
|
||||
|
||||
$client = new Client();
|
||||
$client->setClient($guzzle);
|
||||
|
@ -260,48 +323,30 @@ class ClientTest extends \PHPUnit_Framework_TestCase
|
|||
$response = $client->getResponse();
|
||||
$headers = $response->getHeaders();
|
||||
|
||||
$this->assertInternalType("array", array_shift($headers), "Header not converted from Guzzle\Http\Message\Header to array");
|
||||
$this->assertInternalType('array', array_shift($headers), 'Header not converted from Guzzle\Http\Message\Header to array');
|
||||
}
|
||||
|
||||
public function testNullResponseException()
|
||||
{
|
||||
$this->setExpectedException('GuzzleHttp\Exception\RequestException');
|
||||
$guzzle = $this->getGuzzle();
|
||||
$this->mock->clearQueue();
|
||||
$exception = new RequestException('', $this->getMock('GuzzleHttp\Message\RequestInterface'));
|
||||
$this->mock->addException($exception);
|
||||
$guzzle = $this->getGuzzle([
|
||||
new RequestException('', $this->getMock('Psr\Http\Message\RequestInterface')),
|
||||
]);
|
||||
$client = new Client();
|
||||
$client->setClient($guzzle);
|
||||
$client->request('GET', 'http://www.example.com/');
|
||||
$response = $client->getResponse();
|
||||
}
|
||||
|
||||
protected function assertFile(PostFile $postFile, $fieldName, $fileName, $headers)
|
||||
{
|
||||
$this->assertEquals($postFile->getName(), $fieldName);
|
||||
$this->assertEquals($postFile->getFilename(), $fileName);
|
||||
|
||||
$postFileHeaders = $postFile->getHeaders();
|
||||
|
||||
// Note: Sort 'Content-Disposition' values before comparing, because the order changed in Guzzle 4.2.2
|
||||
$postFileHeaders['Content-Disposition'] = explode('; ', $postFileHeaders['Content-Disposition']);
|
||||
sort($postFileHeaders['Content-Disposition']);
|
||||
$headers['Content-Disposition'] = explode('; ', $headers['Content-Disposition']);
|
||||
sort($headers['Content-Disposition']);
|
||||
|
||||
$this->assertEquals($postFileHeaders, $headers);
|
||||
$client->getResponse();
|
||||
}
|
||||
|
||||
public function testHttps()
|
||||
{
|
||||
$guzzle = $this->getGuzzle();
|
||||
$guzzle = $this->getGuzzle([
|
||||
new GuzzleResponse(200, [], '<html><body><p>Test</p></body></html>'),
|
||||
]);
|
||||
|
||||
$this->mock->clearQueue();
|
||||
$this->mock->addResponse(new GuzzleResponse(200, [], Stream::factory('<html><body><p>Test</p></body></html>')));
|
||||
$client = new Client();
|
||||
$client->setClient($guzzle);
|
||||
$crawler = $client->request('GET', 'https://www.example.com/');
|
||||
$this->assertEquals('https', $this->history->getLastRequest()->getScheme());
|
||||
$this->assertEquals('Test', $crawler->filter('p')->text());
|
||||
}
|
||||
|
||||
|
@ -313,7 +358,7 @@ class ClientTest extends \PHPUnit_Framework_TestCase
|
|||
'HTTP_USER_AGENT' => 'SomeHost',
|
||||
]);
|
||||
$client->setClient($guzzle);
|
||||
$crawler = $client->request('GET', 'http://www.example.com/');
|
||||
$this->assertEquals('SomeHost', $this->history->getLastRequest()->getHeader('User-Agent'));
|
||||
$client->request('GET', 'http://www.example.com/');
|
||||
$this->assertEquals('SomeHost', end($this->history)['request']->getHeaderLine('User-Agent'));
|
||||
}
|
||||
}
|
||||
|
|
1
core/vendor/fabpot/goutte/Goutte/Tests/fixtures.txt
vendored
Normal file
1
core/vendor/fabpot/goutte/Goutte/Tests/fixtures.txt
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
foo
|
22
core/vendor/fabpot/goutte/README.rst
vendored
22
core/vendor/fabpot/goutte/README.rst
vendored
|
@ -9,11 +9,12 @@ responses.
|
|||
Requirements
|
||||
------------
|
||||
|
||||
Goutte depends on PHP 5.4+ and Guzzle 4+.
|
||||
Goutte depends on PHP 5.5+ and Guzzle 6+.
|
||||
|
||||
.. tip::
|
||||
|
||||
If you need support for PHP 5.3 or Guzzle 3, use Goutte 1.0.6.
|
||||
If you need support for PHP 5.4 or Guzzle 4-5, use Goutte 2.x.
|
||||
If you need support for PHP 5.3 or Guzzle 3, use Goutte 1.x.
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
@ -22,7 +23,7 @@ Add ``fabpot/goutte`` as a require dependency in your ``composer.json`` file:
|
|||
|
||||
.. code-block:: bash
|
||||
|
||||
php composer.phar require fabpot/goutte:~2.0
|
||||
composer require fabpot/goutte
|
||||
|
||||
.. tip::
|
||||
|
||||
|
@ -32,6 +33,9 @@ Add ``fabpot/goutte`` as a require dependency in your ``composer.json`` file:
|
|||
|
||||
require_once '/path/to/goutte.phar';
|
||||
|
||||
The phars for Goutte 1.x are also available for `download
|
||||
<http://get.sensiolabs.org/goutte-v1.0.7.phar>`.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
|
@ -73,7 +77,7 @@ Extract data:
|
|||
.. code-block:: php
|
||||
|
||||
// Get the latest post in this category and display the titles
|
||||
$crawler->filter('h2.post > a')->each(function ($node) {
|
||||
$crawler->filter('h2 > a')->each(function ($node) {
|
||||
print $node->text()."\n";
|
||||
});
|
||||
|
||||
|
@ -92,8 +96,14 @@ Submit forms:
|
|||
More Information
|
||||
----------------
|
||||
|
||||
Read the documentation of the BrowserKit and DomCrawler Symfony Components for
|
||||
more information about what you can do with Goutte.
|
||||
Read the documentation of the BrowserKit and `DomCrawler
|
||||
<http://symfony.com/doc/any/components/dom_crawler.html>`_ Symfony Components
|
||||
for more information about what you can do with Goutte.
|
||||
|
||||
Pronunciation
|
||||
-------------
|
||||
|
||||
Goutte is pronounced ``goot`` i.e. it rhymes with ``boot`` and not ``out``.
|
||||
|
||||
Technical Information
|
||||
---------------------
|
||||
|
|
6
core/vendor/fabpot/goutte/composer.json
vendored
6
core/vendor/fabpot/goutte/composer.json
vendored
|
@ -12,18 +12,18 @@
|
|||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.4.0",
|
||||
"php": ">=5.5.0",
|
||||
"symfony/browser-kit": "~2.1",
|
||||
"symfony/css-selector": "~2.1",
|
||||
"symfony/dom-crawler": "~2.1",
|
||||
"guzzlehttp/guzzle": ">=4,<6"
|
||||
"guzzlehttp/guzzle": "^6.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": { "Goutte\\": "Goutte" }
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.0-dev"
|
||||
"dev-master": "3.1-dev"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
11
core/vendor/guzzlehttp/guzzle/.gitignore
vendored
11
core/vendor/guzzlehttp/guzzle/.gitignore
vendored
|
@ -1,11 +0,0 @@
|
|||
phpunit.xml
|
||||
composer.phar
|
||||
composer.lock
|
||||
composer-test.lock
|
||||
vendor/
|
||||
build/artifacts/
|
||||
artifacts/
|
||||
docs/_build
|
||||
docs/*.pyc
|
||||
.idea
|
||||
.DS_STORE
|
7
core/vendor/guzzlehttp/guzzle/.travis.yml
vendored
7
core/vendor/guzzlehttp/guzzle/.travis.yml
vendored
|
@ -1,15 +1,13 @@
|
|||
language: php
|
||||
|
||||
php:
|
||||
- 5.4
|
||||
- 5.5
|
||||
- 5.6
|
||||
- 7.0
|
||||
- hhvm
|
||||
|
||||
before_script:
|
||||
- curl --version
|
||||
- pear config-set php_ini ~/.phpenv/versions/`php -r 'echo phpversion();'`/etc/php.ini || echo 'Error modifying PEAR'
|
||||
- pecl install uri_template || echo 'Error installing uri_template'
|
||||
- composer self-update
|
||||
- composer install --no-interaction --prefer-source --dev
|
||||
- ~/.nvm/nvm.sh install v0.6.14
|
||||
|
@ -20,6 +18,7 @@ script: make test
|
|||
matrix:
|
||||
allow_failures:
|
||||
- php: hhvm
|
||||
- php: 7.0
|
||||
fast_finish: true
|
||||
|
||||
before_deploy:
|
||||
|
@ -36,4 +35,4 @@ deploy:
|
|||
repo: guzzle/guzzle
|
||||
tags: true
|
||||
all_branches: true
|
||||
php: 5.4
|
||||
php: 5.5
|
||||
|
|
111
core/vendor/guzzlehttp/guzzle/CHANGELOG.md
vendored
111
core/vendor/guzzlehttp/guzzle/CHANGELOG.md
vendored
|
@ -1,5 +1,116 @@
|
|||
# CHANGELOG
|
||||
|
||||
## 6.0.2 - 2015-07-04
|
||||
|
||||
* Fixed a memory leak in the curl handlers in which references to callbacks
|
||||
were not being removed by `curl_reset`.
|
||||
* Cookies are now extracted properly before redirects.
|
||||
* Cookies now allow more character ranges.
|
||||
* Decoded Content-Encoding responses are now modified to correctly reflect
|
||||
their state if the encoding was automatically removed by a handler. This
|
||||
means that the `Content-Encoding` header may be removed an the
|
||||
`Content-Length` modified to reflect the message size after removing the
|
||||
encoding.
|
||||
* Added a more explicit error message when trying to use `form_params` and
|
||||
`multipart` in the same request.
|
||||
* Several fixes for HHVM support.
|
||||
* Functions are now conditionally required using an additional level of
|
||||
indirection to help with global Composer installations.
|
||||
|
||||
## 6.0.1 - 2015-05-27
|
||||
|
||||
* Fixed a bug with serializing the `query` request option where the `&`
|
||||
separator was missing.
|
||||
* Added a better error message for when `body` is provided as an array. Please
|
||||
use `form_params` or `multipart` instead.
|
||||
* Various doc fixes.
|
||||
|
||||
## 6.0.0 - 2015-05-26
|
||||
|
||||
* See the UPGRADING.md document for more information.
|
||||
* Added `multipart` and `form_params` request options.
|
||||
* Added `synchronous` request option.
|
||||
* Added the `on_headers` request option.
|
||||
* Fixed `expect` handling.
|
||||
* No longer adding default middlewares in the client ctor. These need to be
|
||||
present on the provided handler in order to work.
|
||||
* Requests are no longer initiated when sending async requests with the
|
||||
CurlMultiHandler. This prevents unexpected recursion from requests completing
|
||||
while ticking the cURL loop.
|
||||
* Removed the semantics of setting `default` to `true`. This is no longer
|
||||
required now that the cURL loop is not ticked for async requests.
|
||||
* Added request and response logging middleware.
|
||||
* No longer allowing self signed certificates when using the StreamHandler.
|
||||
* Ensuring that `sink` is valid if saving to a file.
|
||||
* Request exceptions now include a "handler context" which provides handler
|
||||
specific contextual information.
|
||||
* Added `GuzzleHttp\RequestOptions` to allow request options to be applied
|
||||
using constants.
|
||||
* `$maxHandles` has been removed from CurlMultiHandler.
|
||||
* `MultipartPostBody` is now part of the `guzzlehttp/psr7` package.
|
||||
|
||||
## 5.3.0 - 2015-05-19
|
||||
|
||||
* Mock now supports `save_to`
|
||||
* Marked `AbstractRequestEvent::getTransaction()` as public.
|
||||
* Fixed a bug in which multiple headers using different casing would overwrite
|
||||
previous headers in the associative array.
|
||||
* Added `Utils::getDefaultHandler()`
|
||||
* Marked `GuzzleHttp\Client::getDefaultUserAgent` as deprecated.
|
||||
* URL scheme is now always lowercased.
|
||||
|
||||
## 6.0.0-beta.1
|
||||
|
||||
* Requires PHP >= 5.5
|
||||
* Updated to use PSR-7
|
||||
* Requires immutable messages, which basically means an event based system
|
||||
owned by a request instance is no longer possible.
|
||||
* Utilizing the [Guzzle PSR-7 package](https://github.com/guzzle/psr7).
|
||||
* Removed the dependency on `guzzlehttp/streams`. These stream abstractions
|
||||
are available in the `guzzlehttp/psr7` package under the `GuzzleHttp\Psr7`
|
||||
namespace.
|
||||
* Added middleware and handler system
|
||||
* Replaced the Guzzle event and subscriber system with a middleware system.
|
||||
* No longer depends on RingPHP, but rather places the HTTP handlers directly
|
||||
in Guzzle, operating on PSR-7 messages.
|
||||
* Retry logic is now encapsulated in `GuzzleHttp\Middleware::retry`, which
|
||||
means the `guzzlehttp/retry-subscriber` is now obsolete.
|
||||
* Mocking responses is now handled using `GuzzleHttp\Handler\MockHandler`.
|
||||
* Asynchronous responses
|
||||
* No longer supports the `future` request option to send an async request.
|
||||
Instead, use one of the `*Async` methods of a client (e.g., `requestAsync`,
|
||||
`getAsync`, etc.).
|
||||
* Utilizing `GuzzleHttp\Promise` instead of React's promise library to avoid
|
||||
recursion required by chaining and forwarding react promises. See
|
||||
https://github.com/guzzle/promises
|
||||
* Added `requestAsync` and `sendAsync` to send request asynchronously.
|
||||
* Added magic methods for `getAsync()`, `postAsync()`, etc. to send requests
|
||||
asynchronously.
|
||||
* Request options
|
||||
* POST and form updates
|
||||
* Added the `form_fields` and `form_files` request options.
|
||||
* Removed the `GuzzleHttp\Post` namespace.
|
||||
* The `body` request option no longer accepts an array for POST requests.
|
||||
* The `exceptions` request option has been deprecated in favor of the
|
||||
`http_errors` request options.
|
||||
* The `save_to` request option has been deprecated in favor of `sink` request
|
||||
option.
|
||||
* Clients no longer accept an array of URI template string and variables for
|
||||
URI variables. You will need to expand URI templates before passing them
|
||||
into a client constructor or request method.
|
||||
* Client methods `get()`, `post()`, `put()`, `patch()`, `options()`, etc. are
|
||||
now magic methods that will send synchronous requests.
|
||||
* Replaced `Utils.php` with plain functions in `functions.php`.
|
||||
* Removed `GuzzleHttp\Collection`.
|
||||
* Removed `GuzzleHttp\BatchResults`. Batched pool results are now returned as
|
||||
an array.
|
||||
* Removed `GuzzleHttp\Query`. Query string handling is now handled using an
|
||||
associative array passed into the `query` request option. The query string
|
||||
is serialized using PHP's `http_build_query`. If you need more control, you
|
||||
can pass the query string in as a string.
|
||||
* `GuzzleHttp\QueryParser` has been replaced with the
|
||||
`GuzzleHttp\Psr7\parse_query`.
|
||||
|
||||
## 5.2.0 - 2015-01-27
|
||||
|
||||
* Added `AppliesHeadersInterface` to make applying headers to a request based
|
||||
|
|
2
core/vendor/guzzlehttp/guzzle/LICENSE
vendored
2
core/vendor/guzzlehttp/guzzle/LICENSE
vendored
|
@ -1,4 +1,4 @@
|
|||
Copyright (c) 2014 Michael Dowling, https://github.com/mtdowling <mtdowling@gmail.com>
|
||||
Copyright (c) 2011-2015 Michael Dowling, https://github.com/mtdowling <mtdowling@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
50
core/vendor/guzzlehttp/guzzle/Makefile
vendored
50
core/vendor/guzzlehttp/guzzle/Makefile
vendored
|
@ -1,50 +0,0 @@
|
|||
all: clean coverage docs
|
||||
|
||||
start-server:
|
||||
cd vendor/guzzlehttp/ringphp && make start-server
|
||||
|
||||
stop-server:
|
||||
cd vendor/guzzlehttp/ringphp && make stop-server
|
||||
|
||||
test: start-server
|
||||
vendor/bin/phpunit
|
||||
$(MAKE) stop-server
|
||||
|
||||
coverage: start-server
|
||||
vendor/bin/phpunit --coverage-html=artifacts/coverage
|
||||
$(MAKE) stop-server
|
||||
|
||||
view-coverage:
|
||||
open artifacts/coverage/index.html
|
||||
|
||||
clean:
|
||||
rm -rf artifacts/*
|
||||
|
||||
docs:
|
||||
cd docs && make html && cd ..
|
||||
|
||||
view-docs:
|
||||
open docs/_build/html/index.html
|
||||
|
||||
tag:
|
||||
$(if $(TAG),,$(error TAG is not defined. Pass via "make tag TAG=4.2.1"))
|
||||
@echo Tagging $(TAG)
|
||||
chag update $(TAG)
|
||||
sed -i '' -e "s/VERSION = '.*'/VERSION = '$(TAG)'/" src/ClientInterface.php
|
||||
php -l src/ClientInterface.php
|
||||
git add -A
|
||||
git commit -m '$(TAG) release'
|
||||
chag tag
|
||||
|
||||
perf: start-server
|
||||
php tests/perf.php
|
||||
$(MAKE) stop-server
|
||||
|
||||
package: burgomaster
|
||||
php build/packager.php
|
||||
|
||||
burgomaster:
|
||||
mkdir -p build/artifacts
|
||||
curl -s https://raw.githubusercontent.com/mtdowling/Burgomaster/0.0.2/src/Burgomaster.php > build/artifacts/Burgomaster.php
|
||||
|
||||
.PHONY: docs burgomaster
|
74
core/vendor/guzzlehttp/guzzle/README.md
vendored
74
core/vendor/guzzlehttp/guzzle/README.md
vendored
|
@ -1,25 +1,24 @@
|
|||
Guzzle, PHP HTTP client and webservice framework
|
||||
================================================
|
||||
Guzzle, PHP HTTP client
|
||||
=======================
|
||||
|
||||
[](http://travis-ci.org/guzzle/guzzle)
|
||||
[](http://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.
|
||||
|
||||
- Manages things like persistent connections, represents query strings as
|
||||
collections, simplifies sending streaming POST requests with fields and
|
||||
files, and abstracts away the underlying HTTP transport layer.
|
||||
- Can send both synchronous and asynchronous requests using the same interface
|
||||
without requiring a dependency on a specific event loop.
|
||||
- Pluggable HTTP adapters allows Guzzle to integrate with any method you choose
|
||||
for sending HTTP requests over the wire (e.g., cURL, sockets, PHP's stream
|
||||
wrapper, non-blocking event loops like ReactPHP.
|
||||
- Guzzle makes it so that you no longer need to fool around with cURL options,
|
||||
stream contexts, or sockets.
|
||||
- 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();
|
||||
$response = $client->get('http://guzzlephp.org');
|
||||
$res = $client->get('https://api.github.com/user', ['auth' => ['user', 'pass']]);
|
||||
echo $res->getStatusCode();
|
||||
// "200"
|
||||
|
@ -27,22 +26,23 @@ echo $res->getHeader('content-type');
|
|||
// 'application/json; charset=utf8'
|
||||
echo $res->getBody();
|
||||
// {"type":"User"...'
|
||||
var_export($res->json());
|
||||
// Outputs the JSON decoded data
|
||||
|
||||
// Send an asynchronous request.
|
||||
$req = $client->createRequest('GET', 'http://httpbin.org', ['future' => true]);
|
||||
$client->send($req)->then(function ($response) {
|
||||
echo 'I completed! ' . $response;
|
||||
$request = new \GuzzleHttp\Psr7\Request('GET', 'http://httpbin.org');
|
||||
$promise = $client->sendAsync($request)->then(function ($response) {
|
||||
echo 'I completed! ' . $response->getBody();
|
||||
});
|
||||
$promise->wait();
|
||||
```
|
||||
|
||||
Get more information and answers with the
|
||||
[Documentation](http://guzzlephp.org/),
|
||||
[Forums](https://groups.google.com/forum/?hl=en#!forum/guzzle),
|
||||
and [Gitter](https://gitter.im/guzzle/guzzle).
|
||||
## Help and docs
|
||||
|
||||
### Installing via Composer
|
||||
- [Documentation](http://guzzlephp.org/)
|
||||
- [stackoverflow](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).
|
||||
|
@ -55,7 +55,7 @@ curl -sS https://getcomposer.org/installer | php
|
|||
Next, run the Composer command to install the latest stable version of Guzzle:
|
||||
|
||||
```bash
|
||||
composer require guzzlehttp/guzzle
|
||||
composer.phar require guzzlehttp/guzzle
|
||||
```
|
||||
|
||||
After installing, you need to require Composer's autoloader:
|
||||
|
@ -64,7 +64,25 @@ After installing, you need to require Composer's autoloader:
|
|||
require 'vendor/autoload.php';
|
||||
```
|
||||
|
||||
### Documentation
|
||||
You can then later update Guzzle using composer:
|
||||
|
||||
More information can be found in the online documentation at
|
||||
http://guzzlephp.org/.
|
||||
```bash
|
||||
composer.phar update
|
||||
```
|
||||
|
||||
|
||||
## Version Guidance
|
||||
|
||||
| Version | Status | Packagist | Namespace | Repo | Docs | PSR-7 |
|
||||
|---------|-------------|---------------------|--------------|---------------------|---------------------|-------|
|
||||
| 3.x | EOL | `guzzle/guzzle` | `Guzzle` | [v3][guzzle-3-repo] | [v3][guzzle-3-docs] | No |
|
||||
| 4.x | EOL | `guzzlehttp/guzzle` | `GuzzleHttp` | N/A | N/A | No |
|
||||
| 5.x | Maintained | `guzzlehttp/guzzle` | `GuzzleHttp` | [v5][guzzle-5-repo] | [v5][guzzle-5-docs] | No |
|
||||
| 6.x | Latest | `guzzlehttp/guzzle` | `GuzzleHttp` | [v6][guzzle-6-repo] | [v6][guzzle-6-docs] | Yes |
|
||||
|
||||
[guzzle-3-repo]: https://github.com/guzzle/guzzle3
|
||||
[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/
|
||||
|
|
155
core/vendor/guzzlehttp/guzzle/UPGRADING.md
vendored
155
core/vendor/guzzlehttp/guzzle/UPGRADING.md
vendored
|
@ -1,12 +1,161 @@
|
|||
Guzzle Upgrade Guide
|
||||
====================
|
||||
|
||||
5.0 to 6.0
|
||||
----------
|
||||
|
||||
Guzzle now uses [PSR-7](http://www.php-fig.org/psr/psr-7/) for HTTP messages.
|
||||
Due to the fact that these messages are immutable, this prompted a refactoring
|
||||
of Guzzle to use a middleware based system rather than an event system. Any
|
||||
HTTP message interaction (e.g., `GuzzleHttp\Message\Request`) need to be
|
||||
updated to work with the new immutable PSR-7 request and response objects. Any
|
||||
event listeners or subscribers need to be updated to become middleware
|
||||
functions that wrap handlers (or are injected into a
|
||||
`GuzzleHttp\HandlerStack`).
|
||||
|
||||
- Removed `GuzzleHttp\BatchResults`
|
||||
- Removed `GuzzleHttp\Collection`
|
||||
- Removed `GuzzleHttp\HasDataTrait`
|
||||
- Removed `GuzzleHttp\ToArrayInterface`
|
||||
- The `guzzlehttp/streams` dependency has been removed. Stream functionality
|
||||
is now present in the `GuzzleHttp\Psr7` namespace provided by the
|
||||
`guzzlehttp/psr7` package.
|
||||
- Guzzle no longer uses ReactPHP promises and now uses the
|
||||
`guzzlehttp/promises` library. We use a custom promise library for three
|
||||
significant reasons:
|
||||
1. React promises (at the time of writing this) are recursive. Promise
|
||||
chaining and promise resolution will eventually blow the stack. Guzzle
|
||||
promises are not recursive as they use a sort of trampolining technique.
|
||||
Note: there has been movement in the React project to modify promises to
|
||||
no longer utilize recursion.
|
||||
2. Guzzle needs to have the ability to synchronously block on a promise to
|
||||
wait for a result. Guzzle promises allows this functionality (and does
|
||||
not require the use of recursion).
|
||||
3. Because we need to be able to wait on a result, doing so using React
|
||||
promises requires wrapping react promises with RingPHP futures. This
|
||||
overhead is no longer needed, reducing stack sizes, reducing complexity,
|
||||
and improving performance.
|
||||
- `GuzzleHttp\Mimetypes` has been moved to a function in
|
||||
`GuzzleHttp\Psr7\mimetype_from_extension` and
|
||||
`GuzzleHttp\Psr7\mimetype_from_filename`.
|
||||
- `GuzzleHttp\Query` and `GuzzleHttp\QueryParser` have been removed. Query
|
||||
strings must now be passed into request objects as strings, or provided to
|
||||
the `query` request option when creating requests with clients. The `query`
|
||||
option uses PHP's `http_build_query` to convert an array to a string. If you
|
||||
need a different serialization technique, you will need to pass the query
|
||||
string in as a string. There are a couple helper functions that will make
|
||||
working with query strings easier: `GuzzleHttp\Psr7\parse_query` and
|
||||
`GuzzleHttp\Psr7\build_query`.
|
||||
- Guzzle no longer has a dependency on RingPHP. Due to the use of a middleware
|
||||
system based on PSR-7, using RingPHP and it's middleware system as well adds
|
||||
more complexity than the benefits it provides. All HTTP handlers that were
|
||||
present in RingPHP have been modified to work directly with PSR-7 messages
|
||||
and placed in the `GuzzleHttp\Handler` namespace. This significantly reduces
|
||||
complexity in Guzzle, removes a dependency, and improves performance. RingPHP
|
||||
will be maintained for Guzzle 5 support, but will no longer be a part of
|
||||
Guzzle 6.
|
||||
- As Guzzle now uses a middleware based systems the event system and RingPHP
|
||||
integration has been removed. Note: while the event system has been removed,
|
||||
it is possible to add your own type of event system that is powered by the
|
||||
middleware system.
|
||||
- Removed the `Event` namespace.
|
||||
- Removed the `Subscriber` namespace.
|
||||
- Removed `Transaction` class
|
||||
- Removed `RequestFsm`
|
||||
- Removed `RingBridge`
|
||||
- `GuzzleHttp\Subscriber\Cookie` is now provided by
|
||||
`GuzzleHttp\Middleware::cookies`
|
||||
- `GuzzleHttp\Subscriber\HttpError` is now provided by
|
||||
`GuzzleHttp\Middleware::httpError`
|
||||
- `GuzzleHttp\Subscriber\History` is now provided by
|
||||
`GuzzleHttp\Middleware::history`
|
||||
- `GuzzleHttp\Subscriber\Mock` is now provided by
|
||||
`GuzzleHttp\Handler\MockHandler`
|
||||
- `GuzzleHttp\Subscriber\Prepare` is now provided by
|
||||
`GuzzleHttp\PrepareBodyMiddleware`
|
||||
- `GuzzleHttp\Subscriber\Redirect` is now provided by
|
||||
`GuzzleHttp\RedirectMiddleware`
|
||||
- Guzzle now uses `Psr\Http\Message\UriInterface` (implements in
|
||||
`GuzzleHttp\Psr7\Uri`) for URI support. `GuzzleHttp\Url` is now gone.
|
||||
- Static functions in `GuzzleHttp\Utils` have been moved to namespaced
|
||||
functions under the `GuzzleHttp` namespace. This requires either a Composer
|
||||
based autoloader or you to include functions.php.
|
||||
- `GuzzleHttp\ClientInterface::getDefaultOption` has been renamed to
|
||||
`GuzzleHttp\ClientInterface::getConfig`.
|
||||
- `GuzzleHttp\ClientInterface::setDefaultOption` has been removed.
|
||||
|
||||
## Migrating to middleware
|
||||
|
||||
The change to PSR-7 unfortunately required significant refactoring to Guzzle
|
||||
due to the fact that PSR-7 messages are immutable. Guzzle 5 relied on an event
|
||||
system from plugins. The event system relied on mutability of HTTP messages and
|
||||
side effects in order to work. With immutable messages, you have to change your
|
||||
workflow to become more about either returning a value (e.g., functional
|
||||
middlewares) or setting a value on an object. Guzzle v6 has chosen the
|
||||
functional middleware approach.
|
||||
|
||||
Instead of using the event system to listen for things like the `before` event,
|
||||
you now create a stack based middleware function that intercepts a request on
|
||||
the way in and the promise of the response on the way out. This is a much
|
||||
simpler and more predictable approach than the event system and works nicely
|
||||
with PSR-7 middleware. Due to the use of promises, the middleware system is
|
||||
also asynchronous.
|
||||
|
||||
v5:
|
||||
|
||||
```php
|
||||
use GuzzleHttp\Event\BeforeEvent;
|
||||
$client = new GuzzleHttp\Client();
|
||||
// Get the emitter and listen to the before event.
|
||||
$client->getEmitter()->on('before', function (BeforeEvent $e) {
|
||||
// Guzzle v5 events relied on mutation
|
||||
$e->getRequest()->setHeader('X-Foo', 'Bar');
|
||||
});
|
||||
```
|
||||
|
||||
v6:
|
||||
|
||||
In v6, you can modify the request before it is sent using the `mapRequest`
|
||||
middleware. The idiomatic way in v6 to modify the request/response lifecycle is
|
||||
to setup a handler middleware stack up front and inject the handler into a
|
||||
client.
|
||||
|
||||
```php
|
||||
use GuzzleHttp\Middleware;
|
||||
// Create a handler stack that has all of the default middlewares attached
|
||||
$handler = GuzzleHttp\HandlerStack::create();
|
||||
// Push the handler onto the handler stack
|
||||
$handler->push(Middleware::mapRequest(function (RequestInterface $request) {
|
||||
// Notice that we have to return a request object
|
||||
return $request->withHeader('X-Foo', 'Bar');
|
||||
});
|
||||
// Inject the handler into the client
|
||||
$client = new GuzzleHttp\Client(['handler' => $handler]);
|
||||
```
|
||||
|
||||
## POST Requests
|
||||
|
||||
This version added the [`form_params`](http://guzzle.readthedocs.org/en/latest/request-options.html#form_params)
|
||||
and `multipart` request options. `form_params` is an associative array of
|
||||
strings or array of strings and is used to serialize an
|
||||
`application/x-www-form-urlencoded` POST request. The
|
||||
[`multipart`](http://guzzle.readthedocs.org/en/latest/request-options.html#multipart)
|
||||
option is now used to send a multipart/form-data POST request.
|
||||
|
||||
`GuzzleHttp\Post\PostFile` has been removed. Use the `multipart` option to add
|
||||
POST files to a multipart/form-data request.
|
||||
|
||||
The `body` option no longer accepts an array to send POST requests. Please use
|
||||
`multipart` or `form_params` instead.
|
||||
|
||||
The `base_url` option has been renamed to `base_uri`.
|
||||
|
||||
4.x to 5.0
|
||||
----------
|
||||
|
||||
## Rewritten Adapter Layer
|
||||
|
||||
Guzzle now uses `RingPHP <http://ringphp.readthedocs.org/en/latest/>`_ to send
|
||||
Guzzle now uses [RingPHP](http://ringphp.readthedocs.org/en/latest) to send
|
||||
HTTP requests. The `adapter` option in a `GuzzleHttp\Client` constructor
|
||||
is still supported, but it has now been renamed to `handler`. Instead of
|
||||
passing a `GuzzleHttp\Adapter\AdapterInterface`, you must now pass a PHP
|
||||
|
@ -14,7 +163,7 @@ passing a `GuzzleHttp\Adapter\AdapterInterface`, you must now pass a PHP
|
|||
|
||||
## Removed Fluent Interfaces
|
||||
|
||||
`Fluent interfaces were removed <http://ocramius.github.io/blog/fluent-interfaces-are-evil/>`_
|
||||
[Fluent interfaces were removed](http://ocramius.github.io/blog/fluent-interfaces-are-evil)
|
||||
from the following classes:
|
||||
|
||||
- `GuzzleHttp\Collection`
|
||||
|
@ -35,7 +184,7 @@ functions can be used as replacements.
|
|||
deprecated in favor of using `GuzzleHttp\Pool::batch()`.
|
||||
|
||||
The "procedural" global client has been removed with no replacement (e.g.,
|
||||
`GuzzleHttp\get()`, `GuzzleHttp\post()`, etc.). Use a `GuzzleHttl\Client`
|
||||
`GuzzleHttp\get()`, `GuzzleHttp\post()`, etc.). Use a `GuzzleHttp\Client`
|
||||
object as a replacement.
|
||||
|
||||
## `throwImmediately` has been removed
|
||||
|
|
21
core/vendor/guzzlehttp/guzzle/build/packager.php
vendored
21
core/vendor/guzzlehttp/guzzle/build/packager.php
vendored
|
@ -1,21 +0,0 @@
|
|||
<?php
|
||||
require __DIR__ . '/artifacts/Burgomaster.php';
|
||||
|
||||
$stageDirectory = __DIR__ . '/artifacts/staging';
|
||||
$projectRoot = __DIR__ . '/../';
|
||||
$packager = new \Burgomaster($stageDirectory, $projectRoot);
|
||||
|
||||
// Copy basic files to the stage directory. Note that we have chdir'd onto
|
||||
// the $projectRoot directory, so use relative paths.
|
||||
foreach (['README.md', 'LICENSE'] as $file) {
|
||||
$packager->deepCopy($file, $file);
|
||||
}
|
||||
|
||||
// Copy each dependency to the staging directory. Copy *.php and *.pem files.
|
||||
$packager->recursiveCopy('src', 'GuzzleHttp', ['php']);
|
||||
$packager->recursiveCopy('vendor/react/promise/src', 'React/Promise');
|
||||
$packager->recursiveCopy('vendor/guzzlehttp/ringphp/src', 'GuzzleHttp/Ring');
|
||||
$packager->recursiveCopy('vendor/guzzlehttp/streams/src', 'GuzzleHttp/Stream');
|
||||
$packager->createAutoloader(['React/Promise/functions.php']);
|
||||
$packager->createPhar(__DIR__ . '/artifacts/guzzle.phar');
|
||||
$packager->createZip(__DIR__ . '/artifacts/guzzle.zip');
|
14
core/vendor/guzzlehttp/guzzle/composer.json
vendored
14
core/vendor/guzzlehttp/guzzle/composer.json
vendored
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "guzzlehttp/guzzle",
|
||||
"type": "library",
|
||||
"description": "Guzzle is a PHP HTTP client library and framework for building RESTful web service clients",
|
||||
"description": "Guzzle is a PHP HTTP client library",
|
||||
"keywords": ["framework", "http", "rest", "web service", "curl", "client", "HTTP client"],
|
||||
"homepage": "http://guzzlephp.org/",
|
||||
"license": "MIT",
|
||||
|
@ -13,15 +13,17 @@
|
|||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.4.0",
|
||||
"guzzlehttp/ringphp": "~1.0"
|
||||
"php": ">=5.5.0",
|
||||
"guzzlehttp/psr7": "~1.1",
|
||||
"guzzlehttp/promises": "~1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"ext-curl": "*",
|
||||
"psr/log": "~1.0",
|
||||
"phpunit/phpunit": "~4.0"
|
||||
"phpunit/phpunit": "~4.0",
|
||||
"psr/log": "~1.0"
|
||||
},
|
||||
"autoload": {
|
||||
"files": ["src/functions_include.php"],
|
||||
"psr-4": {
|
||||
"GuzzleHttp\\": "src/"
|
||||
}
|
||||
|
@ -33,7 +35,7 @@
|
|||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "5.0-dev"
|
||||
"dev-master": "6.0-dev"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
153
core/vendor/guzzlehttp/guzzle/docs/Makefile
vendored
153
core/vendor/guzzlehttp/guzzle/docs/Makefile
vendored
|
@ -1,153 +0,0 @@
|
|||
# Makefile for Sphinx documentation
|
||||
#
|
||||
|
||||
# You can set these variables from the command line.
|
||||
SPHINXOPTS =
|
||||
SPHINXBUILD = sphinx-build
|
||||
PAPER =
|
||||
BUILDDIR = _build
|
||||
|
||||
# Internal variables.
|
||||
PAPEROPT_a4 = -D latex_paper_size=a4
|
||||
PAPEROPT_letter = -D latex_paper_size=letter
|
||||
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
|
||||
# the i18n builder cannot share the environment and doctrees with the others
|
||||
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
|
||||
|
||||
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
|
||||
|
||||
help:
|
||||
@echo "Please use \`make <target>' where <target> is one of"
|
||||
@echo " html to make standalone HTML files"
|
||||
@echo " dirhtml to make HTML files named index.html in directories"
|
||||
@echo " singlehtml to make a single large HTML file"
|
||||
@echo " pickle to make pickle files"
|
||||
@echo " json to make JSON files"
|
||||
@echo " htmlhelp to make HTML files and a HTML help project"
|
||||
@echo " qthelp to make HTML files and a qthelp project"
|
||||
@echo " devhelp to make HTML files and a Devhelp project"
|
||||
@echo " epub to make an epub"
|
||||
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
|
||||
@echo " latexpdf to make LaTeX files and run them through pdflatex"
|
||||
@echo " text to make text files"
|
||||
@echo " man to make manual pages"
|
||||
@echo " texinfo to make Texinfo files"
|
||||
@echo " info to make Texinfo files and run them through makeinfo"
|
||||
@echo " gettext to make PO message catalogs"
|
||||
@echo " changes to make an overview of all changed/added/deprecated items"
|
||||
@echo " linkcheck to check all external links for integrity"
|
||||
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
|
||||
|
||||
clean:
|
||||
-rm -rf $(BUILDDIR)/*
|
||||
|
||||
html:
|
||||
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
|
||||
@echo
|
||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
|
||||
|
||||
dirhtml:
|
||||
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
|
||||
@echo
|
||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
|
||||
|
||||
singlehtml:
|
||||
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
|
||||
@echo
|
||||
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
|
||||
|
||||
pickle:
|
||||
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
|
||||
@echo
|
||||
@echo "Build finished; now you can process the pickle files."
|
||||
|
||||
json:
|
||||
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
|
||||
@echo
|
||||
@echo "Build finished; now you can process the JSON files."
|
||||
|
||||
htmlhelp:
|
||||
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
|
||||
@echo
|
||||
@echo "Build finished; now you can run HTML Help Workshop with the" \
|
||||
".hhp project file in $(BUILDDIR)/htmlhelp."
|
||||
|
||||
qthelp:
|
||||
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
|
||||
@echo
|
||||
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
|
||||
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
|
||||
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Guzzle.qhcp"
|
||||
@echo "To view the help file:"
|
||||
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Guzzle.qhc"
|
||||
|
||||
devhelp:
|
||||
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
|
||||
@echo
|
||||
@echo "Build finished."
|
||||
@echo "To view the help file:"
|
||||
@echo "# mkdir -p $$HOME/.local/share/devhelp/Guzzle"
|
||||
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Guzzle"
|
||||
@echo "# devhelp"
|
||||
|
||||
epub:
|
||||
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
|
||||
@echo
|
||||
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
|
||||
|
||||
latex:
|
||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||
@echo
|
||||
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
|
||||
@echo "Run \`make' in that directory to run these through (pdf)latex" \
|
||||
"(use \`make latexpdf' here to do that automatically)."
|
||||
|
||||
latexpdf:
|
||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||
@echo "Running LaTeX files through pdflatex..."
|
||||
$(MAKE) -C $(BUILDDIR)/latex all-pdf
|
||||
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
|
||||
|
||||
text:
|
||||
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
|
||||
@echo
|
||||
@echo "Build finished. The text files are in $(BUILDDIR)/text."
|
||||
|
||||
man:
|
||||
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
|
||||
@echo
|
||||
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
|
||||
|
||||
texinfo:
|
||||
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
|
||||
@echo
|
||||
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
|
||||
@echo "Run \`make' in that directory to run these through makeinfo" \
|
||||
"(use \`make info' here to do that automatically)."
|
||||
|
||||
info:
|
||||
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
|
||||
@echo "Running Texinfo files through makeinfo..."
|
||||
make -C $(BUILDDIR)/texinfo info
|
||||
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
|
||||
|
||||
gettext:
|
||||
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
|
||||
@echo
|
||||
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
|
||||
|
||||
changes:
|
||||
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
|
||||
@echo
|
||||
@echo "The overview file is in $(BUILDDIR)/changes."
|
||||
|
||||
linkcheck:
|
||||
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
|
||||
@echo
|
||||
@echo "Link check complete; look for any errors in the above output " \
|
||||
"or in $(BUILDDIR)/linkcheck/output.txt."
|
||||
|
||||
doctest:
|
||||
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
|
||||
@echo "Testing of doctests in the sources finished, look at the " \
|
||||
"results in $(BUILDDIR)/doctest/output.txt."
|
Binary file not shown.
Before Width: | Height: | Size: 803 B |
BIN
core/vendor/guzzlehttp/guzzle/docs/_static/logo.png
vendored
BIN
core/vendor/guzzlehttp/guzzle/docs/_static/logo.png
vendored
Binary file not shown.
Before Width: | Height: | Size: 242 KiB |
|
@ -1,3 +0,0 @@
|
|||
<li><a href="https://github.com/guzzle/guzzle">GitHub</a></li>
|
||||
<li><a href="https://groups.google.com/forum/?hl=en#!forum/guzzle">Forum</a></li>
|
||||
<li><a href="irc:irc.freenode.com/#guzzlephp">IRC</a></li>
|
1315
core/vendor/guzzlehttp/guzzle/docs/clients.rst
vendored
1315
core/vendor/guzzlehttp/guzzle/docs/clients.rst
vendored
File diff suppressed because it is too large
Load diff
28
core/vendor/guzzlehttp/guzzle/docs/conf.py
vendored
28
core/vendor/guzzlehttp/guzzle/docs/conf.py
vendored
|
@ -1,28 +0,0 @@
|
|||
import sys, os
|
||||
from sphinx.highlighting import lexers
|
||||
from pygments.lexers.web import PhpLexer
|
||||
|
||||
|
||||
lexers['php'] = PhpLexer(startinline=True, linenos=1)
|
||||
lexers['php-annotations'] = PhpLexer(startinline=True, linenos=1)
|
||||
primary_domain = 'php'
|
||||
|
||||
extensions = []
|
||||
templates_path = ['_templates']
|
||||
source_suffix = '.rst'
|
||||
master_doc = 'index'
|
||||
project = u'Guzzle'
|
||||
copyright = u'2014, Michael Dowling'
|
||||
version = '5.0.0'
|
||||
html_title = "Guzzle Documentation"
|
||||
html_short_title = "Guzzle"
|
||||
|
||||
exclude_patterns = ['_build']
|
||||
html_static_path = ['_static']
|
||||
|
||||
on_rtd = os.environ.get('READTHEDOCS', None) == 'True'
|
||||
|
||||
if not on_rtd: # only import and set the theme if we're building docs locally
|
||||
import sphinx_rtd_theme
|
||||
html_theme = 'sphinx_rtd_theme'
|
||||
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
|
520
core/vendor/guzzlehttp/guzzle/docs/events.rst
vendored
520
core/vendor/guzzlehttp/guzzle/docs/events.rst
vendored
|
@ -1,520 +0,0 @@
|
|||
============
|
||||
Event System
|
||||
============
|
||||
|
||||
Guzzle uses an event emitter to allow you to easily extend the behavior of a
|
||||
request, change the response associated with a request, and implement custom
|
||||
error handling. All events in Guzzle are managed and emitted by an
|
||||
**event emitter**.
|
||||
|
||||
Event Emitters
|
||||
==============
|
||||
|
||||
Clients, requests, and any other class that implements the
|
||||
``GuzzleHttp\Event\HasEmitterInterface`` interface have a
|
||||
``GuzzleHttp\Event\Emitter`` object. You can add event *listeners* and
|
||||
event *subscribers* to an event *emitter*.
|
||||
|
||||
emitter
|
||||
An object that implements ``GuzzleHttp\Event\EmitterInterface``. This
|
||||
object emits named events to event listeners. You may register event
|
||||
listeners on subscribers on an emitter.
|
||||
|
||||
event listeners
|
||||
Callable functions that are registered on an event emitter for specific
|
||||
events. Event listeners are registered on an emitter with a *priority*
|
||||
setting. If no priority is provided, ``0`` is used by default.
|
||||
|
||||
event subscribers
|
||||
Classes that tell an event emitter what methods to listen to and what
|
||||
functions on the class to invoke when the event is triggered. Event
|
||||
subscribers subscribe event listeners to an event emitter. They should be
|
||||
used when creating more complex event based logic in applications (i.e.,
|
||||
cookie handling is implemented using an event subscriber because it's
|
||||
easier to share a subscriber than an anonymous function and because
|
||||
handling cookies is a complex process).
|
||||
|
||||
priority
|
||||
Describes the order in which event listeners are invoked when an event is
|
||||
emitted. The higher a priority value, the earlier the event listener will
|
||||
be invoked (a higher priority means the listener is more important). If
|
||||
no priority is provided, the priority is assumed to be ``0``.
|
||||
|
||||
When specifying an event priority, you can pass ``"first"`` or ``"last"`` to
|
||||
dynamically specify the priority based on the current event priorities
|
||||
associated with the given event name in the emitter. Use ``"first"`` to set
|
||||
the priority to the current highest priority plus one. Use ``"last"`` to
|
||||
set the priority to the current lowest event priority minus one. It is
|
||||
important to remember that these dynamic priorities are calculated only at
|
||||
the point of insertion into the emitter and they are not rearranged after
|
||||
subsequent listeners are added to an emitter.
|
||||
|
||||
propagation
|
||||
Describes whether or not other event listeners are triggered. Event
|
||||
emitters will trigger every event listener registered to a specific event
|
||||
in priority order until all of the listeners have been triggered **or**
|
||||
until the propagation of an event is stopped.
|
||||
|
||||
Getting an EventEmitter
|
||||
-----------------------
|
||||
|
||||
You can get the event emitter of ``GuzzleHttp\Event\HasEmitterInterface``
|
||||
object using the the ``getEmitter()`` method. Here's an example of getting a
|
||||
client object's event emitter.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$client = new GuzzleHttp\Client();
|
||||
$emitter = $client->getEmitter();
|
||||
|
||||
.. note::
|
||||
|
||||
You'll notice that the event emitter used in Guzzle is very similar to the
|
||||
`Symfony2 EventDispatcher component <https://github.com/symfony/symfony/tree/master/src/Symfony/Component/EventDispatcher>`_.
|
||||
This is because the Guzzle event system is based on the Symfony2 event
|
||||
system with several changes. Guzzle uses its own event emitter to improve
|
||||
performance, isolate Guzzle from changes to the Symfony, and provide a few
|
||||
improvements that make it easier to use for an HTTP client (e.g., the
|
||||
addition of the ``once()`` method).
|
||||
|
||||
Adding Event Listeners
|
||||
----------------------
|
||||
|
||||
After you have the emitter, you can register event listeners that listen to
|
||||
specific events using the ``on()`` method. When registering an event listener,
|
||||
you must tell the emitter what event to listen to (e.g., "before", "after",
|
||||
"progress", "complete", "error", etc.), what callable to invoke when the
|
||||
event is triggered, and optionally provide a priority.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use GuzzleHttp\Event\BeforeEvent;
|
||||
|
||||
$emitter->on('before', function (BeforeEvent $event) {
|
||||
echo $event->getRequest();
|
||||
});
|
||||
|
||||
When a listener is triggered, it is passed an event that implements the
|
||||
``GuzzleHttp\Event\EventInterface`` interface, the name of the event, and the
|
||||
event emitter itself. The above example could more verbosely be written as
|
||||
follows:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use GuzzleHttp\Event\BeforeEvent;
|
||||
|
||||
$emitter->on('before', function (
|
||||
BeforeEvent $event,
|
||||
$name,
|
||||
EmitterInterface $emitter
|
||||
) {
|
||||
echo $event->getRequest();
|
||||
});
|
||||
|
||||
You can add an event listener that automatically removes itself after it is
|
||||
triggered using the ``once()`` method of an event emitter.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$client = new GuzzleHttp\Client();
|
||||
$client->getEmitter()->once('before', function () {
|
||||
echo 'This will only happen once... per request!';
|
||||
});
|
||||
|
||||
Event Propagation
|
||||
-----------------
|
||||
|
||||
Event listeners can prevent other event listeners from being triggered by
|
||||
stopping an event's propagation.
|
||||
|
||||
Stopping event propagation can be useful, for example, if an event listener has
|
||||
changed the state of the subject to such an extent that allowing subsequent
|
||||
event listeners to be triggered could place the subject in an inconsistent
|
||||
state. This technique is used in Guzzle extensively when intercepting error
|
||||
events with responses.
|
||||
|
||||
You can stop the propagation of an event using the ``stopPropagation()`` method
|
||||
of a ``GuzzleHttp\Event\EventInterface`` object:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use GuzzleHttp\Event\ErrorEvent;
|
||||
|
||||
$emitter->on('error', function (ErrorEvent $event) {
|
||||
$event->stopPropagation();
|
||||
});
|
||||
|
||||
After stopping the propagation of an event, any subsequent event listeners that
|
||||
have not yet been triggered will not be triggered. You can check to see if the
|
||||
propagation of an event was stopped using the ``isPropagationStopped()`` method
|
||||
of the event.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$client = new GuzzleHttp\Client();
|
||||
$emitter = $client->getEmitter();
|
||||
// Note: assume that the $errorEvent was created
|
||||
if ($emitter->emit('error', $errorEvent)->isPropagationStopped()) {
|
||||
echo 'It was stopped!';
|
||||
}
|
||||
|
||||
.. hint::
|
||||
|
||||
When emitting events, the event that was emitted is returned from the
|
||||
emitter. This allows you to easily chain calls as shown in the above
|
||||
example.
|
||||
|
||||
Event Subscribers
|
||||
-----------------
|
||||
|
||||
Event subscribers are classes that implement the
|
||||
``GuzzleHttp\Event\SubscriberInterface`` object. They are used to register
|
||||
one or more event listeners to methods of the class. Event subscribers tell
|
||||
event emitters exactly which events to listen to and what method to invoke on
|
||||
the class when the event is triggered by called the ``getEvents()`` method of
|
||||
a subscriber.
|
||||
|
||||
The following example registers event listeners to the ``before`` and
|
||||
``complete`` event of a request. When the ``before`` event is emitted, the
|
||||
``onBefore`` instance method of the subscriber is invoked. When the
|
||||
``complete`` event is emitted, the ``onComplete`` event of the subscriber is
|
||||
invoked. Each array value in the ``getEvents()`` return value MUST
|
||||
contain the name of the method to invoke and can optionally contain the
|
||||
priority of the listener (as shown in the ``before`` listener in the example).
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use GuzzleHttp\Event\EmitterInterface;
|
||||
use GuzzleHttp\Event\SubscriberInterface;
|
||||
use GuzzleHttp\Event\BeforeEvent;
|
||||
use GuzzleHttp\Event\CompleteEvent;
|
||||
|
||||
class SimpleSubscriber implements SubscriberInterface
|
||||
{
|
||||
public function getEvents()
|
||||
{
|
||||
return [
|
||||
// Provide name and optional priority
|
||||
'before' => ['onBefore', 100],
|
||||
'complete' => ['onComplete'],
|
||||
// You can pass a list of listeners with different priorities
|
||||
'error' => [['beforeError', 'first'], ['afterError', 'last']]
|
||||
];
|
||||
}
|
||||
|
||||
public function onBefore(BeforeEvent $event, $name)
|
||||
{
|
||||
echo 'Before!';
|
||||
}
|
||||
|
||||
public function onComplete(CompleteEvent $event, $name)
|
||||
{
|
||||
echo 'Complete!';
|
||||
}
|
||||
}
|
||||
|
||||
To register the listeners the subscriber needs to be attached to the emitter:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$client = new GuzzleHttp\Client();
|
||||
$emitter = $client->getEmitter();
|
||||
$subscriber = new SimpleSubscriber();
|
||||
$emitter->attach($subscriber);
|
||||
|
||||
//to remove the listeners
|
||||
$emitter->detach($subscriber);
|
||||
|
||||
.. note::
|
||||
|
||||
You can specify event priorities using integers or ``"first"`` and
|
||||
``"last"`` to dynamically determine the priority.
|
||||
|
||||
Event Priorities
|
||||
================
|
||||
|
||||
When adding event listeners or subscribers, you can provide an optional event
|
||||
priority. This priority is used to determine how early or late a listener is
|
||||
triggered. Specifying the correct priority is an important aspect of ensuring
|
||||
a listener behaves as expected. For example, if you wanted to ensure that
|
||||
cookies associated with a redirect were added to a cookie jar, you'd need to
|
||||
make sure that the listener that collects the cookies is triggered before the
|
||||
listener that performs the redirect.
|
||||
|
||||
In order to help make the process of determining the correct event priority of
|
||||
a listener easier, Guzzle provides several pre-determined named event
|
||||
priorities. These priorities are exposed as constants on the
|
||||
``GuzzleHttp\Event\RequestEvents`` object.
|
||||
|
||||
last
|
||||
Use ``"last"`` as an event priority to set the priority to the current
|
||||
lowest event priority minus one.
|
||||
|
||||
first
|
||||
Use ``"first"`` as an event priority to set the priority to the current
|
||||
highest priority plus one.
|
||||
|
||||
``GuzzleHttp\Event\RequestEvents::EARLY``
|
||||
Used when you want a listener to be triggered as early as possible in the
|
||||
event chain.
|
||||
|
||||
``GuzzleHttp\Event\RequestEvents::LATE``
|
||||
Used when you want a listener to be to be triggered as late as possible in
|
||||
the event chain.
|
||||
|
||||
``GuzzleHttp\Event\RequestEvents::PREPARE_REQUEST``
|
||||
Used when you want a listener to be trigger while a request is being
|
||||
prepared during the ``before`` event. This event priority is used by the
|
||||
``GuzzleHttp\Subscriber\Prepare`` event subscriber which is responsible for
|
||||
guessing a Content-Type, Content-Length, and Expect header of a request.
|
||||
You should subscribe after this event is triggered if you want to ensure
|
||||
that this subscriber has already been triggered.
|
||||
|
||||
``GuzzleHttp\Event\RequestEvents::SIGN_REQUEST``
|
||||
Used when you want a listener to be triggered when a request is about to be
|
||||
signed. Any listener triggered at this point should expect that the request
|
||||
object will no longer be mutated. If you are implementing a custom
|
||||
signature subscriber, then you should use this event priority to sign
|
||||
requests.
|
||||
|
||||
``GuzzleHttp\Event\RequestEvents::VERIFY_RESPONSE``
|
||||
Used when you want a listener to be triggered when a response is being
|
||||
validated during the ``complete`` event. The
|
||||
``GuzzleHttp\Subscriber\HttpError`` event subscriber uses this event
|
||||
priority to check if an exception should be thrown due to a 4xx or 5xx
|
||||
level response status code. If you are doing any kind of verification of a
|
||||
response during the complete event, it should happen at this priority.
|
||||
|
||||
``GuzzleHttp\Event\RequestEvents::REDIRECT_RESPONSE``
|
||||
Used when you want a listener to be triggered when a response is being
|
||||
redirected during the ``complete`` event. The
|
||||
``GuzzleHttp\Subscriber\Redirect`` event subscriber uses this event
|
||||
priority when performing redirects.
|
||||
|
||||
You can use the above event priorities as a guideline for determining the
|
||||
priority of you event listeners. You can use these constants and add to or
|
||||
subtract from them to ensure that a listener happens before or after the named
|
||||
priority.
|
||||
|
||||
.. note::
|
||||
|
||||
"first" and "last" priorities are not adjusted after they added to an
|
||||
emitter. For example, if you add a listener with a priority of "first",
|
||||
you can still add subsequent listeners with a higher priority which would
|
||||
be triggered before the listener added with a priority of "first".
|
||||
|
||||
Working With Request Events
|
||||
===========================
|
||||
|
||||
Requests emit lifecycle events when they are transferred.
|
||||
|
||||
.. important::
|
||||
|
||||
Excluding the ``end`` event, request lifecycle events may be triggered
|
||||
multiple times due to redirects, retries, or reusing a request multiple
|
||||
times. Use the ``once()`` method want the event to be triggered once. You
|
||||
can also remove an event listener from an emitter by using the emitter which
|
||||
is provided to the listener.
|
||||
|
||||
.. _before_event:
|
||||
|
||||
before
|
||||
------
|
||||
|
||||
The ``before`` event is emitted before a request is sent. The event emitted is
|
||||
a ``GuzzleHttp\Event\BeforeEvent``.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Event\EmitterInterface;
|
||||
use GuzzleHttp\Event\BeforeEvent;
|
||||
|
||||
$client = new Client(['base_url' => 'http://httpbin.org']);
|
||||
$request = $client->createRequest('GET', '/');
|
||||
$request->getEmitter()->on(
|
||||
'before',
|
||||
function (BeforeEvent $e, $name, EmitterInterface $emitter) {
|
||||
echo $name . "\n";
|
||||
// "before"
|
||||
echo $e->getRequest()->getMethod() . "\n";
|
||||
// "GET" / "POST" / "PUT" / etc.
|
||||
echo get_class($e->getClient());
|
||||
// "GuzzleHttp\Client"
|
||||
}
|
||||
);
|
||||
|
||||
You can intercept a request with a response before the request is sent over the
|
||||
wire. The ``intercept()`` method of the ``BeforeEvent`` accepts a
|
||||
``GuzzleHttp\Message\ResponseInterface``. Intercepting the event will prevent
|
||||
the request from being sent over the wire and stops the propagation of the
|
||||
``before`` event, preventing subsequent event listeners from being invoked.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Event\BeforeEvent;
|
||||
use GuzzleHttp\Message\Response;
|
||||
|
||||
$client = new Client(['base_url' => 'http://httpbin.org']);
|
||||
$request = $client->createRequest('GET', '/status/500');
|
||||
$request->getEmitter()->on('before', function (BeforeEvent $e) {
|
||||
$response = new Response(200);
|
||||
$e->intercept($response);
|
||||
});
|
||||
|
||||
$response = $client->send($request);
|
||||
echo $response->getStatusCode();
|
||||
// 200
|
||||
|
||||
.. attention::
|
||||
|
||||
Any exception encountered while executing the ``before`` event will trigger
|
||||
the ``error`` event of a request.
|
||||
|
||||
.. _complete_event:
|
||||
|
||||
complete
|
||||
--------
|
||||
|
||||
The ``complete`` event is emitted after a transaction completes and an entire
|
||||
response has been received. The event is a ``GuzzleHttp\Event\CompleteEvent``.
|
||||
|
||||
You can intercept the ``complete`` event with a different response if needed
|
||||
using the ``intercept()`` method of the event. This can be useful, for example,
|
||||
for changing the response for caching.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Event\CompleteEvent;
|
||||
use GuzzleHttp\Message\Response;
|
||||
|
||||
$client = new Client(['base_url' => 'http://httpbin.org']);
|
||||
$request = $client->createRequest('GET', '/status/302');
|
||||
$cachedResponse = new Response(200);
|
||||
|
||||
$request->getEmitter()->on(
|
||||
'complete',
|
||||
function (CompleteEvent $e) use ($cachedResponse) {
|
||||
if ($e->getResponse()->getStatusCode() == 302) {
|
||||
// Intercept the original transaction with the new response
|
||||
$e->intercept($cachedResponse);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
$response = $client->send($request);
|
||||
echo $response->getStatusCode();
|
||||
// 200
|
||||
|
||||
.. attention::
|
||||
|
||||
Any ``GuzzleHttp\Exception\RequestException`` encountered while executing
|
||||
the ``complete`` event will trigger the ``error`` event of a request.
|
||||
|
||||
.. _error_event:
|
||||
|
||||
error
|
||||
-----
|
||||
|
||||
The ``error`` event is emitted when a request fails (whether it's from a
|
||||
networking error or an HTTP protocol error). The event emitted is a
|
||||
``GuzzleHttp\Event\ErrorEvent``.
|
||||
|
||||
This event is useful for retrying failed requests. Here's an example of
|
||||
retrying failed basic auth requests by re-sending the original request with
|
||||
a username and password.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Event\ErrorEvent;
|
||||
|
||||
$client = new Client(['base_url' => 'http://httpbin.org']);
|
||||
$request = $client->createRequest('GET', '/basic-auth/foo/bar');
|
||||
$request->getEmitter()->on('error', function (ErrorEvent $e) {
|
||||
if ($e->getResponse()->getStatusCode() == 401) {
|
||||
// Add authentication stuff as needed and retry the request
|
||||
$e->getRequest()->setHeader('Authorization', 'Basic ' . base64_encode('foo:bar'));
|
||||
// Get the client of the event and retry the request
|
||||
$newResponse = $e->getClient()->send($e->getRequest());
|
||||
// Intercept the original transaction with the new response
|
||||
$e->intercept($newResponse);
|
||||
}
|
||||
});
|
||||
|
||||
.. attention::
|
||||
|
||||
If an ``error`` event is intercepted with a response, then the ``complete``
|
||||
event of a request is triggered. If the ``complete`` event fails, then the
|
||||
``error`` event is triggered once again.
|
||||
|
||||
.. _progress_event:
|
||||
|
||||
progress
|
||||
--------
|
||||
|
||||
The ``progress`` event is emitted when data is uploaded or downloaded. The
|
||||
event emitted is a ``GuzzleHttp\Event\ProgressEvent``.
|
||||
|
||||
You can access the emitted progress values using the corresponding public
|
||||
properties of the event object:
|
||||
|
||||
- ``$downloadSize``: The number of bytes that will be downloaded (if known)
|
||||
- ``$downloaded``: The number of bytes that have been downloaded
|
||||
- ``$uploadSize``: The number of bytes that will be uploaded (if known)
|
||||
- ``$uploaded``: The number of bytes that have been uploaded
|
||||
|
||||
This event cannot be intercepted.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Event\ProgressEvent;
|
||||
|
||||
$client = new Client(['base_url' => 'http://httpbin.org']);
|
||||
$request = $client->createRequest('PUT', '/put', [
|
||||
'body' => str_repeat('.', 100000)
|
||||
]);
|
||||
|
||||
$request->getEmitter()->on('progress', function (ProgressEvent $e) {
|
||||
echo 'Downloaded ' . $e->downloaded . ' of ' . $e->downloadSize . ' '
|
||||
. 'Uploaded ' . $e->uploaded . ' of ' . $e->uploadSize . "\r";
|
||||
});
|
||||
|
||||
$client->send($request);
|
||||
echo "\n";
|
||||
|
||||
.. _end_event:
|
||||
|
||||
end
|
||||
---
|
||||
|
||||
The ``end`` event is a terminal event, emitted once per request, that provides
|
||||
access to the response that was received or the exception that was encountered.
|
||||
The event emitted is a ``GuzzleHttp\Event\EndEvent``.
|
||||
|
||||
This event can be intercepted, but keep in mind that the ``complete`` event
|
||||
will not fire after intercepting this event.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Event\EndEvent;
|
||||
|
||||
$client = new Client(['base_url' => 'http://httpbin.org']);
|
||||
$request = $client->createRequest('PUT', '/put', [
|
||||
'body' => str_repeat('.', 100000)
|
||||
]);
|
||||
|
||||
$request->getEmitter()->on('end', function (EndEvent $e) {
|
||||
if ($e->getException()) {
|
||||
echo 'Error: ' . $e->getException()->getMessage();
|
||||
} else {
|
||||
echo 'Response: ' . $e->getResponse();
|
||||
}
|
||||
});
|
||||
|
||||
$client->send($request);
|
||||
echo "\n";
|
199
core/vendor/guzzlehttp/guzzle/docs/faq.rst
vendored
199
core/vendor/guzzlehttp/guzzle/docs/faq.rst
vendored
|
@ -1,199 +0,0 @@
|
|||
===
|
||||
FAQ
|
||||
===
|
||||
|
||||
Why should I use Guzzle?
|
||||
========================
|
||||
|
||||
Guzzle makes it easy to send HTTP requests and super simple to integrate with
|
||||
web services. Guzzle manages things like persistent connections, represents
|
||||
query strings as collections, makes it simple to send streaming POST requests
|
||||
with fields and files, and abstracts away the underlying HTTP transport layer.
|
||||
By providing an object oriented interface for HTTP clients, requests, responses,
|
||||
headers, and message bodies, Guzzle makes it so that you no longer need to fool
|
||||
around with cURL options, stream contexts, or sockets.
|
||||
|
||||
**Asynchronous and Synchronous Requests**
|
||||
|
||||
Guzzle allows you to send both asynchronous and synchronous requests using the
|
||||
same interface and no direct dependency on an event loop. This flexibility
|
||||
allows Guzzle to send an HTTP request using the most appropriate HTTP handler
|
||||
based on the request being sent. For example, when sending synchronous
|
||||
requests, Guzzle will by default send requests using cURL easy handles to
|
||||
ensure you're using the fastest possible method for serially transferring HTTP
|
||||
requests. When sending asynchronous requests, Guzzle might use cURL's multi
|
||||
interface or any other asynchronous handler you configure. When you request
|
||||
streaming data, Guzzle will by default use PHP's stream wrapper.
|
||||
|
||||
**Streams**
|
||||
|
||||
Request and response message bodies use :doc:`Guzzle Streams <streams>`,
|
||||
allowing you to stream data without needing to load it all into memory.
|
||||
Guzzle's stream layer provides a large suite of functionality:
|
||||
|
||||
- You can modify streams at runtime using custom or a number of
|
||||
pre-made decorators.
|
||||
- You can emit progress events as data is read from a stream.
|
||||
- You can validate the integrity of a stream using a rolling hash as data is
|
||||
read from a stream.
|
||||
|
||||
**Event System and Plugins**
|
||||
|
||||
Guzzle's event system allows you to completely modify the behavior of a client
|
||||
or request at runtime to cater them for any API. You can send a request with a
|
||||
client, and the client can do things like automatically retry your request if
|
||||
it fails, automatically redirect, log HTTP messages that are sent over the
|
||||
wire, emit progress events as data is uploaded and downloaded, sign requests
|
||||
using OAuth 1.0, verify the integrity of messages before and after they are
|
||||
sent over the wire, and anything else you might need.
|
||||
|
||||
**Testable**
|
||||
|
||||
Another important aspect of Guzzle is that it's really
|
||||
:doc:`easy to test clients <testing>`. You can mock HTTP responses and when
|
||||
testing an handler implementation, Guzzle provides a mock node.js web server.
|
||||
|
||||
**Ecosystem**
|
||||
|
||||
Guzzle has a large `ecosystem of plugins <http://guzzle.readthedocs.org/en/latest/index.html#http-components>`_,
|
||||
including `service descriptions <https://github.com/guzzle/guzzle-services>`_
|
||||
which allows you to abstract web services using service descriptions. These
|
||||
service descriptions define how to serialize an HTTP request and how to parse
|
||||
an HTTP response into a more meaningful model object.
|
||||
|
||||
- `Guzzle Command <https://github.com/guzzle/command>`_: Provides the building
|
||||
blocks for service description abstraction.
|
||||
- `Guzzle Services <https://github.com/guzzle/guzzle-services>`_: Provides an
|
||||
implementation of "Guzzle Command" that utilizes Guzzle's service description
|
||||
format.
|
||||
|
||||
Does Guzzle require cURL?
|
||||
=========================
|
||||
|
||||
No. Guzzle can use any HTTP handler to send requests. This means that Guzzle
|
||||
can be used with cURL, PHP's stream wrapper, sockets, and non-blocking libraries
|
||||
like `React <http://reactphp.org/>`_. You just need to configure a
|
||||
`RingPHP <http://guzzle-ring.readthedocs.org/en/latest/>`_ handler to use a
|
||||
different method of sending requests.
|
||||
|
||||
.. note::
|
||||
|
||||
Guzzle has historically only utilized cURL to send HTTP requests. cURL is
|
||||
an amazing HTTP client (arguably the best), and Guzzle will continue to use
|
||||
it by default when it is available. It is rare, but some developers don't
|
||||
have cURL installed on their systems or run into version specific issues.
|
||||
By allowing swappable HTTP handlers, Guzzle is now much more customizable
|
||||
and able to adapt to fit the needs of more developers.
|
||||
|
||||
Can Guzzle send asynchronous requests?
|
||||
======================================
|
||||
|
||||
Yes. Pass the ``future`` true request option to a request to send it
|
||||
asynchronously. Guzzle will then return a ``GuzzleHttp\Message\FutureResponse``
|
||||
object that can be used synchronously by accessing the response object like a
|
||||
normal response, and it can be used asynchronously using a promise that is
|
||||
notified when the response is resolved with a real response or rejected with an
|
||||
exception.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$request = $client->createRequest('GET', ['future' => true]);
|
||||
$client->send($request)->then(function ($response) {
|
||||
echo 'Got a response! ' . $response;
|
||||
});
|
||||
|
||||
You can force an asynchronous response to complete using the ``wait()`` method
|
||||
of a response.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$request = $client->createRequest('GET', ['future' => true]);
|
||||
$futureResponse = $client->send($request);
|
||||
$futureResponse->wait();
|
||||
|
||||
How can I add custom cURL options?
|
||||
==================================
|
||||
|
||||
cURL offer a huge number of `customizable options <http://us1.php.net/curl_setopt>`_.
|
||||
While Guzzle normalizes many of these options across different handlers, there
|
||||
are times when you need to set custom cURL options. This can be accomplished
|
||||
by passing an associative array of cURL settings in the **curl** key of the
|
||||
**config** request option.
|
||||
|
||||
For example, let's say you need to customize the outgoing network interface
|
||||
used with a client.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$client->get('/', [
|
||||
'config' => [
|
||||
'curl' => [
|
||||
CURLOPT_INTERFACE => 'xxx.xxx.xxx.xxx'
|
||||
]
|
||||
]
|
||||
]);
|
||||
|
||||
How can I add custom stream context options?
|
||||
============================================
|
||||
|
||||
You can pass custom `stream context options <http://www.php.net/manual/en/context.php>`_
|
||||
using the **stream_context** key of the **config** request option. The
|
||||
**stream_context** array is an associative array where each key is a PHP
|
||||
transport, and each value is an associative array of transport options.
|
||||
|
||||
For example, let's say you need to customize the outgoing network interface
|
||||
used with a client and allow self-signed certificates.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$client->get('/', [
|
||||
'stream' => true,
|
||||
'config' => [
|
||||
'stream_context' => [
|
||||
'ssl' => [
|
||||
'allow_self_signed' => true
|
||||
],
|
||||
'socket' => [
|
||||
'bindto' => 'xxx.xxx.xxx.xxx'
|
||||
]
|
||||
]
|
||||
]
|
||||
]);
|
||||
|
||||
Why am I getting an SSL verification error?
|
||||
===========================================
|
||||
|
||||
You need to specify the path on disk to the CA bundle used by Guzzle for
|
||||
verifying the peer certificate. See :ref:`verify-option`.
|
||||
|
||||
What is this Maximum function nesting error?
|
||||
============================================
|
||||
|
||||
Maximum function nesting level of '100' reached, aborting
|
||||
|
||||
You could run into this error if you have the XDebug extension installed and
|
||||
you execute a lot of requests in callbacks. This error message comes
|
||||
specifically from the XDebug extension. PHP itself does not have a function
|
||||
nesting limit. Change this setting in your php.ini to increase the limit::
|
||||
|
||||
xdebug.max_nesting_level = 1000
|
||||
|
||||
Why am I getting a 417 error response?
|
||||
======================================
|
||||
|
||||
This can occur for a number of reasons, but if you are sending PUT, POST, or
|
||||
PATCH requests with an ``Expect: 100-Continue`` header, a server that does not
|
||||
support this header will return a 417 response. You can work around this by
|
||||
setting the ``expect`` request option to ``false``:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$client = new GuzzleHttp\Client();
|
||||
|
||||
// Disable the expect header on a single request
|
||||
$response = $client->put('/', [], 'the body', [
|
||||
'expect' => false
|
||||
]);
|
||||
|
||||
// Disable the expect header on all client requests
|
||||
$client->setDefaultOption('expect', false)
|
43
core/vendor/guzzlehttp/guzzle/docs/handlers.rst
vendored
43
core/vendor/guzzlehttp/guzzle/docs/handlers.rst
vendored
|
@ -1,43 +0,0 @@
|
|||
================
|
||||
RingPHP Handlers
|
||||
================
|
||||
|
||||
Guzzle uses RingPHP handlers to send HTTP requests over the wire.
|
||||
RingPHP provides a low-level library that can be used to "glue" Guzzle with
|
||||
any transport method you choose. By default, Guzzle utilizes cURL and PHP's
|
||||
stream wrappers to send HTTP requests.
|
||||
|
||||
RingPHP handlers makes it extremely simple to integrate Guzzle with any
|
||||
HTTP transport. For example, you could quite easily bridge Guzzle and React
|
||||
to use Guzzle in React's event loop.
|
||||
|
||||
Using a handler
|
||||
---------------
|
||||
|
||||
You can change the handler used by a client using the ``handler`` option in the
|
||||
``GuzzleHttp\Client`` constructor.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Ring\Client\MockHandler;
|
||||
|
||||
// Create a mock handler that always returns a 200 response.
|
||||
$handler = new MockHandler(['status' => 200]);
|
||||
|
||||
// Configure to client to use the mock handler.
|
||||
$client = new Client(['handler' => $handler]);
|
||||
|
||||
At its core, handlers are simply PHP callables that accept a request array
|
||||
and return a ``GuzzleHttp\Ring\Future\FutureArrayInterface``. This future array
|
||||
can be used just like a normal PHP array, causing it to block, or you can use
|
||||
the promise interface using the ``then()`` method of the future. Guzzle hooks
|
||||
up to the RingPHP project using a very simple bridge class
|
||||
(``GuzzleHttp\RingBridge``).
|
||||
|
||||
Creating a handler
|
||||
------------------
|
||||
|
||||
See the `RingPHP <http://ringphp.readthedocs.org>`_ project
|
||||
documentation for more information on creating custom handlers that can be
|
||||
used with Guzzle clients.
|
483
core/vendor/guzzlehttp/guzzle/docs/http-messages.rst
vendored
483
core/vendor/guzzlehttp/guzzle/docs/http-messages.rst
vendored
|
@ -1,483 +0,0 @@
|
|||
=============================
|
||||
Request and Response Messages
|
||||
=============================
|
||||
|
||||
Guzzle is an HTTP client that sends HTTP requests to a server and receives HTTP
|
||||
responses. Both requests and responses are referred to as messages.
|
||||
|
||||
Headers
|
||||
=======
|
||||
|
||||
Both request and response messages contain HTTP headers.
|
||||
|
||||
Complex Headers
|
||||
---------------
|
||||
|
||||
Some headers contain additional key value pair information. For example, Link
|
||||
headers contain a link and several key value pairs:
|
||||
|
||||
::
|
||||
|
||||
<http://foo.com>; rel="thing"; type="image/jpeg"
|
||||
|
||||
Guzzle provides a convenience feature that can be used to parse these types of
|
||||
headers:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use GuzzleHttp\Message\Request;
|
||||
|
||||
$request = new Request('GET', '/', [
|
||||
'Link' => '<http:/.../front.jpeg>; rel="front"; type="image/jpeg"'
|
||||
]);
|
||||
|
||||
$parsed = Request::parseHeader($request, 'Link');
|
||||
var_export($parsed);
|
||||
|
||||
Will output:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
array (
|
||||
0 =>
|
||||
array (
|
||||
0 => '<http:/.../front.jpeg>',
|
||||
'rel' => 'front',
|
||||
'type' => 'image/jpeg',
|
||||
),
|
||||
)
|
||||
|
||||
The result contains a hash of key value pairs. Header values that have no key
|
||||
(i.e., the link) are indexed numerically while headers parts that form a key
|
||||
value pair are added as a key value pair.
|
||||
|
||||
See :ref:`headers` for information on how the headers of a request and response
|
||||
can be accessed and modified.
|
||||
|
||||
Body
|
||||
====
|
||||
|
||||
Both request and response messages can contain a body.
|
||||
|
||||
You can check to see if a request or response has a body using the
|
||||
``getBody()`` method:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$response = GuzzleHttp\get('http://httpbin.org/get');
|
||||
if ($response->getBody()) {
|
||||
echo $response->getBody();
|
||||
// JSON string: { ... }
|
||||
}
|
||||
|
||||
The body used in request and response objects is a
|
||||
``GuzzleHttp\Stream\StreamInterface``. This stream is used for both uploading
|
||||
data and downloading data. Guzzle will, by default, store the body of a message
|
||||
in a stream that uses PHP temp streams. When the size of the body exceeds
|
||||
2 MB, the stream will automatically switch to storing data on disk rather than
|
||||
in memory (protecting your application from memory exhaustion).
|
||||
|
||||
You can change the body used in a request or response using the ``setBody()``
|
||||
method:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use GuzzleHttp\Stream\Stream;
|
||||
$request = $client->createRequest('PUT', 'http://httpbin.org/put');
|
||||
$request->setBody(Stream::factory('foo'));
|
||||
|
||||
The easiest way to create a body for a request is using the static
|
||||
``GuzzleHttp\Stream\Stream::factory()`` method. This method accepts various
|
||||
inputs like strings, resources returned from ``fopen()``, and other
|
||||
``GuzzleHttp\Stream\StreamInterface`` objects.
|
||||
|
||||
The body of a request or response can be cast to a string or you can read and
|
||||
write bytes off of the stream as needed.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use GuzzleHttp\Stream\Stream;
|
||||
$request = $client->createRequest('PUT', 'http://httpbin.org/put', ['body' => 'testing...']);
|
||||
|
||||
echo $request->getBody()->read(4);
|
||||
// test
|
||||
echo $request->getBody()->read(4);
|
||||
// ing.
|
||||
echo $request->getBody()->read(1024);
|
||||
// ..
|
||||
var_export($request->eof());
|
||||
// true
|
||||
|
||||
You can find out more about Guzzle stream objects in :doc:`streams`.
|
||||
|
||||
Requests
|
||||
========
|
||||
|
||||
Requests are sent from a client to a server. Requests include the method to
|
||||
be applied to a resource, the identifier of the resource, and the protocol
|
||||
version to use.
|
||||
|
||||
Clients are used to create request messages. More precisely, clients use
|
||||
a ``GuzzleHttp\Message\MessageFactoryInterface`` to create request messages.
|
||||
You create requests with a client using the ``createRequest()`` method.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
// Create a request but don't send it immediately
|
||||
$request = $client->createRequest('GET', 'http://httpbin.org/get');
|
||||
|
||||
Request Methods
|
||||
---------------
|
||||
|
||||
When creating a request, you are expected to provide the HTTP method you wish
|
||||
to perform. You can specify any method you'd like, including a custom method
|
||||
that might not be part of RFC 7231 (like "MOVE").
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
// Create a request using a completely custom HTTP method
|
||||
$request = $client->createRequest('MOVE', 'http://httpbin.org/move', ['exceptions' => false]);
|
||||
|
||||
echo $request->getMethod();
|
||||
// MOVE
|
||||
|
||||
$response = $client->send($request);
|
||||
echo $response->getStatusCode();
|
||||
// 405
|
||||
|
||||
You can create and send a request using methods on a client that map to the
|
||||
HTTP method you wish to use.
|
||||
|
||||
:GET: ``$client->get('http://httpbin.org/get', [/** options **/])``
|
||||
:POST: ``$client->post('http://httpbin.org/post', [/** options **/])``
|
||||
:HEAD: ``$client->head('http://httpbin.org/get', [/** options **/])``
|
||||
:PUT: ``$client->put('http://httpbin.org/put', [/** options **/])``
|
||||
:DELETE: ``$client->delete('http://httpbin.org/delete', [/** options **/])``
|
||||
:OPTIONS: ``$client->options('http://httpbin.org/get', [/** options **/])``
|
||||
:PATCH: ``$client->patch('http://httpbin.org/put', [/** options **/])``
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$response = $client->patch('http://httpbin.org/patch', ['body' => 'content']);
|
||||
|
||||
Request URI
|
||||
-----------
|
||||
|
||||
The resource you are requesting with an HTTP request is identified by the
|
||||
path of the request, the query string, and the "Host" header of the request.
|
||||
|
||||
When creating a request, you can provide the entire resource URI as a URL.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$response = $client->get('http://httbin.org/get?q=foo');
|
||||
|
||||
Using the above code, you will send a request that uses ``httpbin.org`` as
|
||||
the Host header, sends the request over port 80, uses ``/get`` as the path,
|
||||
and sends ``?q=foo`` as the query string. All of this is parsed automatically
|
||||
from the provided URI.
|
||||
|
||||
Sometimes you don't know what the entire request will be when it is created.
|
||||
In these cases, you can modify the request as needed before sending it using
|
||||
the ``createRequest()`` method of the client and methods on the request that
|
||||
allow you to change it.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$request = $client->createRequest('GET', 'http://httbin.org');
|
||||
|
||||
You can change the path of the request using ``setPath()``:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$request->setPath('/get');
|
||||
echo $request->getPath();
|
||||
// /get
|
||||
echo $request->getUrl();
|
||||
// http://httpbin.com/get
|
||||
|
||||
Scheme
|
||||
~~~~~~
|
||||
|
||||
The `scheme <http://tools.ietf.org/html/rfc3986#section-3.1>`_ of a request
|
||||
specifies the protocol to use when sending the request. When using Guzzle, the
|
||||
scheme can be set to "http" or "https".
|
||||
|
||||
You can change the scheme of the request using the ``setScheme()`` method:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$request = $client->createRequest('GET', 'http://httbin.org');
|
||||
$request->setScheme('https');
|
||||
echo $request->getScheme();
|
||||
// https
|
||||
echo $request->getUrl();
|
||||
// https://httpbin.com/get
|
||||
|
||||
Port
|
||||
~~~~
|
||||
|
||||
No port is necessary when using the "http" or "https" schemes, but you can
|
||||
override the port using ``setPort()``. If you need to modify the port used with
|
||||
the specified scheme from the default setting, then you must use the
|
||||
``setPort()`` method.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$request = $client->createRequest('GET', 'http://httbin.org');
|
||||
$request->setPort(8080);
|
||||
echo $request->getPort();
|
||||
// 8080
|
||||
echo $request->getUrl();
|
||||
// https://httpbin.com:8080/get
|
||||
|
||||
// Set the port back to the default value for the scheme
|
||||
$request->setPort(443);
|
||||
echo $request->getUrl();
|
||||
// https://httpbin.com/get
|
||||
|
||||
Query string
|
||||
~~~~~~~~~~~~
|
||||
|
||||
You can get the query string of the request using the ``getQuery()`` method.
|
||||
This method returns a ``GuzzleHttp\Query`` object. A Query object can be
|
||||
accessed like a PHP array, iterated in a foreach statement like a PHP array,
|
||||
and cast to a string.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$request = $client->createRequest('GET', 'http://httbin.org');
|
||||
$query = $request->getQuery();
|
||||
$query['foo'] = 'bar';
|
||||
$query['baz'] = 'bam';
|
||||
$query['bam'] = ['test' => 'abc'];
|
||||
|
||||
echo $request->getQuery();
|
||||
// foo=bar&baz=bam&bam%5Btest%5D=abc
|
||||
|
||||
echo $request->getQuery()['foo'];
|
||||
// bar
|
||||
echo $request->getQuery()->get('foo');
|
||||
// bar
|
||||
echo $request->getQuery()->get('foo');
|
||||
// bar
|
||||
|
||||
var_export($request->getQuery()['bam']);
|
||||
// array('test' => 'abc')
|
||||
|
||||
foreach ($query as $key => $value) {
|
||||
var_export($value);
|
||||
}
|
||||
|
||||
echo $request->getUrl();
|
||||
// https://httpbin.com/get?foo=bar&baz=bam&bam%5Btest%5D=abc
|
||||
|
||||
Query Aggregators
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
Query objects can store scalar values or arrays of values. When an array of
|
||||
values is added to a query object, the query object uses a query aggregator to
|
||||
convert the complex structure into a string. Query objects will use
|
||||
`PHP style query strings <http://www.php.net/http_build_query>`_ when complex
|
||||
query string parameters are converted to a string. You can customize how
|
||||
complex query string parameters are aggregated using the ``setAggregator()``
|
||||
method of a query string object.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$query->setAggregator($query::duplicateAggregator());
|
||||
|
||||
In the above example, we've changed the query object to use the
|
||||
"duplicateAggregator". This aggregator will allow duplicate entries to appear
|
||||
in a query string rather than appending "[n]" to each value. So if you had a
|
||||
query string with ``['a' => ['b', 'c']]``, the duplicate aggregator would
|
||||
convert this to "a=b&a=c" while the default aggregator would convert this to
|
||||
"a[0]=b&a[1]=c" (with urlencoded brackets).
|
||||
|
||||
The ``setAggregator()`` method accepts a ``callable`` which is used to convert
|
||||
a deeply nested array of query string variables into a flattened array of key
|
||||
value pairs. The callable accepts an array of query data and returns a
|
||||
flattened array of key value pairs where each value is an array of strings.
|
||||
You can use the ``GuzzleHttp\Query::walkQuery()`` static function to easily
|
||||
create custom query aggregators.
|
||||
|
||||
Host
|
||||
~~~~
|
||||
|
||||
You can change the host header of the request in a predictable way using the
|
||||
``setHost()`` method of a request:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$request->setHost('www.google.com');
|
||||
echo $request->getHost();
|
||||
// www.google.com
|
||||
echo $request->getUrl();
|
||||
// https://www.google.com/get?foo=bar&baz=bam
|
||||
|
||||
.. note::
|
||||
|
||||
The Host header can also be changed by modifying the Host header of a
|
||||
request directly, but modifying the Host header directly could result in
|
||||
sending a request to a different Host than what is specified in the Host
|
||||
header (sometimes this is actually the desired behavior).
|
||||
|
||||
Resource
|
||||
~~~~~~~~
|
||||
|
||||
You can use the ``getResource()`` method of a request to return the path and
|
||||
query string of a request in a single string.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$request = $client->createRequest('GET', 'http://httpbin.org/get?baz=bar');
|
||||
echo $request->getResource();
|
||||
// /get?baz=bar
|
||||
|
||||
Request Config
|
||||
--------------
|
||||
|
||||
Request messages contain a configuration collection that can be used by
|
||||
event listeners and HTTP handlers to modify how a request behaves or is
|
||||
transferred over the wire. For example, many of the request options that are
|
||||
specified when creating a request are actually set as config options that are
|
||||
only acted upon by handlers and listeners when the request is sent.
|
||||
|
||||
You can get access to the request's config object using the ``getConfig()``
|
||||
method of a request.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$request = $client->createRequest('GET', '/');
|
||||
$config = $request->getConfig();
|
||||
|
||||
The config object is a ``GuzzleHttp\Collection`` object that acts like
|
||||
an associative array. You can grab values from the collection using array like
|
||||
access. You can also modify and remove values using array like access.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$config['foo'] = 'bar';
|
||||
echo $config['foo'];
|
||||
// bar
|
||||
|
||||
var_export(isset($config['foo']));
|
||||
// true
|
||||
|
||||
unset($config['foo']);
|
||||
var_export(isset($config['foo']));
|
||||
// false
|
||||
|
||||
var_export($config['foo']);
|
||||
// NULL
|
||||
|
||||
HTTP handlers and event listeners can expose additional customization options
|
||||
through request config settings. For example, in order to specify custom cURL
|
||||
options to the cURL handler, you need to specify an associative array in the
|
||||
``curl`` ``config`` request option.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$client->get('/', [
|
||||
'config' => [
|
||||
'curl' => [
|
||||
CURLOPT_HTTPAUTH => CURLAUTH_NTLM,
|
||||
CURLOPT_USERPWD => 'username:password'
|
||||
]
|
||||
]
|
||||
]);
|
||||
|
||||
Consult the HTTP handlers and event listeners you are using to see if they
|
||||
allow customization through request configuration options.
|
||||
|
||||
Event Emitter
|
||||
-------------
|
||||
|
||||
Request objects implement ``GuzzleHttp\Event\HasEmitterInterface``, so they
|
||||
have a method called ``getEmitter()`` that can be used to get an event emitter
|
||||
used by the request. Any listener or subscriber attached to a request will only
|
||||
be triggered for the lifecycle events of a specific request. Conversely, adding
|
||||
an event listener or subscriber to a client will listen to all lifecycle events
|
||||
of all requests created by the client.
|
||||
|
||||
See :doc:`events` for more information.
|
||||
|
||||
Responses
|
||||
=========
|
||||
|
||||
Responses are the HTTP messages a client receives from a server after sending
|
||||
an HTTP request message.
|
||||
|
||||
Start-Line
|
||||
----------
|
||||
|
||||
The start-line of a response contains the protocol and protocol version,
|
||||
status code, and reason phrase.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$response = GuzzleHttp\get('http://httpbin.org/get');
|
||||
echo $response->getStatusCode();
|
||||
// 200
|
||||
echo $response->getReasonPhrase();
|
||||
// OK
|
||||
echo $response->getProtocolVersion();
|
||||
// 1.1
|
||||
|
||||
Body
|
||||
----
|
||||
|
||||
As described earlier, you can get the body of a response using the
|
||||
``getBody()`` method.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
if ($body = $response->getBody()) {
|
||||
echo $body;
|
||||
// Cast to a string: { ... }
|
||||
$body->seek(0);
|
||||
// Rewind the body
|
||||
$body->read(1024);
|
||||
// Read bytes of the body
|
||||
}
|
||||
|
||||
When working with JSON responses, you can use the ``json()`` method of a
|
||||
response:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$json = $response->json();
|
||||
|
||||
.. note::
|
||||
|
||||
Guzzle uses the ``json_decode()`` method of PHP and uses arrays rather than
|
||||
``stdClass`` objects for objects.
|
||||
|
||||
You can use the ``xml()`` method when working with XML data.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$xml = $response->xml();
|
||||
|
||||
.. note::
|
||||
|
||||
Guzzle uses the ``SimpleXMLElement`` objects when converting response
|
||||
bodies to XML.
|
||||
|
||||
Effective URL
|
||||
-------------
|
||||
|
||||
The URL that was ultimately accessed that returned a response can be accessed
|
||||
using the ``getEffectiveUrl()`` method of a response. This method will return
|
||||
the URL of a request or the URL of the last redirected URL if any redirects
|
||||
occurred while transferring a request.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$response = GuzzleHttp\get('http://httpbin.org/get');
|
||||
echo $response->getEffectiveUrl();
|
||||
// http://httpbin.org/get
|
||||
|
||||
$response = GuzzleHttp\get('http://httpbin.org/redirect-to?url=http://www.google.com');
|
||||
echo $response->getEffectiveUrl();
|
||||
// http://www.google.com
|
98
core/vendor/guzzlehttp/guzzle/docs/index.rst
vendored
98
core/vendor/guzzlehttp/guzzle/docs/index.rst
vendored
|
@ -1,98 +0,0 @@
|
|||
.. title:: Guzzle | PHP HTTP client and framework for consuming RESTful web services
|
||||
|
||||
======
|
||||
Guzzle
|
||||
======
|
||||
|
||||
Guzzle is a PHP HTTP client that makes it easy to send HTTP requests and
|
||||
trivial to integrate with web services.
|
||||
|
||||
- Manages things like persistent connections, represents query strings as
|
||||
collections, simplifies sending streaming POST requests with fields and
|
||||
files, and abstracts away the underlying HTTP transport layer.
|
||||
- Can send both synchronous and asynchronous requests using the same interface
|
||||
without requiring a dependency on a specific event loop.
|
||||
- Pluggable HTTP handlers allows Guzzle to integrate with any method you choose
|
||||
for sending HTTP requests over the wire (e.g., cURL, sockets, PHP's stream
|
||||
wrapper, non-blocking event loops like `React <http://reactphp.org/>`_, etc.).
|
||||
- Guzzle makes it so that you no longer need to fool around with cURL options,
|
||||
stream contexts, or sockets.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$client = new GuzzleHttp\Client();
|
||||
$response = $client->get('http://guzzlephp.org');
|
||||
$res = $client->get('https://api.github.com/user', ['auth' => ['user', 'pass']]);
|
||||
echo $res->getStatusCode();
|
||||
// "200"
|
||||
echo $res->getHeader('content-type');
|
||||
// 'application/json; charset=utf8'
|
||||
echo $res->getBody();
|
||||
// {"type":"User"...'
|
||||
var_export($res->json());
|
||||
// Outputs the JSON decoded data
|
||||
|
||||
// Send an asynchronous request.
|
||||
$req = $client->createRequest('GET', 'http://httpbin.org', ['future' => true]);
|
||||
$client->send($req)->then(function ($response) {
|
||||
echo 'I completed! ' . $response;
|
||||
});
|
||||
|
||||
User guide
|
||||
----------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
overview
|
||||
quickstart
|
||||
clients
|
||||
http-messages
|
||||
events
|
||||
streams
|
||||
handlers
|
||||
testing
|
||||
faq
|
||||
|
||||
HTTP Components
|
||||
---------------
|
||||
|
||||
There are a number of optional libraries you can use along with Guzzle's HTTP
|
||||
layer to add capabilities to the client.
|
||||
|
||||
`Log Subscriber <https://github.com/guzzle/log-subscriber>`_
|
||||
Logs HTTP requests and responses sent over the wire using customizable
|
||||
log message templates.
|
||||
|
||||
`OAuth Subscriber <https://github.com/guzzle/oauth-subscriber>`_
|
||||
Signs requests using OAuth 1.0.
|
||||
|
||||
`Cache Subscriber <https://github.com/guzzle/cache-subscriber>`_
|
||||
Implements a private transparent proxy cache that caches HTTP responses.
|
||||
|
||||
`Retry Subscriber <https://github.com/guzzle/retry-subscriber>`_
|
||||
Retries failed requests using customizable retry strategies (e.g., retry
|
||||
based on response status code, cURL error codes, etc.)
|
||||
|
||||
`Message Integrity Subscriber <https://github.com/guzzle/message-integrity-subscriber>`_
|
||||
Verifies the message integrity of HTTP responses using customizable
|
||||
validators. This plugin can be used, for example, to verify the Content-MD5
|
||||
headers of responses.
|
||||
|
||||
Service Description Commands
|
||||
----------------------------
|
||||
|
||||
You can use the **Guzzle Command** library to encapsulate interaction with a
|
||||
web service using command objects. Building on top of Guzzle's command
|
||||
abstraction allows you to easily implement things like service description that
|
||||
can be used to serialize requests and parse responses using a meta-description
|
||||
of a web service.
|
||||
|
||||
`Guzzle Command <https://github.com/guzzle/command>`_
|
||||
Provides the foundational elements used to build high-level, command based,
|
||||
web service clients with Guzzle.
|
||||
|
||||
`Guzzle Services <https://github.com/guzzle/guzzle-services>`_
|
||||
Provides an implementation of the *Guzzle Command* library that uses
|
||||
Guzzle service descriptions to describe web services, serialize requests,
|
||||
and parse responses into easy to use model structures.
|
150
core/vendor/guzzlehttp/guzzle/docs/overview.rst
vendored
150
core/vendor/guzzlehttp/guzzle/docs/overview.rst
vendored
|
@ -1,150 +0,0 @@
|
|||
========
|
||||
Overview
|
||||
========
|
||||
|
||||
Requirements
|
||||
============
|
||||
|
||||
#. PHP 5.4.0
|
||||
#. To use the PHP stream handler, ``allow_url_fopen`` must be enabled in your
|
||||
system's php.ini.
|
||||
#. To use the cURL handler, you must have a recent version of cURL >= 7.16.2
|
||||
compiled with OpenSSL and zlib.
|
||||
|
||||
.. note::
|
||||
|
||||
Guzzle no longer requires cURL in order to send HTTP requests. Guzzle will
|
||||
use the PHP stream wrapper to send HTTP requests if cURL is not installed.
|
||||
Alternatively, you can provide your own HTTP handler used to send requests.
|
||||
|
||||
.. _installation:
|
||||
|
||||
Installation
|
||||
============
|
||||
|
||||
The recommended way to install Guzzle is with `Composer <http://getcomposer.org>`_. Composer is a dependency
|
||||
management tool for PHP that allows you to declare the dependencies your project needs and installs them into your
|
||||
project.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
# Install Composer
|
||||
curl -sS https://getcomposer.org/installer | php
|
||||
|
||||
You can add Guzzle as a dependency using the composer.phar CLI:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
php composer.phar require guzzlehttp/guzzle:~5.0
|
||||
|
||||
Alternatively, you can specify Guzzle as a dependency in your project's
|
||||
existing composer.json file:
|
||||
|
||||
.. code-block:: js
|
||||
|
||||
{
|
||||
"require": {
|
||||
"guzzlehttp/guzzle": "~5.0"
|
||||
}
|
||||
}
|
||||
|
||||
After installing, you need to require Composer's autoloader:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
require 'vendor/autoload.php';
|
||||
|
||||
You can find out more on how to install Composer, configure autoloading, and
|
||||
other best-practices for defining dependencies at `getcomposer.org <http://getcomposer.org>`_.
|
||||
|
||||
Bleeding edge
|
||||
-------------
|
||||
|
||||
During your development, you can keep up with the latest changes on the master
|
||||
branch by setting the version requirement for Guzzle to ``~5.0@dev``.
|
||||
|
||||
.. code-block:: js
|
||||
|
||||
{
|
||||
"require": {
|
||||
"guzzlehttp/guzzle": "~5.0@dev"
|
||||
}
|
||||
}
|
||||
|
||||
License
|
||||
=======
|
||||
|
||||
Licensed using the `MIT license <http://opensource.org/licenses/MIT>`_.
|
||||
|
||||
Copyright (c) 2014 Michael Dowling <https://github.com/mtdowling>
|
||||
|
||||
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.
|
||||
|
||||
Contributing
|
||||
============
|
||||
|
||||
Guidelines
|
||||
----------
|
||||
|
||||
1. Guzzle follows PSR-0, PSR-1, and PSR-2.
|
||||
2. Guzzle is meant to be lean and fast with very few dependencies.
|
||||
3. Guzzle has a minimum PHP version requirement of PHP 5.4. Pull requests must
|
||||
not require a PHP version greater than PHP 5.4.
|
||||
4. All pull requests must include unit tests to ensure the change works as
|
||||
expected and to prevent regressions.
|
||||
|
||||
Running the tests
|
||||
-----------------
|
||||
|
||||
In order to contribute, you'll need to checkout the source from GitHub and
|
||||
install Guzzle's dependencies using Composer:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
git clone https://github.com/guzzle/guzzle.git
|
||||
cd guzzle && curl -s http://getcomposer.org/installer | php && ./composer.phar install --dev
|
||||
|
||||
Guzzle is unit tested with PHPUnit. Run the tests using the vendored PHPUnit
|
||||
binary:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
vendor/bin/phpunit
|
||||
|
||||
.. note::
|
||||
|
||||
You'll need to install node.js v0.5.0 or newer in order to perform
|
||||
integration tests on Guzzle's HTTP handlers.
|
||||
|
||||
Reporting a security vulnerability
|
||||
==================================
|
||||
|
||||
We want to ensure that Guzzle is a secure HTTP client library for everyone. If
|
||||
you've discovered a security vulnerability in Guzzle, we appreciate your help
|
||||
in disclosing it to us in a `responsible manner <http://en.wikipedia.org/wiki/Responsible_disclosure>`_.
|
||||
|
||||
Publicly disclosing a vulnerability can put the entire community at risk. If
|
||||
you've discovered a security concern, please email us at
|
||||
security@guzzlephp.org. We'll work with you to make sure that we understand the
|
||||
scope of the issue, and that we fully address your concern. We consider
|
||||
correspondence sent to security@guzzlephp.org our highest priority, and work to
|
||||
address any issues that arise as quickly as possible.
|
||||
|
||||
After a security vulnerability has been corrected, a security hotfix release will
|
||||
be deployed as soon as possible.
|
448
core/vendor/guzzlehttp/guzzle/docs/quickstart.rst
vendored
448
core/vendor/guzzlehttp/guzzle/docs/quickstart.rst
vendored
|
@ -1,448 +0,0 @@
|
|||
==========
|
||||
Quickstart
|
||||
==========
|
||||
|
||||
This page provides a quick introduction to Guzzle and introductory examples.
|
||||
If you have not already installed, Guzzle, head over to the :ref:`installation`
|
||||
page.
|
||||
|
||||
Make a Request
|
||||
==============
|
||||
|
||||
You can send requests with Guzzle using a ``GuzzleHttp\ClientInterface``
|
||||
object.
|
||||
|
||||
Creating a Client
|
||||
-----------------
|
||||
|
||||
The procedural API is simple but not very testable; it's best left for quick
|
||||
prototyping. If you want to use Guzzle in a more flexible and testable way,
|
||||
then you'll need to use a ``GuzzleHttp\ClientInterface`` object.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use GuzzleHttp\Client;
|
||||
|
||||
$client = new Client();
|
||||
$response = $client->get('http://httpbin.org/get');
|
||||
|
||||
// You can use the same methods you saw in the procedural API
|
||||
$response = $client->delete('http://httpbin.org/delete');
|
||||
$response = $client->head('http://httpbin.org/get');
|
||||
$response = $client->options('http://httpbin.org/get');
|
||||
$response = $client->patch('http://httpbin.org/patch');
|
||||
$response = $client->post('http://httpbin.org/post');
|
||||
$response = $client->put('http://httpbin.org/put');
|
||||
|
||||
You can create a request with a client and then send the request with the
|
||||
client when you're ready.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$request = $client->createRequest('GET', 'http://www.foo.com');
|
||||
$response = $client->send($request);
|
||||
|
||||
Client objects provide a great deal of flexibility in how request are
|
||||
transferred including default request options, subscribers that are attached
|
||||
to each request, and a base URL that allows you to send requests with relative
|
||||
URLs. You can find out all about clients in the :doc:`clients` page of the
|
||||
documentation.
|
||||
|
||||
Using Responses
|
||||
===============
|
||||
|
||||
In the previous examples, we retrieved a ``$response`` variable. This value is
|
||||
actually a ``GuzzleHttp\Message\ResponseInterface`` object and contains lots
|
||||
of helpful information.
|
||||
|
||||
You can get the status code and reason phrase of the response.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$code = $response->getStatusCode();
|
||||
// 200
|
||||
|
||||
$reason = $response->getReasonPhrase();
|
||||
// OK
|
||||
|
||||
By providing the ``future`` request option to a request, you can send requests
|
||||
asynchronously using the promise interface of a future response.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$client->get('http://httpbin.org', ['future' => true])
|
||||
->then(function ($response) {
|
||||
echo $response->getStatusCode();
|
||||
});
|
||||
|
||||
Response Body
|
||||
-------------
|
||||
|
||||
The body of a response can be retrieved and cast to a string.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$body = $response->getBody();
|
||||
echo $body;
|
||||
// { "some_json_data" ...}
|
||||
|
||||
You can also read read bytes from body of a response like a stream.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$body = $response->getBody();
|
||||
|
||||
while (!$body->eof()) {
|
||||
echo $body->read(1024);
|
||||
}
|
||||
|
||||
JSON Responses
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
You can more easily work with JSON responses using the ``json()`` method of a
|
||||
response.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$response = $client->get('http://httpbin.org/get');
|
||||
$json = $response->json();
|
||||
var_dump($json[0]['origin']);
|
||||
|
||||
Guzzle internally uses PHP's ``json_decode()`` function to parse responses. If
|
||||
Guzzle is unable to parse the JSON response body, then a
|
||||
``GuzzleHttp\Exception\ParseException`` is thrown.
|
||||
|
||||
XML Responses
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
You can use a response's ``xml()`` method to more easily work with responses
|
||||
that contain XML data.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$response = $client->get('https://github.com/mtdowling.atom');
|
||||
$xml = $response->xml();
|
||||
echo $xml->id;
|
||||
// tag:github.com,2008:/mtdowling
|
||||
|
||||
Guzzle internally uses a ``SimpleXMLElement`` object to parse responses. If
|
||||
Guzzle is unable to parse the XML response body, then a
|
||||
``GuzzleHttp\Exception\ParseException`` is thrown.
|
||||
|
||||
Query String Parameters
|
||||
=======================
|
||||
|
||||
Sending query string parameters with a request is easy. You can set query
|
||||
string parameters in the request's URL.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$response = $client->get('http://httpbin.org?foo=bar');
|
||||
|
||||
You can also specify the query string parameters using the ``query`` request
|
||||
option.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$client->get('http://httpbin.org', [
|
||||
'query' => ['foo' => 'bar']
|
||||
]);
|
||||
|
||||
And finally, you can build up the query string of a request as needed by
|
||||
calling the ``getQuery()`` method of a request and modifying the request's
|
||||
``GuzzleHttp\Query`` object as needed.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$request = $client->createRequest('GET', 'http://httpbin.org');
|
||||
$query = $request->getQuery();
|
||||
$query->set('foo', 'bar');
|
||||
|
||||
// You can use the query string object like an array
|
||||
$query['baz'] = 'bam';
|
||||
|
||||
// The query object can be cast to a string
|
||||
echo $query;
|
||||
// foo=bar&baz=bam
|
||||
|
||||
// Setting a value to false or null will cause the "=" sign to be omitted
|
||||
$query['empty'] = null;
|
||||
echo $query;
|
||||
// foo=bar&baz=bam&empty
|
||||
|
||||
// Use an empty string to include the "=" sign with an empty value
|
||||
$query['empty'] = '';
|
||||
echo $query;
|
||||
// foo=bar&baz=bam&empty=
|
||||
|
||||
.. _headers:
|
||||
|
||||
Request and Response Headers
|
||||
----------------------------
|
||||
|
||||
You can specify request headers when sending or creating requests with a
|
||||
client. In the following example, we send the ``X-Foo-Header`` with a value of
|
||||
``value`` by setting the ``headers`` request option.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$response = $client->get('http://httpbin.org/get', [
|
||||
'headers' => ['X-Foo-Header' => 'value']
|
||||
]);
|
||||
|
||||
You can view the headers of a response using header specific methods of a
|
||||
response class. Headers work exactly the same way for request and response
|
||||
object.
|
||||
|
||||
You can retrieve a header from a request or response using the ``getHeader()``
|
||||
method of the object. This method is case-insensitive and by default will
|
||||
return a string containing the header field value.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$response = $client->get('http://www.yahoo.com');
|
||||
$length = $response->getHeader('Content-Length');
|
||||
|
||||
Header fields that contain multiple values can be retrieved as a string or as
|
||||
an array. Retrieving the field values as a string will naively concatenate all
|
||||
of the header values together with a comma. Because not all header fields
|
||||
should be represented this way (e.g., ``Set-Cookie``), you can pass an optional
|
||||
flag to the ``getHeader()`` method to retrieve the header values as an array.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$values = $response->getHeader('Set-Cookie', true);
|
||||
foreach ($values as $value) {
|
||||
echo $value;
|
||||
}
|
||||
|
||||
You can test if a request or response has a specific header using the
|
||||
``hasHeader()`` method. This method accepts a case-insensitive string and
|
||||
returns true if the header is present or false if it is not.
|
||||
|
||||
You can retrieve all of the headers of a message using the ``getHeaders()``
|
||||
method of a request or response. The return value is an associative array where
|
||||
the keys represent the header name as it will be sent over the wire, and each
|
||||
value is an array of strings associated with the header.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$headers = $response->getHeaders();
|
||||
foreach ($message->getHeaders() as $name => $values) {
|
||||
echo $name . ": " . implode(", ", $values);
|
||||
}
|
||||
|
||||
Modifying headers
|
||||
-----------------
|
||||
|
||||
The headers of a message can be modified using the ``setHeader()``,
|
||||
``addHeader()``, ``setHeaders()``, and ``removeHeader()`` methods of a request
|
||||
or response object.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$request = $client->createRequest('GET', 'http://httpbin.org/get');
|
||||
|
||||
// Set a single value for a header
|
||||
$request->setHeader('User-Agent', 'Testing!');
|
||||
|
||||
// Set multiple values for a header in one call
|
||||
$request->setHeader('X-Foo', ['Baz', 'Bar']);
|
||||
|
||||
// Add a header to the message
|
||||
$request->addHeader('X-Foo', 'Bam');
|
||||
|
||||
echo $request->getHeader('X-Foo');
|
||||
// Baz, Bar, Bam
|
||||
|
||||
// Remove a specific header using a case-insensitive name
|
||||
$request->removeHeader('x-foo');
|
||||
echo $request->getHeader('X-Foo');
|
||||
// Echoes an empty string: ''
|
||||
|
||||
Uploading Data
|
||||
==============
|
||||
|
||||
Guzzle provides several methods of uploading data.
|
||||
|
||||
You can send requests that contain a stream of data by passing a string,
|
||||
resource returned from ``fopen``, or a ``GuzzleHttp\Stream\StreamInterface``
|
||||
object to the ``body`` request option.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$r = $client->post('http://httpbin.org/post', ['body' => 'raw data']);
|
||||
|
||||
You can easily upload JSON data using the ``json`` request option.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$r = $client->put('http://httpbin.org/put', ['json' => ['foo' => 'bar']]);
|
||||
|
||||
POST Requests
|
||||
-------------
|
||||
|
||||
In addition to specifying the raw data of a request using the ``body`` request
|
||||
option, Guzzle provides helpful abstractions over sending POST data.
|
||||
|
||||
Sending POST Fields
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Sending ``application/x-www-form-urlencoded`` POST requests requires that you
|
||||
specify the body of a POST request as an array.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$response = $client->post('http://httpbin.org/post', [
|
||||
'body' => [
|
||||
'field_name' => 'abc',
|
||||
'other_field' => '123'
|
||||
]
|
||||
]);
|
||||
|
||||
You can also build up POST requests before sending them.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$request = $client->createRequest('POST', 'http://httpbin.org/post');
|
||||
$postBody = $request->getBody();
|
||||
|
||||
// $postBody is an instance of GuzzleHttp\Post\PostBodyInterface
|
||||
$postBody->setField('foo', 'bar');
|
||||
echo $postBody->getField('foo');
|
||||
// 'bar'
|
||||
|
||||
echo json_encode($postBody->getFields());
|
||||
// {"foo": "bar"}
|
||||
|
||||
// Send the POST request
|
||||
$response = $client->send($request);
|
||||
|
||||
Sending POST Files
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Sending ``multipart/form-data`` POST requests (POST requests that contain
|
||||
files) is the same as sending ``application/x-www-form-urlencoded``, except
|
||||
some of the array values of the POST fields map to PHP ``fopen`` resources, or
|
||||
``GuzzleHttp\Stream\StreamInterface``, or
|
||||
``GuzzleHttp\Post\PostFileInterface`` objects.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use GuzzleHttp\Post\PostFile;
|
||||
|
||||
$response = $client->post('http://httpbin.org/post', [
|
||||
'body' => [
|
||||
'field_name' => 'abc',
|
||||
'file_filed' => fopen('/path/to/file', 'r'),
|
||||
'other_file' => new PostFile('other_file', 'this is the content')
|
||||
]
|
||||
]);
|
||||
|
||||
Just like when sending POST fields, you can also build up POST requests with
|
||||
files before sending them.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use GuzzleHttp\Post\PostFile;
|
||||
|
||||
$request = $client->createRequest('POST', 'http://httpbin.org/post');
|
||||
$postBody = $request->getBody();
|
||||
$postBody->setField('foo', 'bar');
|
||||
$postBody->addFile(new PostFile('test', fopen('/path/to/file', 'r')));
|
||||
$response = $client->send($request);
|
||||
|
||||
Cookies
|
||||
=======
|
||||
|
||||
Guzzle can maintain a cookie session for you if instructed using the
|
||||
``cookies`` request option.
|
||||
|
||||
- Set to ``true`` to use a shared cookie session associated with the client.
|
||||
- Pass an associative array containing cookies to send in the request and start
|
||||
a new cookie session.
|
||||
- Set to a ``GuzzleHttp\Subscriber\CookieJar\CookieJarInterface`` object to use
|
||||
an existing cookie jar.
|
||||
|
||||
Redirects
|
||||
=========
|
||||
|
||||
Guzzle will automatically follow redirects unless you tell it not to. You can
|
||||
customize the redirect behavior using the ``allow_redirects`` request option.
|
||||
|
||||
- Set to true to enable normal redirects with a maximum number of 5 redirects.
|
||||
This is the default setting.
|
||||
- Set to false to disable redirects.
|
||||
- Pass an associative array containing the 'max' key to specify the maximum
|
||||
number of redirects and optionally provide a 'strict' key value to specify
|
||||
whether or not to use strict RFC compliant redirects (meaning redirect POST
|
||||
requests with POST requests vs. doing what most browsers do which is
|
||||
redirect POST requests with GET requests).
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$response = $client->get('http://github.com');
|
||||
echo $response->getStatusCode();
|
||||
// 200
|
||||
echo $response->getEffectiveUrl();
|
||||
// 'https://github.com/'
|
||||
|
||||
The following example shows that redirects can be disabled.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$response = $client->get('http://github.com', ['allow_redirects' => false]);
|
||||
echo $response->getStatusCode();
|
||||
// 301
|
||||
echo $response->getEffectiveUrl();
|
||||
// 'http://github.com/'
|
||||
|
||||
Exceptions
|
||||
==========
|
||||
|
||||
Guzzle throws exceptions for errors that occur during a transfer.
|
||||
|
||||
- In the event of a networking error (connection timeout, DNS errors, etc.),
|
||||
a ``GuzzleHttp\Exception\RequestException`` is thrown. This exception
|
||||
extends from ``GuzzleHttp\Exception\TransferException``. Catching this
|
||||
exception will catch any exception that can be thrown while transferring
|
||||
(non-parallel) requests.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use GuzzleHttp\Exception\RequestException;
|
||||
|
||||
try {
|
||||
$client->get('https://github.com/_abc_123_404');
|
||||
} catch (RequestException $e) {
|
||||
echo $e->getRequest();
|
||||
if ($e->hasResponse()) {
|
||||
echo $e->getResponse();
|
||||
}
|
||||
}
|
||||
|
||||
- A ``GuzzleHttp\Exception\ClientException`` is thrown for 400
|
||||
level errors if the ``exceptions`` request option is set to true. This
|
||||
exception extends from ``GuzzleHttp\Exception\BadResponseException`` and
|
||||
``GuzzleHttp\Exception\BadResponseException`` extends from
|
||||
``GuzzleHttp\Exception\RequestException``.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use GuzzleHttp\Exception\ClientException;
|
||||
|
||||
try {
|
||||
$client->get('https://github.com/_abc_123_404');
|
||||
} catch (ClientException $e) {
|
||||
echo $e->getRequest();
|
||||
echo $e->getResponse();
|
||||
}
|
||||
|
||||
- A ``GuzzleHttp\Exception\ServerException`` is thrown for 500 level
|
||||
errors if the ``exceptions`` request option is set to true. This
|
||||
exception extends from ``GuzzleHttp\Exception\BadResponseException``.
|
||||
- A ``GuzzleHttp\Exception\TooManyRedirectsException`` is thrown when too
|
||||
many redirects are followed. This exception extends from ``GuzzleHttp\Exception\RequestException``.
|
||||
|
||||
All of the above exceptions extend from
|
||||
``GuzzleHttp\Exception\TransferException``.
|
|
@ -1,2 +0,0 @@
|
|||
Sphinx>=1.2b1
|
||||
guzzle_sphinx_theme>=0.6.0
|
213
core/vendor/guzzlehttp/guzzle/docs/streams.rst
vendored
213
core/vendor/guzzlehttp/guzzle/docs/streams.rst
vendored
|
@ -1,213 +0,0 @@
|
|||
=======
|
||||
Streams
|
||||
=======
|
||||
|
||||
Guzzle uses stream objects to represent request and response message bodies.
|
||||
These stream objects allow you to work with various types of data all using a
|
||||
common interface.
|
||||
|
||||
HTTP messages consist of a start-line, headers, and a body. The body of an HTTP
|
||||
message can be very small or extremely large. Attempting to represent the body
|
||||
of a message as a string can easily consume more memory than intended because
|
||||
the body must be stored completely in memory. Attempting to store the body of a
|
||||
request or response in memory would preclude the use of that implementation from
|
||||
being able to work with large message bodies. The StreamInterface is used in
|
||||
order to hide the implementation details of where a stream of data is read from
|
||||
or written to.
|
||||
|
||||
Guzzle's StreamInterface exposes several methods that enable streams to be read
|
||||
from, written to, and traversed effectively.
|
||||
|
||||
Streams expose their capabilities using three methods: ``isReadable()``,
|
||||
``isWritable()``, and ``isSeekable()``. These methods can be used by stream
|
||||
collaborators to determine if a stream is capable of their requirements.
|
||||
|
||||
Each stream instance has various capabilities: they can be read-only,
|
||||
write-only, read-write, allow arbitrary random access (seeking forwards or
|
||||
backwards to any location), or only allow sequential access (for example in the
|
||||
case of a socket or pipe).
|
||||
|
||||
Creating Streams
|
||||
================
|
||||
|
||||
The best way to create a stream is using the static factory method,
|
||||
``GuzzleHttp\Stream\Stream::factory()``. This factory accepts strings,
|
||||
resources returned from ``fopen()``, an object that implements
|
||||
``__toString()``, and an object that implements
|
||||
``GuzzleHttp\Stream\StreamInterface``.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use GuzzleHttp\Stream\Stream;
|
||||
|
||||
$stream = Stream::factory('string data');
|
||||
echo $stream;
|
||||
// string data
|
||||
echo $stream->read(3);
|
||||
// str
|
||||
echo $stream->getContents();
|
||||
// ing data
|
||||
var_export($stream->eof());
|
||||
// true
|
||||
var_export($stream->tell());
|
||||
// 11
|
||||
|
||||
Metadata
|
||||
========
|
||||
|
||||
Guzzle streams expose stream metadata through the ``getMetadata()`` method.
|
||||
This method provides the data you would retrieve when calling PHP's
|
||||
`stream_get_meta_data() function <http://php.net/manual/en/function.stream-get-meta-data.php>`_,
|
||||
and can optionally expose other custom data.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use GuzzleHttp\Stream\Stream;
|
||||
|
||||
$resource = fopen('/path/to/file', 'r');
|
||||
$stream = Stream::factory($resource);
|
||||
echo $stream->getMetadata('uri');
|
||||
// /path/to/file
|
||||
var_export($stream->isReadable());
|
||||
// true
|
||||
var_export($stream->isWritable());
|
||||
// false
|
||||
var_export($stream->isSeekable());
|
||||
// true
|
||||
|
||||
Stream Decorators
|
||||
=================
|
||||
|
||||
With the small and focused interface, add custom functionality to streams is
|
||||
very simple with stream decorators. Guzzle provides several built-in decorators
|
||||
that provide additional stream functionality.
|
||||
|
||||
CachingStream
|
||||
-------------
|
||||
|
||||
The CachingStream is used to allow seeking over previously read bytes on
|
||||
non-seekable streams. This can be useful when transferring a non-seekable
|
||||
entity body fails due to needing to rewind the stream (for example, resulting
|
||||
from a redirect). Data that is read from the remote stream will be buffered in
|
||||
a PHP temp stream so that previously read bytes are cached first in memory,
|
||||
then on disk.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use GuzzleHttp\Stream\Stream;
|
||||
use GuzzleHttp\Stream\CachingStream;
|
||||
|
||||
$original = Stream::factory(fopen('http://www.google.com', 'r'));
|
||||
$stream = new CachingStream($original);
|
||||
|
||||
$stream->read(1024);
|
||||
echo $stream->tell();
|
||||
// 1024
|
||||
|
||||
$stream->seek(0);
|
||||
echo $stream->tell();
|
||||
// 0
|
||||
|
||||
LimitStream
|
||||
-----------
|
||||
|
||||
LimitStream can be used to read a subset or slice of an existing stream object.
|
||||
This can be useful for breaking a large file into smaller pieces to be sent in
|
||||
chunks (e.g. Amazon S3's multipart upload API).
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use GuzzleHttp\Stream\Stream;
|
||||
use GuzzleHttp\Stream\LimitStream;
|
||||
|
||||
$original = Stream::factory(fopen('/tmp/test.txt', 'r+'));
|
||||
echo $original->getSize();
|
||||
// >>> 1048576
|
||||
|
||||
// Limit the size of the body to 1024 bytes and start reading from byte 2048
|
||||
$stream = new LimitStream($original, 1024, 2048);
|
||||
echo $stream->getSize();
|
||||
// >>> 1024
|
||||
echo $stream->tell();
|
||||
// >>> 0
|
||||
|
||||
NoSeekStream
|
||||
------------
|
||||
|
||||
NoSeekStream wraps a stream and does not allow seeking.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use GuzzleHttp\Stream\Stream;
|
||||
use GuzzleHttp\Stream\LimitStream;
|
||||
|
||||
$original = Stream::factory('foo');
|
||||
$noSeek = new NoSeekStream($original);
|
||||
|
||||
echo $noSeek->read(3);
|
||||
// foo
|
||||
var_export($noSeek->isSeekable());
|
||||
// false
|
||||
$noSeek->seek(0);
|
||||
var_export($noSeek->read(3));
|
||||
// NULL
|
||||
|
||||
Creating Custom Decorators
|
||||
--------------------------
|
||||
|
||||
Creating a stream decorator is very easy thanks to the
|
||||
``GuzzleHttp\Stream\StreamDecoratorTrait``. This trait provides methods that
|
||||
implement ``GuzzleHttp\Stream\StreamInterface`` by proxying to an underlying
|
||||
stream. Just ``use`` the ``StreamDecoratorTrait`` and implement your custom
|
||||
methods.
|
||||
|
||||
For example, let's say we wanted to call a specific function each time the last
|
||||
byte is read from a stream. This could be implemented by overriding the
|
||||
``read()`` method.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use GuzzleHttp\Stream\StreamDecoratorTrait;
|
||||
|
||||
class EofCallbackStream implements StreamInterface
|
||||
{
|
||||
use StreamDecoratorTrait;
|
||||
|
||||
private $callback;
|
||||
|
||||
public function __construct(StreamInterface $stream, callable $callback)
|
||||
{
|
||||
$this->stream = $stream;
|
||||
$this->callback = $callback;
|
||||
}
|
||||
|
||||
public function read($length)
|
||||
{
|
||||
$result = $this->stream->read($length);
|
||||
|
||||
// Invoke the callback when EOF is hit.
|
||||
if ($this->eof()) {
|
||||
call_user_func($this->callback);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
This decorator could be added to any existing stream and used like so:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use GuzzleHttp\Stream\Stream;
|
||||
|
||||
$original = Stream::factory('foo');
|
||||
$eofStream = new EofCallbackStream($original, function () {
|
||||
echo 'EOF!';
|
||||
});
|
||||
|
||||
$eofStream->read(2);
|
||||
$eofStream->read(1);
|
||||
// echoes "EOF!"
|
||||
$eofStream->seek(0);
|
||||
$eofStream->read(3);
|
||||
// echoes "EOF!"
|
232
core/vendor/guzzlehttp/guzzle/docs/testing.rst
vendored
232
core/vendor/guzzlehttp/guzzle/docs/testing.rst
vendored
|
@ -1,232 +0,0 @@
|
|||
======================
|
||||
Testing Guzzle Clients
|
||||
======================
|
||||
|
||||
Guzzle provides several tools that will enable you to easily mock the HTTP
|
||||
layer without needing to send requests over the internet.
|
||||
|
||||
* Mock subscriber
|
||||
* Mock handler
|
||||
* Node.js web server for integration testing
|
||||
|
||||
Mock Subscriber
|
||||
===============
|
||||
|
||||
When testing HTTP clients, you often need to simulate specific scenarios like
|
||||
returning a successful response, returning an error, or returning specific
|
||||
responses in a certain order. Because unit tests need to be predictable, easy
|
||||
to bootstrap, and fast, hitting an actual remote API is a test smell.
|
||||
|
||||
Guzzle provides a mock subscriber that can be attached to clients or requests
|
||||
that allows you to queue up a list of responses to use rather than hitting a
|
||||
remote API.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Subscriber\Mock;
|
||||
use GuzzleHttp\Message\Response;
|
||||
|
||||
$client = new Client();
|
||||
|
||||
// Create a mock subscriber and queue two responses.
|
||||
$mock = new Mock([
|
||||
new Response(200, ['X-Foo' => 'Bar']), // Use response object
|
||||
"HTTP/1.1 202 OK\r\nContent-Length: 0\r\n\r\n" // Use a response string
|
||||
]);
|
||||
|
||||
// Add the mock subscriber to the client.
|
||||
$client->getEmitter()->attach($mock);
|
||||
// The first request is intercepted with the first response.
|
||||
echo $client->get('/')->getStatusCode();
|
||||
//> 200
|
||||
// The second request is intercepted with the second response.
|
||||
echo $client->get('/')->getStatusCode();
|
||||
//> 202
|
||||
|
||||
When no more responses are in the queue and a request is sent, an
|
||||
``OutOfBoundsException`` is thrown.
|
||||
|
||||
History Subscriber
|
||||
==================
|
||||
|
||||
When using things like the ``Mock`` subscriber, you often need to know if the
|
||||
requests you expected to send were sent exactly as you intended. While the mock
|
||||
subscriber responds with mocked responses, the ``GuzzleHttp\Subscriber\History``
|
||||
subscriber maintains a history of the requests that were sent by a client.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Subscriber\History;
|
||||
|
||||
$client = new Client();
|
||||
$history = new History();
|
||||
|
||||
// Add the history subscriber to the client.
|
||||
$client->getEmitter()->attach($history);
|
||||
|
||||
$client->get('http://httpbin.org/get');
|
||||
$client->head('http://httpbin.org/get');
|
||||
|
||||
// Count the number of transactions
|
||||
echo count($history);
|
||||
//> 2
|
||||
// Get the last request
|
||||
$lastRequest = $history->getLastRequest();
|
||||
// Get the last response
|
||||
$lastRequest = $history->getLastResponse();
|
||||
|
||||
// Iterate over the transactions that were sent
|
||||
foreach ($history as $transaction) {
|
||||
echo $transaction['request']->getMethod();
|
||||
//> GET, HEAD
|
||||
echo $transaction['response']->getStatusCode();
|
||||
//> 200, 200
|
||||
}
|
||||
|
||||
The history subscriber can also be printed, revealing the requests and
|
||||
responses that were sent as a string, in order.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
echo $history;
|
||||
|
||||
::
|
||||
|
||||
> GET /get HTTP/1.1
|
||||
Host: httpbin.org
|
||||
User-Agent: Guzzle/4.0-dev curl/7.21.4 PHP/5.5.8
|
||||
|
||||
< HTTP/1.1 200 OK
|
||||
Access-Control-Allow-Origin: *
|
||||
Content-Type: application/json
|
||||
Date: Tue, 25 Mar 2014 03:53:27 GMT
|
||||
Server: gunicorn/0.17.4
|
||||
Content-Length: 270
|
||||
Connection: keep-alive
|
||||
|
||||
{
|
||||
"headers": {
|
||||
"Connection": "close",
|
||||
"X-Request-Id": "3d0f7d5c-c937-4394-8248-2b8e03fcccdb",
|
||||
"User-Agent": "Guzzle/4.0-dev curl/7.21.4 PHP/5.5.8",
|
||||
"Host": "httpbin.org"
|
||||
},
|
||||
"origin": "76.104.247.1",
|
||||
"args": {},
|
||||
"url": "http://httpbin.org/get"
|
||||
}
|
||||
|
||||
> HEAD /get HTTP/1.1
|
||||
Host: httpbin.org
|
||||
User-Agent: Guzzle/4.0-dev curl/7.21.4 PHP/5.5.8
|
||||
|
||||
< HTTP/1.1 200 OK
|
||||
Access-Control-Allow-Origin: *
|
||||
Content-length: 270
|
||||
Content-Type: application/json
|
||||
Date: Tue, 25 Mar 2014 03:53:27 GMT
|
||||
Server: gunicorn/0.17.4
|
||||
Connection: keep-alive
|
||||
|
||||
Mock Adapter
|
||||
============
|
||||
|
||||
In addition to using the Mock subscriber, you can use the
|
||||
``GuzzleHttp\Ring\Client\MockAdapter`` as the handler of a client to return the
|
||||
same response over and over or return the result of a callable function.
|
||||
|
||||
Test Web Server
|
||||
===============
|
||||
|
||||
Using mock responses is almost always enough when testing a web service client.
|
||||
When implementing custom :doc:`HTTP handlers <handlers>`, you'll need to send
|
||||
actual HTTP requests in order to sufficiently test the handler. However, a
|
||||
best practice is to contact a local web server rather than a server over the
|
||||
internet.
|
||||
|
||||
- Tests are more reliable
|
||||
- Tests do not require a network connection
|
||||
- Tests have no external dependencies
|
||||
|
||||
Using the test server
|
||||
---------------------
|
||||
|
||||
.. warning::
|
||||
|
||||
The following functionality is provided to help developers of Guzzle
|
||||
develop HTTP handlers. There is no promise of backwards compatibility
|
||||
when it comes to the node.js test server or the ``GuzzleHttp\Tests\Server``
|
||||
class. If you are using the test server or ``Server`` class outside of
|
||||
guzzlehttp/guzzle, then you will need to configure autoloading and
|
||||
ensure the web server is started manually.
|
||||
|
||||
.. hint::
|
||||
|
||||
You almost never need to use this test web server. You should only ever
|
||||
consider using it when developing HTTP handlers. The test web server
|
||||
is not necessary for mocking requests. For that, please use the
|
||||
Mock subcribers and History subscriber.
|
||||
|
||||
Guzzle ships with a node.js test server that receives requests and returns
|
||||
responses from a queue. The test server exposes a simple API that is used to
|
||||
enqueue responses and inspect the requests that it has received.
|
||||
|
||||
Any operation on the ``Server`` object will ensure that
|
||||
the server is running and wait until it is able to receive requests before
|
||||
returning.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Tests\Server;
|
||||
|
||||
// Start the server and queue a response
|
||||
Server::enqueue("HTTP/1.1 200 OK\r\n\Content-Length: 0r\n\r\n");
|
||||
|
||||
$client = new Client(['base_url' => Server::$url]);
|
||||
echo $client->get('/foo')->getStatusCode();
|
||||
// 200
|
||||
|
||||
``GuzzleHttp\Tests\Server`` provides a static interface to the test server. You
|
||||
can queue an HTTP response or an array of responses by calling
|
||||
``Server::enqueue()``. This method accepts a string representing an HTTP
|
||||
response message, a ``GuzzleHttp\Message\ResponseInterface``, or an array of
|
||||
HTTP message strings / ``GuzzleHttp\Message\ResponseInterface`` objects.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
// Queue single response
|
||||
Server::enqueue("HTTP/1.1 200 OK\r\n\Content-Length: 0r\n\r\n");
|
||||
|
||||
// Clear the queue and queue an array of responses
|
||||
Server::enqueue([
|
||||
"HTTP/1.1 200 OK\r\n\Content-Length: 0r\n\r\n",
|
||||
"HTTP/1.1 404 Not Found\r\n\Content-Length: 0r\n\r\n"
|
||||
]);
|
||||
|
||||
When a response is queued on the test server, the test server will remove any
|
||||
previously queued responses. As the server receives requests, queued responses
|
||||
are dequeued and returned to the request. When the queue is empty, the server
|
||||
will return a 500 response.
|
||||
|
||||
You can inspect the requests that the server has retrieved by calling
|
||||
``Server::received()``. This method accepts an optional ``$hydrate`` parameter
|
||||
that specifies if you are retrieving an array of HTTP requests as strings or an
|
||||
array of ``GuzzleHttp\Message\RequestInterface`` objects.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
foreach (Server::received() as $response) {
|
||||
echo $response;
|
||||
}
|
||||
|
||||
You can clear the list of received requests from the web server using the
|
||||
``Server::flush()`` method.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
Server::flush();
|
||||
echo count(Server::received());
|
||||
// 0
|
148
core/vendor/guzzlehttp/guzzle/src/BatchResults.php
vendored
148
core/vendor/guzzlehttp/guzzle/src/BatchResults.php
vendored
|
@ -1,148 +0,0 @@
|
|||
<?php
|
||||
namespace GuzzleHttp;
|
||||
|
||||
/**
|
||||
* Represents the result of a batch operation. This result container is
|
||||
* iterable, countable, and you can can get a result by value using the
|
||||
* getResult function.
|
||||
*
|
||||
* Successful results are anything other than exceptions. Failure results are
|
||||
* exceptions.
|
||||
*
|
||||
* @package GuzzleHttp
|
||||
*/
|
||||
class BatchResults implements \Countable, \IteratorAggregate, \ArrayAccess
|
||||
{
|
||||
private $hash;
|
||||
|
||||
/**
|
||||
* @param \SplObjectStorage $hash Hash of key objects to result values.
|
||||
*/
|
||||
public function __construct(\SplObjectStorage $hash)
|
||||
{
|
||||
$this->hash = $hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the keys that are available on the batch result.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getKeys()
|
||||
{
|
||||
return iterator_to_array($this->hash);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a result from the container for the given object. When getting
|
||||
* results for a batch of requests, provide the request object.
|
||||
*
|
||||
* @param object $forObject Object to retrieve the result for.
|
||||
*
|
||||
* @return mixed|null
|
||||
*/
|
||||
public function getResult($forObject)
|
||||
{
|
||||
return isset($this->hash[$forObject]) ? $this->hash[$forObject] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of successful results.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getSuccessful()
|
||||
{
|
||||
$results = [];
|
||||
foreach ($this->hash as $key) {
|
||||
if (!($this->hash[$key] instanceof \Exception)) {
|
||||
$results[] = $this->hash[$key];
|
||||
}
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of failed results.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getFailures()
|
||||
{
|
||||
$results = [];
|
||||
foreach ($this->hash as $key) {
|
||||
if ($this->hash[$key] instanceof \Exception) {
|
||||
$results[] = $this->hash[$key];
|
||||
}
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows iteration over all batch result values.
|
||||
*
|
||||
* @return \ArrayIterator
|
||||
*/
|
||||
public function getIterator()
|
||||
{
|
||||
$results = [];
|
||||
foreach ($this->hash as $key) {
|
||||
$results[] = $this->hash[$key];
|
||||
}
|
||||
|
||||
return new \ArrayIterator($results);
|
||||
}
|
||||
|
||||
/**
|
||||
* Counts the number of elements in the batch result.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function count()
|
||||
{
|
||||
return count($this->hash);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the batch contains a specific numerical array index.
|
||||
*
|
||||
* @param int $key Index to access
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function offsetExists($key)
|
||||
{
|
||||
return $key < count($this->hash);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows access of the batch using a numerical array index.
|
||||
*
|
||||
* @param int $key Index to access.
|
||||
*
|
||||
* @return mixed|null
|
||||
*/
|
||||
public function offsetGet($key)
|
||||
{
|
||||
$i = -1;
|
||||
foreach ($this->hash as $obj) {
|
||||
if ($key === ++$i) {
|
||||
return $this->hash[$obj];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function offsetUnset($key)
|
||||
{
|
||||
throw new \RuntimeException('Not implemented');
|
||||
}
|
||||
|
||||
public function offsetSet($key, $value)
|
||||
{
|
||||
throw new \RuntimeException('Not implemented');
|
||||
}
|
||||
}
|
646
core/vendor/guzzlehttp/guzzle/src/Client.php
vendored
646
core/vendor/guzzlehttp/guzzle/src/Client.php
vendored
|
@ -1,389 +1,231 @@
|
|||
<?php
|
||||
namespace GuzzleHttp;
|
||||
|
||||
use GuzzleHttp\Event\HasEmitterTrait;
|
||||
use GuzzleHttp\Message\MessageFactory;
|
||||
use GuzzleHttp\Message\MessageFactoryInterface;
|
||||
use GuzzleHttp\Message\RequestInterface;
|
||||
use GuzzleHttp\Message\FutureResponse;
|
||||
use GuzzleHttp\Ring\Client\Middleware;
|
||||
use GuzzleHttp\Ring\Client\CurlMultiHandler;
|
||||
use GuzzleHttp\Ring\Client\CurlHandler;
|
||||
use GuzzleHttp\Ring\Client\StreamHandler;
|
||||
use GuzzleHttp\Ring\Core;
|
||||
use GuzzleHttp\Ring\Future\FutureInterface;
|
||||
use GuzzleHttp\Exception\RequestException;
|
||||
use React\Promise\FulfilledPromise;
|
||||
use React\Promise\RejectedPromise;
|
||||
use GuzzleHttp\Cookie\CookieJar;
|
||||
use GuzzleHttp\Promise;
|
||||
use GuzzleHttp\Psr7;
|
||||
use Psr\Http\Message\UriInterface;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use \InvalidArgumentException as Iae;
|
||||
|
||||
/**
|
||||
* HTTP client
|
||||
* @method ResponseInterface get($uri, array $options = [])
|
||||
* @method ResponseInterface head($uri, array $options = [])
|
||||
* @method ResponseInterface put($uri, array $options = [])
|
||||
* @method ResponseInterface post($uri, array $options = [])
|
||||
* @method ResponseInterface patch($uri, array $options = [])
|
||||
* @method ResponseInterface delete($uri, array $options = [])
|
||||
* @method Promise\PromiseInterface getAsync($uri, array $options = [])
|
||||
* @method Promise\PromiseInterface headAsync($uri, array $options = [])
|
||||
* @method Promise\PromiseInterface putAsync($uri, array $options = [])
|
||||
* @method Promise\PromiseInterface postAsync($uri, array $options = [])
|
||||
* @method Promise\PromiseInterface patchAsync($uri, array $options = [])
|
||||
* @method Promise\PromiseInterface deleteAsync($uri, array $options = [])
|
||||
*/
|
||||
class Client implements ClientInterface
|
||||
{
|
||||
use HasEmitterTrait;
|
||||
|
||||
/** @var MessageFactoryInterface Request factory used by the client */
|
||||
private $messageFactory;
|
||||
|
||||
/** @var Url Base URL of the client */
|
||||
private $baseUrl;
|
||||
|
||||
/** @var array Default request options */
|
||||
private $defaults;
|
||||
|
||||
/** @var callable Request state machine */
|
||||
private $fsm;
|
||||
private $config;
|
||||
|
||||
/**
|
||||
* Clients accept an array of constructor parameters.
|
||||
*
|
||||
* Here's an example of creating a client using an URI template for the
|
||||
* client's base_url and an array of default request options to apply
|
||||
* to each request:
|
||||
* Here's an example of creating a client using a base_uri and an array of
|
||||
* default request options to apply to each request:
|
||||
*
|
||||
* $client = new Client([
|
||||
* 'base_url' => [
|
||||
* 'http://www.foo.com/{version}/',
|
||||
* ['version' => '123']
|
||||
* ],
|
||||
* 'defaults' => [
|
||||
* 'timeout' => 10,
|
||||
* 'allow_redirects' => false,
|
||||
* 'proxy' => '192.168.16.1:10'
|
||||
* ]
|
||||
* 'base_uri' => 'http://www.foo.com/1.0/',
|
||||
* 'timeout' => 0,
|
||||
* 'allow_redirects' => false,
|
||||
* 'proxy' => '192.168.16.1:10'
|
||||
* ]);
|
||||
*
|
||||
* @param array $config Client configuration settings
|
||||
* - base_url: Base URL of the client that is merged into relative URLs.
|
||||
* Can be a string or an array that contains a URI template followed
|
||||
* by an associative array of expansion variables to inject into the
|
||||
* URI template.
|
||||
* - handler: callable RingPHP handler used to transfer requests
|
||||
* - message_factory: Factory used to create request and response object
|
||||
* - defaults: Default request options to apply to each request
|
||||
* - emitter: Event emitter used for request events
|
||||
* - fsm: (internal use only) The request finite state machine. A
|
||||
* function that accepts a transaction and optional final state. The
|
||||
* function is responsible for transitioning a request through its
|
||||
* lifecycle events.
|
||||
* 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 = [])
|
||||
{
|
||||
$this->configureBaseUrl($config);
|
||||
if (!isset($config['handler'])) {
|
||||
$config['handler'] = HandlerStack::create();
|
||||
}
|
||||
|
||||
// Convert the base_uri to a UriInterface
|
||||
if (isset($config['base_uri'])) {
|
||||
$config['base_uri'] = Psr7\uri_for($config['base_uri']);
|
||||
}
|
||||
|
||||
$this->configureDefaults($config);
|
||||
}
|
||||
|
||||
if (isset($config['emitter'])) {
|
||||
$this->emitter = $config['emitter'];
|
||||
public function __call($method, $args)
|
||||
{
|
||||
if (count($args) < 1) {
|
||||
throw new \InvalidArgumentException('Magic request methods require a URI and optional options array');
|
||||
}
|
||||
|
||||
$this->messageFactory = isset($config['message_factory'])
|
||||
? $config['message_factory']
|
||||
: new MessageFactory();
|
||||
$uri = $args[0];
|
||||
$opts = isset($args[1]) ? $args[1] : [];
|
||||
|
||||
if (isset($config['fsm'])) {
|
||||
$this->fsm = $config['fsm'];
|
||||
} else {
|
||||
if (isset($config['handler'])) {
|
||||
$handler = $config['handler'];
|
||||
} elseif (isset($config['adapter'])) {
|
||||
$handler = $config['adapter'];
|
||||
} else {
|
||||
$handler = static::getDefaultHandler();
|
||||
}
|
||||
$this->fsm = new RequestFsm($handler, $this->messageFactory);
|
||||
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)),
|
||||
$options
|
||||
);
|
||||
}
|
||||
|
||||
public function send(RequestInterface $request, array $options = [])
|
||||
{
|
||||
$options[RequestOptions::SYNCHRONOUS] = true;
|
||||
return $this->sendAsync($request, $options)->wait();
|
||||
}
|
||||
|
||||
public function requestAsync($method, $uri = null, 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 = null, 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)
|
||||
{
|
||||
if (!isset($config['base_uri'])) {
|
||||
return $uri instanceof UriInterface ? $uri : new Psr7\Uri($uri);
|
||||
}
|
||||
|
||||
return Psr7\Uri::resolve(Psr7\uri_for($config['base_uri']), $uri);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a default handler to use based on the environment
|
||||
* Configures the default options for a client.
|
||||
*
|
||||
* @throws \RuntimeException if no viable Handler is available.
|
||||
*/
|
||||
public static function getDefaultHandler()
|
||||
{
|
||||
$default = $future = $streaming = null;
|
||||
|
||||
if (extension_loaded('curl')) {
|
||||
$config = [
|
||||
'select_timeout' => getenv('GUZZLE_CURL_SELECT_TIMEOUT') ?: 1
|
||||
];
|
||||
if ($maxHandles = getenv('GUZZLE_CURL_MAX_HANDLES')) {
|
||||
$config['max_handles'] = $maxHandles;
|
||||
}
|
||||
$future = new CurlMultiHandler($config);
|
||||
if (function_exists('curl_reset')) {
|
||||
$default = new CurlHandler();
|
||||
}
|
||||
}
|
||||
|
||||
if (ini_get('allow_url_fopen')) {
|
||||
$streaming = new StreamHandler();
|
||||
}
|
||||
|
||||
if (!($default = ($default ?: $future) ?: $streaming)) {
|
||||
throw new \RuntimeException('Guzzle requires cURL, the '
|
||||
. 'allow_url_fopen ini setting, or a custom HTTP handler.');
|
||||
}
|
||||
|
||||
$handler = $default;
|
||||
|
||||
if ($streaming && $streaming !== $default) {
|
||||
$handler = Middleware::wrapStreaming($default, $streaming);
|
||||
}
|
||||
|
||||
if ($future) {
|
||||
$handler = Middleware::wrapFuture($handler, $future);
|
||||
}
|
||||
|
||||
return $handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default User-Agent string to use with Guzzle
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getDefaultUserAgent()
|
||||
{
|
||||
static $defaultAgent = '';
|
||||
if (!$defaultAgent) {
|
||||
$defaultAgent = 'Guzzle/' . self::VERSION;
|
||||
if (extension_loaded('curl')) {
|
||||
$defaultAgent .= ' curl/' . curl_version()['version'];
|
||||
}
|
||||
$defaultAgent .= ' PHP/' . PHP_VERSION;
|
||||
}
|
||||
|
||||
return $defaultAgent;
|
||||
}
|
||||
|
||||
public function getDefaultOption($keyOrPath = null)
|
||||
{
|
||||
return $keyOrPath === null
|
||||
? $this->defaults
|
||||
: Utils::getPath($this->defaults, $keyOrPath);
|
||||
}
|
||||
|
||||
public function setDefaultOption($keyOrPath, $value)
|
||||
{
|
||||
Utils::setPath($this->defaults, $keyOrPath, $value);
|
||||
}
|
||||
|
||||
public function getBaseUrl()
|
||||
{
|
||||
return (string) $this->baseUrl;
|
||||
}
|
||||
|
||||
public function createRequest($method, $url = null, array $options = [])
|
||||
{
|
||||
$options = $this->mergeDefaults($options);
|
||||
// Use a clone of the client's emitter
|
||||
$options['config']['emitter'] = clone $this->getEmitter();
|
||||
$url = $url || (is_string($url) && strlen($url))
|
||||
? $this->buildUrl($url)
|
||||
: (string) $this->baseUrl;
|
||||
|
||||
return $this->messageFactory->createRequest($method, $url, $options);
|
||||
}
|
||||
|
||||
public function get($url = null, $options = [])
|
||||
{
|
||||
return $this->send($this->createRequest('GET', $url, $options));
|
||||
}
|
||||
|
||||
public function head($url = null, array $options = [])
|
||||
{
|
||||
return $this->send($this->createRequest('HEAD', $url, $options));
|
||||
}
|
||||
|
||||
public function delete($url = null, array $options = [])
|
||||
{
|
||||
return $this->send($this->createRequest('DELETE', $url, $options));
|
||||
}
|
||||
|
||||
public function put($url = null, array $options = [])
|
||||
{
|
||||
return $this->send($this->createRequest('PUT', $url, $options));
|
||||
}
|
||||
|
||||
public function patch($url = null, array $options = [])
|
||||
{
|
||||
return $this->send($this->createRequest('PATCH', $url, $options));
|
||||
}
|
||||
|
||||
public function post($url = null, array $options = [])
|
||||
{
|
||||
return $this->send($this->createRequest('POST', $url, $options));
|
||||
}
|
||||
|
||||
public function options($url = null, array $options = [])
|
||||
{
|
||||
return $this->send($this->createRequest('OPTIONS', $url, $options));
|
||||
}
|
||||
|
||||
public function send(RequestInterface $request)
|
||||
{
|
||||
$isFuture = $request->getConfig()->get('future');
|
||||
$trans = new Transaction($this, $request, $isFuture);
|
||||
$fn = $this->fsm;
|
||||
|
||||
try {
|
||||
$fn($trans);
|
||||
if ($isFuture) {
|
||||
// Turn the normal response into a future if needed.
|
||||
return $trans->response instanceof FutureInterface
|
||||
? $trans->response
|
||||
: new FutureResponse(new FulfilledPromise($trans->response));
|
||||
}
|
||||
// Resolve deep futures if this is not a future
|
||||
// transaction. This accounts for things like retries
|
||||
// that do not have an immediate side-effect.
|
||||
while ($trans->response instanceof FutureInterface) {
|
||||
$trans->response = $trans->response->wait();
|
||||
}
|
||||
return $trans->response;
|
||||
} catch (\Exception $e) {
|
||||
if ($isFuture) {
|
||||
// Wrap the exception in a promise
|
||||
return new FutureResponse(new RejectedPromise($e));
|
||||
}
|
||||
throw RequestException::wrapException($trans->request, $e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of default options to apply to the client
|
||||
* @param array $config
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getDefaultOptions()
|
||||
private function configureDefaults(array $config)
|
||||
{
|
||||
$settings = [
|
||||
'allow_redirects' => true,
|
||||
'exceptions' => true,
|
||||
$defaults = [
|
||||
'allow_redirects' => RedirectMiddleware::$defaultSettings,
|
||||
'http_errors' => true,
|
||||
'decode_content' => true,
|
||||
'verify' => true
|
||||
'verify' => true,
|
||||
'cookies' => false
|
||||
];
|
||||
|
||||
// Use the standard Linux HTTP_PROXY and HTTPS_PROXY if set
|
||||
if ($proxy = getenv('HTTP_PROXY')) {
|
||||
$settings['proxy']['http'] = $proxy;
|
||||
$defaults['proxy']['http'] = $proxy;
|
||||
}
|
||||
|
||||
if ($proxy = getenv('HTTPS_PROXY')) {
|
||||
$settings['proxy']['https'] = $proxy;
|
||||
$defaults['proxy']['https'] = $proxy;
|
||||
}
|
||||
|
||||
return $settings;
|
||||
}
|
||||
$this->config = $config + $defaults;
|
||||
|
||||
/**
|
||||
* Expand a URI template and inherit from the base URL if it's relative
|
||||
*
|
||||
* @param string|array $url URL or an array of the URI template to expand
|
||||
* followed by a hash of template varnames.
|
||||
* @return string
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
private function buildUrl($url)
|
||||
{
|
||||
// URI template (absolute or relative)
|
||||
if (!is_array($url)) {
|
||||
return strpos($url, '://')
|
||||
? (string) $url
|
||||
: (string) $this->baseUrl->combine($url);
|
||||
if (!empty($config['cookies']) && $config['cookies'] === true) {
|
||||
$this->config['cookies'] = new CookieJar();
|
||||
}
|
||||
|
||||
if (!isset($url[1])) {
|
||||
throw new \InvalidArgumentException('You must provide a hash of '
|
||||
. 'varname options in the second element of a URL array.');
|
||||
}
|
||||
|
||||
// Absolute URL
|
||||
if (strpos($url[0], '://')) {
|
||||
return Utils::uriTemplate($url[0], $url[1]);
|
||||
}
|
||||
|
||||
// Combine the relative URL with the base URL
|
||||
return (string) $this->baseUrl->combine(
|
||||
Utils::uriTemplate($url[0], $url[1])
|
||||
);
|
||||
}
|
||||
|
||||
private function configureBaseUrl(&$config)
|
||||
{
|
||||
if (!isset($config['base_url'])) {
|
||||
$this->baseUrl = new Url('', '');
|
||||
} elseif (!is_array($config['base_url'])) {
|
||||
$this->baseUrl = Url::fromString($config['base_url']);
|
||||
} elseif (count($config['base_url']) < 2) {
|
||||
throw new \InvalidArgumentException('You must provide a hash of '
|
||||
. 'varname options in the second element of a base_url array.');
|
||||
// Add the default user-agent header.
|
||||
if (!isset($this->config['headers'])) {
|
||||
$this->config['headers'] = ['User-Agent' => default_user_agent()];
|
||||
} else {
|
||||
$this->baseUrl = Url::fromString(
|
||||
Utils::uriTemplate(
|
||||
$config['base_url'][0],
|
||||
$config['base_url'][1]
|
||||
)
|
||||
);
|
||||
$config['base_url'] = (string) $this->baseUrl;
|
||||
}
|
||||
}
|
||||
|
||||
private function configureDefaults($config)
|
||||
{
|
||||
if (!isset($config['defaults'])) {
|
||||
$this->defaults = $this->getDefaultOptions();
|
||||
} else {
|
||||
$this->defaults = array_replace(
|
||||
$this->getDefaultOptions(),
|
||||
$config['defaults']
|
||||
);
|
||||
}
|
||||
|
||||
// Add the default user-agent header
|
||||
if (!isset($this->defaults['headers'])) {
|
||||
$this->defaults['headers'] = [
|
||||
'User-Agent' => static::getDefaultUserAgent()
|
||||
];
|
||||
} elseif (!Core::hasHeader($this->defaults, 'User-Agent')) {
|
||||
// Add the User-Agent header if one was not already set
|
||||
$this->defaults['headers']['User-Agent'] = static::getDefaultUserAgent();
|
||||
// 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 passed by reference.
|
||||
* Merges default options into the array.
|
||||
*
|
||||
* @param array $options Options to modify by reference
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function mergeDefaults($options)
|
||||
private function prepareDefaults($options)
|
||||
{
|
||||
$defaults = $this->defaults;
|
||||
$defaults = $this->config;
|
||||
|
||||
// Case-insensitively merge in default headers if both defaults and
|
||||
// options have headers specified.
|
||||
if (!empty($defaults['headers']) && !empty($options['headers'])) {
|
||||
// Create a set of lowercased keys that are present.
|
||||
$lkeys = [];
|
||||
foreach (array_keys($options['headers']) as $k) {
|
||||
$lkeys[strtolower($k)] = true;
|
||||
}
|
||||
// Merge in lowercase default keys when not present in above set.
|
||||
foreach ($defaults['headers'] as $key => $value) {
|
||||
if (!isset($lkeys[strtolower($key)])) {
|
||||
$options['headers'][$key] = $value;
|
||||
}
|
||||
}
|
||||
// No longer need to merge in headers.
|
||||
if (!empty($defaults['headers'])) {
|
||||
// Default headers are only added if they are not present.
|
||||
$defaults['_conditional'] = $defaults['headers'];
|
||||
unset($defaults['headers']);
|
||||
}
|
||||
|
||||
$result = array_replace_recursive($defaults, $options);
|
||||
foreach ($options as $k => $v) {
|
||||
// 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]);
|
||||
}
|
||||
|
@ -393,11 +235,159 @@ class Client implements ClientInterface
|
|||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@see GuzzleHttp\Pool} instead.
|
||||
* @see GuzzleHttp\Pool
|
||||
* 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
|
||||
*/
|
||||
public function sendAll($requests, array $options = [])
|
||||
private function transfer(RequestInterface $request, array $options)
|
||||
{
|
||||
Pool::send($this, $requests, $options);
|
||||
// save_to -> sink
|
||||
if (isset($options['save_to'])) {
|
||||
$options['sink'] = $options['save_to'];
|
||||
unset($options['save_to']);
|
||||
}
|
||||
|
||||
// exceptions -> http_error
|
||||
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'], null, '&');
|
||||
unset($options['form_params']);
|
||||
$options['_conditional']['Content-Type'] = 'application/x-www-form-urlencoded';
|
||||
}
|
||||
|
||||
if (isset($options['multipart'])) {
|
||||
$elements = $options['multipart'];
|
||||
unset($options['multipart']);
|
||||
$options['body'] = new Psr7\MultipartStream($elements);
|
||||
// Use a multipart/form-data POST if a Content-Type is not set.
|
||||
$options['_conditional']['Content-Type'] = 'multipart/form-data; boundary='
|
||||
. $options['body']->getBoundary();
|
||||
}
|
||||
|
||||
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'])) {
|
||||
$value = $options['auth'];
|
||||
$type = is_array($value)
|
||||
? (isset($value[2]) ? strtolower($value[2]) : 'basic')
|
||||
: $value;
|
||||
$config['auth'] = $value;
|
||||
switch (strtolower($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;
|
||||
}
|
||||
}
|
||||
|
||||
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 Iae('query must be a string or array');
|
||||
}
|
||||
$modify['query'] = $value;
|
||||
unset($options['query']);
|
||||
}
|
||||
|
||||
if (isset($options['json'])) {
|
||||
$modify['body'] = Psr7\stream_for(json_encode($options['json']));
|
||||
$options['_conditional']['Content-Type'] = 'application/json';
|
||||
unset($options['json']);
|
||||
}
|
||||
|
||||
$request = Psr7\modify_request($request, $modify);
|
||||
|
||||
// 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 a the "multipart" '
|
||||
. 'request option to send a multipart/form-data request.');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,150 +1,84 @@
|
|||
<?php
|
||||
namespace GuzzleHttp;
|
||||
|
||||
use GuzzleHttp\Event\HasEmitterInterface;
|
||||
use GuzzleHttp\Exception\RequestException;
|
||||
use GuzzleHttp\Message\RequestInterface;
|
||||
use GuzzleHttp\Message\ResponseInterface;
|
||||
use GuzzleHttp\Promise\PromiseInterface;
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\UriInterface;
|
||||
|
||||
/**
|
||||
* Client interface for sending HTTP requests
|
||||
* Client interface for sending HTTP requests.
|
||||
*/
|
||||
interface ClientInterface extends HasEmitterInterface
|
||||
interface ClientInterface
|
||||
{
|
||||
const VERSION = '5.2.0';
|
||||
const VERSION = '6.0.2';
|
||||
|
||||
/**
|
||||
* Create and return a new {@see RequestInterface} object.
|
||||
* Send an HTTP request.
|
||||
*
|
||||
* @param RequestInterface $request Request to send
|
||||
* @param array $options Request options to apply to the given
|
||||
* request and to the transfer.
|
||||
*
|
||||
* @return ResponseInterface
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function send(RequestInterface $request, array $options = []);
|
||||
|
||||
/**
|
||||
* Asynchronously send an HTTP request.
|
||||
*
|
||||
* @param RequestInterface $request Request to send
|
||||
* @param array $options Request options to apply to the given
|
||||
* request and to the transfer.
|
||||
*
|
||||
* @return PromiseInterface
|
||||
*/
|
||||
public function sendAsync(RequestInterface $request, array $options = []);
|
||||
|
||||
/**
|
||||
* Create and send an HTTP request.
|
||||
*
|
||||
* Use an absolute path to override the base path of the client, or a
|
||||
* relative path to append to the base path of the client. The URL can
|
||||
* contain the query string as well.
|
||||
*
|
||||
* @param string $method HTTP method
|
||||
* @param string|UriInterface $uri URI object or string.
|
||||
* @param array $options Request options to apply.
|
||||
*
|
||||
* @return ResponseInterface
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function request($method, $uri, array $options = []);
|
||||
|
||||
/**
|
||||
* Create and send an asynchronous HTTP request.
|
||||
*
|
||||
* Use an absolute path to override the base path of the client, or a
|
||||
* relative path to append to the base path of the client. The URL can
|
||||
* contain the query string as well. Use an array to provide a URL
|
||||
* template and additional variables to use in the URL template expansion.
|
||||
*
|
||||
* @param string $method HTTP method
|
||||
* @param string|array|Url $url URL or URI template
|
||||
* @param array $options Array of request options to apply.
|
||||
* @param string $method HTTP method
|
||||
* @param string|UriInterface $uri URI object or string.
|
||||
* @param array $options Request options to apply.
|
||||
*
|
||||
* @return RequestInterface
|
||||
* @return PromiseInterface
|
||||
*/
|
||||
public function createRequest($method, $url = null, array $options = []);
|
||||
public function requestAsync($method, $uri, array $options = []);
|
||||
|
||||
/**
|
||||
* Send a GET request
|
||||
* Get a client configuration option.
|
||||
*
|
||||
* @param string|array|Url $url URL or URI template
|
||||
* @param array $options Array of request options to apply.
|
||||
* These options include default request options of the client, a "handler"
|
||||
* (if utilized by the concrete client), and a "base_uri" if utilized by
|
||||
* the concrete client.
|
||||
*
|
||||
* @return ResponseInterface
|
||||
* @throws RequestException When an error is encountered
|
||||
*/
|
||||
public function get($url = null, $options = []);
|
||||
|
||||
/**
|
||||
* Send a HEAD request
|
||||
*
|
||||
* @param string|array|Url $url URL or URI template
|
||||
* @param array $options Array of request options to apply.
|
||||
*
|
||||
* @return ResponseInterface
|
||||
* @throws RequestException When an error is encountered
|
||||
*/
|
||||
public function head($url = null, array $options = []);
|
||||
|
||||
/**
|
||||
* Send a DELETE request
|
||||
*
|
||||
* @param string|array|Url $url URL or URI template
|
||||
* @param array $options Array of request options to apply.
|
||||
*
|
||||
* @return ResponseInterface
|
||||
* @throws RequestException When an error is encountered
|
||||
*/
|
||||
public function delete($url = null, array $options = []);
|
||||
|
||||
/**
|
||||
* Send a PUT request
|
||||
*
|
||||
* @param string|array|Url $url URL or URI template
|
||||
* @param array $options Array of request options to apply.
|
||||
*
|
||||
* @return ResponseInterface
|
||||
* @throws RequestException When an error is encountered
|
||||
*/
|
||||
public function put($url = null, array $options = []);
|
||||
|
||||
/**
|
||||
* Send a PATCH request
|
||||
*
|
||||
* @param string|array|Url $url URL or URI template
|
||||
* @param array $options Array of request options to apply.
|
||||
*
|
||||
* @return ResponseInterface
|
||||
* @throws RequestException When an error is encountered
|
||||
*/
|
||||
public function patch($url = null, array $options = []);
|
||||
|
||||
/**
|
||||
* Send a POST request
|
||||
*
|
||||
* @param string|array|Url $url URL or URI template
|
||||
* @param array $options Array of request options to apply.
|
||||
*
|
||||
* @return ResponseInterface
|
||||
* @throws RequestException When an error is encountered
|
||||
*/
|
||||
public function post($url = null, array $options = []);
|
||||
|
||||
/**
|
||||
* Send an OPTIONS request
|
||||
*
|
||||
* @param string|array|Url $url URL or URI template
|
||||
* @param array $options Array of request options to apply.
|
||||
*
|
||||
* @return ResponseInterface
|
||||
* @throws RequestException When an error is encountered
|
||||
*/
|
||||
public function options($url = null, array $options = []);
|
||||
|
||||
/**
|
||||
* Sends a single request
|
||||
*
|
||||
* @param RequestInterface $request Request to send
|
||||
*
|
||||
* @return \GuzzleHttp\Message\ResponseInterface
|
||||
* @throws \LogicException When the handler does not populate a response
|
||||
* @throws RequestException When an error is encountered
|
||||
*/
|
||||
public function send(RequestInterface $request);
|
||||
|
||||
/**
|
||||
* Get default request options of the client.
|
||||
*
|
||||
* @param string|null $keyOrPath The Path to a particular default request
|
||||
* option to retrieve or pass null to retrieve all default request
|
||||
* options. The syntax uses "/" to denote a path through nested PHP
|
||||
* arrays. For example, "headers/content-type".
|
||||
* @param string|null $option The config option to retrieve.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getDefaultOption($keyOrPath = null);
|
||||
|
||||
/**
|
||||
* Set a default request option on the client so that any request created
|
||||
* by the client will use the provided default value unless overridden
|
||||
* explicitly when creating a request.
|
||||
*
|
||||
* @param string|null $keyOrPath The Path to a particular configuration
|
||||
* value to set. The syntax uses a path notation that allows you to
|
||||
* specify nested configuration values (e.g., 'headers/content-type').
|
||||
* @param mixed $value Default request option value to set
|
||||
*/
|
||||
public function setDefaultOption($keyOrPath, $value);
|
||||
|
||||
/**
|
||||
* Get the base URL of the client.
|
||||
*
|
||||
* @return string Returns the base URL if present
|
||||
*/
|
||||
public function getBaseUrl();
|
||||
public function getConfig($option = null);
|
||||
}
|
||||
|
|
236
core/vendor/guzzlehttp/guzzle/src/Collection.php
vendored
236
core/vendor/guzzlehttp/guzzle/src/Collection.php
vendored
|
@ -1,236 +0,0 @@
|
|||
<?php
|
||||
namespace GuzzleHttp;
|
||||
|
||||
/**
|
||||
* Key value pair collection object
|
||||
*/
|
||||
class Collection implements
|
||||
\ArrayAccess,
|
||||
\IteratorAggregate,
|
||||
\Countable,
|
||||
ToArrayInterface
|
||||
{
|
||||
use HasDataTrait;
|
||||
|
||||
/**
|
||||
* @param array $data Associative array of data to set
|
||||
*/
|
||||
public function __construct(array $data = [])
|
||||
{
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new collection from an array, validate the keys, and add default
|
||||
* values where missing
|
||||
*
|
||||
* @param array $config Configuration values to apply.
|
||||
* @param array $defaults Default parameters
|
||||
* @param array $required Required parameter names
|
||||
*
|
||||
* @return self
|
||||
* @throws \InvalidArgumentException if a parameter is missing
|
||||
*/
|
||||
public static function fromConfig(
|
||||
array $config = [],
|
||||
array $defaults = [],
|
||||
array $required = []
|
||||
) {
|
||||
$data = $config + $defaults;
|
||||
|
||||
if ($missing = array_diff($required, array_keys($data))) {
|
||||
throw new \InvalidArgumentException(
|
||||
'Config is missing the following keys: ' .
|
||||
implode(', ', $missing));
|
||||
}
|
||||
|
||||
return new self($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all key value pairs
|
||||
*/
|
||||
public function clear()
|
||||
{
|
||||
$this->data = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a specific key value.
|
||||
*
|
||||
* @param string $key Key to retrieve.
|
||||
*
|
||||
* @return mixed|null Value of the key or NULL
|
||||
*/
|
||||
public function get($key)
|
||||
{
|
||||
return isset($this->data[$key]) ? $this->data[$key] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a key value pair
|
||||
*
|
||||
* @param string $key Key to set
|
||||
* @param mixed $value Value to set
|
||||
*/
|
||||
public function set($key, $value)
|
||||
{
|
||||
$this->data[$key] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a value to a key. If a key of the same name has already been added,
|
||||
* the key value will be converted into an array and the new value will be
|
||||
* pushed to the end of the array.
|
||||
*
|
||||
* @param string $key Key to add
|
||||
* @param mixed $value Value to add to the key
|
||||
*/
|
||||
public function add($key, $value)
|
||||
{
|
||||
if (!array_key_exists($key, $this->data)) {
|
||||
$this->data[$key] = $value;
|
||||
} elseif (is_array($this->data[$key])) {
|
||||
$this->data[$key][] = $value;
|
||||
} else {
|
||||
$this->data[$key] = array($this->data[$key], $value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a specific key value pair
|
||||
*
|
||||
* @param string $key A key to remove
|
||||
*/
|
||||
public function remove($key)
|
||||
{
|
||||
unset($this->data[$key]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all keys in the collection
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getKeys()
|
||||
{
|
||||
return array_keys($this->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not the specified key is present.
|
||||
*
|
||||
* @param string $key The key for which to check the existence.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasKey($key)
|
||||
{
|
||||
return array_key_exists($key, $this->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if any keys contains a certain value
|
||||
*
|
||||
* @param string $value Value to search for
|
||||
*
|
||||
* @return mixed Returns the key if the value was found FALSE if the value
|
||||
* was not found.
|
||||
*/
|
||||
public function hasValue($value)
|
||||
{
|
||||
return array_search($value, $this->data, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the data of the object with the value of an array
|
||||
*
|
||||
* @param array $data Associative array of data
|
||||
*/
|
||||
public function replace(array $data)
|
||||
{
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add and merge in a Collection or array of key value pair data.
|
||||
*
|
||||
* @param Collection|array $data Associative array of key value pair data
|
||||
*/
|
||||
public function merge($data)
|
||||
{
|
||||
foreach ($data as $key => $value) {
|
||||
$this->add($key, $value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Overwrite key value pairs in this collection with all of the data from
|
||||
* an array or collection.
|
||||
*
|
||||
* @param array|\Traversable $data Values to override over this config
|
||||
*/
|
||||
public function overwriteWith($data)
|
||||
{
|
||||
if (is_array($data)) {
|
||||
$this->data = $data + $this->data;
|
||||
} elseif ($data instanceof Collection) {
|
||||
$this->data = $data->toArray() + $this->data;
|
||||
} else {
|
||||
foreach ($data as $key => $value) {
|
||||
$this->data[$key] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Collection containing all the elements of the collection after
|
||||
* applying the callback function to each one.
|
||||
*
|
||||
* The callable should accept three arguments:
|
||||
* - (string) $key
|
||||
* - (string) $value
|
||||
* - (array) $context
|
||||
*
|
||||
* The callable must return a the altered or unaltered value.
|
||||
*
|
||||
* @param callable $closure Map function to apply
|
||||
* @param array $context Context to pass to the callable
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function map(callable $closure, array $context = [])
|
||||
{
|
||||
$collection = new static();
|
||||
foreach ($this as $key => $value) {
|
||||
$collection[$key] = $closure($key, $value, $context);
|
||||
}
|
||||
|
||||
return $collection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterates over each key value pair in the collection passing them to the
|
||||
* callable. If the callable returns true, the current value from input is
|
||||
* returned into the result Collection.
|
||||
*
|
||||
* The callable must accept two arguments:
|
||||
* - (string) $key
|
||||
* - (string) $value
|
||||
*
|
||||
* @param callable $closure Evaluation function
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function filter(callable $closure)
|
||||
{
|
||||
$collection = new static();
|
||||
foreach ($this->data as $key => $value) {
|
||||
if ($closure($key, $value)) {
|
||||
$collection[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $collection;
|
||||
}
|
||||
}
|
|
@ -1,14 +1,13 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Cookie;
|
||||
|
||||
use GuzzleHttp\Message\RequestInterface;
|
||||
use GuzzleHttp\Message\ResponseInterface;
|
||||
use GuzzleHttp\ToArrayInterface;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
/**
|
||||
* Cookie jar that stores cookies an an array
|
||||
*/
|
||||
class CookieJar implements CookieJarInterface, ToArrayInterface
|
||||
class CookieJar implements CookieJarInterface
|
||||
{
|
||||
/** @var SetCookie[] Loaded cookie data */
|
||||
private $cookies = [];
|
||||
|
@ -194,23 +193,24 @@ class CookieJar implements CookieJarInterface, ToArrayInterface
|
|||
RequestInterface $request,
|
||||
ResponseInterface $response
|
||||
) {
|
||||
if ($cookieHeader = $response->getHeaderAsArray('Set-Cookie')) {
|
||||
if ($cookieHeader = $response->getHeader('Set-Cookie')) {
|
||||
foreach ($cookieHeader as $cookie) {
|
||||
$sc = SetCookie::fromString($cookie);
|
||||
if (!$sc->getDomain()) {
|
||||
$sc->setDomain($request->getHost());
|
||||
$sc->setDomain($request->getUri()->getHost());
|
||||
}
|
||||
$this->setCookie($sc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function addCookieHeader(RequestInterface $request)
|
||||
public function withCookieHeader(RequestInterface $request)
|
||||
{
|
||||
$values = [];
|
||||
$scheme = $request->getScheme();
|
||||
$host = $request->getHost();
|
||||
$path = $request->getPath();
|
||||
$uri = $request->getUri();
|
||||
$scheme = $uri->getScheme();
|
||||
$host = $uri->getHost();
|
||||
$path = $uri->getPath() ?: '/';
|
||||
|
||||
foreach ($this->cookies as $cookie) {
|
||||
if ($cookie->matchesPath($path) &&
|
||||
|
@ -223,9 +223,9 @@ class CookieJar implements CookieJarInterface, ToArrayInterface
|
|||
}
|
||||
}
|
||||
|
||||
if ($values) {
|
||||
$request->setHeader('Cookie', implode('; ', $values));
|
||||
}
|
||||
return $values
|
||||
? $request->withHeader('Cookie', implode('; ', $values))
|
||||
: $request;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Cookie;
|
||||
|
||||
use GuzzleHttp\Message\RequestInterface;
|
||||
use GuzzleHttp\Message\ResponseInterface;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
/**
|
||||
* Stores HTTP cookies.
|
||||
|
@ -17,14 +17,16 @@ use GuzzleHttp\Message\ResponseInterface;
|
|||
interface CookieJarInterface extends \Countable, \IteratorAggregate
|
||||
{
|
||||
/**
|
||||
* Add a Cookie header to a request.
|
||||
* Create a request with added cookie headers.
|
||||
*
|
||||
* If no matching cookies are found in the cookie jar, then no Cookie
|
||||
* header is added to the request.
|
||||
* header is added to the request and the same request is returned.
|
||||
*
|
||||
* @param RequestInterface $request Request object to update
|
||||
* @param RequestInterface $request Request object to modify.
|
||||
*
|
||||
* @return RequestInterface returns the modified request.
|
||||
*/
|
||||
public function addCookieHeader(RequestInterface $request);
|
||||
public function withCookieHeader(RequestInterface $request);
|
||||
|
||||
/**
|
||||
* Extract cookies from an HTTP response and store them in the CookieJar.
|
||||
|
@ -72,4 +74,11 @@ interface CookieJarInterface extends \Countable, \IteratorAggregate
|
|||
* to RFC 2965.
|
||||
*/
|
||||
public function clearSessionCookies();
|
||||
|
||||
/**
|
||||
* Converts the cookie jar to an array.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function toArray();
|
||||
}
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Cookie;
|
||||
|
||||
use GuzzleHttp\Utils;
|
||||
|
||||
/**
|
||||
* Persists non-session cookies using a JSON formatted file
|
||||
*/
|
||||
|
@ -45,15 +43,14 @@ class FileCookieJar extends CookieJar
|
|||
{
|
||||
$json = [];
|
||||
foreach ($this as $cookie) {
|
||||
/** @var SetCookie $cookie */
|
||||
if ($cookie->getExpires() && !$cookie->getDiscard()) {
|
||||
$json[] = $cookie->toArray();
|
||||
}
|
||||
}
|
||||
|
||||
if (false === file_put_contents($filename, json_encode($json))) {
|
||||
// @codeCoverageIgnoreStart
|
||||
throw new \RuntimeException("Unable to save file {$filename}");
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -69,14 +66,12 @@ class FileCookieJar extends CookieJar
|
|||
{
|
||||
$json = file_get_contents($filename);
|
||||
if (false === $json) {
|
||||
// @codeCoverageIgnoreStart
|
||||
throw new \RuntimeException("Unable to load file {$filename}");
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
$data = Utils::jsonDecode($json, true);
|
||||
$data = json_decode($json, true);
|
||||
if (is_array($data)) {
|
||||
foreach (Utils::jsonDecode($json, true) as $cookie) {
|
||||
foreach (json_decode($json, true) as $cookie) {
|
||||
$this->setCookie(new SetCookie($cookie));
|
||||
}
|
||||
} elseif (strlen($data)) {
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Cookie;
|
||||
|
||||
use GuzzleHttp\Utils;
|
||||
|
||||
/**
|
||||
* Persists cookies in the client session
|
||||
*/
|
||||
|
@ -37,6 +35,7 @@ class SessionCookieJar extends CookieJar
|
|||
{
|
||||
$json = [];
|
||||
foreach ($this as $cookie) {
|
||||
/** @var SetCookie $cookie */
|
||||
if ($cookie->getExpires() && !$cookie->getDiscard()) {
|
||||
$json[] = $cookie->toArray();
|
||||
}
|
||||
|
@ -54,7 +53,7 @@ class SessionCookieJar extends CookieJar
|
|||
? $_SESSION[$this->sessionKey]
|
||||
: null;
|
||||
|
||||
$data = Utils::jsonDecode($cookieJar, true);
|
||||
$data = json_decode($cookieJar, true);
|
||||
if (is_array($data)) {
|
||||
foreach ($data as $cookie) {
|
||||
$this->setCookie(new SetCookie($cookie));
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Cookie;
|
||||
|
||||
use GuzzleHttp\ToArrayInterface;
|
||||
|
||||
/**
|
||||
* Set-Cookie object
|
||||
*/
|
||||
class SetCookie implements ToArrayInterface
|
||||
class SetCookie
|
||||
{
|
||||
/** @var array */
|
||||
private static $defaults = [
|
||||
|
@ -350,8 +348,8 @@ class SetCookie implements ToArrayInterface
|
|||
}
|
||||
|
||||
// Check if any of the invalid characters are present in the cookie name
|
||||
if (preg_match("/[=,; \t\r\n\013\014]/", $name)) {
|
||||
return "Cookie name must not cannot invalid characters: =,; \\t\\r\\n\\013\\014";
|
||||
if (preg_match('/[\x00-\x20\x22\x28-\x29\x2c\x2f\x3a-\x40\x5b-\x5d\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
|
||||
|
|
|
@ -1,20 +0,0 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Event;
|
||||
|
||||
/**
|
||||
* Basic event class that can be extended.
|
||||
*/
|
||||
abstract class AbstractEvent implements EventInterface
|
||||
{
|
||||
private $propagationStopped = false;
|
||||
|
||||
public function isPropagationStopped()
|
||||
{
|
||||
return $this->propagationStopped;
|
||||
}
|
||||
|
||||
public function stopPropagation()
|
||||
{
|
||||
$this->propagationStopped = true;
|
||||
}
|
||||
}
|
|
@ -1,61 +0,0 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Event;
|
||||
|
||||
use GuzzleHttp\Transaction;
|
||||
use GuzzleHttp\ClientInterface;
|
||||
use GuzzleHttp\Message\RequestInterface;
|
||||
|
||||
/**
|
||||
* Base class for request events, providing a request and client getter.
|
||||
*/
|
||||
abstract class AbstractRequestEvent extends AbstractEvent
|
||||
{
|
||||
/** @var Transaction */
|
||||
protected $transaction;
|
||||
|
||||
/**
|
||||
* @param Transaction $transaction
|
||||
*/
|
||||
public function __construct(Transaction $transaction)
|
||||
{
|
||||
$this->transaction = $transaction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the HTTP client associated with the event.
|
||||
*
|
||||
* @return ClientInterface
|
||||
*/
|
||||
public function getClient()
|
||||
{
|
||||
return $this->transaction->client;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the request object
|
||||
*
|
||||
* @return RequestInterface
|
||||
*/
|
||||
public function getRequest()
|
||||
{
|
||||
return $this->transaction->request;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of transaction retries.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getRetryCount()
|
||||
{
|
||||
return $this->transaction->retries;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Transaction
|
||||
*/
|
||||
protected function getTransaction()
|
||||
{
|
||||
return $this->transaction;
|
||||
}
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Event;
|
||||
|
||||
/**
|
||||
* Abstract request event that can be retried.
|
||||
*/
|
||||
class AbstractRetryableEvent extends AbstractTransferEvent
|
||||
{
|
||||
/**
|
||||
* Mark the request as needing a retry and stop event propagation.
|
||||
*
|
||||
* This action allows you to retry a request without emitting the "end"
|
||||
* event multiple times for a given request. When retried, the request
|
||||
* emits a before event and is then sent again using the client that sent
|
||||
* the original request.
|
||||
*
|
||||
* When retrying, it is important to limit the number of retries you allow
|
||||
* to prevent infinite loops.
|
||||
*
|
||||
* This action can only be taken during the "complete" and "error" events.
|
||||
*
|
||||
* @param int $afterDelay If specified, the amount of time in milliseconds
|
||||
* to delay before retrying. Note that this must
|
||||
* be supported by the underlying RingPHP handler
|
||||
* to work properly. Set to 0 or provide no value
|
||||
* to retry immediately.
|
||||
*/
|
||||
public function retry($afterDelay = 0)
|
||||
{
|
||||
// Setting the transition state to 'retry' will cause the next state
|
||||
// transition of the transaction to retry the request.
|
||||
$this->transaction->state = 'retry';
|
||||
|
||||
if ($afterDelay) {
|
||||
$this->transaction->request->getConfig()->set('delay', $afterDelay);
|
||||
}
|
||||
|
||||
$this->stopPropagation();
|
||||
}
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Event;
|
||||
|
||||
use GuzzleHttp\Message\ResponseInterface;
|
||||
use GuzzleHttp\Ring\Future\FutureInterface;
|
||||
|
||||
/**
|
||||
* Event that contains transfer statistics, and can be intercepted.
|
||||
*/
|
||||
abstract class AbstractTransferEvent extends AbstractRequestEvent
|
||||
{
|
||||
/**
|
||||
* Get all transfer information as an associative array if no $name
|
||||
* argument is supplied, or gets a specific transfer statistic if
|
||||
* a $name attribute is supplied (e.g., 'total_time').
|
||||
*
|
||||
* @param string $name Name of the transfer stat to retrieve
|
||||
*
|
||||
* @return mixed|null|array
|
||||
*/
|
||||
public function getTransferInfo($name = null)
|
||||
{
|
||||
if (!$name) {
|
||||
return $this->transaction->transferInfo;
|
||||
}
|
||||
|
||||
return isset($this->transaction->transferInfo[$name])
|
||||
? $this->transaction->transferInfo[$name]
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true/false if a response is available.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasResponse()
|
||||
{
|
||||
return !($this->transaction->response instanceof FutureInterface);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the response.
|
||||
*
|
||||
* @return ResponseInterface|null
|
||||
*/
|
||||
public function getResponse()
|
||||
{
|
||||
return $this->hasResponse() ? $this->transaction->response : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Intercept the request and associate a response
|
||||
*
|
||||
* @param ResponseInterface $response Response to set
|
||||
*/
|
||||
public function intercept(ResponseInterface $response)
|
||||
{
|
||||
$this->transaction->response = $response;
|
||||
$this->transaction->exception = null;
|
||||
$this->stopPropagation();
|
||||
}
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Event;
|
||||
|
||||
use GuzzleHttp\Message\ResponseInterface;
|
||||
|
||||
/**
|
||||
* Event object emitted before a request is sent.
|
||||
*
|
||||
* This event MAY be emitted multiple times (i.e., if a request is retried).
|
||||
* You MAY change the Response associated with the request using the
|
||||
* intercept() method of the event.
|
||||
*/
|
||||
class BeforeEvent extends AbstractRequestEvent
|
||||
{
|
||||
/**
|
||||
* Intercept the request and associate a response
|
||||
*
|
||||
* @param ResponseInterface $response Response to set
|
||||
*/
|
||||
public function intercept(ResponseInterface $response)
|
||||
{
|
||||
$this->transaction->response = $response;
|
||||
$this->transaction->exception = null;
|
||||
$this->stopPropagation();
|
||||
}
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Event;
|
||||
|
||||
/**
|
||||
* Event object emitted after a request has been completed.
|
||||
*
|
||||
* This event MAY be emitted multiple times for a single request. You MAY
|
||||
* change the Response associated with the request using the intercept()
|
||||
* method of the event.
|
||||
*
|
||||
* This event allows the request to be retried if necessary using the retry()
|
||||
* method of the event.
|
||||
*/
|
||||
class CompleteEvent extends AbstractRetryableEvent {}
|
146
core/vendor/guzzlehttp/guzzle/src/Event/Emitter.php
vendored
146
core/vendor/guzzlehttp/guzzle/src/Event/Emitter.php
vendored
|
@ -1,146 +0,0 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Event;
|
||||
|
||||
/**
|
||||
* Guzzle event emitter.
|
||||
*
|
||||
* Some of this class is based on the Symfony EventDispatcher component, which
|
||||
* ships with the following license:
|
||||
*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link https://github.com/symfony/symfony/tree/master/src/Symfony/Component/EventDispatcher
|
||||
*/
|
||||
class Emitter implements EmitterInterface
|
||||
{
|
||||
/** @var array */
|
||||
private $listeners = [];
|
||||
|
||||
/** @var array */
|
||||
private $sorted = [];
|
||||
|
||||
public function on($eventName, callable $listener, $priority = 0)
|
||||
{
|
||||
if ($priority === 'first') {
|
||||
$priority = isset($this->listeners[$eventName])
|
||||
? max(array_keys($this->listeners[$eventName])) + 1
|
||||
: 1;
|
||||
} elseif ($priority === 'last') {
|
||||
$priority = isset($this->listeners[$eventName])
|
||||
? min(array_keys($this->listeners[$eventName])) - 1
|
||||
: -1;
|
||||
}
|
||||
|
||||
$this->listeners[$eventName][$priority][] = $listener;
|
||||
unset($this->sorted[$eventName]);
|
||||
}
|
||||
|
||||
public function once($eventName, callable $listener, $priority = 0)
|
||||
{
|
||||
$onceListener = function (
|
||||
EventInterface $event,
|
||||
$eventName
|
||||
) use (&$onceListener, $eventName, $listener, $priority) {
|
||||
$this->removeListener($eventName, $onceListener);
|
||||
$listener($event, $eventName, $this);
|
||||
};
|
||||
|
||||
$this->on($eventName, $onceListener, $priority);
|
||||
}
|
||||
|
||||
public function removeListener($eventName, callable $listener)
|
||||
{
|
||||
if (empty($this->listeners[$eventName])) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($this->listeners[$eventName] as $priority => $listeners) {
|
||||
if (false !== ($key = array_search($listener, $listeners, true))) {
|
||||
unset(
|
||||
$this->listeners[$eventName][$priority][$key],
|
||||
$this->sorted[$eventName]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function listeners($eventName = null)
|
||||
{
|
||||
// Return all events in a sorted priority order
|
||||
if ($eventName === null) {
|
||||
foreach (array_keys($this->listeners) as $eventName) {
|
||||
if (empty($this->sorted[$eventName])) {
|
||||
$this->listeners($eventName);
|
||||
}
|
||||
}
|
||||
return $this->sorted;
|
||||
}
|
||||
|
||||
// Return the listeners for a specific event, sorted in priority order
|
||||
if (empty($this->sorted[$eventName])) {
|
||||
$this->sorted[$eventName] = [];
|
||||
if (isset($this->listeners[$eventName])) {
|
||||
krsort($this->listeners[$eventName], SORT_NUMERIC);
|
||||
foreach ($this->listeners[$eventName] as $listeners) {
|
||||
foreach ($listeners as $listener) {
|
||||
$this->sorted[$eventName][] = $listener;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->sorted[$eventName];
|
||||
}
|
||||
|
||||
public function hasListeners($eventName)
|
||||
{
|
||||
return !empty($this->listeners[$eventName]);
|
||||
}
|
||||
|
||||
public function emit($eventName, EventInterface $event)
|
||||
{
|
||||
if (isset($this->listeners[$eventName])) {
|
||||
foreach ($this->listeners($eventName) as $listener) {
|
||||
$listener($event, $eventName);
|
||||
if ($event->isPropagationStopped()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $event;
|
||||
}
|
||||
|
||||
public function attach(SubscriberInterface $subscriber)
|
||||
{
|
||||
foreach ($subscriber->getEvents() as $eventName => $listeners) {
|
||||
if (is_array($listeners[0])) {
|
||||
foreach ($listeners as $listener) {
|
||||
$this->on(
|
||||
$eventName,
|
||||
[$subscriber, $listener[0]],
|
||||
isset($listener[1]) ? $listener[1] : 0
|
||||
);
|
||||
}
|
||||
} else {
|
||||
$this->on(
|
||||
$eventName,
|
||||
[$subscriber, $listeners[0]],
|
||||
isset($listeners[1]) ? $listeners[1] : 0
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function detach(SubscriberInterface $subscriber)
|
||||
{
|
||||
foreach ($subscriber->getEvents() as $eventName => $listener) {
|
||||
$this->removeListener($eventName, [$subscriber, $listener[0]]);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,96 +0,0 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Event;
|
||||
|
||||
/**
|
||||
* Guzzle event emitter.
|
||||
*/
|
||||
interface EmitterInterface
|
||||
{
|
||||
/**
|
||||
* Binds a listener to a specific event.
|
||||
*
|
||||
* @param string $eventName Name of the event to bind to.
|
||||
* @param callable $listener Listener to invoke when triggered.
|
||||
* @param int|string $priority The higher this value, the earlier an event
|
||||
* listener will be triggered in the chain (defaults to 0). You can
|
||||
* pass "first" or "last" to dynamically specify the event priority
|
||||
* based on the current event priorities associated with the given
|
||||
* event name in the emitter. Use "first" to set the priority to the
|
||||
* current highest priority plus one. Use "last" to set the priority to
|
||||
* the current lowest event priority minus one.
|
||||
*/
|
||||
public function on($eventName, callable $listener, $priority = 0);
|
||||
|
||||
/**
|
||||
* Binds a listener to a specific event. After the listener is triggered
|
||||
* once, it is removed as a listener.
|
||||
*
|
||||
* @param string $eventName Name of the event to bind to.
|
||||
* @param callable $listener Listener to invoke when triggered.
|
||||
* @param int $priority The higher this value, the earlier an event
|
||||
* listener will be triggered in the chain (defaults to 0)
|
||||
*/
|
||||
public function once($eventName, callable $listener, $priority = 0);
|
||||
|
||||
/**
|
||||
* Removes an event listener from the specified event.
|
||||
*
|
||||
* @param string $eventName The event to remove a listener from
|
||||
* @param callable $listener The listener to remove
|
||||
*/
|
||||
public function removeListener($eventName, callable $listener);
|
||||
|
||||
/**
|
||||
* Gets the listeners of a specific event or all listeners if no event is
|
||||
* specified.
|
||||
*
|
||||
* @param string $eventName The name of the event. Pass null (the default)
|
||||
* to retrieve all listeners.
|
||||
*
|
||||
* @return array The event listeners for the specified event, or all event
|
||||
* listeners by event name. The format of the array when retrieving a
|
||||
* specific event list is an array of callables. The format of the array
|
||||
* when retrieving all listeners is an associative array of arrays of
|
||||
* callables.
|
||||
*/
|
||||
public function listeners($eventName = null);
|
||||
|
||||
/**
|
||||
* Checks if the emitter has listeners by the given name.
|
||||
*
|
||||
* @param string $eventName The name of the event to check.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasListeners($eventName);
|
||||
|
||||
/**
|
||||
* Emits an event to all registered listeners.
|
||||
*
|
||||
* Each event that is bound to the emitted eventName receives a
|
||||
* EventInterface, the name of the event, and the event emitter.
|
||||
*
|
||||
* @param string $eventName The name of the event to dispatch.
|
||||
* @param EventInterface $event The event to pass to the event handlers/listeners.
|
||||
*
|
||||
* @return EventInterface Returns the provided event object
|
||||
*/
|
||||
public function emit($eventName, EventInterface $event);
|
||||
|
||||
/**
|
||||
* Attaches an event subscriber.
|
||||
*
|
||||
* The subscriber is asked for all the events it is interested in and added
|
||||
* as an event listener for each event.
|
||||
*
|
||||
* @param SubscriberInterface $subscriber Subscriber to attach.
|
||||
*/
|
||||
public function attach(SubscriberInterface $subscriber);
|
||||
|
||||
/**
|
||||
* Detaches an event subscriber.
|
||||
*
|
||||
* @param SubscriberInterface $subscriber Subscriber to detach.
|
||||
*/
|
||||
public function detach(SubscriberInterface $subscriber);
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Event;
|
||||
|
||||
/**
|
||||
* A terminal event that is emitted when a request transaction has ended.
|
||||
*
|
||||
* This event is emitted for both successful responses and responses that
|
||||
* encountered an exception. You need to check if an exception is present
|
||||
* in your listener to know the difference.
|
||||
*
|
||||
* You MAY intercept the response associated with the event if needed, but keep
|
||||
* in mind that the "complete" event will not be triggered as a result.
|
||||
*/
|
||||
class EndEvent extends AbstractTransferEvent
|
||||
{
|
||||
/**
|
||||
* Get the exception that was encountered (if any).
|
||||
*
|
||||
* This method should be used to check if the request was sent successfully
|
||||
* or if it encountered errors.
|
||||
*
|
||||
* @return \Exception|null
|
||||
*/
|
||||
public function getException()
|
||||
{
|
||||
return $this->transaction->exception;
|
||||
}
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Event;
|
||||
|
||||
use GuzzleHttp\Exception\RequestException;
|
||||
|
||||
/**
|
||||
* Event emitted when an error occurs while sending a request.
|
||||
*
|
||||
* This event MAY be emitted multiple times. You MAY intercept the exception
|
||||
* and inject a response into the event to rescue the request using the
|
||||
* intercept() method of the event.
|
||||
*
|
||||
* This event allows the request to be retried using the "retry" method of the
|
||||
* event.
|
||||
*/
|
||||
class ErrorEvent extends AbstractRetryableEvent
|
||||
{
|
||||
/**
|
||||
* Get the exception that was encountered
|
||||
*
|
||||
* @return RequestException
|
||||
*/
|
||||
public function getException()
|
||||
{
|
||||
return $this->transaction->exception;
|
||||
}
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Event;
|
||||
|
||||
/**
|
||||
* Base event interface used when dispatching events to listeners using an
|
||||
* event emitter.
|
||||
*/
|
||||
interface EventInterface
|
||||
{
|
||||
/**
|
||||
* Returns whether or not stopPropagation was called on the event.
|
||||
*
|
||||
* @return bool
|
||||
* @see Event::stopPropagation
|
||||
*/
|
||||
public function isPropagationStopped();
|
||||
|
||||
/**
|
||||
* Stops the propagation of the event, preventing subsequent listeners
|
||||
* registered to the same event from being invoked.
|
||||
*/
|
||||
public function stopPropagation();
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Event;
|
||||
|
||||
/**
|
||||
* Holds an event emitter
|
||||
*/
|
||||
interface HasEmitterInterface
|
||||
{
|
||||
/**
|
||||
* Get the event emitter of the object
|
||||
*
|
||||
* @return EmitterInterface
|
||||
*/
|
||||
public function getEmitter();
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Event;
|
||||
|
||||
/**
|
||||
* Trait that implements the methods of HasEmitterInterface
|
||||
*/
|
||||
trait HasEmitterTrait
|
||||
{
|
||||
/** @var EmitterInterface */
|
||||
private $emitter;
|
||||
|
||||
public function getEmitter()
|
||||
{
|
||||
if (!$this->emitter) {
|
||||
$this->emitter = new Emitter();
|
||||
}
|
||||
|
||||
return $this->emitter;
|
||||
}
|
||||
}
|
|
@ -1,88 +0,0 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Event;
|
||||
|
||||
/**
|
||||
* Trait that provides methods for extract event listeners specified in an array
|
||||
* and attaching them to an emitter owned by the object or one of its direct
|
||||
* dependencies.
|
||||
*/
|
||||
trait ListenerAttacherTrait
|
||||
{
|
||||
/**
|
||||
* Attaches event listeners and properly sets their priorities and whether
|
||||
* or not they are are only executed once.
|
||||
*
|
||||
* @param HasEmitterInterface $object Object that has the event emitter.
|
||||
* @param array $listeners Array of hashes representing event
|
||||
* event listeners. Each item contains
|
||||
* "name", "fn", "priority", & "once".
|
||||
*/
|
||||
private function attachListeners(HasEmitterInterface $object, array $listeners)
|
||||
{
|
||||
$emitter = $object->getEmitter();
|
||||
foreach ($listeners as $el) {
|
||||
if ($el['once']) {
|
||||
$emitter->once($el['name'], $el['fn'], $el['priority']);
|
||||
} else {
|
||||
$emitter->on($el['name'], $el['fn'], $el['priority']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the allowed events from the provided array, and ignores anything
|
||||
* else in the array. The event listener must be specified as a callable or
|
||||
* as an array of event listener data ("name", "fn", "priority", "once").
|
||||
*
|
||||
* @param array $source Array containing callables or hashes of data to be
|
||||
* prepared as event listeners.
|
||||
* @param array $events Names of events to look for in the provided $source
|
||||
* array. Other keys are ignored.
|
||||
* @return array
|
||||
*/
|
||||
private function prepareListeners(array $source, array $events)
|
||||
{
|
||||
$listeners = [];
|
||||
foreach ($events as $name) {
|
||||
if (isset($source[$name])) {
|
||||
$this->buildListener($name, $source[$name], $listeners);
|
||||
}
|
||||
}
|
||||
|
||||
return $listeners;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a complete event listener definition from the provided array of
|
||||
* listener data. Also works recursively if more than one listeners are
|
||||
* contained in the provided array.
|
||||
*
|
||||
* @param string $name Name of the event the listener is for.
|
||||
* @param array|callable $data Event listener data to prepare.
|
||||
* @param array $listeners Array of listeners, passed by reference.
|
||||
*
|
||||
* @throws \InvalidArgumentException if the event data is malformed.
|
||||
*/
|
||||
private function buildListener($name, $data, &$listeners)
|
||||
{
|
||||
static $defaults = ['priority' => 0, 'once' => false];
|
||||
|
||||
// If a callable is provided, normalize it to the array format.
|
||||
if (is_callable($data)) {
|
||||
$data = ['fn' => $data];
|
||||
}
|
||||
|
||||
// Prepare the listener and add it to the array, recursively.
|
||||
if (isset($data['fn'])) {
|
||||
$data['name'] = $name;
|
||||
$listeners[] = $data + $defaults;
|
||||
} elseif (is_array($data)) {
|
||||
foreach ($data as $listenerData) {
|
||||
$this->buildListener($name, $listenerData, $listeners);
|
||||
}
|
||||
} else {
|
||||
throw new \InvalidArgumentException('Each event listener must be a '
|
||||
. 'callable or an associative array containing a "fn" key.');
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Event;
|
||||
|
||||
use GuzzleHttp\Transaction;
|
||||
|
||||
/**
|
||||
* Event object emitted when upload or download progress is made.
|
||||
*
|
||||
* You can access the progress values using their corresponding public
|
||||
* properties:
|
||||
*
|
||||
* - $downloadSize: The number of bytes that will be downloaded (if known)
|
||||
* - $downloaded: The number of bytes that have been downloaded
|
||||
* - $uploadSize: The number of bytes that will be uploaded (if known)
|
||||
* - $uploaded: The number of bytes that have been uploaded
|
||||
*/
|
||||
class ProgressEvent extends AbstractRequestEvent
|
||||
{
|
||||
/** @var int Amount of data to be downloaded */
|
||||
public $downloadSize;
|
||||
|
||||
/** @var int Amount of data that has been downloaded */
|
||||
public $downloaded;
|
||||
|
||||
/** @var int Amount of data to upload */
|
||||
public $uploadSize;
|
||||
|
||||
/** @var int Amount of data that has been uploaded */
|
||||
public $uploaded;
|
||||
|
||||
/**
|
||||
* @param Transaction $transaction Transaction being sent.
|
||||
* @param int $downloadSize Amount of data to download (if known)
|
||||
* @param int $downloaded Amount of data that has been downloaded
|
||||
* @param int $uploadSize Amount of data to upload (if known)
|
||||
* @param int $uploaded Amount of data that had been uploaded
|
||||
*/
|
||||
public function __construct(
|
||||
Transaction $transaction,
|
||||
$downloadSize,
|
||||
$downloaded,
|
||||
$uploadSize,
|
||||
$uploaded
|
||||
) {
|
||||
parent::__construct($transaction);
|
||||
$this->downloadSize = $downloadSize;
|
||||
$this->downloaded = $downloaded;
|
||||
$this->uploadSize = $uploadSize;
|
||||
$this->uploaded = $uploaded;
|
||||
}
|
||||
}
|
|
@ -1,56 +0,0 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Event;
|
||||
|
||||
/**
|
||||
* Contains methods used to manage the request event lifecycle.
|
||||
*/
|
||||
final class RequestEvents
|
||||
{
|
||||
// Generic event priorities
|
||||
const EARLY = 10000;
|
||||
const LATE = -10000;
|
||||
|
||||
// "before" priorities
|
||||
const PREPARE_REQUEST = -100;
|
||||
const SIGN_REQUEST = -10000;
|
||||
|
||||
// "complete" and "error" response priorities
|
||||
const VERIFY_RESPONSE = 100;
|
||||
const REDIRECT_RESPONSE = 200;
|
||||
|
||||
/**
|
||||
* Converts an array of event options into a formatted array of valid event
|
||||
* configuration.
|
||||
*
|
||||
* @param array $options Event array to convert
|
||||
* @param array $events Event names to convert in the options array.
|
||||
* @param mixed $handler Event handler to utilize
|
||||
*
|
||||
* @return array
|
||||
* @throws \InvalidArgumentException if the event config is invalid
|
||||
* @internal
|
||||
*/
|
||||
public static function convertEventArray(
|
||||
array $options,
|
||||
array $events,
|
||||
$handler
|
||||
) {
|
||||
foreach ($events as $name) {
|
||||
if (!isset($options[$name])) {
|
||||
$options[$name] = [$handler];
|
||||
} elseif (is_callable($options[$name])) {
|
||||
$options[$name] = [$options[$name], $handler];
|
||||
} elseif (is_array($options[$name])) {
|
||||
if (isset($options[$name]['fn'])) {
|
||||
$options[$name] = [$options[$name], $handler];
|
||||
} else {
|
||||
$options[$name][] = $handler;
|
||||
}
|
||||
} else {
|
||||
throw new \InvalidArgumentException('Invalid event format');
|
||||
}
|
||||
}
|
||||
|
||||
return $options;
|
||||
}
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Event;
|
||||
|
||||
/**
|
||||
* SubscriberInterface provides an array of events to an
|
||||
* EventEmitterInterface when it is registered. The emitter then binds the
|
||||
* listeners specified by the EventSubscriber.
|
||||
*
|
||||
* This interface is based on the SubscriberInterface of the Symfony.
|
||||
* @link https://github.com/symfony/symfony/tree/master/src/Symfony/Component/EventDispatcher
|
||||
*/
|
||||
interface SubscriberInterface
|
||||
{
|
||||
/**
|
||||
* Returns an array of event names this subscriber wants to listen to.
|
||||
*
|
||||
* The returned array keys MUST map to an event name. Each array value
|
||||
* MUST be an array in which the first element is the name of a function
|
||||
* on the EventSubscriber OR an array of arrays in the aforementioned
|
||||
* format. The second element in the array is optional, and if specified,
|
||||
* designates the event priority.
|
||||
*
|
||||
* For example, the following are all valid:
|
||||
*
|
||||
* - ['eventName' => ['methodName']]
|
||||
* - ['eventName' => ['methodName', $priority]]
|
||||
* - ['eventName' => [['methodName'], ['otherMethod']]
|
||||
* - ['eventName' => [['methodName'], ['otherMethod', $priority]]
|
||||
* - ['eventName' => [['methodName', $priority], ['otherMethod', $priority]]
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getEvents();
|
||||
}
|
|
@ -1,4 +1,37 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Exception;
|
||||
|
||||
class ConnectException extends RequestException {}
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
|
||||
/**
|
||||
* Exception thrown when a connection cannot be established.
|
||||
*
|
||||
* Note that no response is present for a ConnectException
|
||||
*/
|
||||
class ConnectException extends RequestException
|
||||
{
|
||||
public function __construct(
|
||||
$message,
|
||||
RequestInterface $request,
|
||||
\Exception $previous = null,
|
||||
array $handlerContext = []
|
||||
) {
|
||||
parent::__construct($message, $request, null, $previous, $handlerContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return null
|
||||
*/
|
||||
public function getResponse()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function hasResponse()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Exception;
|
||||
|
||||
class CouldNotRewindStreamException extends RequestException {}
|
4
core/vendor/guzzlehttp/guzzle/src/Exception/GuzzleException.php
vendored
Normal file
4
core/vendor/guzzlehttp/guzzle/src/Exception/GuzzleException.php
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Exception;
|
||||
|
||||
interface GuzzleException {}
|
|
@ -1,31 +0,0 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Exception;
|
||||
|
||||
use GuzzleHttp\Message\ResponseInterface;
|
||||
|
||||
/**
|
||||
* Exception when a client is unable to parse the response body as XML or JSON
|
||||
*/
|
||||
class ParseException extends TransferException
|
||||
{
|
||||
/** @var ResponseInterface */
|
||||
private $response;
|
||||
|
||||
public function __construct(
|
||||
$message = '',
|
||||
ResponseInterface $response = null,
|
||||
\Exception $previous = null
|
||||
) {
|
||||
parent::__construct($message, 0, $previous);
|
||||
$this->response = $response;
|
||||
}
|
||||
/**
|
||||
* Get the associated response
|
||||
*
|
||||
* @return ResponseInterface|null
|
||||
*/
|
||||
public function getResponse()
|
||||
{
|
||||
return $this->response;
|
||||
}
|
||||
}
|
|
@ -1,11 +1,9 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Exception;
|
||||
|
||||
use GuzzleHttp\Message\RequestInterface;
|
||||
use GuzzleHttp\Message\ResponseInterface;
|
||||
use GuzzleHttp\Ring\Exception\ConnectException;
|
||||
use GuzzleHttp\Exception\ConnectException as HttpConnectException;
|
||||
use GuzzleHttp\Ring\Future\FutureInterface;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use GuzzleHttp\Promise\PromiseInterface;
|
||||
|
||||
/**
|
||||
* HTTP Request exception
|
||||
|
@ -18,23 +16,28 @@ class RequestException extends TransferException
|
|||
/** @var ResponseInterface */
|
||||
private $response;
|
||||
|
||||
/** @var array */
|
||||
private $handlerContext;
|
||||
|
||||
public function __construct(
|
||||
$message,
|
||||
RequestInterface $request,
|
||||
ResponseInterface $response = null,
|
||||
\Exception $previous = null
|
||||
\Exception $previous = null,
|
||||
array $handlerContext = []
|
||||
) {
|
||||
// Set the code of the exception if the response is set and not future.
|
||||
$code = $response && !($response instanceof FutureInterface)
|
||||
$code = $response && !($response instanceof PromiseInterface)
|
||||
? $response->getStatusCode()
|
||||
: 0;
|
||||
parent::__construct($message, $code, $previous);
|
||||
$this->request = $request;
|
||||
$this->response = $response;
|
||||
$this->handlerContext = $handlerContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap non-RequesExceptions with a RequestException
|
||||
* Wrap non-RequestExceptions with a RequestException
|
||||
*
|
||||
* @param RequestInterface $request
|
||||
* @param \Exception $e
|
||||
|
@ -43,13 +46,9 @@ class RequestException extends TransferException
|
|||
*/
|
||||
public static function wrapException(RequestInterface $request, \Exception $e)
|
||||
{
|
||||
if ($e instanceof RequestException) {
|
||||
return $e;
|
||||
} elseif ($e instanceof ConnectException) {
|
||||
return new HttpConnectException($e->getMessage(), $request, null, $e);
|
||||
} else {
|
||||
return new RequestException($e->getMessage(), $request, null, $e);
|
||||
}
|
||||
return $e instanceof RequestException
|
||||
? $e
|
||||
: new RequestException($e->getMessage(), $request, null, $e);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -58,16 +57,24 @@ class RequestException extends TransferException
|
|||
* @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
|
||||
\Exception $previous = null,
|
||||
array $ctx = []
|
||||
) {
|
||||
if (!$response) {
|
||||
return new self('Error completing request', $request, null, $previous);
|
||||
return new self(
|
||||
'Error completing request',
|
||||
$request,
|
||||
null,
|
||||
$previous,
|
||||
$ctx
|
||||
);
|
||||
}
|
||||
|
||||
$level = floor($response->getStatusCode() / 100);
|
||||
|
@ -82,11 +89,12 @@ class RequestException extends TransferException
|
|||
$className = __CLASS__;
|
||||
}
|
||||
|
||||
$message = $label . ' [url] ' . $request->getUrl()
|
||||
$message = $label . ' [url] ' . $request->getUri()
|
||||
. ' [http method] ' . $request->getMethod()
|
||||
. ' [status code] ' . $response->getStatusCode()
|
||||
. ' [reason phrase] ' . $response->getReasonPhrase();
|
||||
|
||||
return new $className($message, $request, $response, $previous);
|
||||
return new $className($message, $request, $response, $previous, $ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -118,4 +126,19 @@ class RequestException extends TransferException
|
|||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Stream\Exception;
|
||||
namespace GuzzleHttp\Exception;
|
||||
|
||||
use GuzzleHttp\Stream\StreamInterface;
|
||||
use Psr\Http\Message\StreamInterface;
|
||||
|
||||
/**
|
||||
* Exception thrown when a seek fails on a stream.
|
||||
*/
|
||||
class SeekException extends \RuntimeException
|
||||
class SeekException extends \RuntimeException implements GuzzleException
|
||||
{
|
||||
private $stream;
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Exception;
|
||||
|
||||
class StateException extends TransferException {};
|
|
@ -1,4 +1,4 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Exception;
|
||||
|
||||
class TransferException extends \RuntimeException {}
|
||||
class TransferException extends \RuntimeException implements GuzzleException {}
|
||||
|
|
|
@ -1,34 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace GuzzleHttp\Exception;
|
||||
|
||||
use GuzzleHttp\Message\ResponseInterface;
|
||||
|
||||
/**
|
||||
* Exception when a client is unable to parse the response body as XML
|
||||
*/
|
||||
class XmlParseException extends ParseException
|
||||
{
|
||||
/** @var \LibXMLError */
|
||||
protected $error;
|
||||
|
||||
public function __construct(
|
||||
$message = '',
|
||||
ResponseInterface $response = null,
|
||||
\Exception $previous = null,
|
||||
\LibXMLError $error = null
|
||||
) {
|
||||
parent::__construct($message, $response, $previous);
|
||||
$this->error = $error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the associated error
|
||||
*
|
||||
* @return \LibXMLError|null
|
||||
*/
|
||||
public function getError()
|
||||
{
|
||||
return $this->error;
|
||||
}
|
||||
}
|
507
core/vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php
vendored
Normal file
507
core/vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php
vendored
Normal file
|
@ -0,0 +1,507 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Handler;
|
||||
|
||||
use GuzzleHttp\Exception\RequestException;
|
||||
use GuzzleHttp\Exception\ConnectException;
|
||||
use GuzzleHttp\Promise\FulfilledPromise;
|
||||
use GuzzleHttp\Promise\RejectedPromise;
|
||||
use GuzzleHttp\Psr7;
|
||||
use GuzzleHttp\Psr7\LazyOpenStream;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
|
||||
/**
|
||||
* Creates curl resources from a request
|
||||
*/
|
||||
class CurlFactory implements CurlFactoryInterface
|
||||
{
|
||||
/** @var array */
|
||||
private $handles;
|
||||
|
||||
/** @var int Total number of idle handles to keep in cache */
|
||||
private $maxHandles;
|
||||
|
||||
/**
|
||||
* @param int $maxHandles Maximum number of idle handles.
|
||||
*/
|
||||
public function __construct($maxHandles)
|
||||
{
|
||||
$this->maxHandles = $maxHandles;
|
||||
}
|
||||
|
||||
public function create(RequestInterface $request, array $options)
|
||||
{
|
||||
$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']);
|
||||
|
||||
if (isset($options['curl']['body_as_string'])) {
|
||||
$options['_body_as_string'] = $options['curl']['body_as_string'];
|
||||
unset($options['curl']['body_as_string']);
|
||||
}
|
||||
|
||||
// Add handler options from the request configuration options
|
||||
if (isset($options['curl'])) {
|
||||
$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 (!$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 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 new RejectedPromise(
|
||||
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 new RejectedPromise($error);
|
||||
}
|
||||
|
||||
private function getDefaultConf(EasyHandle $easy)
|
||||
{
|
||||
$conf = [
|
||||
'_headers' => $easy->request->getHeaders(),
|
||||
CURLOPT_CUSTOMREQUEST => $easy->request->getMethod(),
|
||||
CURLOPT_URL => (string) $easy->request->getUri(),
|
||||
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();
|
||||
$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'])) {
|
||||
$conf[CURLOPT_CAINFO] = $options['verify'];
|
||||
if (!file_exists($options['verify'])) {
|
||||
throw new \InvalidArgumentException(
|
||||
"SSL CA bundle not found: {$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]);
|
||||
}
|
||||
|
||||
if (isset($options['timeout'])) {
|
||||
$conf[CURLOPT_TIMEOUT_MS] = $options['timeout'] * 1000;
|
||||
}
|
||||
|
||||
if (isset($options['connect_timeout'])) {
|
||||
$conf[CURLOPT_CONNECTTIMEOUT_MS] = $options['connect_timeout'] * 1000;
|
||||
}
|
||||
|
||||
if (isset($options['proxy'])) {
|
||||
if (!is_array($options['proxy'])) {
|
||||
$conf[CURLOPT_PROXY] = $options['proxy'];
|
||||
} elseif ($scheme = $easy->request->getUri()->getScheme()) {
|
||||
if (isset($options['proxy'][$scheme])) {
|
||||
$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 = null;
|
||||
} elseif (!is_callable($easy->options['on_headers'])) {
|
||||
throw new \InvalidArgumentException('on_headers must be callable');
|
||||
} else {
|
||||
$onHeaders = $easy->options['on_headers'];
|
||||
}
|
||||
|
||||
return function ($ch, $h) use (
|
||||
$onHeaders,
|
||||
$easy,
|
||||
&$startingResponse
|
||||
) {
|
||||
$value = trim($h);
|
||||
if ($value === '') {
|
||||
$startingResponse = true;
|
||||
$easy->createResponse();
|
||||
if ($onHeaders) {
|
||||
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);
|
||||
};
|
||||
}
|
||||
}
|
27
core/vendor/guzzlehttp/guzzle/src/Handler/CurlFactoryInterface.php
vendored
Normal file
27
core/vendor/guzzlehttp/guzzle/src/Handler/CurlFactoryInterface.php
vendored
Normal file
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Handler;
|
||||
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
|
||||
interface CurlFactoryInterface
|
||||
{
|
||||
/**
|
||||
* Creates a cURL handle resource.
|
||||
*
|
||||
* @param RequestInterface $request Request
|
||||
* @param array $options Transfer options
|
||||
*
|
||||
* @return EasyHandle
|
||||
* @throws \RuntimeException when an option cannot be applied
|
||||
*/
|
||||
public function create(RequestInterface $request, array $options);
|
||||
|
||||
/**
|
||||
* Release an easy handle, allowing it to be reused or closed.
|
||||
*
|
||||
* This function must call unset on the easy handle's "handle" property.
|
||||
*
|
||||
* @param EasyHandle $easy
|
||||
*/
|
||||
public function release(EasyHandle $easy);
|
||||
}
|
45
core/vendor/guzzlehttp/guzzle/src/Handler/CurlHandler.php
vendored
Normal file
45
core/vendor/guzzlehttp/guzzle/src/Handler/CurlHandler.php
vendored
Normal file
|
@ -0,0 +1,45 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Handler;
|
||||
|
||||
use GuzzleHttp\Psr7;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
|
||||
/**
|
||||
* HTTP handler that uses cURL easy handles as a transport layer.
|
||||
*
|
||||
* When using the CurlHandler, custom curl options can be specified as an
|
||||
* associative array of curl option constants mapping to values in the
|
||||
* **curl** key of the "client" key of the request.
|
||||
*/
|
||||
class CurlHandler
|
||||
{
|
||||
/** @var CurlFactoryInterface */
|
||||
private $factory;
|
||||
|
||||
/**
|
||||
* Accepts an associative array of options:
|
||||
*
|
||||
* - factory: Optional curl factory used to create cURL handles.
|
||||
*
|
||||
* @param array $options Array of options to use with the handler
|
||||
*/
|
||||
public function __construct(array $options = [])
|
||||
{
|
||||
$this->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);
|
||||
}
|
||||
}
|
197
core/vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php
vendored
Normal file
197
core/vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php
vendored
Normal file
|
@ -0,0 +1,197 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Handler;
|
||||
|
||||
use GuzzleHttp\Promise as P;
|
||||
use GuzzleHttp\Promise\Promise;
|
||||
use GuzzleHttp\Psr7;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
|
||||
/**
|
||||
* Returns an asynchronous response using curl_multi_* functions.
|
||||
*
|
||||
* When using the CurlMultiHandler, custom curl options can be specified as an
|
||||
* associative array of curl option constants mapping to values in the
|
||||
* **curl** key of the provided request options.
|
||||
*
|
||||
* @property resource $_mh Internal use only. Lazy loaded multi-handle.
|
||||
*/
|
||||
class CurlMultiHandler
|
||||
{
|
||||
/** @var CurlFactoryInterface */
|
||||
private $factory;
|
||||
private $selectTimeout;
|
||||
private $active;
|
||||
private $handles = [];
|
||||
private $delays = [];
|
||||
|
||||
/**
|
||||
* This handler accepts the following options:
|
||||
*
|
||||
* - handle_factory: An optional factory used to create curl handles
|
||||
* - select_timeout: Optional timeout (in seconds) to block before timing
|
||||
* out while selecting curl handles. Defaults to 1 second.
|
||||
*
|
||||
* @param array $options
|
||||
*/
|
||||
public function __construct(array $options = [])
|
||||
{
|
||||
$this->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, $currentTime - $nextTime);
|
||||
}
|
||||
}
|
87
core/vendor/guzzlehttp/guzzle/src/Handler/EasyHandle.php
vendored
Normal file
87
core/vendor/guzzlehttp/guzzle/src/Handler/EasyHandle.php
vendored
Normal file
|
@ -0,0 +1,87 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Handler;
|
||||
|
||||
use GuzzleHttp\Psr7\Response;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\StreamInterface;
|
||||
|
||||
/**
|
||||
* Represents a cURL easy handle and the data it populates.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
final class EasyHandle
|
||||
{
|
||||
/** @var resource cURL resource */
|
||||
public $handle;
|
||||
|
||||
/** @var StreamInterface Where data is being written */
|
||||
public $sink;
|
||||
|
||||
/** @var array Received HTTP headers so far */
|
||||
public $headers = [];
|
||||
|
||||
/** @var ResponseInterface Received response (if any) */
|
||||
public $response;
|
||||
|
||||
/** @var RequestInterface Request being sent */
|
||||
public $request;
|
||||
|
||||
/** @var array Request options */
|
||||
public $options = [];
|
||||
|
||||
/** @var int cURL error number (if any) */
|
||||
public $errno = 0;
|
||||
|
||||
/** @var \Exception Exception during on_headers (if any) */
|
||||
public $onHeadersException;
|
||||
|
||||
/**
|
||||
* Attach a response to the easy handle based on the received headers.
|
||||
*
|
||||
* @throws \RuntimeException if no headers have been received.
|
||||
*/
|
||||
public function createResponse()
|
||||
{
|
||||
if (empty($this->headers)) {
|
||||
throw new \RuntimeException('No headers have been received');
|
||||
}
|
||||
|
||||
// HTTP-version SP status-code SP reason-phrase
|
||||
$startLine = explode(' ', array_shift($this->headers), 3);
|
||||
$headers = \GuzzleHttp\headers_from_lines($this->headers);
|
||||
$normalizedKeys = \GuzzleHttp\normalize_header_keys($headers);
|
||||
|
||||
if (!empty($this->options['decode_content'])
|
||||
&& isset($normalizedKeys['content-encoding'])
|
||||
) {
|
||||
unset($headers[$normalizedKeys['content-encoding']]);
|
||||
if (isset($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]) ? (int) $startLine[2] : null
|
||||
);
|
||||
}
|
||||
|
||||
public function __get($name)
|
||||
{
|
||||
$msg = $name === 'handle'
|
||||
? 'The EasyHandle has been released'
|
||||
: 'Invalid property: ' . $name;
|
||||
throw new \BadMethodCallException($msg);
|
||||
}
|
||||
}
|
152
core/vendor/guzzlehttp/guzzle/src/Handler/MockHandler.php
vendored
Normal file
152
core/vendor/guzzlehttp/guzzle/src/Handler/MockHandler.php
vendored
Normal file
|
@ -0,0 +1,152 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Handler;
|
||||
|
||||
use GuzzleHttp\HandlerStack;
|
||||
use GuzzleHttp\Promise\PromiseInterface;
|
||||
use GuzzleHttp\Promise\RejectedPromise;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
/**
|
||||
* Handler that returns responses or throw exceptions from a queue.
|
||||
*/
|
||||
class MockHandler implements \Countable
|
||||
{
|
||||
private $queue;
|
||||
private $lastRequest;
|
||||
private $lastOptions;
|
||||
private $onFulfilled;
|
||||
private $onRejected;
|
||||
|
||||
/**
|
||||
* Creates a new MockHandler that uses the default handler stack list of
|
||||
* middlewares.
|
||||
*
|
||||
* @param array $queue Array of responses, callables, or exceptions.
|
||||
* @param callable $onFulfilled Callback to invoke when the return value is fulfilled.
|
||||
* @param callable $onRejected Callback to invoke when the return value is rejected.
|
||||
*
|
||||
* @return MockHandler
|
||||
*/
|
||||
public static function createWithMiddleware(
|
||||
array $queue = null,
|
||||
callable $onFulfilled = null,
|
||||
callable $onRejected = null
|
||||
) {
|
||||
return HandlerStack::create(new self($queue, $onFulfilled, $onRejected));
|
||||
}
|
||||
|
||||
/**
|
||||
* The passed in value must be an array of
|
||||
* {@see Psr7\Http\Message\ResponseInterface} objects, Exceptions,
|
||||
* callables, or Promises.
|
||||
*
|
||||
* @param array $queue
|
||||
* @param callable $onFulfilled Callback to invoke when the return value is fulfilled.
|
||||
* @param callable $onRejected Callback to invoke when the return value is rejected.
|
||||
*/
|
||||
public function __construct(
|
||||
array $queue = null,
|
||||
callable $onFulfilled = null,
|
||||
callable $onRejected = null
|
||||
) {
|
||||
$this->onFulfilled = $onFulfilled;
|
||||
$this->onRejected = $onRejected;
|
||||
|
||||
if ($queue) {
|
||||
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 (is_callable($response)) {
|
||||
$response = $response($request, $options);
|
||||
}
|
||||
|
||||
$response = $response instanceof \Exception
|
||||
? new RejectedPromise($response)
|
||||
: \GuzzleHttp\Promise\promise_for($response);
|
||||
|
||||
if (!$this->onFulfilled && !$this->onRejected) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
return $response->then(
|
||||
function ($value) {
|
||||
if ($this->onFulfilled) {
|
||||
call_user_func($this->onFulfilled, $value);
|
||||
}
|
||||
return $value;
|
||||
},
|
||||
function ($reason) {
|
||||
if ($this->onRejected) {
|
||||
call_user_func($this->onRejected, $reason);
|
||||
}
|
||||
return new RejectedPromise($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 RequestInterface
|
||||
*/
|
||||
public function getLastOptions()
|
||||
{
|
||||
return $this->lastOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of remaining items in the queue.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function count()
|
||||
{
|
||||
return count($this->queue);
|
||||
}
|
||||
}
|
54
core/vendor/guzzlehttp/guzzle/src/Handler/Proxy.php
vendored
Normal file
54
core/vendor/guzzlehttp/guzzle/src/Handler/Proxy.php
vendored
Normal file
|
@ -0,0 +1,54 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Handler;
|
||||
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
|
||||
/**
|
||||
* Provides basic proxies for handlers.
|
||||
*/
|
||||
class Proxy
|
||||
{
|
||||
/**
|
||||
* Sends synchronous requests to a specific handler while sending all other
|
||||
* requests to another handler.
|
||||
*
|
||||
* @param callable $default Handler used for normal responses
|
||||
* @param callable $sync Handler used for synchronous responses.
|
||||
*
|
||||
* @return callable Returns the composed handler.
|
||||
*/
|
||||
public static function wrapSync(
|
||||
callable $default,
|
||||
callable $sync
|
||||
) {
|
||||
return function (RequestInterface $request, array $options) use ($default, $sync) {
|
||||
return empty($options['sync'])
|
||||
? $default($request, $options)
|
||||
: $sync($request, $options);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends streaming requests to a streaming compatible handler while sending
|
||||
* all other requests to a default handler.
|
||||
*
|
||||
* This, for example, could be useful for taking advantage of the
|
||||
* performance benefits of curl while still supporting true streaming
|
||||
* through the StreamHandler.
|
||||
*
|
||||
* @param callable $default Handler used for non-streaming responses
|
||||
* @param callable $streaming Handler used for streaming responses
|
||||
*
|
||||
* @return callable Returns the composed handler.
|
||||
*/
|
||||
public static function wrapStreaming(
|
||||
callable $default,
|
||||
callable $streaming
|
||||
) {
|
||||
return function (RequestInterface $request, array $options) use ($default, $streaming) {
|
||||
return empty($options['stream'])
|
||||
? $default($request, $options)
|
||||
: $streaming($request, $options);
|
||||
};
|
||||
}
|
||||
}
|
411
core/vendor/guzzlehttp/guzzle/src/Handler/StreamHandler.php
vendored
Normal file
411
core/vendor/guzzlehttp/guzzle/src/Handler/StreamHandler.php
vendored
Normal file
|
@ -0,0 +1,411 @@
|
|||
<?php
|
||||
namespace GuzzleHttp\Handler;
|
||||
|
||||
use GuzzleHttp\Exception\RequestException;
|
||||
use GuzzleHttp\Exception\ConnectException;
|
||||
use GuzzleHttp\Promise\FulfilledPromise;
|
||||
use GuzzleHttp\Promise\RejectedPromise;
|
||||
use GuzzleHttp\Promise\PromiseInterface;
|
||||
use GuzzleHttp\Psr7;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use Psr\Http\Message\StreamInterface;
|
||||
|
||||
/**
|
||||
* HTTP handler that uses PHP's HTTP stream wrapper.
|
||||
*/
|
||||
class StreamHandler
|
||||
{
|
||||
private $lastHeaders = [];
|
||||
|
||||
/**
|
||||
* Sends an HTTP request.
|
||||
*
|
||||
* @param RequestInterface $request Request to send.
|
||||
* @param array $options Request transfer options.
|
||||
*
|
||||
* @return PromiseInterface
|
||||
*/
|
||||
public function __invoke(RequestInterface $request, array $options)
|
||||
{
|
||||
// Sleep if there is a delay specified.
|
||||
if (isset($options['delay'])) {
|
||||
usleep($options['delay'] * 1000);
|
||||
}
|
||||
|
||||
try {
|
||||
// Does not support the expect header.
|
||||
$request = $request->withoutHeader('Expect');
|
||||
$stream = $this->createStream($request, $options);
|
||||
return $this->createResponse($request, $options, $stream);
|
||||
} 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);
|
||||
}
|
||||
return new RejectedPromise(
|
||||
RequestException::wrapException($request, $e)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private function createResponse(
|
||||
RequestInterface $request,
|
||||
array $options,
|
||||
$stream
|
||||
) {
|
||||
$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 = $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 new RejectedPromise($ex);
|
||||
}
|
||||
}
|
||||
|
||||
if ($sink !== $stream) {
|
||||
$this->drain($stream, $sink);
|
||||
}
|
||||
|
||||
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\Stream(Psr7\try_fopen($sink, 'r+'))
|
||||
: 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)
|
||||
);
|
||||
// Remove content-encoding header
|
||||
unset($headers[$normalizedKeys['content-encoding']]);
|
||||
// Fix content-length header
|
||||
if (isset($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
|
||||
*
|
||||
* @return StreamInterface
|
||||
* @throws \RuntimeException when the sink option is invalid.
|
||||
*/
|
||||
private function drain(StreamInterface $source, StreamInterface $sink)
|
||||
{
|
||||
Psr7\copy_to_stream($source, $sink);
|
||||
$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']
|
||||
);
|
||||
}
|
||||
|
||||
$context = $this->createResource(
|
||||
function () use ($context, $params) {
|
||||
return stream_context_create($context, $params);
|
||||
}
|
||||
);
|
||||
|
||||
return $this->createResource(
|
||||
function () use ($request, &$http_response_header, $context) {
|
||||
$resource = fopen($request->getUri(), 'r', null, $context);
|
||||
$this->lastHeaders = $http_response_header;
|
||||
return $resource;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
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])) {
|
||||
$options['http']['proxy'] = $value[$scheme];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function add_timeout(RequestInterface $request, &$options, $value, &$params)
|
||||
{
|
||||
$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;
|
||||
return;
|
||||
} else {
|
||||
throw new \InvalidArgumentException('Invalid verify request option');
|
||||
}
|
||||
|
||||
$options['ssl']['verify_peer'] = 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();
|
||||
$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);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
272
core/vendor/guzzlehttp/guzzle/src/HandlerStack.php
vendored
Normal file
272
core/vendor/guzzlehttp/guzzle/src/HandlerStack.php
vendored
Normal file
|
@ -0,0 +1,272 @@
|
|||
<?php
|
||||
namespace GuzzleHttp;
|
||||
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
|
||||
/**
|
||||
* Creates a composed Guzzle handler function by stacking middlewares on top of
|
||||
* an HTTP handler function.
|
||||
*/
|
||||
class HandlerStack
|
||||
{
|
||||
/** @var callable */
|
||||
private $handler;
|
||||
|
||||
/** @var array */
|
||||
private $stack = [];
|
||||
|
||||
/** @var callable|null */
|
||||
private $cached;
|
||||
|
||||
/**
|
||||
* Creates a default handler stack that can be used by clients.
|
||||
*
|
||||
* The returned handler will wrap the provided handler or use the most
|
||||
* appropriate default handler for you system. The returned HandlerStack has
|
||||
* support for cookies, redirects, HTTP error exceptions, and preparing a body
|
||||
* before sending.
|
||||
*
|
||||
* The returned handler stack can be passed to a client in the "handler"
|
||||
* option.
|
||||
*
|
||||
* @param callable $handler HTTP handler function to use with the stack. If no
|
||||
* handler is provided, the best handler for your
|
||||
* system will be utilized.
|
||||
*
|
||||
* @return HandlerStack
|
||||
*/
|
||||
public static function create(callable $handler = null)
|
||||
{
|
||||
$stack = new self($handler ?: choose_handler());
|
||||
$stack->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)
|
||||
{
|
||||
if (!$this->cached) {
|
||||
$this->cached = $this->resolve();
|
||||
}
|
||||
|
||||
$handler = $this->cached;
|
||||
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 (!($prev = $this->handler)) {
|
||||
throw new \LogicException('No handler has been specified');
|
||||
}
|
||||
|
||||
foreach (array_reverse($this->stack) as $fn) {
|
||||
$prev = $fn[0]($prev);
|
||||
}
|
||||
|
||||
return $prev;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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) . ')';
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Reference in a new issue