From 37ad11a9b4ae8bb48c920828f958cd129f5c644a Mon Sep 17 00:00:00 2001 From: Oliver Davies Date: Thu, 25 Sep 2025 12:00:00 +0100 Subject: [PATCH] Move from phpat-example Signed-off-by: Oliver Davies --- php/phpat/.envrc | 1 + php/phpat/.gitignore | 1 + php/phpat/.nvim.lua | 10 + php/phpat/composer.json | 21 ++ php/phpat/composer.lock | 181 ++++++++++++++++++ php/phpat/phpstan.neon.dist | 9 + php/phpat/src/Action/DoesSomething.php | 13 ++ .../tests/Architecture/ArchitectureTest.php | 61 ++++++ 8 files changed, 297 insertions(+) create mode 100644 php/phpat/.envrc create mode 100644 php/phpat/.gitignore create mode 100644 php/phpat/.nvim.lua create mode 100644 php/phpat/composer.json create mode 100644 php/phpat/composer.lock create mode 100644 php/phpat/phpstan.neon.dist create mode 100644 php/phpat/src/Action/DoesSomething.php create mode 100644 php/phpat/tests/Architecture/ArchitectureTest.php diff --git a/php/phpat/.envrc b/php/phpat/.envrc new file mode 100644 index 0000000..00a02ea --- /dev/null +++ b/php/phpat/.envrc @@ -0,0 +1 @@ +use flake git+https://code.oliverdavies.uk/opdavies/dev-shells#php83 diff --git a/php/phpat/.gitignore b/php/phpat/.gitignore new file mode 100644 index 0000000..48b8bf9 --- /dev/null +++ b/php/phpat/.gitignore @@ -0,0 +1 @@ +vendor/ diff --git a/php/phpat/.nvim.lua b/php/phpat/.nvim.lua new file mode 100644 index 0000000..c84e4da --- /dev/null +++ b/php/phpat/.nvim.lua @@ -0,0 +1,10 @@ +local cmp_nvim_lsp = require("cmp_nvim_lsp") +local capabilities = cmp_nvim_lsp.default_capabilities(vim.lsp.protocol.make_client_capabilities()) + +local lspconfig = require("lspconfig") + +lspconfig.phpactor.setup({ capabilities = capabilities }) + +require("lint").linters_by_ft = { + php = { "phpstan" }, +} diff --git a/php/phpat/composer.json b/php/phpat/composer.json new file mode 100644 index 0000000..36612ff --- /dev/null +++ b/php/phpat/composer.json @@ -0,0 +1,21 @@ +{ + "require-dev": { + "phpat/phpat": "^0.11.5", + "phpstan/extension-installer": "^1.4" + }, + "config": { + "allow-plugins": { + "phpstan/extension-installer": true + } + }, + "autoload": { + "psr-4": { + "App\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "Tests\\": "tests/" + } + } +} diff --git a/php/phpat/composer.lock b/php/phpat/composer.lock new file mode 100644 index 0000000..6196e78 --- /dev/null +++ b/php/phpat/composer.lock @@ -0,0 +1,181 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "85bfd49ff9043444a18d526d47e46a2e", + "packages": [], + "packages-dev": [ + { + "name": "phpat/phpat", + "version": "0.11.5", + "source": { + "type": "git", + "url": "https://github.com/carlosas/phpat.git", + "reference": "db6aaa96023a6b1b1dfeed7ad9e498e8119a4066" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/carlosas/phpat/zipball/db6aaa96023a6b1b1dfeed7ad9e498e8119a4066", + "reference": "db6aaa96023a6b1b1dfeed7ad9e498e8119a4066", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0", + "phpstan/phpstan": "^2.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.60", + "kubawerlos/php-cs-fixer-custom-fixers": "3.18.*", + "phpunit/phpunit": "^9.0 || 10.5.*" + }, + "type": "phpstan-extension", + "extra": { + "phpstan": { + "includes": [ + "extension.neon" + ] + } + }, + "autoload": { + "files": [ + "helpers.php" + ], + "psr-4": { + "PHPat\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Carlos Alandete Sastre", + "email": "carlos.alandete@gmail.com" + } + ], + "description": "PHP Architecture Tester", + "support": { + "issues": "https://github.com/carlosas/phpat/issues", + "source": "https://github.com/carlosas/phpat/tree/0.11.5" + }, + "time": "2025-05-28T16:39:55+00:00" + }, + { + "name": "phpstan/extension-installer", + "version": "1.4.3", + "source": { + "type": "git", + "url": "https://github.com/phpstan/extension-installer.git", + "reference": "85e90b3942d06b2326fba0403ec24fe912372936" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/extension-installer/zipball/85e90b3942d06b2326fba0403ec24fe912372936", + "reference": "85e90b3942d06b2326fba0403ec24fe912372936", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^2.0", + "php": "^7.2 || ^8.0", + "phpstan/phpstan": "^1.9.0 || ^2.0" + }, + "require-dev": { + "composer/composer": "^2.0", + "php-parallel-lint/php-parallel-lint": "^1.2.0", + "phpstan/phpstan-strict-rules": "^0.11 || ^0.12 || ^1.0" + }, + "type": "composer-plugin", + "extra": { + "class": "PHPStan\\ExtensionInstaller\\Plugin" + }, + "autoload": { + "psr-4": { + "PHPStan\\ExtensionInstaller\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Composer plugin for automatic installation of PHPStan extensions", + "keywords": [ + "dev", + "static analysis" + ], + "support": { + "issues": "https://github.com/phpstan/extension-installer/issues", + "source": "https://github.com/phpstan/extension-installer/tree/1.4.3" + }, + "time": "2024-09-04T20:21:43+00:00" + }, + { + "name": "phpstan/phpstan", + "version": "2.1.17", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan.git", + "reference": "89b5ef665716fa2a52ecd2633f21007a6a349053" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/89b5ef665716fa2a52ecd2633f21007a6a349053", + "reference": "89b5ef665716fa2a52ecd2633f21007a6a349053", + "shasum": "" + }, + "require": { + "php": "^7.4|^8.0" + }, + "conflict": { + "phpstan/phpstan-shim": "*" + }, + "bin": [ + "phpstan", + "phpstan.phar" + ], + "type": "library", + "autoload": { + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPStan - PHP Static Analysis Tool", + "keywords": [ + "dev", + "static analysis" + ], + "support": { + "docs": "https://phpstan.org/user-guide/getting-started", + "forum": "https://github.com/phpstan/phpstan/discussions", + "issues": "https://github.com/phpstan/phpstan/issues", + "security": "https://github.com/phpstan/phpstan/security/policy", + "source": "https://github.com/phpstan/phpstan-src" + }, + "funding": [ + { + "url": "https://github.com/ondrejmirtes", + "type": "github" + }, + { + "url": "https://github.com/phpstan", + "type": "github" + } + ], + "time": "2025-05-21T20:55:28+00:00" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": {}, + "prefer-stable": false, + "prefer-lowest": false, + "platform": {}, + "platform-dev": {}, + "plugin-api-version": "2.6.0" +} diff --git a/php/phpat/phpstan.neon.dist b/php/phpat/phpstan.neon.dist new file mode 100644 index 0000000..2609a5f --- /dev/null +++ b/php/phpat/phpstan.neon.dist @@ -0,0 +1,9 @@ +parameters: + level: max + paths: + - src + - tests +services: + - class: Tests\Architecture\ArchitectureTest + tags: + - phpat.test diff --git a/php/phpat/src/Action/DoesSomething.php b/php/phpat/src/Action/DoesSomething.php new file mode 100644 index 0000000..a1de4d2 --- /dev/null +++ b/php/phpat/src/Action/DoesSomething.php @@ -0,0 +1,13 @@ +classes(Selector::inNamespace(self::ACTION_NAMESPACE)) + ->shouldBeNamed( + fqcn: '/^(?!.*Action$).*$/', + regex: TRUE, + ); + } + + function test_action_classes_are_final(): Rule + { + return PHPat::rule() + ->classes(Selector::inNamespace(self::ACTION_NAMESPACE)) + ->shouldBeFinal(); + } + + function test_action_classes_are_readonly(): Rule + { + return PHPat::rule() + ->classes(Selector::inNamespace(self::ACTION_NAMESPACE)) + ->shouldBeReadonly(); + } + + function test_action_classes_are_invokeable(): Rule + { + return PHPat::rule() + ->classes(Selector::inNamespace(self::ACTION_NAMESPACE)) + ->shouldHaveOnlyOnePublicMethodNamed('__invoke'); + } + + function test_action_classes_do_not_extend_other_classes(): Rule + { + return PHPat::rule() + ->classes(Selector::inNamespace(self::ACTION_NAMESPACE)) + ->shouldNotExtend() + ->classes(Selector::all()); + } + + function test_action_classes_do_not_implement_interfaces(): Rule + { + return PHPat::rule() + ->classes(Selector::inNamespace(self::ACTION_NAMESPACE)) + ->shouldNotImplement() + ->classes(Selector::all()); + } +}