diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml
new file mode 100644
index 0000000..03d62cb
--- /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.1"
+ - "8.2"
+ - "8.3"
+ - "8.4"
+
+ 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 4be1806..d34b488 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,15 @@
# dot-navigation
+`dot-navigation` is Dotkernel's component that allows you to easily define and parse menus inside templates, using a configuration based approach.
+
+## Documentation
+
+Documentation is available at: https://docs.dotkernel.org/dot-navigation/.
+
+## Badges
+

-
+
[](https://github.com/dotkernel/dot-navigation/issues)
[](https://github.com/dotkernel/dot-navigation/network)
@@ -10,8 +18,7 @@
[](https://github.com/dotkernel/dot-navigation/actions/workflows/continuous-integration.yml)
[](https://codecov.io/gh/dotkernel/dot-navigation)
-
-Allows you to easily define and parse menus inside templates, configuration based approach.
+[](https://github.com/dotkernel/dot-navigation/actions/workflows/static-analysis.yml)
## Installation
diff --git a/composer.json b/composer.json
index 5460d86..4aa8925 100644
--- a/composer.json
+++ b/composer.json
@@ -35,8 +35,9 @@
},
"require-dev": {
"laminas/laminas-coding-standard": "^3.0.0",
- "phpunit/phpunit": "^10.4.2",
- "vimeo/psalm": "^6.0"
+ "phpstan/phpstan": "^2.1",
+ "phpstan/phpstan-phpunit": "^2.0",
+ "phpunit/phpunit": "^10.4.2"
},
"autoload": {
"psr-4": {
@@ -57,7 +58,6 @@
"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"
}
}
diff --git a/docs/book/v4/overview.md b/docs/book/v4/overview.md
index 159d976..646cf17 100644
--- a/docs/book/v4/overview.md
+++ b/docs/book/v4/overview.md
@@ -1,3 +1,17 @@
# Overview
`dot-navigation` is Dotkernel's component that allows you to easily define and parse menus inside templates, using a configuration based approach.
+
+## Badges
+
+
+
+
+[](https://github.com/dotkernel/dot-navigation/issues)
+[](https://github.com/dotkernel/dot-navigation/network)
+[](https://github.com/dotkernel/dot-navigation/stargazers)
+[](https://github.com/dotkernel/dot-navigation/blob/4.0/LICENSE.md)
+
+[](https://github.com/dotkernel/dot-navigation/actions/workflows/continuous-integration.yml)
+[](https://codecov.io/gh/dotkernel/dot-navigation)
+[](https://github.com/dotkernel/dot-navigation/actions/workflows/static-analysis.yml)
diff --git a/phpstan.neon b/phpstan.neon
new file mode 100644
index 0000000..349be25
--- /dev/null
+++ b/phpstan.neon
@@ -0,0 +1,8 @@
+includes:
+ - vendor/phpstan/phpstan-phpunit/extension.neon
+parameters:
+ level: 5
+ paths:
+ - src
+ - test
+ treatPhpDocTypesAsCertain: false
diff --git a/psalm-baseline.xml b/psalm-baseline.xml
deleted file mode 100644
index 5b45731..0000000
--- a/psalm-baseline.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
- IsAllowedFilter
-
-
-
-
- RecursiveIterator
-
-
-
diff --git a/psalm.xml b/psalm.xml
deleted file mode 100644
index 9dd8f07..0000000
--- a/psalm.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
-
-
-
-
-
-
diff --git a/src/View/AbstractNavigationRenderer.php b/src/View/AbstractNavigationRenderer.php
index 8f14c4d..23822ac 100644
--- a/src/View/AbstractNavigationRenderer.php
+++ b/src/View/AbstractNavigationRenderer.php
@@ -98,11 +98,11 @@ protected function getContainer(string|NavigationContainer $container): Navigati
{
if (is_string($container)) {
return $this->navigation->getContainer($container);
- } elseif (! $container instanceof NavigationContainer) {
+ } elseif ($container instanceof NavigationContainer) {
+ return $container;
+ } else {
throw new RuntimeException('Container must be a string or an instance of ' . NavigationContainer::class);
}
-
- return $container;
}
protected function cleanAttributes(array $input, array $valid): array
diff --git a/test/Exception/InvalidArgumentExceptionTest.php b/test/Exception/InvalidArgumentExceptionTest.php
index d283fd9..0c37e59 100644
--- a/test/Exception/InvalidArgumentExceptionTest.php
+++ b/test/Exception/InvalidArgumentExceptionTest.php
@@ -13,7 +13,7 @@ class InvalidArgumentExceptionTest extends TestCase
public function testWillReturnCorrectInstances(): void
{
$exception = new InvalidArgumentException('test');
- $this->assertInstanceOf(InvalidArgumentException::class, $exception);
- $this->assertInstanceOf(ExceptionInterface::class, $exception);
+ $this->assertSame(InvalidArgumentException::class, $exception::class);
+ $this->assertContainsOnlyInstancesOf(ExceptionInterface::class, [$exception]);
}
}
diff --git a/test/Exception/RuntimeExceptionTest.php b/test/Exception/RuntimeExceptionTest.php
index 9d46320..e2428c9 100644
--- a/test/Exception/RuntimeExceptionTest.php
+++ b/test/Exception/RuntimeExceptionTest.php
@@ -18,7 +18,7 @@ public function setUp(): void
public function testWillReturnCorrectInstances(): void
{
$exception = new RuntimeException('test');
- $this->assertInstanceOf(RuntimeException::class, $exception);
- $this->assertInstanceOf(ExceptionInterface::class, $exception);
+ $this->assertSame(RuntimeException::class, $exception::class);
+ $this->assertContainsOnlyInstancesOf(ExceptionInterface::class, [$exception]);
}
}
diff --git a/test/Factory/NavigationMiddlewareFactoryTest.php b/test/Factory/NavigationMiddlewareFactoryTest.php
index d075b39..fed1db5 100644
--- a/test/Factory/NavigationMiddlewareFactoryTest.php
+++ b/test/Factory/NavigationMiddlewareFactoryTest.php
@@ -54,6 +54,6 @@ public function testWillCreateMiddleware(): void
->willReturn($navigation);
$middleware = (new NavigationMiddlewareFactory())($container);
- $this->assertInstanceOf(NavigationMiddleware::class, $middleware);
+ $this->assertSame(NavigationMiddleware::class, $middleware::class);
}
}
diff --git a/test/Factory/NavigationOptionsFactoryTest.php b/test/Factory/NavigationOptionsFactoryTest.php
index 6455d8d..1d1fa79 100644
--- a/test/Factory/NavigationOptionsFactoryTest.php
+++ b/test/Factory/NavigationOptionsFactoryTest.php
@@ -79,6 +79,6 @@ public function testWillCreateNavigationOptions(): void
]);
$options = (new NavigationOptionsFactory())($container);
- $this->assertInstanceOf(NavigationOptions::class, $options);
+ $this->assertSame(NavigationOptions::class, $options::class);
}
}
diff --git a/test/Factory/NavigationRendererFactoryTest.php b/test/Factory/NavigationRendererFactoryTest.php
index 38e91ff..b699ac0 100644
--- a/test/Factory/NavigationRendererFactoryTest.php
+++ b/test/Factory/NavigationRendererFactoryTest.php
@@ -97,6 +97,6 @@ public function testWillNotCreateNavigationRenderer(): void
]);
$renderer = (new NavigationRendererFactory())($container);
- $this->assertInstanceOf(NavigationRenderer::class, $renderer);
+ $this->assertSame(NavigationRenderer::class, $renderer::class);
}
}
diff --git a/test/Factory/NavigationServiceFactoryTest.php b/test/Factory/NavigationServiceFactoryTest.php
index fbe9326..1af2f12 100644
--- a/test/Factory/NavigationServiceFactoryTest.php
+++ b/test/Factory/NavigationServiceFactoryTest.php
@@ -101,7 +101,7 @@ public function testWillCreateNavigationServiceWithoutAuthorizationInterface():
]);
$service = (new NavigationServiceFactory())($container);
- $this->assertInstanceOf(Navigation::class, $service);
+ $this->assertSame(Navigation::class, $service::class);
}
/**
@@ -132,6 +132,6 @@ public function testWillCreateNavigationServiceWithAuthorizationInterface(): voi
]);
$service = (new NavigationServiceFactory())($container);
- $this->assertInstanceOf(Navigation::class, $service);
+ $this->assertSame(Navigation::class, $service::class);
}
}
diff --git a/test/Factory/ProviderPluginManagerFactoryTest.php b/test/Factory/ProviderPluginManagerFactoryTest.php
index e79cfa5..4f4511d 100644
--- a/test/Factory/ProviderPluginManagerFactoryTest.php
+++ b/test/Factory/ProviderPluginManagerFactoryTest.php
@@ -106,6 +106,6 @@ public function testWillCreateProviderPluginManager(): void
]);
$manager = (new ProviderPluginManagerFactory())($container);
- $this->assertInstanceOf(ProviderPluginManager::class, $manager);
+ $this->assertSame(ProviderPluginManager::class, $manager::class);
}
}
diff --git a/test/Filter/IsAllowedFilterTest.php b/test/Filter/IsAllowedFilterTest.php
index 6f9f3ed..0035bb6 100644
--- a/test/Filter/IsAllowedFilterTest.php
+++ b/test/Filter/IsAllowedFilterTest.php
@@ -74,7 +74,7 @@ public function testGetChildren(): void
$navigation = $this->createMock(NavigationInterface::class);
$filter = new IsAllowedFilter(new NavigationContainer([new Page()]), $navigation);
- $this->assertInstanceOf(IsAllowedFilter::class, $filter->getChildren());
+ $this->assertSame(IsAllowedFilter::class, $filter->getChildren()::class);
}
/**
@@ -86,6 +86,6 @@ public function testWillCreateFilter(): void
$navigation = $this->createMock(NavigationInterface::class);
$filter = new IsAllowedFilter($iterator, $navigation);
- $this->assertInstanceOf(IsAllowedFilter::class, $filter);
+ $this->assertSame(IsAllowedFilter::class, $filter::class);
}
}
diff --git a/test/NavigationMiddlewareTest.php b/test/NavigationMiddlewareTest.php
index 2063f7a..cb3a4e5 100644
--- a/test/NavigationMiddlewareTest.php
+++ b/test/NavigationMiddlewareTest.php
@@ -22,7 +22,7 @@ public function testWillCreateMiddleware(): void
$navigation = $this->createMock(NavigationInterface::class);
$middleware = new NavigationMiddleware($navigation);
- $this->assertInstanceOf(NavigationMiddleware::class, $middleware);
+ $this->assertSame(NavigationMiddleware::class, $middleware::class);
}
/**
@@ -36,6 +36,6 @@ public function testWillProcessRequest(): void
$middleware = new NavigationMiddleware($navigation);
$response = $middleware->process($request, $handler);
- $this->assertInstanceOf(ResponseInterface::class, $response);
+ $this->assertContainsOnlyInstancesOf(ResponseInterface::class, [$response]);
}
}
diff --git a/test/Options/NavigationOptionsTest.php b/test/Options/NavigationOptionsTest.php
index dfe4f2d..b513994 100644
--- a/test/Options/NavigationOptionsTest.php
+++ b/test/Options/NavigationOptionsTest.php
@@ -12,7 +12,7 @@ class NavigationOptionsTest extends TestCase
public function testWillCreateNavigationOptions(): void
{
$options = new NavigationOptions();
- $this->assertInstanceOf(NavigationOptions::class, $options);
+ $this->assertSame(NavigationOptions::class, $options::class);
}
public function testAccessors(): void
diff --git a/test/PageTest.php b/test/PageTest.php
index cc6601e..255fbf1 100644
--- a/test/PageTest.php
+++ b/test/PageTest.php
@@ -12,7 +12,7 @@ class PageTest extends TestCase
public function testWillCreatePage(): void
{
$page = new Page();
- $this->assertInstanceOf(Page::class, $page);
+ $this->assertSame(Page::class, $page::class);
}
public function testParentAccessors(): void
diff --git a/test/Provider/ArrayProviderTest.php b/test/Provider/ArrayProviderTest.php
index 329194e..f006e07 100644
--- a/test/Provider/ArrayProviderTest.php
+++ b/test/Provider/ArrayProviderTest.php
@@ -13,7 +13,7 @@ class ArrayProviderTest extends TestCase
public function testWillCreateArrayProvider(): void
{
$provider = new ArrayProvider();
- $this->assertInstanceOf(ArrayProvider::class, $provider);
+ $this->assertSame(ArrayProvider::class, $provider::class);
}
public function testAccessors(): void
@@ -40,7 +40,7 @@ public function testGetContainer(): void
'items' => $pageSpecs,
]);
$container = $provider->getContainer();
- $this->assertInstanceOf(NavigationContainer::class, $container);
+ $this->assertSame(NavigationContainer::class, $container::class);
$this->assertCount(2, $container->getChildren());
}
}
diff --git a/test/Provider/FactoryTest.php b/test/Provider/FactoryTest.php
index ea4bee7..7a40130 100644
--- a/test/Provider/FactoryTest.php
+++ b/test/Provider/FactoryTest.php
@@ -25,7 +25,7 @@ public function testWillCreateFactoryWithoutProviderPluginManager(): void
$container = $this->createMock(ContainerInterface::class);
$factory = new Factory($container);
- $this->assertInstanceOf(Factory::class, $factory);
+ $this->assertSame(Factory::class, $factory::class);
}
/**
@@ -37,7 +37,7 @@ public function testWillCreateFactoryWithProviderPluginManager(): void
$manager = $this->createMock(ProviderPluginManager::class);
$factory = new Factory($container, $manager);
- $this->assertInstanceOf(Factory::class, $factory);
+ $this->assertSame(Factory::class, $factory::class);
}
/**
@@ -84,7 +84,7 @@ public function testFactoryWillCreateProviderWithValidProviderTypeAndNoOptions()
$provider = $factory->create([
'type' => ArrayProvider::class,
]);
- $this->assertInstanceOf(ProviderInterface::class, $provider);
+ $this->assertContainsOnlyInstancesOf(ProviderInterface::class, [$provider]);
}
/**
@@ -100,7 +100,7 @@ public function testFactoryWillCreateProviderWithValidProviderTypeAndOptions():
'type' => ArrayProvider::class,
'options' => [],
]);
- $this->assertInstanceOf(ProviderInterface::class, $provider);
+ $this->assertContainsOnlyInstancesOf(ProviderInterface::class, [$provider]);
}
/**
@@ -111,7 +111,7 @@ public function testFactoryWillGetProviderPluginManagerWithoutInitialProviderPlu
$container = $this->createMock(ContainerInterface::class);
$factory = new Factory($container);
- $this->assertInstanceOf(ProviderPluginManager::class, $factory->getProviderPluginManager());
+ $this->assertSame(ProviderPluginManager::class, $factory->getProviderPluginManager()::class);
}
/**
@@ -123,6 +123,6 @@ public function testFactoryWillGetProviderPluginManagerWithInitialProviderPlugin
$manager = $this->createMock(ProviderPluginManager::class);
$factory = new Factory($container, $manager);
- $this->assertInstanceOf(ProviderPluginManager::class, $factory->getProviderPluginManager());
+ $this->assertContainsOnlyInstancesOf(ProviderPluginManager::class, [$factory->getProviderPluginManager()]);
}
}
diff --git a/test/Service/NavigationTest.php b/test/Service/NavigationTest.php
index 01c6574..5f1c2f9 100644
--- a/test/Service/NavigationTest.php
+++ b/test/Service/NavigationTest.php
@@ -30,7 +30,7 @@ public function testNavigationWillInitialize(): void
$options = $this->createMock(NavigationOptions::class);
$navigation = new Navigation($factory, $route, $options);
- $this->assertInstanceOf(NavigationInterface::class, $navigation);
+ $this->assertContainsOnlyInstancesOf(NavigationInterface::class, [$navigation]);
}
/**
@@ -84,7 +84,7 @@ public function testNavigationWillGetValidContainer(): void
]);
$navigation = new Navigation($factory, $route, $options);
- $this->assertInstanceOf(NavigationContainer::class, $navigation->getContainer('default'));
+ $this->assertContainsOnlyInstancesOf(NavigationContainer::class, [$navigation->getContainer('default')]);
}
/**
diff --git a/test/View/NavigationRendererTest.php b/test/View/NavigationRendererTest.php
index 12d25da..ab2c9cb 100644
--- a/test/View/NavigationRendererTest.php
+++ b/test/View/NavigationRendererTest.php
@@ -24,7 +24,7 @@ public function testWillCreateNavigationRenderer(): void
$options = $this->createMock(NavigationOptions::class);
$renderer = new NavigationRenderer($navigation, $template, $options);
- $this->assertInstanceOf(NavigationRenderer::class, $renderer);
+ $this->assertSame(NavigationRenderer::class, $renderer::class);
}
/**