From ca39f34025e68b334d37fa0cd80dea808377e8b3 Mon Sep 17 00:00:00 2001 From: Enea Date: Mon, 18 May 2026 06:25:44 +0200 Subject: [PATCH 1/3] chore(refactor): remove Psalm configuration and annotations, migrate to PHPStan for static analysis, and update related scripts and dependencies --- Makefile | 22 +++++++++---------- bin/theme-json.php | 1 - composer.json | 10 ++++----- phpstan.neon | 11 ++++++++++ psalm.xml | 21 ------------------ src/Api/SectionNames.php | 3 --- src/Api/ThemeJson.php | 3 --- src/Application/Commands/DumpCommand.php | 3 --- src/Application/Commands/InfoCommand.php | 3 --- src/Application/Commands/InitCommand.php | 3 --- src/Application/Commands/ValidateCommand.php | 3 --- src/Application/DumpMessage.php | 3 --- src/Application/Middlewares/Dump.php | 4 ---- src/Application/Middlewares/Info.php | 1 - src/Application/Middlewares/Init.php | 5 ----- src/Application/ValidateMessage.php | 3 --- src/Bootstrap.php | 3 --- src/Domain/Input/Settings/Color/Duotone.php | 3 --- src/Domain/Input/Settings/Color/Gradient.php | 3 --- src/Domain/Input/Settings/Color/Palette.php | 3 --- src/Domain/Input/Settings/Color/Shadow.php | 3 --- .../AchromaticColorsExperimental.php | 3 --- .../Utilities/AnalogousColorsExperimental.php | 3 --- .../Settings/Color/Utilities/BoxShadow.php | 3 --- .../Input/Settings/Color/Utilities/Color.php | 6 ----- .../Settings/Color/Utilities/ColorFactory.php | 3 --- .../Color/Utilities/ColorFactoryInterface.php | 3 --- .../Color/Utilities/ColorInterface.php | 3 --- .../Color/Utilities/ColorModifier.php | 9 -------- .../Utilities/ColorModifierInterface.php | 3 --- .../Color/Utilities/ColorsGenerator.php | 3 --- .../ComplementaryColorsExperimental.php | 3 --- .../Color/Utilities/GradientInterface.php | 3 --- .../Color/Utilities/LinearGradient.php | 3 --- .../MonochromaticColorsExperimental.php | 3 --- .../SplitComplementaryColorsExperimental.php | 3 --- .../Utilities/SquareColorsExperimental.php | 3 --- .../Utilities/TriadicColorsExperimental.php | 3 --- src/Domain/Input/Settings/Custom/Custom.php | 3 --- .../Input/Settings/Custom/CustomToPresets.php | 3 --- src/Domain/Input/Settings/NullPresets.php | 1 - src/Domain/Input/Settings/PresetInterface.php | 3 --- src/Domain/Input/Settings/PresetTrait.php | 3 --- src/Domain/Input/Settings/Presets.php | 2 -- .../Input/Settings/PresetsInterface.php | 3 --- .../Input/Settings/Typography/FontFamily.php | 3 --- .../Input/Settings/Typography/FontSize.php | 3 --- .../Settings/Typography/Utilities/Fluid.php | 3 --- .../Typography/Utilities/FontFace.php | 3 --- .../Settings/Utilities/CalcExperimental.php | 3 --- .../Settings/Utilities/ClampExperimental.php | 3 --- .../Utilities/DimensionExperimental.php | 1 - .../Utilities/SupportedUnitsExperimental.php | 3 --- .../Utilities/UnitInterfaceExperimental.php | 3 --- .../Input/Styles/ArrayableInterface.php | 3 --- src/Domain/Input/Styles/Border.php | 3 --- src/Domain/Input/Styles/Color.php | 3 --- src/Domain/Input/Styles/Css.php | 1 - src/Domain/Input/Styles/CssInterface.php | 3 --- src/Domain/Input/Styles/Outline.php | 3 --- src/Domain/Input/Styles/Scss.php | 1 - src/Domain/Input/Styles/Spacing.php | 3 --- src/Domain/Input/Styles/Typography.php | 3 --- .../Filesystem/FilesExtension.php | 3 --- src/Infrastructure/Filesystem/FilesFinder.php | 3 --- tests/unit/Domain/Output/InitTest.php | 1 - 66 files changed, 27 insertions(+), 220 deletions(-) create mode 100644 phpstan.neon delete mode 100644 psalm.xml diff --git a/Makefile b/Makefile index 4ee3e968..ec680401 100644 --- a/Makefile +++ b/Makefile @@ -94,12 +94,12 @@ cs/fix: up ### Run the code sniffer and fix the errors @$(DOCKER_DIR) ./composer cs:fix @$(FILES_OWNERSHIP) -# Psalm commands - -.PHONY: psalm -psalm: up ### Run the psalm - @echo "Running the psalm" - @$(DOCKER_DIR) ./composer psalm +# PHPStan commands + +.PHONY: phpstan +phpstan: up ### Run PHPStan + @echo "Running PHPStan" + @$(DOCKER_DIR) ./composer phpstan # Codeception commands @@ -137,8 +137,8 @@ acceptance: up ### Run the acceptance tests .PHONY: tests tests: unit integration functional ### Run unit and integration tests -.PHONY: qa -qa: cs psalm unit integration functional ### Run all the tests +.PHONY: qa +qa: cs phpstan unit integration functional ### Run all the tests # Infection commands @@ -180,9 +180,9 @@ docker/metrics: ### Run the phpmetrics # PhpMetrics commands from composer .PHONY: metrics -metrics: up ### Run the composer/metrics - @echo "Running the psalm" - @$(DOCKER_DIR) ./composer metrics +metrics: up ### Run the composer/metrics + @echo "Running phpmetrics" + @$(DOCKER_DIR) ./composer metrics # Generate commands diff --git a/bin/theme-json.php b/bin/theme-json.php index e8e3389f..4a87ccb6 100644 --- a/bin/theme-json.php +++ b/bin/theme-json.php @@ -8,7 +8,6 @@ namespace ItalyStrap\ThemeJsonGenerator; -/** @psalm-suppress UnresolvableInclude */ require $_composer_autoload_path ?? __DIR__ . '/../vendor/autoload.php'; $bootstrap = new Bootstrap(); diff --git a/composer.json b/composer.json index 68b20332..60e6f26a 100644 --- a/composer.json +++ b/composer.json @@ -55,7 +55,7 @@ "phpcompatibility/php-compatibility": "*", "dealerdirect/phpcodesniffer-composer-installer": "^1.0", - "vimeo/psalm": "^5.6", + "phpstan/phpstan": "^1.12", "phpbench/phpbench": "^1.2", "phpmetrics/phpmetrics": "^2.8", @@ -97,8 +97,8 @@ "cs:fix": [ "@php ./vendor/bin/phpcbf -p" ], - "psalm": [ - "@php ./vendor/bin/psalm --no-cache" + "phpstan": [ + "@php ./vendor/bin/phpstan analyse --debug --no-progress" ], "unit": [ "@php ./vendor/bin/codecept run unit" @@ -125,7 +125,7 @@ ], "qa": [ "@cs", - "@psalm", + "@phpstan", "@rector", "@unit" ], @@ -145,7 +145,7 @@ "scripts-descriptions": { "cs": "Run Code Sniffer", "cs:fix": "Run Code Sniffer and fix errors", - "psalm": "Run Psalm", + "phpstan": "Run PHPStan", "unit": "Run Unit tests", "integration": "Run Integration tests", "infection": "Run Infection", diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 00000000..de1815de --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,11 @@ +parameters: + level: 1 + paths: + - bin + - functions + - src + excludePaths: + analyse: + - src/**/*Experimental*.php + parallel: + maximumNumberOfProcesses: 1 diff --git a/psalm.xml b/psalm.xml deleted file mode 100644 index bd590bbf..00000000 --- a/psalm.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/src/Api/SectionNames.php b/src/Api/SectionNames.php index f0c64b79..7ce2a01c 100644 --- a/src/Api/SectionNames.php +++ b/src/Api/SectionNames.php @@ -4,9 +4,6 @@ namespace ItalyStrap\ThemeJsonGenerator\Api; -/** - * @psalm-api - */ final class SectionNames { /** diff --git a/src/Api/ThemeJson.php b/src/Api/ThemeJson.php index e1c27d8d..2b5be676 100644 --- a/src/Api/ThemeJson.php +++ b/src/Api/ThemeJson.php @@ -15,11 +15,9 @@ use ItalyStrap\ThemeJsonGenerator\Domain\Input\Settings\Typography\FontSize; /** - * @psalm-api * @template TKey as array-key * @template TValue * @template-extends Config - * @psalm-suppress DeprecatedInterface */ final class ThemeJson extends Config implements \JsonSerializable { @@ -68,7 +66,6 @@ public function setPresets(PresetsInterface $presets): bool foreach ($keys as $key => $value) { try { - /** @psalm-suppress UndefinedInterfaceMethod */ $this->set($key, $presets->toArrayByCategory($value)); } catch (\Exception $e) { continue; diff --git a/src/Application/Commands/DumpCommand.php b/src/Application/Commands/DumpCommand.php index 65c62890..890a1b8c 100644 --- a/src/Application/Commands/DumpCommand.php +++ b/src/Application/Commands/DumpCommand.php @@ -14,9 +14,6 @@ use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Process\Process; -/** - * @psalm-api - */ #[AsCommand(name: DumpCommand::NAME, description: DumpCommand::DESCRIPTION)] final class DumpCommand extends Command { diff --git a/src/Application/Commands/InfoCommand.php b/src/Application/Commands/InfoCommand.php index 2c9c5aa0..fce2398a 100644 --- a/src/Application/Commands/InfoCommand.php +++ b/src/Application/Commands/InfoCommand.php @@ -12,9 +12,6 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -/** - * @psalm-api - */ #[AsCommand(name: InfoCommand::NAME, description: InfoCommand::DESCRIPTION)] class InfoCommand extends Command { diff --git a/src/Application/Commands/InitCommand.php b/src/Application/Commands/InitCommand.php index f34d5463..fd3d3841 100644 --- a/src/Application/Commands/InitCommand.php +++ b/src/Application/Commands/InitCommand.php @@ -13,9 +13,6 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -/** - * @psalm-api - */ #[AsCommand(name: InitCommand::NAME, description: InitCommand::DESCRIPTION)] class InitCommand extends Command { diff --git a/src/Application/Commands/ValidateCommand.php b/src/Application/Commands/ValidateCommand.php index edbd676a..c36ade06 100644 --- a/src/Application/Commands/ValidateCommand.php +++ b/src/Application/Commands/ValidateCommand.php @@ -14,9 +14,6 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -/** - * @psalm-api - */ #[AsCommand(name: ValidateCommand::NAME, description: ValidateCommand::DESCRIPTION)] class ValidateCommand extends Command { diff --git a/src/Application/DumpMessage.php b/src/Application/DumpMessage.php index 24b3bc1b..8213928e 100644 --- a/src/Application/DumpMessage.php +++ b/src/Application/DumpMessage.php @@ -4,9 +4,6 @@ namespace ItalyStrap\ThemeJsonGenerator\Application; -/** - * @psalm-api - */ class DumpMessage { private string $rootFolder = ''; diff --git a/src/Application/Middlewares/Dump.php b/src/Application/Middlewares/Dump.php index 3a65111e..4b2c9820 100644 --- a/src/Application/Middlewares/Dump.php +++ b/src/Application/Middlewares/Dump.php @@ -18,9 +18,6 @@ use Psr\Container\ContainerInterface; use Symfony\Component\Console\Output\OutputInterface; -/** - * @psalm-api - */ class Dump implements MiddlewareInterface { /** @@ -53,7 +50,6 @@ public function process(object $message, HandlerInterface $handler): int */ foreach ($this->filesFinder->find($message->getRootFolder(), 'php') as $fileName => $file) { $injector = $this->configureContainer(); - /** @psalm-suppress UnresolvableInclude */ $injector->execute(require $file); $presets = $injector->make(PresetsInterface::class); $themeJson = $injector->make(ThemeJson::class); diff --git a/src/Application/Middlewares/Info.php b/src/Application/Middlewares/Info.php index 21126517..7485b8f6 100644 --- a/src/Application/Middlewares/Info.php +++ b/src/Application/Middlewares/Info.php @@ -11,7 +11,6 @@ use Symfony\Component\Console\Command\Command; /** - * @psalm-api * @todo Implement the logic */ class Info implements MiddlewareInterface diff --git a/src/Application/Middlewares/Init.php b/src/Application/Middlewares/Init.php index ba975609..5448d45a 100644 --- a/src/Application/Middlewares/Init.php +++ b/src/Application/Middlewares/Init.php @@ -14,16 +14,12 @@ use PhpParser\Node\Stmt\ClassConst; use PhpParser\NodeFinder; use PhpParser\ParserFactory; -use Psr\EventDispatcher\EventDispatcherInterface; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Output\OutputInterface; use Webimpress\SafeWriter\Exception\ExceptionInterface as FileWriterException; use Webimpress\SafeWriter\FileWriter; use Webmozart\Assert\Assert; -/** - * @psalm-api - */ class Init implements MiddlewareInterface { use DataFromJsonTrait; @@ -52,7 +48,6 @@ class Init implements MiddlewareInterface private FilesFinder $filesFinder; public function __construct( - EventDispatcherInterface $dispatcher, FilesFinder $filesFinder ) { $this->filesFinder = $filesFinder; diff --git a/src/Application/ValidateMessage.php b/src/Application/ValidateMessage.php index a4f62d0d..19f52ed4 100644 --- a/src/Application/ValidateMessage.php +++ b/src/Application/ValidateMessage.php @@ -4,9 +4,6 @@ namespace ItalyStrap\ThemeJsonGenerator\Application; -/** - * @psalm-api - */ class ValidateMessage { private string $rootFolder; diff --git a/src/Bootstrap.php b/src/Bootstrap.php index 3b6172e2..6548fb9f 100644 --- a/src/Bootstrap.php +++ b/src/Bootstrap.php @@ -13,9 +13,6 @@ use Symfony\Component\Console\Application; use Symfony\Component\Console\CommandLoader\ContainerCommandLoader; -/** - * @psalm-api - */ final class Bootstrap { public function container(): ContainerInterface diff --git a/src/Domain/Input/Settings/Color/Duotone.php b/src/Domain/Input/Settings/Color/Duotone.php index 465b759e..b6aca50c 100644 --- a/src/Domain/Input/Settings/Color/Duotone.php +++ b/src/Domain/Input/Settings/Color/Duotone.php @@ -7,9 +7,6 @@ use ItalyStrap\ThemeJsonGenerator\Domain\Input\Settings\PresetTrait; use ItalyStrap\ThemeJsonGenerator\Domain\Input\Settings\PresetInterface; -/** - * @psalm-api - */ class Duotone implements PresetInterface { use PresetTrait; diff --git a/src/Domain/Input/Settings/Color/Gradient.php b/src/Domain/Input/Settings/Color/Gradient.php index 621edf56..a6059f58 100644 --- a/src/Domain/Input/Settings/Color/Gradient.php +++ b/src/Domain/Input/Settings/Color/Gradient.php @@ -8,9 +8,6 @@ use ItalyStrap\ThemeJsonGenerator\Domain\Input\Settings\PresetTrait; use ItalyStrap\ThemeJsonGenerator\Domain\Input\Settings\PresetInterface; -/** - * @psalm-api - */ class Gradient implements PresetInterface { use PresetTrait; diff --git a/src/Domain/Input/Settings/Color/Palette.php b/src/Domain/Input/Settings/Color/Palette.php index 5fdd867d..f7398c09 100644 --- a/src/Domain/Input/Settings/Color/Palette.php +++ b/src/Domain/Input/Settings/Color/Palette.php @@ -8,9 +8,6 @@ use ItalyStrap\ThemeJsonGenerator\Domain\Input\Settings\PresetTrait; use ItalyStrap\ThemeJsonGenerator\Domain\Input\Settings\PresetInterface; -/** - * @psalm-api - */ class Palette implements PresetInterface { use PresetTrait; diff --git a/src/Domain/Input/Settings/Color/Shadow.php b/src/Domain/Input/Settings/Color/Shadow.php index 65183d85..ad885d4f 100644 --- a/src/Domain/Input/Settings/Color/Shadow.php +++ b/src/Domain/Input/Settings/Color/Shadow.php @@ -8,9 +8,6 @@ use ItalyStrap\ThemeJsonGenerator\Domain\Input\Settings\PresetInterface; use ItalyStrap\ThemeJsonGenerator\Domain\Input\Settings\PresetTrait; -/** - * @psalm-api - */ class Shadow implements PresetInterface { use PresetTrait; diff --git a/src/Domain/Input/Settings/Color/Utilities/AchromaticColorsExperimental.php b/src/Domain/Input/Settings/Color/Utilities/AchromaticColorsExperimental.php index 2f2e8259..4b845b86 100644 --- a/src/Domain/Input/Settings/Color/Utilities/AchromaticColorsExperimental.php +++ b/src/Domain/Input/Settings/Color/Utilities/AchromaticColorsExperimental.php @@ -4,9 +4,6 @@ namespace ItalyStrap\ThemeJsonGenerator\Domain\Input\Settings\Color\Utilities; -/** - * @psalm-api - */ class AchromaticColorsExperimental implements ColorsGenerator { public function generate(): array diff --git a/src/Domain/Input/Settings/Color/Utilities/AnalogousColorsExperimental.php b/src/Domain/Input/Settings/Color/Utilities/AnalogousColorsExperimental.php index 314842ae..310f6857 100644 --- a/src/Domain/Input/Settings/Color/Utilities/AnalogousColorsExperimental.php +++ b/src/Domain/Input/Settings/Color/Utilities/AnalogousColorsExperimental.php @@ -4,9 +4,6 @@ namespace ItalyStrap\ThemeJsonGenerator\Domain\Input\Settings\Color\Utilities; -/** - * @psalm-api - */ class AnalogousColorsExperimental implements ColorsGenerator { private ColorModifierInterface $colorModifier; diff --git a/src/Domain/Input/Settings/Color/Utilities/BoxShadow.php b/src/Domain/Input/Settings/Color/Utilities/BoxShadow.php index 3633f050..949873c5 100644 --- a/src/Domain/Input/Settings/Color/Utilities/BoxShadow.php +++ b/src/Domain/Input/Settings/Color/Utilities/BoxShadow.php @@ -6,9 +6,6 @@ use ItalyStrap\ThemeJsonGenerator\Domain\Input\Settings\Color\Palette; -/** - * @psalm-api - */ class BoxShadow { private bool $inset = false; diff --git a/src/Domain/Input/Settings/Color/Utilities/Color.php b/src/Domain/Input/Settings/Color/Utilities/Color.php index ac693975..fe97be82 100644 --- a/src/Domain/Input/Settings/Color/Utilities/Color.php +++ b/src/Domain/Input/Settings/Color/Utilities/Color.php @@ -8,9 +8,6 @@ use Spatie\Color\Factory as ColorFactory; use Spatie\Color\Hsla; -/** - * @psalm-api - */ final class Color implements ColorInterface { private SpatieColor $spatieColor; @@ -39,9 +36,6 @@ public function __construct(string $color) if ($reflected->hasProperty('alpha')) { $reflectionProperty = $reflected->getProperty('alpha'); $reflectionProperty->setAccessible(true); - /** - * @psalm-suppress MixedAssignment - */ $this->alpha = $reflectionProperty->getValue($this->spatieColor); $reflectionProperty->setAccessible(false); } diff --git a/src/Domain/Input/Settings/Color/Utilities/ColorFactory.php b/src/Domain/Input/Settings/Color/Utilities/ColorFactory.php index e078caee..620ddbb0 100644 --- a/src/Domain/Input/Settings/Color/Utilities/ColorFactory.php +++ b/src/Domain/Input/Settings/Color/Utilities/ColorFactory.php @@ -4,9 +4,6 @@ namespace ItalyStrap\ThemeJsonGenerator\Domain\Input\Settings\Color\Utilities; -/** - * @psalm-api - */ final class ColorFactory implements ColorFactoryInterface { /** diff --git a/src/Domain/Input/Settings/Color/Utilities/ColorFactoryInterface.php b/src/Domain/Input/Settings/Color/Utilities/ColorFactoryInterface.php index 418bc006..b4a8fd18 100644 --- a/src/Domain/Input/Settings/Color/Utilities/ColorFactoryInterface.php +++ b/src/Domain/Input/Settings/Color/Utilities/ColorFactoryInterface.php @@ -4,9 +4,6 @@ namespace ItalyStrap\ThemeJsonGenerator\Domain\Input\Settings\Color\Utilities; -/** - * @psalm-api - */ interface ColorFactoryInterface { /** diff --git a/src/Domain/Input/Settings/Color/Utilities/ColorInterface.php b/src/Domain/Input/Settings/Color/Utilities/ColorInterface.php index 4fd15496..a6d8ece7 100644 --- a/src/Domain/Input/Settings/Color/Utilities/ColorInterface.php +++ b/src/Domain/Input/Settings/Color/Utilities/ColorInterface.php @@ -4,9 +4,6 @@ namespace ItalyStrap\ThemeJsonGenerator\Domain\Input\Settings\Color\Utilities; -/** - * @psalm-api - */ // phpcs:ignore PHPCompatibility.Interfaces.NewInterfaces.stringableFound interface ColorInterface extends \Stringable { diff --git a/src/Domain/Input/Settings/Color/Utilities/ColorModifier.php b/src/Domain/Input/Settings/Color/Utilities/ColorModifier.php index 59d932c6..95ad689c 100644 --- a/src/Domain/Input/Settings/Color/Utilities/ColorModifier.php +++ b/src/Domain/Input/Settings/Color/Utilities/ColorModifier.php @@ -6,9 +6,6 @@ use Exception; -/** - * @psalm-api - */ final class ColorModifier implements ColorModifierInterface { private ColorInterface $color; @@ -137,10 +134,6 @@ private function createNewColorWithChangedContrast(int $amount): ColorInterface ); } - /** - * @psalm-suppress MixedInferredReturnType - * @psalm-suppress MixedReturnStatement - */ private function createNewColorFrom( string $hue, string $saturation, @@ -161,8 +154,6 @@ private function createNewColorFrom( /** * @todo Is it a good idea to make it public? * Evaluate possible side effects. - * @psalm-suppress MixedInferredReturnType - * @psalm-suppress MixedReturnStatement */ private function mixWith(string $color_string, float $weight = 0): ColorInterface { diff --git a/src/Domain/Input/Settings/Color/Utilities/ColorModifierInterface.php b/src/Domain/Input/Settings/Color/Utilities/ColorModifierInterface.php index 48b9a33a..58a6d16f 100644 --- a/src/Domain/Input/Settings/Color/Utilities/ColorModifierInterface.php +++ b/src/Domain/Input/Settings/Color/Utilities/ColorModifierInterface.php @@ -4,9 +4,6 @@ namespace ItalyStrap\ThemeJsonGenerator\Domain\Input\Settings\Color\Utilities; -/** - * @psalm-api - */ interface ColorModifierInterface { public function tint(float $weight = 0): ColorInterface; diff --git a/src/Domain/Input/Settings/Color/Utilities/ColorsGenerator.php b/src/Domain/Input/Settings/Color/Utilities/ColorsGenerator.php index 48d9c84a..43b2d09f 100644 --- a/src/Domain/Input/Settings/Color/Utilities/ColorsGenerator.php +++ b/src/Domain/Input/Settings/Color/Utilities/ColorsGenerator.php @@ -4,9 +4,6 @@ namespace ItalyStrap\ThemeJsonGenerator\Domain\Input\Settings\Color\Utilities; -/** - * @psalm-api - */ interface ColorsGenerator { /** diff --git a/src/Domain/Input/Settings/Color/Utilities/ComplementaryColorsExperimental.php b/src/Domain/Input/Settings/Color/Utilities/ComplementaryColorsExperimental.php index 10c8cd0e..65dc9381 100644 --- a/src/Domain/Input/Settings/Color/Utilities/ComplementaryColorsExperimental.php +++ b/src/Domain/Input/Settings/Color/Utilities/ComplementaryColorsExperimental.php @@ -4,9 +4,6 @@ namespace ItalyStrap\ThemeJsonGenerator\Domain\Input\Settings\Color\Utilities; -/** - * @psalm-api - */ class ComplementaryColorsExperimental implements ColorsGenerator { private ColorModifierInterface $color; diff --git a/src/Domain/Input/Settings/Color/Utilities/GradientInterface.php b/src/Domain/Input/Settings/Color/Utilities/GradientInterface.php index 3311c5d2..9aee6da6 100644 --- a/src/Domain/Input/Settings/Color/Utilities/GradientInterface.php +++ b/src/Domain/Input/Settings/Color/Utilities/GradientInterface.php @@ -4,9 +4,6 @@ namespace ItalyStrap\ThemeJsonGenerator\Domain\Input\Settings\Color\Utilities; -/** - * @psalm-api - */ // phpcs:ignore PHPCompatibility.Interfaces.NewInterfaces.stringableFound interface GradientInterface extends \Stringable { diff --git a/src/Domain/Input/Settings/Color/Utilities/LinearGradient.php b/src/Domain/Input/Settings/Color/Utilities/LinearGradient.php index 4873bc3b..451d47c6 100644 --- a/src/Domain/Input/Settings/Color/Utilities/LinearGradient.php +++ b/src/Domain/Input/Settings/Color/Utilities/LinearGradient.php @@ -6,9 +6,6 @@ use ItalyStrap\ThemeJsonGenerator\Domain\Input\Settings\Color\Palette; -/** - * @psalm-api - */ class LinearGradient implements GradientInterface { private string $direction = ''; diff --git a/src/Domain/Input/Settings/Color/Utilities/MonochromaticColorsExperimental.php b/src/Domain/Input/Settings/Color/Utilities/MonochromaticColorsExperimental.php index 0ef44567..25a3d1dc 100644 --- a/src/Domain/Input/Settings/Color/Utilities/MonochromaticColorsExperimental.php +++ b/src/Domain/Input/Settings/Color/Utilities/MonochromaticColorsExperimental.php @@ -4,9 +4,6 @@ namespace ItalyStrap\ThemeJsonGenerator\Domain\Input\Settings\Color\Utilities; -/** - * @psalm-api - */ class MonochromaticColorsExperimental implements ColorsGenerator { private ColorModifierInterface $colorModifier; diff --git a/src/Domain/Input/Settings/Color/Utilities/SplitComplementaryColorsExperimental.php b/src/Domain/Input/Settings/Color/Utilities/SplitComplementaryColorsExperimental.php index 8a710780..81813ba4 100644 --- a/src/Domain/Input/Settings/Color/Utilities/SplitComplementaryColorsExperimental.php +++ b/src/Domain/Input/Settings/Color/Utilities/SplitComplementaryColorsExperimental.php @@ -4,9 +4,6 @@ namespace ItalyStrap\ThemeJsonGenerator\Domain\Input\Settings\Color\Utilities; -/** - * @psalm-api - */ class SplitComplementaryColorsExperimental implements ColorsGenerator { private ColorModifierInterface $colorModifier; diff --git a/src/Domain/Input/Settings/Color/Utilities/SquareColorsExperimental.php b/src/Domain/Input/Settings/Color/Utilities/SquareColorsExperimental.php index 2415c2a9..5ccc94e1 100644 --- a/src/Domain/Input/Settings/Color/Utilities/SquareColorsExperimental.php +++ b/src/Domain/Input/Settings/Color/Utilities/SquareColorsExperimental.php @@ -4,9 +4,6 @@ namespace ItalyStrap\ThemeJsonGenerator\Domain\Input\Settings\Color\Utilities; -/** - * @psalm-api - */ class SquareColorsExperimental implements ColorsGenerator { private ColorModifierInterface $colorModifier; diff --git a/src/Domain/Input/Settings/Color/Utilities/TriadicColorsExperimental.php b/src/Domain/Input/Settings/Color/Utilities/TriadicColorsExperimental.php index 887cbfd4..2905b733 100644 --- a/src/Domain/Input/Settings/Color/Utilities/TriadicColorsExperimental.php +++ b/src/Domain/Input/Settings/Color/Utilities/TriadicColorsExperimental.php @@ -4,9 +4,6 @@ namespace ItalyStrap\ThemeJsonGenerator\Domain\Input\Settings\Color\Utilities; -/** - * @psalm-api - */ class TriadicColorsExperimental implements ColorsGenerator { private ColorModifierInterface $colorModifier; diff --git a/src/Domain/Input/Settings/Custom/Custom.php b/src/Domain/Input/Settings/Custom/Custom.php index 318b6bd2..81e5327a 100644 --- a/src/Domain/Input/Settings/Custom/Custom.php +++ b/src/Domain/Input/Settings/Custom/Custom.php @@ -7,9 +7,6 @@ use ItalyStrap\ThemeJsonGenerator\Domain\Input\Settings\PresetTrait; use ItalyStrap\ThemeJsonGenerator\Domain\Input\Settings\PresetInterface; -/** - * @psalm-api - */ class Custom implements PresetInterface { use PresetTrait; diff --git a/src/Domain/Input/Settings/Custom/CustomToPresets.php b/src/Domain/Input/Settings/Custom/CustomToPresets.php index a9754e21..ab2a6ee4 100644 --- a/src/Domain/Input/Settings/Custom/CustomToPresets.php +++ b/src/Domain/Input/Settings/Custom/CustomToPresets.php @@ -4,9 +4,6 @@ namespace ItalyStrap\ThemeJsonGenerator\Domain\Input\Settings\Custom; -/** - * @psalm-api - */ class CustomToPresets { /** diff --git a/src/Domain/Input/Settings/NullPresets.php b/src/Domain/Input/Settings/NullPresets.php index 7e659276..460dd8be 100644 --- a/src/Domain/Input/Settings/NullPresets.php +++ b/src/Domain/Input/Settings/NullPresets.php @@ -6,7 +6,6 @@ /** * @infection-ignore-all - * @psalm-api */ class NullPresets implements PresetsInterface { diff --git a/src/Domain/Input/Settings/PresetInterface.php b/src/Domain/Input/Settings/PresetInterface.php index ea7f0378..8b04eaff 100644 --- a/src/Domain/Input/Settings/PresetInterface.php +++ b/src/Domain/Input/Settings/PresetInterface.php @@ -4,9 +4,6 @@ namespace ItalyStrap\ThemeJsonGenerator\Domain\Input\Settings; -/** - * @psalm-api - */ // phpcs:ignore PHPCompatibility.Interfaces.NewInterfaces.stringableFound interface PresetInterface extends \Stringable { diff --git a/src/Domain/Input/Settings/PresetTrait.php b/src/Domain/Input/Settings/PresetTrait.php index daf4aca3..ad711061 100644 --- a/src/Domain/Input/Settings/PresetTrait.php +++ b/src/Domain/Input/Settings/PresetTrait.php @@ -4,9 +4,6 @@ namespace ItalyStrap\ThemeJsonGenerator\Domain\Input\Settings; -/** - * @psalm-api - */ trait PresetTrait { public function type(): string diff --git a/src/Domain/Input/Settings/Presets.php b/src/Domain/Input/Settings/Presets.php index b064e496..1f2c9346 100644 --- a/src/Domain/Input/Settings/Presets.php +++ b/src/Domain/Input/Settings/Presets.php @@ -10,7 +10,6 @@ use ItalyStrap\ThemeJsonGenerator\Domain\Input\Settings\Custom\Custom; /** - * @psalm-api * @see PresetsTest * @see PresetsIntegrationTest */ @@ -35,7 +34,6 @@ public function add(PresetInterface $item): self $this->assertIsUnique($key, $item); - /** @psalm-suppress MixedPropertyTypeCoercion */ $this->insertValue( $this->collection, \explode('.', $key), diff --git a/src/Domain/Input/Settings/PresetsInterface.php b/src/Domain/Input/Settings/PresetsInterface.php index 92e6921e..6dc700da 100644 --- a/src/Domain/Input/Settings/PresetsInterface.php +++ b/src/Domain/Input/Settings/PresetsInterface.php @@ -4,9 +4,6 @@ namespace ItalyStrap\ThemeJsonGenerator\Domain\Input\Settings; -/** - * @psalm-api - */ interface PresetsInterface { public function add(PresetInterface $item): self; diff --git a/src/Domain/Input/Settings/Typography/FontFamily.php b/src/Domain/Input/Settings/Typography/FontFamily.php index f0efac9b..44cbaad6 100644 --- a/src/Domain/Input/Settings/Typography/FontFamily.php +++ b/src/Domain/Input/Settings/Typography/FontFamily.php @@ -7,9 +7,6 @@ use ItalyStrap\ThemeJsonGenerator\Domain\Input\Settings\PresetTrait; use ItalyStrap\ThemeJsonGenerator\Domain\Input\Settings\PresetInterface; -/** - * @psalm-api - */ class FontFamily implements PresetInterface { use PresetTrait; diff --git a/src/Domain/Input/Settings/Typography/FontSize.php b/src/Domain/Input/Settings/Typography/FontSize.php index d2dfc421..353680b6 100644 --- a/src/Domain/Input/Settings/Typography/FontSize.php +++ b/src/Domain/Input/Settings/Typography/FontSize.php @@ -8,9 +8,6 @@ use ItalyStrap\ThemeJsonGenerator\Domain\Input\Settings\PresetInterface; use ItalyStrap\ThemeJsonGenerator\Domain\Input\Settings\Typography\Utilities\Fluid; -/** - * @psalm-api - */ class FontSize implements PresetInterface { use PresetTrait; diff --git a/src/Domain/Input/Settings/Typography/Utilities/Fluid.php b/src/Domain/Input/Settings/Typography/Utilities/Fluid.php index 69001aac..9a2947fa 100644 --- a/src/Domain/Input/Settings/Typography/Utilities/Fluid.php +++ b/src/Domain/Input/Settings/Typography/Utilities/Fluid.php @@ -4,9 +4,6 @@ namespace ItalyStrap\ThemeJsonGenerator\Domain\Input\Settings\Typography\Utilities; -/** - * @psalm-api - */ class Fluid { /** diff --git a/src/Domain/Input/Settings/Typography/Utilities/FontFace.php b/src/Domain/Input/Settings/Typography/Utilities/FontFace.php index a20686f0..cda39d0c 100644 --- a/src/Domain/Input/Settings/Typography/Utilities/FontFace.php +++ b/src/Domain/Input/Settings/Typography/Utilities/FontFace.php @@ -4,9 +4,6 @@ namespace ItalyStrap\ThemeJsonGenerator\Domain\Input\Settings\Typography\Utilities; -/** - * @psalm-api - */ class FontFace { private string $fontFamily; diff --git a/src/Domain/Input/Settings/Utilities/CalcExperimental.php b/src/Domain/Input/Settings/Utilities/CalcExperimental.php index 831da7ea..75a438cc 100644 --- a/src/Domain/Input/Settings/Utilities/CalcExperimental.php +++ b/src/Domain/Input/Settings/Utilities/CalcExperimental.php @@ -4,9 +4,6 @@ namespace ItalyStrap\ThemeJsonGenerator\Domain\Input\Settings\Utilities; -/** - * @psalm-api - */ class CalcExperimental { private string $value; diff --git a/src/Domain/Input/Settings/Utilities/ClampExperimental.php b/src/Domain/Input/Settings/Utilities/ClampExperimental.php index 0aeb4bae..4190deb3 100644 --- a/src/Domain/Input/Settings/Utilities/ClampExperimental.php +++ b/src/Domain/Input/Settings/Utilities/ClampExperimental.php @@ -4,9 +4,6 @@ namespace ItalyStrap\ThemeJsonGenerator\Domain\Input\Settings\Utilities; -/** - * @psalm-api - */ class ClampExperimental { private string $value; diff --git a/src/Domain/Input/Settings/Utilities/DimensionExperimental.php b/src/Domain/Input/Settings/Utilities/DimensionExperimental.php index 0d8f3962..38e55c0a 100644 --- a/src/Domain/Input/Settings/Utilities/DimensionExperimental.php +++ b/src/Domain/Input/Settings/Utilities/DimensionExperimental.php @@ -9,7 +9,6 @@ * https://github.com/pimlie/php-unit-conversion * https://github.com/PhpUnitsOfMeasure/php-units-of-measure * https://wiki.php.net/rfc/clamp - * @psalm-api */ final class DimensionExperimental { diff --git a/src/Domain/Input/Settings/Utilities/SupportedUnitsExperimental.php b/src/Domain/Input/Settings/Utilities/SupportedUnitsExperimental.php index f8cedace..a2b64930 100644 --- a/src/Domain/Input/Settings/Utilities/SupportedUnitsExperimental.php +++ b/src/Domain/Input/Settings/Utilities/SupportedUnitsExperimental.php @@ -4,9 +4,6 @@ namespace ItalyStrap\ThemeJsonGenerator\Domain\Input\Settings\Utilities; -/** - * @psalm-api - */ class SupportedUnitsExperimental implements UnitInterfaceExperimental { private array $units; diff --git a/src/Domain/Input/Settings/Utilities/UnitInterfaceExperimental.php b/src/Domain/Input/Settings/Utilities/UnitInterfaceExperimental.php index b661ce99..8f1900fc 100644 --- a/src/Domain/Input/Settings/Utilities/UnitInterfaceExperimental.php +++ b/src/Domain/Input/Settings/Utilities/UnitInterfaceExperimental.php @@ -4,9 +4,6 @@ namespace ItalyStrap\ThemeJsonGenerator\Domain\Input\Settings\Utilities; -/** - * @psalm-api - */ interface UnitInterfaceExperimental { /** diff --git a/src/Domain/Input/Styles/ArrayableInterface.php b/src/Domain/Input/Styles/ArrayableInterface.php index 08c18822..86dda03f 100644 --- a/src/Domain/Input/Styles/ArrayableInterface.php +++ b/src/Domain/Input/Styles/ArrayableInterface.php @@ -4,9 +4,6 @@ namespace ItalyStrap\ThemeJsonGenerator\Domain\Input\Styles; -/** - * @psalm-api - */ interface ArrayableInterface { /** diff --git a/src/Domain/Input/Styles/Border.php b/src/Domain/Input/Styles/Border.php index ef9893ed..ebbeb358 100644 --- a/src/Domain/Input/Styles/Border.php +++ b/src/Domain/Input/Styles/Border.php @@ -4,9 +4,6 @@ namespace ItalyStrap\ThemeJsonGenerator\Domain\Input\Styles; -/** - * @psalm-api - */ final class Border implements ArrayableInterface, \JsonSerializable { use CommonTrait; diff --git a/src/Domain/Input/Styles/Color.php b/src/Domain/Input/Styles/Color.php index 14fac358..9046f3ce 100644 --- a/src/Domain/Input/Styles/Color.php +++ b/src/Domain/Input/Styles/Color.php @@ -4,9 +4,6 @@ namespace ItalyStrap\ThemeJsonGenerator\Domain\Input\Styles; -/** - * @psalm-api - */ final class Color implements ArrayableInterface, \JsonSerializable { use CommonTrait; diff --git a/src/Domain/Input/Styles/Css.php b/src/Domain/Input/Styles/Css.php index 05668b9f..1e02f258 100644 --- a/src/Domain/Input/Styles/Css.php +++ b/src/Domain/Input/Styles/Css.php @@ -17,7 +17,6 @@ * @link https://www.google.it/search?q=php+inline+css+content&sca_esv=596560865&ei=mAicZaTCGp3Axc8Pq7yT8AQ&ved=0ahUKEwik7p-Rgs6DAxUdYPEDHSveBE4Q4dUDCBA&uact=5&oq=php+inline+css+content&gs_lp=Egxnd3Mtd2l6LXNlcnAiFnBocCBpbmxpbmUgY3NzIGNvbnRlbnQyBRAhGKABMgUQIRigATIIECEYFhgeGB0yCBAhGBYYHhgdMggQIRgWGB4YHUjvogFQmgdYwJcBcAF4AZABAJgBsQGgAZkSqgEEMC4xOLgBA8gBAPgBAcICChAAGEcY1gQYsAPCAgoQABiABBiKBRhDwgIFEAAYgATCAgYQABgWGB7CAgcQABiABBgTwgIIEAAYFhgeGBPiAwQYACBBiAYBkAYI&sclient=gws-wiz-serp#ip=1 * @link https://github.com/topics/inline-css?l=php * - * @psalm-api * @see CssTest */ class Css implements CssInterface diff --git a/src/Domain/Input/Styles/CssInterface.php b/src/Domain/Input/Styles/CssInterface.php index ec55bbf5..ac3405a4 100644 --- a/src/Domain/Input/Styles/CssInterface.php +++ b/src/Domain/Input/Styles/CssInterface.php @@ -4,9 +4,6 @@ namespace ItalyStrap\ThemeJsonGenerator\Domain\Input\Styles; -/** - * @psalm-api - */ interface CssInterface { public const M_AMPERSAND_MUST_NOT_BE_AT_THE_BEGINNING = 'CSS cannot begin with an ampersand (&)'; diff --git a/src/Domain/Input/Styles/Outline.php b/src/Domain/Input/Styles/Outline.php index ce42c3fe..ff80abcb 100644 --- a/src/Domain/Input/Styles/Outline.php +++ b/src/Domain/Input/Styles/Outline.php @@ -4,9 +4,6 @@ namespace ItalyStrap\ThemeJsonGenerator\Domain\Input\Styles; -/** - * @psalm-api - */ class Outline implements ArrayableInterface, \JsonSerializable { use CommonTrait; diff --git a/src/Domain/Input/Styles/Scss.php b/src/Domain/Input/Styles/Scss.php index ef8e876d..3af4d1db 100644 --- a/src/Domain/Input/Styles/Scss.php +++ b/src/Domain/Input/Styles/Scss.php @@ -11,7 +11,6 @@ use ScssPhp\ScssPhp\OutputStyle; /** - * @psalm-api * @see ScssTest */ class Scss implements CssInterface diff --git a/src/Domain/Input/Styles/Spacing.php b/src/Domain/Input/Styles/Spacing.php index 52d9ddd3..4f95aa16 100644 --- a/src/Domain/Input/Styles/Spacing.php +++ b/src/Domain/Input/Styles/Spacing.php @@ -4,9 +4,6 @@ namespace ItalyStrap\ThemeJsonGenerator\Domain\Input\Styles; -/** - * @psalm-api - */ final class Spacing implements ArrayableInterface, \JsonSerializable { use CommonTrait; diff --git a/src/Domain/Input/Styles/Typography.php b/src/Domain/Input/Styles/Typography.php index e9ea1048..fb8b3f40 100644 --- a/src/Domain/Input/Styles/Typography.php +++ b/src/Domain/Input/Styles/Typography.php @@ -4,9 +4,6 @@ namespace ItalyStrap\ThemeJsonGenerator\Domain\Input\Styles; -/** - * @psalm-api - */ final class Typography implements ArrayableInterface, \JsonSerializable { use CommonTrait; diff --git a/src/Infrastructure/Filesystem/FilesExtension.php b/src/Infrastructure/Filesystem/FilesExtension.php index 965a75b8..252f8a01 100644 --- a/src/Infrastructure/Filesystem/FilesExtension.php +++ b/src/Infrastructure/Filesystem/FilesExtension.php @@ -4,9 +4,6 @@ namespace ItalyStrap\ThemeJsonGenerator\Infrastructure\Filesystem; -/** - * @psalm-api - */ final class FilesExtension { public const PHP = '.php'; diff --git a/src/Infrastructure/Filesystem/FilesFinder.php b/src/Infrastructure/Filesystem/FilesFinder.php index 1a028e80..064f7b31 100644 --- a/src/Infrastructure/Filesystem/FilesFinder.php +++ b/src/Infrastructure/Filesystem/FilesFinder.php @@ -6,9 +6,6 @@ use ItalyStrap\Finder\FinderInterface; -/** - * @psalm-api - */ class FilesFinder { public const ROOT_FILE_NAME = 'theme'; diff --git a/tests/unit/Domain/Output/InitTest.php b/tests/unit/Domain/Output/InitTest.php index 093b4914..10ea58c8 100644 --- a/tests/unit/Domain/Output/InitTest.php +++ b/tests/unit/Domain/Output/InitTest.php @@ -15,7 +15,6 @@ class InitTest extends UnitTestCase private function makeInstance(): Init { return new Init( - $this->makeDispatcher(), $this->makeFilesFinder(), ); } From d30300edc43919926025e24ba07a3fc4eda884be Mon Sep 17 00:00:00 2001 From: Enea Date: Mon, 18 May 2026 06:29:00 +0200 Subject: [PATCH 2/3] chore(refactor): replace Psalm with PHPStan for static analysis, update scripts, Makefile targets, and workflow configuration --- .github/workflows/static-analysis.yml | 6 +++--- Makefile | 8 ++++---- composer.json | 6 +++--- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml index 082d67b6..69c9e843 100644 --- a/.github/workflows/static-analysis.yml +++ b/.github/workflows/static-analysis.yml @@ -6,7 +6,7 @@ on: paths: - '**workflows/static-analysis.yml' - '**.php' - - '**psalm.xml' + - '**phpstan.neon' - '**composer.json' jobs: @@ -27,5 +27,5 @@ jobs: - uses: ramsey/composer-install@v3 - - name: Psalm - run: vendor/bin/psalm + - name: PHPStan + run: composer stan diff --git a/Makefile b/Makefile index ec680401..21dfe3a9 100644 --- a/Makefile +++ b/Makefile @@ -96,10 +96,10 @@ cs/fix: up ### Run the code sniffer and fix the errors # PHPStan commands -.PHONY: phpstan -phpstan: up ### Run PHPStan +.PHONY: stan +stan: up ### Run PHPStan @echo "Running PHPStan" - @$(DOCKER_DIR) ./composer phpstan + @$(DOCKER_DIR) ./composer stan # Codeception commands @@ -138,7 +138,7 @@ acceptance: up ### Run the acceptance tests tests: unit integration functional ### Run unit and integration tests .PHONY: qa -qa: cs phpstan unit integration functional ### Run all the tests +qa: cs stan unit integration functional ### Run all the tests # Infection commands diff --git a/composer.json b/composer.json index 60e6f26a..04155d25 100644 --- a/composer.json +++ b/composer.json @@ -97,7 +97,7 @@ "cs:fix": [ "@php ./vendor/bin/phpcbf -p" ], - "phpstan": [ + "stan": [ "@php ./vendor/bin/phpstan analyse --debug --no-progress" ], "unit": [ @@ -125,7 +125,7 @@ ], "qa": [ "@cs", - "@phpstan", + "@stan", "@rector", "@unit" ], @@ -145,7 +145,7 @@ "scripts-descriptions": { "cs": "Run Code Sniffer", "cs:fix": "Run Code Sniffer and fix errors", - "phpstan": "Run PHPStan", + "stan": "Run PHPStan", "unit": "Run Unit tests", "integration": "Run Integration tests", "infection": "Run Infection", From e49fd0a96a6b5c901fda2f18f9e71101b6a4f06c Mon Sep 17 00:00:00 2001 From: Enea Date: Mon, 18 May 2026 09:24:35 +0200 Subject: [PATCH 3/3] chore(refactor): replace `HandlerInterface` with `ConsoleHandler`, enhance type safety, improve exception handling, and simplify middleware processing --- phpstan.neon | 4 +- src/Api/ThemeJson.php | 12 ++++++ src/Application/Commands/DumpCommand.php | 17 +++++---- src/Application/Commands/InfoCommand.php | 8 ++-- src/Application/Commands/InitCommand.php | 8 ++-- src/Application/Commands/ValidateCommand.php | 10 ++--- .../Middlewares/DeleteSchemaJson.php | 8 +++- src/Application/Middlewares/Dump.php | 25 +++++++++++- src/Application/Middlewares/Info.php | 4 +- src/Application/Middlewares/Init.php | 4 ++ src/Application/Middlewares/SchemaJson.php | 8 +++- src/Application/Middlewares/Validate.php | 8 +++- .../Input/Settings/Color/Utilities/Color.php | 15 +++++--- .../Color/Utilities/ColorModifier.php | 2 +- .../Input/Settings/Custom/CustomToPresets.php | 9 ++++- src/Domain/Input/Settings/NullPresets.php | 5 +++ src/Domain/Input/Settings/PresetInterface.php | 2 +- src/Domain/Input/Settings/Presets.php | 17 +++++++-- .../Input/Settings/PresetsInterface.php | 5 +++ .../Input/Settings/Typography/FontSize.php | 3 ++ .../Typography/Utilities/FontFace.php | 8 +++- src/Domain/Input/Styles/CommonTrait.php | 15 ++++++-- src/Domain/Input/Styles/Css.php | 2 +- src/Domain/Input/Styles/Spacing.php | 3 ++ .../Filesystem/DataFromJsonTrait.php | 3 ++ src/Infrastructure/Filesystem/FileWriter.php | 1 + src/Infrastructure/Filesystem/FilesFinder.php | 6 ++- .../Filesystem/JsonFileWriter.php | 1 + src/Infrastructure/Filesystem/Path.php | 13 ------- .../Filesystem/ScssFileWriter.php | 5 ++- src/ModuleApplication.php | 38 +++++++++++++++---- src/ModuleInfrastructure.php | 3 ++ stubs/auryn-injector.stub | 18 +++++++++ .../Middlewares/SchemaJsonTest.php | 17 ++++----- 34 files changed, 227 insertions(+), 80 deletions(-) delete mode 100644 src/Infrastructure/Filesystem/Path.php create mode 100644 stubs/auryn-injector.stub diff --git a/phpstan.neon b/phpstan.neon index de1815de..85808fdd 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,9 +1,11 @@ parameters: - level: 1 + level: 9 paths: - bin - functions - src + stubFiles: + - stubs/auryn-injector.stub excludePaths: analyse: - src/**/*Experimental*.php diff --git a/src/Api/ThemeJson.php b/src/Api/ThemeJson.php index 2b5be676..d3093d10 100644 --- a/src/Api/ThemeJson.php +++ b/src/Api/ThemeJson.php @@ -32,16 +32,25 @@ public function appendGlobalCss(string $css): bool return $this->set(SectionNames::STYLES . '.css', $currentCss . $css); } + /** + * @param array $config + */ public function setElementStyle(string $elementName, array $config): bool { return $this->set(SectionNames::STYLES . '.elements.' . $elementName, $config); } + /** + * @param array $config + */ public function setBlockSettings(string $blockName, array $config): bool { return $this->set(SectionNames::SETTINGS . '.blocks.' . $blockName, $config); } + /** + * @param array $config + */ public function setBlockStyle(string $blockName, array $config): bool { return $this->set(SectionNames::STYLES . '.blocks.' . $blockName, $config); @@ -75,6 +84,9 @@ public function setPresets(PresetsInterface $presets): bool return true; } + /** + * @return array + */ public function jsonSerialize(): array { return $this->getArrayCopy(); diff --git a/src/Application/Commands/DumpCommand.php b/src/Application/Commands/DumpCommand.php index 890a1b8c..e8cae02c 100644 --- a/src/Application/Commands/DumpCommand.php +++ b/src/Application/Commands/DumpCommand.php @@ -4,9 +4,9 @@ namespace ItalyStrap\ThemeJsonGenerator\Application\Commands; -use ItalyStrap\Pipeline\HandlerInterface; use ItalyStrap\ThemeJsonGenerator\Application\Commands\Utils\RootFolderTrait; use ItalyStrap\ThemeJsonGenerator\Application\DumpMessage; +use ItalyStrap\ThemeJsonGenerator\Infrastructure\Handler\ConsoleHandler; use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; @@ -46,10 +46,10 @@ final class DumpCommand extends Command */ public const FILE = 'file'; - private HandlerInterface $handler; + private ConsoleHandler $handler; public function __construct( - HandlerInterface $handler + ConsoleHandler $handler ) { $this->handler = $handler; parent::__construct(); @@ -113,17 +113,20 @@ protected function configure(): void protected function execute(InputInterface $input, OutputInterface $output): int { - $rootFolder = $this->rootFolder((string)$input->getOption('path')); + $path = $input->getOption('path'); + $file = $input->getOption(self::FILE); + + $rootFolder = $this->rootFolder(\is_string($path) ? $path : ''); $message = new DumpMessage( $rootFolder, '', - (bool)$input->getOption('dry-run'), - (string)$input->getOption(self::FILE) + $input->getOption('dry-run') === true, + \is_string($file) ? $file : '' ); try { - return (int)$this->handler->handle($message); + return $this->handler->handle($message); } catch (\Exception $exception) { $output->writeln('Error: ' . $exception->getMessage() . ''); return Command::FAILURE; diff --git a/src/Application/Commands/InfoCommand.php b/src/Application/Commands/InfoCommand.php index fce2398a..1a9e3a69 100644 --- a/src/Application/Commands/InfoCommand.php +++ b/src/Application/Commands/InfoCommand.php @@ -4,9 +4,9 @@ namespace ItalyStrap\ThemeJsonGenerator\Application\Commands; -use ItalyStrap\Pipeline\HandlerInterface; use ItalyStrap\ThemeJsonGenerator\Application\Commands\Utils\RootFolderTrait; use ItalyStrap\ThemeJsonGenerator\Application\Message; +use ItalyStrap\ThemeJsonGenerator\Infrastructure\Handler\ConsoleHandler; use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; @@ -20,10 +20,10 @@ class InfoCommand extends Command public const NAME = 'info'; public const DESCRIPTION = 'Show info about JSON theme'; - private HandlerInterface $handler; + private ConsoleHandler $handler; public function __construct( - HandlerInterface $handler + ConsoleHandler $handler ) { $this->handler = $handler; parent::__construct(); @@ -42,7 +42,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $message = new Message($rootFolder); try { - return (int)$this->handler->handle($message); + return $this->handler->handle($message); } catch (\Exception $exception) { $output->writeln('Error: ' . $exception->getMessage() . ''); return Command::FAILURE; diff --git a/src/Application/Commands/InitCommand.php b/src/Application/Commands/InitCommand.php index fd3d3841..3cd494bd 100644 --- a/src/Application/Commands/InitCommand.php +++ b/src/Application/Commands/InitCommand.php @@ -4,10 +4,10 @@ namespace ItalyStrap\ThemeJsonGenerator\Application\Commands; -use ItalyStrap\Pipeline\HandlerInterface; use ItalyStrap\ThemeJsonGenerator\Application\Commands\Utils\RootFolderTrait; use ItalyStrap\ThemeJsonGenerator\Application\Message; use ItalyStrap\ThemeJsonGenerator\Infrastructure\Filesystem\DataFromJsonTrait; +use ItalyStrap\ThemeJsonGenerator\Infrastructure\Handler\ConsoleHandler; use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; @@ -23,10 +23,10 @@ class InitCommand extends Command public const DESCRIPTION = 'Initialize theme.json file'; - private HandlerInterface $handler; + private ConsoleHandler $handler; public function __construct( - HandlerInterface $handler, + ConsoleHandler $handler, ) { $this->handler = $handler; parent::__construct(); @@ -52,7 +52,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $message = new Message($rootFolder); try { - return (int)$this->handler->handle($message); + return $this->handler->handle($message); } catch (\Exception $exception) { $output->writeln('Error: ' . $exception->getMessage() . ''); return Command::FAILURE; diff --git a/src/Application/Commands/ValidateCommand.php b/src/Application/Commands/ValidateCommand.php index c36ade06..9a5fadd9 100644 --- a/src/Application/Commands/ValidateCommand.php +++ b/src/Application/Commands/ValidateCommand.php @@ -4,10 +4,10 @@ namespace ItalyStrap\ThemeJsonGenerator\Application\Commands; -use ItalyStrap\Pipeline\HandlerInterface; use ItalyStrap\ThemeJsonGenerator\Application\Commands\Utils\RootFolderTrait; use ItalyStrap\ThemeJsonGenerator\Application\ValidateMessage; use ItalyStrap\ThemeJsonGenerator\Infrastructure\Filesystem\DataFromJsonTrait; +use ItalyStrap\ThemeJsonGenerator\Infrastructure\Handler\ConsoleHandler; use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; @@ -22,10 +22,10 @@ class ValidateCommand extends Command public const NAME = 'validate'; public const DESCRIPTION = 'Validate theme.json file'; - private HandlerInterface $handler; + private ConsoleHandler $handler; public function __construct( - HandlerInterface $handler + ConsoleHandler $handler ) { $this->handler = $handler; parent::__construct(); @@ -52,10 +52,10 @@ protected function execute(InputInterface $input, OutputInterface $output): int $rootFolder = $this->rootFolder(); $schemaPath = $rootFolder . '/theme.schema.json'; - $message = new ValidateMessage($rootFolder, $schemaPath, (bool)$input->getOption('force')); + $message = new ValidateMessage($rootFolder, $schemaPath, $input->getOption('force') === true); try { - return (int)$this->handler->handle($message); + return $this->handler->handle($message); } catch (\Exception $exception) { $output->writeln('Error: ' . $exception->getMessage() . ''); return Command::FAILURE; diff --git a/src/Application/Middlewares/DeleteSchemaJson.php b/src/Application/Middlewares/DeleteSchemaJson.php index e2540810..98dade27 100644 --- a/src/Application/Middlewares/DeleteSchemaJson.php +++ b/src/Application/Middlewares/DeleteSchemaJson.php @@ -7,17 +7,21 @@ use ItalyStrap\Pipeline\HandlerInterface; use ItalyStrap\Pipeline\MiddlewareInterface; use ItalyStrap\ThemeJsonGenerator\Application\ValidateMessage; +use ItalyStrap\ThemeJsonGenerator\Infrastructure\Handler\ConsoleHandler; class DeleteSchemaJson implements MiddlewareInterface { + /** + * @phpstan-param ValidateMessage $message + * @phpstan-param ConsoleHandler $handler + */ public function process(object $message, HandlerInterface $handler): int { - /** @var ValidateMessage $message */ $schemaPath = $message->getSchemaPath(); if ($message->shouldRecreate() && \file_exists($schemaPath)) { \unlink($schemaPath); } - return (int)$handler->handle($message); + return $handler->handle($message); } } diff --git a/src/Application/Middlewares/Dump.php b/src/Application/Middlewares/Dump.php index 4b2c9820..c67193b6 100644 --- a/src/Application/Middlewares/Dump.php +++ b/src/Application/Middlewares/Dump.php @@ -15,6 +15,7 @@ use ItalyStrap\ThemeJsonGenerator\Infrastructure\Filesystem\FilesFinder; use ItalyStrap\ThemeJsonGenerator\Infrastructure\Filesystem\JsonFileWriter; use ItalyStrap\ThemeJsonGenerator\Infrastructure\Filesystem\ScssFileWriter; +use ItalyStrap\ThemeJsonGenerator\Infrastructure\Handler\ConsoleHandler; use Psr\Container\ContainerInterface; use Symfony\Component\Console\Output\OutputInterface; @@ -35,6 +36,10 @@ public function __construct( $this->filesFinder = $filesFinder; } + /** + * @phpstan-param DumpMessage $message + * @phpstan-param ConsoleHandler $handler + */ public function process(object $message, HandlerInterface $handler): int { /** @@ -53,6 +58,7 @@ public function process(object $message, HandlerInterface $handler): int $injector->execute(require $file); $presets = $injector->make(PresetsInterface::class); $themeJson = $injector->make(ThemeJson::class); + $themeJson->setPresets($presets); $count++; @@ -78,9 +84,12 @@ public function process(object $message, HandlerInterface $handler): int $output->writeln(self::M_NO_FILE_FOUND); } - return (int)$handler->handle($message); + return $handler->handle($message); } + /** + * @param ThemeJson $themeJson + */ private function generateJsonFile( OutputInterface $output, DumpMessage $message, @@ -104,6 +113,9 @@ private function generateJsonFile( $output->writeln('========================'); } + /** + * @param ThemeJson $themeJson + */ private function generateScssFile( OutputInterface $output, DumpMessage $message, @@ -151,15 +163,24 @@ private function configureContainer(): \Auryn\Injector return $injector; } + /** + * @param ConfigInterface $config + */ private function createContainer( \Auryn\Injector $injector, - \ItalyStrap\Config\ConfigInterface $config + ConfigInterface $config ): ContainerInterface { return new class ($injector, $config) implements ContainerInterface { private \Auryn\Injector $injector; + /** + * @var ConfigInterface + */ private ConfigInterface $config; + /** + * @param ConfigInterface $config + */ public function __construct(\Auryn\Injector $injector, ConfigInterface $config) { $this->injector = $injector; diff --git a/src/Application/Middlewares/Info.php b/src/Application/Middlewares/Info.php index 7485b8f6..a7a60023 100644 --- a/src/Application/Middlewares/Info.php +++ b/src/Application/Middlewares/Info.php @@ -23,9 +23,11 @@ public function __construct( $this->filesFinder = $filesFinder; } + /** + * @phpstan-param Message $message + */ public function process(object $message, HandlerInterface $handler): int { - /** @var Message $message */ foreach ($this->filesFinder->find($message->getRootFolder(), 'json') as $file) { echo $file->getBasename() . PHP_EOL; } diff --git a/src/Application/Middlewares/Init.php b/src/Application/Middlewares/Init.php index 5448d45a..837de744 100644 --- a/src/Application/Middlewares/Init.php +++ b/src/Application/Middlewares/Init.php @@ -7,6 +7,7 @@ use Brick\VarExporter\VarExporter; use ItalyStrap\Pipeline\HandlerInterface; use ItalyStrap\Pipeline\MiddlewareInterface; +use ItalyStrap\ThemeJsonGenerator\Application\Message; use ItalyStrap\ThemeJsonGenerator\Infrastructure\Filesystem\DataFromJsonTrait; use ItalyStrap\ThemeJsonGenerator\Infrastructure\Filesystem\FilesFinder; use PhpParser\Error; @@ -53,6 +54,9 @@ public function __construct( $this->filesFinder = $filesFinder; } + /** + * @phpstan-param Message $message + */ public function process(object $message, HandlerInterface $handler): int { /** diff --git a/src/Application/Middlewares/SchemaJson.php b/src/Application/Middlewares/SchemaJson.php index 1124d04e..e4c5e618 100644 --- a/src/Application/Middlewares/SchemaJson.php +++ b/src/Application/Middlewares/SchemaJson.php @@ -7,19 +7,23 @@ use ItalyStrap\Pipeline\HandlerInterface; use ItalyStrap\Pipeline\MiddlewareInterface; use ItalyStrap\ThemeJsonGenerator\Application\ValidateMessage; +use ItalyStrap\ThemeJsonGenerator\Infrastructure\Handler\ConsoleHandler; use Webimpress\SafeWriter\FileWriter; class SchemaJson implements MiddlewareInterface { + /** + * @phpstan-param ValidateMessage $message + * @phpstan-param ConsoleHandler $handler + */ public function process(object $message, HandlerInterface $handler): int { - /** @var ValidateMessage $message */ $schemaPath = $message->getSchemaPath(); if (!\file_exists($schemaPath) || $this->isFileSchemaOlderThanOneWeek($schemaPath)) { $this->createFileSchema($schemaPath); } - return (int)$handler->handle($message); + return $handler->handle($message); } private function isFileSchemaOlderThanOneWeek(string $schemaPath): bool diff --git a/src/Application/Middlewares/Validate.php b/src/Application/Middlewares/Validate.php index a2301027..3723accd 100644 --- a/src/Application/Middlewares/Validate.php +++ b/src/Application/Middlewares/Validate.php @@ -9,6 +9,7 @@ use ItalyStrap\ThemeJsonGenerator\Application\ValidateMessage; use ItalyStrap\ThemeJsonGenerator\Infrastructure\Filesystem\DataFromJsonTrait; use ItalyStrap\ThemeJsonGenerator\Infrastructure\Filesystem\FilesFinder; +use ItalyStrap\ThemeJsonGenerator\Infrastructure\Handler\ConsoleHandler; use JsonSchema\Validator; use ScssPhp\ScssPhp\Compiler; use Symfony\Component\Console\Output\OutputInterface; @@ -33,6 +34,10 @@ public function __construct( $this->compiler = $compiler; } + /** + * @phpstan-param ValidateMessage $message + * @phpstan-param ConsoleHandler $handler + */ public function process(object $message, HandlerInterface $handler): mixed { /** @@ -40,7 +45,6 @@ public function process(object $message, HandlerInterface $handler): mixed */ $output = new \Symfony\Component\Console\Output\ConsoleOutput(); - /** @var ValidateMessage $message */ foreach ($this->filesFinder->find($message->getRootFolder(), 'json') as $file) { $output->writeln('========================'); $output->writeln(\sprintf( @@ -56,7 +60,7 @@ public function process(object $message, HandlerInterface $handler): mixed $this->compiler->compileString(''); } - return (int)$handler->handle($message); + return $handler->handle($message); } private function validateJsonFile( diff --git a/src/Domain/Input/Settings/Color/Utilities/Color.php b/src/Domain/Input/Settings/Color/Utilities/Color.php index fe97be82..e0423a4d 100644 --- a/src/Domain/Input/Settings/Color/Utilities/Color.php +++ b/src/Domain/Input/Settings/Color/Utilities/Color.php @@ -36,7 +36,15 @@ public function __construct(string $color) if ($reflected->hasProperty('alpha')) { $reflectionProperty = $reflected->getProperty('alpha'); $reflectionProperty->setAccessible(true); - $this->alpha = $reflectionProperty->getValue($this->spatieColor); + $alpha = $reflectionProperty->getValue($this->spatieColor); + if (!\is_string($alpha) && !\is_float($alpha) && !\is_int($alpha)) { + throw new \RuntimeException(\sprintf( + 'Expected alpha to be string, float, or int, got %s.', + \get_debug_type($alpha) + )); + } + + $this->alpha = \is_int($alpha) ? (float)$alpha : $alpha; $reflectionProperty->setAccessible(false); } @@ -186,10 +194,7 @@ public function __toString(): string return (string)$this->spatieColor; } - /** - * @param mixed $alpha - */ - private function fromHexToFloat($alpha): float + private function fromHexToFloat(string|int|float $alpha): float { return \is_string($alpha) ? \hexdec($alpha) / 255 : (float)$alpha; } diff --git a/src/Domain/Input/Settings/Color/Utilities/ColorModifier.php b/src/Domain/Input/Settings/Color/Utilities/ColorModifier.php index 95ad689c..54351346 100644 --- a/src/Domain/Input/Settings/Color/Utilities/ColorModifier.php +++ b/src/Domain/Input/Settings/Color/Utilities/ColorModifier.php @@ -202,7 +202,7 @@ private function sanitizeFromFloatToInteger(float $value): int /** * @param ColorInterface $newColor - * @return mixed + * @return ColorInterface * @throws Exception */ private function callMethodOnColorObject(ColorInterface $newColor): ColorInterface diff --git a/src/Domain/Input/Settings/Custom/CustomToPresets.php b/src/Domain/Input/Settings/Custom/CustomToPresets.php index ab2a6ee4..e1f5adee 100644 --- a/src/Domain/Input/Settings/Custom/CustomToPresets.php +++ b/src/Domain/Input/Settings/Custom/CustomToPresets.php @@ -20,17 +20,24 @@ public function __construct( $this->customs = $customs; } + /** + * @return Custom[] + */ public function toArray(): array { return $this->presetsToFlat($this->customs); } + /** + * @param array $presets + * @return Custom[] + */ private function presetsToFlat(array $presets, string $prefix = ''): array { $processed = []; /** - * @var string|array|\Stringable $value + * @var string|array|\Stringable $value */ foreach ($presets as $key => $value) { $fullKey = (string)($prefix === '' ? $key : $prefix . '.' . $key); diff --git a/src/Domain/Input/Settings/NullPresets.php b/src/Domain/Input/Settings/NullPresets.php index 460dd8be..011d4668 100644 --- a/src/Domain/Input/Settings/NullPresets.php +++ b/src/Domain/Input/Settings/NullPresets.php @@ -28,4 +28,9 @@ public function parse(string $content): string { return $content; } + + public function toArrayByCategory(string $category): array + { + return []; + } } diff --git a/src/Domain/Input/Settings/PresetInterface.php b/src/Domain/Input/Settings/PresetInterface.php index 8b04eaff..c31058e3 100644 --- a/src/Domain/Input/Settings/PresetInterface.php +++ b/src/Domain/Input/Settings/PresetInterface.php @@ -20,7 +20,7 @@ public function var(string $fallback = ''): string; public function __toString(): string; /** - * @return array + * @return array|object> */ public function toArray(): array; } diff --git a/src/Domain/Input/Settings/Presets.php b/src/Domain/Input/Settings/Presets.php index 1f2c9346..093cae85 100644 --- a/src/Domain/Input/Settings/Presets.php +++ b/src/Domain/Input/Settings/Presets.php @@ -112,6 +112,9 @@ public function field(string $field): self return $this; } + /** + * @return array + */ public function toArray(): array { $field = $this->field; @@ -127,7 +130,8 @@ public function toArray(): array return $this->processCustomCollection($fetched); } - return $this->processPresetCollection($fetched); + /** @var PresetInterface[] $fetched */ + return $this->processPresetCollection(...$fetched); } /** @@ -139,7 +143,11 @@ public function toArrayByCategory(string $category): array return $this->toArray(); } - private function processPresetCollection(array $collection): array + /** + * @param PresetInterface ...$collection + * @return array> + */ + private function processPresetCollection(PresetInterface ...$collection): array { return \array_values(\array_map( function (PresetInterface $item): array { @@ -160,7 +168,7 @@ function (PresetInterface $item): array { /** * @param array $collection - * @param array-key|string $prefix + * @param string $prefix * @return array */ private function processCustomCollection(array $collection, string $prefix = ''): array @@ -194,6 +202,9 @@ private function assertIsUnique(string $key, PresetInterface $item): void } } + /** + * @return array + */ public function jsonSerialize(): array { return $this->toArray(); diff --git a/src/Domain/Input/Settings/PresetsInterface.php b/src/Domain/Input/Settings/PresetsInterface.php index 6dc700da..9194550e 100644 --- a/src/Domain/Input/Settings/PresetsInterface.php +++ b/src/Domain/Input/Settings/PresetsInterface.php @@ -20,4 +20,9 @@ public function addMultiple(array $items): self; public function get(string $key, $default = null); public function parse(string $content): string; + + /** + * @return array + */ + public function toArrayByCategory(string $category): array; } diff --git a/src/Domain/Input/Settings/Typography/FontSize.php b/src/Domain/Input/Settings/Typography/FontSize.php index 353680b6..b3968be4 100644 --- a/src/Domain/Input/Settings/Typography/FontSize.php +++ b/src/Domain/Input/Settings/Typography/FontSize.php @@ -33,6 +33,9 @@ public function __construct(string $slug, string $name, string $size, ?Fluid $fl $this->fluid = $fluid; } + /** + * @return array{slug: string, name: string, size: string, fluid?: Fluid} + */ public function toArray(): array { return \array_filter([ diff --git a/src/Domain/Input/Settings/Typography/Utilities/FontFace.php b/src/Domain/Input/Settings/Typography/Utilities/FontFace.php index cda39d0c..fca02c70 100644 --- a/src/Domain/Input/Settings/Typography/Utilities/FontFace.php +++ b/src/Domain/Input/Settings/Typography/Utilities/FontFace.php @@ -14,8 +14,14 @@ class FontFace private string $fontStretch; + /** + * @var string[] + */ private array $src; + /** + * @param string[] $src + */ public function __construct( string $fontFamily, string $fontWeight, @@ -31,7 +37,7 @@ public function __construct( } /** - * @return array{fontFamily: string, fontWeight: string, fontStyle: string, fontStretch: string, src: mixed[]} + * @return array{fontFamily: string, fontWeight: string, fontStyle: string, fontStretch: string, src: string[]} */ public function toArray(): array { diff --git a/src/Domain/Input/Styles/CommonTrait.php b/src/Domain/Input/Styles/CommonTrait.php index 46975302..817258b5 100644 --- a/src/Domain/Input/Styles/CommonTrait.php +++ b/src/Domain/Input/Styles/CommonTrait.php @@ -66,17 +66,21 @@ public function property(string $property, string $value): self */ private function setProperty(string $key, string $value): self { - /** - * @var PresetInterface|mixed $value - */ $value = $this->presets->get($value, $value); if ($value instanceof PresetInterface) { $value = $value->var(); } + if (!\is_scalar($value) && !$value instanceof \Stringable) { + throw new \RuntimeException(\sprintf( + 'Expected style value to be stringable, got %s.', + \get_debug_type($value) + )); + } + /** - * This prevents to return a string with the placeholder like this: + * This prevents returning a string with the placeholder like this: * {{color.base}} * instead we want to return the value of the placeholder like this: * var(--wp--preset--color--base) @@ -102,6 +106,9 @@ public function toArray(): array return $result; } + /** + * @return array + */ public function jsonSerialize(): array { return $this->toArray(); diff --git a/src/Domain/Input/Styles/Css.php b/src/Domain/Input/Styles/Css.php index 1e02f258..72b53f4d 100644 --- a/src/Domain/Input/Styles/Css.php +++ b/src/Domain/Input/Styles/Css.php @@ -157,7 +157,7 @@ private function duplicateRulesForSelectorList(string $css): string $pattern = '/\{(.*)}/s'; \preg_match($pattern, $css, $matches); - if (!isset($matches[1])) { + if (!isset($matches[0], $matches[1])) { return $css; } diff --git a/src/Domain/Input/Styles/Spacing.php b/src/Domain/Input/Styles/Spacing.php index 4f95aa16..2711cbbb 100644 --- a/src/Domain/Input/Styles/Spacing.php +++ b/src/Domain/Input/Styles/Spacing.php @@ -57,6 +57,9 @@ public function left(string $value): self * Three values => 10px auto 0px => 10px auto 0px auto * Four values => 1px 2px 3px 4px => 1px 2px 3px 4px */ + /** + * @param string[] $values + */ public function shorthand(array $values): self { switch (\count($values)) { diff --git a/src/Infrastructure/Filesystem/DataFromJsonTrait.php b/src/Infrastructure/Filesystem/DataFromJsonTrait.php index d3ad55dd..70e76dc1 100644 --- a/src/Infrastructure/Filesystem/DataFromJsonTrait.php +++ b/src/Infrastructure/Filesystem/DataFromJsonTrait.php @@ -6,6 +6,9 @@ trait DataFromJsonTrait { + /** + * @return array + */ private function associativeFromPath(string $path): array { return (array)$this->fromPath($path, true); diff --git a/src/Infrastructure/Filesystem/FileWriter.php b/src/Infrastructure/Filesystem/FileWriter.php index c076d937..cf795e13 100644 --- a/src/Infrastructure/Filesystem/FileWriter.php +++ b/src/Infrastructure/Filesystem/FileWriter.php @@ -9,6 +9,7 @@ interface FileWriter { /** + * @param ConfigInterface $data * @throws \Exception */ public function write(ConfigInterface $data): void; diff --git a/src/Infrastructure/Filesystem/FilesFinder.php b/src/Infrastructure/Filesystem/FilesFinder.php index 064f7b31..f51c0e67 100644 --- a/src/Infrastructure/Filesystem/FilesFinder.php +++ b/src/Infrastructure/Filesystem/FilesFinder.php @@ -68,7 +68,7 @@ public function find( public function resolveJsonFile(\SplFileInfo $file): string { $fileName = $this->extractFileName($file); - $themeRoot = \getcwd(); + $themeRoot = (string)\getcwd(); $stylesFolder = ''; if ($fileName !== self::ROOT_FILE_NAME) { $stylesFolder = self::STYLES_FOLDER; @@ -84,6 +84,10 @@ public function resolveJsonFile(\SplFileInfo $file): string } $styleCssContent = \file_get_contents($styleCss); + if ($styleCssContent === false) { + throw new \RuntimeException('Unable to read the style.css file'); + } + if (\strpos($styleCssContent, 'Theme Name:') === false) { throw new \RuntimeException('The style.css file is not a valid WordPress theme'); } diff --git a/src/Infrastructure/Filesystem/JsonFileWriter.php b/src/Infrastructure/Filesystem/JsonFileWriter.php index 90d60381..a4ba15a0 100644 --- a/src/Infrastructure/Filesystem/JsonFileWriter.php +++ b/src/Infrastructure/Filesystem/JsonFileWriter.php @@ -20,6 +20,7 @@ public function __construct(string $path) } /** + * @param ConfigInterface $data * @throws \Exception */ public function write(ConfigInterface $data): void diff --git a/src/Infrastructure/Filesystem/Path.php b/src/Infrastructure/Filesystem/Path.php deleted file mode 100644 index ae59afb8..00000000 --- a/src/Infrastructure/Filesystem/Path.php +++ /dev/null @@ -1,13 +0,0 @@ -path = $path; } + /** + * @param ConfigInterface $data + */ public function write(ConfigInterface $data): void { if (\count($data) === 0) { @@ -35,7 +38,7 @@ public function write(ConfigInterface $data): void } /** - * @param ConfigInterface $data + * @param ConfigInterface $data * @return string */ private function generateScssContent(ConfigInterface $data): string diff --git a/src/ModuleApplication.php b/src/ModuleApplication.php index 20a2ff93..f11de8d4 100644 --- a/src/ModuleApplication.php +++ b/src/ModuleApplication.php @@ -17,37 +17,59 @@ use ItalyStrap\ThemeJsonGenerator\Application\Middlewares\SchemaJson; use ItalyStrap\ThemeJsonGenerator\Application\Middlewares\Validate; use ItalyStrap\ThemeJsonGenerator\Infrastructure\Handler\ConsoleHandler; +use ItalyStrap\Pipeline\MiddlewareInterface; use Psr\Container\ContainerInterface; class ModuleApplication implements ModuleInterface { + /** + * @return array> + */ public function __invoke(): array { return [ AurynConfig::FACTORIES => [ - InitCommand::class => static function (ContainerInterface $container): InitCommand { + InitCommand::class => function (ContainerInterface $container): InitCommand { return new InitCommand(new ConsoleHandler( - $container->get(Init::class) + $this->middleware($container, Init::class) )); }, - DumpCommand::class => static function (ContainerInterface $container): DumpCommand { + DumpCommand::class => function (ContainerInterface $container): DumpCommand { return new DumpCommand(new ConsoleHandler( - $container->get(Dump::class), + $this->middleware($container, Dump::class), )); }, - ValidateCommand::class => static function (ContainerInterface $container): ValidateCommand { + ValidateCommand::class => function (ContainerInterface $container): ValidateCommand { return new ValidateCommand(new ConsoleHandler( new DeleteSchemaJson(), new SchemaJson(), - $container->get(Validate::class) + $this->middleware($container, Validate::class) )); }, - InfoCommand::class => static function (ContainerInterface $container): InfoCommand { + InfoCommand::class => function (ContainerInterface $container): InfoCommand { return new InfoCommand(new ConsoleHandler( - $container->get(Info::class) + $this->middleware($container, Info::class) )); }, ], ]; } + + /** + * @param class-string $id + */ + private function middleware(ContainerInterface $container, string $id): MiddlewareInterface + { + $middleware = $container->get($id); + if (!$middleware instanceof MiddlewareInterface) { + throw new \RuntimeException(\sprintf( + 'Expected container entry %s to be an instance of %s, got %s.', + $id, + MiddlewareInterface::class, + \get_debug_type($middleware) + )); + } + + return $middleware; + } } diff --git a/src/ModuleInfrastructure.php b/src/ModuleInfrastructure.php index a59b5064..84bd9990 100644 --- a/src/ModuleInfrastructure.php +++ b/src/ModuleInfrastructure.php @@ -12,6 +12,9 @@ class ModuleInfrastructure implements \ItalyStrap\Empress\ModuleInterface { + /** + * @return array + */ public function __invoke(): array { return [ diff --git a/stubs/auryn-injector.stub b/stubs/auryn-injector.stub new file mode 100644 index 00000000..cec6213d --- /dev/null +++ b/stubs/auryn-injector.stub @@ -0,0 +1,18 @@ + $args + * @return ($name is class-string ? T : mixed) + */ + public function make($name, array $args = array()) + { + } +} diff --git a/tests/unit/Application/Middlewares/SchemaJsonTest.php b/tests/unit/Application/Middlewares/SchemaJsonTest.php index ca03a44d..6f02f45c 100644 --- a/tests/unit/Application/Middlewares/SchemaJsonTest.php +++ b/tests/unit/Application/Middlewares/SchemaJsonTest.php @@ -7,6 +7,7 @@ use ItalyStrap\Pipeline\HandlerInterface; use ItalyStrap\Tests\UnitTestCase; use ItalyStrap\ThemeJsonGenerator\Application\Middlewares\SchemaJson; +use ItalyStrap\ThemeJsonGenerator\Application\ValidateMessage; final class SchemaJsonTest extends UnitTestCase { @@ -17,12 +18,8 @@ private function makeInstance(): SchemaJson public function testProcess() { - $message = new class { - public function getSchemaPath(): string - { - return \codecept_output_dir('theme.schema.json'); - } - }; + $schemaPath = \codecept_output_dir('theme.schema.json'); + $message = new ValidateMessage('', $schemaPath); $handler = new class implements HandlerInterface { public function handle(object $message): int @@ -31,15 +28,15 @@ public function handle(object $message): int } }; - if (\file_exists($message->getSchemaPath())) { - $this->tester->deleteFile($message->getSchemaPath()); + if (\file_exists($schemaPath)) { + $this->tester->deleteFile($schemaPath); } - $this->tester->writeToFile($message->getSchemaPath(), '{}'); + $this->tester->writeToFile($schemaPath, '{}'); $actual = $this->makeInstance(); $this->assertIsInt($actual->process($message, $handler)); $this->assertSame(1, $actual->process($message, $handler)); - $this->tester->deleteFile($message->getSchemaPath()); + $this->tester->deleteFile($schemaPath); } }