diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml
new file mode 100644
index 0000000..dc4b6fa
--- /dev/null
+++ b/.github/workflows/static-analysis.yml
@@ -0,0 +1,49 @@
+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"
+
+ 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 455e171..e258b0c 100644
--- a/README.md
+++ b/README.md
@@ -1,10 +1,17 @@
# dot-cli
-> [!IMPORTANT]
+Dotkernel component to build console applications based on [laminas-cli](https://github.com/laminas/laminas-cli).
+
> dot-cli is a wrapper on top of [laminas-cli](https://github.com/laminas/laminas-cli)
+## Documentation
+
+Documentation is available at: https://docs.dotkernel.org/dot-cli/.
+
+## Badges
+

-
+
[](https://github.com/dotkernel/dot-cli/issues)
[](https://github.com/dotkernel/dot-cli/network)
@@ -13,8 +20,7 @@
[](https://github.com/dotkernel/dot-cli/actions/workflows/continuous-integration.yml)
[](https://codecov.io/gh/dotkernel/dot-cli)
-
-Dotkernel component to build console applications based on [laminas-cli](https://github.com/laminas/laminas-cli).
+[](https://github.com/dotkernel/dot-cli/actions/workflows/static-analysis.yml)
## Requirements
diff --git a/composer.json b/composer.json
index d0d6af9..a99af41 100644
--- a/composer.json
+++ b/composer.json
@@ -35,8 +35,9 @@
"require-dev": {
"laminas/laminas-coding-standard": "^3.0",
"mikey179/vfsstream": "^1.6.7",
- "phpunit/phpunit": "^10.2",
- "vimeo/psalm": "^6.0"
+ "phpstan/phpstan": "^2.1",
+ "phpstan/phpstan-phpunit": "^2.0",
+ "phpunit/phpunit": "^10.2"
},
"autoload-dev": {
"psr-4": {
@@ -52,7 +53,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/v3/overview.md b/docs/book/v3/overview.md
index e8f6a6b..b18d4e6 100644
--- a/docs/book/v3/overview.md
+++ b/docs/book/v3/overview.md
@@ -1,3 +1,19 @@
# Overview
+Dotkernel component to build console applications based on [laminas-cli](https://github.com/laminas/laminas-cli).
+
> dot-cli is a wrapper on top of [laminas-cli](https://github.com/laminas/laminas-cli)
+
+## Badges
+
+
+
+
+[](https://github.com/dotkernel/dot-cli/issues)
+[](https://github.com/dotkernel/dot-cli/network)
+[](https://github.com/dotkernel/dot-cli/stargazers)
+[](https://github.com/dotkernel/dot-cli/blob/3.0/LICENSE)
+
+[](https://github.com/dotkernel/dot-cli/actions/workflows/continuous-integration.yml)
+[](https://codecov.io/gh/dotkernel/dot-cli)
+[](https://github.com/dotkernel/dot-cli/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 9352203..0000000
--- a/psalm-baseline.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
- new TerminateListener($config)
- new ContainerCommandLoader($container, $config['commands'])
-
-
- new TerminateListener($config)
- new ContainerCommandLoader($container, $config['commands'])
-
-
-
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/test/Command/DemoCommandTest.php b/test/Command/DemoCommandTest.php
index 1987287..956256a 100644
--- a/test/Command/DemoCommandTest.php
+++ b/test/Command/DemoCommandTest.php
@@ -20,7 +20,7 @@ class DemoCommandTest extends TestCase
public function testWillCreateCommand(): void
{
$command = new DemoCommand();
- $this->assertInstanceOf(DemoCommand::class, $command);
+ $this->assertSame(DemoCommand::class, $command::class);
}
/**
diff --git a/test/FileLockerTest.php b/test/FileLockerTest.php
index 996d2e5..4027d47 100644
--- a/test/FileLockerTest.php
+++ b/test/FileLockerTest.php
@@ -32,28 +32,28 @@ public function testAccessors(): void
$fileLocker = new FileLocker();
$this->assertFalse($fileLocker->isEnabled());
$fileLocker->enable();
- $this->assertInstanceOf(FileLocker::class, $fileLocker);
+ $this->assertSame(FileLocker::class, $fileLocker::class);
$this->assertTrue($fileLocker->isEnabled());
$fileLocker->disable();
- $this->assertInstanceOf(FileLocker::class, $fileLocker);
+ $this->assertSame(FileLocker::class, $fileLocker::class);
$this->assertFalse($fileLocker->isEnabled());
$fileLocker->setEnabled(true);
- $this->assertInstanceOf(FileLocker::class, $fileLocker);
+ $this->assertSame(FileLocker::class, $fileLocker::class);
$this->assertTrue($fileLocker->isEnabled());
$fileLocker->setEnabled(false);
- $this->assertInstanceOf(FileLocker::class, $fileLocker);
+ $this->assertSame(FileLocker::class, $fileLocker::class);
$this->assertFalse($fileLocker->isEnabled());
$this->assertNull($fileLocker->getDirPath());
$fileLocker->setDirPath('test');
- $this->assertInstanceOf(FileLocker::class, $fileLocker);
+ $this->assertSame(FileLocker::class, $fileLocker::class);
$this->assertSame('test', $fileLocker->getDirPath());
$this->assertNull($fileLocker->getCommandName());
$fileLocker->setCommandName('test');
- $this->assertInstanceOf(FileLocker::class, $fileLocker);
+ $this->assertSame(FileLocker::class, $fileLocker::class);
$this->assertSame('test', $fileLocker->getCommandName());
$this->assertNull($fileLocker->getLockFile());
$fileLocker->setLockFile('test');
- $this->assertInstanceOf(FileLocker::class, $fileLocker);
+ $this->assertSame(FileLocker::class, $fileLocker::class);
$this->assertSame('test', $fileLocker->getLockFile());
$this->assertSame('test/command-test.lock', $fileLocker->getLockFilePath());
}
@@ -65,7 +65,7 @@ public function testWillInitLockFile(): void
$fileLocker = new FileLocker(true, $config['dirPath'], 'test');
$this->assertNull($fileLocker->getLockFile());
$fileLocker->initLockFile();
- $this->assertInstanceOf(FileLocker::class, $fileLocker);
+ $this->assertSame(FileLocker::class, $fileLocker::class);
$this->assertIsResource($fileLocker->getLockFile());
}
@@ -79,7 +79,7 @@ public function testWillNotLockWhenDisabled(): void
$fileLocker = new FileLocker(false, $config['dirPath'], 'test');
$this->assertNull($fileLocker->getLockFile());
$fileLocker->lock();
- $this->assertInstanceOf(FileLocker::class, $fileLocker);
+ $this->assertSame(FileLocker::class, $fileLocker::class);
$this->assertNull($fileLocker->getLockFile());
}
@@ -93,7 +93,7 @@ public function testWillNotLockWithoutValidCommandName(): void
$fileLocker = new FileLocker(true, $config['dirPath']);
$this->assertNull($fileLocker->getLockFile());
$fileLocker->lock();
- $this->assertInstanceOf(FileLocker::class, $fileLocker);
+ $this->assertSame(FileLocker::class, $fileLocker::class);
$this->assertNull($fileLocker->getLockFile());
}
@@ -107,7 +107,7 @@ public function testWillLockWhenLockedAndEnabledAndHasValidCommandName(): void
$fileLocker = new FileLocker(true, $config['dirPath'], 'test');
$this->assertNull($fileLocker->getLockFile());
$fileLocker->lock();
- $this->assertInstanceOf(FileLocker::class, $fileLocker);
+ $this->assertSame(FileLocker::class, $fileLocker::class);
$this->assertIsResource($fileLocker->getLockFile());
$this->assertFileExists($fileLocker->getLockFilePath());
}
@@ -119,7 +119,7 @@ public function testWillNotUnlockWhenDisabled(): void
$fileLocker = new FileLocker(false, $config['dirPath'], 'test');
$this->assertNull($fileLocker->getLockFile());
$fileLocker->unlock();
- $this->assertInstanceOf(FileLocker::class, $fileLocker);
+ $this->assertSame(FileLocker::class, $fileLocker::class);
$this->assertNull($fileLocker->getLockFile());
}
@@ -130,7 +130,7 @@ public function testWillNotUnlockWithoutValidCommandName(): void
$fileLocker = new FileLocker(false, $config['dirPath']);
$this->assertNull($fileLocker->getLockFile());
$fileLocker->unlock();
- $this->assertInstanceOf(FileLocker::class, $fileLocker);
+ $this->assertSame(FileLocker::class, $fileLocker::class);
$this->assertNull($fileLocker->getLockFile());
}
@@ -141,7 +141,7 @@ public function testWillNotUnlockWhenEnabledAndWithoutValidCommandName(): void
$fileLocker = new FileLocker(true, $config['dirPath']);
$this->assertNull($fileLocker->getLockFile());
$fileLocker->unlock();
- $this->assertInstanceOf(FileLocker::class, $fileLocker);
+ $this->assertSame(FileLocker::class, $fileLocker::class);
$this->assertNull($fileLocker->getLockFile());
}
@@ -154,11 +154,11 @@ public function testWillUnlockWhenLockedAndEnabledAndHasValidCommandName(): void
$fileLocker = new FileLocker(true, $config['dirPath'], 'test');
$fileLocker->lock();
- $this->assertInstanceOf(FileLocker::class, $fileLocker);
+ $this->assertSame(FileLocker::class, $fileLocker::class);
$this->assertIsResource($fileLocker->getLockFile());
$this->assertFileExists($fileLocker->getLockFilePath());
$fileLocker->unlock();
- $this->assertInstanceOf(FileLocker::class, $fileLocker);
+ $this->assertSame(FileLocker::class, $fileLocker::class);
$this->assertFileIsReadable($fileLocker->getLockFilePath());
$this->assertFileIsWritable($fileLocker->getLockFilePath());
}