From e5df86c649f6481359a594f5f774e529c19cad1f Mon Sep 17 00:00:00 2001 From: alexmerlin Date: Mon, 3 Nov 2025 08:30:40 +0200 Subject: [PATCH] Issue #48: Remove PHP 8.1 and add PHP 8.4 & 8.5 support Signed-off-by: alexmerlin --- .github/workflows/codecov.yml | 3 +- .github/workflows/docs-build.yml | 16 -- .github/workflows/static-analysis.yml | 50 +++++ README.md | 48 +++-- SECURITY.md | 6 +- composer.json | 29 +-- docs/book/index.md | 1 - docs/book/v3/configuration.md | 5 - docs/book/v3/events.md | 178 ------------------ docs/book/v3/installation.md | 5 - docs/book/v3/overview.md | 4 - docs/book/v3/plugins.md | 98 ---------- docs/book/v3/usage.md | 60 ------ mkdocs.yml | 21 --- phpstan.neon | 13 ++ psalm.xml | 17 -- src/Plugin/PluginManager.php | 2 +- test/AbstractActionControllerTest.php | 4 +- ...ontrollerEventListenersInitializerTest.php | 3 +- test/Factory/PluginManagerFactoryTest.php | 4 +- 20 files changed, 118 insertions(+), 449 deletions(-) delete mode 100644 .github/workflows/docs-build.yml create mode 100644 .github/workflows/static-analysis.yml delete mode 100644 docs/book/index.md delete mode 100644 docs/book/v3/configuration.md delete mode 100644 docs/book/v3/events.md delete mode 100644 docs/book/v3/installation.md delete mode 100644 docs/book/v3/overview.md delete mode 100644 docs/book/v3/plugins.md delete mode 100644 docs/book/v3/usage.md delete mode 100644 mkdocs.yml create mode 100644 phpstan.neon delete mode 100644 psalm.xml diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml index e21f78b..89e83df 100644 --- a/.github/workflows/codecov.yml +++ b/.github/workflows/codecov.yml @@ -15,9 +15,10 @@ jobs: - ubuntu-latest php: - - "8.1" - "8.2" - "8.3" + - "8.4" + - "8.5" steps: - name: Checkout diff --git a/.github/workflows/docs-build.yml b/.github/workflows/docs-build.yml deleted file mode 100644 index 1a7aa24..0000000 --- a/.github/workflows/docs-build.yml +++ /dev/null @@ -1,16 +0,0 @@ -name: docs-build - -on: - release: - types: [published] - workflow_dispatch: - -jobs: - build-deploy: - runs-on: ubuntu-latest - steps: - - name: Build Docs - uses: dotkernel/documentation-theme/github-actions/docs@main - env: - DEPLOY_TOKEN: ${{ secrets.GITHUB_TOKEN }} - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml new file mode 100644 index 0000000..9976515 --- /dev/null +++ b/.github/workflows/static-analysis.yml @@ -0,0 +1,50 @@ +on: + - push + +name: Run PHPStan checks + +jobs: + mutation: + name: PHPStan ${{ matrix.php }}-${{ matrix.os }} + + runs-on: ${{ matrix.os }} + + strategy: + matrix: + os: + - ubuntu-latest + + php: + - "8.2" + - "8.3" + - "8.4" + - "8.5" + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install PHP + uses: shivammathur/setup-php@v2 + with: + php-version: "${{ matrix.php }}" + coverage: pcov + ini-values: assert.exception=1, zend.assertions=1, error_reporting=-1, log_errors_max_len=0, display_errors=On + tools: composer:v2, cs2pr + + - name: Determine composer cache directory + run: echo "COMPOSER_CACHE_DIR=$(composer config cache-dir)" >> $GITHUB_ENV + + - name: Cache dependencies installed with composer + uses: actions/cache@v4 + with: + path: ${{ env.COMPOSER_CACHE_DIR }} + key: php${{ matrix.php }}-composer-${{ hashFiles('**/composer.json') }} + restore-keys: | + php${{ matrix.php }}-composer- + + - name: Install dependencies with composer + run: composer install --prefer-dist --no-interaction --no-progress --optimize-autoloader --ansi + + - name: Run static analysis with PHPStan + run: vendor/bin/phpstan analyse diff --git a/README.md b/README.md index d647272..357ebdf 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,17 @@ # dot-controller -This is DotKernel's controller package that can be use like middleware inside DotKernel or Mezzio application. -It provides base classes for action based controllers similar to Laminas controller component. It is more lightweight though, but supports controller plugins and event listeners +This is Dotkernel's controller package that can be used like middleware inside Dotkernel or Mezzio application. +It provides base classes for action-based controllers similar to a Laminas controller component. +It is more lightweight, though, but supports controller plugins and event listeners. + +## Documentation + +Documentation is available at: https://docs.dotkernel.org/dot-controller/v3/overview/. + +## Badges ![OSS Lifecycle](https://img.shields.io/osslifecycle/dotkernel/dot-controller) -![PHP from Packagist (specify version)](https://img.shields.io/packagist/php-v/dotkernel/dot-controller/3.4.3) +![PHP from Packagist (specify version)](https://img.shields.io/packagist/php-v/dotkernel/dot-controller/3.6.0) [![GitHub issues](https://img.shields.io/github/issues/dotkernel/dot-controller)](https://github.com/dotkernel/dot-controller/issues) [![GitHub forks](https://img.shields.io/github/forks/dotkernel/dot-controller)](https://github.com/dotkernel/dot-controller/network) @@ -13,33 +20,35 @@ It provides base classes for action based controllers similar to Laminas control [![Build Static](https://github.com/dotkernel/dot-controller/actions/workflows/static-analysis.yml/badge.svg?branch=3.0)](https://github.com/dotkernel/dot-controller/actions/workflows/static-analysis.yml) [![codecov](https://codecov.io/gh/dotkernel/dot-controller/graph/badge.svg?token=VUBG5LM4CK)](https://codecov.io/gh/dotkernel/dot-controller) - -[![SymfonyInsight](https://insight.symfony.com/projects/c4aac671-40d7-4590-b1fa-b3e46a1e3f43/big.svg)](https://insight.symfony.com/projects/c4aac671-40d7-4590-b1fa-b3e46a1e3f43) +[![PHPStan](https://github.com/dotkernel/dot-controller/actions/workflows/static-analysis.yml/badge.svg?branch=3.0)](https://github.com/dotkernel/dot-controller/actions/workflows/static-analysis.yml) ## Installation Install `dot-controller` by executing the following Composer command: -```bash -$ composer require dotkernel/dot-controller +```shell +composer require dotkernel/dot-controller ``` ## Usage Middleware controllers act as a handler for multiple routes. Some conventions were made: -- register controllers in the routes array just like any mezzio middleware. The requirement is that you should define an `action` route parameter(possibly optional) anywhere inside the route(e.g `/user[/{action}]`) -- action parameter value is converted to a method name inside the controller. Underscore, dot and line characters are removed and the action name is converted to camel-case suffixed by the string `Action`. For example a route and action pair like `/user/forgot-password` will be converted to method `forgotPasswordAction`. +- register controllers in the `routes` array just like any mezzio middleware. + The requirement is that you should define an `action` route parameter (possibly optional) anywhere inside the route (e.g `/user[/{action}]`). +- action parameter value is converted to a method name inside the controller. + Underscore, dot and line characters are removed and the action name is converted to a camel-case suffixed by the string `Action`. + For example, a route and action pair like `/user/forgot-password` will be converted to method `forgotPasswordAction`. - the default action value, if not present in the URI is `index`, so you should always define an `indexAction` within your controllers for displaying a default page or redirecting. -In order to create your action based controllers, you must extend the abstract class `DotKernel\DotController\AbstractActionController` +To create your action-based controllers, you must extend the abstract class `Dot\DotController\AbstractActionController` ### Example -Creating a UserController with default action and a register action. Will handle routes `/user` and `/user/register` +Creating a UserController with a default action and a register action. Will handle routes `/user` and `/user/register`. ```php -use DotKernel\DotController\AbstractActionController; +use Dot\DotController\AbstractActionController; class UserController extends AbstractActionController { @@ -55,10 +64,10 @@ class UserController extends AbstractActionController } ``` -Then register this controller as a routed middleware in file `RoutesDelegator.php` just like a regular middleware. +Then register this controller as routed middleware in file `RoutesDelegator.php` just like regular middleware. ```php -//Example from a DotKernel RoutesDelegator +// Example from a Dotkernel RoutesDelegator $app->route( '/user[/{action}]', UserController::class, @@ -69,10 +78,13 @@ $app->route( ### Multiple controllers for the same route -Use case: You have defined a controller inside some package, with default actions. You want to add actions that fall into the same controller name(or route name more exactly). You want to do this without extending the controller provided by the package. In this case you can do the following +Use case: You have defined a controller inside some package, with default actions. You want to add actions that fall into the same controller name (or route name more exactly). +You want to do this without extending the controller provided by the package. +In this case you can do the following: -- create your own controller, independent of the package's controller which adds more actions +- create your own controller, independent of the package's controller, which adds more actions - Mezzio lets you define an array of middleware for a route, so you can register this controller before the package's controller -Now when a request for this route comes in, your controller will run first. DotKernel controllers are designed to ignore requests that cannot be matched to one of its methods, so if no action matches, it will call the next middleware, in our case, the second controller. -If this is the last controller, and action does not match here, it will go to the default 404 Not found page(handled by NotFoundDelegate) +Now when a request for this route comes in, your controller will run first. +Dotkernel controllers are designed to ignore requests that cannot be matched to one of its methods, so if no action matches, it will call the next middleware, in our case, the second controller. +If this is the last controller, and the action does not match here, it will go to the default 404 Not found page (handled by NotFoundDelegate). diff --git a/SECURITY.md b/SECURITY.md index 4a0e65f..eacdb2d 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -2,13 +2,11 @@ ## Supported Versions - | Version | Supported | PHP Version | |---------|--------------------|----------------------------------------------------------------------------------------------------------------| -| 3.x | :white_check_mark: | ![PHP from Packagist (specify version)](https://img.shields.io/packagist/php-v/dotkernel/dot-controller/3.4.3) | +| 3.x | :white_check_mark: | ![PHP from Packagist (specify version)](https://img.shields.io/packagist/php-v/dotkernel/dot-controller/3.6.0) | | <= 2.x | :x: | | - ## Reporting Potential Security Issues If you have encountered a potential security vulnerability in this project, @@ -24,7 +22,7 @@ When reporting issues, please provide the following information: We request that you contact us via the email address above and give the project contributors a chance to resolve the vulnerability and issue a new release prior to any public exposure; this helps protect the project's -users, and provides them with a chance to upgrade and/or update in order to +users and provides them with a chance to upgrade and/or update to protect their applications. diff --git a/composer.json b/composer.json index ebab335..7ed645e 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,7 @@ { "name": "dotkernel/dot-controller", "type": "library", - "description": "DotKernel controller like middleware component with plugin support", + "description": "Dotkernel controller like middleware component with plugin support", "license": "MIT", "homepage": "https://github.com/dotkernel/dot-controller", "keywords": [ @@ -13,23 +13,24 @@ ], "authors": [ { - "name": "DotKernel Team", + "name": "Dotkernel Team", "email": "team@dotkernel.com" } ], "require": { - "php": "~8.1.0 || ~8.2.0 || ~8.3.0", - "psr/http-message": "^1.0 || ^2.0", - "laminas/laminas-servicemanager": "^3.11.2", + "php": "~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0", "dotkernel/dot-event": "^3.2.0", + "laminas/laminas-servicemanager": "^3.11.2", "mezzio/mezzio-template": "^2.4.0", - "mezzio/mezzio-helpers": "^5.8.0" + "mezzio/mezzio-helpers": "^5.8.0", + "psr/http-message": "^1.0 || ^2.0" }, "require-dev": { - "phpunit/phpunit": "^10.2", - "vimeo/psalm": "^5.13", - "laminas/laminas-coding-standard": "^2.5", - "laminas/laminas-diactoros": "^3.0" + "laminas/laminas-coding-standard": "^3.0", + "laminas/laminas-diactoros": "^3.0", + "phpstan/phpstan": "^2.1", + "phpstan/phpstan-phpunit": "^2.0", + "phpunit/phpunit": "^10.2" }, "autoload": { "psr-4": { @@ -44,13 +45,13 @@ "scripts": { "check": [ "@cs-check", - "@test" + "@test", + "@static-analysis" ], "cs-check": "phpcs", "cs-fix": "phpcbf", - "test": "phpunit --colors=always", - "test-coverage": "phpunit --colors=always --coverage-clover clover.xml", - "static-analysis": "psalm --shepherd --stats" + "static-analysis": "phpstan analyse --memory-limit 1G", + "test": "phpunit --colors=always" }, "config": { "sort-packages": true, diff --git a/docs/book/index.md b/docs/book/index.md deleted file mode 100644 index ae42a26..0000000 --- a/docs/book/index.md +++ /dev/null @@ -1 +0,0 @@ -../../README.md diff --git a/docs/book/v3/configuration.md b/docs/book/v3/configuration.md deleted file mode 100644 index 344644b..0000000 --- a/docs/book/v3/configuration.md +++ /dev/null @@ -1,5 +0,0 @@ -# Configuration - -After installation, the package can be used immediately but if you want to use all features of the package, like plugins and events you need to register the `ConfigProvider` in your project by adding the below line to your configuration aggregator (usually: `config/config.php`): - - \Dot\Controller\ConfigProvider::class diff --git a/docs/book/v3/events.md b/docs/book/v3/events.md deleted file mode 100644 index d889f3a..0000000 --- a/docs/book/v3/events.md +++ /dev/null @@ -1,178 +0,0 @@ -# Events - -DotKernel's controller package supports events and those events can be of 2 types: global events (middleware-like) or manually dispatch events. - -## Getting started - -- Every event listener that is triggered from a controller -needs to implement `Dot\Controller\Event\ControllerEventListenerInterface` which actually extends `Laminas\EventManager\ListenerAggregateInterface`. -- You can add the trait `Dot\Controller\Event\ControllerEventListenerTrait` to override the method of the interface. -- Every event listener needs to be registered under the `['dot_controller']['event_listenenrs]` key in the ConfigProvider, and every key must be the class that you want to attach the events - -## Usage - -The events in a controller can be done in 2 different ways, a global way where an event is attached automatically to all the controllers action and works in the same way the middlewares works -or a manually dispatchable way, where you can define to which controller the events is attached, and you can trigger the event where you want. - -For our example we have a UserController with some methods in it - -```php -use DotKernel\DotController\AbstractActionController; - -class UserController extends AbstractActionController -{ - public function indexAction() - { - //... - } - - public function registerAction() - { - //... - } - - // post method for updating the user - public function updateAction() - { - - } -} -``` - -### Example 1 - Global way - -First we will create the event listener - -```php -use Dot\Controller\Event\ControllerEvent; -use Dot\Controller\Event\ControllerEventListenerInterface; -use Dot\Controller\Event\ControllerEventListenerTrait; - -// for the logger we assume you will use your own logger and inject it - -class UserUpdatedListener implements ControllerEventListenerInterface -{ - use ControllerEventListenerTrait; - - public function onBeforeDispatch(ControllerEvent $event): void - { - $this->logger->info('on before dispatch'); - } - - public function onAfterDispatch(ControllerEvent $event): void - { - $this->logger->info('on after dispatch'); - } - -} -``` - -We register the event listener in the configuration key - -```php -'dot_controller' => [ - 'event_listeners' => [ - AccountController::class => [ - UserUpdatedListener::class, - ] - ] -] -``` - -As you can assume, `onBeforeDispatch` is triggered right before the controller is dispatched, and `onAfterDispatch` right -after the controller is dispatched. - -With this it doesn't matter what action is accessed, the event it will run before and after the action. - -In addition, you can make use of the `event` variable to access information about the event. - -For example: - -```php -// UserUpdatedListener -public function onAfterDispatch(ControllerEvent $e): void - { - $method = $e->getTarget()->getRequest()->getMethod(); - $action = $e->getParams()['method']; - if ($method == 'POST' && $action == 'updateAction') { - $this->logger->info('this will trigger '); - - } - } -``` - -So every time the `updateAction` is accessed and the method is post, -right after the action is dispatched, we can log that the user was updated. - -We can use the `onBeforeDispatch` in the same way, to log right before the user is updated. - -### Example 2 - Manually triggered way - -```php -use Dot\Controller\Event\ControllerEvent; -use Dot\Controller\Event\ControllerEventListenerInterface; -use Dot\Controller\Event\ControllerEventListenerTrait; - -// for the logger we assume you will use your own logger and inject it - -class UserUpdatedListener implements ControllerEventListenerInterface -{ - use ControllerEventListenerTrait; - - public function attach(EventManagerInterface $events, $priority = 1): void - { - $this->listeners[] = $events->attach( - 'user.profile.update', - [$this, 'userProfileUpdated'], - $priority - ); - } - - public function userProfileUpdated(ControllerEvent $event): void - { - $this->logger->info('User profile updated'); - } - -} -``` - -The `attach` method is from the `ListenerAggregateInterface` which `ControllerEventListenerTrait` -already is overriding it so can be used in a global way with `onBeforeDispatch` and `onAfterDispatch` -methods, but we can make our custom event and bind it to our method. - -In this case we create attach an event called `user.profile.update` and bind it to the `userProfileUpdated` method. - -Next we need to register the event - -```php -'dot_controller' => [ - 'event_listeners' => [ - AccountController::class => [ - 'user.profile.update' => UserUpdatedListener::class - ] - ] -] -``` - -Now you can manually trigger the event from the controller using build in `dispatchEvent` method. - -```php -// UserController -// post method for updating the user -public function updateAction() -{ - // logic - $this->dispatchEvent('user.profile.update', ['user' => $user]); - -} -``` - -As you can see we attach the `user` key to the parameters, so we can actually access it. - -```php - public function userProfileUpdated(ControllerEvent $event): void - { - $user = $event->getParams()['user']; - $this->logger->info('User profile updated', $user->toArray()); - } -``` diff --git a/docs/book/v3/installation.md b/docs/book/v3/installation.md deleted file mode 100644 index 8c71aa1..0000000 --- a/docs/book/v3/installation.md +++ /dev/null @@ -1,5 +0,0 @@ -# Installation - -Install `dot-controller` by executing the following Composer command: - - composer require dotkernel/dot-controller diff --git a/docs/book/v3/overview.md b/docs/book/v3/overview.md deleted file mode 100644 index 1d154ec..0000000 --- a/docs/book/v3/overview.md +++ /dev/null @@ -1,4 +0,0 @@ -# Overview - -`dot-controller` is DotKernel's controller package that can be use like middleware inside DotKernel or Mezzio application. -It provides base classes for action based controllers similar to Laminas controller component. It is more lightweight though, but supports controller plugins and event listeners diff --git a/docs/book/v3/plugins.md b/docs/book/v3/plugins.md deleted file mode 100644 index bc94d69..0000000 --- a/docs/book/v3/plugins.md +++ /dev/null @@ -1,98 +0,0 @@ -# Plugins - -DotKernel's controller support plugins, much like controllers in a Laminas Applications. -The package comes packed with a few built in plugins, but you can extend controller functionality with your own plugins. - -## Usage - -Any controller plugins must implement `Dot\Controller\Plugin\PluginInterface`. -You need to create a factory in addition to the plugin and register it -under the `['dot_controller']['plugin_manager']['factories']` with the plugin name. - -Once registered, a plugin can be directly accessed in any controller, -by calling a method with the plugin's name (the service name or the key at which the plugin is registered inside the manager) - -Controller plugins offer the advantage of globally accessible functionality -in any controller without to manually inject dependencies. -Plugins should be used for functions that are common to any controller. -Do not clutter controller's code with unnecessary plugins. - -### Example - -First we create our desired plugin, for our example a string helper - -```php -class StringPlugin implements PluginInterface -{ - - // any method inside the plugin needs to be public if you want to access it from a controller - public function toUpper(string $string): string - { - return strtoupper($string); - } -} -``` - -We create a factory for the plugin - -```php -use Psr\Container\ContainerInterface; - -class StringPluginFactory -{ - - public function __invoke(ContainerInterface $container): StringPlugin - { - return new StringPlugin(); - } - -} -``` - -Register the factory under the `['dot_controller']['plugin_manager']['factories']` key. - -```php -'dot_controller' => [ - 'plugin_manager' => [ - 'factories' => [ - 'string' => StringPluginFactory::class - ] - ] -] -``` - -You don't need to register the plugin factory to a regular dependencies in a configuration -because `AbstractPluginManager` actually extends `ServiceManager` - -Access it in a controller. - -```php -//inside a controller -$this->string(); // will return the StringPlugin class, so you can call any public method from it -$this->string()->toUpper("test") // will return TEST -``` - -## Build-in plugins - -The package comes in with 2 default plugins ``template`` and `url`. You can use -them in the same way as our example above. - -- `url` - the plugin is an instance of `Mezzio\Helper\UrlHelper` - -```php - //in a controller action - /** @var UrlHelper $url */ - $url = $this->url(); - echo $url->generate('account', ['action' => 'foo', 'hash' => 'bar']) -``` - -- `template` - the plugin is an instance of `Mezzio\Template\TemplateRendererInterface` - -```php - // in a controller action - return new HtmlResponse( - $this->template->render('page::home', [ - 'foo' => 'bar' - ]) - ); -``` diff --git a/docs/book/v3/usage.md b/docs/book/v3/usage.md deleted file mode 100644 index b5aeffa..0000000 --- a/docs/book/v3/usage.md +++ /dev/null @@ -1,60 +0,0 @@ -# Usage - -Middleware controllers act as a handler for multiple routes. Some conventions were made: - -- register controllers in the routes array just like any mezzio middleware. The requirement is that you should define an `action` route parameter(possibly optional) anywhere inside the route(e.g `/user[/{action}]`) -- action parameter value is converted to a method name inside the controller. Underscore, dot and line characters are removed and the action name is converted to camel-case suffixed by the string `Action`. For example a route and action pair like `/user/forgot-password` will be converted to method `forgotPasswordAction`. -- the default action value, if not present in the URI is `index`, so you should always define an `indexAction` within your controllers for displaying a default page or redirecting. - -In order to create your action based controllers, you must extend the abstract class `DotKernel\DotController\AbstractActionController` - -## Example - -Creating a UserController with default action and a register action. Will handle routes `/user` and `/user/register` - -```php -use DotKernel\DotController\AbstractActionController; - -class UserController extends AbstractActionController -{ - public function indexAction() - { - //... - } - - public function registerAction() - { - //... - } -} -``` - -Then register this controller as a routed middleware in file `RoutesDelegator.php` just like a regular middleware. - -```php -//Example from a DotKernel RoutesDelegator -$app->route( - '/user[/{action}]', - UserController::class, - [RequestMethodInterface::METHOD_GET, RequestMethodInterface::METHOD_POST], - 'user' -); -``` - -### Multiple controllers for the same route - -Use case: You have defined a controller inside some package, with default actions. You want to add actions that fall into the same controller name(or route name more exactly). You want to do this without extending the controller provided by the package. In this case you can do the following - -- create your own controller, independent of the package's controller which adds more actions -- Mezzio lets you define an array of middleware for a route, so you can register this controller before the package's controller - -Now when a request for this route comes in, your controller will run first. DotKernel controllers are designed to ignore requests that cannot be matched to one of its methods, so if no action matches, it will call the next middleware, in our case, the second controller. -If this is the last controller, and action does not match here, it will go to the default 404 Not found page(handled by NotFoundDelegate) - -## Plugins - -- [Plugins](plugins.md) - -## Events - -- [Events](events.md) diff --git a/mkdocs.yml b/mkdocs.yml deleted file mode 100644 index f8ab813..0000000 --- a/mkdocs.yml +++ /dev/null @@ -1,21 +0,0 @@ -docs_dir: docs/book -site_dir: docs/html -extra: - project: Packages - current_version: v3 - versions: - - v3 -nav: - - Home: index.md - - v3: - - Overview: v3/overview.md - - Installation: v3/installation.md - - Configuration: v3/configuration.md - - Usage: v3/usage.md - - Plugins: v3/plugins.md - - Events: v3/events.md -site_name: dot-controller -site_description: "DotKernel's controller package" -repo_url: "https://github.com/dotkernel/dot-controller" -plugins: - - search diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 0000000..8a8b704 --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,13 @@ +includes: + - vendor/phpstan/phpstan-phpunit/extension.neon +parameters: + level: 5 + paths: + - src + - test + treatPhpDocTypesAsCertain: false + ignoreErrors: + - message: '#Call to an undefined method .*::somePlugin\(\)\.#' + path: test/AbstractControllerTest.php + - message: '#Call to an undefined method .*::callablePlugin\(\)\.#' + path: test/AbstractControllerTest.php diff --git a/psalm.xml b/psalm.xml deleted file mode 100644 index 7272b57..0000000 --- a/psalm.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - diff --git a/src/Plugin/PluginManager.php b/src/Plugin/PluginManager.php index a21ce63..4eceefc 100644 --- a/src/Plugin/PluginManager.php +++ b/src/Plugin/PluginManager.php @@ -12,6 +12,6 @@ */ class PluginManager extends AbstractPluginManager { - /** @var string $instanceOf */ + /** @inheritDoc */ protected $instanceOf = PluginInterface::class; } diff --git a/test/AbstractActionControllerTest.php b/test/AbstractActionControllerTest.php index 4f54ac7..831e888 100644 --- a/test/AbstractActionControllerTest.php +++ b/test/AbstractActionControllerTest.php @@ -28,7 +28,7 @@ public function testNonExistingActionWillReturnResponse(): void }; $response = $subject->process($request, $handler); - $this->assertInstanceOf(ResponseInterface::class, $response); + $this->assertContainsOnlyInstancesOf(ResponseInterface::class, [$response]); } /** @@ -49,6 +49,6 @@ public function indexAction(): ResponseInterface }; $response = $subject->process($request, $handler); - $this->assertInstanceOf(ResponseInterface::class, $response); + $this->assertContainsOnlyInstancesOf(ResponseInterface::class, [$response]); } } diff --git a/test/Factory/ControllerEventListenersInitializerTest.php b/test/Factory/ControllerEventListenersInitializerTest.php index 26ed7e5..358120a 100644 --- a/test/Factory/ControllerEventListenersInitializerTest.php +++ b/test/Factory/ControllerEventListenersInitializerTest.php @@ -72,8 +72,7 @@ public function testAttachControllerListeners(): void $this->eventManager->expects($this->any())->method('attach') ->with($this->isInstanceOf(ControllerEventListenerInterface::class), 1); + $this->expectNotToPerformAssertions(); $this->subject->attachControllerListeners($this->container, $this->controller); - - $this->assertTrue(true); } } diff --git a/test/Factory/PluginManagerFactoryTest.php b/test/Factory/PluginManagerFactoryTest.php index ef4f3b1..1d3c2b1 100644 --- a/test/Factory/PluginManagerFactoryTest.php +++ b/test/Factory/PluginManagerFactoryTest.php @@ -60,7 +60,7 @@ public function testInvokeWithUrlHelper(): void $pluginManager = $this->subject->__invoke($this->container); - $this->assertInstanceOf(PluginManager::class, $pluginManager); + $this->assertContainsOnlyInstancesOf(PluginManager::class, [$pluginManager]); $this->assertTrue($pluginManager->has('url')); $this->assertFalse($pluginManager->has('template')); $this->assertInstanceOf(UrlHelperPlugin::class, $pluginManager->get('url')); @@ -91,7 +91,7 @@ public function testInvokeWithTemplateRenderer(): void $pluginManager = $this->subject->__invoke($this->container); - $this->assertInstanceOf(PluginManager::class, $pluginManager); + $this->assertContainsOnlyInstancesOf(PluginManager::class, [$pluginManager]); $this->assertTrue($pluginManager->has('template')); $this->assertFalse($pluginManager->has('url')); $this->assertInstanceOf(TemplatePlugin::class, $pluginManager->get('template'));