diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ec0f4af..1dd3f53a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,20 @@ +# 5.0.0 + +## BC Breaks + +Use PSR-7, PSR-17 and PSR-18 instead of HttpPlug. + +- Change the type of the first parameter of `Akeneo\Pim\ApiClientAkeneoPimClientBuilder::setHttpClient` from `Http\Client\HttpClient` to `Psr\Http\Client\ClientInterface` +- Change the type of the first parameter of `Akeneo\Pim\ApiClientAkeneoPimClientBuilder::setRequestFactory` from `Http\Message\RequestFactory` to `Psr\Http\Message\RequestFactoryInterface` +- Change the type of the first parameter of `Akeneo\Pim\ApiClientAkeneoPimClientBuilder::setStreamFactory` from `Http\Message\StreamFactory` to `Psr\Http\Message\StreamFactoryInterface` + +Factory implementations are necessary as dependency. +For example, with Guzzle: + +```bash +$ php composer.phar require akeneo/api-php-client php-http/guzzle6-adapter:^2.0 http-interop/http-factory-guzzle:^1.0 +``` + # 4.0.0 (2019-02-15) ## BC Breaks @@ -6,6 +23,8 @@ Drop support for PHP 5.6, PHP 7.0 and PHP 7.1 Change the response type from `StreamInterface` to `Response` for `\Akeneo\Pim\ApiClient\Api\MediaFileApiInterface::download` +It allows to get the filename from the response, and also the Mime type. + # 3.0.0 (2018-06-26) # 2.0.1 (2018-05-03) diff --git a/composer.json b/composer.json index 82a03042..28a37d98 100644 --- a/composer.json +++ b/composer.json @@ -22,12 +22,12 @@ "require": { "php": ">=7.2", "psr/http-message": "^1.0", + "psr/http-client": "^1.0", + "psr/http-factory": "^1.0", + "psr/http-message-implementation": "^1.0", "php-http/httplug": "^2.0", - "php-http/message": "^1.7", "php-http/discovery": "^1.6", - "php-http/message-factory": "^v1.0", - "php-http/multipart-stream-builder": "^1.0", - "php-http/client-implementation": "^1.0" + "php-http/multipart-stream-builder": "^1.0" }, "require-dev": { "friendsofphp/php-cs-fixer": "^2.14", @@ -35,6 +35,7 @@ "phpspec/phpspec": "^5.0", "symfony/yaml": "^4.2", "donatj/mock-webserver": "^2.0", + "http-interop/http-factory-guzzle": "^1.0", "php-http/guzzle6-adapter": "^2.0" }, "config": { diff --git a/composer.lock b/composer.lock index 7c061d99..c4bf8257 100644 --- a/composer.lock +++ b/composer.lock @@ -4,176 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "6db2187b9934fc1bd7e022ab4c2e3f52", + "content-hash": "5b83210adcac7fe2f6192262d368cadb", "packages": [ - { - "name": "clue/stream-filter", - "version": "v1.4.0", - "source": { - "type": "git", - "url": "https://github.com/clue/php-stream-filter.git", - "reference": "d80fdee9b3a7e0d16fc330a22f41f3ad0eeb09d0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/clue/php-stream-filter/zipball/d80fdee9b3a7e0d16fc330a22f41f3ad0eeb09d0", - "reference": "d80fdee9b3a7e0d16fc330a22f41f3ad0eeb09d0", - "shasum": "" - }, - "require": { - "php": ">=5.3" - }, - "require-dev": { - "phpunit/phpunit": "^5.0 || ^4.8" - }, - "type": "library", - "autoload": { - "psr-4": { - "Clue\\StreamFilter\\": "src/" - }, - "files": [ - "src/functions.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Christian Lück", - "email": "christian@lueck.tv" - } - ], - "description": "A simple and modern approach to stream filtering in PHP", - "homepage": "https://github.com/clue/php-stream-filter", - "keywords": [ - "bucket brigade", - "callback", - "filter", - "php_user_filter", - "stream", - "stream_filter_append", - "stream_filter_register" - ], - "time": "2017-08-18T09:54:01+00:00" - }, - { - "name": "guzzlehttp/guzzle", - "version": "6.3.3", - "source": { - "type": "git", - "url": "https://github.com/guzzle/guzzle.git", - "reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/407b0cb880ace85c9b63c5f9551db498cb2d50ba", - "reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba", - "shasum": "" - }, - "require": { - "guzzlehttp/promises": "^1.0", - "guzzlehttp/psr7": "^1.4", - "php": ">=5.5" - }, - "require-dev": { - "ext-curl": "*", - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0", - "psr/log": "^1.0" - }, - "suggest": { - "psr/log": "Required for using the Log middleware" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "6.3-dev" - } - }, - "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" - ], - "time": "2018-04-22T15:46:56+00:00" - }, - { - "name": "guzzlehttp/promises", - "version": "v1.3.1", - "source": { - "type": "git", - "url": "https://github.com/guzzle/promises.git", - "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/a59da6cf61d80060647ff4d3eb2c03a2bc694646", - "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646", - "shasum": "" - }, - "require": { - "php": ">=5.5.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4-dev" - } - }, - "autoload": { - "psr-4": { - "GuzzleHttp\\Promise\\": "src/" - }, - "files": [ - "src/functions_include.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - } - ], - "description": "Guzzle promises library", - "keywords": [ - "promise" - ], - "time": "2016-12-20T10:07:11+00:00" - }, { "name": "guzzlehttp/psr7", "version": "1.5.2", @@ -243,16 +75,16 @@ }, { "name": "php-http/discovery", - "version": "1.6.0", + "version": "1.6.1", "source": { "type": "git", "url": "https://github.com/php-http/discovery.git", - "reference": "02b7ea21eafa0757af04140890a67d8ed45f83b2" + "reference": "684855f2c2e9d0a61868b8f8d6bd0295c8a4b651" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-http/discovery/zipball/02b7ea21eafa0757af04140890a67d8ed45f83b2", - "reference": "02b7ea21eafa0757af04140890a67d8ed45f83b2", + "url": "https://api.github.com/repos/php-http/discovery/zipball/684855f2c2e9d0a61868b8f8d6bd0295c8a4b651", + "reference": "684855f2c2e9d0a61868b8f8d6bd0295c8a4b651", "shasum": "" }, "require": { @@ -303,70 +135,7 @@ "message", "psr7" ], - "time": "2019-01-23T12:41:22+00:00" - }, - { - "name": "php-http/guzzle6-adapter", - "version": "v2.0.1", - "source": { - "type": "git", - "url": "https://github.com/php-http/guzzle6-adapter.git", - "reference": "6074a4b1f4d5c21061b70bab3b8ad484282fe31f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-http/guzzle6-adapter/zipball/6074a4b1f4d5c21061b70bab3b8ad484282fe31f", - "reference": "6074a4b1f4d5c21061b70bab3b8ad484282fe31f", - "shasum": "" - }, - "require": { - "guzzlehttp/guzzle": "^6.0", - "php": "^7.1", - "php-http/httplug": "^2.0", - "psr/http-client": "^1.0" - }, - "provide": { - "php-http/async-client-implementation": "1.0", - "php-http/client-implementation": "1.0", - "psr/http-client-implementation": "1.0" - }, - "require-dev": { - "ext-curl": "*", - "php-http/client-integration-tests": "^2.0", - "phpunit/phpunit": "^7.4" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.x-dev" - } - }, - "autoload": { - "psr-4": { - "Http\\Adapter\\Guzzle6\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Márk Sági-Kazár", - "email": "mark.sagikazar@gmail.com" - }, - { - "name": "David de Boer", - "email": "david@ddeboer.nl" - } - ], - "description": "Guzzle 6 HTTP Adapter", - "homepage": "http://httplug.io", - "keywords": [ - "Guzzle", - "http" - ], - "time": "2018-12-16T14:44:03+00:00" + "time": "2019-02-23T07:42:53+00:00" }, { "name": "php-http/httplug", @@ -425,78 +194,6 @@ ], "time": "2018-10-31T09:14:44+00:00" }, - { - "name": "php-http/message", - "version": "1.7.2", - "source": { - "type": "git", - "url": "https://github.com/php-http/message.git", - "reference": "b159ffe570dffd335e22ef0b91a946eacb182fa1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-http/message/zipball/b159ffe570dffd335e22ef0b91a946eacb182fa1", - "reference": "b159ffe570dffd335e22ef0b91a946eacb182fa1", - "shasum": "" - }, - "require": { - "clue/stream-filter": "^1.4", - "php": "^5.4 || ^7.0", - "php-http/message-factory": "^1.0.2", - "psr/http-message": "^1.0" - }, - "provide": { - "php-http/message-factory-implementation": "1.0" - }, - "require-dev": { - "akeneo/phpspec-skip-example-extension": "^1.0", - "coduo/phpspec-data-provider-extension": "^1.0", - "ext-zlib": "*", - "guzzlehttp/psr7": "^1.0", - "henrikbjorn/phpspec-code-coverage": "^1.0", - "phpspec/phpspec": "^2.4", - "slim/slim": "^3.0", - "zendframework/zend-diactoros": "^1.0" - }, - "suggest": { - "ext-zlib": "Used with compressor/decompressor streams", - "guzzlehttp/psr7": "Used with Guzzle PSR-7 Factories", - "slim/slim": "Used with Slim Framework PSR-7 implementation", - "zendframework/zend-diactoros": "Used with Diactoros Factories" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.6-dev" - } - }, - "autoload": { - "psr-4": { - "Http\\Message\\": "src/" - }, - "files": [ - "src/filters.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Márk Sági-Kazár", - "email": "mark.sagikazar@gmail.com" - } - ], - "description": "HTTP Message related tools", - "homepage": "http://php-http.org", - "keywords": [ - "http", - "message", - "psr-7" - ], - "time": "2018-11-01T09:32:41+00:00" - }, { "name": "php-http/message-factory", "version": "v1.0.2", @@ -639,37 +336,86 @@ ], "authors": [ { - "name": "Márk Sági-Kazár", - "email": "mark.sagikazar@gmail.com" - }, - { - "name": "Joel Wurtz", - "email": "joel.wurtz@gmail.com" + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" + }, + { + "name": "Joel Wurtz", + "email": "joel.wurtz@gmail.com" + } + ], + "description": "Promise used for asynchronous HTTP requests", + "homepage": "http://httplug.io", + "keywords": [ + "promise" + ], + "time": "2016-01-26T13:27:02+00:00" + }, + { + "name": "psr/http-client", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-client.git", + "reference": "496a823ef742b632934724bf769560c2a5c7c44e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/496a823ef742b632934724bf769560c2a5c7c44e", + "reference": "496a823ef742b632934724bf769560c2a5c7c44e", + "shasum": "" + }, + "require": { + "php": "^7.0", + "psr/http-message": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" } ], - "description": "Promise used for asynchronous HTTP requests", - "homepage": "http://httplug.io", + "description": "Common interface for HTTP clients", + "homepage": "https://github.com/php-fig/http-client", "keywords": [ - "promise" + "http", + "http-client", + "psr", + "psr-18" ], - "time": "2016-01-26T13:27:02+00:00" + "time": "2018-10-30T23:29:13+00:00" }, { - "name": "psr/http-client", + "name": "psr/http-factory", "version": "1.0.0", "source": { "type": "git", - "url": "https://github.com/php-fig/http-client.git", - "reference": "496a823ef742b632934724bf769560c2a5c7c44e" + "url": "https://github.com/php-fig/http-factory.git", + "reference": "378bfe27931ecc54ff824a20d6f6bfc303bbd04c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-client/zipball/496a823ef742b632934724bf769560c2a5c7c44e", - "reference": "496a823ef742b632934724bf769560c2a5c7c44e", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/378bfe27931ecc54ff824a20d6f6bfc303bbd04c", + "reference": "378bfe27931ecc54ff824a20d6f6bfc303bbd04c", "shasum": "" }, "require": { - "php": "^7.0", + "php": ">=7.0.0", "psr/http-message": "^1.0" }, "type": "library", @@ -680,7 +426,7 @@ }, "autoload": { "psr-4": { - "Psr\\Http\\Client\\": "src/" + "Psr\\Http\\Message\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -693,15 +439,18 @@ "homepage": "http://www.php-fig.org/" } ], - "description": "Common interface for HTTP clients", - "homepage": "https://github.com/php-fig/http-client", + "description": "Common interfaces for PSR-7 HTTP message factories", "keywords": [ + "factory", "http", - "http-client", + "message", "psr", - "psr-18" + "psr-17", + "psr-7", + "request", + "response" ], - "time": "2018-10-30T23:29:13+00:00" + "time": "2018-07-30T21:54:04+00:00" }, { "name": "psr/http-message", @@ -797,16 +546,16 @@ "packages-dev": [ { "name": "composer/semver", - "version": "1.4.2", + "version": "1.5.0", "source": { "type": "git", "url": "https://github.com/composer/semver.git", - "reference": "c7cb9a2095a074d131b65a8a0cd294479d785573" + "reference": "46d9139568ccb8d9e7cdd4539cab7347568a5e2e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/semver/zipball/c7cb9a2095a074d131b65a8a0cd294479d785573", - "reference": "c7cb9a2095a074d131b65a8a0cd294479d785573", + "url": "https://api.github.com/repos/composer/semver/zipball/46d9139568ccb8d9e7cdd4539cab7347568a5e2e", + "reference": "46d9139568ccb8d9e7cdd4539cab7347568a5e2e", "shasum": "" }, "require": { @@ -855,7 +604,7 @@ "validation", "versioning" ], - "time": "2016-08-30T16:08:34+00:00" + "time": "2019-03-19T17:25:45+00:00" }, { "name": "composer/xdebug-handler", @@ -903,16 +652,16 @@ }, { "name": "doctrine/annotations", - "version": "v1.6.0", + "version": "v1.6.1", "source": { "type": "git", "url": "https://github.com/doctrine/annotations.git", - "reference": "c7f2050c68a9ab0bdb0f98567ec08d80ea7d24d5" + "reference": "53120e0eb10355388d6ccbe462f1fea34ddadb24" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/annotations/zipball/c7f2050c68a9ab0bdb0f98567ec08d80ea7d24d5", - "reference": "c7f2050c68a9ab0bdb0f98567ec08d80ea7d24d5", + "url": "https://api.github.com/repos/doctrine/annotations/zipball/53120e0eb10355388d6ccbe462f1fea34ddadb24", + "reference": "53120e0eb10355388d6ccbe462f1fea34ddadb24", "shasum": "" }, "require": { @@ -967,31 +716,33 @@ "docblock", "parser" ], - "time": "2017-12-06T07:11:42+00:00" + "time": "2019-03-25T19:12:02+00:00" }, { "name": "doctrine/instantiator", - "version": "1.1.0", + "version": "1.2.0", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda" + "reference": "a2c590166b2133a4633738648b6b064edae0814a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda", - "reference": "185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/a2c590166b2133a4633738648b6b064edae0814a", + "reference": "a2c590166b2133a4633738648b6b064edae0814a", "shasum": "" }, "require": { "php": "^7.1" }, "require-dev": { - "athletic/athletic": "~0.1.8", + "doctrine/coding-standard": "^6.0", "ext-pdo": "*", "ext-phar": "*", - "phpunit/phpunit": "^6.2.3", - "squizlabs/php_codesniffer": "^3.0.2" + "phpbench/phpbench": "^0.13", + "phpstan/phpstan-phpunit": "^0.11", + "phpstan/phpstan-shim": "^0.11", + "phpunit/phpunit": "^7.0" }, "type": "library", "extra": { @@ -1016,12 +767,12 @@ } ], "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", - "homepage": "https://github.com/doctrine/instantiator", + "homepage": "https://www.doctrine-project.org/projects/instantiator.html", "keywords": [ "constructor", "instantiate" ], - "time": "2017-07-22T11:58:36+00:00" + "time": "2019-03-17T17:37:11+00:00" }, { "name": "doctrine/lexer", @@ -1123,16 +874,16 @@ }, { "name": "friendsofphp/php-cs-fixer", - "version": "v2.14.1", + "version": "v2.14.2", "source": { "type": "git", "url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git", - "reference": "2e82abd1322897eb8aacb861e5ff551af3888349" + "reference": "ff401e58261ffc5934a58f795b3f95b355e276cb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/2e82abd1322897eb8aacb861e5ff551af3888349", - "reference": "2e82abd1322897eb8aacb861e5ff551af3888349", + "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/ff401e58261ffc5934a58f795b3f95b355e276cb", + "reference": "ff401e58261ffc5934a58f795b3f95b355e276cb", "shasum": "" }, "require": { @@ -1153,9 +904,6 @@ "symfony/process": "^3.0 || ^4.0", "symfony/stopwatch": "^3.0 || ^4.0" }, - "conflict": { - "hhvm": "*" - }, "require-dev": { "johnkary/phpunit-speedtrap": "^1.1 || ^2.0 || ^3.0", "justinrainbow/json-schema": "^5.0", @@ -1210,20 +958,186 @@ } ], "description": "A tool to automatically fix PHP code style", - "time": "2019-02-10T22:52:33+00:00" + "time": "2019-02-17T17:44:13+00:00" + }, + { + "name": "guzzlehttp/guzzle", + "version": "6.3.3", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle.git", + "reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/407b0cb880ace85c9b63c5f9551db498cb2d50ba", + "reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba", + "shasum": "" + }, + "require": { + "guzzlehttp/promises": "^1.0", + "guzzlehttp/psr7": "^1.4", + "php": ">=5.5" + }, + "require-dev": { + "ext-curl": "*", + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0", + "psr/log": "^1.0" + }, + "suggest": { + "psr/log": "Required for using the Log middleware" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "6.3-dev" + } + }, + "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" + ], + "time": "2018-04-22T15:46:56+00:00" + }, + { + "name": "guzzlehttp/promises", + "version": "v1.3.1", + "source": { + "type": "git", + "url": "https://github.com/guzzle/promises.git", + "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/promises/zipball/a59da6cf61d80060647ff4d3eb2c03a2bc694646", + "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646", + "shasum": "" + }, + "require": { + "php": ">=5.5.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Promise\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Guzzle promises library", + "keywords": [ + "promise" + ], + "time": "2016-12-20T10:07:11+00:00" + }, + { + "name": "http-interop/http-factory-guzzle", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/http-interop/http-factory-guzzle.git", + "reference": "34861658efb9899a6618cef03de46e2a52c80fc0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/http-interop/http-factory-guzzle/zipball/34861658efb9899a6618cef03de46e2a52c80fc0", + "reference": "34861658efb9899a6618cef03de46e2a52c80fc0", + "shasum": "" + }, + "require": { + "guzzlehttp/psr7": "^1.4.2", + "psr/http-factory": "^1.0" + }, + "provide": { + "psr/http-factory-implementation": "^1.0" + }, + "require-dev": { + "http-interop/http-factory-tests": "^0.5", + "phpunit/phpunit": "^6.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Http\\Factory\\Guzzle\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "An HTTP Factory using Guzzle PSR7", + "keywords": [ + "factory", + "http", + "psr-17", + "psr-7" + ], + "time": "2018-07-31T19:32:56+00:00" }, { "name": "myclabs/deep-copy", - "version": "1.8.1", + "version": "1.9.1", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "3e01bdad3e18354c3dce54466b7fbe33a9f9f7f8" + "reference": "e6828efaba2c9b79f4499dae1d66ef8bfa7b2b72" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3e01bdad3e18354c3dce54466b7fbe33a9f9f7f8", - "reference": "3e01bdad3e18354c3dce54466b7fbe33a9f9f7f8", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/e6828efaba2c9b79f4499dae1d66ef8bfa7b2b72", + "reference": "e6828efaba2c9b79f4499dae1d66ef8bfa7b2b72", "shasum": "" }, "require": { @@ -1258,7 +1172,7 @@ "object", "object graph" ], - "time": "2018-06-11T23:09:50+00:00" + "time": "2019-04-07T13:18:21+00:00" }, { "name": "paragonie/random_compat", @@ -1356,6 +1270,69 @@ ], "time": "2018-02-15T16:58:55+00:00" }, + { + "name": "php-http/guzzle6-adapter", + "version": "v2.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-http/guzzle6-adapter.git", + "reference": "6074a4b1f4d5c21061b70bab3b8ad484282fe31f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-http/guzzle6-adapter/zipball/6074a4b1f4d5c21061b70bab3b8ad484282fe31f", + "reference": "6074a4b1f4d5c21061b70bab3b8ad484282fe31f", + "shasum": "" + }, + "require": { + "guzzlehttp/guzzle": "^6.0", + "php": "^7.1", + "php-http/httplug": "^2.0", + "psr/http-client": "^1.0" + }, + "provide": { + "php-http/async-client-implementation": "1.0", + "php-http/client-implementation": "1.0", + "psr/http-client-implementation": "1.0" + }, + "require-dev": { + "ext-curl": "*", + "php-http/client-integration-tests": "^2.0", + "phpunit/phpunit": "^7.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "Http\\Adapter\\Guzzle6\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" + }, + { + "name": "David de Boer", + "email": "david@ddeboer.nl" + } + ], + "description": "Guzzle 6 HTTP Adapter", + "homepage": "http://httplug.io", + "keywords": [ + "Guzzle", + "http" + ], + "time": "2018-12-16T14:44:03+00:00" + }, { "name": "phpdocumentor/reflection-common", "version": "1.0.1", @@ -2078,6 +2055,7 @@ "mock", "xunit" ], + "abandoned": true, "time": "2017-06-30T09:13:00+00:00" }, { @@ -2642,16 +2620,16 @@ }, { "name": "symfony/console", - "version": "v4.2.3", + "version": "v4.2.7", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "1f0ad51dfde4da8a6070f06adc58b4e37cbb37a4" + "reference": "e2840bb38bddad7a0feaf85931e38fdcffdb2f81" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/1f0ad51dfde4da8a6070f06adc58b4e37cbb37a4", - "reference": "1f0ad51dfde4da8a6070f06adc58b4e37cbb37a4", + "url": "https://api.github.com/repos/symfony/console/zipball/e2840bb38bddad7a0feaf85931e38fdcffdb2f81", + "reference": "e2840bb38bddad7a0feaf85931e38fdcffdb2f81", "shasum": "" }, "require": { @@ -2710,7 +2688,7 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2019-01-25T14:35:16+00:00" + "time": "2019-04-08T14:23:48+00:00" }, { "name": "symfony/contracts", @@ -2782,16 +2760,16 @@ }, { "name": "symfony/event-dispatcher", - "version": "v4.2.3", + "version": "v4.2.7", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "bd09ad265cd50b2b9d09d65ce6aba2d29bc81fe1" + "reference": "fbce53cd74ac509cbe74b6f227622650ab759b02" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/bd09ad265cd50b2b9d09d65ce6aba2d29bc81fe1", - "reference": "bd09ad265cd50b2b9d09d65ce6aba2d29bc81fe1", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/fbce53cd74ac509cbe74b6f227622650ab759b02", + "reference": "fbce53cd74ac509cbe74b6f227622650ab759b02", "shasum": "" }, "require": { @@ -2842,20 +2820,20 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", - "time": "2019-01-16T20:35:37+00:00" + "time": "2019-04-06T13:51:08+00:00" }, { "name": "symfony/filesystem", - "version": "v4.2.3", + "version": "v4.2.7", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "7c16ebc2629827d4ec915a52ac809768d060a4ee" + "reference": "e16b9e471703b2c60b95f14d31c1239f68f11601" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/7c16ebc2629827d4ec915a52ac809768d060a4ee", - "reference": "7c16ebc2629827d4ec915a52ac809768d060a4ee", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/e16b9e471703b2c60b95f14d31c1239f68f11601", + "reference": "e16b9e471703b2c60b95f14d31c1239f68f11601", "shasum": "" }, "require": { @@ -2892,20 +2870,20 @@ ], "description": "Symfony Filesystem Component", "homepage": "https://symfony.com", - "time": "2019-01-16T20:35:37+00:00" + "time": "2019-02-07T11:40:08+00:00" }, { "name": "symfony/finder", - "version": "v4.2.3", + "version": "v4.2.7", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "ef71816cbb264988bb57fe6a73f610888b9aa70c" + "reference": "e45135658bd6c14b61850bf131c4f09a55133f69" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/ef71816cbb264988bb57fe6a73f610888b9aa70c", - "reference": "ef71816cbb264988bb57fe6a73f610888b9aa70c", + "url": "https://api.github.com/repos/symfony/finder/zipball/e45135658bd6c14b61850bf131c4f09a55133f69", + "reference": "e45135658bd6c14b61850bf131c4f09a55133f69", "shasum": "" }, "require": { @@ -2941,20 +2919,20 @@ ], "description": "Symfony Finder Component", "homepage": "https://symfony.com", - "time": "2019-01-16T20:35:37+00:00" + "time": "2019-04-06T13:51:08+00:00" }, { "name": "symfony/options-resolver", - "version": "v4.2.3", + "version": "v4.2.7", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "831b272963a8aa5a0613a1a7f013322d8161bbbb" + "reference": "fd4a5f27b7cd085b489247b9890ebca9f3e10044" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/831b272963a8aa5a0613a1a7f013322d8161bbbb", - "reference": "831b272963a8aa5a0613a1a7f013322d8161bbbb", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/fd4a5f27b7cd085b489247b9890ebca9f3e10044", + "reference": "fd4a5f27b7cd085b489247b9890ebca9f3e10044", "shasum": "" }, "require": { @@ -2995,20 +2973,20 @@ "configuration", "options" ], - "time": "2019-01-16T21:31:25+00:00" + "time": "2019-04-10T16:20:36+00:00" }, { "name": "symfony/polyfill-ctype", - "version": "v1.10.0", + "version": "v1.11.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "e3d826245268269cd66f8326bd8bc066687b4a19" + "reference": "82ebae02209c21113908c229e9883c419720738a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/e3d826245268269cd66f8326bd8bc066687b4a19", - "reference": "e3d826245268269cd66f8326bd8bc066687b4a19", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/82ebae02209c21113908c229e9883c419720738a", + "reference": "82ebae02209c21113908c229e9883c419720738a", "shasum": "" }, "require": { @@ -3020,7 +2998,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.9-dev" + "dev-master": "1.11-dev" } }, "autoload": { @@ -3053,20 +3031,20 @@ "polyfill", "portable" ], - "time": "2018-08-06T14:22:27+00:00" + "time": "2019-02-06T07:57:58+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.10.0", + "version": "v1.11.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "c79c051f5b3a46be09205c73b80b346e4153e494" + "reference": "fe5e94c604826c35a32fa832f35bd036b6799609" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/c79c051f5b3a46be09205c73b80b346e4153e494", - "reference": "c79c051f5b3a46be09205c73b80b346e4153e494", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/fe5e94c604826c35a32fa832f35bd036b6799609", + "reference": "fe5e94c604826c35a32fa832f35bd036b6799609", "shasum": "" }, "require": { @@ -3078,7 +3056,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.9-dev" + "dev-master": "1.11-dev" } }, "autoload": { @@ -3112,20 +3090,20 @@ "portable", "shim" ], - "time": "2018-09-21T13:07:52+00:00" + "time": "2019-02-06T07:57:58+00:00" }, { "name": "symfony/polyfill-php70", - "version": "v1.10.0", + "version": "v1.11.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php70.git", - "reference": "6b88000cdd431cd2e940caa2cb569201f3f84224" + "reference": "bc4858fb611bda58719124ca079baff854149c89" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php70/zipball/6b88000cdd431cd2e940caa2cb569201f3f84224", - "reference": "6b88000cdd431cd2e940caa2cb569201f3f84224", + "url": "https://api.github.com/repos/symfony/polyfill-php70/zipball/bc4858fb611bda58719124ca079baff854149c89", + "reference": "bc4858fb611bda58719124ca079baff854149c89", "shasum": "" }, "require": { @@ -3135,7 +3113,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.9-dev" + "dev-master": "1.11-dev" } }, "autoload": { @@ -3171,20 +3149,20 @@ "portable", "shim" ], - "time": "2018-09-21T06:26:08+00:00" + "time": "2019-02-06T07:57:58+00:00" }, { "name": "symfony/polyfill-php72", - "version": "v1.10.0", + "version": "v1.11.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php72.git", - "reference": "9050816e2ca34a8e916c3a0ae8b9c2fccf68b631" + "reference": "ab50dcf166d5f577978419edd37aa2bb8eabce0c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/9050816e2ca34a8e916c3a0ae8b9c2fccf68b631", - "reference": "9050816e2ca34a8e916c3a0ae8b9c2fccf68b631", + "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/ab50dcf166d5f577978419edd37aa2bb8eabce0c", + "reference": "ab50dcf166d5f577978419edd37aa2bb8eabce0c", "shasum": "" }, "require": { @@ -3193,7 +3171,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.9-dev" + "dev-master": "1.11-dev" } }, "autoload": { @@ -3226,20 +3204,20 @@ "portable", "shim" ], - "time": "2018-09-21T13:07:52+00:00" + "time": "2019-02-06T07:57:58+00:00" }, { "name": "symfony/process", - "version": "v4.2.3", + "version": "v4.2.7", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "6c05edb11fbeff9e2b324b4270ecb17911a8b7ad" + "reference": "8cf39fb4ccff793340c258ee7760fd40bfe745fe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/6c05edb11fbeff9e2b324b4270ecb17911a8b7ad", - "reference": "6c05edb11fbeff9e2b324b4270ecb17911a8b7ad", + "url": "https://api.github.com/repos/symfony/process/zipball/8cf39fb4ccff793340c258ee7760fd40bfe745fe", + "reference": "8cf39fb4ccff793340c258ee7760fd40bfe745fe", "shasum": "" }, "require": { @@ -3275,11 +3253,11 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2019-01-24T22:05:03+00:00" + "time": "2019-04-10T16:20:36+00:00" }, { "name": "symfony/stopwatch", - "version": "v4.2.3", + "version": "v4.2.7", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", @@ -3329,16 +3307,16 @@ }, { "name": "symfony/yaml", - "version": "v4.2.3", + "version": "v4.2.7", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "d461670ee145092b7e2a56c1da7118f19cadadb0" + "reference": "6712daf03ee25b53abb14e7e8e0ede1a770efdb1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/d461670ee145092b7e2a56c1da7118f19cadadb0", - "reference": "d461670ee145092b7e2a56c1da7118f19cadadb0", + "url": "https://api.github.com/repos/symfony/yaml/zipball/6712daf03ee25b53abb14e7e8e0ede1a770efdb1", + "reference": "6712daf03ee25b53abb14e7e8e0ede1a770efdb1", "shasum": "" }, "require": { @@ -3384,7 +3362,7 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2019-01-16T20:35:37+00:00" + "time": "2019-03-30T15:58:42+00:00" }, { "name": "webmozart/assert", diff --git a/spec/Client/HttpClientSpec.php b/spec/Client/HttpClientSpec.php index 994c602a..7aee05bc 100644 --- a/spec/Client/HttpClientSpec.php +++ b/spec/Client/HttpClientSpec.php @@ -2,33 +2,38 @@ namespace spec\Akeneo\Pim\ApiClient\Client; +use Akeneo\Pim\ApiClient\Client\HttpClient; use Akeneo\Pim\ApiClient\Exception\HttpException; use Akeneo\Pim\ApiClient\Client\HttpClientInterface; -use Http\Client\HttpClient; -use Http\Message\RequestFactory; use PhpSpec\ObjectBehavior; +use Psr\Http\Client\ClientInterface; +use Psr\Http\Message\RequestFactoryInterface; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; +use Psr\Http\Message\StreamFactoryInterface; use Psr\Http\Message\StreamInterface; class HttpClientSpec extends ObjectBehavior { function let( - HttpClient $httpClient, - RequestFactory $requestFactory + ClientInterface $httpClient, + RequestFactoryInterface $requestFactory, + StreamFactoryInterface $streamFactory ) { - $this->beConstructedWith($httpClient, $requestFactory); + $this->beConstructedWith($httpClient, $requestFactory, $streamFactory); } function it_is_initializable() { - $this->shouldHaveType(\Akeneo\Pim\ApiClient\Client\HttpClient::class); + $this->shouldHaveType(HttpClient::class); $this->shouldImplement(HttpClientInterface::class); } function it_sends_a_successful_request( - $requestFactory, - $httpClient, + RequestFactoryInterface $requestFactory, + ClientInterface $httpClient, + StreamFactoryInterface $streamFactory, + StreamInterface $stream, RequestInterface $request, ResponseInterface $response ) { @@ -39,6 +44,16 @@ function it_sends_a_successful_request( '{"identifier": "foo"}' )->willReturn($request); + $streamFactory->createStream('{"identifier": "foo"}')->willReturn($stream); + + $requestFactory->createRequest( + 'POST', + 'http://akeneo.com/api/rest/v1/products/foo' + )->willReturn($request); + + $request->withBody($stream)->willReturn($request); + $request->withHeader('Content-Type', 'application/json')->willReturn($request); + $httpClient->sendRequest($request)->willReturn($response); $this->sendRequest( @@ -50,8 +65,10 @@ function it_sends_a_successful_request( } function it_throws_an_exception_when_failing_request( - $requestFactory, - $httpClient, + RequestFactoryInterface $requestFactory, + ClientInterface $httpClient, + StreamFactoryInterface $streamFactory, + StreamInterface $stream, RequestInterface $request, ResponseInterface $response, StreamInterface $responseBody @@ -63,6 +80,16 @@ function it_throws_an_exception_when_failing_request( '{"identifier": "foo"}' )->willReturn($request); + $streamFactory->createStream('{"identifier": "foo"}')->willReturn($stream); + + $requestFactory->createRequest( + 'POST', + 'http://akeneo.com/api/rest/v1/products/foo' + )->willReturn($request); + + $request->withBody($stream)->willReturn($request); + $request->withHeader('Content-Type', 'application/json')->willReturn($request); + $httpClient->sendRequest($request)->willReturn($response); $response->getStatusCode()->willReturn(500); diff --git a/spec/Client/ResourceClientSpec.php b/spec/Client/ResourceClientSpec.php index 44ccb185..8f683e82 100644 --- a/spec/Client/ResourceClientSpec.php +++ b/spec/Client/ResourceClientSpec.php @@ -2,15 +2,16 @@ namespace spec\Akeneo\Pim\ApiClient\Client; +use Akeneo\Pim\ApiClient\Client\HttpClientInterface; use Akeneo\Pim\ApiClient\Client\ResourceClient; use Akeneo\Pim\ApiClient\Client\ResourceClientInterface; use Akeneo\Pim\ApiClient\Exception\InvalidArgumentException; use Akeneo\Pim\ApiClient\Client\HttpClient; +use Akeneo\Pim\ApiClient\MultipartStream\MultipartStreamBuilder; use Akeneo\Pim\ApiClient\Stream\MultipartStreamBuilderFactory; use Akeneo\Pim\ApiClient\Routing\UriGeneratorInterface; use Akeneo\Pim\ApiClient\Stream\UpsertResourceListResponse; use Akeneo\Pim\ApiClient\Stream\UpsertResourceListResponseFactory; -use Http\Message\MultipartStream\MultipartStreamBuilder; use PhpSpec\ObjectBehavior; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\StreamInterface; @@ -18,7 +19,7 @@ class ResourceClientSpec extends ObjectBehavior { function let( - HttpClient $httpClient, + HttpClientInterface $httpClient, UriGeneratorInterface $uriGenerator, MultipartStreamBuilderFactory $multipartStreamBuilderFactory, UpsertResourceListResponseFactory $responseFactory diff --git a/spec/Stream/MultipartStreamBuilderFactorySpec.php b/spec/Stream/MultipartStreamBuilderFactorySpec.php index ccddf964..b6d5fa85 100644 --- a/spec/Stream/MultipartStreamBuilderFactorySpec.php +++ b/spec/Stream/MultipartStreamBuilderFactorySpec.php @@ -2,14 +2,14 @@ namespace spec\Akeneo\Pim\ApiClient\Stream; +use Akeneo\Pim\ApiClient\MultipartStream\MultipartStreamBuilder; use Akeneo\Pim\ApiClient\Stream\MultipartStreamBuilderFactory; -use Http\Message\MultipartStream\MultipartStreamBuilder; -use Http\Message\StreamFactory; use PhpSpec\ObjectBehavior; +use Psr\Http\Message\StreamFactoryInterface; class MultipartStreamBuilderFactorySpec extends ObjectBehavior { - function let(StreamFactory $streamFactory) + function let(StreamFactoryInterface $streamFactory) { $this->beConstructedWith($streamFactory); } diff --git a/src/AkeneoPimClientBuilder.php b/src/AkeneoPimClientBuilder.php index d77b2a45..c78cddcf 100644 --- a/src/AkeneoPimClientBuilder.php +++ b/src/AkeneoPimClientBuilder.php @@ -28,12 +28,11 @@ use Akeneo\Pim\ApiClient\Security\Authentication; use Akeneo\Pim\ApiClient\Stream\MultipartStreamBuilderFactory; use Akeneo\Pim\ApiClient\Stream\UpsertResourceListResponseFactory; -use Http\Client\HttpClient as Client; -use Http\Discovery\HttpClientDiscovery; -use Http\Discovery\MessageFactoryDiscovery; -use Http\Discovery\StreamFactoryDiscovery; -use Http\Message\RequestFactory; -use Http\Message\StreamFactory; +use Http\Discovery\Psr17FactoryDiscovery; +use Http\Discovery\Psr18ClientDiscovery; +use Psr\Http\Client\ClientInterface; +use Psr\Http\Message\RequestFactoryInterface; +use Psr\Http\Message\StreamFactoryInterface; /** * Builder of the class AkeneoPimClient. @@ -48,13 +47,13 @@ class AkeneoPimClientBuilder /** @var string */ protected $baseUri; - /** @var Client */ + /** @var ClientInterface */ protected $httpClient; - /** @var RequestFactory */ + /** @var RequestFactoryInterface */ protected $requestFactory; - /** @var StreamFactory */ + /** @var StreamFactoryInterface */ protected $streamFactory; /** @var FileSystemInterface */ @@ -69,13 +68,9 @@ public function __construct(string $baseUri) } /** - * Allows to directly set a client instead of using HttpClientDiscovery::find() - * - * @param Client $httpClient - * - * @return AkeneoPimClientBuilder + * Allows to directly set a client instead of using the discovery */ - public function setHttpClient(Client $httpClient): self + public function setHttpClient(ClientInterface $httpClient): self { $this->httpClient = $httpClient; @@ -83,13 +78,9 @@ public function setHttpClient(Client $httpClient): self } /** - * Allows to directly set a request factory instead of using MessageFactoryDiscovery::find() - * - * @param RequestFactory $requestFactory - * - * @return AkeneoPimClientBuilder + * Allows to directly set a request factory instead of using the discovery */ - public function setRequestFactory(RequestFactory $requestFactory): self + public function setRequestFactory(RequestFactoryInterface $requestFactory): self { $this->requestFactory = $requestFactory; @@ -97,13 +88,9 @@ public function setRequestFactory(RequestFactory $requestFactory): self } /** - * Allows to directly set a stream factory instead of using StreamFactoryDiscovery::find() - * - * @param StreamFactory $streamFactory - * - * @return AkeneoPimClientBuilder + * Allows to directly set a stream factory instead of using the discovery */ - public function setStreamFactory(StreamFactory $streamFactory): self + public function setStreamFactory(StreamFactoryInterface $streamFactory): self { $this->streamFactory = $streamFactory; @@ -197,7 +184,7 @@ protected function setUp(Authentication $authentication): array { $uriGenerator = new UriGenerator($this->baseUri); - $httpClient = new HttpClient($this->getHttpClient(), $this->getRequestFactory()); + $httpClient = new HttpClient($this->getHttpClient(), $this->getRequestFactory(), $this->getStreamFactory()); $authenticationApi = new AuthenticationApi($httpClient, $uriGenerator); $authenticatedHttpClient = new AuthenticatedHttpClient($httpClient, $authenticationApi, $authentication); @@ -217,28 +204,28 @@ protected function setUp(Authentication $authentication): array return [$resourceClient, $pageFactory, $cursorFactory, $fileSystem]; } - private function getHttpClient(): Client + private function getHttpClient(): ClientInterface { if (null === $this->httpClient) { - $this->httpClient = HttpClientDiscovery::find(); + $this->httpClient = Psr18ClientDiscovery::find(); } return $this->httpClient; } - private function getRequestFactory(): RequestFactory + private function getRequestFactory(): RequestFactoryInterface { if (null === $this->requestFactory) { - $this->requestFactory = MessageFactoryDiscovery::find(); + $this->requestFactory = Psr17FactoryDiscovery::findRequestFactory(); } return $this->requestFactory; } - private function getStreamFactory(): StreamFactory + private function getStreamFactory(): StreamFactoryInterface { if (null === $this->streamFactory) { - $this->streamFactory = StreamFactoryDiscovery::find(); + $this->streamFactory = Psr17FactoryDiscovery::findStreamFactory(); } return $this->streamFactory; diff --git a/src/Client/HttpClient.php b/src/Client/HttpClient.php index 51cd12c3..ecab530f 100644 --- a/src/Client/HttpClient.php +++ b/src/Client/HttpClient.php @@ -2,9 +2,11 @@ namespace Akeneo\Pim\ApiClient\Client; -use Http\Client\HttpClient as Client; -use Http\Message\RequestFactory; +use Psr\Http\Client\ClientInterface; +use Psr\Http\Message\RequestFactoryInterface; use Psr\Http\Message\ResponseInterface; +use Psr\Http\Message\StreamFactoryInterface; +use Psr\Http\Message\StreamInterface; /** * Http client to send a request without any authentication. @@ -15,25 +17,26 @@ */ class HttpClient implements HttpClientInterface { - /** @var Client */ + /** @var ClientInterface */ protected $httpClient; - /** @var RequestFactory */ + /** @var RequestFactoryInterface */ protected $requestFactory; /** @var HttpExceptionHandler */ protected $httpExceptionHandler; - /** - * @param Client $httpClient - * @param RequestFactory $requestFactory - */ + /** @var StreamFactoryInterface */ + private $streamFactory; + public function __construct( - Client $httpClient, - RequestFactory $requestFactory + ClientInterface $httpClient, + RequestFactoryInterface $requestFactory, + StreamFactoryInterface $streamFactory ) { $this->httpClient = $httpClient; $this->requestFactory = $requestFactory; + $this->streamFactory = $streamFactory; $this->httpExceptionHandler = new HttpExceptionHandler(); } @@ -42,7 +45,19 @@ public function __construct( */ public function sendRequest(string $httpMethod, $uri, array $headers = [], $body = null): ResponseInterface { - $request = $this->requestFactory->createRequest($httpMethod, $uri, $headers, $body); + $request = $this->requestFactory->createRequest($httpMethod, $uri); + + if (null !== $body && is_string($body)) { + $request = $request->withBody($this->streamFactory->createStream($body)); + } + if (null !== $body && $body instanceof StreamInterface) { + $request = $request->withBody($body); + } + + foreach ($headers as $header => $content) { + $request = $request->withHeader($header, $content); + } + $response = $this->httpClient->sendRequest($request); $response = $this->httpExceptionHandler->transformResponseToException($request, $response); diff --git a/src/MultipartStream/MultipartStreamBuilder.php b/src/MultipartStream/MultipartStreamBuilder.php new file mode 100644 index 00000000..c8ede8fe --- /dev/null +++ b/src/MultipartStream/MultipartStreamBuilder.php @@ -0,0 +1,277 @@ +streamFactory = $streamFactory; + } + + /** + * Add a resource to the Multipart Stream. + * + * @param string $name the formpost name + * @param string|resource|StreamInterface $resource + * @param array $options { + * + * @var array $headers additional headers ['header-name' => 'header-value'] + * @var string $filename + * } + * + * @return MultipartStreamBuilder + */ + public function addResource(string $name, $resource, array $options = []) + { + if (is_string($resource)) { + $stream = $this->streamFactory->createStream($resource); + } elseif (is_resource($resource)) { + $stream = $this->streamFactory->createStreamFromResource($resource); + } elseif ($resource instanceof StreamInterface) { + $stream = $resource; + } else { + throw new \InvalidArgumentException('Resource should be a string, a resource or a Psr\Http\Message\StreamInterface'); + } + + // validate options['headers'] exists + if (!isset($options['headers'])) { + $options['headers'] = []; + } + + // Try to add filename if it is missing + if (empty($options['filename'])) { + $options['filename'] = null; + $uri = $stream->getMetadata('uri'); + if (substr($uri, 0, 6) !== 'php://') { + $options['filename'] = $uri; + } + } + + $this->prepareHeaders($name, $stream, $options['filename'], $options['headers']); + $this->data[] = ['contents' => $stream, 'headers' => $options['headers'], 'filename' => $options['filename']]; + + return $this; + } + + /** + * Build the stream. + * + * @return StreamInterface + */ + public function build() + { + $streams = ''; + foreach ($this->data as $data) { + // Add start and headers + $streams .= "--{$this->getBoundary()}\r\n". + $this->getHeaders($data['headers'])."\r\n"; + + // Convert the stream to string + /* @var $contentStream StreamInterface */ + $contentStream = $data['contents']; + if ($contentStream->isSeekable()) { + $streams .= $contentStream->__toString(); + } else { + $streams .= $contentStream->getContents(); + } + + $streams .= "\r\n"; + } + + // Append end + $streams .= "--{$this->getBoundary()}--\r\n"; + + return $this->streamFactory->createStream($streams); + } + + /** + * Add extra headers if they are missing. + * + * @param string $name + * @param StreamInterface $stream + * @param string $filename + * @param array &$headers + */ + private function prepareHeaders($name, StreamInterface $stream, $filename, array &$headers) + { + $hasFilename = $filename === '0' || $filename; + + // Set a default content-disposition header if one was not provided + if (!$this->hasHeader($headers, 'content-disposition')) { + $headers['Content-Disposition'] = sprintf('form-data; name="%s"', $name); + if ($hasFilename) { + $headers['Content-Disposition'] .= sprintf('; filename="%s"', $this->basename($filename)); + } + } + + // Set a default content-length header if one was not provided + if (!$this->hasHeader($headers, 'content-length')) { + if ($length = $stream->getSize()) { + $headers['Content-Length'] = (string) $length; + } + } + + // Set a default Content-Type if one was not provided + if (!$this->hasHeader($headers, 'content-type') && $hasFilename) { + if ($type = $this->getMimetypeHelper()->getMimetypeFromFilename($filename)) { + $headers['Content-Type'] = $type; + } + } + } + + /** + * Get the headers formatted for the HTTP message. + * + * @param array $headers + * + * @return string + */ + private function getHeaders(array $headers) + { + $str = ''; + foreach ($headers as $key => $value) { + $str .= sprintf("%s: %s\r\n", $key, $value); + } + + return $str; + } + + /** + * Check if header exist. + * + * @param array $headers + * @param string $key case insensitive + * + * @return bool + */ + private function hasHeader(array $headers, $key) + { + $lowercaseHeader = strtolower($key); + foreach ($headers as $k => $v) { + if (strtolower($k) === $lowercaseHeader) { + return true; + } + } + + return false; + } + + /** + * Get the boundary that separates the streams. + * + * @return string + */ + public function getBoundary() + { + if ($this->boundary === null) { + $this->boundary = uniqid('', true); + } + + return $this->boundary; + } + + /** + * @param string $boundary + * + * @return MultipartStreamBuilder + */ + public function setBoundary($boundary) + { + $this->boundary = $boundary; + + return $this; + } + + /** + * @return MimetypeHelper + */ + private function getMimetypeHelper() + { + if ($this->mimetypeHelper === null) { + $this->mimetypeHelper = new ApacheMimetypeHelper(); + } + + return $this->mimetypeHelper; + } + + /** + * If you have custom file extension you may overwrite the default MimetypeHelper with your own. + * + * @param MimetypeHelper $mimetypeHelper + * + * @return MultipartStreamBuilder + */ + public function setMimetypeHelper(MimetypeHelper $mimetypeHelper) + { + $this->mimetypeHelper = $mimetypeHelper; + + return $this; + } + + /** + * Reset and clear all stored data. This allows you to use builder for a subsequent request. + * + * @return MultipartStreamBuilder + */ + public function reset() + { + $this->data = []; + $this->boundary = null; + + return $this; + } + + /** + * Gets the filename from a given path. + * + * PHP's basename() does not properly support streams or filenames beginning with a non-US-ASCII character. + * + * @author Drupal 8.2 + * + * @param string $path + * + * @return string + */ + private function basename($path) + { + $separators = '/'; + if (DIRECTORY_SEPARATOR != '/') { + // For Windows OS add special separator. + $separators .= DIRECTORY_SEPARATOR; + } + + // Remove right-most slashes when $path points to directory. + $path = rtrim($path, $separators); + + // Returns the trailing part of the $path starting after one of the directory separators. + $filename = preg_match('@[^'.preg_quote($separators, '@').']+$@', $path, $matches) ? $matches[0] : ''; + + return $filename; + } +} diff --git a/src/Stream/MultipartStreamBuilderFactory.php b/src/Stream/MultipartStreamBuilderFactory.php index 5b9b0c2b..c709a608 100644 --- a/src/Stream/MultipartStreamBuilderFactory.php +++ b/src/Stream/MultipartStreamBuilderFactory.php @@ -2,8 +2,8 @@ namespace Akeneo\Pim\ApiClient\Stream; -use Http\Message\MultipartStream\MultipartStreamBuilder; -use Http\Message\StreamFactory; +use Akeneo\Pim\ApiClient\MultipartStream\MultipartStreamBuilder; +use Psr\Http\Message\StreamFactoryInterface; /** * Factory to create a builder of Multipart streams @@ -14,10 +14,10 @@ */ class MultipartStreamBuilderFactory { - /** @var StreamFactory */ + /** @var StreamFactoryInterface */ protected $streamFactory; - public function __construct(StreamFactory $streamFactory) + public function __construct(StreamFactoryInterface $streamFactory) { $this->streamFactory = $streamFactory; } diff --git a/tests/Api/CreateProductTest.php b/tests/Api/CreateProductTest.php index 9546035a..1c3fe011 100644 --- a/tests/Api/CreateProductTest.php +++ b/tests/Api/CreateProductTest.php @@ -22,7 +22,7 @@ public function test_create_product() $api = $this->createClient()->getProductApi(); $response = $api->create('new_shoes', $this->newProduct()); - Assert::assertSame($this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_INPUT], json_encode($this->expectedProduct())); + Assert::assertSame(json_encode($this->expectedProduct()), $this->server->getLastRequest()->jsonSerialize()[RequestInfo::JSON_KEY_INPUT]); Assert::assertSame(201, $response); } diff --git a/tests/Api/UpsertListProductTest.php b/tests/Api/UpsertListProductTest.php index 7239cfc6..10af6cd4 100644 --- a/tests/Api/UpsertListProductTest.php +++ b/tests/Api/UpsertListProductTest.php @@ -6,6 +6,7 @@ use donatj\MockWebServer\RequestInfo; use donatj\MockWebServer\Response; use donatj\MockWebServer\ResponseStack; +use Http\Discovery\Psr17FactoryDiscovery; use Http\Discovery\StreamFactoryDiscovery; use PHPUnit\Framework\Assert; @@ -53,7 +54,7 @@ public function test_upsert_list_from_stream() fwrite($resources, $this->getProductToUpsertJson()); rewind($resources); - $streamedResources = StreamFactoryDiscovery::find()->createStream($resources); + $streamedResources = Psr17FactoryDiscovery::findStreamFactory()->createStreamFromResource($resources); $api = $this->createClient()->getProductAPi(); $response = $api->upsertList($streamedResources);