Maj Library

This commit is contained in:
EoleDev 2016-03-23 15:30:47 +01:00
parent 0dc17aa9ef
commit 54ec6723de
72 changed files with 525 additions and 455 deletions

3
server/composer.json Normal file → Executable file
View file

@ -1,6 +1,5 @@
{ {
"require": { "require": {
"php-opencloud/openstack": "dev-master", "php-opencloud/openstack": "dev-master"
"php-opencloud/common": "dev-master"
} }
} }

48
server/composer.lock generated
View file

@ -4,21 +4,21 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"hash": "7647ed348aee68f2db6b71e4d2fb1fe7", "hash": "e7cbd5d3df36fb1a3f3378b837068196",
"content-hash": "82731500d050a65f09e92b70c1f96ea9", "content-hash": "125e4702f7a417475a4150c889ac6c3d",
"packages": [ "packages": [
{ {
"name": "guzzlehttp/guzzle", "name": "guzzlehttp/guzzle",
"version": "6.1.1", "version": "6.2.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/guzzle/guzzle.git", "url": "https://github.com/guzzle/guzzle.git",
"reference": "c6851d6e48f63b69357cbfa55bca116448140e0c" "reference": "d094e337976dff9d8e2424e8485872194e768662"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/c6851d6e48f63b69357cbfa55bca116448140e0c", "url": "https://api.github.com/repos/guzzle/guzzle/zipball/d094e337976dff9d8e2424e8485872194e768662",
"reference": "c6851d6e48f63b69357cbfa55bca116448140e0c", "reference": "d094e337976dff9d8e2424e8485872194e768662",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -34,7 +34,7 @@
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-master": "6.1-dev" "dev-master": "6.2-dev"
} }
}, },
"autoload": { "autoload": {
@ -67,7 +67,7 @@
"rest", "rest",
"web service" "web service"
], ],
"time": "2015-11-23 00:47:50" "time": "2016-03-21 20:02:09"
}, },
{ {
"name": "guzzlehttp/promises", "name": "guzzlehttp/promises",
@ -246,16 +246,16 @@
}, },
{ {
"name": "php-opencloud/common", "name": "php-opencloud/common",
"version": "dev-master", "version": "v1.0.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/php-opencloud/common.git", "url": "https://github.com/php-opencloud/common.git",
"reference": "fd027b817c3dd8f83b0c8d9fb1df34ebf25f8c62" "reference": "4a4aec0a4f35b471570271dd1a2e52667dee62b8"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/php-opencloud/common/zipball/fd027b817c3dd8f83b0c8d9fb1df34ebf25f8c62", "url": "https://api.github.com/repos/php-opencloud/common/zipball/4a4aec0a4f35b471570271dd1a2e52667dee62b8",
"reference": "fd027b817c3dd8f83b0c8d9fb1df34ebf25f8c62", "reference": "4a4aec0a4f35b471570271dd1a2e52667dee62b8",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -287,7 +287,7 @@
"homepage": "https://github.com/jamiehannaford" "homepage": "https://github.com/jamiehannaford"
} }
], ],
"time": "2016-03-08 12:56:34" "time": "2016-03-18 13:45:42"
}, },
{ {
"name": "php-opencloud/openstack", "name": "php-opencloud/openstack",
@ -295,25 +295,16 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/php-opencloud/openstack.git", "url": "https://github.com/php-opencloud/openstack.git",
"reference": "f2ee77024843659d970817a9e7055bb40a3724f9" "reference": "61626420361a1dab3ed6f9455e1057bda18cc335"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
<<<<<<< HEAD "url": "https://api.github.com/repos/php-opencloud/openstack/zipball/61626420361a1dab3ed6f9455e1057bda18cc335",
<<<<<<< Updated upstream "reference": "61626420361a1dab3ed6f9455e1057bda18cc335",
"url": "https://api.github.com/repos/php-opencloud/openstack/zipball/15aca73f423166c7ef8337ba08615c103c66e931",
=======
"url": "https://api.github.com/repos/php-opencloud/openstack/zipball/f2ee77024843659d970817a9e7055bb40a3724f9",
>>>>>>> develop
"reference": "15aca73f423166c7ef8337ba08615c103c66e931",
=======
"url": "https://api.github.com/repos/php-opencloud/openstack/zipball/f2ee77024843659d970817a9e7055bb40a3724f9",
"reference": "f2ee77024843659d970817a9e7055bb40a3724f9",
>>>>>>> Stashed changes
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php-opencloud/common": "dev-master" "php-opencloud/common": "~1.0"
}, },
"require-dev": { "require-dev": {
"fabpot/php-cs-fixer": "~1.0", "fabpot/php-cs-fixer": "~1.0",
@ -337,7 +328,7 @@
"homepage": "https://github.com/jamiehannaford" "homepage": "https://github.com/jamiehannaford"
} }
], ],
"time": "2016-03-08 14:37:14" "time": "2016-03-20 10:57:06"
}, },
{ {
"name": "psr/http-message", "name": "psr/http-message",
@ -393,8 +384,7 @@
"aliases": [], "aliases": [],
"minimum-stability": "stable", "minimum-stability": "stable",
"stability-flags": { "stability-flags": {
"php-opencloud/openstack": 20, "php-opencloud/openstack": 20
"php-opencloud/common": 20
}, },
"prefer-stable": false, "prefer-stable": false,
"prefer-lowest": false, "prefer-lowest": false,

View file

@ -50,70 +50,6 @@
"response" "response"
] ]
}, },
{
"name": "guzzlehttp/guzzle",
"version": "6.1.1",
"version_normalized": "6.1.1.0",
"source": {
"type": "git",
"url": "https://github.com/guzzle/guzzle.git",
"reference": "c6851d6e48f63b69357cbfa55bca116448140e0c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/c6851d6e48f63b69357cbfa55bca116448140e0c",
"reference": "c6851d6e48f63b69357cbfa55bca116448140e0c",
"shasum": ""
},
"require": {
"guzzlehttp/promises": "~1.0",
"guzzlehttp/psr7": "~1.1",
"php": ">=5.5.0"
},
"require-dev": {
"ext-curl": "*",
"phpunit/phpunit": "~4.0",
"psr/log": "~1.0"
},
"time": "2015-11-23 00:47:50",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "6.1-dev"
}
},
"installation-source": "dist",
"autoload": {
"files": [
"src/functions_include.php"
],
"psr-4": {
"GuzzleHttp\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
}
],
"description": "Guzzle is a PHP HTTP client library",
"homepage": "http://guzzlephp.org/",
"keywords": [
"client",
"curl",
"framework",
"http",
"http client",
"rest",
"web service"
]
},
{ {
"name": "justinrainbow/json-schema", "name": "justinrainbow/json-schema",
"version": "1.6.1", "version": "1.6.1",
@ -182,53 +118,6 @@
"schema" "schema"
] ]
}, },
{
"name": "php-opencloud/common",
"version": "dev-master",
"version_normalized": "9999999-dev",
"source": {
"type": "git",
"url": "https://github.com/php-opencloud/common.git",
"reference": "fd027b817c3dd8f83b0c8d9fb1df34ebf25f8c62"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-opencloud/common/zipball/fd027b817c3dd8f83b0c8d9fb1df34ebf25f8c62",
"reference": "fd027b817c3dd8f83b0c8d9fb1df34ebf25f8c62",
"shasum": ""
},
"require": {
"guzzlehttp/guzzle": "~6.1",
"justinrainbow/json-schema": "~1.3",
"php": "~7.0"
},
"require-dev": {
"fabpot/php-cs-fixer": "~1.0",
"jakub-onderka/php-parallel-lint": "0.*",
"phpunit/phpunit": "~4.0",
"psr/log": "~1.0",
"sami/sami": "dev-master",
"satooshi/php-coveralls": "~1.0"
},
"time": "2016-03-08 12:56:34",
"type": "library",
"installation-source": "source",
"autoload": {
"psr-4": {
"OpenCloud\\": "src/",
"OpenCloud\\Test\\": "tests/unit/",
"OpenCloud\\Integration\\": "tests/integration/"
}
},
"notification-url": "https://packagist.org/downloads/",
"authors": [
{
"name": "Jamie Hannaford",
"email": "jamie.hannaford@rackspace.com",
"homepage": "https://github.com/jamiehannaford"
}
]
},
{ {
"name": "guzzlehttp/promises", "name": "guzzlehttp/promises",
"version": "1.1.0", "version": "1.1.0",
@ -343,22 +232,88 @@
] ]
}, },
{ {
"name": "php-opencloud/openstack", "name": "guzzlehttp/guzzle",
"version": "dev-master", "version": "6.2.0",
"version_normalized": "9999999-dev", "version_normalized": "6.2.0.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/php-opencloud/openstack.git", "url": "https://github.com/guzzle/guzzle.git",
"reference": "f2ee77024843659d970817a9e7055bb40a3724f9" "reference": "d094e337976dff9d8e2424e8485872194e768662"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/php-opencloud/openstack/zipball/f2ee77024843659d970817a9e7055bb40a3724f9", "url": "https://api.github.com/repos/guzzle/guzzle/zipball/d094e337976dff9d8e2424e8485872194e768662",
"reference": "f2ee77024843659d970817a9e7055bb40a3724f9", "reference": "d094e337976dff9d8e2424e8485872194e768662",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php-opencloud/common": "dev-master" "guzzlehttp/promises": "~1.0",
"guzzlehttp/psr7": "~1.1",
"php": ">=5.5.0"
},
"require-dev": {
"ext-curl": "*",
"phpunit/phpunit": "~4.0",
"psr/log": "~1.0"
},
"time": "2016-03-21 20:02:09",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "6.2-dev"
}
},
"installation-source": "dist",
"autoload": {
"files": [
"src/functions_include.php"
],
"psr-4": {
"GuzzleHttp\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
}
],
"description": "Guzzle is a PHP HTTP client library",
"homepage": "http://guzzlephp.org/",
"keywords": [
"client",
"curl",
"framework",
"http",
"http client",
"rest",
"web service"
]
},
{
"name": "php-opencloud/common",
"version": "v1.0.2",
"version_normalized": "1.0.2.0",
"source": {
"type": "git",
"url": "https://github.com/php-opencloud/common.git",
"reference": "4a4aec0a4f35b471570271dd1a2e52667dee62b8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-opencloud/common/zipball/4a4aec0a4f35b471570271dd1a2e52667dee62b8",
"reference": "4a4aec0a4f35b471570271dd1a2e52667dee62b8",
"shasum": ""
},
"require": {
"guzzlehttp/guzzle": "~6.1",
"justinrainbow/json-schema": "~1.3",
"php": "~7.0"
}, },
"require-dev": { "require-dev": {
"fabpot/php-cs-fixer": "~1.0", "fabpot/php-cs-fixer": "~1.0",
@ -368,7 +323,52 @@
"sami/sami": "dev-master", "sami/sami": "dev-master",
"satooshi/php-coveralls": "~1.0" "satooshi/php-coveralls": "~1.0"
}, },
"time": "2016-03-08 14:37:14", "time": "2016-03-18 13:45:42",
"type": "library",
"installation-source": "source",
"autoload": {
"psr-4": {
"OpenCloud\\": "src/",
"OpenCloud\\Test\\": "tests/unit/",
"OpenCloud\\Integration\\": "tests/integration/"
}
},
"notification-url": "https://packagist.org/downloads/",
"authors": [
{
"name": "Jamie Hannaford",
"email": "jamie.hannaford@rackspace.com",
"homepage": "https://github.com/jamiehannaford"
}
]
},
{
"name": "php-opencloud/openstack",
"version": "dev-master",
"version_normalized": "9999999-dev",
"source": {
"type": "git",
"url": "https://github.com/php-opencloud/openstack.git",
"reference": "61626420361a1dab3ed6f9455e1057bda18cc335"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-opencloud/openstack/zipball/61626420361a1dab3ed6f9455e1057bda18cc335",
"reference": "61626420361a1dab3ed6f9455e1057bda18cc335",
"shasum": ""
},
"require": {
"php-opencloud/common": "~1.0"
},
"require-dev": {
"fabpot/php-cs-fixer": "~1.0",
"jakub-onderka/php-parallel-lint": "0.*",
"phpunit/phpunit": "~4.0",
"psr/log": "~1.0",
"sami/sami": "dev-master",
"satooshi/php-coveralls": "~1.0"
},
"time": "2016-03-20 10:57:06",
"type": "library", "type": "library",
"installation-source": "source", "installation-source": "source",
"autoload": { "autoload": {

View file

@ -14,16 +14,17 @@ before_script:
- composer install --no-interaction --prefer-source --dev - composer install --no-interaction --prefer-source --dev
- ~/.nvm/nvm.sh install v0.6.14 - ~/.nvm/nvm.sh install v0.6.14
- ~/.nvm/nvm.sh run v0.6.14 - ~/.nvm/nvm.sh run v0.6.14
- '[ "$TRAVIS_PHP_VERSION" != "7.0" ] || echo "xdebug.overload_var_dump = 1" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini'
script: make test script: make test
matrix: matrix:
allow_failures: allow_failures:
- php: hhvm - php: hhvm
- php: 7.0
fast_finish: true fast_finish: true
before_deploy: before_deploy:
- rvm 1.9.3 do gem install mime-types -v 2.6.2
- make package - make package
deploy: deploy:

View file

@ -1,5 +1,24 @@
# CHANGELOG # CHANGELOG
## 6.2.0 - 2016-03-21
* Feature: added `GuzzleHttp\json_encode` and `GuzzleHttp\json_decode`.
https://github.com/guzzle/guzzle/pull/1389
* Bug fix: Fix sleep calculation when waiting for delayed requests.
https://github.com/guzzle/guzzle/pull/1324
* Feature: More flexible history containers.
https://github.com/guzzle/guzzle/pull/1373
* Bug fix: defer sink stream opening in StreamHandler.
https://github.com/guzzle/guzzle/pull/1377
* Bug fix: do not attempt to escape cookie values.
https://github.com/guzzle/guzzle/pull/1406
* Feature: report original content encoding and length on decoded responses.
https://github.com/guzzle/guzzle/pull/1409
* Bug fix: rewind seekable request bodies before dispatching to cURL.
https://github.com/guzzle/guzzle/pull/1422
* Bug fix: provide an empty string to `http_build_query` for HHVM workaround.
https://github.com/guzzle/guzzle/pull/1367
## 6.1.1 - 2015-11-22 ## 6.1.1 - 2015-11-22
* Bug fix: Proxy::wrapSync() now correctly proxies to the appropriate handler * Bug fix: Proxy::wrapSync() now correctly proxies to the appropriate handler

View file

@ -1,4 +1,4 @@
Copyright (c) 2011-2015 Michael Dowling, https://github.com/mtdowling <mtdowling@gmail.com> Copyright (c) 2011-2016 Michael Dowling, https://github.com/mtdowling <mtdowling@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

View file

@ -24,7 +24,7 @@ $res = $client->request('GET', 'https://api.github.com/user', [
]); ]);
echo $res->getStatusCode(); echo $res->getStatusCode();
// 200 // 200
echo $res->getHeader('content-type'); echo $res->getHeaderLine('content-type');
// 'application/json; charset=utf8' // 'application/json; charset=utf8'
echo $res->getBody(); echo $res->getBody();
// {"type":"User"...' // {"type":"User"...'

View file

@ -35,7 +35,7 @@
}, },
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-master": "6.1-dev" "dev-master": "6.2-dev"
} }
} }
} }

View file

@ -93,7 +93,7 @@ class Client implements ClientInterface
$options = $this->prepareDefaults($options); $options = $this->prepareDefaults($options);
return $this->transfer( return $this->transfer(
$request->withUri($this->buildUri($request->getUri(), $options)), $request->withUri($this->buildUri($request->getUri(), $options), $request->hasHeader('Host')),
$options $options
); );
} }
@ -173,7 +173,7 @@ class Client implements ClientInterface
$cleanedNoProxy = str_replace(' ', '', $noProxy); $cleanedNoProxy = str_replace(' ', '', $noProxy);
$defaults['proxy']['no'] = explode(',', $cleanedNoProxy); $defaults['proxy']['no'] = explode(',', $cleanedNoProxy);
} }
$this->config = $config + $defaults; $this->config = $config + $defaults;
if (!empty($config['cookies']) && $config['cookies'] === true) { if (!empty($config['cookies']) && $config['cookies'] === true) {
@ -291,7 +291,7 @@ class Client implements ClientInterface
. 'x-www-form-urlencoded requests, and the multipart ' . 'x-www-form-urlencoded requests, and the multipart '
. 'option to send multipart/form-data requests.'); . 'option to send multipart/form-data requests.');
} }
$options['body'] = http_build_query($options['form_params'], null, '&'); $options['body'] = http_build_query($options['form_params'], '', '&');
unset($options['form_params']); unset($options['form_params']);
$options['_conditional']['Content-Type'] = 'application/x-www-form-urlencoded'; $options['_conditional']['Content-Type'] = 'application/x-www-form-urlencoded';
} }
@ -357,7 +357,8 @@ class Client implements ClientInterface
} }
if (isset($options['json'])) { if (isset($options['json'])) {
$modify['body'] = Psr7\stream_for(json_encode($options['json'])); $jsonStr = \GuzzleHttp\json_encode($options['json']);
$modify['body'] = Psr7\stream_for($jsonStr);
$options['_conditional']['Content-Type'] = 'application/json'; $options['_conditional']['Content-Type'] = 'application/json';
unset($options['json']); unset($options['json']);
} }

View file

@ -12,7 +12,7 @@ use Psr\Http\Message\UriInterface;
*/ */
interface ClientInterface interface ClientInterface
{ {
const VERSION = '6.1.1'; const VERSION = '6.2.0';
/** /**
* Send an HTTP request. * Send an HTTP request.
@ -44,14 +44,14 @@ interface ClientInterface
* relative path to append to the base path of the client. The URL can * relative path to append to the base path of the client. The URL can
* contain the query string as well. * contain the query string as well.
* *
* @param string $method HTTP method * @param string $method HTTP method.
* @param string|UriInterface $uri URI object or string. * @param string|UriInterface|null $uri URI object or string (default null).
* @param array $options Request options to apply. * @param array $options Request options to apply.
* *
* @return ResponseInterface * @return ResponseInterface
* @throws GuzzleException * @throws GuzzleException
*/ */
public function request($method, $uri, array $options = []); public function request($method, $uri = null, array $options = []);
/** /**
* Create and send an asynchronous HTTP request. * Create and send an asynchronous HTTP request.

View file

@ -5,7 +5,7 @@ use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
/** /**
* Cookie jar that stores cookies an an array * Cookie jar that stores cookies as an array
*/ */
class CookieJar implements CookieJarInterface class CookieJar implements CookieJarInterface
{ {
@ -58,22 +58,10 @@ class CookieJar implements CookieJarInterface
} }
/** /**
* Quote the cookie value if it is not already quoted and it contains * @deprecated
* problematic characters.
*
* @param string $value Value that may or may not need to be quoted
*
* @return string
*/ */
public static function getCookieValue($value) public static function getCookieValue($value)
{ {
if (substr($value, 0, 1) !== '"' &&
substr($value, -1, 1) !== '"' &&
strpbrk($value, ';,=')
) {
$value = '"' . $value . '"';
}
return $value; return $value;
} }
@ -248,7 +236,7 @@ class CookieJar implements CookieJarInterface
(!$cookie->getSecure() || $scheme == 'https') (!$cookie->getSecure() || $scheme == 'https')
) { ) {
$values[] = $cookie->getName() . '=' $values[] = $cookie->getName() . '='
. self::getCookieValue($cookie->getValue()); . $cookie->getValue();
} }
} }

View file

@ -11,7 +11,7 @@ class FileCookieJar extends CookieJar
/** @var bool Control whether to persist session cookies or not. */ /** @var bool Control whether to persist session cookies or not. */
private $storeSessionCookies; private $storeSessionCookies;
/** /**
* Create a new FileCookieJar object * Create a new FileCookieJar object
* *
@ -55,7 +55,8 @@ class FileCookieJar extends CookieJar
} }
} }
if (false === file_put_contents($filename, json_encode($json))) { $jsonStr = \GuzzleHttp\json_encode($json);
if (false === file_put_contents($filename, $jsonStr)) {
throw new \RuntimeException("Unable to save file {$filename}"); throw new \RuntimeException("Unable to save file {$filename}");
} }
} }
@ -73,9 +74,11 @@ class FileCookieJar extends CookieJar
$json = file_get_contents($filename); $json = file_get_contents($filename);
if (false === $json) { if (false === $json) {
throw new \RuntimeException("Unable to load file {$filename}"); throw new \RuntimeException("Unable to load file {$filename}");
} elseif ($json === '') {
return;
} }
$data = json_decode($json, true); $data = \GuzzleHttp\json_decode($json, true);
if (is_array($data)) { if (is_array($data)) {
foreach (json_decode($json, true) as $cookie) { foreach (json_decode($json, true) as $cookie) {
$this->setCookie(new SetCookie($cookie)); $this->setCookie(new SetCookie($cookie));

View file

@ -265,6 +265,9 @@ class CurlFactory implements CurlFactoryInterface
$this->removeHeader('Content-Length', $conf); $this->removeHeader('Content-Length', $conf);
} }
$body = $request->getBody(); $body = $request->getBody();
if ($body->isSeekable()) {
$body->rewind();
}
$conf[CURLOPT_READFUNCTION] = function ($ch, $fd, $length) use ($body) { $conf[CURLOPT_READFUNCTION] = function ($ch, $fd, $length) use ($body) {
return $body->read($length); return $body->read($length);
}; };

View file

@ -192,6 +192,6 @@ class CurlMultiHandler
} }
} }
return max(0, $currentTime - $nextTime); return max(0, $nextTime - $currentTime) * 1000000;
} }
} }

View file

@ -56,8 +56,13 @@ final class EasyHandle
if (!empty($this->options['decode_content']) if (!empty($this->options['decode_content'])
&& isset($normalizedKeys['content-encoding']) && isset($normalizedKeys['content-encoding'])
) { ) {
$headers['x-encoded-content-encoding']
= $headers[$normalizedKeys['content-encoding']];
unset($headers[$normalizedKeys['content-encoding']]); unset($headers[$normalizedKeys['content-encoding']]);
if (isset($normalizedKeys['content-length'])) { if (isset($normalizedKeys['content-length'])) {
$headers['x-encoded-content-length']
= $headers[$normalizedKeys['content-length']];
$bodyLength = (int) $this->sink->getSize(); $bodyLength = (int) $this->sink->getSize();
if ($bodyLength) { if ($bodyLength) {
$headers[$normalizedKeys['content-length']] = $bodyLength; $headers[$normalizedKeys['content-length']] = $bodyLength;

View file

@ -74,7 +74,7 @@ class MockHandler implements \Countable
$response = array_shift($this->queue); $response = array_shift($this->queue);
if (is_callable($response)) { if (is_callable($response)) {
$response = $response($request, $options); $response = call_user_func($response, $request, $options);
} }
$response = $response instanceof \Exception $response = $response instanceof \Exception

View file

@ -138,7 +138,7 @@ class StreamHandler
: fopen('php://temp', 'r+'); : fopen('php://temp', 'r+');
return is_string($sink) return is_string($sink)
? new Psr7\Stream(Psr7\try_fopen($sink, 'r+')) ? new Psr7\LazyOpenStream($sink, 'w+')
: Psr7\stream_for($sink); : Psr7\stream_for($sink);
} }
@ -153,10 +153,15 @@ class StreamHandler
$stream = new Psr7\InflateStream( $stream = new Psr7\InflateStream(
Psr7\stream_for($stream) Psr7\stream_for($stream)
); );
$headers['x-encoded-content-encoding']
= $headers[$normalizedKeys['content-encoding']];
// Remove content-encoding header // Remove content-encoding header
unset($headers[$normalizedKeys['content-encoding']]); unset($headers[$normalizedKeys['content-encoding']]);
// Fix content-length header // Fix content-length header
if (isset($normalizedKeys['content-length'])) { if (isset($normalizedKeys['content-length'])) {
$headers['x-encoded-content-length']
= $headers[$normalizedKeys['content-length']];
$length = (int) $stream->getSize(); $length = (int) $stream->getSize();
if ($length == 0) { if ($length == 0) {
unset($headers[$normalizedKeys['content-length']]); unset($headers[$normalizedKeys['content-length']]);

View file

@ -75,9 +75,14 @@ final class Middleware
* @param array $container Container to hold the history (by reference). * @param array $container Container to hold the history (by reference).
* *
* @return callable Returns a function that accepts the next handler. * @return callable Returns a function that accepts the next handler.
* @throws \InvalidArgumentException if container is not an array or ArrayAccess.
*/ */
public static function history(array &$container) public static function history(&$container)
{ {
if (!is_array($container) && !$container instanceof \ArrayAccess) {
throw new \InvalidArgumentException('history container must be an array or object implementing ArrayAccess');
}
return function (callable $handler) use (&$container) { return function (callable $handler) use (&$container) {
return function ($request, array $options) use ($handler, &$container) { return function ($request, array $options) use ($handler, &$container) {
return $handler($request, $options)->then( return $handler($request, $options)->then(

View file

@ -282,3 +282,49 @@ function is_host_in_noproxy($host, array $noProxyArray)
return false; return false;
} }
/**
* Wrapper for json_decode that throws when an error occurs.
*
* @param string $json JSON data to parse
* @param bool $assoc When true, returned objects will be converted
* into associative arrays.
* @param int $depth User specified recursion depth.
* @param int $options Bitmask of JSON decode options.
*
* @return mixed
* @throws \InvalidArgumentException if the JSON cannot be decoded.
* @link http://www.php.net/manual/en/function.json-decode.php
*/
function json_decode($json, $assoc = false, $depth = 512, $options = 0)
{
$data = \json_decode($json, $assoc, $depth, $options);
if (JSON_ERROR_NONE !== json_last_error()) {
throw new \InvalidArgumentException(
'json_decode error: ' . json_last_error_msg());
}
return $data;
}
/**
* Wrapper for JSON encoding that throws when an error occurs.
*
* @param string $value The value being encoded
* @param int $options JSON encode option bitmask
* @param int $depth Set the maximum depth. Must be greater than zero.
*
* @return string
* @throws \InvalidArgumentException if the JSON cannot be encoded.
* @link http://www.php.net/manual/en/function.json-encode.php
*/
function json_encode($value, $options = 0, $depth = 512)
{
$json = \json_encode($value, $options, $depth);
if (JSON_ERROR_NONE !== json_last_error()) {
throw new \InvalidArgumentException(
'json_encode error: ' . json_last_error_msg());
}
return $json;
}

View file

@ -0,0 +1,30 @@
language: php
sudo: false
cache:
directories:
- $HOME/.composer/cache
matrix:
include:
- php: 7.0
- php: nightly
allow_failures:
- php: nightly
fast_finish: true
before_install:
- composer self-update
before_script:
- composer install --prefer-source
- vendor/bin/parallel-lint --exclude vendor .
- vendor/bin/php-cs-fixer fix --dry-run --diff --level psr2 .
after_script:
- php vendor/bin/coveralls -v
notifications:
email:
- jamie.hannaford@rackspace.com

View file

@ -1,4 +1,4 @@
<?php <?php declare(strict_types = 1);
namespace OpenCloud\Common\Api; namespace OpenCloud\Common\Api;
@ -6,27 +6,27 @@ abstract class AbstractApi implements ApiInterface
{ {
protected $params; protected $params;
protected function isRequired(array $param) protected function isRequired(array $param): array
{ {
return array_merge($param, ['required' => true]); return array_merge($param, ['required' => true]);
} }
protected function notRequired(array $param) protected function notRequired(array $param): array
{ {
return array_merge($param, ['required' => false]); return array_merge($param, ['required' => false]);
} }
protected function query(array $param) protected function query(array $param): array
{ {
return array_merge($param, ['location' => AbstractParams::QUERY]); return array_merge($param, ['location' => AbstractParams::QUERY]);
} }
protected function url(array $param) protected function url(array $param): array
{ {
return array_merge($param, ['location' => AbstractParams::URL]); return array_merge($param, ['location' => AbstractParams::URL]);
} }
public function documented(array $param) public function documented(array $param): array
{ {
return array_merge($param, ['required' => true]); return array_merge($param, ['required' => true]);
} }

View file

@ -1,4 +1,4 @@
<?php <?php declare(strict_types=1);
namespace OpenCloud\Common\Api; namespace OpenCloud\Common\Api;
@ -21,12 +21,12 @@ abstract class AbstractParams
const INT_TYPE = 'integer'; const INT_TYPE = 'integer';
const INTEGER_TYPE = self::INT_TYPE; const INTEGER_TYPE = self::INT_TYPE;
public static function isSupportedLocation($val) public static function isSupportedLocation(string $val): bool
{ {
return in_array($val, [self::QUERY, self::HEADER, self::URL, self::JSON, self::RAW]); return in_array($val, [self::QUERY, self::HEADER, self::URL, self::JSON, self::RAW]);
} }
public function limit() public function limit(): array
{ {
return [ return [
'type' => self::INT_TYPE, 'type' => self::INT_TYPE,
@ -38,7 +38,7 @@ DESC
]; ];
} }
public function marker() public function marker(): array
{ {
return [ return [
'type' => 'string', 'type' => 'string',
@ -51,7 +51,7 @@ DESC
]; ];
} }
public function id($type) public function id(string $type): array
{ {
return [ return [
'description' => sprintf("The unique ID, or identifier, for the %s", $type), 'description' => sprintf("The unique ID, or identifier, for the %s", $type),
@ -60,7 +60,7 @@ DESC
]; ];
} }
public function idPath() public function idPath(): array
{ {
return [ return [
'type' => self::STRING_TYPE, 'type' => self::STRING_TYPE,
@ -69,7 +69,7 @@ DESC
]; ];
} }
public function name($resource) public function name(string $resource): array
{ {
return [ return [
'description' => sprintf("The name of the %s", $resource), 'description' => sprintf("The name of the %s", $resource),
@ -79,7 +79,7 @@ DESC
} }
public function sortDir() public function sortDir(): array
{ {
return [ return [
'type' => self::STRING_TYPE, 'type' => self::STRING_TYPE,
@ -89,7 +89,7 @@ DESC
]; ];
} }
public function sortKey() public function sortKey(): array
{ {
return [ return [
'type' => self::STRING_TYPE, 'type' => self::STRING_TYPE,
@ -97,4 +97,4 @@ DESC
'description' => "Sorts by one or more sets of attribute and sort direction combinations.", 'description' => "Sorts by one or more sets of attribute and sort direction combinations.",
]; ];
} }
} }

View file

@ -1,4 +1,4 @@
<?php <?php declare(strict_types=1);
namespace OpenCloud\Common\Api; namespace OpenCloud\Common\Api;

View file

@ -1,9 +1,7 @@
<?php <?php declare(strict_types=1);
namespace OpenCloud\Common\Api; namespace OpenCloud\Common\Api;
use GuzzleHttp\Utils;
/** /**
* This class represents an OpenCloud API operation. It encapsulates most aspects of the REST operation: its HTTP * This class represents an OpenCloud API operation. It encapsulates most aspects of the REST operation: its HTTP
* method, the URL path, its top-level JSON key, and all of its {@see Parameter} objects. * method, the URL path, its top-level JSON key, and all of its {@see Parameter} objects.
@ -49,7 +47,7 @@ class Operation
/** /**
* @return string * @return string
*/ */
public function getPath() public function getPath(): string
{ {
return $this->path; return $this->path;
} }
@ -57,7 +55,7 @@ class Operation
/** /**
* @return string * @return string
*/ */
public function getMethod() public function getMethod(): string
{ {
return $this->method; return $this->method;
} }
@ -69,7 +67,7 @@ class Operation
* *
* @return bool * @return bool
*/ */
public function hasParam($key) public function hasParam(string $key): bool
{ {
return isset($this->params[$key]); return isset($this->params[$key]);
} }
@ -79,7 +77,7 @@ class Operation
* *
* @return Parameter * @return Parameter
*/ */
public function getParam($name) public function getParam(string $name)
{ {
return isset($this->params[$name]) ? $this->params[$name] : null; return isset($this->params[$name]) ? $this->params[$name] : null;
} }
@ -87,9 +85,9 @@ class Operation
/** /**
* @return string * @return string
*/ */
public function getJsonKey() public function getJsonKey(): string
{ {
return $this->jsonKey; return $this->jsonKey ?: '';
} }
/** /**
@ -100,7 +98,7 @@ class Operation
* *
* @return array * @return array
*/ */
public static function toParamArray(array $data) public static function toParamArray(array $data): array
{ {
$params = []; $params = [];
@ -121,7 +119,7 @@ class Operation
* @return bool TRUE if validation passes * @return bool TRUE if validation passes
* @throws \Exception If validate fails * @throws \Exception If validate fails
*/ */
public function validate(array $userValues) public function validate(array $userValues): bool
{ {
foreach ($this->params as $paramName => $param) { foreach ($this->params as $paramName => $param) {
if (array_key_exists($paramName, $userValues)) { if (array_key_exists($paramName, $userValues)) {
@ -133,4 +131,4 @@ class Operation
return true; return true;
} }
} }

View file

@ -1,7 +1,9 @@
<?php <?php declare(strict_types=1);
namespace OpenCloud\Common\Api; namespace OpenCloud\Common\Api;
use GuzzleHttp\Promise\PromiseInterface;
use GuzzleHttp\Psr7\Uri;
use function GuzzleHttp\uri_template; use function GuzzleHttp\uri_template;
use GuzzleHttp\ClientInterface; use GuzzleHttp\ClientInterface;
use GuzzleHttp\Promise\Promise; use GuzzleHttp\Promise\Promise;
@ -60,12 +62,12 @@ abstract class Operator implements OperatorInterface
* *
* @return Operation * @return Operation
*/ */
public function getOperation(array $definition) public function getOperation(array $definition): Operation
{ {
return new Operation($definition); return new Operation($definition);
} }
protected function sendRequest(Operation $operation, array $userValues = [], $async = false) protected function sendRequest(Operation $operation, array $userValues = [], bool $async = false)
{ {
$operation->validate($userValues); $operation->validate($userValues);
@ -79,7 +81,7 @@ abstract class Operator implements OperatorInterface
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public function execute(array $definition, array $userValues = []) public function execute(array $definition, array $userValues = []): ResponseInterface
{ {
return $this->sendRequest($this->getOperation($definition), $userValues); return $this->sendRequest($this->getOperation($definition), $userValues);
} }
@ -87,7 +89,7 @@ abstract class Operator implements OperatorInterface
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public function executeAsync(array $definition, array $userValues = []) public function executeAsync(array $definition, array $userValues = []): PromiseInterface
{ {
return $this->sendRequest($this->getOperation($definition), $userValues, true); return $this->sendRequest($this->getOperation($definition), $userValues, true);
} }
@ -95,7 +97,7 @@ abstract class Operator implements OperatorInterface
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public function model($class, $data = null) public function model(string $class, $data = null): ResourceInterface
{ {
$model = new $class($this->client, $this->api); $model = new $class($this->client, $this->api);
@ -121,13 +123,13 @@ abstract class Operator implements OperatorInterface
* *
* @return static * @return static
*/ */
public function newInstance() public function newInstance(): self
{ {
return new static($this->client, $this->api); return new static($this->client, $this->api);
} }
/** /**
* @return \GuzzleHttp\Psr7\Uri * @return \GuzzleHttp\Psr7\Uri:null
*/ */
protected function getHttpBaseUrl() protected function getHttpBaseUrl()
{ {

View file

@ -1,8 +1,11 @@
<?php <?php declare(strict_types=1);
namespace OpenCloud\Common\Api; namespace OpenCloud\Common\Api;
use GuzzleHttp\ClientInterface; use GuzzleHttp\ClientInterface;
use GuzzleHttp\Promise\PromiseInterface;
use OpenCloud\Common\Resource\ResourceInterface;
use Psr\Http\Message\ResponseInterface;
/** /**
* An operator is any resource or service that can invoke and send REST operations. In other words, it * An operator is any resource or service that can invoke and send REST operations. In other words, it
@ -28,7 +31,7 @@ interface OperatorInterface
* *
* @return \Psr\Http\Message\ResponseInterface * @return \Psr\Http\Message\ResponseInterface
*/ */
public function execute(array $definition, array $userValues = []); public function execute(array $definition, array $userValues = []): ResponseInterface;
/** /**
* A convenience method that assembles an operation and asynchronously sends it to the remote API * A convenience method that assembles an operation and asynchronously sends it to the remote API
@ -38,7 +41,7 @@ interface OperatorInterface
* *
* @return \GuzzleHttp\Promise\PromiseInterface * @return \GuzzleHttp\Promise\PromiseInterface
*/ */
public function executeAsync(array $definition, array $userValues = []); public function executeAsync(array $definition, array $userValues = []): PromiseInterface;
/** /**
* @param string $name The name of the model class. * @param string $name The name of the model class.
@ -47,5 +50,5 @@ interface OperatorInterface
* *
* @return \OpenCloud\Common\Resource\ResourceInterface * @return \OpenCloud\Common\Resource\ResourceInterface
*/ */
public function model($name, $data = null); public function model(string $name, $data = null): ResourceInterface;
} }

View file

@ -1,4 +1,4 @@
<?php <?php declare(strict_types=1);
namespace OpenCloud\Common\Api; namespace OpenCloud\Common\Api;
@ -42,7 +42,7 @@ class Parameter
* *
* @var string * @var string
*/ */
private $name; private $name = '';
/** /**
* The alias for this parameter. Although the user will always interact with the human-friendly $name property, * The alias for this parameter. Although the user will always interact with the human-friendly $name property,
@ -50,7 +50,7 @@ class Parameter
* *
* @var string * @var string
*/ */
private $sentAs; private $sentAs = '';
/** /**
* For array parameters (for example, an array of security group names when creating a server), each array element * For array parameters (for example, an array of security group names when creating a server), each array element
@ -79,7 +79,7 @@ class Parameter
* *
* @var string * @var string
*/ */
private $type; private $type = '';
/** /**
* Indicates whether this parameter requires a value from the user. * Indicates whether this parameter requires a value from the user.
@ -94,7 +94,7 @@ class Parameter
* *
* @var string * @var string
*/ */
private $location; private $location = '';
/** /**
* Relevant to "json" location parameters only. This property allows for deep nesting through the use of * Relevant to "json" location parameters only. This property allows for deep nesting through the use of
@ -102,14 +102,14 @@ class Parameter
* *
* @var string * @var string
*/ */
private $path; private $path = '';
/** /**
* Allows for the prefixing of parameter names. * Allows for the prefixing of parameter names.
* *
* @var string * @var string
*/ */
private $prefix; private $prefix = '';
/** /**
* The enum values for which this param is restricted. * The enum values for which this param is restricted.
@ -151,7 +151,7 @@ class Parameter
private function stockProperties(array $data) private function stockProperties(array $data)
{ {
if (isset($data['properties'])) { if (isset($data['properties'])) {
if (stripos($this->name, 'metadata') !== false) { if ($this->name && stripos($this->name, 'metadata') !== false) {
$this->properties = new Parameter($data['properties']); $this->properties = new Parameter($data['properties']);
} else { } else {
foreach ($data['properties'] as $name => $property) { foreach ($data['properties'] as $name => $property) {
@ -166,7 +166,7 @@ class Parameter
* *
* @return string * @return string
*/ */
public function getName() public function getName(): string
{ {
return $this->sentAs ?: $this->name; return $this->sentAs ?: $this->name;
} }
@ -176,7 +176,7 @@ class Parameter
* *
* @return bool * @return bool
*/ */
public function isRequired() public function isRequired(): bool
{ {
return $this->required === true; return $this->required === true;
} }
@ -189,7 +189,7 @@ class Parameter
* @return bool TRUE if the validation passes * @return bool TRUE if the validation passes
* @throws \Exception If validation fails * @throws \Exception If validation fails
*/ */
public function validate($userValues) public function validate($userValues): bool
{ {
$this->validateEnums($userValues); $this->validateEnums($userValues);
$this->validateType($userValues); $this->validateType($userValues);
@ -245,9 +245,9 @@ class Parameter
* @returns Parameter * @returns Parameter
* @throws \Exception * @throws \Exception
*/ */
private function getNestedProperty($key) private function getNestedProperty($key): Parameter
{ {
if (stripos($this->name, 'metadata') !== false && $this->properties instanceof Parameter) { if ($this->name && stripos($this->name, 'metadata') !== false && $this->properties instanceof Parameter) {
return $this->properties; return $this->properties;
} elseif (isset($this->properties[$key])) { } elseif (isset($this->properties[$key])) {
return $this->properties[$key]; return $this->properties[$key];
@ -264,7 +264,7 @@ class Parameter
* *
* @return bool * @return bool
*/ */
private function hasCorrectType($userValue) private function hasCorrectType($userValue): bool
{ {
// Helper fn to see whether an array is associative (i.e. a JSON object) // Helper fn to see whether an array is associative (i.e. a JSON object)
$isAssociative = function ($value) { $isAssociative = function ($value) {
@ -293,7 +293,7 @@ class Parameter
* *
* @return bool * @return bool
*/ */
public function isArray() public function isArray(): bool
{ {
return $this->type == 'array' && $this->itemSchema instanceof Parameter; return $this->type == 'array' && $this->itemSchema instanceof Parameter;
} }
@ -303,12 +303,12 @@ class Parameter
* *
* @return bool * @return bool
*/ */
public function isObject() public function isObject(): bool
{ {
return $this->type == 'object' && !empty($this->properties); return $this->type == 'object' && !empty($this->properties);
} }
public function getLocation() public function getLocation(): string
{ {
return $this->location; return $this->location;
} }
@ -320,7 +320,7 @@ class Parameter
* *
* @return bool * @return bool
*/ */
public function hasLocation($value) public function hasLocation($value): bool
{ {
return $this->location == $value; return $this->location == $value;
} }
@ -330,7 +330,7 @@ class Parameter
* *
* @return string|null * @return string|null
*/ */
public function getPath() public function getPath(): string
{ {
return $this->path; return $this->path;
} }
@ -338,7 +338,7 @@ class Parameter
/** /**
* Retrieves the common schema that an array parameter applies to all its child elements. * Retrieves the common schema that an array parameter applies to all its child elements.
* *
* @return Parameter * @return Parameter|null
*/ */
public function getItemSchema() public function getItemSchema()
{ {
@ -350,7 +350,7 @@ class Parameter
* *
* @param string $name * @param string $name
*/ */
public function setName($name) public function setName(string $name)
{ {
$this->name = $name; $this->name = $name;
} }
@ -362,7 +362,7 @@ class Parameter
* *
* @return null|Parameter * @return null|Parameter
*/ */
public function getProperty($name) public function getProperty(string $name)
{ {
if ($this->properties instanceof Parameter) { if ($this->properties instanceof Parameter) {
$this->properties->setName($name); $this->properties->setName($name);
@ -377,12 +377,12 @@ class Parameter
* *
* @return string|null * @return string|null
*/ */
public function getPrefix() public function getPrefix(): string
{ {
return $this->prefix; return $this->prefix;
} }
public function getPrefixedName() public function getPrefixedName(): string
{ {
return $this->prefix . $this->getName(); return $this->prefix . $this->getName();
} }

View file

@ -1,4 +1,4 @@
<?php <?php declare(strict_types=1);
namespace OpenCloud\Common; namespace OpenCloud\Common;
@ -38,7 +38,7 @@ trait ArrayAccessTrait
* *
* @return bool * @return bool
*/ */
public function offsetExists($offset) public function offsetExists(string $offset): bool
{ {
return isset($this->internalState[$offset]); return isset($this->internalState[$offset]);
} }
@ -48,7 +48,7 @@ trait ArrayAccessTrait
* *
* @param string $offset * @param string $offset
*/ */
public function offsetUnset($offset) public function offsetUnset(string $offset)
{ {
unset($this->internalState[$offset]); unset($this->internalState[$offset]);
} }
@ -60,7 +60,7 @@ trait ArrayAccessTrait
* *
* @return mixed|null * @return mixed|null
*/ */
public function offsetGet($offset) public function offsetGet(string $offset)
{ {
return $this->offsetExists($offset) ? $this->internalState[$offset] : null; return $this->offsetExists($offset) ? $this->internalState[$offset] : null;
} }

View file

@ -1,4 +1,4 @@
<?php <?php declare(strict_types=1);
namespace OpenCloud\Common\Auth; namespace OpenCloud\Common\Auth;
@ -14,10 +14,13 @@ use Psr\Http\Message\RequestInterface;
*/ */
class AuthHandler class AuthHandler
{ {
/** @var callable */
private $nextHandler; private $nextHandler;
/** @var callable */
private $tokenGenerator; private $tokenGenerator;
/** @var Token */
private $token; private $token;
/** /**
@ -66,7 +69,7 @@ class AuthHandler
* *
* @return bool * @return bool
*/ */
private function shouldIgnore(RequestInterface $request) private function shouldIgnore(RequestInterface $request): bool
{ {
return strpos((string) $request->getUri(), 'tokens') !== false && $request->getMethod() == 'POST'; return strpos((string) $request->getUri(), 'tokens') !== false && $request->getMethod() == 'POST';
} }

View file

@ -1,4 +1,4 @@
<?php <?php declare(strict_types=1);
namespace OpenCloud\Common\Auth; namespace OpenCloud\Common\Auth;
@ -16,5 +16,5 @@ interface Catalog
* *
* @returns string * @returns string
*/ */
public function getServiceUrl($name, $type, $region, $urlType); public function getServiceUrl(string $name, string $type, string $region, string $urlType): string;
} }

View file

@ -1,4 +1,4 @@
<?php <?php declare(strict_types=1);
namespace OpenCloud\Common\Auth; namespace OpenCloud\Common\Auth;
@ -9,5 +9,5 @@ interface IdentityService
* *
* @return array The FIRST key is {@see Token} instance, the SECOND key is a {@see Catalog} instance * @return array The FIRST key is {@see Token} instance, the SECOND key is a {@see Catalog} instance
*/ */
public function authenticate(array $options); public function authenticate(array $options): array;
} }

View file

@ -1,15 +1,15 @@
<?php <?php declare(strict_types=1);
namespace OpenCloud\Common\Auth; namespace OpenCloud\Common\Auth;
interface Token interface Token
{ {
public function getId(); public function getId(): string;
/** /**
* Indicates whether the token has expired or not. * Indicates whether the token has expired or not.
* *
* @return bool TRUE if the token has expired, FALSE if it is still valid * @return bool TRUE if the token has expired, FALSE if it is still valid
*/ */
public function hasExpired(); public function hasExpired(): bool;
} }

View file

@ -1,4 +1,4 @@
<?php <?php declare(strict_types=1);
namespace OpenCloud\Common\Error; namespace OpenCloud\Common\Error;
@ -28,12 +28,12 @@ class BadResponseError extends BaseError
$this->response = $response; $this->response = $response;
} }
public function getRequest() public function getRequest(): RequestInterface
{ {
return $this->request; return $this->request;
} }
public function getResponse() public function getResponse(): ResponseInterface
{ {
return $this->response; return $this->response;
} }

View file

@ -1,4 +1,4 @@
<?php <?php declare(strict_types=1);
namespace OpenCloud\Common\Error; namespace OpenCloud\Common\Error;

View file

@ -1,4 +1,4 @@
<?php <?php declare(strict_types=1);
namespace OpenCloud\Common\Error; namespace OpenCloud\Common\Error;
@ -48,7 +48,7 @@ class Builder
* *
* @return string * @return string
*/ */
private function header($name) private function header(string $name): string
{ {
return sprintf("%s\n%s\n", $name, str_repeat('~', strlen($name))); return sprintf("%s\n%s\n", $name, str_repeat('~', strlen($name)));
} }
@ -61,7 +61,7 @@ class Builder
* *
* @return bool * @return bool
*/ */
private function linkIsValid($link) private function linkIsValid(string $link): bool
{ {
$link = $this->docDomain . $link; $link = $this->docDomain . $link;
@ -78,7 +78,7 @@ class Builder
* @codeCoverageIgnore * @codeCoverageIgnore
* @return string * @return string
*/ */
public function str(MessageInterface $message) public function str(MessageInterface $message): string
{ {
if ($message instanceof RequestInterface) { if ($message instanceof RequestInterface) {
$msg = trim($message->getMethod() . ' ' $msg = trim($message->getMethod() . ' '
@ -112,7 +112,7 @@ class Builder
* *
* @return BadResponseError * @return BadResponseError
*/ */
public function httpError(RequestInterface $request, ResponseInterface $response) public function httpError(RequestInterface $request, ResponseInterface $response): BadResponseError
{ {
$message = $this->header('HTTP Error'); $message = $this->header('HTTP Error');
@ -138,7 +138,7 @@ class Builder
return $e; return $e;
} }
private function getStatusCodeMessage($statusCode) private function getStatusCodeMessage(int $statusCode): string
{ {
$errors = [ $errors = [
400 => 'Please ensure that your input values are valid and well-formed. ', 400 => 'Please ensure that your input values are valid and well-formed. ',
@ -159,7 +159,7 @@ class Builder
* *
* @return UserInputError * @return UserInputError
*/ */
public function userInputError($expectedType, $userValue, $furtherLink = null) public function userInputError(string $expectedType, $userValue, string $furtherLink = null): UserInputError
{ {
$message = $this->header('User Input Error'); $message = $this->header('User Input Error');

View file

@ -1,4 +1,4 @@
<?php <?php declare(strict_types=1);
namespace OpenCloud\Common\Error; namespace OpenCloud\Common\Error;

View file

@ -1,4 +1,4 @@
<?php <?php declare(strict_types=1);
namespace OpenCloud\Common\Error; namespace OpenCloud\Common\Error;

View file

@ -1,4 +1,4 @@
<?php <?php declare(strict_types=1);
namespace OpenCloud\Common; namespace OpenCloud\Common;
@ -25,7 +25,7 @@ trait HydratorStrategyTrait
} }
} }
private function set($key, $property, array $data, callable $fn = null) private function set(string $key, $property, array $data, callable $fn = null)
{ {
if (isset($data[$key]) && property_exists($this, $property)) { if (isset($data[$key]) && property_exists($this, $property)) {
$value = $fn ? call_user_func($fn, $data[$key]) : $data[$key]; $value = $fn ? call_user_func($fn, $data[$key]) : $data[$key];

View file

@ -1,4 +1,4 @@
<?php <?php declare(strict_types = 1);
namespace OpenCloud\Common; namespace OpenCloud\Common;
@ -42,7 +42,7 @@ class JsonPath
* @param $path The XPath to use * @param $path The XPath to use
* @param $value The new value of the node * @param $value The new value of the node
*/ */
public function set($path, $value) public function set(string $path, $value)
{ {
$this->jsonStructure = $this->setPath($path, $value, $this->jsonStructure); $this->jsonStructure = $this->setPath($path, $value, $this->jsonStructure);
} }
@ -53,9 +53,10 @@ class JsonPath
* @param $path * @param $path
* @param $value * @param $value
* @param $json * @param $json
*
* @return mixed * @return mixed
*/ */
private function setPath($path, $value, $json) private function setPath(string $path, $value, array $json): array
{ {
$nodes = explode('.', $path); $nodes = explode('.', $path);
$point = array_shift($nodes); $point = array_shift($nodes);
@ -87,9 +88,10 @@ class JsonPath
* Get a path's value. If no path can be matched, NULL is returned. * Get a path's value. If no path can be matched, NULL is returned.
* *
* @param $path * @param $path
*
* @return mixed|null * @return mixed|null
*/ */
public function get($path) public function get(string $path)
{ {
return $this->getPath($path, $this->jsonStructure); return $this->getPath($path, $this->jsonStructure);
} }
@ -99,9 +101,10 @@ class JsonPath
* *
* @param $path * @param $path
* @param $json * @param $json
*
* @return null * @return null
*/ */
private function getPath($path, $json) private function getPath(string $path, $json)
{ {
$nodes = explode('.', $path); $nodes = explode('.', $path);
$point = array_shift($nodes); $point = array_shift($nodes);

View file

@ -1,4 +1,4 @@
<?php <?php declare(strict_types=1);
namespace OpenCloud\Common\JsonSchema; namespace OpenCloud\Common\JsonSchema;
@ -13,7 +13,7 @@ class JsonPatch
return (new static)->makeDiff($src, $dest); return (new static)->makeDiff($src, $dest);
} }
public function makeDiff($srcStruct, $desStruct, $path = '') public function makeDiff($srcStruct, $desStruct, string $path = ''): array
{ {
$changes = []; $changes = [];
@ -28,7 +28,7 @@ class JsonPatch
return $changes; return $changes;
} }
protected function handleArray($srcStruct, $desStruct, $path) protected function handleArray(array $srcStruct, array $desStruct, string $path): array
{ {
$changes = []; $changes = [];
@ -53,7 +53,7 @@ class JsonPatch
return $changes; return $changes;
} }
protected function handleObject($srcStruct, $desStruct, $path) protected function handleObject(\stdClass $srcStruct, \stdClass $desStruct, string $path): array
{ {
$changes = []; $changes = [];
@ -76,12 +76,12 @@ class JsonPatch
return $changes; return $changes;
} }
protected function shouldPartiallyReplace($o1, $o2) protected function shouldPartiallyReplace(\stdClass $o1, \stdClass $o2): bool
{ {
return count(array_diff_key((array) $o1, (array) $o2)) < count($o1); return count(array_diff_key((array) $o1, (array) $o2)) < count($o1);
} }
protected function arrayDiff(array $a1, array $a2) protected function arrayDiff(array $a1, array $a2): array
{ {
$result = []; $result = [];
@ -94,8 +94,10 @@ class JsonPatch
return $result; return $result;
} }
protected function path($root, $path) protected function path(string $root, $path): string
{ {
$path = (string) $path;
if ($path === '_empty_') { if ($path === '_empty_') {
$path = ''; $path = '';
} }
@ -103,7 +105,7 @@ class JsonPatch
return rtrim($root, '/') . '/' . ltrim($path, '/'); return rtrim($root, '/') . '/' . ltrim($path, '/');
} }
protected function makePatch($op, $path, $val = null) protected function makePatch(string $op, string $path, $val = null): array
{ {
switch ($op) { switch ($op) {
default: default:

View file

@ -1,4 +1,4 @@
<?php <?php declare(strict_types=1);
namespace OpenCloud\Common\JsonSchema; namespace OpenCloud\Common\JsonSchema;
@ -6,7 +6,10 @@ use JsonSchema\Validator;
class Schema class Schema
{ {
/** @var object */
private $body; private $body;
/** @var Validator */
private $validator; private $validator;
public function __construct($body, Validator $validator = null) public function __construct($body, Validator $validator = null)
@ -15,7 +18,7 @@ class Schema
$this->validator = $validator ?: new Validator(); $this->validator = $validator ?: new Validator();
} }
public function getPropertyPaths() public function getPropertyPaths(): array
{ {
$paths = []; $paths = [];
@ -26,7 +29,7 @@ class Schema
return $paths; return $paths;
} }
public function normalizeObject($subject, array $aliases) public function normalizeObject($subject, array $aliases): \stdClass
{ {
$out = new \stdClass; $out = new \stdClass;
@ -49,17 +52,17 @@ class Schema
$this->validator->check($data, $this->body); $this->validator->check($data, $this->body);
} }
public function isValid() public function isValid(): bool
{ {
return $this->validator->isValid(); return $this->validator->isValid();
} }
public function getErrors() public function getErrors(): array
{ {
return $this->validator->getErrors(); return $this->validator->getErrors();
} }
public function getErrorString() public function getErrorString(): string
{ {
$msg = "Provided values do not validate. Errors:\n"; $msg = "Provided values do not validate. Errors:\n";

View file

@ -1,4 +1,4 @@
<?php <?php declare(strict_types=1);
namespace OpenCloud\Common\Resource; namespace OpenCloud\Common\Resource;
@ -60,7 +60,7 @@ abstract class AbstractResource extends Operator implements ResourceInterface
* *
* @return $this|ResourceInterface * @return $this|ResourceInterface
*/ */
public function populateFromResponse(ResponseInterface $response) public function populateFromResponse(ResponseInterface $response): self
{ {
if (strpos($response->getHeaderLine('Content-Type'), 'application/json') === 0) { if (strpos($response->getHeaderLine('Content-Type'), 'application/json') === 0) {
$json = Utils::jsonDecode($response); $json = Utils::jsonDecode($response);
@ -79,12 +79,12 @@ abstract class AbstractResource extends Operator implements ResourceInterface
* *
* @return mixed|void * @return mixed|void
*/ */
public function populateFromArray(array $array) public function populateFromArray(array $array): self
{ {
$reflClass = new \ReflectionClass($this); $reflClass = new \ReflectionClass($this);
foreach ($array as $key => $val) { foreach ($array as $key => $val) {
$propertyName = isset($this->aliases[$key]) ? $this->aliases[$key] : $key; $propertyName = (string) (isset($this->aliases[$key]) ? $this->aliases[$key] : $key);
if (property_exists($this, $propertyName)) { if (property_exists($this, $propertyName)) {
if ($type = $this->extractTypeFromDocBlock($reflClass, $propertyName)) { if ($type = $this->extractTypeFromDocBlock($reflClass, $propertyName)) {
@ -94,9 +94,11 @@ abstract class AbstractResource extends Operator implements ResourceInterface
$this->$propertyName = $val; $this->$propertyName = $val;
} }
} }
return $this;
} }
private function parseDocBlockValue($type, $val) private function parseDocBlockValue(string $type, $val)
{ {
if (strpos($type, '[]') === 0 && is_array($val)) { if (strpos($type, '[]') === 0 && is_array($val)) {
$array = []; $array = [];
@ -113,7 +115,7 @@ abstract class AbstractResource extends Operator implements ResourceInterface
return $val; return $val;
} }
private function isNotNativeType($type) private function isNotNativeType(string $type): bool
{ {
return !in_array($type, [ return !in_array($type, [
'string', 'bool', 'boolean', 'double', 'null', 'array', 'object', 'int', 'integer', 'float', 'numeric', 'string', 'bool', 'boolean', 'double', 'null', 'array', 'object', 'int', 'integer', 'float', 'numeric',
@ -121,7 +123,7 @@ abstract class AbstractResource extends Operator implements ResourceInterface
]); ]);
} }
private function normalizeModelClass($class) private function normalizeModelClass(string $class): string
{ {
if (strpos($class, '\\') === false) { if (strpos($class, '\\') === false) {
$currentNamespace = (new \ReflectionClass($this))->getNamespaceName(); $currentNamespace = (new \ReflectionClass($this))->getNamespaceName();
@ -131,7 +133,7 @@ abstract class AbstractResource extends Operator implements ResourceInterface
return $class; return $class;
} }
private function extractTypeFromDocBlock(\ReflectionClass $reflClass, $propertyName) private function extractTypeFromDocBlock(\ReflectionClass $reflClass, string $propertyName)
{ {
$docComment = $reflClass->getProperty($propertyName)->getDocComment(); $docComment = $reflClass->getProperty($propertyName)->getDocComment();
@ -174,7 +176,7 @@ abstract class AbstractResource extends Operator implements ResourceInterface
return $this->execute($definition, $this->getAttrs(array_keys($definition['params']))); return $this->execute($definition, $this->getAttrs(array_keys($definition['params'])));
} }
private function getResourcesKey() private function getResourcesKey(): string
{ {
$resourcesKey = $this->resourcesKey; $resourcesKey = $this->resourcesKey;
@ -189,7 +191,7 @@ abstract class AbstractResource extends Operator implements ResourceInterface
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public function enumerate(array $def, array $userVals = [], callable $mapFn = null) public function enumerate(array $def, array $userVals = [], callable $mapFn = null): \Generator
{ {
$operation = $this->getOperation($def); $operation = $this->getOperation($def);
@ -217,7 +219,7 @@ abstract class AbstractResource extends Operator implements ResourceInterface
return $iterator(); return $iterator();
} }
public function extractMultipleInstances(ResponseInterface $response, $key = null) public function extractMultipleInstances(ResponseInterface $response, string $key = null): array
{ {
$key = $key ?: $this->getResourcesKey(); $key = $key ?: $this->getResourcesKey();
$resourcesData = Utils::jsonDecode($response)[$key]; $resourcesData = Utils::jsonDecode($response)[$key];

View file

@ -1,4 +1,4 @@
<?php <?php declare(strict_types=1);
namespace OpenCloud\Common\Resource; namespace OpenCloud\Common\Resource;
@ -15,5 +15,5 @@ interface Creatable
* @param array $userOptions * @param array $userOptions
* @return self * @return self
*/ */
public function create(array $userOptions); public function create(array $userOptions): Creatable;
} }

View file

@ -1,4 +1,4 @@
<?php <?php declare(strict_types=1);
namespace OpenCloud\Common\Resource; namespace OpenCloud\Common\Resource;

View file

@ -1,4 +1,4 @@
<?php <?php declare(strict_types=1);
namespace OpenCloud\Common\Resource; namespace OpenCloud\Common\Resource;
@ -12,7 +12,7 @@ interface HasMetadata
* *
* @return array * @return array
*/ */
public function getMetadata(); public function getMetadata(): array;
/** /**
* Merges a set of new values with those which already exist (on the remote API) for a resource. For example, if * Merges a set of new values with those which already exist (on the remote API) for a resource. For example, if
@ -32,7 +32,7 @@ interface HasMetadata
* *
* @param array $metadata The new metadata items * @param array $metadata The new metadata items
* *
* @return mixed * @return void
*/ */
public function mergeMetadata(array $metadata); public function mergeMetadata(array $metadata);
@ -52,7 +52,7 @@ interface HasMetadata
* *
* @param array $metadata The new metadata items * @param array $metadata The new metadata items
* *
* @return mixed * @return void
*/ */
public function resetMetadata(array $metadata); public function resetMetadata(array $metadata);
@ -63,5 +63,5 @@ interface HasMetadata
* *
* @return array * @return array
*/ */
public function parseMetadata(ResponseInterface $response); public function parseMetadata(ResponseInterface $response): array;
} }

View file

@ -1,4 +1,4 @@
<?php <?php declare(strict_types=1);
namespace OpenCloud\Common\Resource; namespace OpenCloud\Common\Resource;
@ -24,7 +24,7 @@ trait HasWaiterTrait
* or exceed this timeout, the blocking operation will immediately cease. * or exceed this timeout, the blocking operation will immediately cease.
* @param int $sleepPeriod The amount of time to pause between each HTTP request. * @param int $sleepPeriod The amount of time to pause between each HTTP request.
*/ */
public function waitUntil($status, $timeout = 60, $sleepPeriod = 1) public function waitUntil(string $status, $timeout = 60, int $sleepPeriod = 1)
{ {
$startTime = time(); $startTime = time();
@ -53,7 +53,7 @@ trait HasWaiterTrait
* is provided, the timeout will never be considered. * is provided, the timeout will never be considered.
* @param int $sleepPeriod The amount of time to pause between each HTTP request. * @param int $sleepPeriod The amount of time to pause between each HTTP request.
*/ */
public function waitWithCallback(callable $fn, $timeout = 60, $sleepPeriod = 1) public function waitWithCallback(callable $fn, $timeout = 60, int $sleepPeriod = 1)
{ {
$startTime = time(); $startTime = time();
@ -78,7 +78,7 @@ trait HasWaiterTrait
* *
* @return bool * @return bool
*/ */
private function shouldHalt($timeout, $startTime) private function shouldHalt($timeout, int $startTime)
{ {
if ($timeout === false) { if ($timeout === false) {
return false; return false;
@ -100,7 +100,7 @@ trait HasWaiterTrait
$this->waitUntil('ACTIVE', $timeout); $this->waitUntil('ACTIVE', $timeout);
} }
public function waitUntilDeleted($timeout = 60, $sleepPeriod = 1) public function waitUntilDeleted($timeout = 60, int $sleepPeriod = 1)
{ {
$startTime = time(); $startTime = time();

View file

@ -1,4 +1,4 @@
<?php <?php declare(strict_types=1);
namespace OpenCloud\Common\Resource; namespace OpenCloud\Common\Resource;

View file

@ -1,4 +1,4 @@
<?php <?php declare(strict_types=1);
namespace OpenCloud\Common\Resource; namespace OpenCloud\Common\Resource;

View file

@ -1,4 +1,4 @@
<?php <?php declare(strict_types=1);
namespace OpenCloud\Common\Resource; namespace OpenCloud\Common\Resource;

View file

@ -1,4 +1,4 @@
<?php <?php declare(strict_types=1);
namespace OpenCloud\Common\Resource; namespace OpenCloud\Common\Resource;

View file

@ -1,4 +1,4 @@
<?php <?php declare(strict_types=1);
namespace OpenCloud\Common\Resource; namespace OpenCloud\Common\Resource;

View file

@ -1,4 +1,4 @@
<?php <?php declare(strict_types=1);
namespace OpenCloud\Common\Service; namespace OpenCloud\Common\Service;

View file

@ -1,15 +1,15 @@
<?php <?php declare(strict_types = 1);
namespace OpenCloud\Common\Service; namespace OpenCloud\Common\Service;
use GuzzleHttp\Client; use GuzzleHttp\Client;
use GuzzleHttp\ClientInterface; use GuzzleHttp\ClientInterface;
use GuzzleHttp\Middleware as GuzzleMiddleware; use GuzzleHttp\Middleware as GuzzleMiddleware;
use OpenCloud\Common\Auth\IdentityService;
use OpenCloud\Common\Auth\Token; use OpenCloud\Common\Auth\Token;
use OpenCloud\Common\Transport\HandlerStack; use OpenCloud\Common\Transport\HandlerStack;
use OpenCloud\Common\Transport\Middleware; use OpenCloud\Common\Transport\Middleware;
use OpenCloud\Common\Transport\Utils; use OpenCloud\Common\Transport\Utils;
use OpenCloud\Identity\v3\Service;
/** /**
* A Builder for easily creating OpenCloud services. * A Builder for easily creating OpenCloud services.
@ -54,7 +54,7 @@ class Builder
* *
* @return array * @return array
*/ */
private function getClasses($serviceName, $serviceVersion) private function getClasses(string $serviceName, int $serviceVersion)
{ {
$rootNamespace = sprintf("%s\\%s\\v%d", $this->rootNamespace, $serviceName, $serviceVersion); $rootNamespace = sprintf("%s\\%s\\v%d", $this->rootNamespace, $serviceName, $serviceVersion);
@ -70,19 +70,18 @@ class Builder
* directly - this setup includes the configuration of the HTTP client's base URL, and the * directly - this setup includes the configuration of the HTTP client's base URL, and the
* attachment of an authentication handler. * attachment of an authentication handler.
* *
* @param $serviceName The name of the service as it appears in the OpenCloud\* namespace * @param string $serviceName The name of the service as it appears in the OpenCloud\* namespace
* @param $serviceVersion The major version of the service * @param int $serviceVersion The major version of the service
* @param array $serviceOptions The service-specific options to use * @param array $serviceOptions The service-specific options to use
* *
* @return \OpenCloud\Common\Service\ServiceInterface * @return \OpenCloud\Common\Service\ServiceInterface
* *
* @throws \Exception * @throws \Exception
*/ */
public function createService($serviceName, $serviceVersion, array $serviceOptions = []) public function createService(string $serviceName, int $serviceVersion, array $serviceOptions = []): ServiceInterface
{ {
$options = $this->mergeOptions($serviceOptions); $options = $this->mergeOptions($serviceOptions);
$this->stockIdentityService($options);
$this->stockAuthHandler($options); $this->stockAuthHandler($options);
$this->stockHttpClient($options, $serviceName); $this->stockHttpClient($options, $serviceName);
@ -91,7 +90,7 @@ class Builder
return new $serviceClass($options['httpClient'], new $apiClass()); return new $serviceClass($options['httpClient'], new $apiClass());
} }
private function stockHttpClient(array &$options, $serviceName) private function stockHttpClient(array &$options, string $serviceName)
{ {
if (!isset($options['httpClient']) || !($options['httpClient'] instanceof ClientInterface)) { if (!isset($options['httpClient']) || !($options['httpClient'] instanceof ClientInterface)) {
if (strcasecmp($serviceName, 'identity') === 0) { if (strcasecmp($serviceName, 'identity') === 0) {
@ -121,16 +120,9 @@ class Builder
} }
} }
private function stockIdentityService(array &$options)
{
if (!isset($options['identityService'])) {
$httpClient = $this->httpClient($options['authUrl'], HandlerStack::create());
$options['identityService'] = Service::factory($httpClient);
}
}
/** /**
* @param array $options * @param array $options
*
* @codeCoverageIgnore * @codeCoverageIgnore
*/ */
private function stockAuthHandler(array &$options) private function stockAuthHandler(array &$options)
@ -142,14 +134,14 @@ class Builder
} }
} }
private function getStack(callable $authHandler, Token $token = null) private function getStack(callable $authHandler, Token $token = null): HandlerStack
{ {
$stack = HandlerStack::create(); $stack = HandlerStack::create();
$stack->push(Middleware::authHandler($authHandler, $token)); $stack->push(Middleware::authHandler($authHandler, $token));
return $stack; return $stack;
} }
private function httpClient($baseUrl, HandlerStack $stack) private function httpClient(string $baseUrl, HandlerStack $stack): ClientInterface
{ {
return new Client([ return new Client([
'base_uri' => Utils::normalizeUrl($baseUrl), 'base_uri' => Utils::normalizeUrl($baseUrl),
@ -157,7 +149,7 @@ class Builder
]); ]);
} }
private function mergeOptions(array $serviceOptions) private function mergeOptions(array $serviceOptions): array
{ {
$options = array_merge($this->defaults, $this->globalOptions, $serviceOptions); $options = array_merge($this->defaults, $this->globalOptions, $serviceOptions);
@ -165,6 +157,12 @@ class Builder
throw new \InvalidArgumentException('"authUrl" is a required option'); throw new \InvalidArgumentException('"authUrl" is a required option');
} }
if (!isset($options['identityService']) || !($options['identityService'] instanceof IdentityService)) {
throw new \InvalidArgumentException(sprintf(
'"identityService" must be specified and implement %s', IdentityService::class
));
}
return $options; return $options;
} }
} }

View file

@ -1,4 +1,4 @@
<?php <?php declare(strict_types=1);
namespace OpenCloud\Common\Service; namespace OpenCloud\Common\Service;

View file

@ -1,4 +1,4 @@
<?php <?php declare(strict_types=1);
namespace OpenCloud\Common\Transport; namespace OpenCloud\Common\Transport;
@ -7,7 +7,7 @@ use GuzzleHttp\HandlerStack as GuzzleStack;
class HandlerStack extends GuzzleStack class HandlerStack extends GuzzleStack
{ {
public static function create(callable $handler = null) public static function create(callable $handler = null): self
{ {
$stack = new self($handler ?: choose_handler()); $stack = new self($handler ?: choose_handler());

View file

@ -1,4 +1,4 @@
<?php <?php declare(strict_types=1);
namespace OpenCloud\Common\Transport; namespace OpenCloud\Common\Transport;
@ -22,7 +22,7 @@ class JsonSerializer
* *
* @return array|mixed * @return array|mixed
*/ */
private function stockValue(Parameter $param, $userValue, $json) private function stockValue(Parameter $param, $userValue, array $json): array
{ {
$name = $param->getName(); $name = $param->getName();
if ($path = $param->getPath()) { if ($path = $param->getPath()) {
@ -46,7 +46,7 @@ class JsonSerializer
* *
* @return array|mixed * @return array|mixed
*/ */
private function stockArrayJson(Parameter $param, $userValue) private function stockArrayJson(Parameter $param, array $userValue): array
{ {
$elems = []; $elems = [];
foreach ($userValue as $item) { foreach ($userValue as $item) {
@ -63,7 +63,7 @@ class JsonSerializer
* *
* @return array * @return array
*/ */
private function stockObjectJson(Parameter $param, $userValue) private function stockObjectJson(Parameter $param, \stdClass $userValue): array
{ {
$object = []; $object = [];
foreach ($userValue as $key => $val) { foreach ($userValue as $key => $val) {
@ -82,12 +82,12 @@ class JsonSerializer
* *
* @return array * @return array
*/ */
public function stockJson(Parameter $param, $userValue, $json) public function stockJson(Parameter $param, $userValue, array $json): array
{ {
if ($param->isArray()) { if ($param->isArray()) {
$userValue = $this->stockArrayJson($param, $userValue); $userValue = $this->stockArrayJson($param, $userValue);
} elseif ($param->isObject()) { } elseif ($param->isObject()) {
$userValue = $this->stockObjectJson($param, $userValue); $userValue = $this->stockObjectJson($param, (object) $userValue);
} }
// Populate the final value // Populate the final value
return $this->stockValue($param, $userValue, $json); return $this->stockValue($param, $userValue, $json);

View file

@ -1,4 +1,4 @@
<?php <?php declare(strict_types=1);
namespace OpenCloud\Common\Transport; namespace OpenCloud\Common\Transport;
@ -9,13 +9,15 @@ use OpenCloud\Common\Auth\AuthHandler;
use OpenCloud\Common\Auth\Token; use OpenCloud\Common\Auth\Token;
use OpenCloud\Common\Error\Builder; use OpenCloud\Common\Error\Builder;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
use Psr\Log\LoggerInterface;
use Psr\Log\LogLevel;
final class Middleware final class Middleware
{ {
/** /**
* @return callable * @return callable
*/ */
public static function httpErrors() public static function httpErrors(): callable
{ {
return function (callable $handler) { return function (callable $handler) {
return function ($request, array $options) use ($handler) { return function ($request, array $options) use ($handler) {
@ -37,7 +39,7 @@ final class Middleware
* *
* @return callable * @return callable
*/ */
public static function authHandler(callable $tokenGenerator, Token $token = null) public static function authHandler(callable $tokenGenerator, Token $token = null): callable
{ {
return function (callable $handler) use ($tokenGenerator, $token) { return function (callable $handler) use ($tokenGenerator, $token) {
return new AuthHandler($handler, $tokenGenerator, $token); return new AuthHandler($handler, $tokenGenerator, $token);
@ -47,7 +49,7 @@ final class Middleware
/** /**
* @codeCoverageIgnore * @codeCoverageIgnore
*/ */
public static function history(array &$container) public static function history(array &$container): callable
{ {
return GuzzleMiddleware::history($container); return GuzzleMiddleware::history($container);
} }
@ -55,7 +57,7 @@ final class Middleware
/** /**
* @codeCoverageIgnore * @codeCoverageIgnore
*/ */
public static function retry(callable $decider, callable $delay = null) public static function retry(callable $decider, callable $delay = null): callable
{ {
return GuzzleMiddleware::retry($decider, $delay); return GuzzleMiddleware::retry($decider, $delay);
} }
@ -63,7 +65,7 @@ final class Middleware
/** /**
* @codeCoverageIgnore * @codeCoverageIgnore
*/ */
public static function log(LoggerInterface $logger, MessageFormatter $formatter, $logLevel = LogLevel::INFO) public static function log(LoggerInterface $logger, MessageFormatter $formatter, $logLevel = LogLevel::INFO): callable
{ {
return GuzzleMiddleware::log($logger, $formatter, $logLevel); return GuzzleMiddleware::log($logger, $formatter, $logLevel);
} }
@ -71,7 +73,7 @@ final class Middleware
/** /**
* @codeCoverageIgnore * @codeCoverageIgnore
*/ */
public static function prepareBody() public static function prepareBody(): callable
{ {
return GuzzleMiddleware::prepareBody(); return GuzzleMiddleware::prepareBody();
} }
@ -79,7 +81,7 @@ final class Middleware
/** /**
* @codeCoverageIgnore * @codeCoverageIgnore
*/ */
public static function mapRequest(callable $fn) public static function mapRequest(callable $fn): callable
{ {
return GuzzleMiddleware::mapRequest($fn); return GuzzleMiddleware::mapRequest($fn);
} }
@ -87,7 +89,7 @@ final class Middleware
/** /**
* @codeCoverageIgnore * @codeCoverageIgnore
*/ */
public static function mapResponse(callable $fn) public static function mapResponse(callable $fn): callable
{ {
return GuzzleMiddleware::mapResponse($fn); return GuzzleMiddleware::mapResponse($fn);
} }

View file

@ -1,4 +1,4 @@
<?php <?php declare(strict_types=1);
namespace OpenCloud\Common\Transport; namespace OpenCloud\Common\Transport;
@ -17,7 +17,7 @@ class RequestSerializer
$this->jsonSerializer = $jsonSerializer ?: new JsonSerializer(); $this->jsonSerializer = $jsonSerializer ?: new JsonSerializer();
} }
public function serializeOptions(Operation $operation, array $userValues = []) public function serializeOptions(Operation $operation, array $userValues = []): array
{ {
$options = ['headers' => []]; $options = ['headers' => []];

View file

@ -1,4 +1,4 @@
<?php <?php declare(strict_types=1);
namespace OpenCloud\Common\Transport; namespace OpenCloud\Common\Transport;
@ -8,7 +8,7 @@ use Psr\Http\Message\UriInterface;
class Utils class Utils
{ {
public static function jsonDecode(ResponseInterface $response, $assoc = true) public static function jsonDecode(ResponseInterface $response, bool $assoc = true)
{ {
$jsonErrors = [ $jsonErrors = [
JSON_ERROR_DEPTH => 'JSON_ERROR_DEPTH - Maximum stack depth exceeded', JSON_ERROR_DEPTH => 'JSON_ERROR_DEPTH - Maximum stack depth exceeded',
@ -40,11 +40,11 @@ class Utils
* Method for flattening a nested array. * Method for flattening a nested array.
* *
* @param array $data The nested array * @param array $data The nested array
* @param null $key The key to extract * @param string $key The key to extract
* *
* @return array * @return array
*/ */
public static function flattenJson($data, $key = null) public static function flattenJson($data, string $key = null)
{ {
return (!empty($data) && $key && isset($data[$key])) ? $data[$key] : $data; return (!empty($data) && $key && isset($data[$key])) ? $data[$key] : $data;
} }
@ -59,7 +59,7 @@ class Utils
* *
* @return string * @return string
*/ */
public static function normalizeUrl($url) public static function normalizeUrl(string $url): string
{ {
if (strpos($url, 'http') === false) { if (strpos($url, 'http') === false) {
$url = 'http://' . $url; $url = 'http://' . $url;
@ -76,12 +76,12 @@ class Utils
* *
* @return UriInterface * @return UriInterface
*/ */
public static function addPaths(UriInterface $uri, ...$paths) public static function addPaths(UriInterface $uri, ...$paths): UriInterface
{ {
return uri_for(rtrim((string) $uri, '/') . '/' . implode('/', $paths)); return uri_for(rtrim((string) $uri, '/') . '/' . implode('/', $paths));
} }
public static function appendPath(UriInterface $uri, $path) public static function appendPath(UriInterface $uri, $path): UriInterface
{ {
return uri_for(rtrim((string) $uri, '/') . '/' . $path); return uri_for(rtrim((string) $uri, '/') . '/' . $path);
} }

View file

@ -1,6 +1,6 @@
<?php <?php
namespace OpenCloud\integration; namespace OpenCloud\Integration;
use Psr\Log\AbstractLogger; use Psr\Log\AbstractLogger;

View file

@ -1,16 +1,19 @@
<?php <?php
namespace OpenCloud\integration; namespace OpenCloud\Integration;
class Runner class Runner
{ {
private $basePath; private $basePath;
private $logger; private $logger;
private $services = []; private $services = [];
private $namespace;
public function __construct($basePath) public function __construct($basePath, $testNamespace)
{ {
$this->basePath = $basePath; $this->basePath = $basePath;
$this->namespace = $testNamespace;
$this->logger = new DefaultLogger(); $this->logger = new DefaultLogger();
$this->assembleServicesFromSamples(); $this->assembleServicesFromSamples();
} }
@ -73,15 +76,14 @@ class Runner
*/ */
private function getTest($serviceName, $version, $verbosity) private function getTest($serviceName, $version, $verbosity)
{ {
$namespace = (new \ReflectionClass($this))->getNamespaceName(); $className = sprintf("%s\\%s\\%sTest", $this->namespace, Utils::toCamelCase($serviceName), ucfirst($version));
$className = sprintf("%s\\%s\\%sTest", $namespace, Utils::toCamelCase($serviceName), ucfirst($version));
if (!class_exists($className)) { if (!class_exists($className)) {
throw new \RuntimeException(sprintf("%s does not exist", $className)); throw new \RuntimeException(sprintf("%s does not exist", $className));
} }
$basePath = $this->basePath . DIRECTORY_SEPARATOR . $serviceName . DIRECTORY_SEPARATOR . $version; $basePath = $this->basePath . DIRECTORY_SEPARATOR . $serviceName . DIRECTORY_SEPARATOR . $version;
$smClass = sprintf("%s\\SampleManager", $namespace); $smClass = sprintf("%s\\SampleManager", $this->namespace);
$class = new $className($this->logger, new $smClass($basePath, $verbosity)); $class = new $className($this->logger, new $smClass($basePath, $verbosity));
if (!($class instanceof TestInterface)) { if (!($class instanceof TestInterface)) {

View file

@ -1,6 +1,6 @@
<?php <?php
namespace OpenCloud\integration; namespace OpenCloud\Integration;
interface SampleManagerInterface interface SampleManagerInterface
{ {

View file

@ -1,6 +1,6 @@
<?php <?php
namespace OpenCloud\integration; namespace OpenCloud\Integration;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;

View file

@ -1,6 +1,6 @@
<?php <?php
namespace OpenCloud\integration; namespace OpenCloud\Integration;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;

View file

@ -1,57 +1,11 @@
<?php <?php
namespace OpenCloud\integration; namespace OpenCloud\Integration;
use GuzzleHttp\Client; use GuzzleHttp\Client;
use OpenCloud\Identity\v2\Api;
use OpenCloud\Identity\v2\Service;
use OpenCloud\Common\Transport\HandlerStack;
use OpenCloud\Common\Transport\Utils as CommonUtils;
class Utils class Utils
{ {
public static function getAuthOptsV3()
{
return [
'authUrl' => getenv('OS_AUTH_URL'),
'region' => getenv('OS_REGION_NAME'),
'user' => [
'id' => getenv('OS_USER_ID'),
'password' => getenv('OS_PASSWORD'),
],
'scope' => [
'project' => [
'id' => getenv('OS_PROJECT_ID'),
]
]
];
}
public static function getAuthOptsV2()
{
$httpClient = new Client([
'base_uri' => CommonUtils::normalizeUrl(getenv('OS_AUTH_URL')),
'handler' => HandlerStack::create(),
]);
return [
'authUrl' => getenv('OS_AUTH_URL'),
'region' => getenv('OS_REGION_NAME'),
'username' => getenv('OS_USERNAME'),
'password' => getenv('OS_PASSWORD'),
'tenantName' => getenv('OS_TENANT_NAME'),
'identityService' => new Service($httpClient, new Api),
];
}
public static function getAuthOpts(array $options = [])
{
$authOptions = getenv('OS_IDENTITY_API_VERSION') == '2.0'
? self::getAuthOptsV2()
: self::getAuthOptsV3();
return array_merge($authOptions, $options);
}
public static function toCamelCase($word, $separator = '_') public static function toCamelCase($word, $separator = '_')
{ {
return str_replace($separator, '', ucwords($word, $separator)); return str_replace($separator, '', ucwords($word, $separator));

View file

@ -1,10 +0,0 @@
<?php
$rootDir = dirname(dirname(__DIR__));
require_once $rootDir . '/vendor/autoload.php';
$basePath = $rootDir . '/samples';
$runner = new \OpenCloud\Integration\Runner($basePath);
$runner->runServices();

View file

@ -10,7 +10,6 @@ use GuzzleHttp\Psr7\Uri;
use OpenCloud\Common\Api\Operator; use OpenCloud\Common\Api\Operator;
use OpenCloud\Common\Resource\AbstractResource; use OpenCloud\Common\Resource\AbstractResource;
use OpenCloud\Common\Resource\ResourceInterface; use OpenCloud\Common\Resource\ResourceInterface;
use OpenCloud\Compute\v2\Models\Server;
use OpenCloud\Test\Fixtures\ComputeV2Api; use OpenCloud\Test\Fixtures\ComputeV2Api;
use OpenCloud\Test\TestCase; use OpenCloud\Test\TestCase;
use Prophecy\Argument; use Prophecy\Argument;
@ -45,7 +44,7 @@ class OperatorTest extends TestCase
public function test_it_sends_a_request_when_operations_are_executed() public function test_it_sends_a_request_when_operations_are_executed()
{ {
$this->client->request('GET', 'test', ['headers' => []])->willReturn(new Request('GET', 'test')); $this->client->request('GET', 'test', ['headers' => []])->willReturn(new Response());
$this->operator->execute($this->def, []); $this->operator->execute($this->def, []);
} }

View file

@ -53,7 +53,11 @@ class AuthHandlerTest extends TestCase
} }
} }
class FakeToken implements Token { class FakeToken implements Token
public function getId() {} {
public function hasExpired() {} public function getId(): string
{}
public function hasExpired(): bool
{}
} }

View file

@ -95,8 +95,8 @@ class SchemaTest extends TestCase
public function test_it_checks_validity() public function test_it_checks_validity()
{ {
$this->validator->isValid()->shouldBeCalled(); $this->validator->isValid()->shouldBeCalled()->willReturn(true);
$this->schema->isValid(); $this->schema->isValid();
} }
} }

View file

@ -47,8 +47,8 @@ class JsonSerializerTest extends \PHPUnit_Framework_TestCase
$itemSchema = $this->prophesize(Parameter::class); $itemSchema = $this->prophesize(Parameter::class);
$itemSchema->isArray()->shouldBeCalled()->willReturn(false); $itemSchema->isArray()->shouldBeCalled()->willReturn(false);
$itemSchema->isObject()->shouldBeCalled()->willReturn(false); $itemSchema->isObject()->shouldBeCalled()->willReturn(false);
$itemSchema->getName()->shouldBeCalled()->willReturn(null); $itemSchema->getName()->shouldBeCalled()->willReturn('');
$itemSchema->getPath()->shouldBeCalled()->willReturn(null); $itemSchema->getPath()->shouldBeCalled()->willReturn('');
$param->getItemSchema()->shouldBeCalled()->willReturn($itemSchema); $param->getItemSchema()->shouldBeCalled()->willReturn($itemSchema);
@ -67,7 +67,7 @@ class JsonSerializerTest extends \PHPUnit_Framework_TestCase
$prop->isArray()->shouldBeCalled()->willReturn(false); $prop->isArray()->shouldBeCalled()->willReturn(false);
$prop->isObject()->shouldBeCalled()->willReturn(false); $prop->isObject()->shouldBeCalled()->willReturn(false);
$prop->getName()->shouldBeCalled()->willReturn('foo'); $prop->getName()->shouldBeCalled()->willReturn('foo');
$prop->getPath()->shouldBeCalled()->willReturn(null); $prop->getPath()->shouldBeCalled()->willReturn('');
$param = $this->prophesize(Parameter::class); $param = $this->prophesize(Parameter::class);
$param->isArray()->shouldBeCalled()->willReturn(false); $param->isArray()->shouldBeCalled()->willReturn(false);
@ -78,7 +78,7 @@ class JsonSerializerTest extends \PHPUnit_Framework_TestCase
$expected = ['topLevel' => ['foo' => true]]; $expected = ['topLevel' => ['foo' => true]];
$json = $this->serializer->stockJson($param->reveal(), ['foo' => true], []); $json = $this->serializer->stockJson($param->reveal(), (object) ['foo' => true], []);
$this->assertEquals($expected, $json); $this->assertEquals($expected, $json);
} }

View file

@ -53,7 +53,17 @@ class ComputeV2Api implements ApiInterface
] ]
], ],
'name' => ['type' => 'string', 'required' => true], 'name' => ['type' => 'string', 'required' => true],
'metadata' => ['type' => 'object', 'location' => 'json'], 'metadata' => [
'type' => 'object',
'location' => 'json',
'description' => 'An arbitrary key/value pairing that will be used for metadata.',
'properties' => [
'type' => 'string',
'description' => <<<TYPEOTHER
The value being set for your key. Bear in mind that "key" is just an example, you can name it anything.
TYPEOTHER
]
],
'personality' => ['type' => 'string'], 'personality' => ['type' => 'string'],
'blockDeviceMapping' => [ 'blockDeviceMapping' => [
'type' => 'array', 'type' => 'array',

@ -1 +1 @@
Subproject commit 4ba218fc7ed0e618fd83eaf690b2e4e3bf22cde5 Subproject commit 61626420361a1dab3ed6f9455e1057bda18cc335