Update to Drupal 8.0.0 beta 14. For more information, see https://drupal.org/node/2544542

This commit is contained in:
Pantheon Automation 2015-08-27 12:03:05 -07:00 committed by Greg Anderson
parent 3b2511d96d
commit 81ccda77eb
2155 changed files with 54307 additions and 46870 deletions

View file

@ -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

View file

@ -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());
}
}

View file

@ -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'));
}
}

View file

@ -0,0 +1 @@
foo

View file

@ -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
---------------------

View file

@ -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"
}
}
}