diff --git a/.gitignore b/.gitignore index f72eefc..80c6daf 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,5 @@ composer.phar /phpunit.xml /build.properties /docs -.phpunit.*.cache \ No newline at end of file +.phpunit.*.cache +/.php-cs-fixer.cache diff --git a/.php-cs-fixer.php b/.php-cs-fixer.php new file mode 100644 index 0000000..815ce81 --- /dev/null +++ b/.php-cs-fixer.php @@ -0,0 +1,88 @@ +. + */ + +declare(strict_types=1); + +$header = <<<'EOF' +Copyright (c) 2013-2024, OVH SAS. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of OVH SAS nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY OVH SAS AND CONTRIBUTORS ``AS IS'' AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL OVH SAS AND CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +EOF; + +$finder = PhpCsFixer\Finder::create() + ->files() + ->name(['*.php']) + ->in(__DIR__ . '/src') + ->in(__DIR__ . '/tests'); + +$config = new PhpCsFixer\Config(); +$config + ->setRiskyAllowed(true) + ->setRules([ + '@PhpCsFixer' => true, + '@PSR2' => true, + 'header_comment' => ['header' => $header], + 'no_empty_comment' => true, + 'no_trailing_whitespace_in_comment' => true, + 'ordered_interfaces' => true, + 'concat_space' => ['spacing' => 'one'], + 'function_declaration' => ['closure_function_spacing' => 'none'], + 'single_line_comment_style' => ['comment_types' => ['hash']], + 'constant_case' => ['case' => 'lower'], + 'single_quote' => true, + 'array_syntax' => ['syntax' => 'short'], + 'class_definition' => [ + 'single_line' => false, + ], + 'braces' => [ + 'position_after_functions_and_oop_constructs' => 'next', + 'position_after_control_structures' => 'same', + 'position_after_anonymous_constructs' => 'same', + ], + 'binary_operator_spaces' => ['operators' => + ['=>' => 'align_single_space_minimal', '=' => 'align_single_space_minimal'] + ], + 'single_line_empty_body' => false, + ]) + ->setFinder($finder); + +return $config; diff --git a/composer.json b/composer.json index a771425..04d846b 100644 --- a/composer.json +++ b/composer.json @@ -22,6 +22,7 @@ "ext-json": "*" }, "require-dev": { + "friendsofphp/php-cs-fixer": "^v3.54.0", "php-parallel-lint/php-parallel-lint": "^1.3.1", "phpdocumentor/shim": "^3", "phpunit/phpunit": "^9.5", @@ -36,6 +37,7 @@ } }, "scripts": { + "cs-fix": "PHP_CS_FIXER_IGNORE_ENV=1 ./vendor/bin/php-cs-fixer fix", "phpdoc": "vendor/bin/phpdoc", "phpcs": "vendor/bin/phpcs -sp --colors", "phpcbf": "vendor/bin/phpcbf -sp", diff --git a/scripts/update-copyright.sh b/scripts/update-copyright.sh deleted file mode 100755 index 3bffa1a..0000000 --- a/scripts/update-copyright.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash -# -# Usage: ./scripts/update-copyright.sh -# - -PCRE_MATCH_COPYRIGHT="Copyright \(c\) 2013-[0-9]{4}, OVH SAS." -PCRE_MATCH_DEBIAN="Copyright: [-0-9]* OVH SAS" -YEAR=$(date +%Y) - -echo -n "Updating copyright headers to ${YEAR}... " -grep -rPl "${PCRE_MATCH_COPYRIGHT}" | xargs sed -ri "s/${PCRE_MATCH_COPYRIGHT}/Copyright (c) 2013-${YEAR}, OVH SAS./g" -grep -rPl "${PCRE_MATCH_DEBIAN}" | xargs sed -ri "s/${PCRE_MATCH_DEBIAN}/Copyright: 2013-${YEAR} OVH SAS/g" -echo "[OK]" - diff --git a/src/Api.php b/src/Api.php index 4a237ae..519295c 100644 --- a/src/Api.php +++ b/src/Api.php @@ -1,31 +1,35 @@ endpoint = $api_endpoint; + $this->endpoint = $api_endpoint; } else { if (!array_key_exists($api_endpoint, $this->endpoints)) { - throw new Exceptions\InvalidParameterException("Unknown provided endpoint"); + throw new Exceptions\InvalidParameterException('Unknown provided endpoint'); } - $this->endpoint = $this->endpoints[$api_endpoint]; + $this->endpoint = $this->endpoints[$api_endpoint]; } if (!isset($http_client)) { @@ -156,47 +148,26 @@ public function __construct( $this->consumer_key = $consumer_key; } - /** - * Calculate time delta between local machine and API's server - * - * @throws ClientException if http request is an error - * @return int - */ - private function calculateTimeDelta() - { - if (!isset($this->time_delta)) { - $response = $this->rawCall( - 'GET', - "/auth/time", - null, - false - ); - $serverTimestamp = (int)(string)$response->getBody(); - $this->time_delta = $serverTimestamp - (int)\time(); - } - - return $this->time_delta; - } - /** * Request a consumer key from the API and the validation link to - * authorize user to validate this consumer key + * authorize user to validate this consumer key. * - * @param array $accessRules list of rules your application need. + * @param array $accessRules list of rules your application need * @param string $redirection url to redirect on your website after authentication * * @return mixed + * * @throws ClientException if http request is an error */ public function requestCredentials( array $accessRules, $redirection = null ) { - $parameters = new \StdClass(); + $parameters = new \stdClass(); $parameters->accessRules = $accessRules; $parameters->redirection = $redirection; - //bypass authentication for this call + // bypass authentication for this call $response = $this->decodeResponse( $this->rawCall( 'POST', @@ -206,26 +177,128 @@ public function requestCredentials( ) ); - $this->consumer_key = $response["consumerKey"]; + $this->consumer_key = $response['consumerKey']; return $response; } + /** + * Wrap call to Ovh APIs for GET requests. + * + * @param string $path path ask inside api + * @param array $content content to send inside body of request + * @param array headers custom HTTP headers to add on the request + * @param bool is_authenticated if the request need to be authenticated + * @param null|mixed $headers + * @param mixed $is_authenticated + * + * @throws ClientException if http request is an error + * @throws \JsonException + */ + public function get($path, $content = null, $headers = null, $is_authenticated = true) + { + if (preg_match('/^\/[^\/]+\.json$/', $path)) { + // Schema description must be access without authentication + return $this->decodeResponse( + $this->rawCall('GET', $path, $content, false, $headers) + ); + } + + return $this->decodeResponse( + $this->rawCall('GET', $path, $content, $is_authenticated, $headers) + ); + } + + /** + * Wrap call to Ovh APIs for POST requests. + * + * @param string $path path ask inside api + * @param array $content content to send inside body of request + * @param array headers custom HTTP headers to add on the request + * @param bool is_authenticated if the request need to be authenticated + * @param null|mixed $headers + * @param mixed $is_authenticated + * + * @throws ClientException if http request is an error + */ + public function post($path, $content = null, $headers = null, $is_authenticated = true) + { + return $this->decodeResponse( + $this->rawCall('POST', $path, $content, $is_authenticated, $headers) + ); + } + + /** + * Wrap call to Ovh APIs for PUT requests. + * + * @param string $path path ask inside api + * @param array $content content to send inside body of request + * @param array headers custom HTTP headers to add on the request + * @param bool is_authenticated if the request need to be authenticated + * @param null|mixed $headers + * @param mixed $is_authenticated + * + * @throws ClientException if http request is an error + */ + public function put($path, $content, $headers = null, $is_authenticated = true) + { + return $this->decodeResponse( + $this->rawCall('PUT', $path, $content, $is_authenticated, $headers) + ); + } + + /** + * Wrap call to Ovh APIs for DELETE requests. + * + * @param string $path path ask inside api + * @param array $content content to send inside body of request + * @param array headers custom HTTP headers to add on the request + * @param bool is_authenticated if the request need to be authenticated + * @param null|mixed $headers + * @param mixed $is_authenticated + * + * @throws ClientException if http request is an error + */ + public function delete($path, $content = null, $headers = null, $is_authenticated = true) + { + return $this->decodeResponse( + $this->rawCall('DELETE', $path, $content, $is_authenticated, $headers) + ); + } + + /** + * Get the current consumer key. + */ + public function getConsumerKey(): ?string + { + return $this->consumer_key; + } + + /** + * Return instance of http client. + */ + public function getHttpClient(): ?Client + { + return $this->http_client; + } + /** * getTarget returns the URL to target given an endpoint and a path. * If the path starts with `/v1` or `/v2`, then remove the trailing `/1.0` from the endpoint. * * @param string path to use prefix from - * @return string + * @param mixed $path */ - protected function getTarget($path) : string + protected function getTarget($path): string { $endpoint = $this->endpoint; - if (substr($endpoint, -4) == '/1.0' && ( - substr($path, 0, 3) == '/v1' || - substr($path, 0, 3) == '/v2')) { - $endpoint = substr($endpoint, 0, strlen($endpoint)-4); + if ('/1.0' == substr($endpoint, -4) && ( + '/v1' == substr($path, 0, 3) + || '/v2' == substr($path, 0, 3) + )) { + $endpoint = substr($endpoint, 0, strlen($endpoint) - 4); } + return $endpoint . $path; } @@ -233,13 +306,12 @@ protected function getTarget($path) : string * This is the main method of this wrapper. It will * sign a given query and return its result. * - * @param string $method HTTP method of request (GET,POST,PUT,DELETE) - * @param string $path relative url of API request - * @param \stdClass|array|null $content body of the request - * @param bool $is_authenticated if the request use authentication + * @param string $method HTTP method of request (GET,POST,PUT,DELETE) + * @param string $path relative url of API request + * @param null|array|\stdClass $content body of the request + * @param bool $is_authenticated if the request use authentication + * @param null $headers * - * @param null $headers - * @return ResponseInterface * @throws Exceptions\InvalidParameterException * @throws GuzzleException * @throws \JsonException @@ -248,55 +320,55 @@ protected function rawCall($method, $path, $content = null, $is_authenticated = { if ($is_authenticated) { if (!isset($this->application_key)) { - throw new Exceptions\InvalidParameterException("Application key parameter is empty"); + throw new Exceptions\InvalidParameterException('Application key parameter is empty'); } if (!isset($this->application_secret)) { - throw new Exceptions\InvalidParameterException("Application secret parameter is empty"); + throw new Exceptions\InvalidParameterException('Application secret parameter is empty'); } } $url = $this->getTarget($path); $request = new Request($method, $url); - if (isset($content) && $method === 'GET') { + if (isset($content) && 'GET' === $method) { $query_string = $request->getUri()->getQuery(); $query = []; if (!empty($query_string)) { $queries = explode('&', $query_string); foreach ($queries as $element) { - $key_value_query = explode('=', $element, 2); + $key_value_query = explode('=', $element, 2); $query[$key_value_query[0]] = $key_value_query[1]; } } - $query = array_merge($query, (array)$content); + $query = array_merge($query, (array) $content); // rewrite query args to properly dump true/false parameters foreach ($query as $key => $value) { - if ($value === false) { - $query[$key] = "false"; - } elseif ($value === true) { - $query[$key] = "true"; + if (false === $value) { + $query[$key] = 'false'; + } elseif (true === $value) { + $query[$key] = 'true'; } } - $query = \GuzzleHttp\Psr7\Query::build($query); + $query = Query::build($query); $url = $request->getUri()->withQuery($query); $request = $request->withUri($url); - $body = ""; + $body = ''; } elseif (isset($content)) { $body = json_encode($content, JSON_THROW_ON_ERROR | JSON_UNESCAPED_SLASHES); $request->getBody()->write($body); } else { - $body = ""; + $body = ''; } if (!is_array($headers)) { $headers = []; } - $headers['Content-Type'] = 'application/json; charset=utf-8'; + $headers['Content-Type'] = 'application/json; charset=utf-8'; $headers['X-Ovh-Application'] = $this->application_key ?? ''; if ($is_authenticated) { @@ -308,7 +380,7 @@ protected function rawCall($method, $path, $content = null, $is_authenticated = $headers['X-Ovh-Timestamp'] = $now; if (isset($this->consumer_key)) { - $toSign = $this->application_secret . '+' . $this->consumer_key . '+' . $method + $toSign = $this->application_secret . '+' . $this->consumer_key . '+' . $method . '+' . $url . '+' . $body . '+' . $now; $signature = '$1$' . sha1($toSign); $headers['X-Ovh-Consumer'] = $this->consumer_key; @@ -316,114 +388,46 @@ protected function rawCall($method, $path, $content = null, $is_authenticated = } } - /** @var Response $response */ + /* + * @var Response $response + */ return $this->http_client->send($request, ['headers' => $headers]); } /** - * Decode a Response object body to an Array - * - * @param Response $response - * - * @throws \JsonException - */ - private function decodeResponse(Response $response) - { - if ($response->getStatusCode() === 204 || $response->getBody()->getSize() === 0) { - return null; - } - return json_decode($response->getBody(), true, 512, JSON_THROW_ON_ERROR); - } - - /** - * Wrap call to Ovh APIs for GET requests + * Calculate time delta between local machine and API's server. * - * @param string $path path ask inside api - * @param array $content content to send inside body of request - * @param array headers custom HTTP headers to add on the request - * @param bool is_authenticated if the request need to be authenticated + * @return int * * @throws ClientException if http request is an error - * @throws \JsonException */ - public function get($path, $content = null, $headers = null, $is_authenticated = true) + private function calculateTimeDelta() { - if (preg_match('/^\/[^\/]+\.json$/', $path)) { - // Schema description must be access without authentication - return $this->decodeResponse( - $this->rawCall("GET", $path, $content, false, $headers) + if (!isset($this->time_delta)) { + $response = $this->rawCall( + 'GET', + '/auth/time', + null, + false ); + $serverTimestamp = (int) (string) $response->getBody(); + $this->time_delta = $serverTimestamp - (int) \time(); } - return $this->decodeResponse( - $this->rawCall("GET", $path, $content, $is_authenticated, $headers) - ); - } - - /** - * Wrap call to Ovh APIs for POST requests - * - * @param string $path path ask inside api - * @param array $content content to send inside body of request - * @param array headers custom HTTP headers to add on the request - * @param bool is_authenticated if the request need to be authenticated - * - * @throws ClientException if http request is an error - */ - public function post($path, $content = null, $headers = null, $is_authenticated = true) - { - return $this->decodeResponse( - $this->rawCall("POST", $path, $content, $is_authenticated, $headers) - ); - } - - /** - * Wrap call to Ovh APIs for PUT requests - * - * @param string $path path ask inside api - * @param array $content content to send inside body of request - * @param array headers custom HTTP headers to add on the request - * @param bool is_authenticated if the request need to be authenticated - * - * @throws ClientException if http request is an error - */ - public function put($path, $content, $headers = null, $is_authenticated = true) - { - return $this->decodeResponse( - $this->rawCall("PUT", $path, $content, $is_authenticated, $headers) - ); + return $this->time_delta; } /** - * Wrap call to Ovh APIs for DELETE requests + * Decode a Response object body to an Array. * - * @param string $path path ask inside api - * @param array $content content to send inside body of request - * @param array headers custom HTTP headers to add on the request - * @param bool is_authenticated if the request need to be authenticated - * - * @throws ClientException if http request is an error - */ - public function delete($path, $content = null, $headers = null, $is_authenticated = true) - { - return $this->decodeResponse( - $this->rawCall("DELETE", $path, $content, $is_authenticated, $headers) - ); - } - - /** - * Get the current consumer key + * @throws \JsonException */ - public function getConsumerKey(): ?string + private function decodeResponse(Response $response) { - return $this->consumer_key; - } + if (204 === $response->getStatusCode() || 0 === $response->getBody()->getSize()) { + return null; + } - /** - * Return instance of http client - */ - public function getHttpClient(): ?Client - { - return $this->http_client; + return json_decode($response->getBody(), true, 512, JSON_THROW_ON_ERROR); } } diff --git a/src/Exceptions/ApiException.php b/src/Exceptions/ApiException.php index 7696466..00760d9 100644 --- a/src/Exceptions/ApiException.php +++ b/src/Exceptions/ApiException.php @@ -1,31 +1,35 @@ = 400) * - * @package Ovh * @category Exceptions */ -class ApiException extends Exception +class ApiException extends \Exception { } diff --git a/src/Exceptions/InvalidParameterException.php b/src/Exceptions/InvalidParameterException.php index e9c2e5e..c28e127 100644 --- a/src/Exceptions/InvalidParameterException.php +++ b/src/Exceptions/InvalidParameterException.php @@ -1,31 +1,35 @@ markTestSkipped("Skip test due to missing $envName variable"); + $this->markTestSkipped("Skip test due to missing {$envName} variable"); + return; } } @@ -111,39 +117,7 @@ protected function setUp() :void } /** - * Get private and protected method to unit test it - * - * @param string $name - * - * @return \ReflectionMethod - */ - protected static function getPrivateMethod($name) - { - $class = new \ReflectionClass(\Ovh\Api::class); - $method = $class->getMethod($name); - $method->setAccessible(true); - - return $method; - } - - /** - * Get private and protected property to unit test it - * - * @param string $name - * - * @return \ReflectionProperty - */ - protected static function getPrivateProperty($name) - { - $class = new \ReflectionClass(\Ovh\Api::class); - $property = $class->getProperty($name); - $property->setAccessible(true); - - return $property; - } - - /** - * Test if result contains consumerKey and validationUrl + * Test if result contains consumerKey and validationUrl. */ public function testIfConsumerKeyIsReplace() { @@ -158,12 +132,12 @@ public function testIfConsumerKeyIsReplace() $credentials = $this->api->requestCredentials($accessRules); $consumer_key = $property->getValue($this->api); - $this->assertSame($consumer_key, $credentials["consumerKey"]); + $this->assertSame($consumer_key, $credentials['consumerKey']); $this->assertNotEquals($consumer_key, $this->consumer_key); } /** - * Test if post request on me + * Test if post request on me. */ public function testPostRestrictionAccessIp() { @@ -172,15 +146,15 @@ public function testPostRestrictionAccessIp() ); $this->assertNull( - $this->api->post('/me/accessRestriction/ip', ['ip' => $this->alternativeRangeIP, - 'rule' => 'deny', - 'warning' => true, + $this->api->post('/me/accessRestriction/ip', ['ip' => $this->alternativeRangeIP, + 'rule' => 'deny', + 'warning' => true, ]) ); } /** - * Test if get request on /me + * Test if get request on /me. */ public function testGetRestrictionAccessIP() { @@ -199,7 +173,7 @@ public function testGetRestrictionAccessIP() } /** - * Test if delete request on /me + * Test if delete request on /me. */ public function testPutRestrictionAccessIP() { @@ -208,7 +182,7 @@ public function testPutRestrictionAccessIP() foreach ($result as $restrictionId) { $restriction = $this->api->get('/me/accessRestriction/ip/' . $restrictionId); - if (in_array($restriction["ip"], [$this->rangeIP, $this->alternativeRangeIP])) { + if (in_array($restriction['ip'], [$this->rangeIP, $this->alternativeRangeIP])) { $this->assertNull( $this->api->put('/me/accessRestriction/ip/' . $restrictionId, ['rule' => 'accept', 'warning' => true]) ); @@ -220,7 +194,7 @@ public function testPutRestrictionAccessIP() } /** - * Test if delete request on /me + * Test if delete request on /me. */ public function testDeleteRestrictionAccessIP() { @@ -228,7 +202,7 @@ public function testDeleteRestrictionAccessIP() foreach ($result as $restrictionId) { $restriction = $this->api->get('/me/accessRestriction/ip/' . $restrictionId); - if (in_array($restriction["ip"], [$this->rangeIP, $this->alternativeRangeIP])) { + if (in_array($restriction['ip'], [$this->rangeIP, $this->alternativeRangeIP])) { $result = $this->api->delete('/me/accessRestriction/ip/' . $restrictionId); $this->assertNull($result); } @@ -236,18 +210,18 @@ public function testDeleteRestrictionAccessIP() } /** - * Test if request without authentication works + * Test if request without authentication works. */ public function testIfRequestWithoutAuthenticationWorks() { $api = new Api($this->application_key, $this->application_secret, $this->endpoint, null, $this->client); $invoker = self::getPrivateMethod('rawCall'); - $result = $invoker->invokeArgs($api, ['GET', '/xdsl/incidents']); + $result = $invoker->invokeArgs($api, ['GET', '/xdsl/incidents']); $this->assertIsObject($result); } /** - * Test Api::get + * Test Api::get. */ public function testApiGetWithParameters() { @@ -257,7 +231,7 @@ public function testApiGetWithParameters() } /** - * Test Api::get, should build valide signature + * Test Api::get, should build valide signature. */ public function testApiGetWithQueryString() { @@ -266,12 +240,44 @@ public function testApiGetWithQueryString() } /** - * Test APi::get without authentication + * Test APi::get without authentication. */ public function testApiGetWithoutAuthentication() { - $api = new Api(null, null, $this->endpoint, null, $this->client); + $api = new Api(null, null, $this->endpoint, null, $this->client); $result = $api->get('/hosting/web/moduleList', null, null, false); $this->assertIsArray($result); } + + /** + * Get private and protected method to unit test it. + * + * @param string $name + * + * @return \ReflectionMethod + */ + protected static function getPrivateMethod($name) + { + $class = new \ReflectionClass(Api::class); + $method = $class->getMethod($name); + $method->setAccessible(true); + + return $method; + } + + /** + * Get private and protected property to unit test it. + * + * @param string $name + * + * @return \ReflectionProperty + */ + protected static function getPrivateProperty($name) + { + $class = new \ReflectionClass(Api::class); + $property = $class->getProperty($name); + $property->setAccessible(true); + + return $property; + } } diff --git a/tests/ApiTest.php b/tests/ApiTest.php index 585f32e..84a9235 100644 --- a/tests/ApiTest.php +++ b/tests/ApiTest.php @@ -1,29 +1,32 @@ calls); $handlerStack = HandlerStack::create($mock); @@ -63,31 +63,18 @@ public function __construct(...$responses) } /** - * Test Api class + * Test Api class. * - * @package Ovh * @category Ovh + * + * @internal + * + * @coversNothing */ class ApiTest extends TestCase { /** - * Get private and protected property to unit test it - * - * @param string $name - * - * @return \ReflectionProperty - */ - protected static function getPrivateProperty($name) - { - $class = new \ReflectionClass(\Ovh\Api::class); - $property = $class->getProperty($name); - $property->setAccessible(true); - - return $property; - } - - /** - * Test missing $application_key + * Test missing $application_key. */ public function testMissingApplicationKey() { @@ -98,7 +85,7 @@ public function testMissingApplicationKey() } /** - * Test missing $application_secret + * Test missing $application_secret. */ public function testMissingApplicationSecret() { @@ -109,14 +96,14 @@ public function testMissingApplicationSecret() } /** - * Test we don't check Application Key for unauthenticated call + * Test we don't check Application Key for unauthenticated call. */ public function testNoCheckAppKeyForUnauthCall() { $client = new MockClient(new Response(200, [], '{}')); $api = new Api(null, null, 'ovh-eu', null, $client); - $api->get("/me", null, null, false); + $api->get('/me', null, null, false); $calls = $client->calls; $this->assertCount(1, $calls); @@ -128,7 +115,7 @@ public function testNoCheckAppKeyForUnauthCall() } /** - * Test missing $api_endpoint + * Test missing $api_endpoint. */ public function testMissingApiEndpoint() { @@ -138,7 +125,7 @@ public function testMissingApiEndpoint() } /** - * Test bad $api_endpoint + * Test bad $api_endpoint. */ public function testBadApiEndpoint() { @@ -148,7 +135,7 @@ public function testBadApiEndpoint() } /** - * Test creating Client if none is provided + * Test creating Client if none is provided. */ public function testClientCreation() { @@ -157,7 +144,7 @@ public function testClientCreation() } /** - * Test the compute of time delta + * Test the compute of time delta. */ public function testTimeDeltaCompute() { @@ -167,9 +154,9 @@ public function testTimeDeltaCompute() ); $api = new Api(MOCK_APPLICATION_KEY, MOCK_APPLICATION_SECRET, 'ovh-eu', MOCK_CONSUMER_KEY, $client); - $api->get("/me"); + $api->get('/me'); - $property = self::getPrivateProperty('time_delta'); + $property = self::getPrivateProperty('time_delta'); $time_delta = $property->getValue($api); $this->assertSame('-10', $time_delta); @@ -186,7 +173,7 @@ public function testTimeDeltaCompute() } /** - * Test if consumer key is replaced + * Test if consumer key is replaced. */ public function testIfConsumerKeyIsReplace() { @@ -217,7 +204,7 @@ public function testIfConsumerKeyIsReplace() } /** - * Test invalid applicationKey + * Test invalid applicationKey. */ public function testInvalidApplicationKey() { @@ -233,7 +220,7 @@ public function testInvalidApplicationKey() } /** - * Test invalid rights + * Test invalid rights. */ public function testInvalidRight() { @@ -254,9 +241,8 @@ public function testGetConsumerKey() $this->assertSame(MOCK_CONSUMER_KEY, $api->getConsumerKey()); } - /** - * Test GET query args + * Test GET query args. */ public function testGetQueryArgs() { @@ -274,14 +260,14 @@ public function testGetQueryArgs() } /** - * Test GET overlapping query args + * Test GET overlapping query args. */ public function testGetOverlappingQueryArgs() { $client = new MockClient(new Response(200, [], '{}')); $api = new Api(MOCK_APPLICATION_KEY, MOCK_APPLICATION_SECRET, 'ovh-eu', MOCK_CONSUMER_KEY, $client); - $api->get('/me/api/credential?applicationId=49&status=pendingValidation', ['status' => 'expired', 'test' => "success"], null, false); + $api->get('/me/api/credential?applicationId=49&status=pendingValidation', ['status' => 'expired', 'test' => 'success'], null, false); $calls = $client->calls; $this->assertCount(1, $calls); @@ -292,7 +278,7 @@ public function testGetOverlappingQueryArgs() } /** - * Test GET boolean query args + * Test GET boolean query args. */ public function testGetBooleanQueryArgs() { @@ -310,14 +296,14 @@ public function testGetBooleanQueryArgs() } /** - * Test valid provided endpoint + * Test valid provided endpoint. */ public function testProvidedUrl() { foreach ([ - ['endpoint' => 'http://api.ovh.com/1.0', 'expectedUrl' => 'http://api.ovh.com/1.0'], + ['endpoint' => 'http://api.ovh.com/1.0', 'expectedUrl' => 'http://api.ovh.com/1.0'], ['endpoint' => 'https://api.ovh.com/1.0', 'expectedUrl' => 'https://api.ovh.com/1.0'], - ['endpoint' => 'ovh-eu', 'expectedUrl' => 'https://eu.api.ovh.com/1.0'], + ['endpoint' => 'ovh-eu', 'expectedUrl' => 'https://eu.api.ovh.com/1.0'], ] as $test) { $client = new MockClient(new Response(200, [], '{}')); @@ -334,7 +320,7 @@ public function testProvidedUrl() } /** - * Test missing header X-OVH-Application on requestCredentials + * Test missing header X-OVH-Application on requestCredentials. */ public function testMissingOvhApplicationHeaderOnRequestCredentials() { @@ -366,13 +352,13 @@ public function testCallSignature() // GET /auth/time $mocks = [new Response(200, [], MOCK_TIME)]; // (GET,POST,PUT,DELETE) x (/auth,/unauth) - for ($i = 0; $i < 8; $i++) { + for ($i = 0; $i < 8; ++$i) { $mocks[] = new Response(200, [], '{}'); } $client = new MockClient(...$mocks); - $api = new Api(MOCK_APPLICATION_KEY, MOCK_APPLICATION_SECRET, 'ovh-eu', MOCK_CONSUMER_KEY, $client); - $body = ["a" => "b", "c" => "d"]; + $api = new Api(MOCK_APPLICATION_KEY, MOCK_APPLICATION_SECRET, 'ovh-eu', MOCK_CONSUMER_KEY, $client); + $body = ['a' => 'b', 'c' => 'd']; // Authenticated calls $api->get('/auth'); @@ -394,9 +380,9 @@ public function testCallSignature() $this->assertSame('https://eu.api.ovh.com/1.0/auth/time', $req->getUri()->__toString()); foreach ([ - 1 => ['method' => 'GET', 'sig' => '$1$e9556054b6309771395efa467c22e627407461ad'], - 2 => ['method' => 'POST', 'sig' => '$1$ec2fb5c7a81f64723c77d2e5b609ae6f58a84fc1'], - 3 => ['method' => 'PUT', 'sig' => '$1$8a75a9e7c8e7296c9dbeda6a2a735eb6bd58ec4b'], + 1 => ['method' => 'GET', 'sig' => '$1$e9556054b6309771395efa467c22e627407461ad'], + 2 => ['method' => 'POST', 'sig' => '$1$ec2fb5c7a81f64723c77d2e5b609ae6f58a84fc1'], + 3 => ['method' => 'PUT', 'sig' => '$1$8a75a9e7c8e7296c9dbeda6a2a735eb6bd58ec4b'], 4 => ['method' => 'DELETE', 'sig' => '$1$a1eecd00b3b02b6cf5708b84b9ff42059a950d85'], ] as $i => $test) { $req = $calls[$i]['request']; @@ -406,7 +392,7 @@ public function testCallSignature() $this->assertSame(MOCK_CONSUMER_KEY, $req->getHeaderLine('X-Ovh-Consumer')); $this->assertSame(MOCK_TIME, $req->getHeaderLine('X-Ovh-Timestamp')); $this->assertSame($test['sig'], $req->getHeaderLine('X-Ovh-Signature')); - if ($test['method'] == 'POST' || $test['method'] == 'PUT') { + if ('POST' == $test['method'] || 'PUT' == $test['method']) { $this->assertSame('application/json; charset=utf-8', $req->getHeaderLine('Content-Type')); } } @@ -419,7 +405,7 @@ public function testCallSignature() $this->assertNotTrue($req->hasHeader('X-Ovh-Consumer')); $this->assertNotTrue($req->hasHeader('X-Ovh-Timestamp')); $this->assertNotTrue($req->hasHeader('X-Ovh-Signature')); - if ($method == 'POST' || $method == 'PUT') { + if ('POST' == $method || 'PUT' == $method) { $this->assertSame('application/json; charset=utf-8', $req->getHeaderLine('Content-Type')); } } @@ -430,7 +416,7 @@ public function testVersionInUrl() // GET /auth/time $mocks = [new Response(200, [], MOCK_TIME)]; // GET) x (/1.0/call,/v1/call,/v2/call) - for ($i = 0; $i < 3; $i++) { + for ($i = 0; $i < 3; ++$i) { $mocks[] = new Response(200, [], '{}'); } $client = new MockClient(...$mocks); @@ -450,8 +436,8 @@ public function testVersionInUrl() foreach ([ 1 => ['path' => '1.0/call', 'sig' => '$1$7f2db49253edfc41891023fcd1a54cf61db05fbb'], - 2 => ['path' => 'v1/call', 'sig' => '$1$e6e7906d385eb28adcbfbe6b66c1528a42d741ad'], - 3 => ['path' => 'v2/call', 'sig' => '$1$bb63b132a6f84ad5433d0c534d48d3f7c3804285'], + 2 => ['path' => 'v1/call', 'sig' => '$1$e6e7906d385eb28adcbfbe6b66c1528a42d741ad'], + 3 => ['path' => 'v2/call', 'sig' => '$1$bb63b132a6f84ad5433d0c534d48d3f7c3804285'], ] as $i => $test) { $req = $calls[$i]['request']; $this->assertSame('GET', $req->getMethod()); @@ -472,7 +458,7 @@ public function testEmptyResponseBody() new Response(204, [], ''), ); - $api = new Api(MOCK_APPLICATION_KEY, MOCK_APPLICATION_SECRET, 'ovh-eu', MOCK_CONSUMER_KEY, $client); + $api = new Api(MOCK_APPLICATION_KEY, MOCK_APPLICATION_SECRET, 'ovh-eu', MOCK_CONSUMER_KEY, $client); $response = $api->post('/domain/zone/nonexisting.ovh/refresh'); $this->assertSame(null, $response); @@ -487,4 +473,20 @@ public function testEmptyResponseBody() $this->assertSame('POST', $req->getMethod()); $this->assertSame('https://eu.api.ovh.com/1.0/domain/zone/nonexisting.ovh/refresh', $req->getUri()->__toString()); } + + /** + * Get private and protected property to unit test it. + * + * @param string $name + * + * @return \ReflectionProperty + */ + protected static function getPrivateProperty($name) + { + $class = new \ReflectionClass(Api::class); + $property = $class->getProperty($name); + $property->setAccessible(true); + + return $property; + } } diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 84fd0c3..e4199df 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -1,28 +1,31 @@