From 1022e36093d3b9a3a0120009b25b9cede1cba3a8 Mon Sep 17 00:00:00 2001 From: Kevin Pfeifer Date: Sun, 15 Oct 2023 10:40:47 +0200 Subject: [PATCH 1/2] Cake5 upgrade --- .github/workflows/ci.yml | 18 +++--- .gitignore | 2 +- composer.json | 10 ++-- phpcs.xml | 6 ++ phpunit.xml.dist | 42 ++++++++------ src/Database/Type/SerializedType.php | 16 +++--- src/Middleware/SocialAuthMiddleware.php | 42 +++++++------- src/Model/Entity/SocialProfile.php | 2 +- src/Model/Table/SocialProfilesTable.php | 15 +---- src/Plugin.php | 4 +- tests/Fixture/SocialProfilesFixture.php | 56 ------------------- tests/Fixture/UsersFixture.php | 39 ------------- .../Middleware/SocialAuthMiddlewareTest.php | 13 ++--- .../Model/Table/SocialProfilesTableTest.php | 11 +--- tests/bootstrap.php | 7 --- tests/schema.php | 39 +++++++++++++ .../test_app/src/Http/TestRequestHandler.php | 2 +- 17 files changed, 126 insertions(+), 198 deletions(-) create mode 100644 phpcs.xml delete mode 100644 tests/Fixture/SocialProfilesFixture.php delete mode 100644 tests/Fixture/UsersFixture.php create mode 100644 tests/schema.php diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2fcf09e..8a49014 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,15 +10,15 @@ on: jobs: testsuite: - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 strategy: fail-fast: false matrix: - php-version: ['7.4', '8.0', '8.1'] + php-version: ['8.1', '8.2'] db-type: [sqlite, mysql, pgsql] prefer-lowest: [''] include: - - php-version: '7.2' + - php-version: '8.1' db-type: 'sqlite' prefer-lowest: 'prefer-lowest' @@ -31,7 +31,7 @@ jobs: POSTGRES_PASSWORD: postgres steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Setup Service if: matrix.db-type == 'mysql' @@ -62,14 +62,14 @@ jobs: if [[ ${{ matrix.db-type }} == 'sqlite' ]]; then export DB_URL='sqlite:///:memory:'; fi if [[ ${{ matrix.db-type }} == 'mysql' ]]; then export DB_URL='mysql://root:root@127.0.0.1/cakephp'; fi if [[ ${{ matrix.db-type }} == 'pgsql' ]]; then export DB_URL='postgres://postgres:postgres@127.0.0.1/postgres'; fi - if [[ ${{ matrix.php-version }} == '7.4' ]]; then + if [[ ${{ matrix.php-version }} == '8.1' ]]; then vendor/bin/phpunit --coverage-clover=coverage.xml else vendor/bin/phpunit fi - name: Code Coverage Report - if: success() && matrix.php-version == '7.4' + if: success() && matrix.php-version == '8.1' uses: codecov/codecov-action@v3 cs-stan: @@ -77,12 +77,12 @@ jobs: runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Setup PHP uses: shivammathur/setup-php@v2 with: - php-version: '7.4' + php-version: '8.1' extensions: mbstring, intl coverage: none tools: cs2pr, vimeo/psalm:4, phpstan:1 @@ -91,7 +91,7 @@ jobs: run: composer install - name: Run phpcs - run: vendor/bin/phpcs -q --report=checkstyle --standard=vendor/cakephp/cakephp-codesniffer/CakePHP src/ tests/ | cs2pr + run: vendor/bin/phpcs --report=checkstyle src/ tests/ | cs2pr - name: Run psalm if: always() diff --git a/.gitignore b/.gitignore index 60785c7..c99e558 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ /composer.lock /phpunit.xml /vendor/ -.phpunit.result.cache +/.phpunit.cache /.idea/ /config/Migrations/schema-dump-default.lock diff --git a/composer.json b/composer.json index 676cfea..d3225bc 100644 --- a/composer.json +++ b/composer.json @@ -3,12 +3,12 @@ "description": "A CakePHP plugin which allows you to authenticate using social providers like Facebook/Google/Twitter etc.", "type": "cakephp-plugin", "require": { - "cakephp/cakephp": "^4.1", + "cakephp/cakephp": "^5.0", "socialconnect/auth": "^3.1" }, "require-dev": { - "phpunit/phpunit": "^8.5.0 || ^9.5.0", - "cakephp/cakephp-codesniffer": "^4.0" + "phpunit/phpunit": "^10.1", + "cakephp/cakephp-codesniffer": "^5.0" }, "autoload": { "psr-4": { @@ -24,8 +24,8 @@ }, "license": "MIT", "scripts": { - "cs-check": "vendor/bin/phpcs -n -p --extensions=php --standard=vendor/cakephp/cakephp-codesniffer/CakePHP src/ tests/", - "cs-fix": "vendor/bin/phpcbf -p --extensions=php --standard=vendor/cakephp/cakephp-codesniffer/CakePHP src/ tests/" + "cs-check": "phpcs --colors -p ./src ./tests", + "cs-fix": "phpcbf --colors -p ./src ./tests" }, "config": { "allow-plugins": { diff --git a/phpcs.xml b/phpcs.xml new file mode 100644 index 0000000..210a0c8 --- /dev/null +++ b/phpcs.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 4974a28..d2bb38c 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,9 +1,10 @@ - + @@ -11,19 +12,24 @@ - - - - - - - - + + + - - + + src/ - - + + + + + + + + + diff --git a/src/Database/Type/SerializedType.php b/src/Database/Type/SerializedType.php index 41320b4..19f7e25 100644 --- a/src/Database/Type/SerializedType.php +++ b/src/Database/Type/SerializedType.php @@ -10,7 +10,7 @@ namespace ADmad\SocialAuth\Database\Type; -use Cake\Database\DriverInterface; +use Cake\Database\Driver; use Cake\Database\Type\BaseType; use PDO; @@ -20,10 +20,10 @@ class SerializedType extends BaseType * Convert a value data into a serialized string. * * @param mixed $value The value to convert. - * @param \Cake\Database\DriverInterface $driver The driver instance to convert with. + * @param \Cake\Database\Driver $driver The driver instance to convert with. * @return string|null */ - public function toDatabase($value, DriverInterface $driver) + public function toDatabase(mixed $value, Driver $driver): mixed { if ($value === null || is_string($value)) { return $value; @@ -36,10 +36,10 @@ public function toDatabase($value, DriverInterface $driver) * Convert string values to PHP data structure. * * @param mixed $value The value to convert. - * @param \Cake\Database\DriverInterface $driver The driver instance to convert with. + * @param \Cake\Database\Driver $driver The driver instance to convert with. * @return mixed */ - public function toPHP($value, DriverInterface $driver) + public function toPHP(mixed $value, Driver $driver): mixed { if ($value === null) { return $value; @@ -58,10 +58,10 @@ public function toPHP($value, DriverInterface $driver) * Get the correct PDO binding type for string data. * * @param mixed $value The value being bound. - * @param \Cake\Database\DriverInterface $driver The driver. + * @param \Cake\Database\Driver $driver The driver. * @return int */ - public function toStatement($value, DriverInterface $driver) + public function toStatement(mixed $value, Driver $driver): int { if ($value === null) { return PDO::PARAM_NULL; @@ -76,7 +76,7 @@ public function toStatement($value, DriverInterface $driver) * @param mixed $value The value to convert. * @return mixed Converted value. */ - public function marshal($value) + public function marshal(mixed $value): mixed { if (is_array($value) || $value === null) { return $value; diff --git a/src/Middleware/SocialAuthMiddleware.php b/src/Middleware/SocialAuthMiddleware.php index e27ac12..8d431b8 100644 --- a/src/Middleware/SocialAuthMiddleware.php +++ b/src/Middleware/SocialAuthMiddleware.php @@ -22,8 +22,10 @@ use Cake\Http\Session as CakeSession; use Cake\Log\Log; use Cake\ORM\Locator\LocatorAwareTrait; +use Cake\ORM\Table; use Cake\Routing\Router; use Cake\Utility\Hash; +use Exception; use Laminas\Diactoros\RequestFactory; use Laminas\Diactoros\StreamFactory; use Psr\Http\Message\ResponseInterface; @@ -127,7 +129,7 @@ class SocialAuthMiddleware implements MiddlewareInterface, EventDispatcherInterf * * @var array */ - protected $_defaultConfig = [ + protected array $_defaultConfig = [ 'requestMethod' => 'POST', 'loginUrl' => '/users/login', 'loginRedirect' => '/', @@ -150,35 +152,35 @@ class SocialAuthMiddleware implements MiddlewareInterface, EventDispatcherInterf * * @var \SocialConnect\Auth\Service|null */ - protected $_service; + protected ?Service $_service = null; /** * Session for SocialConnect service. * * @var \SocialConnect\Provider\Session\SessionInterface|null */ - protected $_session; + protected ?SessionInterface $_session; /** * User model instance. * * @var \Cake\ORM\Table */ - protected $_userModel; + protected Table $_userModel; /** * Profile model instance. * * @var \Cake\ORM\Table */ - protected $_profileModel; + protected Table $_profileModel; /** * Error. * * @var string */ - protected $_error; + protected string $_error; /** * Constructor. @@ -322,7 +324,7 @@ protected function _setupModelInstances(): void * @param \Cake\Http\ServerRequest $request Request instance. * @return \Cake\Datasource\EntityInterface|null */ - protected function _getProfile($providerName, ServerRequest $request): ?EntityInterface + protected function _getProfile(string $providerName, ServerRequest $request): ?EntityInterface { $return = $this->_getSocialIdentity($providerName, $request); if ($return === null) { @@ -352,7 +354,7 @@ protected function _getProfile($providerName, ServerRequest $request): ?EntityIn * @param \Cake\Http\ServerRequest $request Request instance. * @return array{identity: \SocialConnect\Common\Entity\User, access_token: \SocialConnect\Provider\AccessTokenInterface}|null */ - protected function _getSocialIdentity($providerName, ServerRequest $request): ?array + protected function _getSocialIdentity(string $providerName, ServerRequest $request): ?array { try { $provider = $this->_getService($request)->getProvider($providerName); @@ -444,11 +446,11 @@ protected function _getUser(EntityInterface $profile, CakeSession $session): ?En * @param string $providerName Provider name. * @param \SocialConnect\Common\Entity\User $identity Social connect entity. * @param \SocialConnect\Provider\AccessTokenInterface $accessToken Access token - * @param \Cake\Datasource\EntityInterface $profile Social profile entity + * @param \Cake\Datasource\EntityInterface|null $profile Social profile entity * @return \Cake\Datasource\EntityInterface */ protected function _patchProfile( - $providerName, + string $providerName, SocialConnectUser $identity, AccessTokenInterface $accessToken, ?EntityInterface $profile = null @@ -603,8 +605,8 @@ protected function _setRedirectUrl(ServerRequest $request): void $redirectUrl = $request->getQuery(static::QUERY_STRING_REDIRECT); if ( empty($redirectUrl) - || substr($redirectUrl, 0, 1) !== '/' - || substr($redirectUrl, 0, 2) === '//' + || !str_starts_with($redirectUrl, '/') + || str_starts_with($redirectUrl, '//') ) { return; } @@ -616,9 +618,9 @@ protected function _setRedirectUrl(ServerRequest $request): void * Get URL to redirect to after authentication. * * @param \Cake\Http\ServerRequest $request Request instance. - * @return string|array + * @return array|string */ - protected function _getRedirectUrl(ServerRequest $request) + protected function _getRedirectUrl(ServerRequest $request): array|string { $redirectUrl = $request->getSession()->read('SocialAuth.redirectUrl'); if ($redirectUrl) { @@ -634,15 +636,15 @@ protected function _getRedirectUrl(ServerRequest $request) * Trigger "beforeRedirect" event. * * @param \Psr\Http\Message\ServerRequestInterface $request Request instance. - * @param string|array $redirectUrl Redirect URL. + * @param array|string $redirectUrl Redirect URL. * @param string $status Auth status. - * @return string|array + * @return array|string */ protected function _triggerBeforeRedirect( - $request, - $redirectUrl, + ServerRequestInterface $request, + array|string $redirectUrl, string $status = self::AUTH_STATUS_SUCCESS - ) { + ): array|string { $event = $this->dispatchEvent(self::EVENT_BEFORE_REDIRECT, [ 'redirectUrl' => $redirectUrl, 'status' => $status, @@ -664,7 +666,7 @@ protected function _triggerBeforeRedirect( * @param \Exception $exception The exception to log a message for. * @return string Error message */ - protected function _getLogMessage($request, $exception): string + protected function _getLogMessage(ServerRequestInterface $request, Exception $exception): string { $message = sprintf( '[%s] %s', diff --git a/src/Model/Entity/SocialProfile.php b/src/Model/Entity/SocialProfile.php index 6a55cee..a63b195 100644 --- a/src/Model/Entity/SocialProfile.php +++ b/src/Model/Entity/SocialProfile.php @@ -35,7 +35,7 @@ class SocialProfile extends Entity /** * @var array */ - protected $_accessible = [ + protected array $_accessible = [ '*' => true, 'id' => false, ]; diff --git a/src/Model/Table/SocialProfilesTable.php b/src/Model/Table/SocialProfilesTable.php index 171d149..a083ce0 100644 --- a/src/Model/Table/SocialProfilesTable.php +++ b/src/Model/Table/SocialProfilesTable.php @@ -10,7 +10,6 @@ namespace ADmad\SocialAuth\Model\Table; -use Cake\Database\Schema\TableSchemaInterface; use Cake\ORM\Table; /** @@ -42,18 +41,6 @@ public function initialize(array $config): void parent::initialize($config); $this->addBehavior('Timestamp'); - } - - /** - * Set custom type of "access_token" column. - * - * @param \Cake\Database\Schema\TableSchemaInterface $schema The table definition fetched from database. - * @return \Cake\Database\Schema\TableSchemaInterface - */ - protected function _initializeSchema(TableSchemaInterface $schema): TableSchemaInterface - { - $schema->setColumnType('access_token', 'social-auth.serialized'); - - return $schema; + $this->getSchema()->setColumnType('access_token', 'social-auth.serialized'); } } diff --git a/src/Plugin.php b/src/Plugin.php index bed64a1..eee9132 100644 --- a/src/Plugin.php +++ b/src/Plugin.php @@ -21,7 +21,7 @@ class Plugin extends BasePlugin /** * @var bool */ - protected $consoleEnabled = false; + protected bool $consoleEnabled = false; /** * @param \Cake\Core\PluginApplicationInterface $app Application instance. @@ -41,7 +41,7 @@ public function routes(RouteBuilder $routes): void $routes->scope( '/social-auth', ['plugin' => 'ADmad/SocialAuth', 'controller' => 'Auth'], - function (RouteBuilder $routes) { + function (RouteBuilder $routes): void { $routes->connect( '/login/{provider}', ['action' => 'login'], diff --git a/tests/Fixture/SocialProfilesFixture.php b/tests/Fixture/SocialProfilesFixture.php deleted file mode 100644 index 24a422e..0000000 --- a/tests/Fixture/SocialProfilesFixture.php +++ /dev/null @@ -1,56 +0,0 @@ - ['type' => 'integer', 'length' => null, 'unsigned' => false, 'null' => false, 'default' => null, 'autoIncrement' => true], - 'user_id' => ['type' => 'integer', 'length' => null, 'unsigned' => false, 'null' => true, 'default' => null, 'autoIncrement' => null], - 'provider' => ['type' => 'string', 'length' => 255, 'null' => false, 'default' => null], - 'access_token' => ['type' => 'binary', 'length' => null, 'null' => false, 'default' => null], - 'identifier' => ['type' => 'string', 'length' => 255, 'null' => false, 'default' => null], - 'username' => ['type' => 'string', 'length' => 255, 'null' => true, 'default' => null], - 'first_name' => ['type' => 'string', 'length' => 255, 'null' => true, 'default' => null], - 'last_name' => ['type' => 'string', 'length' => 255, 'null' => true, 'default' => null], - 'full_name' => ['type' => 'string', 'length' => 255, 'null' => true, 'default' => null], - 'email' => ['type' => 'string', 'length' => 255, 'null' => true, 'default' => null], - 'birth_date' => ['type' => 'date', 'length' => null, 'null' => true, 'default' => null], - 'gender' => ['type' => 'string', 'length' => 255, 'null' => true, 'default' => null], - 'picture_url' => ['type' => 'string', 'length' => 255, 'null' => true, 'default' => null], - 'email_verified' => ['type' => 'boolean', 'length' => null, 'null' => false, 'default' => '0'], - 'created' => ['type' => 'datetime', 'length' => null, 'null' => true, 'default' => null], - 'modified' => ['type' => 'datetime', 'length' => null, 'null' => true, 'default' => null], - '_indexes' => [ - 'user_id' => ['type' => 'index', 'columns' => ['user_id'], 'length' => []], - ], - '_constraints' => [ - 'primary' => ['type' => 'primary', 'columns' => ['id'], 'length' => []], - ], - ]; - // phpcs:enable - - /** - * Init method - * - * @return void - */ - public function init(): void - { - $this->records = []; - - parent::init(); - } -} diff --git a/tests/Fixture/UsersFixture.php b/tests/Fixture/UsersFixture.php deleted file mode 100644 index 647e7d4..0000000 --- a/tests/Fixture/UsersFixture.php +++ /dev/null @@ -1,39 +0,0 @@ - ['type' => 'integer', 'length' => null, 'unsigned' => false, 'null' => false, 'default' => null, 'autoIncrement' => true], - 'email' => ['type' => 'string', 'length' => 255, 'null' => true, 'default' => null], - '_constraints' => [ - 'primary' => ['type' => 'primary', 'columns' => ['id'], 'length' => []], - ], - ]; - // phpcs:enable - - /** - * Init method - * - * @return void - */ - public function init(): void - { - $this->records = []; - - parent::init(); - } -} diff --git a/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php b/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php index b336a6f..eebdf34 100644 --- a/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php +++ b/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php @@ -10,23 +10,20 @@ use Cake\Event\EventManager; use Cake\Http\Exception\MethodNotAllowedException; use Cake\Http\Response; +use Cake\Http\ServerRequest; use Cake\Http\ServerRequestFactory; use Cake\TestSuite\TestCase; +use Psr\Http\Server\RequestHandlerInterface; use SocialConnect\Common\Entity\User; use SocialConnect\Provider\AccessTokenInterface; use SocialConnect\Provider\Session\Dummy; use TestApp\Http\TestRequestHandler; -/** - * @property \Cake\Http\ServerRequest $request - * @property \Psr\Http\Server\RequestHandlerInterface $handler - */ class SocialAuthMiddlewareTest extends TestCase { - protected $fixtures = [ - 'plugin.ADmad/SocialAuth.Users', - 'plugin.ADmad/SocialAuth.SocialProfiles', - ]; + protected ServerRequest $request; + + protected RequestHandlerInterface $handler; public function setUp(): void { diff --git a/tests/TestCase/Model/Table/SocialProfilesTableTest.php b/tests/TestCase/Model/Table/SocialProfilesTableTest.php index cf002fd..30d2624 100644 --- a/tests/TestCase/Model/Table/SocialProfilesTableTest.php +++ b/tests/TestCase/Model/Table/SocialProfilesTableTest.php @@ -3,19 +3,12 @@ namespace ADmad\SocialAuth\Test\TestCase\Model\Table; +use ADmad\SocialAuth\Model\Table\SocialProfilesTable; use Cake\TestSuite\TestCase; -/** - * @property \ADmad\SocialAuth\Model\Table\SocialProfilesTable $socialProfilesTable - */ class SocialProfilesTableTest extends TestCase { - /** - * @var string[] - */ - protected $fixtures = [ - 'plugin.ADmad/SocialAuth.SocialProfiles', - ]; + protected SocialProfilesTable $socialProfilesTable; /** * @return void diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 1f6835f..9f7192c 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -1,8 +1,6 @@ 'social_profiles', + 'columns' => [ + 'id' => ['type' => 'integer', 'length' => null, 'unsigned' => false, 'null' => false, 'default' => null, 'autoIncrement' => true], + 'user_id' => ['type' => 'integer', 'length' => null, 'unsigned' => false, 'null' => true, 'default' => null, 'autoIncrement' => null], + 'provider' => ['type' => 'string', 'length' => 255, 'null' => false, 'default' => null], + 'access_token' => ['type' => 'binary', 'length' => null, 'null' => false, 'default' => null], + 'identifier' => ['type' => 'string', 'length' => 255, 'null' => false, 'default' => null], + 'username' => ['type' => 'string', 'length' => 255, 'null' => true, 'default' => null], + 'first_name' => ['type' => 'string', 'length' => 255, 'null' => true, 'default' => null], + 'last_name' => ['type' => 'string', 'length' => 255, 'null' => true, 'default' => null], + 'full_name' => ['type' => 'string', 'length' => 255, 'null' => true, 'default' => null], + 'email' => ['type' => 'string', 'length' => 255, 'null' => true, 'default' => null], + 'birth_date' => ['type' => 'date', 'length' => null, 'null' => true, 'default' => null], + 'gender' => ['type' => 'string', 'length' => 255, 'null' => true, 'default' => null], + 'picture_url' => ['type' => 'string', 'length' => 255, 'null' => true, 'default' => null], + 'email_verified' => ['type' => 'boolean', 'length' => null, 'null' => false, 'default' => '0'], + 'created' => ['type' => 'datetime', 'length' => null, 'null' => true, 'default' => null], + 'modified' => ['type' => 'datetime', 'length' => null, 'null' => true, 'default' => null], + ], + 'constraints' => [ + 'primary' => ['type' => 'primary', 'columns' => ['id'], 'length' => []], + ], + ], + [ + 'table' => 'users', + 'columns' => [ + 'id' => ['type' => 'integer', 'length' => null, 'unsigned' => false, 'null' => false, 'default' => null, 'autoIncrement' => true], + 'email' => ['type' => 'string', 'length' => 255, 'null' => true, 'default' => null], + ], + 'constraints' => [ + 'primary' => ['type' => 'primary', 'columns' => ['id'], 'length' => []], + ], + ], +]; diff --git a/tests/test_app/src/Http/TestRequestHandler.php b/tests/test_app/src/Http/TestRequestHandler.php index cef398f..77ada6e 100644 --- a/tests/test_app/src/Http/TestRequestHandler.php +++ b/tests/test_app/src/Http/TestRequestHandler.php @@ -12,7 +12,7 @@ class TestRequestHandler implements RequestHandlerInterface { public $callable; - public $called = false; + public bool $called = false; public function __construct(?callable $callable = null) { From c8c779e1e3d5497c20b6b0fac728fec38cf5aee2 Mon Sep 17 00:00:00 2001 From: Kevin Pfeifer Date: Sun, 15 Oct 2023 11:04:37 +0200 Subject: [PATCH 2/2] use phive setup for stan --- .github/workflows/ci.yml | 17 ++++++++++------- .gitignore | 1 + .phive/phars.xml | 5 +++++ composer.json | 12 +++++++++++- phpstan-baseline.neon | 11 +++++++++++ phpstan.neon | 8 +++----- psalm.xml | 3 +++ src/Middleware/SocialAuthMiddleware.php | 8 ++++++-- src/Model/Table/SocialProfilesTable.php | 10 +++++----- 9 files changed, 55 insertions(+), 20 deletions(-) create mode 100644 .phive/phars.xml create mode 100644 phpstan-baseline.neon diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8a49014..89f9198 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -74,7 +74,7 @@ jobs: cs-stan: name: Coding Standard & Static Analysis - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 @@ -85,18 +85,21 @@ jobs: php-version: '8.1' extensions: mbstring, intl coverage: none - tools: cs2pr, vimeo/psalm:4, phpstan:1 + tools: phive, cs2pr + + - name: Composer install + uses: ramsey/composer-install@v2 - - name: Composer Install - run: composer install + - name: Install PHP tools with phive. + run: "phive install --trust-gpg-keys 'CF1A108D0E7AE720,51C67305FFC2E5C0,12CE0F1D262429A5'" - name: Run phpcs run: vendor/bin/phpcs --report=checkstyle src/ tests/ | cs2pr - name: Run psalm if: always() - run: psalm --output-format=github + run: tools/psalm --output-format=github - - name: Run psalm + - name: Run phpstan if: always() - run: phpstan analyse + run: tools/phpstan analyse --error-format=github diff --git a/.gitignore b/.gitignore index c99e558..5964e8e 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ /.phpunit.cache /.idea/ /config/Migrations/schema-dump-default.lock +/tools diff --git a/.phive/phars.xml b/.phive/phars.xml new file mode 100644 index 0000000..17093fd --- /dev/null +++ b/.phive/phars.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/composer.json b/composer.json index d3225bc..79bf4bd 100644 --- a/composer.json +++ b/composer.json @@ -25,7 +25,17 @@ "license": "MIT", "scripts": { "cs-check": "phpcs --colors -p ./src ./tests", - "cs-fix": "phpcbf --colors -p ./src ./tests" + "cs-fix": "phpcbf --colors -p ./src ./tests", + "test": "phpunit", + "phpstan": "tools/phpstan analyse", + "psalm": "tools/psalm --show-info=false", + "stan": [ + "@phpstan", + "@psalm" + ], + "phpstan-baseline": "tools/phpstan --generate-baseline", + "psalm-baseline": "tools/psalm --set-baseline=psalm-baseline.xml", + "stan-setup": "phive install" }, "config": { "allow-plugins": { diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon new file mode 100644 index 0000000..3192ef8 --- /dev/null +++ b/phpstan-baseline.neon @@ -0,0 +1,11 @@ +parameters: + ignoreErrors: + - + message: "#^Parameter \\#1 \\$callback of function call_user_func expects callable\\(\\)\\: mixed, array\\{Cake\\\\ORM\\\\Table, mixed\\} given\\.$#" + count: 1 + path: src/Middleware/SocialAuthMiddleware.php + + - + message: "#^Method ADmad\\\\SocialAuth\\\\Plugin\\:\\:bootstrap\\(\\) has parameter \\$app with generic interface Cake\\\\Core\\\\PluginApplicationInterface but does not specify its types\\: TSubject$#" + count: 1 + path: src/Plugin.php diff --git a/phpstan.neon b/phpstan.neon index 19914e0..8cdbddf 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,3 +1,6 @@ +includes: + - phpstan-baseline.neon + parameters: level: 8 checkMissingIterableValueType: false @@ -5,8 +8,3 @@ parameters: - tests/bootstrap.php paths: - src/ - ignoreErrors: - - - message: "#^Parameter \\#1 \\$function of function call_user_func expects callable\\(\\)\\: mixed, array\\{Cake\\\\ORM\\\\Table, mixed\\} given\\.$#" - count: 1 - path: src/Middleware/SocialAuthMiddleware.php diff --git a/psalm.xml b/psalm.xml index 5359f52..b538299 100644 --- a/psalm.xml +++ b/psalm.xml @@ -1,5 +1,8 @@ + */ class SocialAuthMiddleware implements MiddlewareInterface, EventDispatcherInterface { + /** + * @use \Cake\Event\EventDispatcherTrait<\ADmad\SocialAuth\Middleware\SocialAuthMiddleware> + */ use EventDispatcherTrait; use InstanceConfigTrait; use LocatorAwareTrait; @@ -562,7 +568,6 @@ protected function _getService(ServerRequest $request): Service $serviceConfig = Configure::consume('SocialAuth'); } - /** @psalm-suppress PossiblyInvalidArrayOffset */ if (!isset($serviceConfig['redirectUri'])) { $serviceConfig['redirectUri'] = Router::url([ 'plugin' => 'ADmad/SocialAuth', @@ -580,7 +585,6 @@ protected function _getService(ServerRequest $request): Service new StreamFactory() ); - /** @psalm-suppress PossiblyNullArgument */ $this->_service = new Service( $httpStack, $this->_session ?: new SocialConnectSession(), diff --git a/src/Model/Table/SocialProfilesTable.php b/src/Model/Table/SocialProfilesTable.php index a083ce0..54ffd66 100644 --- a/src/Model/Table/SocialProfilesTable.php +++ b/src/Model/Table/SocialProfilesTable.php @@ -16,16 +16,16 @@ * @method \ADmad\SocialAuth\Model\Entity\SocialProfile newEmptyEntity() * @method \ADmad\SocialAuth\Model\Entity\SocialProfile newEntity(array $data, array $options = []) * @method \ADmad\SocialAuth\Model\Entity\SocialProfile[] newEntities(array $data, array $options = []) - * @method \ADmad\SocialAuth\Model\Entity\SocialProfile get($primaryKey, $options = []) + * @method \ADmad\SocialAuth\Model\Entity\SocialProfile get(mixed $primaryKey, array|string $finder = 'all', \Psr\SimpleCache\CacheInterface|string|null $cache = null, \Closure|string|null $cacheKey = null, mixed ...$args) * @method \ADmad\SocialAuth\Model\Entity\SocialProfile findOrCreate($search, ?callable $callback = null, $options = []) * @method \ADmad\SocialAuth\Model\Entity\SocialProfile patchEntity(\Cake\Datasource\EntityInterface $entity, array $data, array $options = []) * @method \ADmad\SocialAuth\Model\Entity\SocialProfile[] patchEntities(iterable $entities, array $data, array $options = []) * @method \ADmad\SocialAuth\Model\Entity\SocialProfile|false save(\Cake\Datasource\EntityInterface $entity, $options = []) * @method \ADmad\SocialAuth\Model\Entity\SocialProfile saveOrFail(\Cake\Datasource\EntityInterface $entity, $options = []) - * @method \ADmad\SocialAuth\Model\Entity\SocialProfile[]|\Cake\Datasource\ResultSetInterface|false saveMany(iterable $entities, $options = []) - * @method \ADmad\SocialAuth\Model\Entity\SocialProfile[]|\Cake\Datasource\ResultSetInterface saveManyOrFail(iterable $entities, $options = []) - * @method \ADmad\SocialAuth\Model\Entity\SocialProfile[]|\Cake\Datasource\ResultSetInterface|false deleteMany(iterable $entities, $options = []) - * @method \ADmad\SocialAuth\Model\Entity\SocialProfile[]|\Cake\Datasource\ResultSetInterface deleteManyOrFail(iterable $entities, $options = []) + * @method \ADmad\SocialAuth\Model\Entity\SocialProfile[]|false saveMany(iterable $entities, $options = []) + * @method \ADmad\SocialAuth\Model\Entity\SocialProfile[] saveManyOrFail(iterable $entities, $options = []) + * @method \ADmad\SocialAuth\Model\Entity\SocialProfile[]|false deleteMany(iterable $entities, $options = []) + * @method \ADmad\SocialAuth\Model\Entity\SocialProfile[] deleteManyOrFail(iterable $entities, $options = []) * @mixin \Cake\ORM\Behavior\TimestampBehavior */ class SocialProfilesTable extends Table