diff --git a/.github/workflows/Build-Test.yml b/.github/workflows/Build-Test.yml new file mode 100644 index 0000000..1c0dde3 --- /dev/null +++ b/.github/workflows/Build-Test.yml @@ -0,0 +1,90 @@ + +# Run this workflow every time a new commit pushed to your repository +on: + push: + +jobs: + tests: + if: "! contains(toJSON(github.event.commits.*.msg), 'skip') && ! contains(toJSON(github.event.commits.*.msg), 'ci')" #skip ci... + runs-on: ${{ matrix.operating-system }} + + strategy: + fail-fast: false + matrix: + operating-system: [ubuntu-20.04] + php-versions: ['7.2', '7.3', '7.4', '8.0'] + include: + - operating-system: ubuntu-16.04 + php-versions: '7.1' + COMPOSER_FLAGS: '--prefer-stable --prefer-lowest' + COVERAGE: 'true' + PHPUNIT_FLAGS: '--coverage-clover build/coverage.xml' + + name: PHP ${{ matrix.php-versions }} - ${{ matrix.operating-system }} + + env: + extensions: curl json libxml dom + key: cache-v1 # can be any string, change to clear the extension cache. + + steps: + # Checks out a copy of your repository on the ubuntu machine + - name: Checkout code + uses: actions/checkout@v2 + + - name: Setup cache environment + id: extcache + uses: shivammathur/cache-extensions@v1 + with: + php-version: ${{ matrix.php-versions }} + extensions: ${{ env.extensions }} + key: ${{ env.key }} + + - name: Cache PHP Extensions + uses: actions/cache@v2 + with: + path: ${{ steps.extcache.outputs.dir }} + key: ${{ steps.extcache.outputs.key }} + restore-keys: ${{ steps.extcache.outputs.key }} + + - name: Cache Composer Dependencies + uses: actions/cache@v1 + with: + path: ~/.composer/cache/files + key: dependencies-composer-${{ hashFiles('composer.json') }} + + - name: Setup PHP Action + uses: shivammathur/setup-php@2.8.0 + with: + php-version: ${{ matrix.php-versions }} + extensions: ${{ env.extensions }} + coverage: xdebug + tools: pecl, composer + + - name: Get composer cache directory + id: composer-cache + run: echo "::set-output name=dir::$(composer config cache-files-dir)" + + - name: Cache dependencies + uses: actions/cache@v2 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Composer self update + run: composer self-update + + - name: Install Composer dependencies + run: composer update ${{ matrix.COMPOSER_FLAGS }} --prefer-source --no-interaction + + - name: boot test server + run: vendor/bin/http_test_server > /dev/null 2>&1 & + + - name: Apply tests + run: composer test + + - name: Apply coverage + if: ${{ matrix.COVERAGE == 'true' }} + run: | + wget https://scrutinizer-ci.com/ocular.phar + php ocular.phar code-coverage:upload --format=php-clover build/coverage.xml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 64a5a82..0000000 --- a/.travis.yml +++ /dev/null @@ -1,38 +0,0 @@ -language: php -sudo: false -dist: trusty - -cache: - directories: - - $HOME/.composer/cache - -php: - - 7.1 - - 7.2 - - 7.3 - -env: - global: - - TEST_COMMAND="composer test" - -matrix: - fast_finish: true - include: - - php: 7.1 - name: "Lowest dependencies" - env: COMPOSER_FLAGS="--prefer-stable --prefer-lowest" COVERAGE=true PHPUNIT_FLAGS="--coverage-clover build/coverage.xml" - -before_install: - - travis_retry composer self-update - -install: - - travis_retry composer update ${COMPOSER_FLAGS} --prefer-source --no-interaction - -before_script: vendor/bin/http_test_server > /dev/null 2>&1 & - -script: - - $TEST_COMMAND - -after_success: - - if [[ "$COVERAGE" = true ]]; then wget https://scrutinizer-ci.com/ocular.phar; fi - - if [[ "$COVERAGE" = true ]]; then php ocular.phar code-coverage:upload --format=php-clover build/coverage.xml; fi diff --git a/composer.json b/composer.json index 94e7c3d..55f90d7 100644 --- a/composer.json +++ b/composer.json @@ -8,16 +8,14 @@ "psr-18" ], "homepage": "http://php-http.org", - "authors": [ - { - "name": "Михаил Красильников", - "email": "m.krasilnikov@yandex.ru" - } - ], + "authors": [{ + "name": "Михаил Красильников", + "email": "m.krasilnikov@yandex.ru" + }], "prefer-stable": true, "minimum-stability": "dev", "require": { - "php": "^7.1", + "php": "^7.1 || ^8.0", "ext-curl": "*", "php-http/discovery": "^1.6", "php-http/httplug": "^2.0", @@ -28,8 +26,8 @@ }, "require-dev": { "guzzlehttp/psr7": "^1.0", - "php-http/client-integration-tests": "^2.0", - "phpunit/phpunit": "^7.5", + "php-http/client-integration-tests": "^3.0", + "phpunit/phpunit": "^7.5 || ^9.4", "laminas/laminas-diactoros": "^2.0" }, "autoload": { @@ -56,4 +54,4 @@ "dev-master": "2.x-dev" } } -} +} \ No newline at end of file diff --git a/src/Client.php b/src/Client.php index f6b844c..739fdc2 100644 --- a/src/Client.php +++ b/src/Client.php @@ -53,7 +53,7 @@ class Client implements HttpClient, HttpAsyncClient /** * cURL synchronous requests handle. * - * @var resource|null + * @var resource|\CurlHandle|null */ private $handle; diff --git a/src/PromiseCore.php b/src/PromiseCore.php index 2b0256d..b58776f 100644 --- a/src/PromiseCore.php +++ b/src/PromiseCore.php @@ -69,9 +69,9 @@ class PromiseCore /** * Create shared core. * - * @param RequestInterface $request HTTP request. - * @param resource $handle cURL handle. - * @param ResponseBuilder $responseBuilder Response builder. + * @param RequestInterface $request HTTP request. + * @param resource|\CurlHandle $handle cURL handle. + * @param ResponseBuilder $responseBuilder Response builder. * * @throws \InvalidArgumentException If $handle is not a cURL resource. */ @@ -80,20 +80,29 @@ public function __construct( $handle, ResponseBuilder $responseBuilder ) { - if (!is_resource($handle)) { - throw new \InvalidArgumentException( - sprintf( - 'Parameter $handle expected to be a cURL resource, %s given', - gettype($handle) - ) - ); + if (PHP_MAJOR_VERSION === 7) { + if (!is_resource($handle)) { + throw new \InvalidArgumentException( + sprintf( + 'Parameter $handle expected to be a cURL resource, %s given', + gettype($handle) + ) + ); + } elseif (get_resource_type($handle) !== 'curl') { + throw new \InvalidArgumentException( + sprintf( + 'Parameter $handle expected to be a cURL resource, %s resource given', + get_resource_type($handle) + ) + ); + } } - if (get_resource_type($handle) !== 'curl') { + if (PHP_MAJOR_VERSION > 7 && !$handle instanceof \CurlHandle) { throw new \InvalidArgumentException( sprintf( - 'Parameter $handle expected to be a cURL resource, %s resource given', - get_resource_type($handle) + 'Parameter $handle expected to be a cURL resource, %s given', + get_debug_type($handle) ) ); } @@ -138,7 +147,7 @@ public function addOnRejected(callable $callback): void /** * Return cURL handle. * - * @return resource + * @return resource|\CurlHandle */ public function getHandle() { diff --git a/tests/Functional/HttpClientDiactorosTest.php b/tests/Functional/HttpClientDiactorosTest.php index 6ce67ce..a8fd42f 100644 --- a/tests/Functional/HttpClientDiactorosTest.php +++ b/tests/Functional/HttpClientDiactorosTest.php @@ -4,7 +4,9 @@ namespace Http\Client\Curl\Tests\Functional; + use Http\Client\Curl\Client; +use Psr\Http\Client\ClientInterface; use Http\Client\HttpClient; use Psr\Http\Message\StreamInterface; use Laminas\Diactoros\ResponseFactory; @@ -21,7 +23,7 @@ protected function createFileStream(string $filename): StreamInterface return new Stream($filename); } - protected function createHttpAdapter(): HttpClient + protected function createHttpAdapter(): ClientInterface { return new Client(new ResponseFactory(), new StreamFactory()); } diff --git a/tests/Unit/PromiseCoreTest.php b/tests/Unit/PromiseCoreTest.php index b52df28..7374640 100644 --- a/tests/Unit/PromiseCoreTest.php +++ b/tests/Unit/PromiseCoreTest.php @@ -36,7 +36,11 @@ public function testHandleIsNotACurlResource(): void $responseBuilder = $this->createMock(ResponseBuilder::class); $this->expectException(\InvalidArgumentException::class); - $this->expectExceptionMessage('Parameter $handle expected to be a cURL resource, stream resource given'); + if (PHP_MAJOR_VERSION > 7) { + $this->expectExceptionMessage('Parameter $handle expected to be a cURL resource, resource (stream) given'); + } else { + $this->expectExceptionMessage('Parameter $handle expected to be a cURL resource, stream resource given'); + } new PromiseCore($request, fopen('php://memory', 'r+b'), $responseBuilder); } @@ -50,7 +54,11 @@ public function testHandleIsNotAResource(): void $responseBuilder = $this->createMock(ResponseBuilder::class); $this->expectException(\InvalidArgumentException::class); - $this->expectExceptionMessage('Parameter $handle expected to be a cURL resource, NULL given'); + if (PHP_MAJOR_VERSION > 7) { + $this->expectExceptionMessage('Parameter $handle expected to be a cURL resource, null given'); + } else { + $this->expectExceptionMessage('Parameter $handle expected to be a cURL resource, NULL given'); + } new PromiseCore($request, null, $responseBuilder); } @@ -152,7 +160,7 @@ function (RequestException $exception) { self::assertEquals('Bar', $core->getException()->getMessage()); } - protected function tearDown() + protected function tearDown(): void { if (is_resource($this->handle)) { curl_close($this->handle);