From 19fcd56d3ed205e41ec3a0144e171a23ec296401 Mon Sep 17 00:00:00 2001 From: Kevin Wenger Date: Wed, 26 Jun 2024 13:34:58 +0200 Subject: [PATCH] add Psalm linter --- .github/workflows/styles.yml | 24 +- CHANGELOG.md | 1 + composer.json | 5 +- composer.lock | 772 ++++++++++++++++++++++++++++++++++- psalm.xml | 28 ++ src/TrustedShops.php | 145 +++---- 6 files changed, 888 insertions(+), 87 deletions(-) create mode 100644 psalm.xml diff --git a/.github/workflows/styles.yml b/.github/workflows/styles.yml index 60f7836..43c1598 100644 --- a/.github/workflows/styles.yml +++ b/.github/workflows/styles.yml @@ -46,18 +46,18 @@ jobs: # - run: composer install --prefer-dist # - run: ./vendor/bin/phpstan analyse ./src ./tests --error-format=checkstyle | cs2pr -# psalm: -# name: psalm -# runs-on: ubuntu-latest -# steps: -# - name: Setup PHP -# uses: shivammathur/setup-php@v2 -# with: -# php-version: '7.4' -# extensions: mbstring, intl, gd, xml, dom, json, fileinfo, curl, zip, iconv -# - uses: actions/checkout@v2 -# - run: composer install --prefer-dist -# - run: ./vendor/bin/psalm --output-format=github + psalm: + name: psalm + runs-on: ubuntu-latest + steps: + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '7.4' + extensions: mbstring, intl, gd, xml, dom, json, fileinfo, curl, zip, iconv + - uses: actions/checkout@v2 + - run: composer install --prefer-dist + - run: ./vendor/bin/psalm --output-format=github # security-checker: # name: security-checker diff --git a/CHANGELOG.md b/CHANGELOG.md index b25765f..6a5a0e3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ### Added - add Github Actions integration +- add Psalm linter ## 1.0.0 - 2019-10-08 ### Changed diff --git a/composer.json b/composer.json index 7b4cb2c..f3130bf 100644 --- a/composer.json +++ b/composer.json @@ -3,7 +3,7 @@ "description": "Super-simple, minimum abstraction TrustedShops API v2.x wrapper, in PHP", "license": "MIT", "require": { - "php": ">=7.0", + "php": ">=7.4", "ext-curl": "*", "ext-json": "*" }, @@ -14,7 +14,8 @@ "friendsofphp/php-cs-fixer": "^2.12", "phpmd/phpmd": "^2.6", "php-coveralls/php-coveralls": "^2.1", - "php-mock/php-mock-phpunit": "^2.4" + "php-mock/php-mock-phpunit": "^2.4", + "vimeo/psalm": "^4.30" }, "autoload": { "psr-4": { diff --git a/composer.lock b/composer.lock index d965d76..6dc5fe1 100644 --- a/composer.lock +++ b/composer.lock @@ -4,9 +4,242 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "d1d66d4fea11efb0ba1f7a60061698a1", + "content-hash": "9b030f0acddbd94dd3d950d8b34859d6", "packages": [], "packages-dev": [ + { + "name": "amphp/amp", + "version": "v2.6.4", + "source": { + "type": "git", + "url": "https://github.com/amphp/amp.git", + "reference": "ded3d9be08f526089eb7ee8d9f16a9768f9dec2d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/amp/zipball/ded3d9be08f526089eb7ee8d9f16a9768f9dec2d", + "reference": "ded3d9be08f526089eb7ee8d9f16a9768f9dec2d", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "dev-master", + "amphp/phpunit-util": "^1", + "ext-json": "*", + "jetbrains/phpstorm-stubs": "^2019.3", + "phpunit/phpunit": "^7 | ^8 | ^9", + "react/promise": "^2", + "vimeo/psalm": "^3.12" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "autoload": { + "files": [ + "lib/functions.php", + "lib/Internal/functions.php" + ], + "psr-4": { + "Amp\\": "lib" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Daniel Lowrey", + "email": "rdlowrey@php.net" + }, + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Bob Weinand", + "email": "bobwei9@hotmail.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + } + ], + "description": "A non-blocking concurrency framework for PHP applications.", + "homepage": "https://amphp.org/amp", + "keywords": [ + "async", + "asynchronous", + "awaitable", + "concurrency", + "event", + "event-loop", + "future", + "non-blocking", + "promise" + ], + "support": { + "irc": "irc://irc.freenode.org/amphp", + "issues": "https://github.com/amphp/amp/issues", + "source": "https://github.com/amphp/amp/tree/v2.6.4" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2024-03-21T18:52:26+00:00" + }, + { + "name": "amphp/byte-stream", + "version": "v1.8.2", + "source": { + "type": "git", + "url": "https://github.com/amphp/byte-stream.git", + "reference": "4f0e968ba3798a423730f567b1b50d3441c16ddc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/byte-stream/zipball/4f0e968ba3798a423730f567b1b50d3441c16ddc", + "reference": "4f0e968ba3798a423730f567b1b50d3441c16ddc", + "shasum": "" + }, + "require": { + "amphp/amp": "^2", + "php": ">=7.1" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "dev-master", + "amphp/phpunit-util": "^1.4", + "friendsofphp/php-cs-fixer": "^2.3", + "jetbrains/phpstorm-stubs": "^2019.3", + "phpunit/phpunit": "^6 || ^7 || ^8", + "psalm/phar": "^3.11.4" + }, + "type": "library", + "autoload": { + "files": [ + "lib/functions.php" + ], + "psr-4": { + "Amp\\ByteStream\\": "lib" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + } + ], + "description": "A stream abstraction to make working with non-blocking I/O simple.", + "homepage": "https://amphp.org/byte-stream", + "keywords": [ + "amp", + "amphp", + "async", + "io", + "non-blocking", + "stream" + ], + "support": { + "issues": "https://github.com/amphp/byte-stream/issues", + "source": "https://github.com/amphp/byte-stream/tree/v1.8.2" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2024-04-13T18:00:56+00:00" + }, + { + "name": "composer/package-versions-deprecated", + "version": "1.11.99.5", + "source": { + "type": "git", + "url": "https://github.com/composer/package-versions-deprecated.git", + "reference": "b4f54f74ef3453349c24a845d22392cd31e65f1d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/package-versions-deprecated/zipball/b4f54f74ef3453349c24a845d22392cd31e65f1d", + "reference": "b4f54f74ef3453349c24a845d22392cd31e65f1d", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.1.0 || ^2.0", + "php": "^7 || ^8" + }, + "replace": { + "ocramius/package-versions": "1.11.99" + }, + "require-dev": { + "composer/composer": "^1.9.3 || ^2.0@dev", + "ext-zip": "^1.13", + "phpunit/phpunit": "^6.5 || ^7" + }, + "type": "composer-plugin", + "extra": { + "class": "PackageVersions\\Installer", + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "PackageVersions\\": "src/PackageVersions" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + }, + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be" + } + ], + "description": "Composer plugin that provides efficient querying for installed package versions (no runtime IO)", + "support": { + "issues": "https://github.com/composer/package-versions-deprecated/issues", + "source": "https://github.com/composer/package-versions-deprecated/tree/1.11.99.5" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2022-01-17T14:14:24+00:00" + }, { "name": "composer/semver", "version": "1.5.0", @@ -113,6 +346,43 @@ ], "time": "2019-05-27T17:52:04+00:00" }, + { + "name": "dnoegel/php-xdg-base-dir", + "version": "v0.1.1", + "source": { + "type": "git", + "url": "https://github.com/dnoegel/php-xdg-base-dir.git", + "reference": "8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dnoegel/php-xdg-base-dir/zipball/8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd", + "reference": "8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "require-dev": { + "phpunit/phpunit": "~7.0|~6.0|~5.0|~4.8.35" + }, + "type": "library", + "autoload": { + "psr-4": { + "XdgBaseDir\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "implementation of xdg base directory specification for php", + "support": { + "issues": "https://github.com/dnoegel/php-xdg-base-dir/issues", + "source": "https://github.com/dnoegel/php-xdg-base-dir/tree/v0.1.1" + }, + "time": "2019-12-04T15:06:13+00:00" + }, { "name": "doctrine/annotations", "version": "v1.7.0", @@ -299,6 +569,107 @@ ], "time": "2019-07-30T19:33:28+00:00" }, + { + "name": "felixfbecker/advanced-json-rpc", + "version": "v3.1.1", + "source": { + "type": "git", + "url": "https://github.com/felixfbecker/php-advanced-json-rpc.git", + "reference": "0ed363f8de17d284d479ec813c9ad3f6834b5c40" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/felixfbecker/php-advanced-json-rpc/zipball/0ed363f8de17d284d479ec813c9ad3f6834b5c40", + "reference": "0ed363f8de17d284d479ec813c9ad3f6834b5c40", + "shasum": "" + }, + "require": { + "netresearch/jsonmapper": "^1.0 || ^2.0", + "php": ">=7.0", + "phpdocumentor/reflection-docblock": "^4.0.0 || ^5.0.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "AdvancedJsonRpc\\": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "ISC" + ], + "authors": [ + { + "name": "Felix Becker", + "email": "felix.b@outlook.com" + } + ], + "description": "A more advanced JSONRPC implementation", + "support": { + "issues": "https://github.com/felixfbecker/php-advanced-json-rpc/issues", + "source": "https://github.com/felixfbecker/php-advanced-json-rpc/tree/master" + }, + "time": "2020-03-11T15:21:41+00:00" + }, + { + "name": "felixfbecker/language-server-protocol", + "version": "v1.5.2", + "source": { + "type": "git", + "url": "https://github.com/felixfbecker/php-language-server-protocol.git", + "reference": "6e82196ffd7c62f7794d778ca52b69feec9f2842" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/felixfbecker/php-language-server-protocol/zipball/6e82196ffd7c62f7794d778ca52b69feec9f2842", + "reference": "6e82196ffd7c62f7794d778ca52b69feec9f2842", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "require-dev": { + "phpstan/phpstan": "*", + "squizlabs/php_codesniffer": "^3.1", + "vimeo/psalm": "^4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "LanguageServerProtocol\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "ISC" + ], + "authors": [ + { + "name": "Felix Becker", + "email": "felix.b@outlook.com" + } + ], + "description": "PHP classes for the Language Server Protocol", + "keywords": [ + "language", + "microsoft", + "php", + "server" + ], + "support": { + "issues": "https://github.com/felixfbecker/php-language-server-protocol/issues", + "source": "https://github.com/felixfbecker/php-language-server-protocol/tree/v1.5.2" + }, + "time": "2022-03-02T22:36:06+00:00" + }, { "name": "friendsofphp/php-cs-fixer", "version": "v2.19.3", @@ -643,6 +1014,166 @@ ], "time": "2019-08-09T12:45:53+00:00" }, + { + "name": "netresearch/jsonmapper", + "version": "v2.1.0", + "source": { + "type": "git", + "url": "https://github.com/cweiske/jsonmapper.git", + "reference": "e0f1e33a71587aca81be5cffbb9746510e1fe04e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/cweiske/jsonmapper/zipball/e0f1e33a71587aca81be5cffbb9746510e1fe04e", + "reference": "e0f1e33a71587aca81be5cffbb9746510e1fe04e", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-pcre": "*", + "ext-reflection": "*", + "ext-spl": "*", + "php": ">=5.6" + }, + "require-dev": { + "phpunit/phpunit": "~4.8.35 || ~5.7 || ~6.4 || ~7.0", + "squizlabs/php_codesniffer": "~3.5" + }, + "type": "library", + "autoload": { + "psr-0": { + "JsonMapper": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "OSL-3.0" + ], + "authors": [ + { + "name": "Christian Weiske", + "email": "cweiske@cweiske.de", + "homepage": "http://github.com/cweiske/jsonmapper/", + "role": "Developer" + } + ], + "description": "Map nested JSON structures onto PHP classes", + "support": { + "email": "cweiske@cweiske.de", + "issues": "https://github.com/cweiske/jsonmapper/issues", + "source": "https://github.com/cweiske/jsonmapper/tree/master" + }, + "time": "2020-04-16T18:48:43+00:00" + }, + { + "name": "nikic/php-parser", + "version": "v4.19.1", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "4e1b88d21c69391150ace211e9eaf05810858d0b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/4e1b88d21c69391150ace211e9eaf05810858d0b", + "reference": "4e1b88d21c69391150ace211e9eaf05810858d0b", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": ">=7.1" + }, + "require-dev": { + "ircmaxell/php-yacc": "^0.0.7", + "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" + }, + "bin": [ + "bin/php-parse" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.9-dev" + } + }, + "autoload": { + "psr-4": { + "PhpParser\\": "lib/PhpParser" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov" + } + ], + "description": "A PHP parser written in PHP", + "keywords": [ + "parser", + "php" + ], + "support": { + "issues": "https://github.com/nikic/PHP-Parser/issues", + "source": "https://github.com/nikic/PHP-Parser/tree/v4.19.1" + }, + "time": "2024-03-17T08:10:35+00:00" + }, + { + "name": "openlss/lib-array2xml", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/nullivex/lib-array2xml.git", + "reference": "a91f18a8dfc69ffabe5f9b068bc39bb202c81d90" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nullivex/lib-array2xml/zipball/a91f18a8dfc69ffabe5f9b068bc39bb202c81d90", + "reference": "a91f18a8dfc69ffabe5f9b068bc39bb202c81d90", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "type": "library", + "autoload": { + "psr-0": { + "LSS": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Bryan Tong", + "email": "bryan@nullivex.com", + "homepage": "https://www.nullivex.com" + }, + { + "name": "Tony Butler", + "email": "spudz76@gmail.com", + "homepage": "https://www.nullivex.com" + } + ], + "description": "Array2XML conversion library credit to lalit.org", + "homepage": "https://www.nullivex.com", + "keywords": [ + "array", + "array conversion", + "xml", + "xml conversion" + ], + "support": { + "issues": "https://github.com/nullivex/lib-array2xml/issues", + "source": "https://github.com/nullivex/lib-array2xml/tree/master" + }, + "time": "2019-03-29T20:06:56+00:00" + }, { "name": "paragonie/random_compat", "version": "v9.99.99", @@ -3392,6 +3923,86 @@ ], "time": "2019-08-06T08:03:45+00:00" }, + { + "name": "symfony/polyfill-php80", + "version": "v1.30.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "77fa7995ac1b21ab60769b7323d600a991a90433" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/77fa7995ac1b21ab60769b7323d600a991a90433", + "reference": "77fa7995ac1b21ab60769b7323d600a991a90433", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php80\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php80/tree/v1.30.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-05-31T15:07:36+00:00" + }, { "name": "symfony/process", "version": "v4.3.4", @@ -3648,6 +4259,114 @@ "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", "time": "2019-06-13T22:48:21+00:00" }, + { + "name": "vimeo/psalm", + "version": "4.30.0", + "source": { + "type": "git", + "url": "https://github.com/vimeo/psalm.git", + "reference": "d0bc6e25d89f649e4f36a534f330f8bb4643dd69" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/vimeo/psalm/zipball/d0bc6e25d89f649e4f36a534f330f8bb4643dd69", + "reference": "d0bc6e25d89f649e4f36a534f330f8bb4643dd69", + "shasum": "" + }, + "require": { + "amphp/amp": "^2.4.2", + "amphp/byte-stream": "^1.5", + "composer/package-versions-deprecated": "^1.8.0", + "composer/semver": "^1.4 || ^2.0 || ^3.0", + "composer/xdebug-handler": "^1.1 || ^2.0 || ^3.0", + "dnoegel/php-xdg-base-dir": "^0.1.1", + "ext-ctype": "*", + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-simplexml": "*", + "ext-tokenizer": "*", + "felixfbecker/advanced-json-rpc": "^3.0.3", + "felixfbecker/language-server-protocol": "^1.5", + "netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0 || ^4.0", + "nikic/php-parser": "^4.13", + "openlss/lib-array2xml": "^1.0", + "php": "^7.1|^8", + "sebastian/diff": "^3.0 || ^4.0", + "symfony/console": "^3.4.17 || ^4.1.6 || ^5.0 || ^6.0", + "symfony/polyfill-php80": "^1.25", + "webmozart/path-util": "^2.3" + }, + "provide": { + "psalm/psalm": "self.version" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.2", + "brianium/paratest": "^4.0||^6.0", + "ext-curl": "*", + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpdocumentor/reflection-docblock": "^5", + "phpmyadmin/sql-parser": "5.1.0||dev-master", + "phpspec/prophecy": ">=1.9.0", + "phpstan/phpdoc-parser": "1.2.* || 1.6.4", + "phpunit/phpunit": "^9.0", + "psalm/plugin-phpunit": "^0.16", + "slevomat/coding-standard": "^7.0", + "squizlabs/php_codesniffer": "^3.5", + "symfony/process": "^4.3 || ^5.0 || ^6.0", + "weirdan/prophecy-shim": "^1.0 || ^2.0" + }, + "suggest": { + "ext-curl": "In order to send data to shepherd", + "ext-igbinary": "^2.0.5 is required, used to serialize caching data" + }, + "bin": [ + "psalm", + "psalm-language-server", + "psalm-plugin", + "psalm-refactor", + "psalter" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.x-dev", + "dev-3.x": "3.x-dev", + "dev-2.x": "2.x-dev", + "dev-1.x": "1.x-dev" + } + }, + "autoload": { + "files": [ + "src/functions.php", + "src/spl_object_id.php" + ], + "psr-4": { + "Psalm\\": "src/Psalm/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Matthew Brown" + } + ], + "description": "A static analysis tool for finding errors in PHP applications", + "keywords": [ + "code", + "inspection", + "php" + ], + "support": { + "issues": "https://github.com/vimeo/psalm/issues", + "source": "https://github.com/vimeo/psalm/tree/4.30.0" + }, + "time": "2022-11-06T20:37:08+00:00" + }, { "name": "webmozart/assert", "version": "1.5.0", @@ -3697,6 +4416,57 @@ "validate" ], "time": "2019-08-24T08:43:50+00:00" + }, + { + "name": "webmozart/path-util", + "version": "2.3.0", + "source": { + "type": "git", + "url": "https://github.com/webmozart/path-util.git", + "reference": "d939f7edc24c9a1bb9c0dee5cb05d8e859490725" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozart/path-util/zipball/d939f7edc24c9a1bb9c0dee5cb05d8e859490725", + "reference": "d939f7edc24c9a1bb9c0dee5cb05d8e859490725", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "webmozart/assert": "~1.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.6", + "sebastian/version": "^1.0.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.3-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\PathUtil\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "A robust cross-platform utility for normalizing, comparing and modifying file paths.", + "support": { + "issues": "https://github.com/webmozart/path-util/issues", + "source": "https://github.com/webmozart/path-util/tree/2.3.0" + }, + "abandoned": "symfony/filesystem", + "time": "2015-12-17T08:42:14+00:00" } ], "aliases": [], diff --git a/psalm.xml b/psalm.xml new file mode 100644 index 0000000..d1c0af3 --- /dev/null +++ b/psalm.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/TrustedShops.php b/src/TrustedShops.php index 24458c0..8a75e6b 100644 --- a/src/TrustedShops.php +++ b/src/TrustedShops.php @@ -73,43 +73,37 @@ class TrustedShops * * Read before disabling: * http://snippets.webaware.com.au/howto/stop-turning-off-curlopt_ssl_verifypeer-and-fix-your-php-config/ - * - * @var bool */ - public $verify_ssl = true; + public bool $verify_ssl = true; - private $request_successful = false; - private $last_error = ''; - private $last_response = []; - private $last_request = []; + private bool $request_successful = false; + private string $last_error = ''; + private array $last_response = []; + private array $last_request = []; /** * The API username credentials. - * - * @var string */ - private $api_credentials_user; + private ?string $api_credentials_user = null; /** * The API password credentials. - * - * @var string */ - private $api_credentials_pass; + private ?string $api_credentials_pass = null; /** * Create a new instance. * - * @param string $api_scoop + * @param ?string $api_scoop * The API range of call to be used - * @param string $api_version + * @param ?string $api_version * The API version you use - * @param string $api_dc + * @param ?string $api_dc * The API dc of call to be used * * @throws \Exception */ - public function __construct($api_scoop = null, $api_version = null, $api_dc = null) + public function __construct(?string $api_scoop = null, ?string $api_version = null, ?string $api_dc = null) { if (!function_exists('curl_init') || !function_exists('curl_setopt')) { throw new RuntimeException("cURL support is required, but can't be found."); @@ -140,17 +134,17 @@ public function __construct($api_scoop = null, $api_version = null, $api_dc = nu /** * Set the concrete API endpoint. * - * @param string $api_dc + * @param ?string $api_dc * The API dc of call to be used - * @param string $api_scoop + * @param ?string $api_scoop * The API range of call to be used - * @param string $api_version + * @param ?string $api_version * The API version you use * * @return string * The endpoint url */ - public function setEndpoint($api_dc = null, $api_scoop = null, $api_version = null) + public function setEndpoint(?string $api_dc = null, ?string $api_scoop = null, ?string $api_version = null): string { if (null !== $api_dc) { $this->api_dc = $api_dc; @@ -180,7 +174,7 @@ public function setEndpoint($api_dc = null, $api_scoop = null, $api_version = nu * @return string * The endpoint url */ - public function getApiEndpoint() + public function getApiEndpoint(): string { return $this->api_endpoint; } @@ -194,7 +188,7 @@ public function getApiEndpoint() * @param string $password * The TrustedShops password authorized for restricted API calls */ - public function setApiCredentials($username, $password) + public function setApiCredentials(string $username, string $password): void { $this->api_credentials_user = $username; $this->api_credentials_pass = $password; @@ -206,7 +200,7 @@ public function setApiCredentials($username, $password) * @return bool * True for success, FALSE for failure */ - public function success() + public function success(): bool { return $this->request_successful; } @@ -230,7 +224,7 @@ public function getLastError() * @return array * Assoc array with keys 'headers' and 'body' */ - public function getLastResponse() + public function getLastResponse(): array { return $this->last_response; } @@ -241,7 +235,7 @@ public function getLastResponse() * @return array * Assoc array */ - public function getLastRequest() + public function getLastRequest(): array { return $this->last_request; } @@ -261,7 +255,7 @@ public function getLastRequest() * * @throws \Exception */ - public function delete($method, $args = [], $timeout = self::TIMEOUT) + public function delete(string $method, array $args = [], int $timeout = self::TIMEOUT) { return $this->makeRequest('delete', $method, $args, $timeout); } @@ -281,7 +275,7 @@ public function delete($method, $args = [], $timeout = self::TIMEOUT) * * @throws \Exception */ - public function get($method, $args = [], $timeout = self::TIMEOUT) + public function get(string $method, array $args = [], int $timeout = self::TIMEOUT) { return $this->makeRequest('get', $method, $args, $timeout); } @@ -301,7 +295,7 @@ public function get($method, $args = [], $timeout = self::TIMEOUT) * * @throws \Exception */ - public function patch($method, $args = [], $timeout = self::TIMEOUT) + public function patch(string $method, array $args = [], int $timeout = self::TIMEOUT) { return $this->makeRequest('patch', $method, $args, $timeout); } @@ -321,7 +315,7 @@ public function patch($method, $args = [], $timeout = self::TIMEOUT) * * @throws \Exception */ - public function post($method, $args = [], $timeout = self::TIMEOUT) + public function post(string $method, array $args = [], int $timeout = self::TIMEOUT) { return $this->makeRequest('post', $method, $args, $timeout); } @@ -341,7 +335,7 @@ public function post($method, $args = [], $timeout = self::TIMEOUT) * * @throws \Exception */ - public function put($method, $args = [], $timeout = self::TIMEOUT) + public function put(string $method, array $args = [], int $timeout = self::TIMEOUT) { return $this->makeRequest('put', $method, $args, $timeout); } @@ -363,21 +357,21 @@ public function put($method, $args = [], $timeout = self::TIMEOUT) * * @throws \Exception */ - protected function makeRequest($http_verb, $method, $args = [], $timeout = self::TIMEOUT) + protected function makeRequest(string $http_verb, string $method, array $args = [], int $timeout = self::TIMEOUT) { $url = $this->api_endpoint.'/'.$method; $response = $this->prepareStateForRequest($http_verb, $method, $url, $timeout); $httpHeader = [ - 'Accept: application/json', - 'Content-Type: application/json', - // TrustedShops needs the X-Requested-With header to works properly. - 'X-Requested-With: XMLHttpRequest', - ]; + 'Accept: application/json', + 'Content-Type: application/json', + // TrustedShops needs the X-Requested-With header to works properly. + 'X-Requested-With: XMLHttpRequest', + ]; if (isset($args['language'])) { - $httpHeader[] = 'Accept-Language: '.$args['language']; + $httpHeader[] = 'Accept-Language: '.(string) $args['language']; } if ('put' === $http_verb) { @@ -429,15 +423,21 @@ protected function makeRequest($http_verb, $method, $args = [], $timeout = self: } $response_content = curl_exec($curl); - $response['headers'] = curl_getinfo($curl); + /** @var array|false $curl_info */ + $curl_info = curl_getinfo($curl); + $response['headers'] = $curl_info; $response = $this->setResponseState($response, $response_content, $curl); $formattedResponse = $this->formatResponse($response); curl_close($curl); - $isSuccess = $this->determineSuccess($response, $formattedResponse['response'], $timeout); + if (isset($formattedResponse['response']) && is_array($formattedResponse['response'])) { + $this->determineSuccess($response, $formattedResponse['response'], $timeout); + + return $formattedResponse['response']; + } - return is_array($formattedResponse['response']) ? $formattedResponse['response'] : $isSuccess; + return $this->determineSuccess($response, false, $timeout); } /** @@ -445,32 +445,30 @@ protected function makeRequest($http_verb, $method, $args = [], $timeout = self: * The HTTP verb to use: get, post, put, patch, delete * @param string $method * The API method to be called - * @param array $args - * Assoc array of parameters to be passed + * @param string $url + * The URL * @param int $timeout * Timeout limit for request in seconds - * - * @return array */ - protected function prepareStateForRequest($http_verb, $method, $url, $timeout) + protected function prepareStateForRequest(string $http_verb, string $method, string $url, int $timeout): array { $this->last_error = ''; $this->request_successful = false; $this->last_response = [ - 'headers' => null, // array of details from curl_getinfo(). - 'httpHeaders' => null, // array of HTTP headers. - 'body' => null, // content of the response. - ]; + 'headers' => null, // array of details from curl_getinfo(). + 'httpHeaders' => null, // array of HTTP headers. + 'body' => null, // content of the response. + ]; $this->last_request = [ - 'method' => $http_verb, - 'path' => $method, - 'url' => $url, - 'body' => '', - 'timeout' => $timeout, - ]; + 'method' => $http_verb, + 'path' => $method, + 'url' => $url, + 'body' => '', + 'timeout' => $timeout, + ]; return $this->last_response; } @@ -484,11 +482,11 @@ protected function prepareStateForRequest($http_verb, $method, $url, $timeout) * @return array * The parsed headers */ - protected function getHeadersAsArray($headersAsString) + protected function getHeadersAsArray(string $headersAsString): array { $headers = []; - foreach (explode(PHP_EOL, $headersAsString) as $i => $line) { + foreach (explode(PHP_EOL, $headersAsString) as $line) { if (1 === preg_match('/HTTP\/[1-2]/', substr($line, 0, 7))) { // http code continue; } @@ -513,7 +511,7 @@ protected function getHeadersAsArray($headersAsString) * @param array $data * Assoc array of data to attach */ - protected function attachRequestPayload(&$curl, $data) + protected function attachRequestPayload(&$curl, array $data): void { $encoded = json_encode($data); $this->last_request['body'] = $encoded; @@ -529,17 +527,20 @@ protected function attachRequestPayload(&$curl, $data) * @return array|false * A decoded array from JSON response */ - protected function formatResponse($response) + protected function formatResponse(array $response) { $this->last_response = $response; - if (empty($response['body'])) { + if (empty($response['body']) || !is_string($response['body'])) { return false; } - // Return the decoded response from JSON when reponse is a valid json. + // Return the decoded response from JSON when response is a valid json. // Will return FALSE otherwise. - return ($result = json_decode($response['body'], true)) ? $result : false; + /** @var array|null $result */ + $result = json_decode($response['body'], true); + + return $result ?? false; } /** @@ -547,7 +548,7 @@ protected function formatResponse($response) * * @param array $response * The response from the curl request - * @param string $response_content + * @param string|bool $response_content * The body of the response from the curl request * @param resource $curl * The curl resource @@ -557,13 +558,13 @@ protected function formatResponse($response) * * @throws \Exception */ - protected function setResponseState($response, $response_content, $curl) + protected function setResponseState(array $response, $response_content, $curl): array { if (false === $response_content) { $this->last_error = curl_error($curl); throw new Exception($this->last_error); - } else { - $headerSize = $response['headers']['header_size']; + } elseif (is_string($response_content)) { + $headerSize = isset($response['headers']['header_size']) ? (int) $response['headers']['header_size'] : 0; $response['httpHeaders'] = $this->getHeadersAsArray(substr($response_content, 0, $headerSize)); $response['body'] = substr($response_content, $headerSize); @@ -591,7 +592,7 @@ protected function setResponseState($response, $response_content, $curl) * * @throws \Exception */ - protected function determineSuccess($response, $formattedResponse, $timeout) + protected function determineSuccess(array $response, $formattedResponse, int $timeout): bool { $status = $this->findHTTPStatus($response, $formattedResponse); @@ -602,12 +603,12 @@ protected function determineSuccess($response, $formattedResponse, $timeout) } if (isset($formattedResponse['message'])) { - $this->last_error = sprintf('%s %d: %s', $formattedResponse['status'], $formattedResponse['code'], $formattedResponse['message']); + $this->last_error = sprintf('%s %d: %s', (string) $formattedResponse['status'], (int) $formattedResponse['code'], (string) $formattedResponse['message']); throw new Exception($this->last_error); } - if ($timeout > 0 && $response['headers'] && $response['headers']['total_time'] >= $timeout) { - $this->last_error = sprintf('Request timed out after %f seconds.', $response['headers']['total_time']); + if (isset($response['headers']['total_time']) && $timeout > 0 && $response['headers']['total_time'] >= $timeout) { + $this->last_error = sprintf('Request timed out after %f seconds.', (float) $response['headers']['total_time']); throw new Exception($this->last_error); } @@ -626,7 +627,7 @@ protected function determineSuccess($response, $formattedResponse, $timeout) * @return int * HTTP status code */ - protected function findHTTPStatus($response, $formattedResponse) + protected function findHTTPStatus(array $response, $formattedResponse): int { if (!empty($response['headers']) && isset($response['headers']['http_code'])) { return (int) $response['headers']['http_code'];