diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index f5d1843e..310de04b 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -124,7 +124,7 @@ jobs: cs: runs-on: ubuntu-20.04 - name: CS tests + name: CS & PHPSTAN tests steps: - uses: actions/checkout@v2 @@ -142,3 +142,6 @@ jobs: - name: Run CS tests run: vendor/bin/php-cs-fixer fix --config=.php_cs -v --dry-run --using-cache=no --show-progress=dots --diff $(git diff -- '*.php' --name-only --diff-filter=ACMRTUXB "HEAD~..HEAD") + + - name: Run PHPSTAN + run: composer phpstan diff --git a/.gitignore b/.gitignore index c847cd4a..42f512e9 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ .phpunit.result.cache /.ddev/mautic-preference /mautic +.php_cs.cache diff --git a/composer.json b/composer.json index 1ae1c54e..b9b092cf 100644 --- a/composer.json +++ b/composer.json @@ -23,9 +23,12 @@ "raveren/kint": "~0.9", "friendsofphp/php-cs-fixer": "~2.16.1", "phpunit/phpunit": "~9.5.0", - "brianium/paratest": "^6.2" + "brianium/paratest": "^6.2", + "phpstan/phpstan": "^0.12.78" }, "scripts": { - "test": "vendor/bin/paratest" + "test": "vendor/bin/paratest", + "phpstan": "vendor/bin/phpstan analyse", + "cs": "vendor/bin/php-cs-fixer fix --config=.php_cs" } } diff --git a/composer.lock b/composer.lock index 594042a9..6408d094 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "12efc0f4bf879266563111bdc11dd051", + "content-hash": "8a2161a83a0ac0534a47ba6b3e6e0f74", "packages": [ { "name": "psr/log", @@ -51,9 +51,6 @@ "psr", "psr-3" ], - "support": { - "source": "https://github.com/php-fig/log/tree/1.1.3" - }, "time": "2020-03-23T09:12:05+00:00" } ], @@ -482,10 +479,6 @@ "parser", "php" ], - "support": { - "issues": "https://github.com/doctrine/lexer/issues", - "source": "https://github.com/doctrine/lexer/tree/1.2.1" - }, "funding": [ { "url": "https://www.doctrine-project.org/sponsorship.html", @@ -929,10 +922,6 @@ "reflection", "static analysis" ], - "support": { - "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", - "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x" - }, "time": "2020-06-27T09:03:43+00:00" }, { @@ -985,10 +974,6 @@ } ], "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "support": { - "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", - "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/master" - }, "time": "2020-09-03T19:13:55+00:00" }, { @@ -1034,10 +1019,6 @@ } ], "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", - "support": { - "issues": "https://github.com/phpDocumentor/TypeResolver/issues", - "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.4.0" - }, "time": "2020-09-17T18:55:26+00:00" }, { @@ -1107,6 +1088,62 @@ }, "time": "2020-12-19T10:15:11+00:00" }, + { + "name": "phpstan/phpstan", + "version": "0.12.78", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan.git", + "reference": "eecce8d2ee3cac6769f37b4cb1998b2715f82984" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/eecce8d2ee3cac6769f37b4cb1998b2715f82984", + "reference": "eecce8d2ee3cac6769f37b4cb1998b2715f82984", + "shasum": "" + }, + "require": { + "php": "^7.1|^8.0" + }, + "conflict": { + "phpstan/phpstan-shim": "*" + }, + "bin": [ + "phpstan", + "phpstan.phar" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "0.12-dev" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPStan - PHP Static Analysis Tool", + "funding": [ + { + "url": "https://github.com/ondrejmirtes", + "type": "github" + }, + { + "url": "https://www.patreon.com/phpstan", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan", + "type": "tidelift" + } + ], + "time": "2021-02-20T13:24:36+00:00" + }, { "name": "phpunit/php-code-coverage", "version": "9.2.5", @@ -1563,10 +1600,6 @@ "container-interop", "psr" ], - "support": { - "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container/tree/master" - }, "time": "2017-02-14T16:28:37+00:00" }, { @@ -1613,10 +1646,6 @@ "psr", "psr-14" ], - "support": { - "issues": "https://github.com/php-fig/event-dispatcher/issues", - "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" - }, "time": "2019-01-08T18:20:26+00:00" }, { @@ -1668,10 +1697,6 @@ "kint", "php" ], - "support": { - "issues": "https://github.com/raveren/kint/issues", - "source": "https://github.com/raveren/kint/tree/v0.9.1" - }, "abandoned": "kint-php/kint", "time": "2014-08-11T11:44:51+00:00" }, @@ -2760,9 +2785,6 @@ ], "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/master" - }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -2924,9 +2946,6 @@ "interoperability", "standards" ], - "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v2.2.0" - }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -3887,9 +3906,6 @@ "interoperability", "standards" ], - "support": { - "source": "https://github.com/symfony/service-contracts/tree/master" - }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -4089,10 +4105,6 @@ } ], "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", - "support": { - "issues": "https://github.com/theseer/tokenizer/issues", - "source": "https://github.com/theseer/tokenizer/tree/master" - }, "funding": [ { "url": "https://github.com/theseer", @@ -4106,12 +4118,12 @@ "version": "1.9.1", "source": { "type": "git", - "url": "https://github.com/webmozarts/assert.git", + "url": "https://github.com/webmozart/assert.git", "reference": "bafc69caeb4d49c39fd0779086c03a3738cbb389" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webmozarts/assert/zipball/bafc69caeb4d49c39fd0779086c03a3738cbb389", + "url": "https://api.github.com/repos/webmozart/assert/zipball/bafc69caeb4d49c39fd0779086c03a3738cbb389", "reference": "bafc69caeb4d49c39fd0779086c03a3738cbb389", "shasum": "" }, @@ -4148,10 +4160,6 @@ "check", "validate" ], - "support": { - "issues": "https://github.com/webmozart/assert/issues", - "source": "https://github.com/webmozart/assert/tree/master" - }, "time": "2020-07-08T17:02:28+00:00" } ], diff --git a/lib/Api/Api.php b/lib/Api/Api.php index 01b3825f..03fc9422 100644 --- a/lib/Api/Api.php +++ b/lib/Api/Api.php @@ -10,7 +10,7 @@ namespace Mautic\Api; -use Mautic\Auth\ApiAuth; +use Mautic\Auth\AbstractAuth; use Mautic\Auth\AuthInterface; use Mautic\QueryBuilder\QueryBuilder; use Psr\Log\LoggerAwareInterface; @@ -86,7 +86,7 @@ class Api implements LoggerAwareInterface protected $searchCommands = []; /** - * @var ApiAuth + * @var AbstractAuth */ private $auth; diff --git a/lib/MauticApi.php b/lib/MauticApi.php index 15c44ba8..b7bd04c9 100644 --- a/lib/MauticApi.php +++ b/lib/MauticApi.php @@ -37,7 +37,7 @@ public static function getContext($apiContext, AuthInterface $auth, $baseUrl = ' $apiContext = ucfirst($apiContext); - if (!isset($context[$apiContext])) { + if (!isset($contexts[$apiContext])) { $class = 'Mautic\\Api\\'.$apiContext; if (!class_exists($class)) { diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 00000000..5a13f47c --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,5 @@ +parameters: + level: 1 + paths: + - lib + - tests diff --git a/tests/Api/AssetsTest.php b/tests/Api/AssetsTest.php index 05757bfe..fedccc9d 100644 --- a/tests/Api/AssetsTest.php +++ b/tests/Api/AssetsTest.php @@ -10,6 +10,8 @@ namespace Mautic\Tests\Api; +use Mautic\Api\Files; + class AssetsTest extends MauticApiTestCase { protected $skipPayloadAssertion = ['file']; @@ -37,12 +39,13 @@ public function testGetListOfSpecificIds() public function testCreateWithLocalFileGetAndDelete() { // Upload a testing file - $this->apiFiles = $this->getContext('files'); - $this->apiFiles->setFolder('assets'); + /** @var Files */ + $apiFiles = $this->getContext('files'); + $apiFiles->setFolder('assets'); $fileRequest = [ 'file' => dirname(__DIR__).'/'.'mauticlogo.png', ]; - $response = $this->apiFiles->create($fileRequest); + $response = $apiFiles->create($fileRequest); $this->assertErrors($response); $file = $response['file']; diff --git a/tests/Api/CampaignsTest.php b/tests/Api/CampaignsTest.php index 143055ac..042c171d 100644 --- a/tests/Api/CampaignsTest.php +++ b/tests/Api/CampaignsTest.php @@ -471,7 +471,7 @@ public function testCampaignContactEditEvent() $date = new \DateTime($log['triggerDate'], new \DateTimeZone('UTC')); $this->assertEquals($log['triggerDate'], $date->format('c')); } else { - $this->assertFalse(false, 'Event ID not recognized in the log.', var_export($event, true)); + $this->assertFalse(var_export($event, true), 'Event ID not recognized in the log.'); } } diff --git a/tests/Api/FormsTest.php b/tests/Api/FormsTest.php index a56005d2..cbc8c2c3 100644 --- a/tests/Api/FormsTest.php +++ b/tests/Api/FormsTest.php @@ -10,8 +10,13 @@ namespace Mautic\Tests\Api; +use Mautic\Api\Forms; + class FormsTest extends MauticApiTestCase { + /** @var Forms */ + protected $api; + public function setUp(): void { $this->api = $this->getContext('forms'); @@ -218,10 +223,15 @@ public function testFormSubmissions() $response = $this->api->getSubmissions($formId); $this->assertErrors($response); - foreach ($response['submissions'] as $submission) { + $submissions = $response['submissions']; + $this->assertTrue(count($submissions) > 0, 'Expected at least one form submission'); + + foreach ($submissions as $submission) { $this->assertSubmission($submission, $formId); } + $submission = end($submissions); + // Try to fetch the last submission $response = $this->api->getSubmission($formId, $submission['id']); $this->assertErrors($response); diff --git a/tests/Api/MauticApiTestCase.php b/tests/Api/MauticApiTestCase.php index 2beaa7e7..58232ec3 100644 --- a/tests/Api/MauticApiTestCase.php +++ b/tests/Api/MauticApiTestCase.php @@ -43,7 +43,7 @@ protected function getAuth() $auth = $apiAuth->newAuth($this->config, $authMethod); if ('BasicAuth' != $authMethod) { if (empty($this->config['refreshToken']) && !$auth->isAuthorized()) { - $this->assertTrue($authorized, 'Authorization failed. Check credentials in local.config.php.'); + $this->assertTrue($auth->isAuthorized(), 'Authorization failed. Check credentials in local.config.php.'); } else { try { $auth->validateAccessToken(); @@ -179,7 +179,7 @@ protected function standardTestGetListOfSpecificIds($callback = null) $itemIds[] = $response[$this->api->itemName()]['id']; } - if (is_callable($callback)) { + if (is_callable($callback) && !empty($response)) { // Allow support to make additional tests based on created associations with this item that // may not have create/edit endpoints $callback($response); diff --git a/tests/Api/UtmTagsTest.php b/tests/Api/UtmTagsTest.php index eadffe41..6339403c 100644 --- a/tests/Api/UtmTagsTest.php +++ b/tests/Api/UtmTagsTest.php @@ -150,7 +150,11 @@ protected function removeUtmTags($utmIds) } } - $this->assertSame(0, count($response[$this->api->itemName()]['utmtags']), 'Should be no more items'); + if (!empty($response)) { + $this->assertSame(0, count($response[$this->api->itemName()]['utmtags']), 'Should be no more items'); + } else { + throw new \Exception('Expected a reponse object'); + } } protected function addUtmTags()