.gitignore 0000644 00000000357 15174272742 0006554 0 ustar 00 # Ingore common cruft
.DS_STORE
coverage
# Ignore binary files
guzzle.phar
guzzle-min.phar
# Ignore potentially sensitive phpunit file
phpunit.xml
# Ignore composer generated files
composer.phar
composer.lock
composer-test.lock
vendor/
.travis.yml 0000644 00000001321 15174272742 0006665 0 ustar 00 language: php
php:
- 5.3
- 5.4
before_script:
- curl --version
- echo 'Installing pecl_http'
- wget --quiet http://pecl.php.net/get/pecl_http-1.7.4.tgz
- tar -xzf pecl_http-1.7.4.tgz
- sh -c "cd pecl_http-1.7.4 && phpize && ./configure && make && sudo make install"
- echo "extension=http.so" >> `php --ini | grep "Loaded Configuration" | sed -e "s|.*:\s*||"`
- echo 'Installing composer'
- wget --quiet http://getcomposer.org/composer.phar
- php composer.phar install --dev
- cp phpunit.xml.dist phpunit.xml
- echo 'Ensuring the correct version of node is running'
- ~/.nvm/nvm.sh install v0.6.14
- ~/.nvm/nvm.sh run v0.6.14 tests/Guzzle/Tests/Http/server.js &
script: sudo phpunit --debug
CHANGELOG.md 0000644 00000014276 15174272742 0006402 0 ustar 00 CHANGELOG
=========
* 2.6.4 (05-30-2012)
* BC: Cleaning up how POST files are stored in EntityEnclosingRequest objects. Adding PostFile class.
* BC: Moving ApiCommand specific functionality from the Inspector and on to the ApiCommand
* Bug: Fixing magic method command calls on clients
* Bug: Email constraint only validates strings
* Bug: Aggregate POST fields when POST files are present in curl handle
* Bug: Fixing default User-Agent header
* Bug: Only appending or prepending parameters in commands if they are specified
* Bug: Not requiring response reason phrases or status codes to match a predefined list of codes
* Allowing the use of dot notation for class namespaces when using instance_of constraint
* Added any_match validation constraint
* Added an AsyncPlugin
* Passing request object to the calculateWait method of the ExponentialBackoffPlugin
* Allowing the result of a command object to be changed
* Parsing location and type sub values when instantiating a service description rather than over and over at runtime
* 2.6.3 (05-23-2012)
* [BC] Guzzle\Common\FromConfigInterface no longer requires any config options.
* [BC] Refactoring how POST files are stored on an EntityEnclosingRequest. They are now separate from POST fields.
* You can now use an array of data when creating PUT request bodies in the request factory.
* Removing the requirement that HTTPS requests needed a Cache-Control: public directive to be cacheable.
* [Http] Adding support for Content-Type in multipart POST uploads per upload
* [Http] Added support for uploading multiple files using the same name (foo[0], foo[1])
* Adding more POST data operations for easier manipulation of POST data.
* You can now set empty POST fields.
* The body of a request is only shown on EntityEnclosingRequest objects that do not use POST files.
* Split the Guzzle\Service\Inspector::validateConfig method into two methods. One to initialize when a command is created, and one to validate.
* CS updates
* 2.6.2 (05-19-2012)
* [Http] Better handling of nested scope requests in CurlMulti. Requests are now always prepares in the send() method rather than the addRequest() method.
* 2.6.1 (05-19-2012)
* [BC] Removing 'path' support in service descriptions. Use 'uri'.
* [BC] Guzzle\Service\Inspector::parseDocBlock is now protected. Adding getApiParamsForClass() with cache.
* [BC] Removing Guzzle\Common\NullObject. Use https://github.com/mtdowling/NullObject if you need it.
* [BC] Removing Guzzle\Common\XmlElement.
* All commands, both dynamic and concrete, have ApiCommand objects.
* Adding a fix for CurlMulti so that if all of the connections encounter some sort of curl error, then the loop exits.
* Adding checks to EntityEnclosingRequest so that empty POST files and fields are ignored.
* Making the method signature of Guzzle\Service\Builder\ServiceBuilder::factory more flexible.
* 2.6.0 (05-15-2012)
* [BC] Moving Guzzle\Service\Builder to Guzzle\Service\Builder\ServiceBuilder
* [BC] Executing a Command returns the result of the command rather than the command
* [BC] Moving all HTTP parsing logic to Guzzle\Http\Parsers. Allows for faster C implementations if needed.
* [BC] Changing the Guzzle\Http\Message\Response::setProtocol() method to accept a protocol and version in separate args.
* [BC] Moving ResourceIterator* to Guzzle\Service\Resource
* [BC] Completely refactored ResourceIterators to iterate over a cloned command object
* [BC] Moved Guzzle\Http\UriTemplate to Guzzle\Http\Parser\UriTemplate\UriTemplate
* [BC] Guzzle\Guzzle is now deprecated
* Moving Guzzle\Common\Guzzle::inject to Guzzle\Common\Collection::inject
* Adding Guzzle\Version class to give version information about Guzzle
* Adding Guzzle\Http\Utils class to provide getDefaultUserAgent() and getHttpDate()
* Adding Guzzle\Curl\CurlVersion to manage caching curl_version() data
* ServiceDescription and ServiceBuilder are now cacheable using similar configs
* Changing the format of XML and JSON service builder configs. Backwards compatible.
* Cleaned up Cookie parsing
* Trimming the default Guzzle User-Agent header
* Adding a setOnComplete() method to Commands that is called when a command completes
* Keeping track of requests that were mocked in the MockPlugin
* Fixed a caching bug in the CacheAdapterFactory
* Inspector objects can be injected into a Command object
* Refactoring a lot of code and tests to be case insensitive when dealing with headers
* Adding Guzzle\Http\Message\HeaderComparison for easy comparison of HTTP headers using a DSL
* Adding the ability to set global option overrides to service builder configs
* Adding the ability to include other service builder config files from within XML and JSON files
* Moving the parseQuery method out of Url and on to QueryString::fromString() as a static factory method.
* 2.5.0 (05-08-2012)
* Major performance improvements
* [BC] Simplifying Guzzle\Common\Collection. Please check to see if you are using features that are now deprecated.
* [BC] Using a custom validation system that allows a flyweight implementation for much faster validation. No longer using Symfony2 Validation component.
* [BC] No longer supporting "{{ }}" for injecting into command or UriTemplates. Use "{}"
* Added the ability to passed parameters to all requests created by a client
* Added callback functionality to the ExponentialBackoffPlugin
* Using microtime in ExponentialBackoffPlugin to allow more granular backoff stategies.
* Rewinding request stream bodies when retrying requests
* Exception is thrown when JSON response body cannot be decoded
* Added configurable magic method calls to clients and commands. This is off by default.
* Fixed a defect that added a hash to every parsed URL part
* Fixed duplicate none generation for OauthPlugin.
* Emitting an event each time a client is generated by a ServiceBuilder
* Using an ApiParams object instead of a Collection for parameters of an ApiCommand
* cache.* request parameters should be renamed to params.cache.*
* Added the ability to set arbitrary curl options on requests (disable_wire, progress, etc). See CurlHandle.
* Added the ability to disable type validation of service descriptions
* ServiceDescriptions and ServiceBuilders are now Serializable
LICENSE 0000644 00000002127 15174272742 0005566 0 ustar 00 Copyright (c) 2011 Michael Dowling, https://github.com/mtdowling
* $q = new \Guzzle\Http\QueryString(array(
* 'value' => array(1, 2, 3)
* ));
* $q->setAggregateFunction(array($q, 'aggregateUsingComma'));
* echo $q; // outputs: ?value=1,2,3
*
*
* @param string $key The name of the query string parameter
* @param array $value The values of the parameter
* @param bool $encodeFields Set to TRUE to encode field names
* @param bool $encodeValues Set to TRUE to encode values
*
* @return array Returns an array of the combined values
*/
public function aggregateUsingComma($key, array $value, $encodeFields = false, $encodeValues = false)
{
return array(
$encodeFields ? rawurlencode($key) : $key => $encodeValues
? implode(',', array_map('rawurlencode', $value))
: implode(',', $value)
);
}
/**
* Aggregate multi-valued parameters using duplicate values in a query string
*
* Example: http://test.com?q=1&q=2
*
* @param string $key The name of the query string parameter
* @param array $value The values of the parameter
* @param bool $encodeFields Set to TRUE to encode field names
* @param bool $encodeValues Set to TRUE to encode values
*
* @return array Returns an array of the combined values
*/
public function aggregateUsingDuplicates($key, array $value, $encodeFields = false, $encodeValues = false)
{
return array(
$encodeFields ? rawurlencode($key) : $key => $encodeValues
? array_map('rawurlencode', $value)
: $value
);
}
/**
* Get the query string field separator
*
* @return string
*/
public function getFieldSeparator()
{
return $this->fieldSeparator;
}
/**
* Get the query string prefix
*
* @return string
*/
public function getPrefix()
{
return $this->prefix;
}
/**
* Get the query string value separator
*
* @return string
*/
public function getValueSeparator()
{
return $this->valueSeparator;
}
/**
* Returns whether or not field names are being urlencoded when converting
* the query string object to a string
*
* @return bool
*/
public function isEncodingFields()
{
return $this->encodeFields;
}
/**
* Returns whether or not values are being urlencoded when converting
* the query string object to a string
*
* @return bool
*/
public function isEncodingValues()
{
return $this->encodeValues;
}
/**
* Provide a function for combining multi-valued query string parameters
* into a single or multiple fields
*
* @param callback|null $callback A function or callback array that accepts
* a $key, $value, $encodeFields, and $encodeValues as arguments and
* returns an associative array containing the combined values. Set
* to null to remove any custom aggregator.
*
* @return QueryString
*
* @see \Guzzle\Http\QueryString::aggregateUsingComma()
*/
public function setAggregateFunction($callback)
{
$this->aggregator = $callback;
}
/**
* Set whether or not field names should be urlencoded when converting
* the query string object to a string
*
* @param bool $encode Set to TRUE to encode field names, FALSE to not encode field names
*
* @return QueryString
*/
public function setEncodeFields($encode)
{
$this->encodeFields = $encode;
return $this;
}
/**
* Set whether or not field values should be urlencoded when converting
* the query string object to a string
*
* @param bool $encode Set to TRUE to encode field values, FALSE to not encode field values
*
* @return QueryString
*/
public function setEncodeValues($encode)
{
$this->encodeValues = $encode;
return $this;
}
/**
* Set the query string separator
*
* @param string $separator The query string separator that will separate fields
*
* @return QueryString
*/
public function setFieldSeparator($separator)
{
$this->fieldSeparator = $separator;
return $this;
}
/**
* Set the query string prefix
*
* @param string $prefix Prefix to use with the query string (e.g. '?')
*
* @return QueryString
*/
public function setPrefix($prefix)
{
$this->prefix = $prefix;
return $this;
}
/**
* Set the query string value separator
*
* @param string $separator The query string separator that will separate values from fields
*
* @return QueryString
*/
public function setValueSeparator($separator)
{
$this->valueSeparator = $separator;
return $this;
}
/**
* Returns an array of url encoded field names and values
*
* @return array
*/
public function urlEncode()
{
return $this->encodeData($this->data, $this->encodeFields, $this->encodeValues);
}
/**
* Url encode parameter data.
*
* If a parameter value is an array and no aggregator has been set, the
* values of the array will be converted into a PHP compatible form array.
* If an aggregator is set, the values will be converted using the
* aggregator function
*
* @param array $data The data to encode
* @param bool $encodeFields Toggle URL encoding of fields
* @param bool $encodeValues Toggle URL encoding of values
*
* @return array Returns an array of encoded values and keys
*/
protected function encodeData(array $data, $encodeFields = true, $encodeValues = true)
{
if (!$this->aggregator) {
$this->aggregator = array($this, 'aggregateUsingPhp');
}
$temp = array();
foreach ($data as $key => &$value) {
if (is_array($value)) {
$encoded = $this->encodeData($value, $encodeFields, $encodeValues);
$temp = array_merge($temp, call_user_func_array($this->aggregator, array($key, $value, $encodeFields, $encodeValues)));
} else {
if ($encodeValues && is_string($value) || is_numeric($value)) {
$value = rawurlencode($value);
}
if ($encodeFields) {
$temp[rawurlencode($key)] = $value;
} else {
$temp[$key] = $value;
}
}
}
return $temp;
}
}
src/Guzzle/Http/Url.php 0000644 00000031507 15174272742 0011026 0 ustar 00 parseUrl($url);
// Convert the query string into a QueryString object
if ($parts['query']) {
$parts['query'] = QueryString::fromString($parts['query']);
}
return new self($parts['scheme'], $parts['host'], $parts['user'],
$parts['pass'], $parts['port'], $parts['path'], $parts['query'],
$parts['fragment']);
}
/**
* Build a URL from parse_url parts. The generated URL will be a relative
* URL if a scheme or host are not provided.
*
* @param array $parts Array of parse_url parts
*
* @return string
*/
public static function buildUrl(array $parts)
{
$url = $scheme = '';
if (isset($parts['scheme'])) {
$scheme = $parts['scheme'];
$url .= $scheme . '://';
}
if (isset($parts['host'])) {
if (isset($parts['user'])) {
$url .= $parts['user'];
if (isset($parts['pass'])) {
$url .= ':' . $parts['pass'];
}
$url .= '@';
}
$url .= $parts['host'];
// Only include the port if it is not the default port of the scheme
if (isset($parts['port'])
&& !(($scheme == 'http' && $parts['port'] == 80)
|| ($scheme == 'https' && $parts['port'] == 443))) {
$url .= ':' . $parts['port'];
}
}
if (empty($parts['path'])) {
$url .= '/';
} else {
if ($parts['path'][0] != '/') {
$url .= '/';
}
$url .= $parts['path'];
}
// Add the query string if present
if (!empty($parts['query'])) {
if ($parts['query'][0] != '?') {
$url .= array_key_exists('query_prefix', $parts)
? $parts['query_prefix'] : '?';
}
$url .= $parts['query'];
}
// Ensure that # is only added to the url if fragment contains anything.
if (isset($parts['fragment']) && !empty($parts['fragment'])) {
$url .= '#' . $parts['fragment'];
}
return $url;
}
/**
* Create a new URL from URL parts
*
* @param string $scheme Scheme of the URL
* @param string $host Host of the URL
* @param string $username Username of the URL
* @param string $password Password of the URL
* @param int $port Port of the URL
* @param string $path Path of the URL
* @param QueryString|array|string $query Query string of the URL
* @param string $fragment Fragment of the URL
*/
public function __construct($scheme, $host, $username = null, $password = null, $port = null, $path = null, QueryString $query = null, $fragment = null)
{
$this->scheme = $scheme;
$this->host = $host;
$this->port = $port;
$this->username = $username;
$this->password = $password;
$this->fragment = $fragment;
$this->setQuery($query ?: new QueryString());
if ($path) {
$this->setPath($path);
}
}
/**
* Clone the URL
*/
public function __clone()
{
$this->query = clone $this->query;
}
/**
* Returns the URL as a URL string
*
* @return string
*/
public function __toString()
{
return self::buildUrl($this->getParts());
}
/**
* Get the parts of the URL as an array
*
* @return array
*/
public function getParts()
{
return array(
'scheme' => $this->scheme,
'user' => $this->username,
'pass' => $this->password,
'host' => $this->host,
'port' => $this->port,
'path' => $this->getPath(),
'query' => (string) $this->query,
'fragment' => $this->fragment,
'query_prefix' => $this->query->getPrefix()
);
}
/**
* Set the host of the request.
*
* @param string $host Host to set (e.g. www.yahoo.com, yahoo.com)
*
* @return Url
*/
public function setHost($host)
{
if (strpos($host, ':') === false) {
$this->host = $host;
} else {
list($host, $port) = explode(':', $host);
$this->host = $host;
$this->setPort($port);
}
return $this;
}
/**
* Get the host part of the URL
*
* @return string
*/
public function getHost()
{
return $this->host;
}
/**
* Set the scheme part of the URL (http, https, ftp, etc)
*
* @param string $scheme Scheme to set
*
* @return Url
*/
public function setScheme($scheme)
{
$this->scheme = $scheme;
return $this;
}
/**
* Get the scheme part of the URL
*
* @return string
*/
public function getScheme()
{
return $this->scheme;
}
/**
* Set the port part of the URL
*
* @param int $port Port to set
*
* @return Url
*/
public function setPort($port)
{
$this->port = $port;
return $this;
}
/**
* Get the port part of the URl. Will return the default port for a given
* scheme if a port has not explicitly been set.
*
* @return int|null
*/
public function getPort()
{
if ($this->port) {
return $this->port;
} elseif ($this->scheme == 'http') {
return 80;
} elseif ($this->scheme == 'https') {
return 443;
}
return null;
}
/**
* Set the path part of the URL
*
* @param array|string $path Path string or array of path segments
*
* @return Url
*/
public function setPath($path)
{
if (is_array($path)) {
$this->path = '/' . implode('/', $path);
} else {
$this->path = $path;
if ($this->path != '*' && substr($this->path, 0, 1) != '/') {
$this->path = '/' . $path;
}
}
return $this;
}
/**
* Normalize the URL so that double slashes and relative paths are removed
*
* @return Url
*/
public function normalizePath()
{
if ($this->path == '*') {
return $this;
}
if ($this->path && $this->path != '/') {
// Replace // and /./ with /
$this->path = str_replace(array('/./', '//'), '/', $this->path);
// Remove trailing relative paths if possible
$segments = $this->getPathSegments();
$totalSegments = count($segments);
$last = end($segments);
$trailingSlash = false;
if ($last === '') {
array_pop($segments);
$trailingSlash = true;
}
while ($last == '..' || $last == '.') {
if ($last == '..') {
array_pop($segments);
$last = array_pop($segments);
}
if ($last == '.' || $last == '') {
$last = array_pop($segments);
}
}
$this->path = implode('/', $segments);
if ($trailingSlash) {
$this->path .= '/';
}
}
// Must always start with a slash
if (substr($this->path, 0, 1) != '/') {
$this->path = '/' . $this->path;
}
return $this;
}
/**
* Add a relative path to the currently set path
*
* @param string $relativePath Relative path to add
*
* @return Url
*/
public function addPath($relativePath)
{
if (!$relativePath || $relativePath == '/') {
return $this;
}
// Add a leading slash if needed
if ($relativePath[0] != '/') {
$relativePath = '/' . $relativePath;
}
return $this->setPath(str_replace('//', '/', $this->getPath() . $relativePath));
}
/**
* Get the path part of the URL
*
* @return string
*/
public function getPath()
{
return $this->path ?: '/';
}
/**
* Get the path segments of the URL as an array
*
* @return array
*/
public function getPathSegments()
{
return array_slice(explode('/', $this->getPath()), 1);
}
/**
* Set the password part of the URL
*
* @param string $password Password to set
*
* @return Url
*/
public function setPassword($password)
{
$this->password = $password;
return $this;
}
/**
* Get the password part of the URL
*
* @return null|string
*/
public function getPassword()
{
return $this->password;
}
/**
* Set the username part of the URL
*
* @param string $username Username to set
*
* @return Url
*/
public function setUsername($username)
{
$this->username = $username;
return $this;
}
/**
* Get the username part of the URl
*
* @return null|string
*/
public function getUsername()
{
return $this->username;
}
/**
* Get the query part of the URL as a QueryString object
*
* @return QueryString
*/
public function getQuery()
{
return $this->query;
}
/**
* Set the query part of the URL
*
* @param QueryString|string|array $query Query to set
*
* @return Url
*/
public function setQuery($query)
{
if (is_string($query)) {
$output = null;
parse_str($query, $output);
$this->query = new QueryString($output);
} elseif (is_array($query)) {
$this->query = new QueryString($query);
} elseif ($query instanceof QueryString) {
$this->query = $query;
}
return $this;
}
/**
* Get the fragment part of the URL
*
* @return null|string
*/
public function getFragment()
{
return $this->fragment;
}
/**
* Set the fragment part of the URL
*
* @param string $fragment Fragment to set
*
* @return Url
*/
public function setFragment($fragment)
{
$this->fragment = $fragment;
return $this;
}
/**
* Check if this is an absolute URL
*
* @return bool
*/
public function isAbsolute()
{
return $this->scheme && $this->host;
}
/**
* Combine the URL with another URL. Every part of the second URL supersede
* the current URL if that part is specified.
*
* @param string $url Relative URL to combine with
*
* @return Url
* @throws InvalidArgumentException
*/
public function combine($url)
{
$absolutePath = $url[0] == '/';
$url = self::factory($url);
if ($url->getScheme()) {
$this->scheme = $url->getScheme();
}
if ($url->getHost()) {
$this->host = $url->getHost();
}
if ($url->getPort()) {
$this->port = $url->getPort();
}
if ($url->getUsername()) {
$this->username = $url->getUsername();
}
if ($url->getPassword()) {
$this->password = $url->getPassword();
}
if ($url->getFragment()) {
$this->fragment = $url->getFragment();
}
if ($absolutePath) {
// Replace the current URL and query if set
if ($url->getPath()) {
$this->path = $url->getPath();
}
if (count($url->getQuery())) {
$this->query = clone $url->getQuery();
}
} else {
// Append to the current path and query string
if ($url->getPath()) {
$this->addPath($url->getPath());
}
if ($url->getQuery()) {
$this->query->merge($url->getQuery());
}
}
return $this;
}
}
src/Guzzle/Http/Utils.php 0000644 00000002071 15174272742 0011356 0 ustar 00 get('version'), PHP_VERSION,
$curl->get('ssl_version')
);
}
return self::$userAgent;
}
}
src/Guzzle/Service/AbstractFactory.php 0000644 00000004747 15174272742 0014046 0 ustar 00 getCacheTtlKey($config);
// Check if a cache was provided
if (isset($options['cache.adapter']) && is_string($config)) {
$adapter = $options['cache.adapter'];
$ttl = isset($options[$cacheTtlKey]) ? $options[$cacheTtlKey] : 3600;
$cacheKey = 'guzzle' . crc32($config);
// Check if the instantiated data is in the cache
$cached = $adapter->fetch($cacheKey);
if ($cached) {
return $cached;
}
}
// Get the name of the class to instantiate for the type of data
$class = $this->getClassName($config);
if ($class) {
$result = $this->getFactory($class)->build($config, $options);
if ($adapter) {
$adapter->save($cacheKey, $result, $ttl);
}
return $result;
}
$this->throwException();
}
/**
* Get the string used to hold cache TTL specific information for the factory
*
* @param mixed $config Config data being loaded
*
* @return string
*/
abstract protected function getCacheTtlKey($config);
/**
* Throw an exception when the abstract factory cannot instantiate anything
*
* @param string $message Message for the exception
*
* @return string
* @throws Exception
*/
abstract protected function throwException($message = '');
/**
* Get the name of a class to instantiate for the type of data provided
*
* @param mixed $config Data to use to determine a class name
*
* @return mixed
*/
abstract protected function getClassName($config);
/**
* Get a factory by object name, or retrieve previously a created factory
*
* @param string $class Name of the factory class to retrieve
*
* @return mixed
*/
protected function getFactory($class)
{
if (!isset($this->factories[$class])) {
$factory = $class;
$this->factories[$class] = new $factory();
}
return $this->factories[$class];
}
}
src/Guzzle/Service/Builder/ArrayServiceBuilderFactory.php 0000644 00000004040 15174272742 0017561 0 ustar 00 &$service) {
$service['params'] = isset($service['params']) ? $service['params'] : array();
// Check if this client builder extends another client
if (!empty($service['extends'])) {
// Make sure that the service it's extending has been defined
if (!isset($services[$service['extends']])) {
throw new ServiceNotFoundException($name . ' is trying to extend a non-existent service: ' . $service['extends']);
}
$service['class'] = empty($service['class'])
? $services[$service['extends']]['class'] : $service['class'];
$extendsParams = isset($services[$service['extends']]['params']) ? $services[$service['extends']]['params'] : false;
if ($extendsParams) {
$service['params'] = array_merge($extendsParams, $service['params']);
}
}
// Overwrite default values with global parameter values
if (!empty($options)) {
$service['params'] = array_merge($service['params'], $options);
}
$service['class'] = !isset($service['class']) ? '' : str_replace('.', '\\', $service['class']);
}
return new $class($services);
}
}
src/Guzzle/Service/Builder/JsonServiceBuilderFactory.php 0000644 00000001066 15174272742 0017421 0 ustar 00 loader) {
$this->loader = new JsonLoader();
}
return ServiceBuilder::factory($this->loader->parseJsonFile($config), $options);
}
}
src/Guzzle/Service/Builder/ServiceBuilder.php 0000644 00000013176 15174272742 0015244 0 ustar 00 build($config, $globalParameters);
}
/**
* Construct a new service builder
*
* @param array $serviceBuilderConfig Service configuration settings:
* - name: Name of the service
* - class: Client class to instantiate using a factory method
* - params: array of key value pair configuration settings for the builder
*/
public function __construct(array $serviceBuilderConfig)
{
$this->builderConfig = $serviceBuilderConfig;
}
/**
* {@inheritdoc}
*/
public static function getAllEvents()
{
return array('service_builder.create_client');
}
/**
* Restores the service builder from JSON
*
* @param string $serialized JSON data to restore from
*/
public function unserialize($serialized)
{
$this->builderConfig = json_decode($serialized, true);
}
/**
* Represents the service builder as a string
*
* @return array
*/
public function serialize()
{
return json_encode($this->builderConfig);
}
/**
* Get a client using a registered builder
*
* @param string $name Name of the registered client to retrieve
* @param bool $throwAway Set to TRUE to not store the client for later retrieval from the ServiceBuilder
*
* @return ClientInterface
* @throws ServiceNotFoundException when a client cannot be found by name
*/
public function get($name, $throwAway = false)
{
if (!isset($this->builderConfig[$name])) {
throw new ServiceNotFoundException('No service is registered as ' . $name);
}
if (!$throwAway && isset($this->clients[$name])) {
return $this->clients[$name];
}
// Convert references to the actual client
foreach ($this->builderConfig[$name]['params'] as $k => &$v) {
if (0 === strpos($v, '{') && strlen($v) - 1 == strrpos($v, '}')) {
$v = $this->get(trim(str_replace(array('{', '}'), '', $v)));
}
}
$client = call_user_func(
array($this->builderConfig[$name]['class'], 'factory'),
$this->builderConfig[$name]['params']
);
if (!$throwAway) {
$this->clients[$name] = $client;
}
// Dispatch an event letting listeners know a client was created
$this->dispatch('service_builder.create_client', array(
'client' => $client
));
return $client;
}
/**
* Register a client by name with the service builder
*
* @param string $name Name of the client to register
* @param mixed $value Service to register
*
* @return ServiceBuilderInterface
*/
public function set($key, $service)
{
$this->builderConfig[$key] = $service;
return $this;
}
/**
* Register a client by name with the service builder
*
* @param string $offset Name of the client to register
* @param ClientInterface $value Client to register
*/
public function offsetSet($offset, $value)
{
$this->set($offset, $value);
}
/**
* Remove a registered client by name
*
* @param string $offset Client to remove by name
*/
public function offsetUnset($offset)
{
unset($this->builderConfig[$offset]);
}
/**
* Check if a client is registered with the service builder by name
*
* @param string $offset Name to check to see if a client exists
*
* @return bool
*/
public function offsetExists($offset)
{
return isset($this->builderConfig[$offset]);
}
/**
* Get a registered client by name
*
* @param string $offset Registered client name to retrieve
*
* @return ClientInterface
*/
public function offsetGet($offset)
{
return $this->get($offset);
}
}
src/Guzzle/Service/Builder/ServiceBuilderAbstractFactory.php 0000644 00000003017 15174272742 0020251 0 ustar 00 throwException('Must pass a file name, array, or SimpleXMLElement');
}
return __NAMESPACE__ . '\\' . $class;
}
}
src/Guzzle/Service/Builder/ServiceBuilderFactoryInterface.php 0000644 00000000715 15174272742 0020410 0 ustar 00 parseXmlFile($config), $options);
}
/**
* Parse an XML document into an array
*
* @param string $filename Path to the file
*
* @return array
*/
protected function parseXmlFile($filename)
{
if ($filename instanceof \SimpleXMLElement) {
$xml = $filename;
} else {
$xml = new \SimpleXMLElement($filename, null, true);
$result = array(
'services' => array()
);
}
// Account for old style service builder config files
if (isset($xml->services)) {
$services = $xml->services->service;
} else {
$services = $xml->clients->client;
}
foreach ($services as $service) {
$row = array();
foreach ($service->param as $param) {
$row[(string) $param->attributes()->name] = (string) $param->attributes()->value;
}
$result['services'][(string) $service->attributes()->name] = array(
'class' => (string) $service->attributes()->class,
'extends' => (string) $service->attributes()->extends,
'params' => $row
);
}
// Include any XML files under the includes elements
if (isset($xml->includes->include)) {
// You can only extend other services when using a file
if ($filename instanceof \SimpleXMLElement) {
throw new ServiceBuilderException('You can not extend other SimpleXMLElement services');
}
foreach ($xml->includes->include as $include) {
$path = (string) $include->attributes()->path;
if ($path[0] != DIRECTORY_SEPARATOR) {
$path = dirname($filename) . DIRECTORY_SEPARATOR . $path;
}
$result = array_merge_recursive($this->parseXmlFile($path), $result);
}
}
// Grab the class name if it's set
if (isset($xml->class)) {
$result['class'] = str_replace('.', '\\', (string) $xml->class);
}
return $result;
}
}
src/Guzzle/Service/Client.php 0000644 00000025301 15174272742 0012156 0 ustar 00 magicMethodBehavior == self::MAGIC_CALL_DISABLED) {
throw new BadMethodCallException(
"Missing method $method. Enable magic calls to use magic methods with command names."
);
}
$args = isset($args[0]) ? $args[0] : array();
$command = $this->getCommand(Inflector::snake($method), $args);
return $this->magicMethodBehavior == self::MAGIC_CALL_RETURN
? $command
: $this->execute($command);
}
/**
* Set the behavior for missing methods
*
* @param int $behavior Behavior to use when a missing method is called.
* - Client::MAGIC_CALL_DISABLED: Disable magic method calls
* - Client::MAGIC_CALL_EXECUTE: Execute commands and return the result
* - Client::MAGIC_CALL_RETURN: Instantiate and return the command
*
* @return Client
*/
public function setMagicCallBehavior($behavior)
{
$this->magicMethodBehavior = (int) $behavior;
return $this;
}
/**
* Get a command by name. First, the client will see if it has a service
* description and if the service description defines a command by the
* supplied name. If no dynamic command is found, the client will look for
* a concrete command class exists matching the name supplied. If neither
* are found, an InvalidArgumentException is thrown.
*
* @param string $name Name of the command to retrieve
* @param array $args Arguments to pass to the command
*
* @return CommandInterface
* @throws InvalidArgumentException if no command can be found by name
*/
public function getCommand($name, array $args = array())
{
// Enable magic method calls on commands if it's enabled on the client
if ($this->magicMethodBehavior) {
$args['command.magic_method_call'] = true;
}
$command = $this->getCommandFactory()->factory($name, $args);
if (!$command) {
throw new InvalidArgumentException("Command was not found matching {$name}");
}
$command->setClient($this);
$this->dispatch('client.command.create', array(
'client' => $this,
'command' => $command
));
return $command;
}
/**
* Set the command factory used to create commands by name
*
* @param CommandFactoryInterface $factory Command factory
*
* @return Client
*/
public function setCommandFactory(CommandFactoryInterface $factory)
{
$this->commandFactory = $factory;
return $this;
}
/**
* Set the resource iterator factory associated with the client
*
* @param ResourceIteratorFactoryInterface $factory Resource iterator factory
*
* @return Client
*/
public function setResourceIteratorFactory(ResourceIteratorFactoryInterface $factory)
{
$this->resourceIteratorFactory = $factory;
return $this;
}
/**
* Get a resource iterator from the client.
*
* @param string|CommandInterface $command Command class or command name.
* @param array $commandOptions Command options used when creating commands.
* @param array $iteratorOptions Iterator options passed to the iterator when it is instantiated.
*
* @return ResourceIteratorInterface
*/
public function getIterator($command, array $commandOptions = null, array $iteratorOptions = array())
{
if (!($command instanceof CommandInterface)) {
$command = $this->getCommand($command, $commandOptions ?: array());
}
return $this->getResourceIteratorFactory()->build($command, $iteratorOptions);
}
/**
* Execute a command and return the response
*
* @param CommandInterface|CommandSet|array $command Command or set to execute
*
* @return mixed Returns the result of the executed command's
* {@see CommandInterface::getResult} method if a CommandInterface is
* passed, or the CommandSet itself if a CommandSet is passed
* @throws InvalidArgumentException if an invalid command is passed
* @throws CommandSetException if a set contains commands associated with other clients
*/
public function execute($command)
{
if ($command instanceof CommandInterface) {
$request = $command->setClient($this)->prepare();
$this->dispatch('command.before_send', array(
'command' => $command
));
// Set the state to new if the command was previously executed
if ($request->getState() !== RequestInterface::STATE_NEW) {
$request->setState(RequestInterface::STATE_NEW);
}
$request->send();
$this->dispatch('command.after_send', array(
'command' => $command
));
return $command->getResult();
} elseif ($command instanceof CommandSet) {
foreach ($command as $c) {
if ($c->getClient() && $c->getClient() !== $this) {
throw new CommandSetException(
'Attempting to run a mixed-Client CommandSet from a ' .
'Client context. Run the set using CommandSet::execute() '
);
}
$c->setClient($this);
}
return $command->execute();
} elseif (is_array($command)) {
return $this->execute(new CommandSet($command));
}
throw new InvalidArgumentException('Invalid command sent to ' . __METHOD__);
}
/**
* Set the service description of the client
*
* @param ServiceDescription $service Service description
* @param bool $updateFactory Set to FALSE to not update the service description based
* command factory if it is not already on the client.
*
* @return Client
*/
public function setDescription(ServiceDescription $service, $updateFactory = true)
{
$this->serviceDescription = $service;
// Add the service description factory to the factory chain if it is not set
if ($updateFactory) {
// Convert non chain factories to a chain factory
if (!($this->getCommandFactory() instanceof CompositeFactory)) {
$this->commandFactory = new CompositeFactory(array($this->commandFactory));
}
// Add a service description factory if one does not already exist
if (!$this->commandFactory->has('Guzzle\\Service\\Command\\Factory\\ServiceDescriptionFactory')) {
// Add the service description factory before the concrete factory
$this->commandFactory->add(new ServiceDescriptionFactory($service), 'Guzzle\\Service\\Command\\Factory\\ConcreteClassFactory');
} else {
// Update an existing service description factory
$factory = $this->commandFactory->find('Guzzle\\Service\\Command\\Factory\\ServiceDescriptionFactory');
$factory->setServiceDescription($service);
}
}
return $this;
}
/**
* Get the service description of the client
*
* @return ServiceDescription|null
*/
public function getDescription()
{
return $this->serviceDescription;
}
/**
* Get the resource iterator factory associated with the client
*
* @return ResourceIteratorFactoryInterface
*/
protected function getResourceIteratorFactory()
{
if (!$this->resourceIteratorFactory) {
// Build the default resource iterator factory if one is not set
$clientClass = get_class($this);
$namespace = substr($clientClass, 0, strrpos($clientClass, '\\')) . '\\Model';
$this->resourceIteratorFactory = new ResourceIteratorClassFactory($namespace);
}
return $this->resourceIteratorFactory;
}
/**
* Get the command factory associated with the client
*
* @return CommandFactoryInterface
*/
protected function getCommandFactory()
{
if (!$this->commandFactory) {
$this->commandFactory = CompositeFactory::getDefaultChain($this);
}
return $this->commandFactory;
}
}
src/Guzzle/Service/ClientInterface.php 0000644 00000007065 15174272742 0014006 0 ustar 00 apiCommand = $apiCommand ?: ApiCommand::fromCommand(get_class($this));
$this->initConfig();
$headers = $this->get('headers');
if (!$headers instanceof Collection) {
$this->set('headers', new Collection((array) $headers));
}
// You can set a command.on_complete option in your parameters as a
// convenience method for setting an onComplete function
$onComplete = $this->get('command.on_complete');
if ($onComplete) {
$this->remove('command.on_complete');
$this->setOnComplete($onComplete);
}
$this->init();
}
/**
* Custom clone behavior
*/
public function __clone()
{
$this->request = null;
$this->result = null;
}
/**
* Enables magic methods for setting parameters.
*
* @param string $method Name of the parameter to set
* @param array $args Arguments to pass to the command
*
* @return AbstractCommand
* @throws BadMethodCallException when a parameter doesn't exist
*/
public function __call($method, $args = null)
{
// Ensure magic method call behavior is enabled
if (!$this->get('command.magic_method_call')) {
throw new BadMethodCallException('Magic method calls are disabled '
. 'for this command. Consider enabling magic method calls by '
. 'setting the command.magic_method_call parameter to true.');
}
if ($args && strpos($method, 'set') === 0) {
// Convert the method into the snake cased parameter key
$key = Inflector::snake(substr($method, 3));
// If the parameter exists, set it
if (array_key_exists($key, $this->apiCommand->getParams())) {
$this->set($key, $args[0]);
return $this;
}
}
// If the method is not a set method, or the parameter doesn't exist, fail
throw new BadMethodCallException("Missing method {$method}.");
}
/**
* Get the short form name of the command
*
* @return string
*/
public function getName()
{
return $this->apiCommand->getName();
}
/**
* Get the API command information about the command
*
* @return ApiCommand
*/
public function getApiCommand()
{
return $this->apiCommand;
}
/**
* Specify a callable to execute when the command completes
*
* @param mixed $callable Callable to execute when the command completes.
* The callable must accept a {@see CommandInterface} object as the
* only argument.
*
* @return Command
* @throws InvalidArgumentException
*/
public function setOnComplete($callable)
{
if (!is_callable($callable)) {
throw new InvalidArgumentException('The onComplete function must be callable');
}
$this->onComplete = $callable;
return $this;
}
/**
* Execute the command and return the result
*
* @return mixed Returns the result of {@see AbstractCommand::execute}
* @throws CommandException if a client has not been associated with the command
*/
public function execute()
{
if (!$this->client) {
throw new CommandException('A Client object must be associated with the command before it can be executed from the context of the command.');
}
return $this->client->execute($this);
}
/**
* Get the client object that will execute the command
*
* @return ClientInterface|null
*/
public function getClient()
{
return $this->client;
}
/**
* Set the client objec that will execute the command
*
* @param ClientInterface $client The client objec that will execute the command
*
* @return Command
*/
public function setClient(ClientInterface $client)
{
$this->client = $client;
return $this;
}
/**
* Get the request object associated with the command
*
* @return RequestInterface
* @throws CommandException if the command has not been executed
*/
public function getRequest()
{
if (!$this->request) {
throw new CommandException('The command must be prepared before retrieving the request');
}
return $this->request;
}
/**
* Get the response object associated with the command
*
* @return Response
* @throws CommandException if the command has not been executed
*/
public function getResponse()
{
if (!$this->isExecuted()) {
throw new CommandException('The command must be executed before retrieving the response');
}
return $this->request->getResponse();
}
/**
* Get the result of the command
*
* @return Response By default, commands return a Response
* object unless overridden in a subclass
* @throws CommandException if the command has not been executed
*/
public function getResult()
{
if (!$this->isExecuted()) {
throw new CommandException('The command must be executed before retrieving the result');
}
if (null === $this->result) {
$this->process();
// Call the onComplete method if one is set
if ($this->onComplete) {
call_user_func($this->onComplete, $this);
}
}
return $this->result;
}
/**
* Set the result of the command
*
* @param mixed $result Result to set
*
* @return self
*/
public function setResult($result)
{
$this->result = $result;
return $this;
}
/**
* Returns TRUE if the command has been prepared for executing
*
* @return bool
*/
public function isPrepared()
{
return $this->request !== null;
}
/**
* Returns TRUE if the command has been executed
*
* @return bool
*/
public function isExecuted()
{
return $this->request !== null && $this->request->getState() == 'complete';
}
/**
* Prepare the command for executing and create a request object.
*
* @return RequestInterface Returns the generated request
* @throws CommandException if a client object has not been set previously
* or in the prepare()
*/
public function prepare()
{
if (!$this->isPrepared()) {
if (!$this->client) {
throw new CommandException('A Client object must be associated with the command before it can be prepared.');
}
// Fail on missing required arguments, and change parameters via filters
$this->apiCommand->validate($this, $this->getInspector());
$this->build();
// Add custom request headers set on the command
$headers = $this->get('headers');
if ($headers && $headers instanceof Collection) {
foreach ($headers as $key => $value) {
$this->request->setHeader($key, $value);
}
}
}
return $this->getRequest();
}
/**
* Get the object that manages the request headers that will be set on any
* outbound requests from the command
*
* @return Collection
*/
public function getRequestHeaders()
{
return $this->get('headers', new Collection());
}
/**
* Set the Inspector to use with the command
*
* @param Inspector $inspector Inspector to use for config validation
*
* @return AbstractCommand
*/
public function setInspector(Inspector $inspector)
{
$this->inspector = $inspector;
return $this;
}
/**
* Get the Inspector used with the Command
*
* @return Inspector
*/
protected function getInspector()
{
if (!$this->inspector) {
$this->inspector = Inspector::getInstance();
}
return $this->inspector;
}
/**
* Initialize the command (hook to be implemented in subclasses)
*/
protected function init() {}
/**
* Create the request object that will carry out the command
*/
abstract protected function build();
/**
* Create the result of the command after the request has been completed.
*
* Sets the result as the response by default. If the response is an XML
* document, this will set the result as a SimpleXMLElement. If the XML
* response is invalid, the result will remain the Response, not XML.
* If an application/json response is received, the result will automat-
* ically become an array.
*/
protected function process()
{
// Uses the response object by default
$this->result = $this->getRequest()->getResponse();
$contentType = $this->result->getContentType();
// Is the body an JSON document? If so, set the result to be an array
if (stripos($contentType, 'json') !== false) {
$body = trim($this->result->getBody(true));
if ($body) {
$decoded = json_decode($body, true);
if (JSON_ERROR_NONE !== json_last_error()) {
throw new JsonException('The response body can not be decoded to JSON', json_last_error());
}
$this->result = $decoded;
}
} if (stripos($contentType, 'xml') !== false) {
// Is the body an XML document? If so, set the result to be a SimpleXMLElement
// If the body is available, then parse the XML
$body = trim($this->result->getBody(true));
if ($body) {
// Silently allow parsing the XML to fail
try {
$xml = new \SimpleXMLElement($body);
$this->result = $xml;
} catch (\Exception $e) {}
}
}
}
/**
* Prepare the default and static settings of the command
*/
protected function initConfig()
{
foreach ($this->apiCommand->getParams() as $name => $arg) {
$currentValue = $this->get($name);
$configValue = $arg->getValue($currentValue);
// If default or static values are set, then this should always be
// updated on the config object
if ($currentValue !== $configValue) {
$this->set($name, $configValue);
}
}
}
}
src/Guzzle/Service/Command/ClosureCommand.php 0000644 00000002425 15174272742 0015233 0 ustar 00 get('closure')) {
throw new InvalidArgumentException('A closure must be passed in the parameters array');
}
}
/**
* {@inheritdoc}
*
* @throws UnexpectedValueException If the closure does not return a request
*/
protected function build()
{
$closure = $this->get('closure');
$this->request = $closure($this, $this->apiCommand);
if (!$this->request || !$this->request instanceof RequestInterface) {
throw new UnexpectedValueException('Closure command did not return a RequestInterface object');
}
}
}
src/Guzzle/Service/Command/CommandInterface.php 0000644 00000007113 15174272742 0015516 0 ustar 00 addCommand($command);
}
}
/**
* Add a command to the set
*
* @param CommandInterface $command Command object to add to the command set
*
* @return CommandSet
*/
public function addCommand(CommandInterface $command)
{
$this->commands[] = $command;
return $this;
}
/**
* Implements Countable
*
* @return int
*/
public function count()
{
return count($this->commands);
}
/**
* Execute the command set
*
* @return CommandSet
* @throws CommandSetException if any of the commands do not have an associated
* {@see ClientInterface} object
*/
public function execute()
{
// Keep a list of all commands with no client
$invalid = array_filter($this->commands, function($command) {
return !$command->getClient();
});
// If any commands do not have a client, then throw an exception
if (count($invalid)) {
$e = new CommandSetException('Commands found with no associated client');
$e->setCommands($invalid);
throw $e;
}
// Execute all batched commands in parallel
if (count($this->commands)) {
$multis = array();
// Prepare each request and send out client notifications
foreach ($this->commands as $command) {
$request = $command->prepare();
$request->getParams()->set('command', $command);
$request->getEventDispatcher()->addListener('request.complete', array($this, 'update'), -99999);
$command->getClient()->dispatch('command.before_send', array(
'command' => $command
));
$command->getClient()->getCurlMulti()->add($command->getRequest());
if (!in_array($command->getClient()->getCurlMulti(), $multis)) {
$multis[] = $command->getClient()->getCurlMulti();
}
}
foreach ($multis as $multi) {
$multi->send();
}
}
return $this;
}
/**
* Implements IteratorAggregate
*
* @return ArrayIterator
*/
public function getIterator()
{
return new \ArrayIterator($this->commands);
}
/**
* Get all of the attached commands
*
* @return array
*/
public function getCommands()
{
return $this->commands;
}
/**
* Check if the set contains a specific command
*
* @param string|CommandInterface $command Command object class name or
* concrete CommandInterface object
*
* @return bool
*/
public function hasCommand($command)
{
return (bool) (count(array_filter($this->commands, function($value) use ($command) {
return is_string($command) ? ($value instanceof $command) : ($value === $command);
})) > 0);
}
/**
* Remove a command from the set
*
* @param string|CommandInterface $command The command object or command
* class name to remove
*
* @return CommandSet
*/
public function removeCommand($command)
{
$this->commands = array_values(array_filter($this->commands, function($value) use ($command) {
return is_string($command) ? !($value instanceof $command) : ($value !== $command);
}));
return $this;
}
/**
* Trigger the result of the command to be created as commands complete and
* make sure the command isn't going to send more requests
*
* {@inheritdoc}
*/
public function update(Event $event)
{
$request = $event['request'];
$command = $request->getParams()->get('command');
if ($command && $command->isExecuted()) {
$request = $event['request'];
$request->getEventDispatcher()->removeListener('request.complete', $this);
$request->getParams()->remove('command');
// Force the result to be processed
$command->getResult();
$command->getClient()->dispatch('command.after_send', array(
'command' => $command
));
}
}
}
src/Guzzle/Service/Command/DynamicCommand.php 0000644 00000005100 15174272742 0015174 0 ustar 00 apiCommand->getUri()) {
$url = $this->getClient()->getBaseUrl();
} else {
// Get the path values and use the client config settings
$variables = $this->getClient()->getConfig()->getAll();
foreach ($this->apiCommand->getParams() as $name => $arg) {
$configValue = $this->get($name);
if (is_scalar($configValue)) {
$variables[$name] = $arg->getPrepend() . $configValue . $arg->getAppend();
}
}
// Expand the URI template using the URI values
$uri = ParserRegistry::get('uri_template')->expand($this->apiCommand->getUri(), $variables);
// Merge the client's base URL with the URI template
$url = Url::factory($this->getClient()->getBaseUrl());
$url->combine($uri);
$url = (string) $url;
}
// Inject path and base_url values into the URL
$this->request = $this->getClient()->createRequest($this->apiCommand->getMethod(), $url);
// Add arguments to the request using the location attribute
foreach ($this->apiCommand->getParams() as $name => $arg) {
$configValue = $this->get($name);
$location = $arg->getLocation();
if (!$configValue || !$location) {
continue;
}
// Create the value based on prepend and append settings
if ($arg->getPrepend() || $arg->getAppend()) {
$value = $arg->getPrepend() . $configValue . $arg->getAppend();
} else {
$value = $configValue;
}
// If a location key mapping is set, then use it
$key = $arg->getLocationKey() ?: $name;
// Add the parameter to the request
switch ($location) {
case 'body':
$this->request->setBody(EntityBody::factory($value));
break;
case 'header':
$this->request->setHeader($key, $value);
break;
case 'query':
$this->request->getQuery()->set($key, $value);
break;
}
}
}
}
src/Guzzle/Service/Command/Factory/AliasFactory.php 0000644 00000002235 15174272742 0016307 0 ustar 00 client = $client;
$this->aliases = $aliases;
}
/**
* {@inheritdoc}
*/
public function factory($name, array $args = array())
{
if (isset($this->aliases[$name])) {
try {
return $this->client->getCommand($this->aliases[$name], $args);
} catch (InvalidArgumentException $e) {
return null;
}
}
}
}
src/Guzzle/Service/Command/Factory/CompositeFactory.php 0000644 00000010223 15174272742 0017214 0 ustar 00 getDescription();
if ($description instanceof ServiceDescription) {
$chain->add(new ServiceDescriptionFactory($description));
}
$chain->add(new ConcreteClassFactory($client));
return $chain;
}
/**
* @param array $factories Array of command factories
*/
public function __construct(array $factories = array())
{
$this->factories = $factories;
}
/**
* Add a command factory to the chain
*
* @param FactoryInterface $factory Factory to add
* @param string|FactoryInterface $before Insert the new command factory before a command
* factory class or object matching a class name.
*
* @return CompositeFactory
*/
public function add(FactoryInterface $factory, $before = null)
{
$pos = null;
if ($before) {
foreach ($this->factories as $i => $f) {
if ($before instanceof FactoryInterface) {
if ($f === $before) {
$pos = $i;
break;
}
} elseif (is_string($before)) {
if ($f instanceof $before) {
$pos = $i;
break;
}
}
}
}
if ($pos === null) {
$this->factories[] = $factory;
} else {
array_splice($this->factories, $i, 0, array($factory));
}
return $this;
}
/**
* Check if the chain contains a specific command factory
*
* @param FactoryInterface|string $factory Factory to check
*
* @return bool
*/
public function has($factory)
{
return (bool) $this->find($factory);
}
/**
* Remove a specific command factory from the chain
*
* @param string|FactoryInterface $factory Factory to remove by name or instance
*
* @return CompositeFactory
*/
public function remove($factory = null)
{
if (!($factory instanceof FactoryInterface)) {
$factory = $this->find($factory);
}
$this->factories = array_values(array_filter($this->factories, function($f) use ($factory) {
return $f !== $factory;
}));
return $this;
}
/**
* Get a command factory by class name
*
* @param string|FactoryInterface $factory Command factory class or instance
*
* @return null|FactoryInterface
*/
public function find($factory)
{
foreach ($this->factories as $f) {
if ($factory === $f || (is_string($factory) && $f instanceof $factory)) {
return $f;
}
}
}
/**
* Create a command using the associated command factories
*
* @param string $name Name of the command
* @param array $args Command arguments
*
* @return CommandInterface
*/
public function factory($name, array $args = array())
{
foreach ($this->factories as $factory) {
$command = $factory->factory($name, $args);
if ($command) {
return $command;
}
}
}
/**
* {@inheritdoc}
*/
public function count()
{
return count($this->factories);
}
/**
* {@inheritdoc}
*/
public function getIterator()
{
return new \ArrayIterator($this->factories);
}
}
src/Guzzle/Service/Command/Factory/ConcreteClassFactory.php 0000644 00000002532 15174272742 0020006 0 ustar 00 client = $client;
}
/**
* {@inheritdoc}
*/
public function factory($name, array $args = array())
{
// Determine the class to instantiate based on the namespace of the
// current client and the default location of commands
$prefix = $this->client->getConfig('command.prefix');
if (!$prefix) {
// The prefix can be specified in a factory method and is cached
$prefix = implode('\\', array_slice(explode('\\', get_class($this->client)), 0, -1)) . '\\Command\\';
$this->client->getConfig()->set('command.prefix', $prefix);
}
$class = $prefix . str_replace(' ', '\\', ucwords(str_replace('.', ' ', Inflector::camel($name))));
// Create the concrete command if it exists
if (class_exists($class)) {
return new $class($args);
}
}
}
src/Guzzle/Service/Command/Factory/FactoryInterface.php 0000644 00000000643 15174272742 0017157 0 ustar 00 map = $map;
}
/**
* {@inheritdoc}
*/
public function factory($name, array $args = array())
{
if (isset($this->map[$name])) {
$class = $this->map[$name];
return new $class($args);
}
}
}
src/Guzzle/Service/Command/Factory/ServiceDescriptionFactory.php 0000644 00000002605 15174272742 0021063 0 ustar 00 setServiceDescription($description);
}
/**
* Change the service description used with the factory
*
* @param ServiceDescription $description Service description to use
*
* @return ServiceDescriptionFactory
*/
public function setServiceDescription(ServiceDescription $description)
{
$this->description = $description;
return $this;
}
/**
* Returns the service description
*
* @return ServiceDescription
*/
public function getServiceDescription()
{
return $this->description;
}
/**
* {@inheritdoc}
*/
public function factory($name, array $args = array())
{
if ($this->description->hasCommand($name)) {
$command = $this->description->getCommand($name);
$class = $command->getConcreteClass();
return new $class($args, $command);
}
}
}
src/Guzzle/Service/Description/ApiCommand.php 0000644 00000025106 15174272742 0015236 0 ustar 00 name = isset($config['name']) ? trim($config['name']) : '';
$this->doc = isset($config['doc']) ? trim($config['doc']) : '';
$this->method = isset($config['method']) ? trim($config['method']) : '';
$this->uri = isset($config['uri']) ? trim($config['uri']) : '';
$this->class = isset($config['class']) ? trim($config['class']) : self::DEFAULT_COMMAND_CLASS;
if (!empty($config['params'])) {
foreach ($config['params'] as $name => $param) {
$this->params[$name] = $param instanceof ApiParam ? $param : new ApiParam($param);
}
}
}
/**
* Create an ApiCommand object from a class and its docblock
*
* The following is the format for @guzzle arguments:
* @guzzle argument_name [default="default value"] [required="true|false"] [type="registered constraint name"] [type_args=""] [doc="Description of argument"]
* Example: @guzzle my_argument default="hello" required="true" doc="Set the argument to control the widget..."
*
* @param string $className Name of the class
*
* @return ApiCommand
*/
public static function fromCommand($className)
{
if (!isset(self::$apiCommandCache[$className])) {
$reflection = new \ReflectionClass($className);
// Get all of the @guzzle annotations from the class
$matches = array();
$params = array();
preg_match_all('/' . self::GUZZLE_ANNOTATION . '\s+([A-Za-z0-9_\-\.]+)\s*([A-Za-z0-9]+=".+")*/', $reflection->getDocComment(), $matches);
// Parse the docblock annotations
if (!empty($matches[1])) {
foreach ($matches[1] as $index => $match) {
// Add the matched argument to the array keys
$params[$match] = array();
if (isset($matches[2])) {
// Break up the argument attributes by closing quote
foreach (explode('" ', $matches[2][$index]) as $part) {
$attrs = array();
// Find the attribute and attribute value
preg_match('/([A-Za-z0-9]+)="(.+)"*/', $part, $attrs);
if (isset($attrs[1]) && isset($attrs[0])) {
// Sanitize the strings
if ($attrs[2][strlen($attrs[2]) - 1] == '"') {
$attrs[2] = substr($attrs[2], 0, strlen($attrs[2]) - 1);
}
$params[$match][$attrs[1]] = $attrs[2];
}
}
}
$params[$match] = new ApiParam($params[$match]);
}
}
self::$apiCommandCache[$className] = new ApiCommand(array(
'name' => str_replace('\\_', '.', Inflector::snake(substr($className, strpos($className, 'Command') + 8))),
'class' => $className,
'params' => $params
));
}
return self::$apiCommandCache[$className];
}
/**
* Get as an array
*
* @return true
*/
public function toArray()
{
return array(
'name' => $this->name,
'doc' => $this->doc,
'method' => $this->method,
'uri' => $this->uri,
'class' => $this->class,
'params' => $this->params
);
}
/**
* Get the params of the command
*
* @return array
*/
public function getParams()
{
return $this->params;
}
/**
* Get a single parameter of the command
*
* @param string $param Parameter to retrieve by name
*
* @return ApiParam|null
*/
public function getParam($param)
{
return isset($this->params[$param]) ? $this->params[$param] : null;
}
/**
* Get the HTTP method of the command
*
* @return string
*/
public function getMethod()
{
return $this->method;
}
/**
* Get the concrete command class that implements this command
*
* @return string
*/
public function getConcreteClass()
{
return $this->class;
}
/**
* Get the name of the command
*
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* Get the documentation for the command
*
* @return string
*/
public function getDoc()
{
return $this->doc;
}
/**
* Get the URI that will be merged into the generated request
*
* @return string
*/
public function getUri()
{
return $this->uri;
}
/**
* Validates that all required args are included in a config object,
* and if not, throws an InvalidArgumentException with a helpful error message. Adds
* default args to the passed config object if the parameter was not
* set in the config object.
*
* @param Collection $config Configuration settings
*
* @throws ValidationException when validation errors occur
*/
public function validate(Collection $config, Inspector $inspector = null)
{
$inspector = $inspector ?: Inspector::getInstance();
$typeValidation = $inspector->getTypeValidation();
$errors = array();
foreach ($this->params as $name => $arg) {
$currentValue = $config->get($name);
$configValue = $arg->getValue($currentValue);
// Inject configuration information into the config value
if ($configValue && is_string($configValue)) {
$configValue = $config->inject($configValue);
}
// Ensure that required arguments are set
if ($arg->getRequired() && ($configValue === null || $configValue === '')) {
$errors[] = 'Requires that the ' . $name . ' argument be supplied.' . ($arg->getDoc() ? ' (' . $arg->getDoc() . ').' : '');
continue;
}
// Ensure that the correct data type is being used
if ($typeValidation && $configValue !== null && $argType = $arg->getType()) {
$validation = $inspector->validateConstraint($argType, $configValue, $arg->getTypeArgs());
if ($validation !== true) {
$errors[] = $name . ': ' . $validation;
$config->set($name, $configValue);
continue;
}
}
$configValue = $arg->filter($configValue);
// Update the config value if it changed
if (!$configValue !== $currentValue) {
$config->set($name, $configValue);
}
// Check the length values if validating data
$argMinLength = $arg->getMinLength();
if ($argMinLength && strlen($configValue) < $argMinLength) {
$errors[] = 'Requires that the ' . $name . ' argument be >= ' . $arg->getMinLength() . ' characters.';
}
$argMaxLength = $arg->getMaxLength();
if ($argMaxLength && strlen($configValue) > $argMaxLength) {
$errors[] = 'Requires that the ' . $name . ' argument be <= ' . $arg->getMaxLength() . ' characters.';
}
}
if (!empty($errors)) {
$e = new ValidationException('Validation errors: ' . implode("\n", $errors));
$e->setErrors($errors);
throw $e;
}
}
}
src/Guzzle/Service/Description/ApiParam.php 0000644 00000014435 15174272742 0014723 0 ustar 00 $value) {
if ($key == 'min_length') {
$this->minLength = $value;
} elseif ($key == 'max_length') {
$this->maxLength = $value;
} elseif ($key == 'location' && strpos($value, ':')) {
list($this->location, $this->locationKey) = explode(':', $value, 2);
} elseif ($key == 'location_key') {
$this->locationKey = $value;
} elseif ($key == 'type' && strpos($value, ':')) {
list($this->type, $this->typeArgs) = explode(':', $value, 2);
} elseif ($key == 'type_args') {
$this->typeArgs = $value;
} else {
$this->{$key} = $value;
}
}
if ($this->filters) {
$this->filters = array_map('trim', explode(',', $this->filters));
} else {
$this->filters = array();
}
if ($this->required === 'false') {
$this->required = false;
} elseif ($this->required === 'true') {
$this->required = true;
}
// Parse CSV type value data into an array
if ($this->typeArgs && is_string($this->typeArgs)) {
if (strpos($this->typeArgs, ',') !== false) {
$this->typeArgs = str_getcsv($this->typeArgs, ',', "'");
} else {
$this->typeArgs = array($this->typeArgs);
}
}
}
/**
* Convert the object to an array
*
* @return array
*/
public function toArray()
{
return array(
'name' => $this->name,
'type' => $this->type,
'type_args' => $this->typeArgs,
'required' => $this->required,
'default' => $this->default,
'doc' => $this->doc,
'min_length' => $this->minLength,
'max_length' => $this->maxLength,
'location' => $this->location,
'location_key' => $this->locationKey,
'static' => $this->static,
'prepend' => $this->prepend,
'append' => $this->append,
'filters' => implode(',', $this->filters)
);
}
/**
* Get the default or static value of the command based on a value
*
* @param string $value Value that is currently set
*
* @return mixed Returns the value, a static value if one is present, or a default value
*/
public function getValue($value)
{
if ($this->static || ($this->default && !$value)) {
$check = $this->static ?: $this->default;
if ($check === 'true') {
return true;
} elseif ($check === 'false') {
return false;
} else {
return $check;
}
}
return $value;
}
/**
* Filter a value
*
* @param mixed $value Value to filter
*
* @return mixed Returns the filtered value
*/
public function filter($value)
{
if ($this->filters) {
foreach ($this->filters as $filter) {
$value = call_user_func($filter, $value);
}
}
return $value;
}
/**
* Get the name of the parameter
*
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* Get the type
*
* @return string
*/
public function getType()
{
return $this->type;
}
/**
* Get the arguments to pass to type constraint
*
* @return array|null
*/
public function getTypeArgs()
{
return $this->typeArgs;
}
/**
* Get if the parameter is required
*
* @return bool
*/
public function getRequired()
{
return $this->required;
}
/**
* Get the default value of the parameter
*
* @return string|null
*/
public function getDefault()
{
return $this->default;
}
/**
* Get the docs for the parameter
*
* @return string|null
*/
public function getDoc()
{
return $this->doc;
}
/**
* Get the minimum allowed length of the parameter
*
* @return int|null
*/
public function getMinLength()
{
return $this->minLength;
}
/**
* Get the maximum allowed length of the parameter
*
* @return int|null
*/
public function getMaxLength()
{
return $this->maxLength;
}
/**
* Get the location of the parameter
*
* @return string|null
*/
public function getLocation()
{
return $this->location;
}
/**
* Get the location key mapping of the parameter
*
* @return string|null
*/
public function getLocationKey()
{
return $this->locationKey;
}
/**
* Get the static value of the parameter
*
* @return int|null
*/
public function getStatic()
{
return $this->static;
}
/**
* Get the string to prepend to values
*
* @return string
*/
public function getPrepend()
{
return $this->prepend;
}
/**
* Get the string to append to values
*
* @return string
*/
public function getAppend()
{
return $this->append;
}
/**
* Get an array of filters used by the parameter
*
* @return array
*/
public function getFilters()
{
return $this->filters;
}
}
src/Guzzle/Service/Description/ArrayDescriptionBuilder.php 0000644 00000004210 15174272742 0020010 0 ustar 00 $type) {
$default = array();
if (!isset($type['class'])) {
throw new DescriptionBuilderException('Custom types require a class attribute');
}
foreach ($type as $key => $value) {
if ($key != 'name' && $key != 'class') {
$default[$key] = $value;
}
}
Inspector::getInstance()->registerConstraint($name, $type['class'], $default);
}
}
$commands = array();
if (!empty($config['commands'])) {
foreach ($config['commands'] as $name => $command) {
$name = $command['name'] = isset($command['name']) ? $command['name'] : $name;
// Extend other commands
if (!empty($command['extends'])) {
if (empty($commands[$command['extends']])) {
throw new DescriptionBuilderException($name . ' extends missing command ' . $command['extends']);
}
$params = array_merge($commands[$command['extends']]->getParams(), !empty($command['params']) ? $command['params'] : array());
$command = array_merge($commands[$command['extends']]->toArray(), $command);
$command['params'] = $params;
}
// Use the default class
$command['class'] = isset($command['class']) ? str_replace('.', '\\', $command['class']) : ServiceDescription::DEFAULT_COMMAND_CLASS;
$commands[$name] = new ApiCommand($command);
}
}
return new ServiceDescription($commands);
}
}
src/Guzzle/Service/Description/DescriptionBuilderInterface.php 0000644 00000000642 15174272742 0020637 0 ustar 00 loader) {
$this->loader = new JsonLoader();
}
return ServiceDescription::factory($this->loader->parseJsonFile($config));
}
}
src/Guzzle/Service/Description/ServiceDescription.php 0000644 00000005647 15174272742 0017042 0 ustar 00 build($config);
}
/**
* Create a new ServiceDescription
*
* @param array $commands Array of {@see ApiCommand} objects
*/
public function __construct(array $commands = array())
{
$this->commands = $commands;
}
/**
* Serialize the service description
*
* @return string
*/
public function serialize()
{
return json_encode(array_map(function($command) {
// Convert ApiCommands into arrays
$data = $command->toArray();
// Convert ApiParams into arrays
$data['params'] = array_map(function($param) {
return $param->toArray();
}, $data['params']);
return $data;
}, $this->commands));
}
/**
* Unserialize the service description
*
* @param string|array $json JSON data
*/
public function unserialize($json)
{
$this->commands = array_map(function($data) {
// Convert params to ApiParam objects
$data['params'] = array_map(function($param) {
return new ApiParam($param);
}, $data['params']);
// Convert commands into ApiCommands
return new ApiCommand($data);
}, json_decode($json, true));
}
/**
* Get the API commands of the service
*
* @return array Returns an array of ApiCommand objects
*/
public function getCommands()
{
return $this->commands;
}
/**
* Check if the service has a command by name
*
* @param string $name Name of the command to check
*
* @return bool
*/
public function hasCommand($name)
{
return array_key_exists($name, $this->commands);
}
/**
* Get an API command by name
*
* @param string $name Name of the command
*
* @return ApiCommand|null
*/
public function getCommand($name)
{
return $this->hasCommand($name) ? $this->commands[$name] : null;
}
}
src/Guzzle/Service/Description/ServiceDescriptionAbstractFactory.php 0000644 00000002331 15174272742 0022041 0 ustar 00 parseXmlFile($config));
}
/**
* Convert an XML file to an array of service data
*
* @param string $file XML filename to parse
*
* @return array
* @throws InvalidArgumentException
*/
protected function parseXmlFile($file)
{
if (!file_exists($file)) {
throw new DescriptionBuilderException('Unable to open ' . $file . ' for reading');
}
$xml = new \SimpleXMLElement($file, null, true);
$config = array(
'types' => array(),
'commands' => array()
);
// Register any custom type definitions
$types = $xml->types->type;
if ($types) {
foreach ($types as $type) {
$attr = $type->attributes();
$name = (string) $attr->name;
$config['types'][$name] = array();
foreach ($attr as $key => $value) {
$config['types'][$name][(string) $key] = (string) $value;
}
}
}
// Parse the commands in the XML doc
$commands = $xml->commands->command;
if ($commands) {
foreach ($commands as $command) {
$attr = $command->attributes();
$name = (string) $attr->name;
$config['commands'][$name] = array(
'params' => array()
);
foreach ($attr as $key => $value) {
$config['commands'][$name][(string) $key] = (string) $value;
}
$config['commands'][$name]['doc'] = (string) $command->doc;
foreach ($command->param as $param) {
$attr = $param->attributes();
$paramName = (string) $attr['name'];
$config['commands'][$name]['params'][$paramName] = array();
foreach ($attr as $pk => $pv) {
$pv = (string) $pk == 'required' ? (string) $pv === 'true' : (string) $pv;
$config['commands'][$name]['params'][$paramName][(string) $pk] = (string) $pv;
}
}
}
}
// Handle XML includes
$includes = $xml->includes->include;
if ($includes) {
foreach ($includes as $includeFile) {
$path = (string) $includeFile->attributes()->path;
if ($path[0] != DIRECTORY_SEPARATOR) {
$path = dirname($file) . DIRECTORY_SEPARATOR . $path;
}
$config = array_merge_recursive(self::parseXmlFile($path), $config);
}
}
return $config;
}
}
src/Guzzle/Service/Exception/CommandException.php 0000644 00000000216 15174272742 0016131 0 ustar 00 invalidCommands;
}
/**
* Set the invalid commands in the CommandSet
*
* @param array $commands Array of Command objects
*/
public function setCommands(array $commands)
{
$this->invalidCommands = $commands;
}
}
src/Guzzle/Service/Exception/DescriptionBuilderException.php 0000644 00000000231 15174272742 0020342 0 ustar 00 errors = $errors;
}
/**
* Get any validation errors
*
* @return array
*/
public function getErrors()
{
return $this->errors;
}
}
src/Guzzle/Service/Inflector.php 0000644 00000003576 15174272742 0012677 0 ustar 00 array(),
'camel' => array()
);
/**
* Converts strings from camel case to snake case
* (e.g. CamelCase camel_case).
*
* @param string $word Word to convert to snake case
*
* @return string
*/
public static function snake($word)
{
if (isset(self::$cache['snake'][$word])) {
return self::$cache['snake'][$word];
}
self::pruneCache('snake');
return self::$cache['snake'][$word] = strtolower($word) == $word
? $word : strtolower(preg_replace('/(.)([A-Z])/', "$1_$2", $word));
}
/**
* Converts strings from snake_case to upper CamelCase
*
* @param string $word Value to convert into upper CamelCase
*
* @return string
*/
public static function camel($word)
{
if (isset(self::$cache['camel'][$word])) {
return self::$cache['camel'][$word];
}
self::pruneCache('camel');
return self::$cache['camel'][$word] = str_replace(' ', '', ucwords(strtr($word, '_-', ' ')));
}
/**
* Prune one of the caches
*
* @param string $cache Name of the cache to prune
*/
private static function pruneCache($cache)
{
if (count(self::$cache[$cache]) == self::MAX_ENTRIES_PER_CACHE) {
self::$cache[$cache] = array_slice(self::$cache[$cache], self::MAX_ENTRIES_PER_CACHE * 0.1);
}
}
}
src/Guzzle/Service/Inspector.php 0000644 00000014104 15174272742 0012705 0 ustar 00 constraints = array(
'blank' => array($base . 'Blank', null),
'not_blank' => array($base . 'NotBlank', null),
'integer' => array($base . 'Numeric', null),
'float' => array($base . 'Numeric', null),
'string' => array($base . 'Type', array('type' => 'string')),
'file' => array($base . 'Type', array('type' => 'file')),
'array' => array($base . 'Type', array('type' => 'array')),
'bool' => array($base . 'Bool', null),
'boolean' => array($base . 'Bool', null),
'email' => array($base . 'Email', null),
'ip' => array($base . 'Ip', null),
'url' => array($base . 'Url', null),
'class' => array($base . 'IsInstanceOf', null),
'type' => array($base . 'Type', null),
'any_match' => array($base . 'AnyMatch', null),
'ctype' => array($base . 'Ctype', null),
'choice' => array($base . 'Choice', null),
'enum' => array($base . 'Choice', null),
'regex' => array($base . 'Regex', null),
'date' => array($base . 'Type', array('type' => 'string')),
'date_time' => array($base . 'Type', array('type' => 'string')),
'time' => array($base . 'Numeric', null)
);
}
/**
* Get an instance of the Inspector
*
* @return Inspector
*/
public static function getInstance()
{
// @codeCoverageIgnoreStart
if (!self::$instance) {
self::$instance = new self();
}
// @codeCoverageIgnoreEnd
return self::$instance;
}
/**
* Validate and prepare configuration parameters
*
* @param array $config Configuration values to apply.
* @param array $defaults Default parameters
* @param array $required Required parameter names
*
* @return Collection
* @throws InvalidArgumentException if a parameter is missing
*/
public static function prepareConfig(array $config = null, array $defaults = null, array $required = null)
{
$collection = new Collection($defaults);
foreach ((array) $config as $key => $value) {
$collection->set($key, $value);
}
foreach ((array) $required as $key) {
if ($collection->hasKey($key) === false) {
throw new ValidationException(
"Config must contain a '{$key}' key"
);
}
}
return $collection;
}
/**
* Enable/disable type validation of configuration settings. This is
* useful for very high performance requirements.
*
* @param bool $typeValidation Set to TRUE or FALSE
*
* @return Inspector
*/
public function setTypeValidation($typeValidation)
{
$this->typeValidation = $typeValidation;
}
/**
* Check if type validation is enabled
*
* @return bool
*/
public function getTypeValidation()
{
return $this->typeValidation;
}
/**
* Get an array of the registered constraints by name
*
* @return array
*/
public function getRegisteredConstraints()
{
return array_map(function($constraint) {
return $constraint[0];
}, $this->constraints);
}
/**
* Register a constraint class with a special name
*
* @param string $name Name of the constraint to register
* @param string $class Name of the class or object to use when filtering by this name
* @param array $default Default values to pass to the constraint
*
* @return Inspector
*/
public function registerConstraint($name, $class, array $default = array())
{
$this->constraints[$name] = array($class, $default);
}
/**
* Get a constraint by name
*
* @param string $name Constraint name
*
* @return ConstraintInterface
* @throws InvalidArgumentException if the constraint is not registered
*/
public function getConstraint($name)
{
if (!isset($this->constraints[$name])) {
throw new InvalidArgumentException($name . ' has not been registered');
}
if (!isset($this->constraintCache[$name])) {
$c = $this->constraints[$name][0];
$this->constraintCache[$name] = new $c();
}
return $this->constraintCache[$name];
}
/**
* Validate a constraint by name: e.g. "type:Guzzle\Common\Collection";
* type:string; choice:a,b,c; choice:'a','b','c'; etc...
*
* @param string $name Constraint to retrieve with optional CSV args after colon
* @param mixed $value Value to validate
* @param array $args Optional arguments to pass to the type validation
*
* @return bool|string Returns TRUE if valid, or an error message if invalid
*/
public function validateConstraint($name, $value, array $args = null)
{
if (!$args) {
$args = isset($this->constraints[$name][1]) ? $this->constraints[$name][1] : array();
}
return $this->getConstraint($name)->validate($value, $args);
}
}
src/Guzzle/Service/JsonLoader.php 0000644 00000002634 15174272742 0013004 0 ustar 00 parseJsonFile($path), $data);
}
}
return $data;
}
}
src/Guzzle/Service/Resource/ResourceIterator.php 0000644 00000020621 15174272742 0016030 0 ustar 00 originalCommand = $command;
// Parse options from the array of options
$this->data = $data;
$this->limit = array_key_exists('limit', $data) ? $data['limit'] : 0;
$this->pageSize = array_key_exists('page_size', $data) ? $data['page_size'] : false;
}
/**
* Get all of the resources as an array (be careful as this could issue a
* large number of requests if no limit is specified)
*
* @return array
*/
public function toArray()
{
return iterator_to_array($this, false);
}
/**
* {@inheritdoc}
*/
public function setLimit($limit)
{
$this->limit = $limit;
$this->resetState();
return $this;
}
/**
* {@inheritdoc}
*/
public function setPageSize($pageSize)
{
$this->pageSize = $pageSize;
$this->resetState();
return $this;
}
/**
* Get an option from the iterator
*
* @param string $key Key of the option to retrieve
*
* @return mixed|null Returns NULL if not set or the value if set
*/
public function get($key)
{
return array_key_exists($key, $this->data) ? $this->data[$key] : null;
}
/**
* Set an option on the iterator
*
* @param string $key Key of the option to set
* @param mixed $value Value to set for the option
*
* @return ResourceIterator
*/
public function set($key, $value)
{
$this->data[$key] = $value;
return $this;
}
/**
* Return the current element.
*
* @return mixed Returns the current element.
*/
public function current()
{
return $this->resources ? current($this->resources) : false;
}
/**
* Return the key of the current element.
*
* @return mixed
*/
public function key()
{
return max(0, $this->iteratedCount - 1);
}
/**
* Return the total number of items that have been retrieved thus far.
*
* @return int
*/
public function count()
{
return $this->retrievedCount;
}
/**
* Get the total number of requests sent
*
* @return int
*/
public function getRequestCount()
{
return $this->requestCount;
}
/**
* Rewind the Iterator to the first element and send the original command
*/
public function rewind()
{
// Use the original command
$this->command = clone $this->originalCommand;
$this->resetState();
$this->next();
}
/**
* Check if there is a current element after calls to rewind() or next().
*
* @return bool Returns TRUE if the current element is valid or FALSE
*/
public function valid()
{
return !$this->invalid && (!$this->resources || $this->current() || $this->nextToken)
&& (!$this->limit || $this->iteratedCount < $this->limit + 1);
}
/**
* Move forward to next element and may trigger subsequent requests
*/
public function next()
{
$this->iteratedCount++;
// Check if a new set of resources needs to be retrieved
$sendRequest = false;
if (!$this->resources) {
$sendRequest = true;
} else {
// iterate over the internal array
$current = next($this->resources);
$sendRequest = $current === false && $this->nextToken && (!$this->limit || $this->iteratedCount < $this->limit + 1);
}
if ($sendRequest) {
$this->dispatch('resource_iterator.before_send', array(
'iterator' => $this,
'resources' => $this->resources
));
// Get a new command object from the original command
$this->command = clone $this->originalCommand;
// Send a request and retrieve the newly loaded resources
$this->resources = $this->sendRequest();
$this->requestCount++;
// If no resources were found, then the last request was not needed
// and iteration must stop
if (empty($this->resources)) {
$this->invalid = true;
} else {
// Add to the number of retrieved resources
$this->retrievedCount += count($this->resources);
// Ensure that we rewind to the beginning of the array
reset($this->resources);
}
$this->dispatch('resource_iterator.after_send', array(
'iterator' => $this,
'resources' => $this->resources
));
}
}
/**
* Retrieve the NextToken that can be used in other iterators.
*
* @return string Returns a NextToken
*/
public function getNextToken()
{
return $this->nextToken;
}
/**
* Returns the value that should be specified for the page size for
* a request that will maintain any hard limits, but still honor the
* specified pageSize if the number of items retrieved + pageSize < hard
* limit
*
* @return int Returns the page size of the next request.
*/
protected function calculatePageSize()
{
if ($this->limit && $this->iteratedCount + $this->pageSize > $this->limit) {
return 1 + ($this->limit - $this->iteratedCount);
}
return (int) $this->pageSize;
}
/**
* Reset the internal state of the iterator without triggering a rewind()
*/
protected function resetState()
{
$this->iteratedCount = 0;
$this->retrievedCount = 0;
$this->nextToken = false;
$this->resources = null;
$this->invalid = false;
}
/**
* Send a request to retrieve the next page of results.
* Hook for sublasses to implement.
*
* @return array Returns the newly loaded resources
*/
abstract protected function sendRequest();
}
src/Guzzle/Service/Resource/ResourceIteratorApplyBatched.php 0000644 00000006765 15174272742 0020326 0 ustar 00 iterator = $iterator;
$this->callback = $callback;
}
/**
* Apply the callback to the contents of the resource iterator
*
* Calling this method dispatches four events:
* - before_apply: Before adding a resource to a batch. Context is the resource
* - after_apply: After adding the resource to a batch. Context is the resource
* - before_batch: Before a batch request is sent if one is sent. Context is an array of resources
* - after_batch: After a batch request is sent if one is sent. Context is an array of resources
*
* @param int $perBatch The number of records to batch before executing the callback
*
* @return int Returns the number of resources iterated
*/
public function apply($perBatch = 20)
{
if ($this->iterated == 0) {
$batched = array();
foreach ($this->iterator as $resource) {
$batched[] = $resource;
if (count($batched) >= $perBatch) {
$this->applyBatch($batched);
$batched = array();
}
$this->iterated++;
}
if (count($batched)) {
$this->applyBatch($batched);
}
}
return $this->iterated;
}
/**
* Get the total number of batches sent
*
* @return int
*/
public function getBatchCount()
{
return $this->batches;
}
/**
* Get the total number of iterated resources
*
* @return int
*/
public function getIteratedCount()
{
return $this->iterated;
}
/**
* Apply the callback to a collection of resources
*
* @param array $batch
*/
private function applyBatch(array $batch)
{
$this->batches++;
$this->dispatch('iterator_batch.before_batch', array(
'iterator' => $this,
'batch' => $batch
));
call_user_func_array($this->callback, array(
$this->iterator, $batch
));
$this->dispatch('iterator_batch.after_batch', array(
'iterator' => $this,
'batch' => $batch
));
}
}
src/Guzzle/Service/Resource/ResourceIteratorClassFactory.php 0000644 00000003122 15174272742 0020343 0 ustar 00 CamelCaseIterator).
*/
class ResourceIteratorClassFactory implements ResourceIteratorFactoryInterface
{
/**
* @var string
*/
protected $baseNamespace;
/**
* @param string $baseNamespace Base namespace of all iterator object.
*/
public function __construct($baseNamespace)
{
$this->baseNamespace = $baseNamespace;
}
/**
* Create a resource iterator
*
* @param CommandInterface $data Command used for building the iterator
* @param array $options Iterator options.
*
* @return ResourceIteratorInterface
*/
public function build($data, array $options = null)
{
if (!($data instanceof CommandInterface)) {
throw new InvalidArgumentException('The first argument must be an '
. 'instance of CommandInterface');
}
// Determine the name of the class to load
$className = $this->baseNamespace . '\\'
. Inflector::camel($data->getName()) . 'Iterator';
return new $className($data, $options);
}
}
src/Guzzle/Service/Resource/ResourceIteratorFactoryInterface.php 0000644 00000000677 15174272742 0021212 0 ustar 00 assertEquals(array(), AbstractHasDispatcher::getAllEvents());
}
/**
* @covers Guzzle\Common\AbstractHasDispatcher::setEventDispatcher
* @covers Guzzle\Common\AbstractHasDispatcher::getEventDispatcher
*/
public function testAllowsDispatcherToBeInjected()
{
$d = new EventDispatcher();
$mock = $this->getMockForAbstractClass('Guzzle\Common\AbstractHasDispatcher');
$this->assertSame($mock, $mock->setEventDispatcher($d));
$this->assertSame($d, $mock->getEventDispatcher());
}
/**
* @covers Guzzle\Common\AbstractHasDispatcher::getEventDispatcher
*/
public function testCreatesDefaultEventDispatcherIfNeeded()
{
$mock = $this->getMockForAbstractClass('Guzzle\Common\AbstractHasDispatcher');
$this->assertInstanceOf('Symfony\Component\EventDispatcher\EventDispatcher', $mock->getEventDispatcher());
}
/**
* @covers Guzzle\Common\AbstractHasDispatcher::dispatch
*/
public function testHelperDispatchesEvents()
{
$data = array();
$mock = $this->getMockForAbstractClass('Guzzle\Common\AbstractHasDispatcher');
$mock->getEventDispatcher()->addListener('test', function(Event $e) use (&$data) {
$data = $e->getIterator()->getArrayCopy();
});
$mock->dispatch('test', array(
'param' => 'abc'
));
$this->assertEquals(array(
'param' => 'abc',
), $data);
}
}
tests/Guzzle/Tests/Common/Cache/CacheAdapterFactoryTest.php 0000644 00000007745 15174272742 0017760 0 ustar 00 cache = new ArrayCache();
$this->adapter = new DoctrineCacheAdapter($this->cache);
}
/**
* @covers Guzzle\Common\Cache\CacheAdapterFactory::factory
* @expectedException InvalidArgumentException
*/
public function testEnsuresConfigIsArray()
{
CacheAdapterFactory::factory(new \stdClass());
}
/**
* @covers Guzzle\Common\Cache\CacheAdapterFactory::factory
* @expectedException InvalidArgumentException
* @expectedExceptionMessage cache.provider is a required CacheAdapterFactory option
*/
public function testEnsuresRequiredProviderOption()
{
CacheAdapterFactory::factory(array(
'cache.adapter' => $this->adapter
));
}
/**
* @covers Guzzle\Common\Cache\CacheAdapterFactory::factory
* @expectedException Guzzle\Common\Exception\InvalidArgumentException
* @expectedExceptionMessage cache.adapter is a required CacheAdapterFactory option
*/
public function testEnsuresRequiredAdapterOption()
{
CacheAdapterFactory::factory(array(
'cache.provider' => $this->cache
));
}
/**
* @covers Guzzle\Common\Cache\CacheAdapterFactory::factory
* @expectedException InvalidArgumentException
* @expectedExceptionMessage foo is not a valid class for cache.adapter
*/
public function testEnsuresClassesExist()
{
CacheAdapterFactory::factory(array(
'cache.provider' => 'abc',
'cache.adapter' => 'foo'
));
}
/**
* @covers Guzzle\Common\Cache\CacheAdapterFactory::factory
* @covers Guzzle\Common\Cache\CacheAdapterFactory::createObject
*/
public function testCreatesProviderFromConfig()
{
$cache = CacheAdapterFactory::factory(array(
'cache.provider' => 'Doctrine\Common\Cache\ApcCache',
'cache.adapter' => 'Guzzle\Common\Cache\DoctrineCacheAdapter'
));
$this->assertInstanceOf('Guzzle\Common\Cache\DoctrineCacheAdapter', $cache);
$this->assertInstanceOf('Doctrine\Common\Cache\ApcCache', $cache->getCacheObject());
}
/**
* @covers Guzzle\Common\Cache\CacheAdapterFactory::factory
* @covers Guzzle\Common\Cache\CacheAdapterFactory::createObject
*/
public function testCreatesProviderFromConfigWithArguments()
{
$cache = CacheAdapterFactory::factory(array(
'cache.provider' => 'Doctrine\Common\Cache\ApcCache',
'cache.provider.args' => array(),
'cache.adapter' => 'Guzzle\Common\Cache\DoctrineCacheAdapter',
'cache.adapter.args' => array()
));
$this->assertInstanceOf('Guzzle\Common\Cache\DoctrineCacheAdapter', $cache);
$this->assertInstanceOf('Doctrine\Common\Cache\ApcCache', $cache->getCacheObject());
}
/**
* @covers Guzzle\Common\Cache\CacheAdapterFactory
* @expectedException Guzzle\Common\Exception\RuntimeException
*/
public function testWrapsExceptionsOnObjectCreation()
{
CacheAdapterFactory::factory(array(
'cache.provider' => 'Guzzle\Tests\Mock\ExceptionMock',
'cache.adapter' => 'Guzzle\Tests\Mock\ExceptionMock'
));
}
/**
* @covers Guzzle\Common\Cache\CacheAdapterFactory
*/
public function testCreatesNullCacheAdapterByDefault()
{
$adapter = CacheAdapterFactory::factory(array());
$this->assertInstanceOf('Guzzle\\Common\\Cache\\NullCacheAdapter', $adapter);
}
}
tests/Guzzle/Tests/Common/Cache/CacheAdapterTest.php 0000644 00000004061 15174272742 0016414 0 ustar 00 cache = new ArrayCache();
$this->adapter = new DoctrineCacheAdapter($this->cache);
}
/**
* Cleans up the environment after running a test.
*/
protected function tearDown()
{
$this->adapter = null;
$this->cache = null;
parent::tearDown();
}
/**
* @covers \Guzzle\Common\Cache\AbstractCacheAdapter::getCacheObject
*/
public function testGetCacheObject()
{
$this->assertEquals($this->cache, $this->adapter->getCacheObject());
}
/**
* @covers \Guzzle\Common\Cache\DoctrineCacheAdapter::save
*/
public function testSave()
{
$this->assertTrue($this->adapter->save('test', 'data', 1000));
}
/**
* @covers \Guzzle\Common\Cache\DoctrineCacheAdapter::fetch
*/
public function testFetch()
{
$this->assertTrue($this->adapter->save('test', 'data', 1000));
$this->assertEquals('data', $this->adapter->fetch('test'));
}
/**
* @covers \Guzzle\Common\Cache\DoctrineCacheAdapter::contains
*/
public function testContains()
{
$this->assertTrue($this->adapter->save('test', 'data', 1000));
$this->assertTrue($this->adapter->contains('test'));
}
/**
* @covers \Guzzle\Common\Cache\DoctrineCacheAdapter::delete
*/
public function testDelete()
{
$this->assertTrue($this->adapter->save('test', 'data', 1000));
$this->assertTrue($this->adapter->delete('test'));
$this->assertFalse($this->adapter->contains('test'));
}
}
tests/Guzzle/Tests/Common/Cache/ClosureCacheAdapterTest.php 0000644 00000006110 15174272742 0017746 0 ustar 00 callables = array(
'contains' => function($id, $options = array()) use ($that) {
return array_key_exists($id, $that->data);
},
'delete' => function($id, $options = array()) use ($that) {
unset($that->data[$id]);
return true;
},
'fetch' => function($id, $options = array()) use ($that) {
return array_key_exists($id, $that->data) ? $that->data[$id] : null;
},
'save' => function($id, $data, $lifeTime, $options = array()) use ($that) {
$that->data[$id] = $data;
return true;
}
);
$this->adapter = new ClosureCacheAdapter($this->callables);
}
/**
* Cleans up the environment after running a test.
*/
protected function tearDown()
{
$this->cache = null;
$this->callables = null;
parent::tearDown();
}
/**
* @covers Guzzle\Common\Cache\ClosureCacheAdapter::__construct
* @expectedException InvalidArgumentException
*/
public function testEnsuresCallablesArePresent()
{
$callables = $this->callables;
unset($callables['delete']);
$cache = new ClosureCacheAdapter($callables);
}
/**
* @covers Guzzle\Common\Cache\ClosureCacheAdapter::__construct
*/
public function testAllCallablesMustBePresent()
{
$cache = new ClosureCacheAdapter($this->callables);
}
/**
* @covers Guzzle\Common\Cache\ClosureCacheAdapter::save
* @covers Guzzle\Common\Cache\ClosureCacheAdapter::fetch
*/
public function testCachesDataUsingCallables()
{
$this->assertTrue($this->adapter->save('test', 'data', 1000));
$this->assertEquals('data', $this->adapter->fetch('test'));
}
/**
* @covers Guzzle\Common\Cache\ClosureCacheAdapter::contains
*/
public function testChecksIfCacheContainsKeys()
{
$this->adapter->save('test', 'data', 1000);
$this->assertTrue($this->adapter->contains('test'));
$this->assertFalse($this->adapter->contains('foo'));
}
/**
* @covers Guzzle\Common\Cache\ClosureCacheAdapter::delete
*/
public function testDeletesFromCacheByKey()
{
$this->adapter->save('test', 'data', 1000);
$this->assertTrue($this->adapter->contains('test'));
$this->adapter->delete('test');
$this->assertFalse($this->adapter->contains('test'));
}
}
tests/Guzzle/Tests/Common/Cache/NullCacheAdapterTest.php 0000644 00000001020 15174272742 0017237 0 ustar 00 assertEquals(false, $c->contains('foo'));
$this->assertEquals(true, $c->delete('foo'));
$this->assertEquals(false, $c->fetch('foo'));
$this->assertEquals(true, $c->save('foo', 'bar'));
}
}
tests/Guzzle/Tests/Common/Cache/Zf1CacheAdapterTest.php 0000644 00000001104 15174272742 0016770 0 ustar 00 assertTrue($adapter->save('id', 'data'));
$this->assertTrue($adapter->delete('id'));
$this->assertEquals('foo', $adapter->fetch('id'));
$this->assertEquals('123456', $adapter->contains('id'));
}
}
tests/Guzzle/Tests/Common/Cache/Zf2CacheAdapterTest.php 0000644 00000005134 15174272742 0017000 0 ustar 00 cache = StorageFactory::factory(array(
'adapter' => 'memory'
));
$this->adapter = new Zf2CacheAdapter($this->cache);
}
/**
* Cleans up the environment after running a test.
*/
protected function tearDown()
{
$this->adapter = null;
$this->cache = null;
parent::tearDown();
}
/**
* @covers Guzzle\Common\Cache\Zf2CacheAdapter::__construct
*/
public function testConstructorAddsDefaultOptions()
{
$default = array(
'contains' => array(
'namespace' => 'foo'
)
);
$adapter = new Zf2CacheAdapter(StorageFactory::factory(array(
'adapter' => 'memory'
)), $default);
// Access the protected property
$class = new \ReflectionClass($adapter);
$property = $class->getProperty('defaultOptions');
$property->setAccessible(true);
$defaultOptions = $property->getValue($adapter);
$this->assertEquals(array_merge($default, array(
'delete' => array(),
'fetch' => array(),
'save' => array()
)), $defaultOptions);
}
/**
* @covers Guzzle\Common\Cache\Zf2CacheAdapter::save
* @covers Guzzle\Common\Cache\Zf2CacheAdapter::fetch
*/
public function testCachesDataUsingCallables()
{
$this->assertTrue($this->adapter->save('test', 'data', 1000));
$this->assertEquals('data', $this->adapter->fetch('test'));
}
/**
* @covers Guzzle\Common\Cache\Zf2CacheAdapter::contains
*/
public function testChecksIfCacheContainsKeys()
{
$this->adapter->save('test', 'data', 1000);
$this->assertTrue($this->adapter->contains('test'));
$this->assertFalse($this->adapter->contains('foo'));
}
/**
* @covers Guzzle\Common\Cache\Zf2CacheAdapter::delete
*/
public function testDeletesFromCacheByKey()
{
$this->adapter->save('test', 'data', 1000);
$this->assertTrue($this->adapter->contains('test'));
$this->adapter->delete('test');
$this->assertFalse($this->adapter->contains('test'));
}
}
tests/Guzzle/Tests/Common/CollectionTest.php 0000644 00000031125 15174272742 0015201 0 ustar 00 coll = new Collection();
}
/**
* @covers Guzzle\Common\Collection::__construct
*/
public function testConstructorCanBeCalledWithNoParams()
{
$this->coll = new Collection();
$p = $this->coll->getAll();
$this->assertEmpty($p, '-> Collection must be empty when no data is passed');
}
/**
* @covers Guzzle\Common\Collection::__construct
* @covers Guzzle\Common\Collection::getAll
*/
public function testConstructorCanBeCalledWithParams()
{
$testData = array(
'test' => 'value',
'test_2' => 'value2'
);
$this->coll = new Collection($testData);
$this->assertEquals($this->coll->getAll(), $testData, '-> getAll() must return the data passed in the constructor');
}
/**
* @covers Guzzle\Common\Collection::__toString
*/
public function testCollectionCanBeConvertingIntoString()
{
$data = new Collection();
$this->assertEquals('Guzzle\Common\Collection@' . spl_object_hash($data), (string) $data, '-> __toString() must represent the collection');
}
/**
* Test the IteratorAggregate implementation of theCollection object
*
* @covers Guzzle\Common\Collection::getIterator
*/
public function testImplementsIteratorAggregate()
{
$this->coll->set('key', 'value');
$this->assertInstanceOf('ArrayIterator', $this->coll->getIterator());
$this->assertEquals(1, count($this->coll));
$total = 0;
foreach ($this->coll as $key => $value) {
$this->assertEquals('key', $key);
$this->assertEquals('value', $value);
$total++;
}
$this->assertEquals(1, $total);
}
/**
* @covers Guzzle\Common\Collection::add
*/
public function testCanAddValuesToExistingKeysByUsingArray()
{
$this->coll->add('test', 'value1');
$this->assertEquals($this->coll->getAll(), array('test' => 'value1'));
$this->coll->add('test', 'value2');
$this->assertEquals($this->coll->getAll(), array('test' => array('value1', 'value2')));
$this->coll->add('test', 'value3');
$this->assertEquals($this->coll->getAll(), array('test' => array('value1', 'value2', 'value3')));
}
/**
* @covers Guzzle\Common\Collection::merge
* @covers Guzzle\Common\Collection::getAll
*/
public function testHandlesMergingInDisparateDataSources()
{
$params = array(
'test' => 'value1',
'test2' => 'value2',
'test3' => array('value3', 'value4')
);
$this->coll->merge($params);
$this->assertEquals($this->coll->getAll(), $params);
// Pass an invalid value and expect the same unaltered object
$this->assertEquals($this->coll->merge(false), $this->coll);
// Pass the same object to itself
$this->assertEquals($this->coll->merge($this->coll), $this->coll);
}
/**
* @covers Guzzle\Common\Collection::clear
* @covers Guzzle\Common\Collection::remove
*/
public function testCanClearAllDataOrSpecificKeys()
{
$this->coll->merge(array(
'test' => 'value1',
'test2' => 'value2'
));
// Clear a specific parameter by name
$this->coll->remove('test');
$this->assertEquals($this->coll->getAll(), array(
'test2' => 'value2'
));
// Clear all parameters
$this->coll->clear();
$this->assertEquals($this->coll->getAll(), array());
}
/**
* @covers Guzzle\Common\Collection::get
* @covers Guzzle\Common\Collection::getAll
*/
public function testGetsValuesByKey()
{
$this->assertNull($this->coll->get('test'));
$this->coll->add('test', 'value');
$this->assertEquals('value', $this->coll->get('test'));
$this->coll->set('test2', 'v2');
$this->coll->set('test3', 'v3');
$this->assertEquals(array(
'test' => 'value',
'test2' => 'v2'
), $this->coll->getAll(array('test', 'test2')));
}
/**
* @covers Guzzle\Common\Collection::getKeys
* @covers Guzzle\Common\Collection::remove
*/
public function testProvidesKeys()
{
$this->assertEquals(array(), $this->coll->getKeys());
$this->coll->merge(array(
'test1' => 'value1',
'test2' => 'value2'
));
$this->assertEquals(array('test1', 'test2'), $this->coll->getKeys());
// Returns the cached array previously returned
$this->assertEquals(array('test1', 'test2'), $this->coll->getKeys());
$this->coll->remove('test1');
$this->assertEquals(array('test2'), $this->coll->getKeys());
$this->coll->add('test3', 'value3');
$this->assertEquals(array('test2', 'test3'), $this->coll->getKeys());
}
/**
* @covers Guzzle\Common\Collection::hasKey
*/
public function testChecksIfHasKey()
{
$this->assertFalse($this->coll->hasKey('test'));
$this->coll->add('test', 'value');
$this->assertEquals(true, $this->coll->hasKey('test'));
$this->coll->add('test2', 'value2');
$this->assertEquals(true, $this->coll->hasKey('test'));
$this->assertEquals(true, $this->coll->hasKey('test2'));
$this->assertFalse($this->coll->hasKey('testing'));
$this->assertEquals(false, $this->coll->hasKey('AB-C', 'junk'));
}
/**
* @covers Guzzle\Common\Collection::hasValue
*/
public function testChecksIfHasValue()
{
$this->assertFalse($this->coll->hasValue('value'));
$this->coll->add('test', 'value');
$this->assertEquals('test', $this->coll->hasValue('value'));
$this->coll->add('test2', 'value2');
$this->assertEquals('test', $this->coll->hasValue('value'));
$this->assertEquals('test2', $this->coll->hasValue('value2'));
$this->assertFalse($this->coll->hasValue('val'));
}
/**
* @covers Guzzle\Common\Collection::getAll
*/
public function testCanGetAllValuesByArray()
{
$this->coll->add('foo', 'bar');
$this->coll->add('tEsT', 'value');
$this->coll->add('tesTing', 'v2');
$this->coll->add('key', 'v3');
$this->assertNull($this->coll->get('test'));
$this->assertEquals(array(
'foo' => 'bar',
'tEsT' => 'value',
'tesTing' => 'v2'
), $this->coll->getAll(array(
'foo', 'tesTing', 'tEsT'
)));
}
/**
* @covers Guzzle\Common\Collection::count
*/
public function testImplementsCount()
{
$data = new Collection();
$this->assertEquals(0, $data->count());
$data->add('key', 'value');
$this->assertEquals(1, count($data));
$data->add('key', 'value2');
$this->assertEquals(1, count($data));
$data->add('key_2', 'value3');
$this->assertEquals(2, count($data));
}
/**
* @covers Guzzle\Common\Collection::merge
*/
public function testAddParamsByMerging()
{
$params = array(
'test' => 'value1',
'test2' => 'value2',
'test3' => array('value3', 'value4')
);
// Add some parameters
$this->coll->merge($params);
// Add more parameters by merging them in
$this->coll->merge(array(
'test' => 'another',
'different_key' => 'new value'
));
$this->assertEquals(array(
'test' => array('value1', 'another'),
'test2' => 'value2',
'test3' => array('value3', 'value4'),
'different_key' => 'new value'
), $this->coll->getAll());
}
/**
* @covers Guzzle\Common\Collection::filter
*/
public function testAllowsFunctionalFilter()
{
$this->coll->merge(array(
'fruit' => 'apple',
'number' => 'ten',
'prepositions' => array('about', 'above', 'across', 'after'),
'same_number' => 'ten'
));
$filtered = $this->coll->filter(function($key, $value) {
return $value == 'ten';
});
$this->assertNotEquals($filtered, $this->coll);
$this->assertEquals(array(
'number' => 'ten',
'same_number' => 'ten'
), $filtered->getAll());
}
/**
* @covers Guzzle\Common\Collection::map
*/
public function testAllowsFunctionalMapping()
{
$this->coll->merge(array(
'number_1' => 1,
'number_2' => 2,
'number_3' => 3
));
$mapped = $this->coll->map(function($key, $value) {
return $value * $value;
});
$this->assertNotEquals($mapped, $this->coll);
$this->assertEquals(array(
'number_1' => 1,
'number_2' => 4,
'number_3' => 9
), $mapped->getAll());
}
/**
* @covers Guzzle\Common\Collection::offsetGet
* @covers Guzzle\Common\Collection::offsetSet
* @covers Guzzle\Common\Collection::offsetUnset
* @covers Guzzle\Common\Collection::offsetExists
*/
public function testImplementsArrayAccess()
{
$this->coll->merge(array(
'k1' => 'v1',
'k2' => 'v2'
));
$this->assertTrue($this->coll->offsetExists('k1'));
$this->assertFalse($this->coll->offsetExists('Krull'));
$this->coll->offsetSet('k3', 'v3');
$this->assertEquals('v3', $this->coll->offsetGet('k3'));
$this->assertEquals('v3', $this->coll->get('k3'));
$this->coll->offsetUnset('k1');
$this->assertFalse($this->coll->offsetExists('k1'));
}
/**
* @covers Guzzle\Common\Collection::filter
* @covers Guzzle\Common\Collection::map
*/
public function testUsesStaticWhenCreatingNew()
{
$qs = new QueryString(array(
'a' => 'b',
'c' => 'd'
));
$this->assertInstanceOf('Guzzle\\Http\\QueryString', $qs->map(function($a, $b) {}));
$this->assertInstanceOf('Guzzle\\Common\\Collection', $qs->map(function($a, $b) {}, array(), false));
$this->assertInstanceOf('Guzzle\\Http\\QueryString', $qs->filter(function($a, $b) {}));
$this->assertInstanceOf('Guzzle\\Common\\Collection', $qs->filter(function($a, $b) {}, false));
}
/**
* @covers Guzzle\Common\Collection::replace
*/
public function testCanReplaceAllData()
{
$this->assertSame($this->coll, $this->coll->replace(array(
'a' => '123'
)));
$this->assertEquals(array(
'a' => '123'
), $this->coll->getAll());
}
/**
* @covers Guzzle\Common\Collection::getPregMatchValue
*/
public function testReturnsValuesForPregMatch()
{
$c = new Collection(array('foo' => 'bar'));
$this->assertEquals('bar', $c->getPregMatchValue(array(1 => 'foo')));
}
public function dataProvider()
{
return array(
array('this_is_a_test', '{ a }_is_a_{ b }', array(
'a' => 'this',
'b' => 'test'
)),
array('this_is_a_test', '{abc}_is_a_{ 0 }', array(
'abc' => 'this',
0 => 'test'
)),
array('this_is_a_test', '{ abc }_is_{ not_found }a_{ 0 }', array(
'abc' => 'this',
0 => 'test'
)),
array('this_is_a_test', 'this_is_a_test', array(
'abc' => 'this'
)),
array('_is_a_', '{ abc }_is_{ not_found }a_{ 0 }', array()),
array('_is_a_', '{abc}_is_{not_found}a_{0}', array()),
);
}
/**
* @covers Guzzle\Common\Collection::inject
* @dataProvider dataProvider
*/
public function testInjectsConfigData($output, $input, $config)
{
$collection = new Collection($config);
$this->assertEquals($output, $collection->inject($input));
}
/**
* @covers Guzzle\Common\Collection::keySearch
*/
public function testCanSearchByKey()
{
$collection = new Collection(array(
'foo' => 'bar',
'BaZ' => 'pho'
));
$this->assertEquals('foo', $collection->keySearch('FOO'));
$this->assertEquals('BaZ', $collection->keySearch('baz'));
$this->assertEquals(false, $collection->keySearch('Bar'));
}
}
tests/Guzzle/Tests/Common/EventTest.php 0000644 00000002772 15174272742 0014175 0 ustar 00 '123',
'other' => '456',
'event' => 'test.notify'
));
}
/**
* @covers Guzzle\Common\Event::__construct
*/
public function testAllowsParameterInjection()
{
$event = new Event(array(
'test' => '123'
));
$this->assertEquals('123', $event['test']);
}
/**
* @covers Guzzle\Common\Event::offsetGet
* @covers Guzzle\Common\Event::offsetSet
* @covers Guzzle\Common\Event::offsetUnset
* @covers Guzzle\Common\Event::offsetExists
*/
public function testImplementsArrayAccess()
{
$event = $this->getEvent();
$this->assertEquals('123', $event['test']);
$this->assertNull($event['foobar']);
$this->assertTrue($event->offsetExists('test'));
$this->assertFalse($event->offsetExists('foobar'));
unset($event['test']);
$this->assertFalse($event->offsetExists('test'));
$event['test'] = 'new';
$this->assertEquals('new', $event['test']);
}
/**
* @covers Guzzle\Common\Event::getIterator
*/
public function testImplementsIteratorAggregate()
{
$event = $this->getEvent();
$this->assertInstanceOf('ArrayIterator', $event->getIterator());
}
}
tests/Guzzle/Tests/Common/Exception/ExceptionCollectionTest.php 0000644 00000002317 15174272742 0021017 0 ustar 00 getExceptions();
$e->add($exceptions[0]);
$e->add($exceptions[1]);
$this->assertEquals("Test\nTesting", $e->getMessage());
}
public function testActsAsArray()
{
$e = new ExceptionCollection();
$exceptions = $this->getExceptions();
$e->add($exceptions[0]);
$e->add($exceptions[1]);
$this->assertEquals(2, count($e));
$this->assertEquals($exceptions, $e->getIterator()->getArrayCopy());
}
public function testCanAddSelf()
{
$e1 = new ExceptionCollection();
$e1->add(new \Exception("Test"));
$e2 = new ExceptionCollection();
$e2->add(new \Exception("Test 2"));
$e1->add($e2);
$this->assertEquals("Test\nTest 2", $e1->getMessage());
}
}
tests/Guzzle/Tests/Common/Log/ClosureLogAdapterTest.php 0000644 00000002010 15174272742 0017175 0 ustar 00 adapter = new ClosureLogAdapter(function($message, $priority, $extras = null) use ($that) {
$that->modified = array($message, $priority, $extras);
});
$this->adapter->log('test', \LOG_NOTICE, 'localhost');
$this->assertEquals(array('test', \LOG_NOTICE, 'localhost'), $this->modified);
}
/**
* @covers \Guzzle\Common\Log\ClosureLogAdapter
* @expectedException InvalidArgumentException
*/
public function testThrowsExceptionWhenNotCallable()
{
$abc = 123;
$this->adapter = new ClosureLogAdapter($abc);
}
}
tests/Guzzle/Tests/Common/Log/MonologLogAdapterTest.php 0000644 00000001221 15174272742 0017176 0 ustar 00 pushHandler($handler);
$adapter = new MonologLogAdapter($log);
$adapter->log('test!', LOG_INFO);
$this->assertTrue($handler->hasInfoRecords());
}
}
tests/Guzzle/Tests/Common/Log/Zend_Log.php 0000644 00000047040 15174272742 0014473 0 ustar 00 _priorities = array_flip($r->getConstants());
if ($writer !== null) {
$this->addWriter($writer);
}
}
/**
* Factory to construct the logger and one or more writers
* based on the configuration array
*
* @param array|Zend_Config Array or instance of Zend_Config
* @return Zend_Log
* @throws Zend_Log_Exception
*/
static public function factory($config = array())
{
if ($config instanceof Zend_Config) {
$config = $config->toArray();
}
if (!is_array($config) || empty($config)) {
/** @see Zend_Log_Exception */
require_once 'Zend/Log/Exception.php';
throw new Zend_Log_Exception('Configuration must be an array or instance of Zend_Config');
}
$log = new self;
if (array_key_exists('timestampFormat', $config)) {
if (null != $config['timestampFormat'] && '' != $config['timestampFormat']) {
$log->setTimestampFormat($config['timestampFormat']);
}
unset($config['timestampFormat']);
}
if (!is_array(current($config))) {
$log->addWriter(current($config));
} else {
foreach($config as $writer) {
$log->addWriter($writer);
}
}
return $log;
}
/**
* Construct a writer object based on a configuration array
*
* @param array $spec config array with writer spec
* @return Zend_Log_Writer_Abstract
* @throws Zend_Log_Exception
*/
protected function _constructWriterFromConfig($config)
{
$writer = $this->_constructFromConfig('writer', $config, $this->_defaultWriterNamespace);
if (!$writer instanceof Zend_Log_Writer_Abstract) {
$writerName = is_object($writer)
? get_class($writer)
: 'The specified writer';
/** @see Zend_Log_Exception */
require_once 'Zend/Log/Exception.php';
throw new Zend_Log_Exception("{$writerName} does not extend Zend_Log_Writer_Abstract!");
}
if (isset($config['filterName'])) {
$filter = $this->_constructFilterFromConfig($config);
$writer->addFilter($filter);
}
if (isset($config['formatterName'])) {
$formatter = $this->_constructFormatterFromConfig($config);
$writer->setFormatter($formatter);
}
return $writer;
}
/**
* Construct filter object from configuration array or Zend_Config object
*
* @param array|Zend_Config $config Zend_Config or Array
* @return Zend_Log_Filter_Interface
* @throws Zend_Log_Exception
*/
protected function _constructFilterFromConfig($config)
{
$filter = $this->_constructFromConfig('filter', $config, $this->_defaultFilterNamespace);
if (!$filter instanceof Zend_Log_Filter_Interface) {
$filterName = is_object($filter)
? get_class($filter)
: 'The specified filter';
/** @see Zend_Log_Exception */
require_once 'Zend/Log/Exception.php';
throw new Zend_Log_Exception("{$filterName} does not implement Zend_Log_Filter_Interface");
}
return $filter;
}
/**
* Construct formatter object from configuration array or Zend_Config object
*
* @param array|Zend_Config $config Zend_Config or Array
* @return Zend_Log_Formatter_Interface
* @throws Zend_Log_Exception
*/
protected function _constructFormatterFromConfig($config)
{
$formatter = $this->_constructFromConfig('formatter', $config, $this->_defaultFormatterNamespace);
if (!$formatter instanceof Zend_Log_Formatter_Interface) {
$formatterName = is_object($formatter)
? get_class($formatter)
: 'The specified formatter';
/** @see Zend_Log_Exception */
require_once 'Zend/Log/Exception.php';
throw new Zend_Log_Exception($formatterName . ' does not implement Zend_Log_Formatter_Interface');
}
return $formatter;
}
/**
* Construct a filter or writer from config
*
* @param string $type 'writer' of 'filter'
* @param mixed $config Zend_Config or Array
* @param string $namespace
* @return object
* @throws Zend_Log_Exception
*/
protected function _constructFromConfig($type, $config, $namespace)
{
if ($config instanceof Zend_Config) {
$config = $config->toArray();
}
if (!is_array($config) || empty($config)) {
require_once 'Zend/Log/Exception.php';
throw new Zend_Log_Exception(
'Configuration must be an array or instance of Zend_Config'
);
}
$params = isset($config[ $type .'Params' ]) ? $config[ $type .'Params' ] : array();
$className = $this->getClassName($config, $type, $namespace);
if (!class_exists($className)) {
require_once 'Zend/Loader.php';
Zend_Loader::loadClass($className);
}
$reflection = new ReflectionClass($className);
if (!$reflection->implementsInterface('Zend_Log_FactoryInterface')) {
require_once 'Zend/Log/Exception.php';
throw new Zend_Log_Exception(
$className . ' does not implement Zend_Log_FactoryInterface and can not be constructed from config.'
);
}
return call_user_func(array($className, 'factory'), $params);
}
/**
* Get the writer or filter full classname
*
* @param array $config
* @param string $type filter|writer
* @param string $defaultNamespace
* @return string full classname
* @throws Zend_Log_Exception
*/
protected function getClassName($config, $type, $defaultNamespace)
{
if (!isset($config[$type . 'Name'])) {
require_once 'Zend/Log/Exception.php';
throw new Zend_Log_Exception("Specify {$type}Name in the configuration array");
}
$className = $config[$type . 'Name'];
$namespace = $defaultNamespace;
if (isset($config[$type . 'Namespace'])) {
$namespace = $config[$type . 'Namespace'];
}
// PHP >= 5.3.0 namespace given?
if (substr($namespace, -1) == '\\') {
return $namespace . $className;
}
// emtpy namespace given?
if (strlen($namespace) === 0) {
return $className;
}
return $namespace . '_' . $className;
}
/**
* Packs message and priority into Event array
*
* @param string $message Message to log
* @param integer $priority Priority of message
* @return array Event array
*/
protected function _packEvent($message, $priority)
{
return array_merge(array(
'timestamp' => date($this->_timestampFormat),
'message' => $message,
'priority' => $priority,
'priorityName' => $this->_priorities[$priority]
),
$this->_extras
);
}
/**
* Class destructor. Shutdown log writers
*
* @return void
*/
public function __destruct()
{
foreach($this->_writers as $writer) {
$writer->shutdown();
}
}
/**
* Undefined method handler allows a shortcut:
* $log->priorityName('message')
* instead of
* $log->log('message', Zend_Log::PRIORITY_NAME)
*
* @param string $method priority name
* @param string $params message to log
* @return void
* @throws Zend_Log_Exception
*/
public function __call($method, $params)
{
$priority = strtoupper($method);
if (($priority = array_search($priority, $this->_priorities)) !== false) {
switch (count($params)) {
case 0:
/** @see Zend_Log_Exception */
require_once 'Zend/Log/Exception.php';
throw new Zend_Log_Exception('Missing log message');
case 1:
$message = array_shift($params);
$extras = null;
break;
default:
$message = array_shift($params);
$extras = array_shift($params);
break;
}
$this->log($message, $priority, $extras);
} else {
/** @see Zend_Log_Exception */
require_once 'Zend/Log/Exception.php';
throw new Zend_Log_Exception('Bad log priority');
}
}
/**
* Log a message at a priority
*
* @param string $message Message to log
* @param integer $priority Priority of message
* @param mixed $extras Extra information to log in event
* @return void
* @throws Zend_Log_Exception
*/
public function log($message, $priority, $extras = null)
{
// sanity checks
if (empty($this->_writers)) {
/** @see Zend_Log_Exception */
require_once 'Zend/Log/Exception.php';
throw new Zend_Log_Exception('No writers were added');
}
if (! isset($this->_priorities[$priority])) {
/** @see Zend_Log_Exception */
require_once 'Zend/Log/Exception.php';
throw new Zend_Log_Exception('Bad log priority');
}
// pack into event required by filters and writers
$event = $this->_packEvent($message, $priority);
// Check to see if any extra information was passed
if (!empty($extras)) {
$info = array();
if (is_array($extras)) {
foreach ($extras as $key => $value) {
if (is_string($key)) {
$event[$key] = $value;
} else {
$info[] = $value;
}
}
} else {
$info = $extras;
}
if (!empty($info)) {
$event['info'] = $info;
}
}
// abort if rejected by the global filters
foreach ($this->_filters as $filter) {
if (! $filter->accept($event)) {
return;
}
}
// send to each writer
foreach ($this->_writers as $writer) {
$writer->write($event);
}
}
/**
* Add a custom priority
*
* @param string $name Name of priority
* @param integer $priority Numeric priority
* @throws Zend_Log_Exception
*/
public function addPriority($name, $priority)
{
// Priority names must be uppercase for predictability.
$name = strtoupper($name);
if (isset($this->_priorities[$priority])
|| false !== array_search($name, $this->_priorities)) {
/** @see Zend_Log_Exception */
require_once 'Zend/Log/Exception.php';
throw new Zend_Log_Exception('Existing priorities cannot be overwritten');
}
$this->_priorities[$priority] = $name;
return $this;
}
/**
* Add a filter that will be applied before all log writers.
* Before a message will be received by any of the writers, it
* must be accepted by all filters added with this method.
*
* @param int|Zend_Config|array|Zend_Log_Filter_Interface $filter
* @return Zend_Log
* @throws Zend_Log_Exception
*/
public function addFilter($filter)
{
if (is_int($filter)) {
/** @see Zend_Log_Filter_Priority */
require_once 'Zend/Log/Filter/Priority.php';
$filter = new Zend_Log_Filter_Priority($filter);
} elseif ($filter instanceof Zend_Config || is_array($filter)) {
$filter = $this->_constructFilterFromConfig($filter);
} elseif(! $filter instanceof Zend_Log_Filter_Interface) {
/** @see Zend_Log_Exception */
require_once 'Zend/Log/Exception.php';
throw new Zend_Log_Exception('Invalid filter provided');
}
$this->_filters[] = $filter;
return $this;
}
/**
* Add a writer. A writer is responsible for taking a log
* message and writing it out to storage.
*
* @param mixed $writer Zend_Log_Writer_Abstract or Config array
* @return Zend_Log
*/
public function addWriter($writer)
{
if (is_array($writer) || $writer instanceof Zend_Config) {
$writer = $this->_constructWriterFromConfig($writer);
}
if (!$writer instanceof Zend_Log_Writer_Abstract) {
/** @see Zend_Log_Exception */
require_once 'Zend/Log/Exception.php';
throw new Zend_Log_Exception(
'Writer must be an instance of Zend_Log_Writer_Abstract'
. ' or you should pass a configuration array'
);
}
$this->_writers[] = $writer;
return $this;
}
/**
* Set an extra item to pass to the log writers.
*
* @param string $name Name of the field
* @param string $value Value of the field
* @return Zend_Log
*/
public function setEventItem($name, $value)
{
$this->_extras = array_merge($this->_extras, array($name => $value));
return $this;
}
/**
* Register Logging system as an error handler to log php errors
* Note: it still calls the original error handler if set_error_handler is able to return it.
*
* Errors will be mapped as:
* E_NOTICE, E_USER_NOTICE => NOTICE
* E_WARNING, E_CORE_WARNING, E_USER_WARNING => WARN
* E_ERROR, E_USER_ERROR, E_CORE_ERROR, E_RECOVERABLE_ERROR => ERR
* E_DEPRECATED, E_STRICT, E_USER_DEPRECATED => DEBUG
* (unknown/other) => INFO
*
* @link http://www.php.net/manual/en/function.set-error-handler.php Custom error handler
*
* @return Zend_Log
*/
public function registerErrorHandler()
{
// Only register once. Avoids loop issues if it gets registered twice.
if ($this->_registeredErrorHandler) {
return $this;
}
$this->_origErrorHandler = set_error_handler(array($this, 'errorHandler'));
// Contruct a default map of phpErrors to Zend_Log priorities.
// Some of the errors are uncatchable, but are included for completeness
$this->_errorHandlerMap = array(
E_NOTICE => Zend_Log::NOTICE,
E_USER_NOTICE => Zend_Log::NOTICE,
E_WARNING => Zend_Log::WARN,
E_CORE_WARNING => Zend_Log::WARN,
E_USER_WARNING => Zend_Log::WARN,
E_ERROR => Zend_Log::ERR,
E_USER_ERROR => Zend_Log::ERR,
E_CORE_ERROR => Zend_Log::ERR,
E_RECOVERABLE_ERROR => Zend_Log::ERR,
E_STRICT => Zend_Log::DEBUG,
);
// PHP 5.3.0+
if (defined('E_DEPRECATED')) {
$this->_errorHandlerMap['E_DEPRECATED'] = Zend_Log::DEBUG;
}
if (defined('E_USER_DEPRECATED')) {
$this->_errorHandlerMap['E_USER_DEPRECATED'] = Zend_Log::DEBUG;
}
$this->_registeredErrorHandler = true;
return $this;
}
/**
* Error Handler will convert error into log message, and then call the original error handler
*
* @link http://www.php.net/manual/en/function.set-error-handler.php Custom error handler
* @param int $errno
* @param string $errstr
* @param string $errfile
* @param int $errline
* @param array $errcontext
* @return boolean
*/
public function errorHandler($errno, $errstr, $errfile, $errline, $errcontext)
{
$errorLevel = error_reporting();
if ($errorLevel && $errno) {
if (isset($this->_errorHandlerMap[$errno])) {
$priority = $this->_errorHandlerMap[$errno];
} else {
$priority = Zend_Log::INFO;
}
$this->log($errstr, $priority, array('errno'=>$errno, 'file'=>$errfile, 'line'=>$errline, 'context'=>$errcontext));
}
if ($this->_origErrorHandler !== null) {
return call_user_func($this->_origErrorHandler, $errno, $errstr, $errfile, $errline, $errcontext);
}
return false;
}
/**
* Set timestamp format for log entries.
*
* @param string $format
* @return Zend_Log
*/
public function setTimestampFormat($format)
{
$this->_timestampFormat = $format;
return $this;
}
/**
* Get timestamp format used for log entries.
*
* @return string
*/
public function getTimestampFormat()
{
return $this->_timestampFormat;
}
}
tests/Guzzle/Tests/Common/Log/Zf1LogAdapterTest.php 0000644 00000003452 15174272742 0016234 0 ustar 00 stream = fopen('php://temp', 'r+');
$this->log = new \Zend_Log(new \Zend_Log_Writer_Stream($this->stream));
$this->adapter = new Zf1LogAdapter($this->log);
}
/**
* @covers Guzzle\Common\Log\Zf1LogAdapter::log
*/
public function testLogsMessagesToAdaptedObject()
{
// Test without a priority
$this->adapter->log('test', \LOG_NOTICE, 'guzzle.common.log.adapter.zend_log_adapter', 'localhost');
rewind($this->stream);
$this->assertEquals(1, substr_count(stream_get_contents($this->stream), 'test'));
// Test with a priority
$this->adapter->log('test', \LOG_ALERT);
rewind($this->stream);
$this->assertEquals(2, substr_count(stream_get_contents($this->stream), 'test'));
}
/**
* @covers Guzzle\Common\Log\AbstractLogAdapter::getLogObject
*/
public function testExposesAdaptedLogObject()
{
$this->assertEquals($this->log, $this->adapter->getLogObject());
}
}
tests/Guzzle/Tests/Common/Log/Zf2LogAdapterTest.php 0000644 00000003135 15174272742 0016233 0 ustar 00 stream = fopen('php://temp', 'r+');
$this->log = new Logger(new Stream($this->stream));
$this->adapter = new Zf2LogAdapter($this->log);
}
/**
* @covers Guzzle\Common\Log\Zf2LogAdapter::log
*/
public function testLogsMessagesToAdaptedObject()
{
// Test without a priority
$this->adapter->log('Zend_Test!', \LOG_NOTICE);
rewind($this->stream);
$contents = stream_get_contents($this->stream);
$this->assertEquals(1, substr_count($contents, 'Zend_Test!'));
// Test with a priority
$this->adapter->log('Zend_Test!', \LOG_ALERT);
rewind($this->stream);
$contents = stream_get_contents($this->stream);
$this->assertEquals(2, substr_count($contents, 'Zend_Test!'));
}
/**
* @covers Guzzle\Common\Log\AbstractLogAdapter::getLogObject
*/
public function testExposesAdaptedLogObject()
{
$this->assertEquals($this->log, $this->adapter->getLogObject());
}
}
tests/Guzzle/Tests/Common/StreamTest.php 0000644 00000012256 15174272742 0014345 0 ustar 00 assertEquals($handle, $stream->getStream());
$this->assertTrue($stream->isReadable());
$this->assertTrue($stream->isWritable());
$this->assertTrue($stream->isLocal());
$this->assertTrue($stream->isSeekable());
$this->assertEquals('php', $stream->getWrapper());
$this->assertEquals('temp', $stream->getStreamType());
$this->assertEquals(4, $stream->getSize());
$this->assertEquals('php://temp', $stream->getUri());
$this->assertEquals(array(), $stream->getWrapperData());
$this->assertFalse($stream->isConsumed());
unset($stream);
}
/**
* @covers Guzzle\Common\Stream::__destruct
*/
public function testStreamClosesHandleOnDestruct()
{
$handle = fopen('php://temp', 'r');
$stream = new Stream($handle);
unset($stream);
$this->assertFalse(is_resource($handle));
}
/**
* @covers Guzzle\Common\Stream::__toString
*/
public function testConvertsToString()
{
$handle = fopen('php://temp', 'w+');
fwrite($handle, 'data');
$stream = new Stream($handle);
$this->assertEquals('data', (string)$stream);
unset($stream);
$handle = fopen(__DIR__ . '/../TestData/FileBody.txt', 'w');
$stream = new Stream($handle);
$this->assertEquals('', (string)$stream);
unset($stream);
}
/**
* @covers Guzzle\Common\Stream::isConsumed
*/
public function testIsConsumed()
{
$handle = fopen('php://temp', 'w+');
fwrite($handle, 'data');
$stream = new Stream($handle);
$this->assertFalse($stream->isConsumed());
$stream->read(4);
$this->assertTrue($stream->isConsumed());
}
/**
* @covers Guzzle\Common\Stream::setSize
* @covers Guzzle\Common\Stream::getSize
*/
public function testAllowsSettingManualSize()
{
$handle = fopen('php://temp', 'w+');
fwrite($handle, 'data');
$stream = new Stream($handle);
$stream->setSize(10);
$this->assertEquals(10, $stream->getSize());
unset($stream);
}
/**
* @covers Guzzle\Common\Stream::read
* @covers Guzzle\Common\Stream::write
* @covers Guzzle\Common\Stream::seek
* @covers Guzzle\Common\Stream::isReadable
* @covers Guzzle\Common\Stream::isSeekable
*/
public function testWrapsStream()
{
$handle = fopen('php://temp', 'w+');
fwrite($handle, 'data');
$stream = new Stream($handle);
$this->assertTrue($stream->isSeekable());
$this->assertTrue($stream->isReadable());
$this->assertTrue($stream->seek(0));
$this->assertEquals('da', $stream->read(2));
$this->assertEquals('ta', $stream->read(2));
$this->assertTrue($stream->seek(0));
$this->assertEquals('data', $stream->read(4));
$stream->write('_appended');
$stream->seek(0);
$this->assertEquals('data_appended', $stream->read(13));
}
/**
* @covers Guzzle\Common\Stream::getSize
* @covers Guzzle\Common\Stream::__construct
*/
public function testGetSize()
{
$size = filesize(__DIR__ . '/../../../bootstrap.php');
$handle = fopen(__DIR__ . '/../../../bootstrap.php', 'r');
$stream = new Stream($handle);
$this->assertEquals($handle, $stream->getStream());
$this->assertEquals($size, $stream->getSize());
$this->assertEquals($size, $stream->getSize());
unset($stream);
// Make sure that false is returned when the size cannot be determined
$this->getServer()->enqueue("HTTP/1.1 200 OK\r\nContent-Lenght: 0\r\n\r\n");
$handle = fopen('http://localhost:' . $this->getServer()->getPort(), 'r');
$stream = new Stream($handle);
$this->assertEquals(false, $stream->getSize());
unset($stream);
}
/**
* @covers Guzzle\Common\Stream::getMetaData
*/
public function testAbstractsMetaData()
{
$handle = fopen(__DIR__ . '/../../../bootstrap.php', 'r');
$stream = new Stream($handle);
$this->assertEquals('plainfile', $stream->getMetaData('wrapper_type'));
$this->assertEquals(null, $stream->getMetaData('wrapper_data'));
$this->assertInternalType('array', $stream->getMetaData());
}
/**
* @covers Guzzle\Common\Stream::write
*/
public function testDoesNotAttempToWriteToReadonlyStream()
{
$handle = fopen(__DIR__ . '/../../../bootstrap.php', 'r');
$stream = new Stream($handle);
$this->assertEquals(0, $stream->write('foo'));
}
}
tests/Guzzle/Tests/Common/Validation/AnyMatchTest.php 0000644 00000004065 15174272742 0016707 0 ustar 00 markTestSkipped('Inspector not present');
}
$i = Inspector::getInstance();
return array(
array($c, 'a', array('constraints' => 'type:string', 'inspector' => $i), true, null),
array($c, 'a', array('type:string', 'inspector' => $i), true, null),
array($c, 'foo', array('constraints' => 'type:string;type:numeric'), true, null),
array($c, new \stdClass(), array('constraints' => 'type:string;type:numeric', 'inspector' => $i), 'Value type must match one of type:string OR type:numeric', null),
array($c, 'foo', array('constraints' => 'type:numeric;type:boolean;ip;email', 'inspector' => $i), 'Value type must match one of type:numeric OR type:boolean OR ip OR email', null),
array($c, 'http://www.example.com', array('constraints' => 'ip;url', 'inspector' => $i), true, null),
array($c, '192.168.16.148', array('constraints' => 'ip;url', 'inspector' => $i), true, null),
array($c, 'foo', array('constraints' => 'email;choice:foo,bar;ip;array', 'inspector' => $i), true, null),
array($c, 'bar', array('constraints' => 'email;choice:foo,bar;ip;array', 'inspector' => $i), true, null),
array($c, '192.168.16.48', array('constraints' => 'email;choice:foo,bar;ip;array', 'inspector' => $i), true, null),
array($c, array(), array('constraints' => 'email;choice:foo,bar;ip;array', 'inspector' => $i), true, null),
array($c, 'michael@awesome.com', array('constraints' => 'email;choice:foo,bar;ip;array', 'inspector' => $i), true, null),
array($c, new \stdClass(), array('constraints' => 'type:object', 'inspector' => $i), true, null)
);
}
}
tests/Guzzle/Tests/Common/Validation/BlankTest.php 0000644 00000000743 15174272742 0016231 0 ustar 00 array('foo', 'bar')), true, null),
array($c, 'baz', array('options' => array('foo', 'bar')), 'Value must be one of: foo, bar', null)
);
}
}
tests/Guzzle/Tests/Common/Validation/CtypeTest.php 0000644 00000001362 15174272742 0016264 0 ustar 00 'alpha'), true, null),
array($c, 'a', array('alpha'), true, null),
array($c, '2', array('type' => 'alpha'), 'Value must be of type alpha', null),
array($c, ' ', array('type' => 'space'), true, null),
array($c, 'a', array('type' => 'foo'), null, 'Guzzle\Common\Exception\InvalidArgumentException')
);
}
}
tests/Guzzle/Tests/Common/Validation/EmailTest.php 0000644 00000000615 15174272742 0016227 0 ustar 00 'stdClass'), 'Value must be an instance of stdClass', null),
array($c, new \stdClass(), array('class' => 'stdClass'), true, null),
array($c, new IsInstanceOf(), array('class' => 'Guzzle.Common.Validation.IsInstanceOf'), true, null),
array($c, 'a', null, true, 'Guzzle\Common\Exception\InvalidArgumentException'),
array($c, new \stdClass(), null, true, 'Guzzle\Common\Exception\InvalidArgumentException')
);
}
}
tests/Guzzle/Tests/Common/Validation/NotBlankTest.php 0000644 00000000704 15174272742 0016707 0 ustar 00 '/[a-z]+/'), true, null),
array($c, 'foo', array('/[a-z]+/'), true, null),
array($c, 'foo', array('pattern' => '/[0-9]+/'), 'foo does not match the regular expression', null),
array($c, 'baz', null, null, 'Guzzle\Common\Exception\InvalidArgumentException')
);
}
}
tests/Guzzle/Tests/Common/Validation/StringTest.php 0000644 00000000712 15174272742 0016444 0 ustar 00 'string'), true, null),
array($c, 'a', array('string'), true, null),
array($c, '2', array('type' => 'array'), 'Value must be of type array', null)
);
}
}
tests/Guzzle/Tests/Common/Validation/UrlTest.php 0000644 00000000743 15174272742 0015744 0 ustar 00 validate($value, $options);
$this->assertEquals($result, $r);
} catch (\Exception $e) {
if (!$exception) {
throw $e;
}
if (!($e instanceof $exception)) {
throw $e;
}
}
}
}
tests/Guzzle/Tests/GuzzleTestCase.php 0000644 00000014730 15174272742 0013735 0 ustar 00 isRunning()) {
self::$server->flush();
} else {
self::$server->start();
}
} catch (\Exception $e) {
fwrite(STDERR, $e->getMessage());
}
}
return self::$server;
}
/**
* Set the service builder to use for tests
*
* @param ServiceBuilder $builder Service builder
*/
public static function setServiceBuilder(ServiceBuilderInterface $builder)
{
self::$serviceBuilder = $builder;
}
/**
* Get a service builder object that can be used throughout the service tests
*
* @return ServiceBuilder
*/
public static function getServiceBuilder()
{
if (!self::$serviceBuilder) {
throw new RuntimeException('No service builder has been set via setServiceBuilder()');
}
return self::$serviceBuilder;
}
/**
* Check if an event dispatcher has a subscriber
*
* @param HasDispatcherInterface $dispatcher
* @param EventSubscriberInterface $subscriber
*
* @return bool
*/
protected function hasSubscriber(HasDispatcherInterface $dispatcher, EventSubscriberInterface $subscriber)
{
$class = get_class($subscriber);
$all = array_keys(call_user_func(array($class, 'getSubscribedEvents')));
foreach ($all as $i => $event) {
foreach ($dispatcher->getEventDispatcher()->getListeners($event) as $e) {
if ($e[0] === $subscriber) {
unset($all[$i]);
break;
}
}
}
return count($all) == 0;
}
/**
* Get a wildcard observer for an event dispatcher
*
* @param HasEventDispatcherInterface $hasEvent
*
* @return MockObserver
*/
public function getWildcardObserver(HasDispatcherInterface $hasDispatcher)
{
$class = get_class($hasDispatcher);
$o = new MockObserver();
$events = call_user_func(array($class, 'getAllEvents'));
foreach ($events as $event) {
$hasDispatcher->getEventDispatcher()->addListener($event, array($o, 'update'));
}
return $o;
}
/**
* Set the mock response base path
*
* @param string $path Path to mock response folder
*
* @return GuzzleTestCase
*/
public static function setMockBasePath($path)
{
self::$mockBasePath = $path;
}
/**
* Mark a request as being mocked
*
* @param RequestInterface $request
*/
public function addMockedRequest(RequestInterface $request)
{
$this->requests[] = $request;
return $this;
}
/**
* Get all of the mocked requests
*
* @return array
*/
public function getMockedRequests()
{
return $this->requests;
}
/**
* Get a mock response for a client by mock file name
*
* @param string $path Relative path to the mock response file
*
* @return Response
*/
public function getMockResponse($path)
{
return MockPlugin::getMockFile(self::$mockBasePath . DIRECTORY_SEPARATOR . $path);
}
/**
* Set a mock response from a mock file on the next client request.
*
* This method assumes that mock response files are located under the
* Command/Mock/ directory of the Service being tested
* (e.g. Unfuddle/Command/Mock/). A mock response is added to the next
* request sent by the client.
*
* @param Client $client Client object to modify
* @param string $paths Path to files within the Mock folder of the service
*
* @return MockPlugin returns the created mock plugin
*/
public function setMockResponse(Client $client, $paths)
{
$this->requests = array();
$that = $this;
$mock = new MockPlugin(null, true);
$client->getEventDispatcher()->removeSubscriber($mock);
$mock->getEventDispatcher()->addListener('mock.request', function(Event $event) use ($that) {
$that->addMockedRequest($event['request']);
});
foreach ((array) $paths as $path) {
$mock->addResponse($this->getMockResponse($path));
}
$client->getEventDispatcher()->addSubscriber($mock);
return $mock;
}
/**
* Compare HTTP headers and use special markup to filter values
* A header prefixed with '!' means it must not exist
* A header prefixed with '_' means it must be ignored
* A header value of '*' means anything after the * will be ignored
*
* @param array $filteredHeaders Array of special headers
* @param array $actualHeaders Array of headers to check against
*
* @return array|false Returns an array of the differences or FALSE if none
*/
public function compareHeaders($filteredHeaders, $actualHeaders)
{
$comparison = new HeaderComparison();
return $comparison->compare($filteredHeaders, $actualHeaders);
}
/**
* Case insensitive assertContains
*
* @param string $needle Search string
* @param string $haystack Search this
* @param string $message Optional failure message
*/
public function assertContainsIns($needle, $haystack, $message = null)
{
$this->assertContains(strtolower($needle), strtolower($haystack), $message);
}
}
tests/Guzzle/Tests/Http/ClientTest.php 0000644 00000050163 15174272742 0014016 0 ustar 00 assertEquals('http://www.google.com/', $client->getBaseUrl());
$this->assertSame($client, $client->setConfig(array(
'test' => '123'
)));
$this->assertEquals(array('test' => '123'), $client->getConfig()->getAll());
$this->assertEquals('123', $client->getConfig('test'));
$this->assertSame($client, $client->setBaseUrl('http://www.test.com/{{test}}'));
$this->assertEquals('http://www.test.com/123', $client->getBaseUrl());
$this->assertEquals('http://www.test.com/{{test}}', $client->getBaseUrl(false));
try {
$client->setConfig(false);
} catch (\InvalidArgumentException $e) {
}
}
/**
* @covers Guzzle\Http\Client::getAllEvents
*/
public function testDescribesEvents()
{
$this->assertEquals(array('client.create_request'), Client::getAllEvents());
}
/**
* @covers Guzzle\Http\Client::__toString
*/
public function testConvertsToString()
{
$client = new Client();
$hash = spl_object_hash($client);
$this->assertEquals($hash, (string) $client);
}
/**
* @covers Guzzle\Http\Client::__construct
*/
public function testConstructorCanAcceptConfig()
{
$client = new Client('http://www.test.com/', array(
'data' => '123'
));
$this->assertEquals('123', $client->getConfig('data'));
}
/**
* @covers Guzzle\Http\Client::setConfig
*/
public function testCanUseCollectionAsConfig()
{
$client = new Client('http://www.google.com/');
$client->setConfig(new Collection(array(
'api' => 'v1',
'key' => 'value',
'base_url' => 'http://www.google.com/'
)));
$this->assertEquals('v1', $client->getConfig('api'));
}
/**
* @covers Guzzle\Http\Client
*/
public function testExpandsUriTemplatesUsingConfig()
{
$client = new Client('http://www.google.com/');
$client->setConfig(array(
'api' => 'v1',
'key' => 'value',
'foo' => 'bar'
));
$this->assertEquals('Testing...api/v1/key/value', $client->expandTemplate('Testing...api/{api}/key/{{key}}'));
// Make sure that the client properly validates and injects config
$this->assertEquals('bar', $client->getConfig('foo'));
}
/**
* @covers Guzzle\Http\Client::__construct
* @covers Guzzle\Http\Client::createRequest
*/
public function testClientAttachersObserversToRequests()
{
$this->getServer()->flush();
$this->getServer()->enqueue("HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n");
$client = new Client($this->getServer()->getUrl());
$logPlugin = $this->getLogPlugin();
$client->getEventDispatcher()->addSubscriber($logPlugin);
// Get a request from the client and ensure the the observer was
// attached to the new request
$request = $client->createRequest();
$this->assertTrue($this->hasSubscriber($request, $logPlugin));
}
/**
* @covers Guzzle\Http\Client::getBaseUrl
* @covers Guzzle\Http\Client::setBaseUrl
*/
public function testClientReturnsValidBaseUrls()
{
$client = new Client('http://www.{{foo}}.{{data}}/', array(
'data' => '123',
'foo' => 'bar'
));
$this->assertEquals('http://www.bar.123/', $client->getBaseUrl());
$client->setBaseUrl('http://www.google.com/');
$this->assertEquals('http://www.google.com/', $client->getBaseUrl());
}
/**
* @covers Guzzle\Http\Client::setUserAgent
* @covers Guzzle\Http\Client::createRequest
* @covers Guzzle\Http\Client::prepareRequest
*/
public function testSetsUserAgent()
{
$client = new Client('http://www.test.com/', array(
'api' => 'v1'
));
$this->assertSame($client, $client->setUserAgent('Test/1.0Ab', true));
$this->assertEquals('Test/1.0Ab ' . Utils::getDefaultUserAgent(), $client->get()->getHeader('User-Agent'));
$client->setUserAgent('Test/1.0Ab');
$this->assertEquals('Test/1.0Ab', $client->get()->getHeader('User-Agent'));
}
/**
* @covers Guzzle\Http\Client::createRequest
* @covers Guzzle\Http\Client::prepareRequest
*/
public function testClientAddsCurlOptionsToRequests()
{
$client = new Client('http://www.test.com/', array(
'api' => 'v1',
// Adds the option using the curl values
'curl.CURLOPT_HTTPAUTH' => 'CURLAUTH_DIGEST',
'curl.abc' => 'not added',
'curl.blacklist' => 'abc'
));
$request = $client->createRequest();
$options = $request->getCurlOptions();
$this->assertEquals(CURLAUTH_DIGEST, $options->get(CURLOPT_HTTPAUTH));
$this->assertNull($options->get('curl.abc'));
$this->assertNull($options->get('curl.blacklist'));
}
/**
* @covers Guzzle\Http\Client::createRequest
* @covers Guzzle\Http\Client::prepareRequest
*/
public function testClientAddsCustomCurlOptionsToRequests()
{
$client = new Client('http://www.test.com/', array(
'api' => 'v1',
'curl.disable_wire' => true,
'curl.foo' => 'bar'
));
$request = $client->createRequest();
$this->assertTrue($request->getCurlOptions()->get('disable_wire'));
$this->assertEquals('bar', $request->getCurlOptions()->get('foo'));
}
/**
* @covers Guzzle\Http\Client::prepareRequest
*/
public function testClientAddsParamsToRequests()
{
$client = new Client('http://www.example.com', array(
'api' => 'v1',
'params.foo' => 'bar',
'params.baz' => 'jar',
));
$request = $client->createRequest();
$this->assertEquals('bar', $request->getParams()->get('foo'));
$this->assertEquals('jar', $request->getParams()->get('baz'));
}
public function urlProvider()
{
$u = $this->getServer()->getUrl() . 'base/';
$u2 = $this->getServer()->getUrl() . 'base?z=1';
return array(
array($u, '', $u),
array($u, 'relative/path/to/resource', $u . 'relative/path/to/resource'),
array($u, 'relative/path/to/resource?a=b&c=d', $u . 'relative/path/to/resource?a=b&c=d'),
array($u, '/absolute/path/to/resource', $this->getServer()->getUrl() . 'absolute/path/to/resource'),
array($u, '/absolute/path/to/resource?a=b&c=d', $this->getServer()->getUrl() . 'absolute/path/to/resource?a=b&c=d'),
array($u2, '/absolute/path/to/resource?a=b&c=d', $this->getServer()->getUrl() . 'absolute/path/to/resource?a=b&c=d'),
array($u2, 'relative/path/to/resource', $this->getServer()->getUrl() . 'base/relative/path/to/resource?z=1'),
array($u2, 'relative/path/to/resource?another=query', $this->getServer()->getUrl() . 'base/relative/path/to/resource?z=1&another=query')
);
}
/**
* @dataProvider urlProvider
* @covers Guzzle\Http\Client::createRequest
*/
public function testBuildsRelativeUrls($baseUrl, $url, $result)
{
$client = new Client($baseUrl);
$this->assertEquals($client->get($url)->getUrl(), $result);
}
/**
* @covers Guzzle\Http\Client
*/
public function testAllowsConfigsToBeChangedAndInjectedInBaseUrl()
{
$client = new Client('http://{{a}}/{{b}}');
$this->assertEquals('http:///', $client->getBaseUrl());
$this->assertEquals('http://{{a}}/{{b}}', $client->getBaseUrl(false));
$client->setConfig(array(
'a' => 'test.com',
'b' => 'index.html'
));
$this->assertEquals('http://test.com/index.html', $client->getBaseUrl());
}
/**
* @covers Guzzle\Http\Client::createRequest
*/
public function testCreatesRequestsWithDefaultValues()
{
$client = new Client($this->getServer()->getUrl() . 'base');
// Create a GET request
$request = $client->createRequest();
$this->assertEquals('GET', $request->getMethod());
$this->assertEquals($client->getBaseUrl(), $request->getUrl());
// Create a DELETE request
$request = $client->createRequest('DELETE');
$this->assertEquals('DELETE', $request->getMethod());
$this->assertEquals($client->getBaseUrl(), $request->getUrl());
// Create a HEAD request with custom headers
$request = $client->createRequest('HEAD', 'http://www.test.com/');
$this->assertEquals('HEAD', $request->getMethod());
$this->assertEquals('http://www.test.com/', $request->getUrl());
// Create a PUT request
$request = $client->createRequest('PUT');
$this->assertEquals('PUT', $request->getMethod());
// Create a PUT request with injected config
$client->getConfig()->set('a', 1)->set('b', 2);
$request = $client->createRequest('PUT', '/path/{{a}}?q={{b}}');
$this->assertEquals($request->getUrl(), $this->getServer()->getUrl() . 'path/1?q=2');
}
/**
* @covers Guzzle\Http\Client::get
* @covers Guzzle\Http\Client::delete
* @covers Guzzle\Http\Client::head
* @covers Guzzle\Http\Client::put
* @covers Guzzle\Http\Client::post
* @covers Guzzle\Http\Client::options
* @covers Guzzle\Http\Client::patch
*/
public function testClientHasHelperMethodsForCreatingRequests()
{
$url = $this->getServer()->getUrl();
$client = new Client($url . 'base');
$this->assertEquals('GET', $client->get()->getMethod());
$this->assertEquals('PUT', $client->put()->getMethod());
$this->assertEquals('POST', $client->post()->getMethod());
$this->assertEquals('HEAD', $client->head()->getMethod());
$this->assertEquals('DELETE', $client->delete()->getMethod());
$this->assertEquals('OPTIONS', $client->options()->getMethod());
$this->assertEquals('PATCH', $client->patch()->getMethod());
$this->assertEquals($url . 'base/abc', $client->get('abc')->getUrl());
$this->assertEquals($url . 'zxy', $client->put('/zxy')->getUrl());
$this->assertEquals($url . 'zxy?a=b', $client->post('/zxy?a=b')->getUrl());
$this->assertEquals($url . 'base?a=b', $client->head('?a=b')->getUrl());
$this->assertEquals($url . 'base?a=b', $client->delete('/base?a=b')->getUrl());
}
/**
* @covers Guzzle\Http\Client::createRequest
*/
public function testClientInjectsConfigsIntoUrls()
{
$client = new Client('http://www.test.com/api/v1', array(
'test' => '123'
));
$request = $client->get('relative/{{test}}');
$this->assertEquals('http://www.test.com/api/v1/relative/123', $request->getUrl());
}
/**
* @covers Guzzle\Http\Client
*/
public function testAllowsEmptyBaseUrl()
{
$client = new Client();
$request = $client->get('http://www.google.com/');
$this->assertEquals('http://www.google.com/', $request->getUrl());
$request->setResponse(new Response(200), true);
$request->send();
}
/**
* @covers Guzzle\Http\Client::send
* @covers Guzzle\Http\Client::setCurlMulti
* @covers Guzzle\Http\Client::getCurlMulti
*/
public function testAllowsCustomCurlMultiObjects()
{
$mock = $this->getMock('Guzzle\\Http\\Curl\\CurlMulti', array('add', 'send'));
$mock->expects($this->once())
->method('add');
$mock->expects($this->once())
->method('send');
$client = new Client();
$client->setCurlMulti($mock);
$request = $client->get();
$request->setResponse(new Response(200), true);
$client->send($request);
}
/**
* @covers Guzzle\Http\Client::send
*/
public function testClientSendsMultipleRequests()
{
$client = new Client($this->getServer()->getUrl());
$mock = new MockPlugin();
$responses = array(
new Response(200),
new Response(201),
new Response(202)
);
$mock->addResponse($responses[0]);
$mock->addResponse($responses[1]);
$mock->addResponse($responses[2]);
$client->getEventDispatcher()->addSubscriber($mock);
$requests = array(
$client->get(),
$client->head(),
$client->put('/', null, 'test')
);
$this->assertEquals(array(
$responses[0],
$responses[1],
$responses[2]
), $client->send($requests));
}
/**
* @covers Guzzle\Http\Client::send
*/
public function testClientSendsSingleRequest()
{
$client = new Client($this->getServer()->getUrl());
$mock = new MockPlugin();
$response = new Response(200);
$mock->addResponse($response);
$client->getEventDispatcher()->addSubscriber($mock);
$this->assertEquals($response, $client->send($client->get()));
}
/**
* @covers Guzzle\Http\Client::send
* @expectedException Guzzle\Http\Exception\BadResponseException
*/
public function testClientThrowsExceptionForSingleRequest()
{
$client = new Client($this->getServer()->getUrl());
$mock = new MockPlugin();
$response = new Response(404);
$mock->addResponse($response);
$client->getEventDispatcher()->addSubscriber($mock);
$client->send($client->get());
}
/**
* @covers Guzzle\Http\Client::send
* @expectedException Guzzle\Common\Exception\ExceptionCollection
*/
public function testClientThrowsExceptionForMultipleRequests()
{
$client = new Client($this->getServer()->getUrl());
$mock = new MockPlugin();
$mock->addResponse(new Response(200));
$mock->addResponse(new Response(404));
$client->getEventDispatcher()->addSubscriber($mock);
$client->send(array($client->get(), $client->head()));
}
/**
* @covers Guzzle\Http\Client
*/
public function testQueryStringsAreNotDoubleEncoded()
{
$client = new Client('http://test.com', array(
'path' => array('foo', 'bar'),
'query' => 'hi there',
'data' => array(
'test' => 'a&b'
)
));
$request = $client->get('{/path*}{?query,data*}');
$this->assertEquals('http://test.com/foo/bar?query=hi%20there&test=a%26b', $request->getUrl());
$this->assertEquals('hi there', $request->getQuery()->get('query'));
$this->assertEquals('a&b', $request->getQuery()->get('test'));
}
/**
* @covers Guzzle\Http\Client
*/
public function testQueryStringsAreNotDoubleEncodedUsingAbsolutePaths()
{
$client = new Client('http://test.com', array(
'path' => array('foo', 'bar'),
'query' => 'hi there',
));
$request = $client->get('http://test.com{?query}');
$this->assertEquals('http://test.com/?query=hi%20there', $request->getUrl());
$this->assertEquals('hi there', $request->getQuery()->get('query'));
}
/**
* @covers Guzzle\Http\Client::setUriTemplate
* @covers Guzzle\Http\Client::getUriTemplate
*/
public function testAllowsUriTemplateInjection()
{
$client = new Client('http://test.com', array(
'path' => array('foo', 'bar'),
'query' => 'hi there',
));
$a = $client->getUriTemplate();
$this->assertSame($a, $client->getUriTemplate());
$client->setUriTemplate(new UriTemplate());
$this->assertNotSame($a, $client->getUriTemplate());
}
/**
* @covers Guzzle\Http\Client::expandTemplate
*/
public function testAllowsCustomVariablesWhenExpandingTemplates()
{
$client = new Client('http://test.com', array(
'test' => 'hi',
));
$uri = $client->expandTemplate('http://{test}{?query*}', array(
'query' => array(
'han' => 'solo'
)
));
$this->assertEquals('http://hi?han=solo', $uri);
}
/**
* @covers Guzzle\Http\Client::createRequest
* @expectedException InvalidArgumentException
*/
public function testUriArrayMustContainExactlyTwoElements()
{
$client = new Client();
$client->createRequest('GET', array('haha!'));
}
/**
* @covers Guzzle\Http\Client::createRequest
* @expectedException InvalidArgumentException
*/
public function testUriArrayMustContainAnArray()
{
$client = new Client();
$client->createRequest('GET', array('haha!', 'test'));
}
/**
* @covers Guzzle\Http\Client::createRequest
* @covers Guzzle\Http\Client::get
* @covers Guzzle\Http\Client::put
* @covers Guzzle\Http\Client::post
* @covers Guzzle\Http\Client::head
* @covers Guzzle\Http\Client::options
*/
public function testUriArrayAllowsCustomTemplateVariables()
{
$client = new Client();
$vars = array(
'var' => 'hi'
);
$this->assertEquals('/hi', (string) $client->createRequest('GET', array('/{var}', $vars))->getUrl());
$this->assertEquals('/hi', (string) $client->get(array('/{var}', $vars))->getUrl());
$this->assertEquals('/hi', (string) $client->put(array('/{var}', $vars))->getUrl());
$this->assertEquals('/hi', (string) $client->post(array('/{var}', $vars))->getUrl());
$this->assertEquals('/hi', (string) $client->head(array('/{var}', $vars))->getUrl());
$this->assertEquals('/hi', (string) $client->options(array('/{var}', $vars))->getUrl());
}
/**
* @covers Guzzle\Http\Client::setDefaultHeaders
* @covers Guzzle\Http\Client::getDefaultHeaders
* @covers Guzzle\Http\Client::createRequest
*/
public function testAllowsDefaultHeaders()
{
$default = array(
'X-Test' => 'Hi!'
);
$other = array(
'X-Other' => 'Foo'
);
$client = new Client();
$client->setDefaultHeaders($default);
$this->assertEquals($default, $client->getDefaultHeaders()->getAll());
$client->setDefaultHeaders(new Collection($default));
$this->assertEquals($default, $client->getDefaultHeaders()->getAll());
$request = $client->createRequest('GET', null, $other);
$this->assertEquals('Hi!', $request->getHeader('X-Test'));
$this->assertEquals('Foo', $request->getHeader('X-Other'));
$request = $client->createRequest('GET', null, new Collection($other));
$this->assertEquals('Hi!', $request->getHeader('X-Test'));
$this->assertEquals('Foo', $request->getHeader('X-Other'));
$request = $client->createRequest('GET');
$this->assertEquals('Hi!', $request->getHeader('X-Test'));
}
/**
* @covers Guzzle\Http\Client::setDefaultHeaders
* @expectedException InvalidArgumentException
*/
public function testValidatesDefaultHeaders()
{
$client = new Client();
$client->setDefaultHeaders('foo');
}
}
tests/Guzzle/Tests/Http/CookieJar/ArrayCookieJarTest.php 0000644 00000030154 15174272742 0017311 0 ustar 00 jar = new ArrayCookieJar();
}
/**
* Add values to the cookiejar
*/
public static function addCookies(CookieJarInterface $jar)
{
$jar->save(array(
'cookie' => array('foo', 'bar'),
'domain' => 'example.com',
'path' => '/',
'max_age' => '86400',
'port' => array(80, 8080),
'version' => '1',
'secure' => true
))->save(array(
'cookie' => array('baz', 'foobar'),
'domain' => 'example.com',
'path' => '/',
'max_age' => '86400',
'port' => array(80, 8080),
'version' => '1',
'secure' => true
))->save(array(
'cookie' => array('test', '123'),
'domain' => 'www.foobar.com',
'path' => '/path/',
'discard' => true
))->save(array(
'domain' => '.y.example.com',
'path' => '/acme/',
'cookie' => array('muppet', 'cookie_monster'),
'comment' => 'Comment goes here...',
'expires' => Utils::getHttpDate('+1 day')
))->save(array(
'domain' => '.example.com',
'path' => '/test/acme/',
'cookie' => array('googoo', 'gaga'),
'max_age' => 1500,
'version' => 2
));
}
/**
* Provides test data for cookie jar retrieval
*/
public function getCookiesDataProvider()
{
return array(
array(array('foo', 'baz', 'test', 'muppet', 'googoo'), '', '', '', false),
array(array('foo', 'baz', 'muppet', 'googoo'), '', '', '', true),
array(array('googoo'), 'www.example.com', '', '', false),
array(array('muppet', 'googoo'), 'test.y.example.com', '', '', false),
array(array('foo', 'baz'), 'example.com', '', '', false),
array(array('muppet'), 'x.y.example.com', '/acme/', '', false),
array(array('muppet'), 'x.y.example.com', '/acme/test/', '', false),
array(array('googoo'), 'x.y.example.com', '/test/acme/test/', '', false),
array(array('foo', 'baz'), 'example.com', '', '', false),
array(array('baz'), 'example.com', '', 'baz', false),
);
}
/**
* @covers Guzzle\Http\CookieJar\ArrayCookieJar
*/
public function testStoresAndRetrievesCookies()
{
$j = $this->jar;
$this->assertSame($j, $j->save(array(
'cookie' => array('foo', 'bar'),
'domain' => '.example.com',
'path' => '/',
'max_age' => '86400',
'port' => array(80, 8080),
'version' => '1',
'secure' => true
)));
$this->assertSame($j, $j->save(array(
'cookie' => array('baz', 'foobar'),
'domain' => '.example.com',
'path' => '/',
'max_age' => '86400',
'port' => array(80, 8080),
'version' => '1',
'secure' => true
)));
$this->assertSame($j, $j->save(array(
'cookie' => array('test', '123'),
'domain' => 'www.foobar.com',
'path' => '/path/'
)));
$this->assertEquals(array(
array (
'cookie' => array('foo', 'bar'),
'domain' => '.example.com',
'path' => '/',
'max_age' => '86400',
'port' => array(80, 8080),
'version' => '1',
'secure' => true,
'expires' => time() + 86400,
'comment' => NULL,
'comment_url' => NULL,
'discard' => NULL,
'http_only' => false
),
array (
'cookie' => array('baz', 'foobar'),
'domain' => '.example.com',
'path' => '/',
'max_age' => '86400',
'port' => array(
0 => 80,
1 => 8080,
),
'version' => '1',
'secure' => true,
'expires' => time() + 86400,
'comment' => NULL,
'comment_url' => NULL,
'discard' => NULL,
'http_only' => false
),
array (
'cookie' => array('test' , '123'),
'domain' => 'www.foobar.com',
'path' => '/path/',
'max_age' => 0,
'comment' => NULL,
'comment_url' => NULL,
'port' => array (),
'secure' => NULL,
'expires' => null,
'discard' => NULL,
'version' => null,
'http_only' => false
),
), $j->getCookies());
}
/**
* Checks if cookies (by name) are present in a cookieJar
*
* @param array $cookies Cookies from the cookie jar
* @param array $names Names to check for
*
* @return true
*/
protected function hasCookies(array $cookies, array $names)
{
$remaining = $names;
$extra = array();
foreach ($cookies as $cookie) {
$match = false;
foreach ($remaining as $ri => $c) {
if ($cookie['cookie'][0] == $c) {
unset($remaining[$ri]);
$match = true;
}
}
if (!$match) {
$extra[] = $cookie['cookie'][0] . '=' . $cookie['cookie'][1];
}
}
$this->assertTrue(count($remaining) == 0 && count($extra) == 0, 'Unmatched: ' . implode(', ', $remaining) . ' | Extra: ' . implode(', ', $extra));
}
/**
* @covers Guzzle\Http\CookieJar\ArrayCookieJar
* @dataProvider getCookiesDataProvider
*/
public function testGetCookies(array $matches, $domain = null, $path = null, $name = null, $skipDiscardable = false)
{
self::addCookies($this->jar);
$cookies = $this->jar->getCookies($domain, $path, $name, $skipDiscardable);
$this->hasCookies($cookies, $matches);
}
/**
* @covers Guzzle\Http\CookieJar\ArrayCookieJar
*/
public function testClearsTemporaryCookies()
{
self::addCookies($this->jar);
$this->assertEquals(1, $this->jar->clearTemporary());
$this->hasCookies($this->jar->getCookies(), array('foo', 'baz', 'muppet', 'googoo'));
// Doesn't clear anything out because nothing is temporary
$this->assertEquals(0, $this->jar->clearTemporary());
// Add an expired cookie
$this->jar->save(array(
'cookie' => array('data', 'abc'),
'domain' => '.example.com'
));
// Filters out expired cookies
$this->hasCookies($this->jar->getCookies(), array('foo', 'baz', 'muppet', 'googoo', 'data'));
// Removes the expired cookie
$this->assertEquals(1, $this->jar->clearTemporary());
$this->hasCookies($this->jar->getCookies(), array('foo', 'baz', 'muppet', 'googoo'));
}
/**
* @covers Guzzle\Http\CookieJar\ArrayCookieJar
*/
public function testClearsExpiredCookies()
{
self::addCookies($this->jar);
$this->assertEquals(0, $this->jar->deleteExpired());
// Add an expired cookie
$this->jar->save(array(
'cookie' => array('data', 'abc'),
'expires' => Utils::getHttpDate('-1 day'),
'domain' => '.example.com'
));
// Filters out expired cookies
$this->hasCookies($this->jar->getCookies(), array('foo', 'baz', 'test', 'muppet', 'googoo'));
$this->assertEquals(1, $this->jar->deleteExpired());
$this->assertEquals(0, $this->jar->deleteExpired());
}
/**
* @covers Guzzle\Http\CookieJar\ArrayCookieJar
* @expectedException InvalidArgumentException
* @expectedExceptionMessage Cookies require a domain
*/
public function testValidatesDomainWhenSaving()
{
$this->jar->save(array());
}
/**
* @covers Guzzle\Http\CookieJar\ArrayCookieJar
* @expectedException InvalidArgumentException
* @expectedExceptionMessage Cookies require a names and values
*/
public function testValidatesCookiesArePresentWhenSaving()
{
$this->jar->save(array(
'domain' => '.test.com'
));
}
/**
* Provides test data for cookie jar clearing
*/
public function clearCookiesDataProvider()
{
return array(
array(array(), 4, '', '', '', ''),
array(array('test', 'muppet', 'googoo'), 1, 'example.com', '', ''),
array(array('foo', 'baz', 'test'), 2, 'a.y.example.com', '', ''),
array(array('foo', 'baz', 'test', 'googoo'), 1, 'a.y.example.com', '/acme/', ''),
// Removes only baz from the cookie that contains two values
array(array('test', 'muppet', 'googoo', 'foo'), 1, 'example.com', '/', 'baz'),
array(array('foo', 'baz', 'test', 'muppet'), 1, 'www.example.com', '/test/acme/', '')
);
}
/**
* @covers Guzzle\Http\CookieJar\ArrayCookieJar
* @dataProvider clearCookiesDataProvider
*/
public function testClearsCookies($matches, $total, $domain, $path, $name)
{
self::addCookies($this->jar);
$this->jar->clear($domain, $path, $name);
$this->hasCookies($this->jar->getCookies(null, null, null, null, false, true), $matches);
}
/**
* @covers Guzzle\Http\CookieJar\ArrayCookieJar
*/
public function testDoesNotAddDuplicates()
{
$this->jar->clear();
$this->assertEquals(0, count($this->jar->getCookies()));
$data = array(
'cookie' => array('foo', 'bar'),
'domain' => '.example.com',
'path' => '/',
'max_age' => '86400',
'port' => array(80, 8080),
'version' => '1',
'secure' => true
);
$this->jar->save($data);
$this->jar->save($data);
$this->assertEquals(1, count($this->jar->getCookies()));
}
/**
* @covers Guzzle\Http\CookieJar\ArrayCookieJar
*/
public function testOverwritesCookiesThatAreOlderOrDiscardable()
{
$this->jar->clear();
$t = time() + 1000;
$data = array(
'cookie' => array('foo', 'bar'),
'domain' => '.example.com',
'path' => '/',
'max_age' => '86400',
'port' => array(80, 8080),
'version' => '1',
'secure' => true,
'discard' => true,
'expires' => $t
);
// Make sure that the discard cookie is overridden with the non-discard
$this->jar->save($data);
unset($data['discard']);
$this->jar->save($data);
$this->assertEquals(1, count($this->jar->getCookies()));
$c = $this->jar->getCookies();
$this->assertEquals(false, $c[0]['discard']);
$this->assertEquals($t, $c[0]['expires']);
// Make sure it doesn't duplicate the cookie
$this->jar->save($data);
$this->assertEquals(1, count($this->jar->getCookies()));
// Make sure the more future-ful expiration date supercedes the other
$data['expires'] = time() + 2000;
$this->jar->save($data);
$this->assertEquals(1, count($this->jar->getCookies()));
$c = $this->jar->getCookies();
$this->assertNotEquals($t, $c[0]['expires']);
}
/**
* @covers Guzzle\Http\CookieJar\ArrayCookieJar::serialize
* @covers Guzzle\Http\CookieJar\ArrayCookieJar::unserialize
*/
public function testSerialization()
{
$j = $this->jar;
static::addCookies($j);
$c = count($j->getCookies());
$deflate = serialize($j);
$inflate = unserialize($deflate);
$this->assertEquals($c, count($inflate->getCookies()));
}
}
tests/Guzzle/Tests/Http/CookieJar/FileCookieJarTest.php 0000644 00000004716 15174272742 0017117 0 ustar 00 file = tempnam('/tmp', 'file-cookies');
$this->jar = new FileCookieJar($this->file);
}
/**
* Add values to the cookiejar
*/
protected function addCookies()
{
$this->jar->save(array(
'cookie' => array('foo', 'bar'),
'domain' => 'example.com',
'path' => '/',
'max_age' => '86400',
'port' => array(80, 8080),
'version' => '1',
'secure' => true
))->save(array(
'cookie' => array('test', '123'),
'domain' => 'www.foobar.com',
'path' => '/path/',
'discard' => true
))->save(array(
'domain' => '.y.example.com',
'path' => '/acme/',
'cookie' => array('muppet', 'cookie_monster'),
'comment' => 'Comment goes here...',
'expires' => Utils::getHttpDate('+1 day')
))->save(array(
'domain' => '.example.com',
'path' => '/test/acme/',
'cookie' => array('googoo', 'gaga'),
'max_age' => 1500,
'version' => 2
));
}
/**
* @covers Guzzle\Http\CookieJar\FileCookieJar
*/
public function testLoadsFromFileFile()
{
unset($this->jar);
$this->jar = new FileCookieJar($this->file);
$this->assertEquals(array(), $this->jar->getCookies());
unlink($this->file);
}
/**
* @covers Guzzle\Http\CookieJar\FileCookieJar
*/
public function testPersistsToFileFile()
{
unset($this->jar);
$this->jar = new FileCookieJar($this->file);
$this->addCookies();
$this->assertEquals(4, count($this->jar->getCookies()));
unset($this->jar);
// Make sure it wrote to the file
$contents = file_get_contents($this->file);
$this->assertNotEmpty($contents);
// Load the jar from the file
$jar = new FileCookieJar($this->file);
// Weeds out temporary and session cookies
$this->assertEquals(3, count($jar->getCookies()));
unset($jar);
unlink($this->file);
}
}
tests/Guzzle/Tests/Http/CookieTest.php 0000644 00000003727 15174272742 0014015 0 ustar 00 'value'
)),
array('name=value;name2=value 2', array(
'name' => 'value',
'name2' => 'value 2'
)),
array('name=value;name2=x=y&a=b', array(
'name' => 'value',
'name2' => 'x=y&a=b'
)),
);
}
/**
* @covers Guzzle\Http\Cookie::factory
* @dataProvider provider
*/
public function testFactoryBuildsCookiesFromCookieStrings($cookieString, array $data)
{
$jar = Cookie::factory($cookieString);
$this->assertEquals($data, $jar->getAll());
}
/**
* @covers Guzzle\Http\Cookie::__construct
*/
public function testConstructorSetsDefaults()
{
$jar = new Cookie();
$this->assertEquals(';', $jar->getFieldSeparator());
$this->assertEquals('=', $jar->getValueSeparator());
$this->assertEquals(false, $jar->isEncodingFields());
$this->assertEquals(false, $jar->isEncodingValues());
$this->assertEquals('', $jar->getPrefix());
}
/**
* @covers Guzzle\Http\QueryString::__toString
* @dataProvider provider
*/
public function testConvertsToString($cookieString)
{
$cookie = Cookie::factory($cookieString);
$this->assertEquals($cookieString, (string) $cookie);
}
/**
* @covers Guzzle\Http\QueryString
* @covers Guzzle\Http\Cookie
*/
public function testAggregatesMultipleCookieValues()
{
$cookie = Cookie::factory('name=a;name=b');
$this->assertEquals(array('a', 'b'), $cookie->get('name'));
$this->assertEquals('name=a;name=b', (string) $cookie);
}
}
tests/Guzzle/Tests/Http/Curl/CurlHandleTest.php 0000644 00000100074 15174272742 0015523 0 ustar 00 getServer()->getUrl());
try {
$ha = new CurlHandle($h, false);
$this->fail('Expected InvalidArgumentException');
} catch (\InvalidArgumentException $e) {
}
$ha = new CurlHandle($h, array(
CURLOPT_URL => $this->getServer()->getUrl()
));
$this->assertEquals($this->getServer()->getUrl(), $ha->getOptions()->get(CURLOPT_URL));
$ha = new CurlHandle($h, new Collection(array(
CURLOPT_URL => $this->getServer()->getUrl()
)));
$this->assertEquals($this->getServer()->getUrl(), $ha->getOptions()->get(CURLOPT_URL));
}
/**
* @covers Guzzle\Http\Curl\CurlHandle::__construct
* @covers Guzzle\Http\Curl\CurlHandle::getHandle
* @covers Guzzle\Http\Curl\CurlHandle::getUrl
* @covers Guzzle\Http\Curl\CurlHandle::getOptions
*/
public function testConstructorInitializesObject()
{
$handle = curl_init($this->getServer()->getUrl());
$h = new CurlHandle($handle, array(
CURLOPT_URL => $this->getServer()->getUrl()
));
$this->assertSame($handle, $h->getHandle());
$this->assertInstanceOf('Guzzle\\Http\\Url', $h->getUrl());
$this->assertEquals($this->getServer()->getUrl(), (string) $h->getUrl());
$this->assertEquals($this->getServer()->getUrl(), $h->getOptions()->get(CURLOPT_URL));
}
/**
* @covers Guzzle\Http\Curl\CurlHandle::getStderr
*/
public function testStoresStdErr()
{
$h = CurlHandle::factory(RequestFactory::getInstance()->create('GET', 'http://test.com'));
$this->assertEquals($h->getStderr(true), $h->getOptions()->get(CURLOPT_STDERR));
$this->assertInternalType('resource', $h->getStderr(true));
$this->assertInternalType('string', $h->getStderr(false));
$r = $h->getStderr(true);
fwrite($r, 'test');
$this->assertEquals('test', $h->getStderr(false));
}
/**
* @covers Guzzle\Http\Curl\CurlHandle::setErrorNo
* @covers Guzzle\Http\Curl\CurlHandle::getErrorNo
*/
public function testStoresCurlErrorNumber()
{
$h = new CurlHandle(curl_init('http://test.com'), array(CURLOPT_URL => 'http://test.com'));
$this->assertEquals(CURLE_OK, $h->getErrorNo());
$h->setErrorNo(CURLE_OPERATION_TIMEOUTED);
$this->assertEquals(CURLE_OPERATION_TIMEOUTED, $h->getErrorNo());
}
/**
* @covers Guzzle\Http\Curl\CurlHandle::getStderr
*/
public function testAccountsForMissingStdErr()
{
$handle = curl_init('http://www.test.com/');
$h = new CurlHandle($handle, array(
CURLOPT_URL => 'http://www.test.com/'
));
$this->assertNull($h->getStderr(false));
}
/**
* @covers Guzzle\Http\Curl\CurlHandle::isAvailable
*/
public function testDeterminesIfResourceIsAvailable()
{
$handle = curl_init($this->getServer()->getUrl());
$h = new CurlHandle($handle, array());
$this->assertTrue($h->isAvailable());
// Mess it up by closing the handle
curl_close($handle);
$this->assertFalse($h->isAvailable());
// Mess it up by unsetting the handle
$handle = null;
$this->assertFalse($h->isAvailable());
}
/**
* @covers Guzzle\Http\Curl\CurlHandle::getError
* @covers Guzzle\Http\Curl\CurlHandle::getErrorNo
* @covers Guzzle\Http\Curl\CurlHandle::getInfo
*/
public function testWrapsErrorsAndInfo()
{
if (!defined('CURLOPT_TIMEOUT_MS')) {
$this->markTestSkipped('Update curl');
}
$settings = array(
CURLOPT_PORT => 123,
CURLOPT_CONNECTTIMEOUT_MS => 1
);
$handle = curl_init($this->getServer()->getUrl());
curl_setopt_array($handle, $settings);
$h = new CurlHandle($handle, $settings);
@curl_exec($handle);
$errors = array(
CURLE_COULDNT_CONNECT => "couldn't connect to host",
CURLE_OPERATION_TIMEOUTED => 'timeout was reached'
);
$this->assertTrue(in_array(strtolower($h->getError()), $errors));
$this->assertTrue($h->getErrorNo() > 0);
$this->assertEquals($this->getServer()->getUrl(), $h->getInfo(CURLINFO_EFFECTIVE_URL));
$this->assertInternalType('array', $h->getInfo());
curl_close($handle);
$this->assertEquals(null, $h->getInfo('url'));
}
/**
* @covers Guzzle\Http\Curl\CurlHandle::getOptions
*/
public function testWrapsCurlOptions()
{
$handle = curl_init($this->getServer()->getUrl());
$h = new CurlHandle($handle, array(
CURLOPT_AUTOREFERER => true,
CURLOPT_BUFFERSIZE => 1024
));
$this->assertEquals(true, $h->getOptions()->get(CURLOPT_AUTOREFERER));
$this->assertEquals(1024, $h->getOptions()->get(CURLOPT_BUFFERSIZE));
}
/**
* Data provider for factory tests
*
* @return array
*/
public function dataProvider()
{
$testFile = __DIR__ . '/../../../../../phpunit.xml';
$postBody = new QueryString(array(
'file' => '@' . $testFile
));
$qs = new QueryString(array(
'x' => 'y',
'z' => 'a'
));
$userAgent = Utils::getDefaultUserAgent();
$auth = base64_encode('michael:123');
$testFileSize = filesize($testFile);
return array(
// Send a regular GET
array('GET', 'http://www.google.com/', null, null, array(
CURLOPT_RETURNTRANSFER => 0,
CURLOPT_HEADER => 0,
CURLOPT_FOLLOWLOCATION => 1,
CURLOPT_MAXREDIRS => 5,
CURLOPT_CONNECTTIMEOUT => 10,
CURLOPT_USERAGENT => $userAgent,
CURLOPT_WRITEFUNCTION => 'callback',
CURLOPT_HEADERFUNCTION => 'callback',
CURLOPT_ENCODING => '',
CURLOPT_HTTPHEADER => array('Host: www.google.com', 'User-Agent: ' . $userAgent),
)),
// Test that custom request methods can be used
array('TRACE', 'http://www.google.com/', null, null, array(
CURLOPT_CUSTOMREQUEST => 'TRACE'
)),
// Send a GET using a port
array('GET', 'http://127.0.0.1:8080', null, null, array(
CURLOPT_RETURNTRANSFER => 0,
CURLOPT_HEADER => 0,
CURLOPT_FOLLOWLOCATION => 1,
CURLOPT_MAXREDIRS => 5,
CURLOPT_CONNECTTIMEOUT => 10,
CURLOPT_USERAGENT => $userAgent,
CURLOPT_WRITEFUNCTION => 'callback',
CURLOPT_HEADERFUNCTION => 'callback',
CURLOPT_ENCODING => '',
CURLOPT_PORT => 8080,
CURLOPT_HTTPHEADER => array('Host: 127.0.0.1:8080', 'User-Agent: ' . $userAgent),
)),
// Send a HEAD request
array('HEAD', 'http://www.google.com/', null, null, array(
CURLOPT_RETURNTRANSFER => 0,
CURLOPT_HEADER => 0,
CURLOPT_FOLLOWLOCATION => 1,
CURLOPT_MAXREDIRS => 5,
CURLOPT_CONNECTTIMEOUT => 10,
CURLOPT_USERAGENT => $userAgent,
CURLOPT_HEADERFUNCTION => 'callback',
CURLOPT_ENCODING => '',
CURLOPT_HTTPHEADER => array('Host: www.google.com', 'User-Agent: ' . $userAgent),
CURLOPT_NOBODY => 1
)),
// Send a GET using basic auth
array('GET', 'https://michael:123@localhost/index.html?q=2', null, null, array(
CURLOPT_RETURNTRANSFER => 0,
CURLOPT_HEADER => 0,
CURLOPT_FOLLOWLOCATION => 1,
CURLOPT_MAXREDIRS => 5,
CURLOPT_CONNECTTIMEOUT => 10,
CURLOPT_USERAGENT => $userAgent,
CURLOPT_WRITEFUNCTION => 'callback',
CURLOPT_HEADERFUNCTION => 'callback',
CURLOPT_ENCODING => '',
CURLOPT_HTTPHEADER => array(
'Host: localhost',
'Authorization: Basic ' . $auth,
'User-Agent: ' . $userAgent
),
CURLOPT_PORT => 443
)),
// Send a GET request with custom headers
array('GET', 'http://localhost:8124/', array(
'x-test-data' => 'Guzzle'
), null, array(
CURLOPT_PORT => 8124,
CURLOPT_HTTPHEADER => array(
'Host: localhost:8124',
'x-test-data: Guzzle',
'User-Agent: ' . $userAgent
)
), array(
'_Accept' => '*',
'_Accept-Encoding' => '*',
'Host' => '*',
'User-Agent' => '*',
'x-test-data' => 'Guzzle'
)),
// Send a POST using a query string
array('POST', 'http://localhost:8124/post.php', null, $qs, array(
CURLOPT_RETURNTRANSFER => 0,
CURLOPT_HEADER => 0,
CURLOPT_FOLLOWLOCATION => 1,
CURLOPT_MAXREDIRS => 5,
CURLOPT_CONNECTTIMEOUT => 10,
CURLOPT_USERAGENT => $userAgent,
CURLOPT_WRITEFUNCTION => 'callback',
CURLOPT_HEADERFUNCTION => 'callback',
CURLOPT_ENCODING => '',
CURLOPT_POSTFIELDS => 'x=y&z=a',
CURLOPT_HTTPHEADER => array (
'Expect:',
'Host: localhost:8124',
'User-Agent: ' . $userAgent,
'Content-Type: application/x-www-form-urlencoded'
)
), array(
'_Accept' => '*',
'_Accept-Encoding' => '*',
'Host' => '*',
'User-Agent' => '*',
'Content-Length' => '7',
'!Expect' => null,
'Content-Type' => 'application/x-www-form-urlencoded',
'!Transfer-Encoding' => null
)),
// Send a PUT using raw data
array('PUT', 'http://localhost:8124/put.php', null, EntityBody::factory(fopen($testFile, 'r+')), array(
CURLOPT_RETURNTRANSFER => 0,
CURLOPT_HEADER => 0,
CURLOPT_FOLLOWLOCATION => 1,
CURLOPT_MAXREDIRS => 5,
CURLOPT_CONNECTTIMEOUT => 10,
CURLOPT_USERAGENT => $userAgent,
CURLOPT_WRITEFUNCTION => 'callback',
CURLOPT_HEADERFUNCTION => 'callback',
CURLOPT_READFUNCTION => 'callback',
CURLOPT_ENCODING => '',
CURLOPT_INFILESIZE => filesize($testFile),
CURLOPT_HTTPHEADER => array (
'Host: localhost:8124',
'User-Agent: ' . $userAgent,
'Expect: 100-Continue'
)
), array(
'_Accept' => '*',
'_Accept-Encoding' => '*',
'Host' => '*',
'User-Agent' => '*',
'Expect' => '100-Continue',
'Content-Length' => $testFileSize,
'!Transfer-Encoding' => null
)),
// Send a POST request using an array of fields
array('POST', 'http://localhost:8124/post.php', null, array(
'x' => 'y',
'a' => 'b'
), array(
CURLOPT_RETURNTRANSFER => 0,
CURLOPT_HEADER => 0,
CURLOPT_FOLLOWLOCATION => 1,
CURLOPT_MAXREDIRS => 5,
CURLOPT_CONNECTTIMEOUT => 10,
CURLOPT_USERAGENT => $userAgent,
CURLOPT_WRITEFUNCTION => 'callback',
CURLOPT_HEADERFUNCTION => 'callback',
CURLOPT_ENCODING => '',
CURLOPT_POST => 1,
CURLOPT_POSTFIELDS => 'x=y&a=b',
CURLOPT_HTTPHEADER => array (
'Expect:',
'Host: localhost:8124',
'User-Agent: ' . $userAgent,
'Content-Type: application/x-www-form-urlencoded'
)
), array(
'_Accept' => '*',
'_Accept-Encoding' => '*',
'Host' => '*',
'User-Agent' => '*',
'Content-Length' => '7',
'!Expect' => null,
'Content-Type' => 'application/x-www-form-urlencoded',
'!Transfer-Encoding' => null
)),
// Send a POST request using a POST file
array('POST', 'http://localhost:8124/post.php', null, $postBody, array(
CURLOPT_RETURNTRANSFER => 0,
CURLOPT_HEADER => 0,
CURLOPT_FOLLOWLOCATION => 1,
CURLOPT_MAXREDIRS => 5,
CURLOPT_CONNECTTIMEOUT => 10,
CURLOPT_USERAGENT => $userAgent,
CURLOPT_WRITEFUNCTION => 'callback',
CURLOPT_HEADERFUNCTION => 'callback',
CURLOPT_ENCODING => '',
CURLOPT_POST => 1,
CURLOPT_POSTFIELDS => array(
'file' => '@' . $testFile . ';type=application/xml'
),
CURLOPT_HTTPHEADER => array (
'Host: localhost:8124',
'User-Agent: ' . $userAgent,
'Expect: 100-Continue',
'Content-Type: multipart/form-data'
)
), array(
'_Accept' => '*',
'_Accept-Encoding' => '*',
'Host' => '*',
'User-Agent' => '*',
'Content-Length' => '*',
'Expect' => '100-Continue',
'Content-Type' => 'multipart/form-data; boundary=*',
'!Transfer-Encoding' => null
)),
// Send a POST request with raw POST data and a custom content-type
array('POST', 'http://localhost:8124/post.php', array(
'Content-Type' => 'application/json'
), '{"hi":"there"}', array(
CURLOPT_RETURNTRANSFER => 0,
CURLOPT_HEADER => 0,
CURLOPT_FOLLOWLOCATION => 1,
CURLOPT_MAXREDIRS => 5,
CURLOPT_CONNECTTIMEOUT => 10,
CURLOPT_USERAGENT => $userAgent,
CURLOPT_WRITEFUNCTION => 'callback',
CURLOPT_HEADERFUNCTION => 'callback',
CURLOPT_ENCODING => '',
CURLOPT_POST => 1,
CURLOPT_HTTPHEADER => array (
'Host: localhost:8124',
'User-Agent: ' . $userAgent,
'Expect: 100-Continue',
'Content-Type: application/json',
'Content-Length: 14'
),
), array(
'_Accept-Encoding' => '*',
'_Accept' => '*',
'Host' => '*',
'User-Agent' => '*',
'Content-Type' => 'application/json',
'Expect' => '100-Continue',
'Content-Length' => '14',
'!Transfer-Encoding' => null
)),
// Send a POST request with raw POST data, a custom content-type, and use chunked encoding
array('POST', 'http://localhost:8124/post.php', array(
'Content-Type' => 'application/json',
'Transfer-Encoding' => 'chunked'
), '{"hi":"there"}', array(
CURLOPT_RETURNTRANSFER => 0,
CURLOPT_HEADER => 0,
CURLOPT_FOLLOWLOCATION => 1,
CURLOPT_MAXREDIRS => 5,
CURLOPT_CONNECTTIMEOUT => 10,
CURLOPT_USERAGENT => $userAgent,
CURLOPT_WRITEFUNCTION => 'callback',
CURLOPT_HEADERFUNCTION => 'callback',
CURLOPT_ENCODING => '',
CURLOPT_POST => 1,
CURLOPT_HTTPHEADER => array (
'Host: localhost:8124',
'User-Agent: ' . $userAgent,
'Expect: 100-Continue',
'Content-Type: application/json',
'Transfer-Encoding: chunked'
),
), array(
'_Accept-Encoding' => '*',
'_Accept' => '*',
'Host' => '*',
'User-Agent' => '*',
'Content-Type' => 'application/json',
'Expect' => '100-Continue',
'Transfer-Encoding' => 'chunked',
'!Content-Length' => ''
)),
// Send a POST that does not have a body defined
array('POST', 'http://localhost:8124/foo.php', null, null, array(
CURLOPT_HTTPHEADER => array (
'Expect:',
'Host: localhost:8124',
'User-Agent: ' . $userAgent,
'Content-Length: 0'
)
), array(
'_Accept' => '*',
'_Accept-Encoding' => '*',
'Host' => '*',
'User-Agent' => '*',
'Content-Length' => '0',
'!Expect' => null,
'!Content-Type' => '*',
'!Transfer-Encoding' => null
)),
// Send a PUT that does not have a body defined
array('PUT', 'http://localhost:8124/empty-put.php', null, null, array(
CURLOPT_HTTPHEADER => array (
'Expect:',
'Host: localhost:8124',
'User-Agent: ' . $userAgent,
'Content-Length: 0'
)
), array(
'_Accept' => '*',
'_Accept-Encoding' => '*',
'Host' => '*',
'User-Agent' => '*',
'Content-Length' => '0',
'!Expect' => null,
'!Content-Type' => null,
'!Transfer-Encoding' => null
)),
// Send a PATCH request
array('PATCH', 'http://localhost:8124/patch.php', null, 'body', array(
CURLOPT_INFILESIZE => 4,
CURLOPT_HTTPHEADER => array (
'Host: localhost:8124',
'User-Agent: ' . $userAgent,
'Expect: 100-Continue'
)
)
/*, array(
'_Accept' => '*',
'_Accept-Encoding' => '*',
'Host' => '*',
'User-Agent' => '*',
'Content-Length' => '4',
'Expect' => '100-Continue',
'!Content-Type' => null,
'!Transfer-Encoding' => null
)*/
),
);
}
/**
* @covers Guzzle\Http\Curl\CurlHandle::factory
* @covers Guzzle\Http\Curl\CurlHandle::updateRequestFromTransfer
* @covers Guzzle\Http\Curl\RequestMediator
* @dataProvider dataProvider
*/
public function testFactoryCreatesCurlBasedOnRequest($method, $url, $headers, $body, $options, $expectedHeaders = null)
{
$request = RequestFactory::getInstance()->create($method, $url, $headers, $body);
$originalRequest = clone $request;
$curlTest = clone $request;
$handle = CurlHandle::factory($curlTest);
$this->assertInstanceOf('Guzzle\\Http\\Curl\\CurlHandle', $handle);
$o = $curlTest->getParams()->get('curl.last_options');
// Headers are case-insensitive
if (isset($o[CURLOPT_HTTPHEADER])) {
$o[CURLOPT_HTTPHEADER] = array_map('strtolower', $o[CURLOPT_HTTPHEADER]);
}
if (isset($options[CURLOPT_HTTPHEADER])) {
$options[CURLOPT_HTTPHEADER] = array_map('strtolower', $options[CURLOPT_HTTPHEADER]);
}
$check = 0;
foreach ($options as $key => $value) {
$check++;
$this->assertArrayHasKey($key, $o, '-> Check number ' . $check);
if ($key != CURLOPT_HTTPHEADER && $key != CURLOPT_POSTFIELDS && (is_array($o[$key])) || $o[$key] instanceof \Closure) {
$this->assertEquals('callback', $value, '-> Check number ' . $check);
} else {
$this->assertTrue($value == $o[$key], '-> Check number ' . $check . ' - ' . var_export($value, true) . ' != ' . var_export($o[$key], true));
}
}
// If we are testing the actual sent headers
if ($expectedHeaders) {
// Send the request to the test server
$client = new Client($this->getServer()->getUrl());
$request->setClient($client);
$this->getServer()->flush();
$this->getServer()->enqueue("HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n");
$request->send();
// Get the request that was sent and create a request that we expected
$requests = $this->getServer()->getReceivedRequests(true);
$this->assertEquals($method, $requests[0]->getMethod());
$test = $this->compareHeaders($expectedHeaders, $requests[0]->getHeaders());
$this->assertFalse($test, $test . "\nSent: \n" . $request . "\n\n" . $requests[0]);
// Ensure only one Content-Length header is sent
if ($request->getHeader('Content-Length')) {
$this->assertEquals((string) $request->getHeader('Content-Length'), (string) $requests[0]->getHeader('Content-Length'));
}
}
}
/**
* @covers Guzzle\Http\Curl\CurlHandle
*/
public function testFactoryUsesSpecifiedProtocol()
{
$request = RequestFactory::getInstance()->create('GET', 'http://localhost:8124/');
$request->setProtocolVersion('1.1');
$handle = CurlHandle::factory($request);
$options = $request->getParams()->get('curl.last_options');
$this->assertEquals(CURL_HTTP_VERSION_1_1, $options[CURLOPT_HTTP_VERSION]);
}
/**
* @covers Guzzle\Http\Curl\CurlHandle
*/
public function testUploadsPutData()
{
$this->getServer()->flush();
$this->getServer()->enqueue("HTTP/1.1 200 OK\r\nContent-Length: 2\r\n\r\nhi");
$client = new Client($this->getServer()->getUrl());
$request = $client->put('/');
$request->setBody(EntityBody::factory('test'), 'text/plain', false);
$request->getCurlOptions()->set('progress', true);
$o = $this->getWildcardObserver($request);
$request->send();
// Make sure that the events were dispatched
$this->assertTrue($o->has('curl.callback.progress'));
// Ensure that the request was received exactly as intended
$r = $this->getServer()->getReceivedRequests(true);
$this->assertEquals(strtolower($request), strtolower($r[0]));
$this->assertFalse($r[0]->hasHeader('Transfer-Encoding'));
$this->assertEquals(4, (string) $r[0]->getHeader('Content-Length'));
}
/**
* @covers Guzzle\Http\Curl\CurlHandle
*/
public function testUploadsPutDataUsingChunkedEncodingWhenLengthCannotBeDetermined()
{
$this->getServer()->flush();
$this->getServer()->enqueue(array(
"HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n",
"HTTP/1.1 200 OK\r\nContent-Length: 2\r\n\r\nhi"
));
$client = new Client($this->getServer()->getUrl());
$request = $client->put('/');
$request->setBody(EntityBody::factory(fopen($this->getServer()->getUrl(), 'r')), 'text/plain');
$request->send();
$r = $this->getServer()->getReceivedRequests(true);
$this->assertEquals('chunked', $r[1]->getHeader('Transfer-Encoding'));
$this->assertFalse($r[1]->hasHeader('Content-Length'));
}
/**
* @covers Guzzle\Http\Curl\CurlHandle
*/
public function testUploadsPutDataUsingChunkedEncodingWhenForced()
{
$this->getServer()->flush();
$this->getServer()->enqueue("HTTP/1.1 200 OK\r\nContent-Length: 2\r\n\r\nhi");
$client = new Client($this->getServer()->getUrl());
$request = $client->put('/');
$request->setBody(EntityBody::factory('hi!'), 'text/plain', true);
$request->send();
$r = $this->getServer()->getReceivedRequests(true);
$this->assertEquals('chunked', $r[0]->getHeader('Transfer-Encoding'));
$this->assertFalse($r[0]->hasHeader('Content-Length'));
$this->assertEquals('hi!', $r[0]->getBody(true));
}
/**
* @covers Guzzle\Http\Curl\CurlHandle
*/
public function testSendsPostRequestsWithFields()
{
$this->getServer()->flush();
$this->getServer()->enqueue("HTTP/1.1 200 OK\r\nContent-Length: 2\r\n\r\nhi");
$request = RequestFactory::getInstance()->create('POST', $this->getServer()->getUrl());
$request->setClient(new Client());
$request->addPostFields(array(
'a' => 'b',
'c' => 'ay! ~This is a test, isn\'t it?'
));
$request->send();
// Ensure the CURLOPT_POSTFIELDS option was set properly
$options = $request->getParams()->get('curl.last_options');
$this->assertEquals('a=b&c=ay%21%20~This%20is%20a%20test%2C%20isn%27t%20it%3F', $options[CURLOPT_POSTFIELDS]);
// Make sure that the request was sent correctly
$r = $this->getServer()->getReceivedRequests(true);
$this->assertEquals(strtolower($request), strtolower($r[0]));
}
/**
* @covers Guzzle\Http\Curl\CurlHandle
*/
public function testSendsPostRequestsWithFiles()
{
$this->getServer()->flush();
$this->getServer()->enqueue("HTTP/1.1 200 OK\r\nContent-Length: 2\r\n\r\nhi");
$request = RequestFactory::getInstance()->create('POST', $this->getServer()->getUrl());
$request->setClient(new Client());
$request->addPostFiles(array(
'foo' => __FILE__,
));
$request->addPostFields(array(
'bar' => 'baz',
'arr' => array('a' => 1, 'b' => 2),
));
$request->send();
// Ensure the CURLOPT_POSTFIELDS option was set properly
$options = $request->getParams()->get('curl.last_options');
$this->assertEquals(array(
'foo' => '@' . __FILE__ . ';type=text/x-php',
'bar' => 'baz',
'arr[a]' => '1',
'arr[b]' => '2',
), $options[CURLOPT_POSTFIELDS]);
// Ensure that a Content-Length header was sent by cURL
$this->assertTrue($request->hasHeader('Content-Length'));
}
/**
* @covers Guzzle\Http\Curl\CurlHandle::factory
*/
public function testHeadersCanBeBlacklisted()
{
$request = RequestFactory::getInstance()->create('PUT', $this->getServer()->getUrl());
$request->setClient(new Client('http://www.example.com', array(
'curl.blacklist' => array('header.Accept', 'header.Foo', CURLOPT_ENCODING)
)));
$request->setHeader('Foo', 'Bar');
$handle = CurlHandle::factory($request);
$headers = $handle->getOptions()->get(CURLOPT_HTTPHEADER);
$this->assertTrue(in_array('Accept:', $headers));
$this->assertTrue(in_array('Foo:', $headers));
$this->assertFalse($handle->getOptions()->hasKey(CURLOPT_ENCODING));
$this->getServer()->flush();
$this->getServer()->enqueue("HTTP/1.1 200 OK\r\nContent-Length: 2\r\n\r\nhi");
$request->send();
$r = $this->getServer()->getReceivedRequests(true);
$this->assertFalse($r[0]->hasHeader('Accept'));
$this->assertFalse($r[0]->hasHeader('Foo'));
}
/**
* @covers Guzzle\Http\Curl\CurlHandle::factory
*/
public function testAllowsHeadersSetToNull()
{
$request = RequestFactory::getInstance()->create('PUT', $this->getServer()->getUrl());
$request->setClient(new Client());
$request->setBody('test');
$request->setHeader('Expect', null);
$request->setHeader('Accept', null);
$handle = CurlHandle::factory($request);
$headers = $handle->getOptions()->get(CURLOPT_HTTPHEADER);
$this->assertTrue(in_array('Expect:', $headers));
$this->assertTrue(in_array('Accept:', $headers));
}
/**
* @covers Guzzle\Http\Curl\CurlHandle::updateRequestFromTransfer
*/
public function testEnsuresRequestsHaveResponsesWhenUpdatingFromTransfer()
{
$request = RequestFactory::getInstance()->create('PUT', $this->getServer()->getUrl());
$handle = CurlHandle::factory($request);
$handle->updateRequestFromTransfer($request);
}
public function testCurlFollowsRedirectsUsingPost()
{
$this->markTestIncomplete('This is a bug with PHP: https://bugs.php.net/bug.php?id=47204');
$url = $this->getServer()->getUrl();
$this->getServer()->enqueue(array(
"HTTP/1.1 303 See Other\r\nServer: Apache-Coyote/1.1\r\nLocation: {$url}\r\nContent-Length: 0\r\n\r\n",
"HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n"
));
$client = new Client($url);
$request = $client->post('/', null, '{}');
$request->removeHeader('Expect');
$request->send();
$received = $this->getServer()->getReceivedRequests(true);
$this->assertEquals(2, count($received));
}
public function testAllowsWireTransferInfoToBeDisabled()
{
$request = RequestFactory::getInstance()->create('PUT', $this->getServer()->getUrl());
$request->getCurlOptions()->set('disable_wire', true);
$handle = CurlHandle::factory($request);
$this->assertNull($handle->getOptions()->get(CURLOPT_STDERR));
$this->assertNull($handle->getOptions()->get(CURLOPT_VERBOSE));
}
public function testAddsCustomCurlOptions()
{
$request = RequestFactory::getInstance()->create('PUT', $this->getServer()->getUrl());
$request->getCurlOptions()->set(CURLOPT_TIMEOUT, 200);
$handle = CurlHandle::factory($request);
$this->assertEquals(200, $handle->getOptions()->get(CURLOPT_TIMEOUT));
}
public function testSendsPostUploadsWithContentDispositionHeaders()
{
$this->getServer()->flush();
$this->getServer()->enqueue("HTTP/1.1 200 OK\r\n\r\nContent-Length: 0\r\n\r\n");
$fileToUpload = dirname(dirname(__DIR__)) . DIRECTORY_SEPARATOR . 'TestData' . DIRECTORY_SEPARATOR . 'test_service.json';
$client = new Client($this->getServer()->getUrl());
$request = $client->post();
$request->addPostFile('foo', $fileToUpload, 'application/json');
$request->addPostFile('foo', __FILE__);
$request->send();
$requests = $this->getServer()->getReceivedRequests(true);
$body = (string) $requests[0]->getBody();
$this->assertContains('Content-Disposition: form-data; name="foo[0]"; filename="', $body);
$this->assertContains('Content-Type: application/json', $body);
$this->assertContains('Content-Type: text/x-php', $body);
$this->assertContains('Content-Disposition: form-data; name="foo[1]"; filename="', $body);
}
}
tests/Guzzle/Tests/Http/Curl/CurlMultiTest.php 0000644 00000052465 15174272742 0015434 0 ustar 00 updates = new Collection();
$this->multi = new MockMulti();
$this->mock = $this->getWildcardObserver($this->multi);
}
/**
* @covers Guzzle\Http\Curl\CurlMulti::getInstance
*/
public function testReturnsCachedInstance()
{
$c = CurlMulti::getInstance();
$this->assertInstanceOf('Guzzle\\Http\\Curl\\CurlMultiInterface', $c);
$this->assertSame($c, CurlMulti::getInstance());
}
/**
* @covers Guzzle\Http\Curl\CurlMulti::__construct
* @covers Guzzle\Http\Curl\CurlMulti::__destruct
*/
public function testConstructorCreateMultiHandle()
{
$this->assertInternalType('resource', $this->multi->getHandle());
$this->assertEquals('curl_multi', get_resource_type($this->multi->getHandle()));
}
/**
* @covers Guzzle\Http\Curl\CurlMulti::__destruct
*/
public function testDestructorClosesMultiHandle()
{
$handle = $this->multi->getHandle();
$this->multi->__destruct();
$this->assertFalse(is_resource($handle));
}
/**
* @covers Guzzle\Http\Curl\curlMulti::add
* @covers Guzzle\Http\Curl\curlMulti::all
* @covers Guzzle\Http\Curl\curlMulti::count
*/
public function testRequestsCanBeAddedAndCounted()
{
$multi = new CurlMulti();
$mock = $this->getWildcardObserver($multi);
$request1 = new Request('GET', 'http://www.google.com/');
$multi->add($request1);
$this->assertEquals(array($request1), $multi->all());
$request2 = new Request('POST', 'http://www.google.com/');
$multi->add($request2);
$this->assertEquals(array($request1, $request2), $multi->all());
$this->assertEquals(2, count($multi));
$this->assertTrue($mock->has(CurlMulti::ADD_REQUEST));
$this->assertFalse($mock->has(CurlMulti::REMOVE_REQUEST));
$this->assertFalse($mock->has(CurlMulti::POLLING));
$this->assertFalse($mock->has(CurlMulti::COMPLETE));
}
/**
* @covers Guzzle\Http\Curl\CurlMulti::remove
* @covers Guzzle\Http\Curl\CurlMulti::all
*/
public function testRequestsCanBeRemoved()
{
$request1 = new Request('GET', 'http://www.google.com/');
$this->multi->add($request1);
$request2 = new Request('PUT', 'http://www.google.com/');
$this->multi->add($request2);
$this->assertEquals(array($request1, $request2), $this->multi->all());
$this->assertSame($this->multi, $this->multi->remove($request1));
$this->assertEquals(array($request2), $this->multi->all());
}
/**
* @covers Guzzle\Http\Curl\CurlMulti::reset
*/
public function testsResetRemovesRequestsAndResetsState()
{
$request1 = new Request('GET', 'http://www.google.com/');
$this->multi->add($request1);
$this->multi->reset();
$this->assertEquals(array(), $this->multi->all());
$this->assertEquals('idle', $this->multi->getState());
}
/**
* @covers Guzzle\Http\Curl\CurlMulti::send
* @covers Guzzle\Http\Curl\CurlMulti::getState
*/
public function testSendsRequestsInParallel()
{
$this->getServer()->enqueue("HTTP/1.1 200 OK\r\nContent-Length: 4\r\n\r\nBody");
$this->assertEquals('idle', $this->multi->getState());
$request = new Request('GET', $this->getServer()->getUrl());
$this->multi->add($request);
$this->multi->send();
$this->assertEquals('idle', $this->multi->getState());
$this->assertTrue($this->mock->has(CurlMulti::ADD_REQUEST));
$this->assertTrue($this->mock->has(CurlMulti::COMPLETE));
$this->assertEquals('Body', $request->getResponse()->getBody()->__toString());
// Sending it again will not do anything because there are no requests
$this->multi->send();
}
/**
* @covers Guzzle\Http\Curl\CurlMulti::send
*/
public function testSendsRequestsThroughCurl()
{
$this->getServer()->enqueue(array(
"HTTP/1.1 204 No content\r\n" .
"Content-Length: 0\r\n" .
"Server: Jetty(6.1.3)\r\n\r\n",
"HTTP/1.1 200 OK\r\n" .
"Content-Type: text/html; charset=utf-8\r\n" .
"Content-Length: 4\r\n" .
"Server: Jetty(6.1.3)\r\n\r\n" .
"data"
));
$request1 = new Request('GET', $this->getServer()->getUrl());
$mock1 = $this->getWildcardObserver($request1);
$request2 = new Request('GET', $this->getServer()->getUrl());
$mock2 = $this->getWildcardObserver($request2);
$this->multi->add($request1);
$this->multi->add($request2);
$this->multi->send();
$response1 = $request1->getResponse();
$response2 = $request2->getResponse();
$this->assertInstanceOf('Guzzle\\Http\\Message\\Response', $response1);
$this->assertInstanceOf('Guzzle\\Http\\Message\\Response', $response2);
$this->assertTrue($response1->getBody(true) == 'data' || $response2->getBody(true) == 'data');
$this->assertTrue($response1->getBody(true) == '' || $response2->getBody(true) == '');
$this->assertTrue($response1->getStatusCode() == '204' || $response2->getStatusCode() == '204');
$this->assertNotEquals((string) $response1, (string) $response2);
$this->assertTrue($mock1->has('request.before_send'));
$this->assertTrue($mock2->has('request.before_send'));
}
/**
* @covers Guzzle\Http\Curl\CurlMulti::send
*/
public function testSendsThroughCurlAndAggregatesRequestExceptions()
{
$this->getServer()->enqueue(array(
"HTTP/1.1 200 OK\r\n" .
"Content-Type: text/html; charset=utf-8\r\n" .
"Content-Length: 4\r\n" .
"Server: Jetty(6.1.3)\r\n" .
"\r\n" .
"data",
"HTTP/1.1 204 No content\r\n" .
"Content-Length: 0\r\n" .
"Server: Jetty(6.1.3)\r\n" .
"\r\n",
"HTTP/1.1 404 Not Found\r\n" .
"Content-Length: 0\r\n" .
"\r\n"
));
$request1 = new Request('GET', $this->getServer()->getUrl());
$request2 = new Request('HEAD', $this->getServer()->getUrl());
$request3 = new Request('GET', $this->getServer()->getUrl());
$this->multi->add($request1);
$this->multi->add($request2);
$this->multi->add($request3);
try {
$this->multi->send();
$this->fail('ExceptionCollection not thrown when aggregating request exceptions');
} catch (ExceptionCollection $e) {
$this->assertInstanceOf('ArrayIterator', $e->getIterator());
$this->assertEquals(1, count($e));
$exceptions = $e->getIterator();
$response1 = $request1->getResponse();
$response2 = $request2->getResponse();
$response3 = $request3->getResponse();
$this->assertNotEquals((string) $response1, (string) $response2);
$this->assertNotEquals((string) $response3, (string) $response1);
$this->assertInstanceOf('Guzzle\\Http\\Message\\Response', $response1);
$this->assertInstanceOf('Guzzle\\Http\\Message\\Response', $response2);
$this->assertInstanceOf('Guzzle\\Http\\Message\\Response', $response3);
$failed = $exceptions[0]->getResponse();
$this->assertEquals(404, $failed->getStatusCode());
$this->assertEquals(1, count($e));
// Test the IteratorAggregate functionality
foreach ($e as $excep) {
$this->assertEquals($failed, $excep->getResponse());
}
}
}
/**
* @covers Guzzle\Http\Curl\CurlMulti::send
* @covers Guzzle\Http\Curl\CurlMulti::processResponse
*/
public function testCurlErrorsAreCaught()
{
$this->getServer()->enqueue("HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n");
try {
$request = RequestFactory::getInstance()->create('GET', 'http://127.0.0.1:9876/');
$request->setClient(new Client());
$request->getCurlOptions()->set(CURLOPT_FRESH_CONNECT, true);
$request->getCurlOptions()->set(CURLOPT_FORBID_REUSE, true);
$request->getCurlOptions()->set(CURLOPT_CONNECTTIMEOUT_MS, 5);
$request->send();
$this->fail('CurlException not thrown');
} catch (CurlException $e) {
$m = $e->getMessage();
$this->assertContains('[curl] ', $m);
$this->assertContains('[url] http://127.0.0.1:9876/', $m);
$this->assertContains('[debug] ', $m);
$this->assertContains('[info] array (', $m);
}
}
/**
* @covers Guzzle\Http\Curl\CurlMulti
*/
public function testRemovesQueuedRequests()
{
$request = RequestFactory::getInstance()->create('GET', 'http://127.0.0.1:9876/');
$request->setClient(new Client());
$request->setResponse(new Response(200), true);
$this->multi->add($request);
$this->multi->send();
$this->assertTrue($this->mock->has(CurlMulti::ADD_REQUEST));
$this->assertTrue($this->mock->has(CurlMulti::POLLING) === false);
$this->assertTrue($this->mock->has(CurlMulti::COMPLETE) !== false);
}
/**
* @covers Guzzle\Http\Curl\CurlMulti
*/
public function testRemovesQueuedRequestsAddedInTransit()
{
$this->getServer()->flush();
$this->getServer()->enqueue(array(
"HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n"
));
$client = new Client($this->getServer()->getUrl());
$r = $client->get();
$r->getEventDispatcher()->addListener('request.receive.status_line', function(Event $event) use ($client) {
// Create a request using a queued response
$request = $client->get()->setResponse(new Response(200), true);
$request->send();
});
$r->send();
$this->assertEquals(1, count($this->getServer()->getReceivedRequests(false)));
}
/**
* @covers Guzzle\Http\Curl\CurlMulti
*/
public function testProperlyBlocksBasedOnRequestsInScope()
{
$this->getServer()->flush();
$this->getServer()->enqueue(array(
"HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\ntest1",
"HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\ntest2",
"HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\ntest3",
"HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\ntest4",
"HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\ntest5",
"HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\ntest6",
"HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n",
"HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n"
));
$client = new Client($this->getServer()->getUrl());
$requests = array(
$client->get(),
$client->get()
);
$sendHeadFunction = function($event) use ($client) {
$client->head()->send();
};
// Sends 2 new requests in the middle of a CurlMulti loop while other requests
// are completing. This causes the scope of the multi handle to go up.
$callback = function(Event $event) use ($client, $sendHeadFunction) {
$client->getConfig()->set('called', $client->getConfig('called') + 1);
if ($client->getConfig('called') <= 2) {
$request = $client->get();
$request->getEventDispatcher()->addListener('request.complete', $sendHeadFunction);
$request->send();
}
};
$requests[0]->getEventDispatcher()->addListener('request.complete', $callback);
$client->send($requests);
$this->assertEquals(4, count($this->getServer()->getReceivedRequests(false)));
}
/**
* @covers Guzzle\Http\Curl\CurlMulti
* @expectedException RuntimeException
* @expectedExceptionMessage Testing!
*/
public function testCatchesExceptionsBeforeSendingCurlMulti()
{
$client = new Client($this->getServer()->getUrl());
$multi = new CurlMulti();
$client->setCurlMulti($multi);
$multi->getEventDispatcher()->addListener(CurlMulti::BEFORE_SEND, function() {
throw new \RuntimeException('Testing!');
});
$client->get()->send();
}
/**
* @covers Guzzle\Http\Curl\CurlMulti
* @covers Guzzle\Http\Curl\CurlMulti::removeErroredRequest
* @expectedException Guzzle\Common\Exception\ExceptionCollection
* @expectedExceptionMessage Thrown before sending!
*/
public function testCatchesExceptionsBeforeSendingRequests()
{
$client = new Client($this->getServer()->getUrl());
$request = $client->get();
$request->getEventDispatcher()->addListener('request.before_send', function() {
throw new \RuntimeException('Thrown before sending!');
});
$client->send(array($request));
}
/**
* @covers Guzzle\Http\Curl\CurlMulti
* @covers Guzzle\Http\Curl\CurlMulti::removeErroredRequest
* @expectedException Guzzle\Http\Exception\BadResponseException
*/
public function testCatchesExceptionsWhenRemovingQueuedRequests()
{
$this->getServer()->enqueue("HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n");
$client = new Client($this->getServer()->getUrl());
$r = $client->get();
$r->getEventDispatcher()->addListener('request.sent', function() use ($client) {
// Create a request using a queued response
$client->get()->setResponse(new Response(404), true)->send();
});
$r->send();
}
/**
* @covers Guzzle\Http\Curl\CurlMulti
* @covers Guzzle\Http\Curl\CurlMulti::removeErroredRequest
* @expectedException Guzzle\Http\Exception\BadResponseException
*/
public function testCatchesExceptionsWhenRemovingQueuedRequestsBeforeSending()
{
$this->getServer()->enqueue("HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n");
$client = new Client($this->getServer()->getUrl());
$r = $client->get();
$r->getEventDispatcher()->addListener('request.before_send', function() use ($client) {
// Create a request using a queued response
$client->get()->setResponse(new Response(404), true)->send();
});
$r->send();
}
/**
* @covers Guzzle\Http\Curl\CurlMulti::send
* @covers Guzzle\Http\Curl\CurlMulti::removeErroredRequest
* @expectedException Guzzle\Common\Exception\ExceptionCollection
* @expectedExceptionMessage test
*/
public function testCatchesRandomExceptionsThrownDuringPerform()
{
$client = new Client($this->getServer()->getUrl());
$multi = $this->getMock('Guzzle\\Http\\Curl\\CurlMulti', array('perform'));
$multi->expects($this->once())
->method('perform')
->will($this->throwException(new \Exception('test')));
$multi->add($client->get());
$multi->send();
}
/**
* @covers Guzzle\Http\Curl\CurlMulti::send
*/
public function testDoesNotSendRequestsDecliningToBeSent()
{
if (!defined('CURLOPT_TIMEOUT_MS')) {
$this->markTestSkipped('Update curl');
}
// Create a client that is bound to fail connecting
$client = new Client('http://localhost:123', array(
'curl.CURLOPT_PORT' => 123,
'curl.CURLOPT_CONNECTTIMEOUT_MS' => 1,
));
$request = $client->get();
$multi = new CurlMulti();
$multi->add($request);
// Listen for request exceptions, and when they occur, first change the
// state of the request back to transferring, and then just allow it to
// exception out
$request->getEventDispatcher()->addListener('request.exception', function(Event $event) use ($multi) {
$retries = $event['request']->getParams()->get('retries');
// Allow the first failure to retry
if ($retries == 0) {
$event['request']->setState('transfer');
$event['request']->getParams()->set('retries', 1);
// Remove the request to try again
$multi->remove($event['request']);
$multi->add($event['request'], true);
}
});
try {
$multi->send();
$this->fail('Did not throw an exception at all!?!');
} catch (\Exception $e) {
$this->assertEquals(1, $request->getParams()->get('retries'));
}
}
/**
* @covers Guzzle\Http\Curl\CurlMulti::send
*/
public function testDoesNotThrowExceptionsWhenRequestsRecoverWithRetry()
{
$this->getServer()->flush();
$client = new Client($this->getServer()->getUrl());
$request = $client->get();
$request->getEventDispatcher()->addListener('request.before_send', function(Event $event) {
$event['request']->setResponse(new Response(200));
});
$multi = new CurlMulti();
$multi->add($request);
$multi->send();
$this->assertEquals(0, count($this->getServer()->getReceivedRequests(false)));
}
/**
* @covers Guzzle\Http\Curl\CurlMulti::send
*/
public function testDoesNotThrowExceptionsWhenRequestsRecoverWithSuccess()
{
// Attempt a port that 99.9% is not listening
$client = new Client('http://localhost:123');
$request = $client->get();
// Ensure it times out quickly if needed
$request->getCurlOptions()->set(CURLOPT_TIMEOUT_MS, 1)->set(CURLOPT_CONNECTTIMEOUT_MS, 1);
$request->getEventDispatcher()->addListener('request.exception', function(Event $event) use (&$count) {
$event['request']->setResponse(new Response(200));
});
$multi = new CurlMulti();
$multi->add($request);
$multi->send();
// Ensure that the exception was caught, and the response was set manually
$this->assertEquals(200, $request->getResponse()->getStatusCode());
}
/**
* @covers Guzzle\Http\Curl\CurlMulti::reset
*/
public function testHardResetReopensMultiHandle()
{
$this->getServer()->enqueue(array(
"HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n",
"HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n"
));
$client = new Client($this->getServer()->getUrl());
$message = '';
$plugin = new LogPlugin(new ClosureLogAdapter(function($msg) use (&$message) {
$message .= $msg . "\n";
}), LogPlugin::LOG_VERBOSE);
$client->getEventDispatcher()->addSubscriber($plugin);
$request = $client->get();
$multi = new CurlMulti();
$multi->add($request);
$multi->send();
$multi->reset(true);
$multi->add($request);
$multi->send();
$this->assertNotContains('Re-using existing connection', $message);
}
/**
* @covers Guzzle\Http\Curl\CurlMulti::checkCurlResult
*/
public function testThrowsMeaningfulExceptionsForCurlMultiErrors()
{
$multi = new CurlMulti();
// Set the state of the multi object to sending to trigger the exception
$reflector = new \ReflectionMethod('Guzzle\Http\Curl\CurlMulti', 'checkCurlResult');
$reflector->setAccessible(true);
// Successful
$reflector->invoke($multi, 0);
// Known error
try {
$reflector->invoke($multi, CURLM_BAD_HANDLE);
$this->fail('Expected an exception here');
} catch (CurlException $e) {
$this->assertContains('The passed-in handle is not a valid CURLM handle.', $e->getMessage());
$this->assertContains('CURLM_BAD_HANDLE', $e->getMessage());
$this->assertContains(strval(CURLM_BAD_HANDLE), $e->getMessage());
}
// Unknown error
try {
$reflector->invoke($multi, 255);
$this->fail('Expected an exception here');
} catch (CurlException $e) {
$this->assertEquals('Unexpected cURL error: 255', $e->getMessage());
}
}
/**
* @covers Guzzle\Http\Curl\curlMulti::add
*/
public function testAddsAsyncRequestsNormallyWhenNotSending()
{
$multi = new CurlMulti();
$request = new Request('GET', 'http://www.google.com/');
$multi->add($request, true);
// Ensure that the request was added at the correct next scope
$requests = $this->readAttribute($multi, 'requests');
$this->assertEquals(array($request), $requests[0]);
}
}
tests/Guzzle/Tests/Http/Curl/CurlVersionTest.php 0000644 00000003007 15174272742 0015753 0 ustar 00 getProperty('version');
$refProperty->setAccessible(true);
$refProperty->setValue($instance, array());
$this->assertEquals($info, $instance->getAll());
$this->assertEquals($info, $instance->getAll());
$this->assertEquals($info['version'], $instance->get('version'));
$this->assertFalse($instance->get('foo'));
}
public function testDeterminesIfCurlCanFollowLocation()
{
if (!ini_get('open_basedir')) {
$this->assertTrue(CurlVersion::getInstance()->get('follow_location'));
} else {
$this->assertFalse(CurlVersion::getInstance()->get('follow_location'));
}
}
public function testIsSingleton()
{
$refObject = new \ReflectionClass('Guzzle\Http\Curl\CurlVersion');
$refProperty = $refObject->getProperty('instance');
$refProperty->setAccessible(true);
$refProperty->setValue(null, null);
$this->assertInstanceOf('Guzzle\Http\Curl\CurlVersion', CurlVersion::getInstance());
}
}
tests/Guzzle/Tests/Http/Curl/RequestMediatorTest.php 0000644 00000003703 15174272742 0016620 0 ustar 00 events[] = $event;
}
public function testEmitsEvents()
{
$request = new EntityEnclosingRequest('PUT', 'http://www.example.com');
$request->setBody('foo');
$request->setResponse(new Response(200));
// Ensure that IO events are emitted
$request->getParams()->set('curl.emit_io', true);
// Attach listeners for each event type
$request->getEventDispatcher()->addListener('curl.callback.progress', array($this, 'event'));
$request->getEventDispatcher()->addListener('curl.callback.read', array($this, 'event'));
$request->getEventDispatcher()->addListener('curl.callback.write', array($this, 'event'));
$mediator = new RequestMediator($request, true);
$mediator->progress('a', 'b', 'c', 'd');
$this->assertEquals(1, count($this->events));
$this->assertEquals('curl.callback.progress', $this->events[0]->getName());
$this->assertEquals(3, $mediator->writeResponseBody('foo', 'bar'));
$this->assertEquals(2, count($this->events));
$this->assertEquals('curl.callback.write', $this->events[1]->getName());
$this->assertEquals('bar', $this->events[1]['write']);
$this->assertSame($request, $this->events[1]['request']);
$this->assertEquals('foo', $mediator->readRequestBody('a', 'b', 3));
$this->assertEquals(3, count($this->events));
$this->assertEquals('curl.callback.read', $this->events[2]->getName());
$this->assertEquals('foo', $this->events[2]['read']);
$this->assertSame($request, $this->events[2]['request']);
}
}
tests/Guzzle/Tests/Http/EntityBodyTest.php 0000644 00000013721 15174272742 0014671 0 ustar 00 assertEquals('data', (string)$body);
$this->assertEquals(4, $body->getContentLength());
$this->assertEquals('php', $body->getWrapper());
$this->assertEquals('temp', $body->getStreamType());
$handle = fopen(__DIR__ . '/../../../../phpunit.xml', 'r');
if (!$handle) {
$this->fail('Could not open test file');
}
$body = EntityBody::factory($handle);
$this->assertEquals(__DIR__ . '/../../../../phpunit.xml', $body->getUri());
$this->assertTrue($body->isLocal());
$this->assertEquals(__DIR__ . '/../../../../phpunit.xml', $body->getUri());
$this->assertEquals(filesize(__DIR__ . '/../../../../phpunit.xml'), $body->getContentLength());
// make sure that a body will return as the same object
$this->assertTrue($body === EntityBody::factory($body));
}
/**
* @covers Guzzle\Http\EntityBody::factory
*/
public function testFactoryCreatesTempStreamByDefault()
{
$body = EntityBody::factory('');
$this->assertEquals('php', $body->getWrapper());
$this->assertEquals('temp', $body->getStreamType());
$body = EntityBody::factory();
$this->assertEquals('php', $body->getWrapper());
$this->assertEquals('temp', $body->getStreamType());
}
/**
* @covers Guzzle\Http\EntityBody::compress
* @covers Guzzle\Http\EntityBody::uncompress
* @covers Guzzle\Http\EntityBody::getContentEncoding
* @covers Guzzle\Http\EntityBody::setStreamFilterContentEncoding
* @covers Guzzle\Http\EntityBody::handleCompression
* @covers Guzzle\Http\EntityBody::getContentLength
*/
public function testHandlesCompression()
{
$body = EntityBody::factory('testing 123...testing 123');
$this->assertFalse($body->getContentEncoding(), '-> getContentEncoding() must initially return FALSE');
$size = $body->getContentLength();
$body->compress();
$this->assertEquals('gzip', $body->getContentEncoding(), '-> getContentEncoding() must return the correct encoding after compressing');
$this->assertEquals(gzdeflate('testing 123...testing 123'), (string) $body);
$this->assertTrue($body->getContentLength() < $size);
$this->assertTrue($body->uncompress());
$this->assertEquals('testing 123...testing 123', (string) $body);
$this->assertFalse($body->getContentEncoding(), '-> getContentEncoding() must reset to FALSE');
if (in_array('bzip2.*', stream_get_filters())) {
$this->assertTrue($body->compress('bzip2.compress'));
$this->assertEquals('compress', $body->getContentEncoding(), '-> compress() must set \'compress\' as the Content-Encoding');
}
$this->assertFalse($body->compress('non-existent'), '-> compress() must return false when a non-existent stream filter is used');
// Release the body
unset($body);
// Use gzip compression on the initial content. This will include a
// gzip header which will need to be stripped when deflating the stream
$body = EntityBody::factory(gzencode('test'));
$this->assertSame($body, $body->setStreamFilterContentEncoding('zlib.deflate'));
$this->assertTrue($body->uncompress('zlib.inflate'));
$this->assertEquals('test', (string)$body);
unset($body);
// Test using a very long string
$largeString = '';
for ($i = 0; $i < 25000; $i++) {
$largeString .= chr(rand(33, 126));
}
$body = EntityBody::factory($largeString);
$this->assertEquals($largeString, (string)$body);
$this->assertTrue($body->compress());
$this->assertNotEquals($largeString, (string)$body);
$compressed = (string)$body;
$this->assertTrue($body->uncompress());
$this->assertEquals($largeString, (string)$body);
$this->assertEquals($compressed, gzdeflate($largeString));
$body = EntityBody::factory(fopen(__DIR__ . '/../TestData/compress_test', 'w'));
$this->assertFalse($body->compress());
unset($body);
unlink(__DIR__ . '/../TestData/compress_test');
}
/**
* @covers Guzzle\Http\EntityBody::getContentType
*/
public function testDeterminesContentType()
{
// Test using a string/temp stream
$body = EntityBody::factory('testing 123...testing 123');
$this->assertEquals('application/octet-stream', $body->getContentType());
// Use a local file
$body = EntityBody::factory(fopen(__FILE__, 'r'));
$this->assertEquals('text/x-php', $body->getContentType());
}
/**
* @covers Guzzle\Http\EntityBody::getContentMd5
*/
public function testCreatesMd5Checksum()
{
$body = EntityBody::factory('testing 123...testing 123');
$this->assertEquals(md5('testing 123...testing 123'), $body->getContentMd5());
$server = $this->getServer()->enqueue(
"HTTP/1.1 200 OK" . "\r\n" .
"Content-Length: 3" . "\r\n\r\n" .
"abc"
);
$body = EntityBody::factory(fopen($this->getServer()->getUrl(), 'r'));
$this->assertFalse($body->getContentMd5());
}
/**
* @covers Guzzle\Http\EntityBody::factory
*/
public function testGetTypeFormBodyFactoring()
{
$body = EntityBody::factory(array('key1' => 'val1', 'key2' => 'val2'));
$this->assertEquals('key1=val1&key2=val2', (string)$body);
}
}
tests/Guzzle/Tests/Http/Exception/CurlExceptionTest.php 0000644 00000001363 15174272742 0017320 0 ustar 00 assertNull($e->getError());
$this->assertNull($e->getErrorNo());
$this->assertSame($e, $e->setError('test', 12));
$this->assertEquals('test', $e->getError());
$this->assertEquals(12, $e->getErrorNo());
$handle = new CurlHandle(curl_init(), array());
$e->setCurlHandle($handle);
$this->assertSame($handle, $e->getCurlHandle());
$handle->close();
}
}
tests/Guzzle/Tests/Http/Exception/ExceptionTest.php 0000644 00000004201 15174272742 0016464 0 ustar 00 setRequest($request);
$this->assertEquals($request, $e->getRequest());
}
/**
* @covers Guzzle\Http\Exception\BadResponseException
*/
public function testBadResponseException()
{
$e = new BadResponseException('Message');
$response = new Response(200);
$e->setResponse($response);
$this->assertEquals($response, $e->getResponse());
}
/**
* @covers Guzzle\Http\Exception\BadResponseException::factory
*/
public function testCreatesGenericErrorExceptionOnError()
{
$request = new Request('GET', 'http://www.example.com');
$response = new Response(307);
$e = BadResponseException::factory($request, $response);
$this->assertInstanceOf('Guzzle\Http\Exception\BadResponseException', $e);
}
/**
* @covers Guzzle\Http\Exception\BadResponseException::factory
*/
public function testCreatesClientErrorExceptionOnClientError()
{
$request = new Request('GET', 'http://www.example.com');
$response = new Response(404);
$e = BadResponseException::factory($request, $response);
$this->assertInstanceOf('Guzzle\Http\Exception\ClientErrorResponseException', $e);
}
/**
* @covers Guzzle\Http\Exception\BadResponseException::factory
*/
public function testCreatesServerErrorExceptionOnServerError()
{
$request = new Request('GET', 'http://www.example.com');
$response = new Response(503);
$e = BadResponseException::factory($request, $response);
$this->assertInstanceOf('Guzzle\Http\Exception\ServerErrorResponseException', $e);
}
}
tests/Guzzle/Tests/Http/Message/AbstractMessageTest.php 0000644 00000023224 15174272742 0017232 0 ustar 00 mock = $this->getMockForAbstractClass('Guzzle\Http\Message\AbstractMessage');
}
/**
* @covers Guzzle\Http\Message\AbstractMessage::getParams
*/
public function testGetParams()
{
$request = new Request('GET', 'http://example.com');
$this->assertInstanceOf('Guzzle\\Common\\Collection', $request->getParams());
}
/**
* @covers Guzzle\Http\Message\AbstractMessage::addHeaders
*/
public function testAddHeaders()
{
$this->mock->setHeader('A', 'B');
$this->assertEquals($this->mock, $this->mock->addHeaders(array(
'X-Data' => '123'
)));
$this->assertTrue($this->mock->hasHeader('X-Data') !== false);
$this->assertTrue($this->mock->hasHeader('A') !== false);
}
/**
* @covers Guzzle\Http\Message\AbstractMessage::setHeader
*/
public function testAllowsHeaderToSetAsHeader()
{
$h = new Header('A', 'B');
$this->mock->setHeader('A', $h);
$this->assertSame($h, $this->mock->getHeader('A'));
}
/**
* @covers Guzzle\Http\Message\AbstractMessage::getHeaders
*/
public function testGetHeader()
{
$this->mock->setHeader('Test', '123');
$this->assertEquals('123', $this->mock->getHeader('Test'));
}
/**
* @covers Guzzle\Http\Message\AbstractMessage::getHeaders
* @covers Guzzle\Http\Message\AbstractMessage::getHeader
* @covers Guzzle\Http\Message\AbstractMessage::setHeaders
*/
public function testGetHeaders()
{
$this->assertSame($this->mock, $this->mock->setHeaders(array(
'a' => 'b',
'c' => 'd'
)));
$this->assertEquals(array(
'a' => array('b'),
'c' => array('d')
), $this->mock->getHeaders()->getAll());
}
/**
* @covers Guzzle\Http\Message\AbstractMessage::hasHeader
*/
public function testHasHeader()
{
$this->assertFalse($this->mock->hasHeader('Foo'));
$this->mock->setHeader('Foo', 'Bar');
$this->assertEquals(true, $this->mock->hasHeader('Foo'));
$this->mock->setHeader('foo', 'yoo');
$this->assertEquals(true, $this->mock->hasHeader('Foo'));
$this->assertEquals(true, $this->mock->hasHeader('foo'));
$this->assertEquals(false, $this->mock->hasHeader('bar'));
}
/**
* @covers Guzzle\Http\Message\AbstractMessage::removeHeader
* @covers Guzzle\Http\Message\AbstractMessage::setHeader
*/
public function testRemoveHeader()
{
$this->mock->setHeader('Foo', 'Bar');
$this->assertEquals(true, $this->mock->hasHeader('Foo'));
$this->mock->removeHeader('Foo');
$this->assertFalse($this->mock->hasHeader('Foo'));
}
/**
* @covers Guzzle\Http\Message\AbstractMessage
*/
public function testHoldsCacheControlDirectives()
{
$mock = $this->mock;
// Set a directive using a header
$mock->setHeader('Cache-Control', 'max-age=100');
$this->assertEquals(100, $mock->getCacheControlDirective('max-age'));
// Set a header using the directive and check that the header was updated
$this->assertSame($mock, $mock->addCacheControlDirective('max-age', 80));
$this->assertEquals(80, $mock->getCacheControlDirective('max-age'));
$this->assertEquals('max-age=80', $mock->getHeader('Cache-Control'));
// Remove the directive
$this->assertEquals($mock, $mock->removeCacheControlDirective('max-age'));
$this->assertEquals('', $mock->getHeader('Cache-Control'));
$this->assertEquals(null, $mock->getCacheControlDirective('max-age'));
// Remove a non-existent directive
$this->assertEquals($mock, $mock->removeCacheControlDirective('max-age'));
// Has directive
$this->assertFalse($mock->hasCacheControlDirective('max-age'));
$mock->addCacheControlDirective('must-revalidate');
$this->assertTrue($mock->hasCacheControlDirective('must-revalidate'));
// Make sure that it works with multiple Cache-Control headers
$mock->setHeader('Cache-Control', 'must-revalidate, max-age=100');
$mock->addHeaders(array(
'Cache-Control' => 'no-cache'
));
$this->assertEquals(true, $mock->getCacheControlDirective('no-cache'));
$this->assertEquals(true, $mock->getCacheControlDirective('must-revalidate'));
$this->assertEquals(100, $mock->getCacheControlDirective('max-age'));
}
public function tokenizedHeaderProvider()
{
return array(
array('ISO-8859-1,utf-8;q=0.7,*;q=0.7"', ';', array(
'ISO-8859-1,utf-8',
'q' => array('0.7,*', '0.7"')
)),
array('gzip,deflate', ',', array('gzip', 'deflate')),
array('en-us,en;q=0.5', ';', array(
'en-us,en',
'q' => '0.5'
))
);
}
/**
* @covers Guzzle\Http\Message\AbstractMessage::getTokenizedHeader
* @dataProvider tokenizedHeaderProvider
*/
public function testConvertsTokenizedHeadersToArray($string, $token, $result)
{
$this->mock->setHeader('test', $string);
$this->assertEquals($result, $this->mock->getTokenizedHeader('test', $token)->getAll());
}
/**
* @covers Guzzle\Http\Message\AbstractMessage::setTokenizedHeader
* @dataProvider tokenizedHeaderProvider
*/
public function testConvertsArrayToTokenizedHeader($string, $token, $result)
{
$this->mock->setTokenizedHeader('test', $result, $token);
$this->assertEquals($string, $this->mock->getHeader('test'));
}
/**
* @covers Guzzle\Http\Message\AbstractMessage::setTokenizedHeader
* @expectedException InvalidArgumentException
*/
public function testTokenizedHeaderMustBeArrayToSet()
{
$this->mock->setTokenizedHeader('test', false);
}
/**
* @covers Guzzle\Http\Message\AbstractMessage::getTokenizedHeader
*/
public function testReturnsNullWhenTokenizedHeaderNotFound()
{
$this->assertNull($this->mock->getTokenizedHeader('foo'));
}
/**
* @covers Guzzle\Http\Message\AbstractMessage::getTokenizedHeader
*/
public function testMultipleTokenizedHeadersAreCombined()
{
$this->mock->addHeader('test', 'ISO-8859-1,utf-8;q=0.7,*;q=0.7');
$this->mock->addHeader('test', 'foo;q=123,*;q=456;q=0.7');
$this->mock->addHeader('Content-Length', 0);
$this->assertEquals(array(
0 => 'ISO-8859-1,utf-8',
'q' => array('0.7,*', '0.7', '123,*', '456'),
2 => 'foo',
), $this->mock->getTokenizedHeader('test')->getAll());
}
/**
* @covers Guzzle\Http\Message\AbstractMessage::getHeader
*/
public function testReturnsNullWhenHeaderIsNotFound()
{
$this->assertNull($this->mock->getHeader('foo'));
}
/**
* @covers Guzzle\Http\Message\AbstractMessage::addHeaders
* @covers Guzzle\Http\Message\AbstractMessage::addHeader
* @covers Guzzle\Http\Message\AbstractMessage::getHeader
*/
public function testAddingHeadersWithMultipleValuesUsesCaseInsensitiveKey()
{
$this->mock->addHeaders(array(
'test' => '123',
'Test' => '456'
));
$this->mock->addHeader('TEST', '789');
$headers = array(
'test' => array('123'),
'Test' => array('456'),
'TEST' => array('789'),
);
$header = $this->mock->getHeader('test');
$this->assertInstanceOf('Guzzle\Http\Message\Header', $header);
$this->assertSame($header, $this->mock->getHeader('TEST'));
$this->assertSame($header, $this->mock->getHeader('TeSt'));
$this->assertEquals($headers, $header->raw());
}
/**
* @covers Guzzle\Http\Message\AbstractMessage::setHeader
*/
public function testSettingHeadersUsesCaseInsensitiveKey()
{
$this->mock->setHeader('test', '123');
$this->mock->setHeader('TEST', '456');
$this->assertEquals('456', $this->mock->getHeader('test'));
$this->assertEquals('456', $this->mock->getHeader('TEST'));
}
/**
* @covers Guzzle\Http\Message\AbstractMessage::addHeaders
*/
public function testAddingHeadersPreservesOriginalHeaderCase()
{
$this->mock->addHeaders(array(
'test' => '123',
'Test' => 'abc'
));
$this->mock->addHeader('test', '456');
$this->mock->addHeader('test', '789');
$header = $this->mock->getHeader('test');
$this->assertEquals(array('123', '456', '789', 'abc'), $header->toArray());
$this->mock->addHeader('Test', 'abc');
// Add a header of a different name
$this->assertEquals(array(
'test' => array('123', '456', '789'),
'Test' => array('abc', 'abc')
), $this->mock->getHeader('test')->raw());
}
/**
* @covers Guzzle\Http\Message\AbstractMessage
*/
public function testCanStoreEmptyHeaders()
{
$this->mock->setHeader('Content-Length', 0);
$this->assertTrue($this->mock->hasHeader('Content-Length'));
$this->assertEquals(0, $this->mock->getHeader('Content-Length', true));
}
}
tests/Guzzle/Tests/Http/Message/EntityEnclosingRequestTest.php 0000644 00000043703 15174272742 0020655 0 ustar 00 '123'
));
$request->setBody('Test');
$this->assertEquals('123', $request->getHeader('X-Test'));
$this->assertEquals('100-Continue', $request->getHeader('Expect'));
}
/**
* @covers Guzzle\Http\Message\EntityEnclosingRequest::setBody
*/
public function testCanSetBodyWithoutOverridingContentType()
{
$request = new EntityEnclosingRequest('PUT', 'http://test.com', array(
'Content-Type' => 'application/json'
));
$request->setBody('{"a":"b"}');
$this->assertEquals('application/json', $request->getHeader('Content-Type'));
}
/**
* @covers Guzzle\Http\Message\EntityEnclosingRequest::__toString
* @covers Guzzle\Http\Message\EntityEnclosingRequest::addPostFields
*/
public function testRequestIncludesBodyInMessage()
{
$request = RequestFactory::getInstance()->create('PUT', 'http://www.guzzle-project.com/', null, 'data');
$this->assertEquals("PUT / HTTP/1.1\r\n"
. "Host: www.guzzle-project.com\r\n"
. "User-Agent: " . Utils::getDefaultUserAgent() . "\r\n"
. "Expect: 100-Continue\r\n"
. "Content-Length: 4\r\n\r\n"
. "data", (string) $request);
}
/**
* @covers Guzzle\Http\Message\EntityEnclosingRequest::__toString
*/
public function testRequestIncludesPostBodyInMessageOnlyWhenNoPostFiles()
{
$request = RequestFactory::getInstance()->create('POST', 'http://www.guzzle-project.com/', null, array(
'foo' => 'bar'
));
$this->assertEquals("POST / HTTP/1.1\r\n"
. "Host: www.guzzle-project.com\r\n"
. "User-Agent: " . Utils::getDefaultUserAgent() . "\r\n"
. "Content-Type: application/x-www-form-urlencoded\r\n\r\n"
. "foo=bar", (string) $request);
$request = RequestFactory::getInstance()->create('POST', 'http://www.guzzle-project.com/', null, array(
'foo' => '@' . __FILE__
));
$this->assertEquals("POST / HTTP/1.1\r\n"
. "Host: www.guzzle-project.com\r\n"
. "User-Agent: " . Utils::getDefaultUserAgent() . "\r\n"
. "Expect: 100-Continue\r\n"
. "Content-Type: multipart/form-data\r\n\r\n", (string) $request);
}
/**
* @covers Guzzle\Http\Message\EntityEnclosingRequest::__toString
* @covers Guzzle\Http\Message\EntityEnclosingRequest::addPostFields
*/
public function testAddsPostFieldsAndSetsContentLength()
{
$request = RequestFactory::getInstance()->create('POST', 'http://www.guzzle-project.com/', null, array(
'data' => '123'
));
$this->assertEquals("POST / HTTP/1.1\r\n"
. "Host: www.guzzle-project.com\r\n"
. "User-Agent: " . Utils::getDefaultUserAgent() . "\r\n"
. "Content-Type: application/x-www-form-urlencoded\r\n\r\n"
. "data=123", (string) $request);
}
/**
* @covers Guzzle\Http\Message\EntityEnclosingRequest::__toString
* @covers Guzzle\Http\Message\EntityEnclosingRequest::addPostFiles
* @covers Guzzle\Http\Message\EntityEnclosingRequest::addPostFields
*/
public function testAddsPostFilesAndSetsContentType()
{
$request = RequestFactory::getInstance()->create('POST', 'http://www.test.com/')
->addPostFiles(array(
'file' => __FILE__
))->addPostFields(array(
'a' => 'b'
));
$message = (string) $request;
$this->assertEquals('multipart/form-data', $request->getHeader('Content-Type'));
$this->assertEquals('100-Continue', $request->getHeader('Expect'));
}
/**
* @covers Guzzle\Http\Message\EntityEnclosingRequest::processPostFields
*/
public function testRequestBodyContainsPostFiles()
{
$request = RequestFactory::getInstance()->create('POST', 'http://www.test.com/');
$request->addPostFields(array(
'test' => '123'
));
$this->assertContains("\r\n\r\ntest=123", (string) $request);
}
/**
* @covers Guzzle\Http\Message\EntityEnclosingRequest::processPostFields
*/
public function testRequestBodyAddsContentLength()
{
$request = RequestFactory::getInstance()->create('PUT', 'http://www.test.com/');
$request->setBody(EntityBody::factory('test'));
$this->assertEquals(4, (string) $request->getHeader('Content-Length'));
$this->assertFalse($request->hasHeader('Transfer-Encoding'));
}
/**
* Tests using a Transfer-Encoding chunked entity body already set
* @covers Guzzle\Http\Message\EntityEnclosingRequest::processPostFields
* @covers Guzzle\Http\Message\EntityEnclosingRequest::setBody
*/
public function testRequestBodyDoesNotUseContentLengthWhenChunked()
{
$request = RequestFactory::getInstance()->create('PUT', 'http://www.test.com/');
$request->setBody(EntityBody::factory('test'), null, true);
$this->assertNull($request->getHeader('Content-Length'));
$this->assertTrue($request->hasHeader('Transfer-Encoding'));
}
/**
* @covers Guzzle\Http\Message\EntityEnclosingRequest::getBody
* @covers Guzzle\Http\Message\EntityEnclosingRequest::setBody
*/
public function testRequestHasMutableBody()
{
$request = RequestFactory::getInstance()->create('PUT', 'http://www.guzzle-project.com/', null, 'data');
$body = $request->getBody();
$this->assertInstanceOf('Guzzle\\Http\\EntityBody', $body);
$this->assertSame($body, $request->getBody());
$newBody = EntityBody::factory('foobar');
$request->setBody($newBody);
$this->assertEquals('foobar', (string) $request->getBody());
$this->assertSame($newBody, $request->getBody());
}
/**
* @covers Guzzle\Http\Message\EntityEnclosingRequest::addPostFields
* @covers Guzzle\Http\Message\EntityEnclosingRequest::getPostFields
* @covers Guzzle\Http\Message\EntityEnclosingRequest::getPostFiles
*/
public function testSetPostFields()
{
$request = RequestFactory::getInstance()->create('POST', 'http://www.guzzle-project.com/');
$this->assertInstanceOf('Guzzle\\Http\\QueryString', $request->getPostFields());
$fields = new QueryString(array(
'a' => 'b'
));
$request->addPostFields($fields);
$this->assertEquals($fields->getAll(), $request->getPostFields()->getAll());
$this->assertEquals(array(), $request->getPostFiles());
}
/**
* @covers Guzzle\Http\Message\EntityEnclosingRequest::getPostFiles
* @covers Guzzle\Http\Message\EntityEnclosingRequest::addPostFiles
*/
public function testSetPostFiles()
{
$request = RequestFactory::getInstance()->create('POST', $this->getServer()->getUrl())
->setClient(new Client())
->addPostFiles(array(__FILE__))
->addPostFields(array(
'test' => 'abc'
));
$this->assertEquals(array(
'test' => 'abc'
), $request->getPostFields()->getAll());
$this->assertEquals(array(
'file' => array(new PostFile('file', __FILE__, 'text/x-php'))
), $request->getPostFiles());
$this->getServer()->enqueue("HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n");
$request->send();
$this->assertNotNull($request->getHeader('Content-Length'));
$this->assertContains('multipart/form-data; boundary=', (string) $request->getHeader('Content-Type'), '-> cURL must add the boundary');
}
/**
* @covers Guzzle\Http\Message\EntityEnclosingRequest::addPostFiles
* @covers Guzzle\Http\Message\EntityEnclosingRequest::addPostFile
* @expectedException Guzzle\Common\Exception\InvalidArgumentException
*/
public function testSetPostFilesThrowsExceptionWhenFileIsNotFound()
{
$request = RequestFactory::getInstance()->create('POST', 'http://www.guzzle-project.com/')
->addPostFiles(array(
'file' => 'filenotfound.ini'
));
}
/**
* @covers Guzzle\Http\Message\EntityEnclosingRequest::addPostFile
* @expectedException Guzzle\Http\Exception\RequestException
*/
public function testThrowsExceptionWhenNonStringsAreAddedToPost()
{
$request = RequestFactory::getInstance()->create('POST', 'http://www.guzzle-project.com/')
->addPostFile('foo', new \stdClass());
}
/**
* @covers Guzzle\Http\Message\EntityEnclosingRequest::addPostFile
*/
public function testAllowsContentTypeInPostUploads()
{
$request = RequestFactory::getInstance()->create('POST', 'http://www.guzzle-project.com/')
->addPostFile('foo', __FILE__, 'text/plain');
$this->assertEquals(array(
new PostFile('foo', __FILE__, 'text/plain')
), $request->getPostFile('foo'));
}
/**
* @covers Guzzle\Http\Message\EntityEnclosingRequest::addPostFile
*/
public function testGuessesContentTypeOfPostUpload()
{
$request = RequestFactory::getInstance()->create('POST', 'http://www.guzzle-project.com/')
->addPostFile('foo', __FILE__);
$this->assertEquals(array(
new PostFile('foo', __FILE__, 'text/x-php')
), $request->getPostFile('foo'));
}
/**
* @covers Guzzle\Http\Message\EntityEnclosingRequest::addPostFiles
*/
public function testAllowsContentDispositionFieldsInPostUploadsWhenSettingInBulk()
{
$postFile = new PostFile('foo', __FILE__, 'text/x-php');
$request = RequestFactory::getInstance()->create('POST', 'http://www.guzzle-project.com/')
->addPostFiles(array(
'foo' => $postFile
));
$this->assertEquals(array($postFile), $request->getPostFile('foo'));
}
/**
* @covers Guzzle\Http\Message\EntityEnclosingRequest::setPostField
* @covers Guzzle\Http\Message\EntityEnclosingRequest::processPostFields
*/
public function testPostRequestsUseApplicationXwwwForUrlEncodedForArrays()
{
$request = RequestFactory::getInstance()->create('POST', 'http://www.guzzle-project.com/');
$request->setPostField('a', 'b');
$this->assertContains("\r\n\r\na=b", (string) $request);
$this->assertEquals('application/x-www-form-urlencoded', $request->getHeader('Content-Type'));
}
/**
* @covers Guzzle\Http\Message\EntityEnclosingRequest::processPostFields
*/
public function testProcessMethodAddsContentType()
{
$request = RequestFactory::getInstance()->create('POST', 'http://www.guzzle-project.com/');
$request->setPostField('a', 'b');
$this->assertEquals('application/x-www-form-urlencoded', $request->getHeader('Content-Type'));
}
/**
* @covers Guzzle\Http\Message\EntityEnclosingRequest::processPostFields
*/
public function testPostRequestsUseMultipartFormDataWithFiles()
{
$request = RequestFactory::getInstance()->create('POST', 'http://www.guzzle-project.com/');
$request->addPostFiles(array('file' => __FILE__));
$this->assertEquals('multipart/form-data', $request->getHeader('Content-Type'));
}
/**
* @covers Guzzle\Http\Message\EntityEnclosingRequest::setBody
* @covers Guzzle\Http\Message\EntityEnclosingRequest::processPostFields
*/
public function testCanSendMultipleRequestsUsingASingleRequestObject()
{
$this->getServer()->flush();
$this->getServer()->enqueue(array(
"HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n",
"HTTP/1.1 201 Created\r\nContent-Length: 0\r\n\r\n",
));
// Send the first request
$request = RequestFactory::getInstance()->create('PUT', $this->getServer()->getUrl())
->setBody('test')
->setClient(new Client());
$request->send();
$this->assertEquals(200, $request->getResponse()->getStatusCode());
// Send the second request
$request->setBody('abcdefg', 'application/json', false);
$request->send();
$this->assertEquals(201, $request->getResponse()->getStatusCode());
// Ensure that the same request was sent twice with different bodies
$requests = $this->getServer()->getReceivedRequests(true);
$this->assertEquals(2, count($requests));
$this->assertEquals(4, $requests[0]->getHeader('Content-Length', true));
$this->assertEquals(7, $requests[1]->getHeader('Content-Length', true));
}
/**
* @covers Guzzle\Http\Message\EntityEnclosingRequest::getPostField
* @covers Guzzle\Http\Message\EntityEnclosingRequest::removePostField
*/
public function testRemovingPostFieldRebuildsPostFields()
{
$request = new EntityEnclosingRequest('POST', 'http://test.com');
$request->setPostField('test', 'value');
$request->removePostField('test');
$this->assertNull($request->getPostField('test'));
}
/**
* @covers Guzzle\Http\Message\EntityEnclosingRequest::setBody
*/
public function testUsesChunkedTransferWhenBodyLengthCannotBeDetermined()
{
$this->getServer()->enqueue("HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n");
$request = new EntityEnclosingRequest('PUT', 'http://test.com/');
$request->setBody(fopen($this->getServer()->getUrl(), 'r'));
$this->assertEquals('chunked', $request->getHeader('Transfer-Encoding'));
$this->assertFalse($request->hasHeader('Content-Length'));
}
/**
* @covers Guzzle\Http\Message\EntityEnclosingRequest::setBody
* @expectedException Guzzle\Http\Exception\RequestException
*/
public function testThrowsExceptionWhenContentLengthCannotBeDeterminedAndUsingHttp1()
{
$request = new EntityEnclosingRequest('PUT', 'http://test.com/');
$this->getServer()->enqueue("HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n");
$request->setProtocolVersion('1.0');
$request->setBody(fopen($this->getServer()->getUrl(), 'r'));
}
/**
* @covers Guzzle\Http\Message\EntityEnclosingRequest::getPostFiles
*/
public function testAllowsNestedPostData()
{
$request = new EntityEnclosingRequest('POST', 'http://test.com/');
$request->addPostFields(array(
'a' => array('b', 'c')
));
$this->assertEquals(array(
'a' => array('b', 'c')
), $request->getPostFields()->getAll());
}
/**
* @covers Guzzle\Http\Message\EntityEnclosingRequest::addPostFields
*/
public function testAllowsEmptyFields()
{
$request = new EntityEnclosingRequest('POST', 'http://test.com/');
$request->addPostFields(array(
'a' => ''
));
$this->assertEquals(array(
'a' => ''
), $request->getPostFields()->getAll());
}
/**
* @covers Guzzle\Http\Message\EntityEnclosingRequest::addPostFiles
* @expectedException Guzzle\Http\Exception\RequestException
*/
public function testFailsOnInvalidFiles()
{
$request = new EntityEnclosingRequest('POST', 'http://test.com/');
$request->addPostFiles(array(
'a' => new \stdClass()
));
}
/**
* @covers Guzzle\Http\Message\EntityEnclosingRequest::addPostFields
* @covers Guzzle\Http\Message\EntityEnclosingRequest::getPostFields
*/
public function testHandlesEmptyStrings()
{
$request = new EntityEnclosingRequest('POST', 'http://test.com/');
$request->addPostFields(array(
'a' => '',
'b' => null,
'c' => 'Foo'
));
$this->assertEquals(array(
'a' => '',
'b' => null,
'c' => 'Foo'
), $request->getPostFields()->getAll());
}
/**
* @covers Guzzle\Http\Message\EntityEnclosingRequest::getPostFiles
* @covers Guzzle\Http\Message\EntityEnclosingRequest::getPostFile
* @covers Guzzle\Http\Message\EntityEnclosingRequest::addPostFile
* @covers Guzzle\Http\Message\EntityEnclosingRequest::removePostFile
*/
public function testHoldsPostFiles()
{
$request = new EntityEnclosingRequest('POST', 'http://test.com/');
$request->addPostFile('foo', __FILE__);
$request->addPostFile(new PostFile('foo', __FILE__));
$this->assertEquals(array(
new PostFile('foo', __FILE__, 'text/x-php'),
new PostFile('foo', __FILE__, 'text/x-php')
), $request->getPostFile('foo'));
$this->assertEquals(array(
'foo' => array(
new PostFile('foo', __FILE__, 'text/x-php'),
new PostFile('foo', __FILE__, 'text/x-php')
)
), $request->getPostFiles());
$request->removePostFile('foo');
$this->assertEquals(array(), $request->getPostFiles());
}
/**
* @covers Guzzle\Http\Message\EntityEnclosingRequest::addPostFiles
*/
public function testAllowsAtPrefixWhenAddingPostFiles()
{
$request = new EntityEnclosingRequest('POST', 'http://test.com/');
$request->addPostFiles(array(
'foo' => '@' . __FILE__
));
$this->assertEquals(array(
'foo' => array(
new PostFile('foo', __FILE__, 'text/x-php'),
)
), $request->getPostFiles());
}
}
tests/Guzzle/Tests/Http/Message/HeaderComparisonTest.php 0000644 00000005640 15174272742 0017407 0 ustar 00 'Foo'
), array(
'Content-Length' => 'Foo'
), false),
// Missing header
array(array(
'X-Foo' => 'Bar'
), array(), array(
'- X-Foo' => 'Bar'
)),
// Extra headers is present
array(array(
'X-Foo' => 'Bar'
), array(
'X-Foo' => 'Bar',
'X-Baz' => 'Jar'
), array(
'+ X-Baz' => 'Jar'
)),
// Header is present but must be absent
array(array(
'!X-Foo' => '*'
), array(
'X-Foo' => 'Bar'
), array(
'++ X-Foo' => 'Bar'
)),
// Different values
array(array(
'X-Foo' => 'Bar'
), array(
'X-Foo' => 'Baz'
), array(
'X-Foo' => 'Baz != Bar'
)),
// Wildcard search passes
array(array(
'X-Foo' => '*'
), array(
'X-Foo' => 'Bar'
), false),
// Wildcard search fails
array(array(
'X-Foo' => '*'
), array(), array(
'- X-Foo' => '*'
)),
// Ignore extra header if present
array(array(
'X-Foo' => '*',
'_X-Bar' => '*',
), array(
'X-Foo' => 'Baz',
'X-Bar' => 'Jar'
), false),
// Ignore extra header if present and is not
array(array(
'X-Foo' => '*',
'_X-Bar' => '*',
), array(
'X-Foo' => 'Baz'
), false),
// Case insensitive
array(array(
'X-Foo' => '*',
'_X-Bar' => '*',
), array(
'x-foo' => 'Baz',
'x-BAR' => 'baz'
), false),
// Case insensitive with collection
array(array(
'X-Foo' => '*',
'_X-Bar' => '*',
), new Collection(array(
'x-foo' => 'Baz',
'x-BAR' => 'baz'
)), false),
);
}
/**
* @dataProvider filterProvider
*/
public function testComparesHeaders($filters, $headers, $result)
{
$compare = new HeaderComparison();
$this->assertEquals($result, $compare->compare($filters, $headers));
}
}
tests/Guzzle/Tests/Http/Message/HeaderTest.php 0000644 00000006172 15174272742 0015355 0 ustar 00 array('foo', 'Foo'),
'Zoo' => 'bar',
);
public function testRawReturnsRawArray()
{
$i = new Header('Zoo', $this->test);
$this->assertEquals(array(
'zoo' => array('foo', 'Foo'),
'Zoo' => array('bar')
), $i->raw());
}
public function testStoresHeaderName()
{
$i = new Header('Zoo', $this->test);
$this->assertEquals('Zoo', $i->getName());
}
public function testConvertsToString()
{
$i = new Header('Zoo', $this->test);
$this->assertEquals('foo, Foo, bar', (string) $i);
$i->setGlue('; ');
$this->assertEquals('foo; Foo; bar', (string) $i);
}
public function testNormalizesCases()
{
$h = new Header('Zoo', $this->test);
$h->normalize();
$this->assertEquals(array(
'Zoo' => array('foo', 'Foo', 'bar')
), $h->raw());
}
public function testCanSearchForValues()
{
$h = new Header('Zoo', $this->test);
$this->assertTrue($h->hasValue('foo'));
$this->assertTrue($h->hasValue('Foo'));
$this->assertTrue($h->hasValue('bar'));
$this->assertFalse($h->hasValue('moo'));
$this->assertFalse($h->hasValue('FoO'));
$this->assertTrue($h->hasValue('FoO', true));
}
public function testIsCountable()
{
$h = new Header('Zoo', $this->test);
$this->assertEquals(3, count($h));
}
public function testCanBeIterated()
{
$h = new Header('Zoo', $this->test);
$results = array();
foreach ($h as $key => $value) {
$results[$key] = $value;
}
$this->assertEquals(array(
'foo', 'Foo', 'bar'
), $results);
}
public function testAllowsFalseyValues()
{
// Allows 0
$h = new Header('Foo', 0, ';');
$this->assertEquals('0', (string) $h);
$this->assertEquals(1, count($h));
$this->assertEquals(';', $h->getGlue());
// Does not add a null header by default
$h = new Header('Foo');
$this->assertEquals('', (string) $h);
$this->assertEquals(0, count($h));
// Allows null array for a single null header
$h = new Header('Foo', array(null));
$this->assertEquals('', (string) $h);
$this->assertEquals(1, count($h));
// Allows empty string
$h = new Header('Foo', '');
$this->assertEquals('', (string) $h);
$this->assertEquals(1, count($h));
}
public function testUsesHeaderNameWhenNoneIsSupplied()
{
$h = new Header('Foo', 'bar', ';');
$h->add('baz');
$this->assertEquals(array('Foo'), array_keys($h->raw()));
}
public function testCanCheckForExactHeaderValues()
{
$h = new Header('Foo', 'bar', ';');
$this->assertTrue($h->hasExactHeader('Foo'));
$this->assertFalse($h->hasExactHeader('foo'));
}
}
tests/Guzzle/Tests/Http/Message/PostFileTest.php 0000644 00000002735 15174272742 0015713 0 ustar 00 assertEquals('foo', $file->getFieldName());
$this->assertEquals(__FILE__, $file->getFilename());
$this->assertEquals('x-foo', $file->getContentType());
}
public function testRemovesLeadingAtSymbolFromPath()
{
$file = new PostFile('foo', '@' . __FILE__);
$this->assertEquals(__FILE__, $file->getFilename());
}
/**
* @expectedException Guzzle\Common\Exception\InvalidArgumentException
*/
public function testEnsuresFileIsReadable()
{
$file = new PostFile('foo', '/foo/baz/bar');
}
public function testCanChangeContentType()
{
$file = new PostFile('foo', '@' . __FILE__);
$file->setContentType('Boo');
$this->assertEquals('Boo', $file->getContentType());
}
public function testCanChangeFieldName()
{
$file = new PostFile('foo', '@' . __FILE__);
$file->setFieldName('Boo');
$this->assertEquals('Boo', $file->getFieldName());
}
public function testReturnsCurlValueString()
{
$file = new PostFile('foo', __FILE__);
$this->assertEquals('@' . __FILE__ . ';type=text/x-php', $file->getCurlString());
}
}
tests/Guzzle/Tests/Http/Message/RequestFactoryTest.php 0000644 00000034745 15174272742 0017154 0 ustar 00 assertSame($factory, RequestFactory::getInstance());
}
/**
* @covers Guzzle\Http\Message\RequestFactory::create
* @covers Guzzle\Http\Message\RequestFactory::getInstance
*/
public function testCreatesNewGetRequests()
{
$request = RequestFactory::getInstance()->create('GET', 'http://www.google.com/');
$this->assertInstanceOf('Guzzle\\Http\\Message\\MessageInterface', $request);
$this->assertInstanceOf('Guzzle\\Http\\Message\\RequestInterface', $request);
$this->assertInstanceOf('Guzzle\\Http\\Message\\Request', $request);
$this->assertEquals('GET', $request->getMethod());
$this->assertEquals('http', $request->getScheme());
$this->assertEquals('http://www.google.com/', $request->getUrl());
$this->assertEquals('www.google.com', $request->getHost());
$this->assertEquals('/', $request->getPath());
$this->assertEquals('/', $request->getResourceUri());
// Create a GET request with a custom receiving body
$this->getServer()->enqueue("HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n");
$b = EntityBody::factory();
$request = RequestFactory::getInstance()->create('GET', $this->getServer()->getUrl(), null, $b);
$request->setClient(new Client());
$response = $request->send();
$this->assertSame($b, $response->getBody());
}
/**
* @covers Guzzle\Http\Message\RequestFactory::create
*/
public function testCreatesPutRequests()
{
// Test using a string
$request = RequestFactory::getInstance()->create('PUT', 'http://www.google.com/path?q=1&v=2', null, 'Data');
$this->assertInstanceOf('Guzzle\\Http\\Message\\EntityEnclosingRequest', $request);
$this->assertEquals('PUT', $request->getMethod());
$this->assertEquals('http', $request->getScheme());
$this->assertEquals('http://www.google.com/path?q=1&v=2', $request->getUrl());
$this->assertEquals('www.google.com', $request->getHost());
$this->assertEquals('/path', $request->getPath());
$this->assertEquals('/path?q=1&v=2', $request->getResourceUri());
$this->assertInstanceOf('Guzzle\\Http\\EntityBody', $request->getBody());
$this->assertEquals('Data', (string) $request->getBody());
unset($request);
// Test using an EntityBody
$request = RequestFactory::getInstance()->create('PUT', 'http://www.google.com/path?q=1&v=2', null, EntityBody::factory('Data'));
$this->assertInstanceOf('Guzzle\\Http\\Message\\EntityEnclosingRequest', $request);
$this->assertEquals('Data', (string) $request->getBody());
// Test using a resource
$resource = fopen('php://temp', 'w+');
fwrite($resource, 'Data');
$request = RequestFactory::getInstance()->create('PUT', 'http://www.google.com/path?q=1&v=2', null, $resource);
$this->assertInstanceOf('Guzzle\\Http\\Message\\EntityEnclosingRequest', $request);
$this->assertEquals('Data', (string) $request->getBody());
// Test using an object that can be cast as a string
$request = RequestFactory::getInstance()->create('PUT', 'http://www.google.com/path?q=1&v=2', null, Url::factory('http://www.example.com/'));
$this->assertInstanceOf('Guzzle\\Http\\Message\\EntityEnclosingRequest', $request);
$this->assertEquals('http://www.example.com/', (string) $request->getBody());
}
/**
* @covers Guzzle\Http\Message\RequestFactory::create
*/
public function testCreatesHeadAndDeleteRequests()
{
$request = RequestFactory::getInstance()->create('DELETE', 'http://www.test.com/');
$this->assertEquals('DELETE', $request->getMethod());
$request = RequestFactory::getInstance()->create('HEAD', 'http://www.test.com/');
$this->assertEquals('HEAD', $request->getMethod());
}
/**
* @covers Guzzle\Http\Message\RequestFactory::create
*/
public function testCreatesOptionsRequests()
{
$request = RequestFactory::getInstance()->create('OPTIONS', 'http://www.example.com/');
$this->assertEquals('OPTIONS', $request->getMethod());
$this->assertInstanceOf('Guzzle\\Http\\Message\\Request', $request);
}
/**
* @covers Guzzle\Http\Message\RequestFactory::create
*/
public function testCreatesNewPutRequestWithBody()
{
$request = RequestFactory::getInstance()->create('PUT', 'http://www.google.com/path?q=1&v=2', null, 'Data');
$this->assertEquals('Data', (string) $request->getBody());
}
/**
* @covers Guzzle\Http\Message\RequestFactory::create
*/
public function testCreatesNewPostRequestWithFields()
{
// Use an array
$request = RequestFactory::getInstance()->create('POST', 'http://www.google.com/path?q=1&v=2', null, array(
'a' => 'b'
));
$this->assertEquals(array('a' => 'b'), $request->getPostFields()->getAll());
unset($request);
// Use a collection
$request = RequestFactory::getInstance()->create('POST', 'http://www.google.com/path?q=1&v=2', null, new Collection(array(
'a' => 'b'
)));
$this->assertEquals(array('a' => 'b'), $request->getPostFields()->getAll());
// Use a QueryString
$request = RequestFactory::getInstance()->create('POST', 'http://www.google.com/path?q=1&v=2', null, new QueryString(array(
'a' => 'b'
)));
$this->assertEquals(array('a' => 'b'), $request->getPostFields()->getAll());
$request = RequestFactory::getInstance()->create('POST', 'http://www.test.com/', null, array(
'a' => 'b',
'file' => '@' . __FILE__
));
$this->assertEquals(array(
'a' => 'b'
), $request->getPostFields()->getAll());
$this->assertEquals(array(
'file' => array(new PostFile('file', __FILE__, 'text/x-php'))
), $request->getPostFiles());
}
/**
* @covers Guzzle\Http\Message\RequestFactory::fromParts
* @covers Guzzle\Http\Message\RequestFactory::create
*/
public function testCreatesFromParts()
{
$parts = parse_url('http://michael:123@www.google.com:8080/path?q=1&v=2');
$request = RequestFactory::getInstance()->fromParts('PUT', $parts, null, 'Data');
$this->assertInstanceOf('Guzzle\\Http\\Message\\EntityEnclosingRequest', $request);
$this->assertEquals('PUT', $request->getMethod());
$this->assertEquals('http', $request->getScheme());
$this->assertEquals('http://www.google.com:8080/path?q=1&v=2', $request->getUrl());
$this->assertEquals('www.google.com', $request->getHost());
$this->assertEquals('www.google.com:8080', $request->getHeader('Host'));
$this->assertEquals('/path', $request->getPath());
$this->assertEquals('/path?q=1&v=2', $request->getResourceUri());
$this->assertInstanceOf('Guzzle\\Http\\EntityBody', $request->getBody());
$this->assertEquals('Data', (string)$request->getBody());
$this->assertEquals('michael', $request->getUsername());
$this->assertEquals('123', $request->getPassword());
$this->assertEquals('8080', $request->getPort());
$this->assertEquals(array(
'scheme' => 'http',
'host' => 'www.google.com',
'port' => 8080,
'path' => '/path',
'query' => 'q=1&v=2',
), parse_url($request->getUrl()));
}
/**
* @covers Guzzle\Http\Message\RequestFactory::fromMessage
* @covers Guzzle\Http\Message\RequestFactory::create
*/
public function testCreatesFromMessage()
{
$auth = base64_encode('michael:123');
$message = "PUT /path?q=1&v=2 HTTP/1.1\r\nHost: www.google.com:8080\r\nContent-Length: 4\r\nAuthorization: Basic {$auth}\r\n\r\nData";
$request = RequestFactory::getInstance()->fromMessage($message);
$this->assertInstanceOf('Guzzle\\Http\\Message\\EntityEnclosingRequest', $request);
$this->assertEquals('PUT', $request->getMethod());
$this->assertEquals('http', $request->getScheme());
$this->assertEquals('http://www.google.com:8080/path?q=1&v=2', $request->getUrl());
$this->assertEquals('www.google.com', $request->getHost());
$this->assertEquals('www.google.com:8080', $request->getHeader('Host'));
$this->assertEquals('/path', $request->getPath());
$this->assertEquals('/path?q=1&v=2', $request->getResourceUri());
$this->assertInstanceOf('Guzzle\\Http\\EntityBody', $request->getBody());
$this->assertEquals('Data', (string) $request->getBody());
$this->assertEquals('michael', $request->getUsername());
$this->assertEquals('123', $request->getPassword());
$this->assertEquals('8080', $request->getPort());
// Test passing a blank message returns false
$this->assertFalse($request = RequestFactory::getInstance()->fromMessage(''));
// Test passing a url with no port
$message = "PUT /path?q=1&v=2 HTTP/1.1\r\nHost: www.google.com\r\nContent-Length: 4\r\nAuthorization: Basic {$auth}\r\n\r\nData";
$request = RequestFactory::getInstance()->fromMessage($message);
$this->assertInstanceOf('Guzzle\\Http\\Message\\EntityEnclosingRequest', $request);
$this->assertEquals('PUT', $request->getMethod());
$this->assertEquals('http', $request->getScheme());
$this->assertEquals('http://www.google.com/path?q=1&v=2', $request->getUrl());
$this->assertEquals('www.google.com', $request->getHost());
$this->assertEquals('/path', $request->getPath());
$this->assertEquals('/path?q=1&v=2', $request->getResourceUri());
$this->assertInstanceOf('Guzzle\\Http\\EntityBody', $request->getBody());
$this->assertEquals('Data', (string)$request->getBody());
$this->assertEquals('michael', $request->getUsername());
$this->assertEquals('123', $request->getPassword());
$this->assertEquals(80, $request->getPort());
}
/**
* @covers Guzzle\Http\Message\RequestFactory::create
*/
public function testCreatesNewTraceRequest()
{
$request = RequestFactory::getInstance()->create('TRACE', 'http://www.google.com/');
$this->assertFalse($request instanceof \Guzzle\Http\Message\EntityEnclosingRequest);
$this->assertEquals('TRACE', $request->getMethod());
}
/**
* @covers Guzzle\Http\Message\RequestFactory::create
*/
public function testCreatesProperTransferEncodingRequests()
{
$request = RequestFactory::getInstance()->create('PUT', 'http://www.google.com/', array(
'Transfer-Encoding' => 'chunked'
), 'hello');
$this->assertEquals('chunked', $request->getHeader('Transfer-Encoding'));
$this->assertFalse($request->hasHeader('Content-Length'));
}
/**
* @covers Guzzle\Http\Message\RequestFactory::fromMessage
*/
public function testProperlyDealsWithDuplicateHeaders()
{
$parser = new MessageParser();
$message = "POST / http/1.1\r\n"
. "DATE:Mon, 09 Sep 2011 23:36:00 GMT\r\n"
. "host:host.foo.com\r\n"
. "ZOO:abc\r\n"
. "ZOO:123\r\n"
. "ZOO:HI\r\n"
. "zoo:456\r\n\r\n";
$parts = $parser->parseRequest($message);
$this->assertEquals(array (
'DATE' => 'Mon, 09 Sep 2011 23:36:00 GMT',
'host' => 'host.foo.com',
'ZOO' => array('abc', '123', 'HI'),
'zoo' => '456',
), $parts['headers']);
$request = RequestFactory::getInstance()->fromMessage($message);
$this->assertEquals(array(
'ZOO' => array('abc', '123', 'HI'),
'zoo' => array('456')
), $request->getHeader('zoo')->raw());
}
/**
* @covers Guzzle\Http\Message\RequestFactory::fromMessage
* @covers Guzzle\Http\Message\RequestFactory::create
*/
public function testCreatesHttpMessagesWithBodiesAndNormalizesLineEndings()
{
$message = "POST / http/1.1\r\n"
. "Content-Type:application/x-www-form-urlencoded; charset=utf8\r\n"
. "Date:Mon, 09 Sep 2011 23:36:00 GMT\r\n"
. "Host:host.foo.com\r\n\r\n"
. "foo=bar";
$request = RequestFactory::getInstance()->fromMessage($message);
$this->assertEquals('application/x-www-form-urlencoded; charset=utf8', (string) $request->getHeader('Content-Type'));
$this->assertEquals('foo=bar', (string) $request->getBody());
$message = "POST / http/1.1\n"
. "Content-Type:application/x-www-form-urlencoded; charset=utf8\n"
. "Date:Mon, 09 Sep 2011 23:36:00 GMT\n"
. "Host:host.foo.com\n\n"
. "foo=bar";
$request = RequestFactory::getInstance()->fromMessage($message);
$this->assertEquals('foo=bar', (string) $request->getBody());
$message = "PUT / HTTP/1.1\r\nContent-Length: 0\r\n\r\n";
$request = RequestFactory::getInstance()->fromMessage($message);
$this->assertTrue($request->hasHeader('Content-Length'));
$this->assertEquals(0, (string) $request->getHeader('Content-Length'));
}
/**
* @covers Guzzle\Http\Message\RequestFactory::create
*/
public function testHandlesChunkedTransferEncoding()
{
$request = RequestFactory::getInstance()->create('PUT', 'http://www.foo.com/', array(
'Transfer-Encoding' => 'chunked'
), 'Test');
$this->assertFalse($request->hasHeader('Content-Length'));
$this->assertEquals('chunked', $request->getHeader('Transfer-Encoding'));
$request = RequestFactory::getInstance()->create('POST', 'http://www.foo.com/', array(
'transfer-encoding' => 'chunked'
), array(
'foo' => 'bar'
));
$this->assertFalse($request->hasHeader('Content-Length'));
$this->assertEquals('chunked', $request->getHeader('Transfer-Encoding'));
}
}
tests/Guzzle/Tests/Http/Message/RequestTest.php 0000644 00000076021 15174272742 0015615 0 ustar 00 client = new Client($this->getServer()->getUrl());
$this->request = $this->client->get();
}
public function tearDown()
{
unset($this->request);
unset($this->client);
}
/**
* @covers Guzzle\Http\Message\Request::__construct
*/
public function testConstructorBuildsRequestWithArrayHeaders()
{
// Test passing an array of headers
$request = new Request('GET', 'http://www.guzzle-project.com/', array(
'foo' => 'bar'
));
$this->assertEquals('GET', $request->getMethod());
$this->assertEquals('http://www.guzzle-project.com/', $request->getUrl());
$this->assertEquals('bar', $request->getHeader('foo'));
}
/**
* @covers Guzzle\Http\Message\Request::getAllEvents
*/
public function testDescribesEvents()
{
$this->assertInternalType('array', Request::getAllEvents());
}
/**
* @covers Guzzle\Http\Message\Request::__construct
*/
public function testConstructorBuildsRequestWithCollectionHeaders()
{
$request = new Request('GET', 'http://www.guzzle-project.com/', new Collection(array(
'foo' => 'bar'
)));
$this->assertEquals('bar', $request->getHeader('foo'));
}
/**
* @covers Guzzle\Http\Message\Request::__construct
*/
public function testConstructorBuildsRequestWithNoHeaders()
{
$request = new Request('GET', 'http://www.guzzle-project.com/', null);
$this->assertFalse($request->hasHeader('foo'));
}
/**
* @covers Guzzle\Http\Message\Request::__construct
*/
public function testConstructorHandlesBasicAuth()
{
$auth = base64_encode('michael:foo');
$request = new Request('GET', 'http://www.guzzle-project.com/', array(
'Authorization' => 'Basic ' . $auth
));
$this->assertEquals('michael', $request->getUserName());
$this->assertEquals('foo', $request->getPassword());
$this->assertEquals('Basic ' . $auth, (string) $request->getHeader('Authorization'));
}
/**
* @covers Guzzle\Http\Message\Request::__construct
*/
public function testConstructorHandlesNonBasicAuth()
{
$request = new Request('GET', 'http://www.guzzle-project.com/', array(
'Authorization' => 'Foo bar'
));
$this->assertNull($request->getUserName());
$this->assertNull($request->getPassword());
$this->assertEquals('Foo bar', (string) $request->getHeader('Authorization'));
}
/**
* @covers Guzzle\Http\Message\Request::__toString
* @covers Guzzle\Http\Message\Request::getRawHeaders
* @covers Guzzle\Http\Message\AbstractMessage::getHeaderString
*/
public function testRequestsCanBeConvertedToRawMessageStrings()
{
$auth = base64_encode('michael:123');
$message = "PUT /path?q=1&v=2 HTTP/1.1\r\n"
. "Host: www.google.com\r\n"
. "Authorization: Basic {$auth}\r\n"
. "User-Agent: " . Utils::getDefaultUserAgent() . "\r\n"
. "Expect: 100-Continue\r\n"
. "Content-Length: 4\r\n\r\nData";
$request = RequestFactory::getInstance()->create('PUT', 'http://www.google.com/path?q=1&v=2', array(
'Authorization' => 'Basic ' . $auth
), 'Data');
$this->assertEquals($message, $request->__toString());
}
/**
* Add authorization after the fact and see that it was put in the message
*
* @covers Guzzle\Http\Message\Request::__toString
* @covers Guzzle\Http\Message\Request::getRawHeaders
*/
public function testRequestStringsIncludeAuth()
{
$auth = base64_encode('michael:123');
$this->getServer()->enqueue("HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n");
$request = RequestFactory::getInstance()->create('PUT', $this->getServer()->getUrl(), null, 'Data')
->setClient($this->client)
->setAuth('michael', '123', CURLAUTH_BASIC);
$request->send();
$this->assertContains('Authorization: Basic ' . $auth, (string) $request);
}
/**
* @covers Guzzle\Http\Message\Request::getEventDispatcher
*/
public function testGetEventDispatcher()
{
$d = $this->request->getEventDispatcher();
$this->assertInstanceOf('Symfony\\Component\\EventDispatcher\\EventDispatcherInterface', $d);
$this->assertEquals($d, $this->request->getEventDispatcher());
}
/**
* @covers Guzzle\Http\Message\Request::getClient
* @covers Guzzle\Http\Message\Request::setClient
*/
public function testRequestsManageClients()
{
$request = new Request('GET', 'http://test.com');
$this->assertNull($request->getClient());
$request->setClient($this->client);
$this->assertSame($this->client, $request->getClient());
}
/**
* @covers Guzzle\Http\Message\Request::send
* @expectedException RuntimeException
* @expectedExceptionMessage A client must be set on the request
*/
public function testRequestsRequireClients()
{
$request = new Request('GET', 'http://test.com');
$request->send();
}
/**
* @covers Guzzle\Http\Message\Request::send
* @covers Guzzle\Http\Message\Request::getResponse
* @covers Guzzle\Http\Message\Request::setResponse
* @covers Guzzle\Http\Message\Request::processResponse
* @covers Guzzle\Http\Message\Request::getResponseBody
*/
public function testSend()
{
$response = new Response(200, array(
'Content-Length' => 3
), 'abc');
$this->request->setResponse($response, true);
$r = $this->request->send();
$this->assertSame($response, $r);
$this->assertInstanceOf('Guzzle\\Http\\Message\\Response', $this->request->getResponse());
$this->assertSame($r, $this->request->getResponse());
$this->assertEquals('complete', $this->request->getState());
}
/**
* @covers Guzzle\Http\Message\Request::getResponse
* @covers Guzzle\Http\Message\Request::setResponse
* @covers Guzzle\Http\Message\Request::processResponse
* @covers Guzzle\Http\Message\Request::getResponseBody
*/
public function testGetResponse()
{
$this->assertNull($this->request->getResponse());
$response = new Response(200, array(
'Content-Length' => 3
), 'abc');
$this->request->setResponse($response);
$this->assertEquals($response, $this->request->getResponse());
$request = new Request('GET', 'http://www.google.com/');
$request->setResponse($response, true);
$request->setState(RequestInterface::STATE_COMPLETE);
$requestResponse = $request->getResponse();
$this->assertSame($response, $requestResponse);
// Try again, making sure it's still the same response
$this->assertSame($requestResponse, $request->getResponse());
$response = new Response(204);
$request = new Request('GET', 'http://www.google.com/');
$request->setResponse($response, true);
$request->setState('complete');
$requestResponse = $request->getResponse();
$this->assertSame($response, $requestResponse);
$this->assertInstanceOf('Guzzle\\Http\\EntityBody', $response->getBody());
}
/**
* @covers Guzzle\Http\Message\Request::getResponse
* @covers Guzzle\Http\Message\Request::processResponse
* @covers Guzzle\Http\Message\Request::getResponseBody
*/
public function testRequestThrowsExceptionOnBadResponse()
{
$response = new Response(404, array(
'Content-Length' => 3
), 'abc');
$request = new Request('GET', 'http://www.google.com/');
$request->setClient($this->client);
try {
$request->setResponse($response, true);
$request->send();
$this->fail('Expected exception not thrown');
} catch (BadResponseException $e) {
$this->assertInstanceOf('Guzzle\\Http\\Message\\RequestInterface', $e->getRequest());
$this->assertInstanceOf('Guzzle\\Http\\Message\\Response', $e->getResponse());
$this->assertContains('Client error response', $e->getMessage());
}
}
/**
* @covers Guzzle\Http\Message\Request::getQuery
*/
public function testManagesQuery()
{
$this->assertInstanceOf('Guzzle\\Http\\QueryString', $this->request->getQuery());
$this->request->getQuery()->set('test', '123');
$this->assertEquals('?test=123', $this->request->getQuery(true));
}
/**
* @covers Guzzle\Http\Message\Request::getMethod
*/
public function testRequestHasMethod()
{
$this->assertEquals('GET', $this->request->getMethod());
}
/**
* @covers Guzzle\Http\Message\Request::getScheme
* @covers Guzzle\Http\Message\Request::setScheme
*/
public function testRequestHasScheme()
{
$this->assertEquals('http', $this->request->getScheme());
$this->assertEquals($this->request, $this->request->setScheme('https'));
$this->assertEquals('https', $this->request->getScheme());
}
/**
* @covers Guzzle\Http\Message\Request::getHost
* @covers Guzzle\Http\Message\Request::setHost
*/
public function testRequestHasHost()
{
$this->assertEquals('127.0.0.1', $this->request->getHost());
$this->assertEquals('127.0.0.1:8124', (string) $this->request->getHeader('Host'));
$this->assertSame($this->request, $this->request->setHost('www2.google.com'));
$this->assertEquals('www2.google.com', $this->request->getHost());
$this->assertEquals('www2.google.com:8124', (string) $this->request->getHeader('Host'));
$this->assertSame($this->request, $this->request->setHost('www.test.com:8081'));
$this->assertEquals('www.test.com', $this->request->getHost());
$this->assertEquals(8081, $this->request->getPort());
}
/**
* @covers Guzzle\Http\Message\Request::getProtocolVersion
* @covers Guzzle\Http\Message\Request::setProtocolVersion
*/
public function testRequestHasProtocol()
{
$this->assertEquals('1.1', $this->request->getProtocolVersion());
$this->assertEquals($this->request, $this->request->setProtocolVersion('1.1'));
$this->assertEquals('1.1', $this->request->getProtocolVersion());
$this->assertEquals($this->request, $this->request->setProtocolVersion('1.0'));
$this->assertEquals('1.0', $this->request->getProtocolVersion());
}
/**
* @covers Guzzle\Http\Message\Request::getPath
* @covers Guzzle\Http\Message\Request::setPath
*/
public function testRequestHasPath()
{
$this->assertEquals('/', $this->request->getPath());
$this->assertEquals($this->request, $this->request->setPath('/index.html'));
$this->assertEquals('/index.html', $this->request->getPath());
$this->assertEquals($this->request, $this->request->setPath('index.html'));
$this->assertEquals('/index.html', $this->request->getPath());
}
/**
* @covers Guzzle\Http\Message\Request::getPort
* @covers Guzzle\Http\Message\Request::setPort
*/
public function testRequestHasPort()
{
$this->assertEquals(8124, $this->request->getPort());
$this->assertEquals('127.0.0.1:8124', $this->request->getHeader('Host'));
$this->assertEquals($this->request, $this->request->setPort('8080'));
$this->assertEquals('8080', $this->request->getPort());
$this->assertEquals('127.0.0.1:8080', $this->request->getHeader('Host'));
$this->request->setPort(80);
$this->assertEquals('127.0.0.1', $this->request->getHeader('Host'));
}
/**
* @covers Guzzle\Http\Message\Request::getUsername
* @covers Guzzle\Http\Message\Request::getPassword
* @covers Guzzle\Http\Message\Request::setAuth
*/
public function testRequestHandlesAuthorization()
{
// Uninitialized auth
$this->assertEquals(null, $this->request->getUsername());
$this->assertEquals(null, $this->request->getPassword());
// Set an auth
$this->assertSame($this->request, $this->request->setAuth('michael', '123'));
$this->assertEquals('michael', $this->request->getUsername());
$this->assertEquals('123', $this->request->getPassword());
// Remove the auth
$this->request->setAuth(false);
$this->assertEquals(null, $this->request->getUsername());
$this->assertEquals(null, $this->request->getPassword());
// Make sure that the cURL based auth works too
$request = new Request('GET', $this->getServer()->getUrl());
$request->setAuth('michael', 'password', CURLAUTH_DIGEST);
$this->assertEquals('michael:password', $request->getCurlOptions()->get(CURLOPT_USERPWD));
$this->assertEquals(CURLAUTH_DIGEST, $request->getCurlOptions()->get(CURLOPT_HTTPAUTH));
}
/**
* @covers Guzzle\Http\Message\Request::getResourceUri
*/
public function testGetResourceUri()
{
$this->assertEquals('/', $this->request->getResourceUri());
$this->request->setPath('/index.html');
$this->assertEquals('/index.html', $this->request->getResourceUri());
$this->request->getQuery()->add('v', '1');
$this->assertEquals('/index.html?v=1', $this->request->getResourceUri());
}
/**
* @covers Guzzle\Http\Message\Request::getUrl
* @covers Guzzle\Http\Message\Request::setUrl
*/
public function testRequestHasMutableUrl()
{
$url = 'http://www.test.com:8081/path?q=123#fragment';
$u = Url::factory($url);
$this->assertSame($this->request, $this->request->setUrl($url));
$this->assertEquals($url, $this->request->getUrl());
$this->assertSame($this->request, $this->request->setUrl($u));
$this->assertEquals($url, $this->request->getUrl());
}
/**
* @covers Guzzle\Http\Message\Request::setState
* @covers Guzzle\Http\Message\Request::getState
*/
public function testRequestHasState()
{
$this->assertEquals(RequestInterface::STATE_NEW, $this->request->getState());
$this->request->setState(RequestInterface::STATE_TRANSFER);
$this->assertEquals(RequestInterface::STATE_TRANSFER, $this->request->getState());
}
/**
* @covers Guzzle\Http\Message\Request::setResponse
* @covers Guzzle\Http\Message\Request::getResponse
* @covers Guzzle\Http\Message\Request::getState
*/
public function testSetManualResponse()
{
$response = new Response(200, array(
'Date' => 'Sat, 16 Oct 2010 17:27:14 GMT',
'Expires' => '-1',
'Cache-Control' => 'private, max-age=0',
'Content-Type' => 'text/html; charset=ISO-8859-1',
), 'response body');
$this->assertSame($this->request, $this->request->setResponse($response), '-> setResponse() must use a fluent interface');
$this->assertEquals('complete', $this->request->getState(), '-> setResponse() must change the state of the request to complete');
$this->assertSame($response, $this->request->getResponse(), '-> setResponse() must set the exact same response that was passed in to it');
}
/**
* @covers Guzzle\Http\Message\Request::setResponseBody
*/
public function testRequestCanHaveManuallySetResponseBody()
{
$file = __DIR__ . '/../../TestData/temp.out';
if (file_exists($file)) {
unlink($file);
}
$this->getServer()->enqueue("HTTP/1.1 200 OK\r\nContent-Length: 4\r\n\r\ndata");
$request = RequestFactory::getInstance()->create('GET', $this->getServer()->getUrl());
$request->setClient($this->client);
$request->setResponseBody(EntityBody::factory(fopen($file, 'w+')));
$request->send();
$this->assertTrue(file_exists($file));
unlink($file);
$this->assertEquals('data', $request->getResponse()->getBody(true));
}
/**
* @covers Guzzle\Http\Message\Request::isResponseBodyRepeatable
*/
public function testDeterminesIfResponseBodyRepeatable()
{
// The default stream created for responses is seekable
$request = RequestFactory::getInstance()->create('GET', 'http://localhost:' . $this->getServer()->getPort());
$this->assertTrue($request->isResponseBodyRepeatable());
// This should return false because an HTTP stream is not seekable
$this->getServer()->enqueue("HTTP/1.1 200 OK\r\nContent-Length: 4\r\n\r\ndata");
$request->setResponseBody(EntityBody::factory(fopen($this->getServer()->getUrl(), true)));
$this->assertFalse($request->isResponseBodyRepeatable());
}
/**
* @covers Guzzle\Http\Message\Request::canCache
*/
public function testDeterminesIfCanCacheRequest()
{
$this->assertTrue(RequestFactory::getInstance()->fromMessage(
"GET / HTTP/1.1\r\nHost: www.test.com\r\nCache-Control: no-cache, max-age=120\r\n\r\n"
)->canCache());
$this->assertTrue(RequestFactory::getInstance()->fromMessage(
"HEAD / HTTP/1.1\r\nHost: www.test.com\r\nCache-Control: no-cache, max-age=120\r\n\r\n"
)->canCache());
$this->assertFalse(RequestFactory::getInstance()->fromMessage(
"HEAD / HTTP/1.1\r\nHost: www.test.com\r\nCache-Control: no-cache, max-age=120, no-store\r\n\r\n"
)->canCache());
$this->assertFalse(RequestFactory::getInstance()->fromMessage(
"POST / HTTP/1.1\r\nHost: www.test.com\r\n\r\n"
)->canCache());
$this->assertFalse(RequestFactory::getInstance()->fromMessage(
"PUT / HTTP/1.1\r\nHost: www.test.com\r\nCache-Control: no-cache, max-age=120\r\n\r\n"
)->canCache());
}
/**
* @covers Guzzle\Http\Message\Request
*/
public function testHoldsCookies()
{
$cookie = $this->request->getCookie();
$this->assertInstanceOf('Guzzle\\Http\\Cookie', $this->request->getCookie());
// Ensure that the cookie will not affect the request
$this->assertNull($this->request->getCookie('test'));
$cookie->set('test', 'abc');
$this->assertNull($this->request->getCookie('test'));
// Set a cookie
$this->assertSame($this->request, $this->request->addCookie('test', 'abc'));
$this->assertEquals('abc', $this->request->getCookie('test'));
// Unset the cookies by setting the Cookie header to null
$this->request->setHeader('Cookie', null);
$this->assertNull($this->request->getCookie('test'));
// Set and remove a cookie
$this->assertSame($this->request, $this->request->addCookie('test', 'abc'));
$this->assertEquals('abc', $this->request->getCookie('test'));
$this->assertSame($this->request, $this->request->removeCookie('test'));
$this->assertNull($this->request->getCookie('test'));
// Remove the cookie header
$this->assertSame($this->request, $this->request->addCookie('test', 'abc'));
$this->request->removeHeader('Cookie');
$this->assertEquals('', (string)$this->request->getCookie());
// Set the cookie using a cookie object
$this->assertSame($this->request, $this->request->setCookie($cookie));
$this->assertEquals($cookie->getAll(), $this->request->getCookie()->getAll());
// Set the cookie using an array
$this->assertSame($this->request, $this->request->setCookie(array(
'test' => 'def'
)));
$this->assertEquals(array(
'test' => 'def'
), $this->request->getCookie()->getAll());
// Test using an invalid value
try {
$this->request->setCookie('a');
$this->fail('Did not throw expected exception when passing invalid value');
} catch (\InvalidArgumentException $e) {
}
}
/**
* @covers Guzzle\Http\Message\Request::processResponse
* @expectedException Guzzle\Http\Exception\RequestException
* @expectedExceptionMessage Error completing request
*/
public function testRequestThrowsExceptionWhenSetToCompleteWithNoResponse()
{
$this->request->setState(RequestInterface::STATE_COMPLETE);
}
/**
* @covers Guzzle\Http\Message\Request::__clone
*/
public function testClonedRequestsUseNewInternalState()
{
$p = new ExponentialBackoffPlugin();
$this->request->getEventDispatcher()->addSubscriber($p);
$h = $this->request->getHeader('Host');
$r = clone $this->request;
$this->assertEquals(RequestInterface::STATE_NEW, $r->getState());
$this->assertNotSame($r->getQuery(), $this->request->getQuery());
$this->assertNotSame($r->getCurlOptions(), $this->request->getCurlOptions());
$this->assertNotSame($r->getEventDispatcher(), $this->request->getEventDispatcher());
$this->assertEquals($r->getHeaders(), $this->request->getHeaders());
$this->assertNotSame($h, $r->getHeader('Host'));
$this->assertNotSame($r->getParams(), $this->request->getParams());
$this->assertNull($r->getParams()->get('queued_response'));
$this->assertTrue($this->request->getEventDispatcher()->hasListeners('request.sent'));
}
/**
* @covers Guzzle\Http\Message\Request::changedHeader
* @covers Guzzle\Http\Message\Request::setHeader
*/
public function testCatchesAllHostHeaderChanges()
{
// Tests setting using headers
$this->request->setHeader('Host', 'www.abc.com');
$this->assertEquals('www.abc.com', $this->request->getHost());
$this->assertEquals('www.abc.com:8124', $this->request->getHeader('Host'));
$this->assertEquals(8124, $this->request->getPort());
// Tests setting using setHost()
$this->request->setHost('abc.com');
$this->assertEquals('abc.com', $this->request->getHost());
$this->assertEquals('abc.com:8124', $this->request->getHeader('Host'));
$this->assertEquals(8124, $this->request->getPort());
// Tests setting with a port
$this->request->setHost('abc.com:8081');
$this->assertEquals('abc.com', $this->request->getHost());
$this->assertEquals('abc.com:8081', $this->request->getHeader('Host'));
$this->assertEquals(8081, $this->request->getPort());
// Tests setting with a port using the Host header
$this->request->setHeader('Host', 'solr.com:8983');
$this->assertEquals('solr.com', $this->request->getHost());
$this->assertEquals('solr.com:8983', (string) $this->request->getHeader('Host'));
$this->assertEquals(8983, $this->request->getPort());
// Tests setting with an inferred 443 port using the Host header
$this->request->setScheme('https');
$this->request->setHeader('Host', 'solr.com');
$this->assertEquals('solr.com', $this->request->getHost());
$this->assertEquals('solr.com:8983', (string) $this->request->getHeader('Host'));
$this->assertEquals(8983, $this->request->getPort());
}
/**
* @covers Guzzle\Http\Message\Request::setUrl
*/
public function testRecognizesBasicAuthCredentialsInUrls()
{
$this->request->setUrl('http://michael:test@test.com/');
$this->assertEquals('michael', $this->request->getUsername());
$this->assertEquals('test', $this->request->getPassword());
}
/**
* This test launches a dummy Guzzle\Http\Server\Server object that listens
* for incoming requests. The server allows us to test how cURL sends
* requests and receives responses. We can validate the request structure
* and whether or not the response was interpreted correctly.
*
* @covers Guzzle\Http\Message\Request
*/
public function testRequestCanBeSentUsingCurl()
{
$this->getServer()->flush();
$this->getServer()->enqueue(array(
"HTTP/1.1 200 OK\r\nContent-Length: 4\r\nExpires: Thu, 01 Dec 1994 16:00:00 GMT\r\nConnection: close\r\n\r\ndata",
"HTTP/1.1 200 OK\r\nContent-Length: 4\r\nExpires: Thu, 01 Dec 1994 16:00:00 GMT\r\nConnection: close\r\n\r\ndata",
"HTTP/1.1 404 Not Found\r\nContent-Encoding: application/xml\r\nContent-Length: 48\r\n\r\n