From 795938cd87daeaf24b44e894de20b74a6d987809 Mon Sep 17 00:00:00 2001 From: Jannik Zschiesche Date: Thu, 26 Jun 2025 18:53:20 +0200 Subject: [PATCH 01/10] Add option to not automatically run `composer update` after Janus finished --- CHANGELOG.md | 6 ++++++ src/Command/InitializeCommand.php | 16 ++++++++++++++-- src/Initializer/LibraryInitializer.php | 13 ++++++++++--- src/Initializer/SymfonyInitializer.php | 13 ++++++++++--- 4 files changed, 40 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 61b9cc9..4dd5d19 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +1.5.2 +===== + +* (improvement) Add option to not automatically run `composer update` after Janus finished. + + 1.5.1 ===== diff --git a/src/Command/InitializeCommand.php b/src/Command/InitializeCommand.php index 4c1b326..4b5e517 100644 --- a/src/Command/InitializeCommand.php +++ b/src/Command/InitializeCommand.php @@ -42,6 +42,11 @@ protected function configure () : void "The project type to initialize", default: null, suggestedValues: self::ALLOWED_TYPES, + ) + ->addOption( + "no-auto-install", + mode: InputOption::VALUE_NONE, + description: "Whether to automatically run composer after changing anything", ); } @@ -73,12 +78,19 @@ protected function execute (InputInterface $input, OutputInterface $output) : in \assert(\is_string($type)); + $io->comment(\sprintf( + "Initializing janus for type %s", + $type, + )); + + $runComposerAutomatically = !$input->getOption("no-auto-install"); + try { return match ($type) { - "symfony" => (new SymfonyInitializer())->initialize($io), - "library" => (new LibraryInitializer())->initialize($io), + "symfony" => (new SymfonyInitializer())->initialize($io, $runComposerAutomatically), + "library" => (new LibraryInitializer())->initialize($io, $runComposerAutomatically), }; } catch (\Throwable $exception) diff --git a/src/Initializer/LibraryInitializer.php b/src/Initializer/LibraryInitializer.php index 1138d8a..d4ef3c7 100644 --- a/src/Initializer/LibraryInitializer.php +++ b/src/Initializer/LibraryInitializer.php @@ -9,7 +9,7 @@ /** * */ - public function initialize (TorrStyle $io) : int + public function initialize (TorrStyle $io, bool $runComposerAutomatically = true) : int { $helper = new InitializeHelper($io); @@ -47,8 +47,15 @@ public function initialize (TorrStyle $io) : int "phpstan" => "vendor-bin/phpstan/vendor/bin/phpstan analyze -c phpstan.neon . --ansi -v", ]); - $io->writeln("• Running composer update..."); - $helper->runComposerInProject(["update"]); + if ($runComposerAutomatically) + { + $io->writeln("• Running composer update..."); + $helper->runComposerInProject(["update"]); + } + else + { + $io->caution("Your project was updated, you should run `composer update`."); + } return 0; } diff --git a/src/Initializer/SymfonyInitializer.php b/src/Initializer/SymfonyInitializer.php index b372b83..8b48c86 100644 --- a/src/Initializer/SymfonyInitializer.php +++ b/src/Initializer/SymfonyInitializer.php @@ -9,7 +9,7 @@ /** * */ - public function initialize (TorrStyle $io) : int + public function initialize (TorrStyle $io, bool $runComposerAutomatically = true) : int { $helper = new InitializeHelper($io); @@ -49,8 +49,15 @@ public function initialize (TorrStyle $io) : int "phpstan" => "vendor-bin/phpstan/vendor/bin/phpstan analyze -c phpstan.neon . --ansi -v", ]); - $io->writeln("• Running composer update..."); - $helper->runComposerInProject(["update"]); + if ($runComposerAutomatically) + { + $io->writeln("• Running composer update..."); + $helper->runComposerInProject(["update"]); + } + else + { + $io->caution("Your project was updated, you should run `composer update`."); + } return 0; } From 051c00376ee31555e2de7ee1ff6d80ff7daa97b8 Mon Sep 17 00:00:00 2001 From: Jannik Zschiesche Date: Thu, 26 Jun 2025 18:53:39 +0200 Subject: [PATCH 02/10] Transform janus to a composer plugin And run it automatically --- composer.json | 7 +- src/Command/InitializeCommand.php | 3 +- src/Composer/JanusPlugin.php | 165 ++++++++++++++++++++++++++++++ 3 files changed, 172 insertions(+), 3 deletions(-) create mode 100644 src/Composer/JanusPlugin.php diff --git a/composer.json b/composer.json index 8edd838..6fcffbc 100644 --- a/composer.json +++ b/composer.json @@ -2,7 +2,7 @@ "name": "21torr/janus", "description": "Code style, encoded as rules for common tools.", "license": "BSD-3-Clause", - "type": "lib", + "type": "composer-plugin", "authors": [ { "name": "21TORR", @@ -12,12 +12,14 @@ "homepage": "https://github.com/21TORR/janus-php", "require": { "php": ">= 8.4", + "composer-plugin-api": "^2.6", "21torr/cli": "^1.2.3", "symfony/console": "^7.3", "symfony/process": "^7.3" }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", + "composer/composer": "^2.8.9", "roave/security-advisories": "dev-latest" }, "autoload": { @@ -40,7 +42,8 @@ "bamarni-bin": { "bin-links": false, "forward-command": true - } + }, + "class": "Janus\\Composer\\JanusPlugin" }, "scripts": { "fix-lint": [ diff --git a/src/Command/InitializeCommand.php b/src/Command/InitializeCommand.php index 4b5e517..95abb7c 100644 --- a/src/Command/InitializeCommand.php +++ b/src/Command/InitializeCommand.php @@ -7,12 +7,13 @@ use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Torr\Cli\Console\Style\TorrStyle; final class InitializeCommand extends Command { - private const array ALLOWED_TYPES = [ + public const array ALLOWED_TYPES = [ "symfony", "library", ]; diff --git a/src/Composer/JanusPlugin.php b/src/Composer/JanusPlugin.php new file mode 100644 index 0000000..6ba8cf8 --- /dev/null +++ b/src/Composer/JanusPlugin.php @@ -0,0 +1,165 @@ +getOperations() as $operation) + { + if ($this->isJanusUpdate($operation)) + { + $this->hadJanusOperation = true; + break; + } + } + } + + /** + * + */ + private function isJanusUpdate (OperationInterface $operation) : bool + { + if ($operation instanceof InstallOperation) + { + return "21torr/janus" === $operation->getPackage()->getName(); + } + + if ($operation instanceof UpdateOperation) + { + return "21torr/janus" === $operation->getTargetPackage()->getName(); + } + + return false; + } + + /** + * Callback after the autoloader was dumped + */ + public function afterAutoloadDump (Event $event) : void + { + if (!$this->hadJanusOperation) + { + return; + } + + $this->hadJanusOperation = false; + + $io = $event->getIO(); + $io->write("\nJanus update detected, running janus update\n"); + + $selected = $io->select( + "What are you currently using?", + InitializeCommand::ALLOWED_TYPES, + "library", + ); + $type = InitializeCommand::ALLOWED_TYPES[$selected] ?? null; + + $vendorDir = $event->getComposer()->getConfig()->get('vendor-dir'); + \assert(\is_string($vendorDir)); + + $success = $this->runJanus($io, $vendorDir, $type); + + if ($success) + { + $io->write("\nJanus installation complete.\n"); + } + else + { + $io->writeError("\nJanus installation failed, please run it manually: `composer exec janus init`\n"); + } + } + + /** + * Runs Janus + */ + private function runJanus ( + IOInterface $io, + string $vendorDir, + ?string $type, + ) : bool + { + $command = [ + "{$vendorDir}/bin/janus", + "init", + ]; + + if (null !== $type) + { + $command[] = $type; + } + + $command[] = "--no-auto-install"; + $command[] = "--ansi"; + + $output = new Process($command); + $output->run( + static function ($type, $buffer) use ($io) : void + { + $io->write($buffer); + }, + ); + + return $output->isSuccessful(); + } + + /** + * @inheritDoc + */ + #[\Override] + public static function getSubscribedEvents () + { + return [ + PackageEvents::POST_PACKAGE_INSTALL => "checkForJanusOperations", + PackageEvents::POST_PACKAGE_UPDATE => "checkForJanusOperations", + ScriptEvents::POST_AUTOLOAD_DUMP => "afterAutoloadDump", + ]; + } +} From 8e26e2771e322bf7108efa0ba3d5d4e4e9a07a96 Mon Sep 17 00:00:00 2001 From: Jannik Zschiesche Date: Thu, 26 Jun 2025 18:56:46 +0200 Subject: [PATCH 03/10] Update changelog --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4dd5d19..c2a6fd7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,8 @@ -1.5.2 +1.6.0 ===== * (improvement) Add option to not automatically run `composer update` after Janus finished. +* (feature) Add composer plugin to run composer automatically. 1.5.1 From 3e3e91c21e71e92ff8f6f0093456e89e815eb85f Mon Sep 17 00:00:00 2001 From: Jannik Zschiesche Date: Thu, 26 Jun 2025 20:47:49 +0200 Subject: [PATCH 04/10] Automatically detect package type in composer plugin --- src/Composer/JanusPlugin.php | 33 ++++++++++++++++++++++++--------- src/Type/PackageType.php | 25 +++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 9 deletions(-) create mode 100644 src/Type/PackageType.php diff --git a/src/Composer/JanusPlugin.php b/src/Composer/JanusPlugin.php index 6ba8cf8..cf3ea89 100644 --- a/src/Composer/JanusPlugin.php +++ b/src/Composer/JanusPlugin.php @@ -14,6 +14,7 @@ use Composer\Script\Event; use Composer\Script\ScriptEvents; use Janus\Command\InitializeCommand; +use Janus\Type\PackageType; use Symfony\Component\Process\Process; /** @@ -95,17 +96,31 @@ public function afterAutoloadDump (Event $event) : void $io = $event->getIO(); $io->write("\nJanus update detected, running janus update\n"); - $selected = $io->select( - "What are you currently using?", - InitializeCommand::ALLOWED_TYPES, - "library", + $packageType = PackageType::tryFromComposerType( + $event->getComposer()->getPackage()->getType() ); - $type = InitializeCommand::ALLOWED_TYPES[$selected] ?? null; + + if (null === $packageType) + { + $selected = $io->select( + "What are you currently using?", + InitializeCommand::ALLOWED_TYPES, + "library", + ); + $packageType = PackageType::tryFromComposerType(InitializeCommand::ALLOWED_TYPES[$selected] ?? null); + } + else + { + $io->write(\sprintf( + "Detected package type %s", + $packageType->value, + )); + } $vendorDir = $event->getComposer()->getConfig()->get('vendor-dir'); \assert(\is_string($vendorDir)); - $success = $this->runJanus($io, $vendorDir, $type); + $success = $this->runJanus($io, $vendorDir, $packageType); if ($success) { @@ -123,7 +138,7 @@ public function afterAutoloadDump (Event $event) : void private function runJanus ( IOInterface $io, string $vendorDir, - ?string $type, + ?PackageType $type, ) : bool { $command = [ @@ -133,7 +148,7 @@ private function runJanus ( if (null !== $type) { - $command[] = $type; + $command[] = $type->value; } $command[] = "--no-auto-install"; @@ -154,7 +169,7 @@ static function ($type, $buffer) use ($io) : void * @inheritDoc */ #[\Override] - public static function getSubscribedEvents () + public static function getSubscribedEvents () : array { return [ PackageEvents::POST_PACKAGE_INSTALL => "checkForJanusOperations", diff --git a/src/Type/PackageType.php b/src/Type/PackageType.php new file mode 100644 index 0000000..1b9aa51 --- /dev/null +++ b/src/Type/PackageType.php @@ -0,0 +1,25 @@ + self::Symfony, + + "symfony-bundle", + "library" => self::Library, + + default => null, + }; + } +} From 7ffe9691c1d72d1dc431aa2b4ab149e8a379f3e4 Mon Sep 17 00:00:00 2001 From: Jannik Zschiesche Date: Thu, 26 Jun 2025 21:42:11 +0200 Subject: [PATCH 05/10] Refactor implementation to automatically detect the package type --- CHANGELOG.md | 5 +- LICENSE | 2 +- src/Command/InitializeCommand.php | 133 ++++++++++---- src/Composer/ComposerJson.php | 102 +++++++++++ src/Composer/JanusPlugin.php | 8 +- src/Exception/ComposerNotFoundException.php | 10 ++ src/Initializer/InitializeHelper.php | 181 -------------------- src/Initializer/LibraryInitializer.php | 62 ------- src/Initializer/SymfonyInitializer.php | 64 ------- src/Package/PackageInitializer.php | 92 ++++++++++ src/Package/PackageType.php | 49 ++++++ src/Project/ProjectHelper.php | 157 +++++++++++++++++ src/Type/PackageType.php | 25 --- vendor-bin/phpstan/composer.json | 14 +- 14 files changed, 527 insertions(+), 377 deletions(-) create mode 100644 src/Composer/ComposerJson.php create mode 100644 src/Exception/ComposerNotFoundException.php delete mode 100644 src/Initializer/InitializeHelper.php delete mode 100644 src/Initializer/LibraryInitializer.php delete mode 100644 src/Initializer/SymfonyInitializer.php create mode 100644 src/Package/PackageInitializer.php create mode 100644 src/Package/PackageType.php create mode 100644 src/Project/ProjectHelper.php delete mode 100644 src/Type/PackageType.php diff --git a/CHANGELOG.md b/CHANGELOG.md index c2a6fd7..1d06c54 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ -1.6.0 +2.0.0 ===== +* (bc) Remove deprecated init commands +* (feature) Automatically detect the package type according to the type in `composer.json`. +* (feature) Write back the package type, if none was set. * (improvement) Add option to not automatically run `composer update` after Janus finished. * (feature) Add composer plugin to run composer automatically. diff --git a/LICENSE b/LICENSE index 59466da..3b72341 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2024 21TORR +Copyright (c) 2025 21TORR Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Command/InitializeCommand.php b/src/Command/InitializeCommand.php index 95abb7c..c003185 100644 --- a/src/Command/InitializeCommand.php +++ b/src/Command/InitializeCommand.php @@ -2,8 +2,12 @@ namespace Janus\Command; -use Janus\Initializer\LibraryInitializer; -use Janus\Initializer\SymfonyInitializer; +use Janus\Composer\ComposerJson; +use Janus\Exception\InvalidCallException; +use Janus\Exception\JanusException; +use Janus\Package\PackageInitializer; +use Janus\Project\ProjectHelper; +use Janus\Package\PackageType; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; @@ -17,10 +21,6 @@ final class InitializeCommand extends Command "symfony", "library", ]; - private const array LEGACY_COMMANDS = [ - "init-symfony", - "init-library", - ]; /** */ @@ -36,13 +36,12 @@ protected function configure () : void { $this ->setDescription("Initializes a given command") - ->setAliases(self::LEGACY_COMMANDS) ->addArgument( "type", InputArgument::OPTIONAL, "The project type to initialize", default: null, - suggestedValues: self::ALLOWED_TYPES, + suggestedValues: PackageType::values(), ) ->addOption( "no-auto-install", @@ -57,48 +56,114 @@ protected function configure () : void protected function execute (InputInterface $input, OutputInterface $output) : int { $io = new TorrStyle($input, $output); + $projectHelper = new ProjectHelper($io); + $packageInitializer = new PackageInitializer(); + $io->title("Janus: Initialize"); + $runComposerAutomatically = !$input->getOption('no-auto-install'); - if (\in_array($input->getFirstArgument(), self::LEGACY_COMMANDS, true)) + try { - $io->caution("You are using a deprecated command. Use the `init` command instead."); - } + $composerJson = $projectHelper->loadComposerJson(); + $packageType = $this->fetchPackageType($io, $composerJson, $input->getArgument("type")); - $type = $input->getArgument("type"); - \assert(null === $type || \is_string($type)); + $io->writeln(\sprintf( + "• Initializing janus for type %s", + $packageType->value, + )); - if (!\in_array($type, self::ALLOWED_TYPES, true)) - { - if (null !== $type) + $io->writeln("• Copying main init files"); + $projectHelper->copyInitFilesIntoProject($packageType); + + $io->writeln("• Updating composer.json"); + + // write basics + match ($packageType) + { + PackageType::Symfony => $packageInitializer->initializeSymfony($composerJson), + PackageType::Library => $packageInitializer->initializeLibrary($composerJson), + }; + + // set project type (only if it is not yet set. We want to keep even unknown values here, so only set it if it is unset) + if (!$composerJson->hasType()) { - $io->error("Used invalid type: {$type}"); + $io->writeln("• Your composer.json has no type set"); + $io->writeln(sprintf( + "• Setting it to the type %s (according to your selection %s)", + $packageType->getComposerType(), + $packageType->value, + )); + + $composerJson->replaceConfig([ + "type" => $packageType->getComposerType(), + ]); } - $type = $io->choice("Please select the type to initialize", self::ALLOWED_TYPES); - } + $projectHelper->writeComposerJson($composerJson); - \assert(\is_string($type)); + if ($runComposerAutomatically) + { + $io->writeln("• Running composer update..."); + $projectHelper->runComposerInProject(["update"]); + } + else + { + $io->caution("Your project was updated, you should run `composer update`."); + } - $io->comment(\sprintf( - "Initializing janus for type %s", - $type, - )); + return self::SUCCESS; + } + catch (JanusException $exception) + { + $io->error($exception->getMessage()); - $runComposerAutomatically = !$input->getOption("no-auto-install"); + return self::FAILURE; + } + } - try + /** + * + */ + private function fetchPackageType ( + TorrStyle $io, + ComposerJson $composerJson, + mixed $typeCliArgument, + ) : PackageType + { + // first try CLI parameter + $packageType = \is_string($typeCliArgument) + ? PackageType::tryFrom($typeCliArgument) + : null; + + if (null !== $packageType) { - return match ($type) - { - "symfony" => (new SymfonyInitializer())->initialize($io, $runComposerAutomatically), - "library" => (new LibraryInitializer())->initialize($io, $runComposerAutomatically), - }; + return $packageType; } - catch (\Throwable $exception) + + // then error out if the user explicitly passed an invalid value + if (null !== $typeCliArgument) { - $io->error("Running janus failed: {$exception->getMessage()}"); + throw new InvalidCallException(\sprintf( + "Invalid type selected: %s", + \is_scalar($typeCliArgument) + ? $typeCliArgument + : get_debug_type($typeCliArgument), + )); + } + + // no CLI parameter passed, so test if we can detect the type from composer.json + $packageType = $composerJson->getType(); - return 2; + if (null !== $packageType) + { + $io->writeln("• Automatically detected type from the package type in your composer.json"); + return $packageType; } + + // could not detect, so just ask for it + $type = $io->choice("Please select the type to initialize", PackageType::values()); + \assert(\is_string($type)); + + return PackageType::from($type); } } diff --git a/src/Composer/ComposerJson.php b/src/Composer/ComposerJson.php new file mode 100644 index 0000000..5826478 --- /dev/null +++ b/src/Composer/ComposerJson.php @@ -0,0 +1,102 @@ + */ + public private(set) array $content, + ) {} + + /** + * Takes a list of scripts to replace and updates the configs. + * + * The $scripts array has a keywords as key, and replaces the line containing that keyword. + * So for example the key "phpunit" would replace the line that contains "phpunit". + * If there are multiple lines matching, all will be replaced. + * If there are no lines matching, the call will just be appended. + * + * @param string $key the scripts key to update + * @param array $scripts the scripts to replace + */ + public function updateScripts (string $key, array $scripts) : void + { + $allExistingScripts = $this->content["scripts"] ?? []; + + if (!\is_array($allExistingScripts)) + { + throw new InvalidSetupException(\sprintf( + "Invalid composer.json: scripts must be an array, %s given", + get_debug_type($allExistingScripts), + )); + } + + $existingScripts = $allExistingScripts[$key] ?? []; + // keep existing scripts + $result = []; + \assert(\is_array($existingScripts)); + + foreach ($existingScripts as $line) + { + \assert(\is_string($line)); + + foreach ($scripts as $replacedKeyword => $newLine) + { + if (str_contains($line, $replacedKeyword)) + { + continue 2; + } + } + + // append the line if no replacement matches + $result[] = $line; + } + + // append all new lines + foreach ($scripts as $newLine) + { + $result[] = $newLine; + } + + $allExistingScripts[$key] = $result; + $this->content["scripts"] = $allExistingScripts; + } + + /** + * Add the given config to the projects composer.json + * + * @param array $config + */ + public function replaceConfig (array $config) : void + { + $this->content = array_replace_recursive( + $this->content, + $config, + ); + } + + /** + * + */ + public function getType () : ?PackageType + { + return PackageType::tryFromComposerType($this->content["type"] ?? null); + } + + /** + * + */ + public function hasType () : bool + { + return array_key_exists("type", $this->content); + } +} diff --git a/src/Composer/JanusPlugin.php b/src/Composer/JanusPlugin.php index cf3ea89..af90717 100644 --- a/src/Composer/JanusPlugin.php +++ b/src/Composer/JanusPlugin.php @@ -14,7 +14,9 @@ use Composer\Script\Event; use Composer\Script\ScriptEvents; use Janus\Command\InitializeCommand; -use Janus\Type\PackageType; +use Janus\Exception\ComposerNotFoundException; +use Janus\Package\PackageType; +use Janus\Project\ProjectHelper; use Symfony\Component\Process\Process; /** @@ -96,8 +98,9 @@ public function afterAutoloadDump (Event $event) : void $io = $event->getIO(); $io->write("\nJanus update detected, running janus update\n"); + // please note, that the detection can fail: composer defaults to "library", if it's not set $packageType = PackageType::tryFromComposerType( - $event->getComposer()->getPackage()->getType() + $event->getComposer()->getPackage()->getType(), ); if (null === $packageType) @@ -132,6 +135,7 @@ public function afterAutoloadDump (Event $event) : void } } + /** * Runs Janus */ diff --git a/src/Exception/ComposerNotFoundException.php b/src/Exception/ComposerNotFoundException.php new file mode 100644 index 0000000..36f24da --- /dev/null +++ b/src/Exception/ComposerNotFoundException.php @@ -0,0 +1,10 @@ +cwd = (string) getcwd(); - } - - /** - * Copies the files from the given init dir to the project dir - */ - public function copyFilesIntoProject (string $directory) : void - { - $sourceDir = self::INIT_DIR . "/{$directory}/."; - - $this->runProcessInProject([ - "cp", - "-a", - $sourceDir, - ".", - ]); - } - - /** - * Add the given config to the projects composer.json - * - * @param array $config - */ - public function addToProjectComposerJson (array $config) : void - { - $jsonContent = array_replace_recursive( - $this->readProjectComposerJson(), - $config, - ); - - $this->writeProjectComposerJson($jsonContent); - } - - /** - * Takes a list of scripts to replace and updates the configs. - * - * The $scripts array has a keywords as key, and replaces the line containing that keyword. - * So for example the key "phpunit" would replace the line that contains "phpunit". - * If there are multiple lines matching, all will be replaced. - * If there are no lines matching, the call will just be appended. - * - * @param string $key the scripts key to update - * @param array $scripts the scripts to replace - */ - public function updateProjectComposerJsonScripts (string $key, array $scripts) : void - { - $jsonContent = $this->readProjectComposerJson(); - \assert(!isset($jsonContent["scripts"]) || \is_array($jsonContent["scripts"])); - - $existingScripts = $jsonContent["scripts"][$key] ?? []; - // keep existing scripts - $result = []; - - foreach ($existingScripts as $line) - { - foreach ($scripts as $replacedKeyword => $newLine) - { - if (str_contains($line, $replacedKeyword)) - { - continue 2; - } - } - - // append the line if no replacement matches - $result[] = $line; - } - - // append all new lines - foreach ($scripts as $newLine) - { - $result[] = $newLine; - } - - $jsonContent["scripts"][$key] = $result; - $this->writeProjectComposerJson($jsonContent); - } - - /** - * Writes the given config to the project composer.json - * - * @param array $config - */ - private function writeProjectComposerJson (array $config) : void - { - $filePath = "{$this->cwd}/composer.json"; - - file_put_contents( - $filePath, - json_encode( - $config, - \JSON_PRETTY_PRINT | \JSON_UNESCAPED_SLASHES | \JSON_THROW_ON_ERROR, - ), - ); - } - - /** - * @return array - */ - private function readProjectComposerJson () : array - { - $filePath = "{$this->cwd}/composer.json"; - - $result = json_decode( - (string) file_get_contents($filePath), - true, - flags: \JSON_THROW_ON_ERROR, - ); - \assert(\is_array($result)); - - return $result; - } - - /** - * Runs a composer command in the project - * - * @param string[] $cmd - */ - public function runComposerInProject (array $cmd) : void - { - $finder = new ExecutableFinder(); - $composer = $finder->find("composer"); - - if (null === $composer) - { - throw new InvalidSetupException("Could not find locally installed composer"); - } - - array_unshift($cmd, $composer); - $cmd[] = "--ansi"; - $this->runProcessInProject($cmd); - } - - /** - * Runs the given command in the project directory - * - * @param string[] $cmd - */ - public function runProcessInProject (array $cmd) : void - { - $this->io->writeln(\sprintf( - "$> Running command %s", - implode(" ", $cmd), - )); - - $process = new Process( - $cmd, - cwd: $this->cwd, - ); - $process->mustRun(); - - $output = trim(\sprintf("%s\n%s", $process->getErrorOutput(), $process->getOutput())); - - if ("" !== $output) - { - $this->io->block( - trim(\sprintf("%s\n%s", $process->getErrorOutput(), $process->getOutput())), - prefix: " │ ", - ); - } - } -} diff --git a/src/Initializer/LibraryInitializer.php b/src/Initializer/LibraryInitializer.php deleted file mode 100644 index d4ef3c7..0000000 --- a/src/Initializer/LibraryInitializer.php +++ /dev/null @@ -1,62 +0,0 @@ -writeln("• Copying config files to the project..."); - $helper->copyFilesIntoProject("library"); - - $io->writeln("• Updating composer.json..."); - $helper->addToProjectComposerJson([ - "config" => [ - "allow-plugins" => [ - "bamarni/composer-bin-plugin" => true, - ], - "sort-packages" => true, - ], - "extra" => [ - "bamarni-bin" => [ - "bin-links" => false, - "forward-command" => true, - ], - ], - "require-dev" => [ - "bamarni/composer-bin-plugin" => "^1.8.2", - "roave/security-advisories" => "dev-latest", - ], - ]); - $helper->updateProjectComposerJsonScripts("fix-lint", [ - "normalize" => "@composer bin c-norm normalize \"$(pwd)/composer.json\" --indent-style tab --indent-size 1 --ansi", - "cs-fixer" => "PHP_CS_FIXER_IGNORE_ENV=1 vendor-bin/cs-fixer/vendor/bin/php-cs-fixer fix --diff --config vendor-bin/cs-fixer/vendor/21torr/php-cs-fixer/.php-cs-fixer.dist.php --no-interaction --ansi", - ]); - $helper->updateProjectComposerJsonScripts("lint", [ - "normalize" => "@composer bin c-norm normalize \"$(pwd)/composer.json\" --indent-style tab --indent-size 1 --dry-run --ansi", - "cs-fixer" => "PHP_CS_FIXER_IGNORE_ENV=1 vendor-bin/cs-fixer/vendor/bin/php-cs-fixer check --diff --config vendor-bin/cs-fixer/vendor/21torr/php-cs-fixer/.php-cs-fixer.dist.php --no-interaction --ansi", - ]); - $helper->updateProjectComposerJsonScripts("test", [ - "phpstan" => "vendor-bin/phpstan/vendor/bin/phpstan analyze -c phpstan.neon . --ansi -v", - ]); - - if ($runComposerAutomatically) - { - $io->writeln("• Running composer update..."); - $helper->runComposerInProject(["update"]); - } - else - { - $io->caution("Your project was updated, you should run `composer update`."); - } - - return 0; - } -} diff --git a/src/Initializer/SymfonyInitializer.php b/src/Initializer/SymfonyInitializer.php deleted file mode 100644 index 8b48c86..0000000 --- a/src/Initializer/SymfonyInitializer.php +++ /dev/null @@ -1,64 +0,0 @@ -writeln("• Copying config files to the project..."); - $helper->copyFilesIntoProject("symfony"); - - $io->writeln("• Updating composer.json..."); - $helper->addToProjectComposerJson([ - "config" => [ - "allow-plugins" => [ - "bamarni/composer-bin-plugin" => true, - ], - "sort-packages" => true, - ], - "extra" => [ - "bamarni-bin" => [ - "bin-links" => false, - "forward-command" => true, - ], - ], - "require-dev" => [ - "bamarni/composer-bin-plugin" => "^1.8.2", - "roave/security-advisories" => "dev-latest", - ], - ]); - $helper->updateProjectComposerJsonScripts("fix-lint", [ - "normalize" => "@composer bin c-norm normalize \"$(pwd)/composer.json\" --indent-style tab --indent-size 1 --ansi", - "cs-fixer" => "PHP_CS_FIXER_IGNORE_ENV=1 vendor-bin/cs-fixer/vendor/bin/php-cs-fixer fix --diff --config vendor-bin/cs-fixer/vendor/21torr/php-cs-fixer/.php-cs-fixer.dist.php --no-interaction --ansi", - ]); - $helper->updateProjectComposerJsonScripts("lint", [ - "lint:yaml" => "bin/console lint:yaml config --parse-tags", - "lint:twig" => "bin/console lint:twig templates", - "normalize" => "@composer bin c-norm normalize \"$(pwd)/composer.json\" --indent-style tab --indent-size 1 --dry-run --ansi", - "cs-fixer" => "PHP_CS_FIXER_IGNORE_ENV=1 vendor-bin/cs-fixer/vendor/bin/php-cs-fixer check --diff --config vendor-bin/cs-fixer/vendor/21torr/php-cs-fixer/.php-cs-fixer.dist.php --no-interaction --ansi", - ]); - $helper->updateProjectComposerJsonScripts("test", [ - "phpstan" => "vendor-bin/phpstan/vendor/bin/phpstan analyze -c phpstan.neon . --ansi -v", - ]); - - if ($runComposerAutomatically) - { - $io->writeln("• Running composer update..."); - $helper->runComposerInProject(["update"]); - } - else - { - $io->caution("Your project was updated, you should run `composer update`."); - } - - return 0; - } -} diff --git a/src/Package/PackageInitializer.php b/src/Package/PackageInitializer.php new file mode 100644 index 0000000..42dad95 --- /dev/null +++ b/src/Package/PackageInitializer.php @@ -0,0 +1,92 @@ +replaceConfig([ + "config" => [ + "allow-plugins" => [ + "21torr/janus" => true, + "bamarni/composer-bin-plugin" => true, + ], + "sort-packages" => true, + ], + "extra" => [ + "bamarni-bin" => [ + "bin-links" => false, + "forward-command" => true, + ], + ], + "require-dev" => [ + "bamarni/composer-bin-plugin" => "^1.8.2", + "roave/security-advisories" => "dev-latest", + ], + ]); + + $composerJson->updateScripts("fix-lint", [ + "normalize" => "@composer bin c-norm normalize \"$(pwd)/composer.json\" --indent-style tab --indent-size 1 --ansi", + "cs-fixer" => "PHP_CS_FIXER_IGNORE_ENV=1 vendor-bin/cs-fixer/vendor/bin/php-cs-fixer fix --diff --config vendor-bin/cs-fixer/vendor/21torr/php-cs-fixer/.php-cs-fixer.dist.php --no-interaction --ansi", + ]); + + $composerJson->updateScripts("lint", [ + "lint:yaml" => "bin/console lint:yaml config --parse-tags", + "lint:twig" => "bin/console lint:twig templates", + "normalize" => "@composer bin c-norm normalize \"$(pwd)/composer.json\" --indent-style tab --indent-size 1 --dry-run --ansi", + "cs-fixer" => "PHP_CS_FIXER_IGNORE_ENV=1 vendor-bin/cs-fixer/vendor/bin/php-cs-fixer check --diff --config vendor-bin/cs-fixer/vendor/21torr/php-cs-fixer/.php-cs-fixer.dist.php --no-interaction --ansi", + ]); + + $composerJson->updateScripts("test", [ + "phpstan" => "vendor-bin/phpstan/vendor/bin/phpstan analyze -c phpstan.neon . --ansi -v", + ]); + } + + /** + * + */ + public function initializeLibrary (ComposerJson $composerJson) : void + { + $composerJson->replaceConfig([ + "config" => [ + "allow-plugins" => [ + "bamarni/composer-bin-plugin" => true, + ], + "sort-packages" => true, + ], + "extra" => [ + "bamarni-bin" => [ + "bin-links" => false, + "forward-command" => true, + ], + ], + "require-dev" => [ + "bamarni/composer-bin-plugin" => "^1.8.2", + "roave/security-advisories" => "dev-latest", + ], + ]); + + $composerJson->updateScripts("fix-lint", [ + "normalize" => "@composer bin c-norm normalize \"$(pwd)/composer.json\" --indent-style tab --indent-size 1 --ansi", + "cs-fixer" => "PHP_CS_FIXER_IGNORE_ENV=1 vendor-bin/cs-fixer/vendor/bin/php-cs-fixer fix --diff --config vendor-bin/cs-fixer/vendor/21torr/php-cs-fixer/.php-cs-fixer.dist.php --no-interaction --ansi", + ]); + + $composerJson->updateScripts("lint", [ + "normalize" => "@composer bin c-norm normalize \"$(pwd)/composer.json\" --indent-style tab --indent-size 1 --dry-run --ansi", + "cs-fixer" => "PHP_CS_FIXER_IGNORE_ENV=1 vendor-bin/cs-fixer/vendor/bin/php-cs-fixer check --diff --config vendor-bin/cs-fixer/vendor/21torr/php-cs-fixer/.php-cs-fixer.dist.php --no-interaction --ansi", + ]); + + $composerJson->updateScripts("test", [ + "phpstan" => "vendor-bin/phpstan/vendor/bin/phpstan analyze -c phpstan.neon . --ansi -v", + ]); + } +} diff --git a/src/Package/PackageType.php b/src/Package/PackageType.php new file mode 100644 index 0000000..afe4b7e --- /dev/null +++ b/src/Package/PackageType.php @@ -0,0 +1,49 @@ + "project", + self::Library => "library", + }; + } + + /** + * @return list + */ + public static function values () : array + { + return array_map( + static fn (self $type) => $type->value, + self::cases(), + ); + } + + /** + * + */ + public static function tryFromComposerType (mixed $type) : ?self + { + return match ($type) + { + "project" => self::Symfony, + + "symfony-bundle", + "library" => self::Library, + + default => null, + }; + } +} diff --git a/src/Project/ProjectHelper.php b/src/Project/ProjectHelper.php new file mode 100644 index 0000000..f945210 --- /dev/null +++ b/src/Project/ProjectHelper.php @@ -0,0 +1,157 @@ +cwd = (string) getcwd(); + } + + /** + * Copies the files from the given init dir to the project dir + */ + public function copyInitFilesIntoProject (PackageType $packageType) : void + { + $sourceDir = self::INIT_DIR . "/{$packageType->value}/."; + + $this->runProcessInProject([ + "cp", + "-a", + $sourceDir, + ".", + ]); + } + + /** + */ + public function loadComposerJson () : ComposerJson + { + $filePath = "{$this->cwd}/composer.json"; + + if (!is_file($filePath) || !is_readable($filePath)) + { + throw new ComposerNotFoundException(\sprintf( + "composer.json not found at '%s'", + $filePath, + )); + } + + try + { + $result = json_decode( + (string) file_get_contents($filePath), + true, + depth: 512, + flags: \JSON_THROW_ON_ERROR, + ); + \assert(\is_array($result)); + + return new ComposerJson($result); + } + catch (\JsonException $exception) + { + throw new ComposerNotFoundException( + \sprintf( + "composer.json at '%s' contains invalid JSON", + $filePath, + ), + previous: $exception, + ); + } + } + + /** + * Writes the given config to the project composer.json + */ + public function writeComposerJson (ComposerJson $composerJson) : void + { + $filePath = "{$this->cwd}/composer.json"; + + try + { + file_put_contents( + $filePath, + json_encode( + $composerJson->content, + \JSON_PRETTY_PRINT | \JSON_UNESCAPED_SLASHES | \JSON_THROW_ON_ERROR, + ), + ); + } + catch (\JsonException $exception) + { + throw new InvalidSetupException( + \sprintf( + "Could not write back composer.json at '%s'", + $filePath, + ), + previous: $exception, + ); + } + } + + /** + * Runs a composer command in the project + * + * @param string[] $cmd + */ + public function runComposerInProject (array $cmd) : void + { + $finder = new ExecutableFinder(); + $composer = $finder->find("composer"); + + if (null === $composer) + { + throw new InvalidSetupException("Could not find locally installed composer"); + } + + array_unshift($cmd, $composer); + $cmd[] = "--ansi"; + $this->runProcessInProject($cmd); + } + + /** + * Runs the given command in the project directory + * + * @param string[] $cmd + */ + public function runProcessInProject (array $cmd) : void + { + $this->io?->writeln(\sprintf( + "$> Running command %s", + implode(" ", $cmd), + )); + + $process = new Process( + $cmd, + cwd: $this->cwd, + ); + $process->mustRun(); + + $output = trim(\sprintf("%s\n%s", $process->getErrorOutput(), $process->getOutput())); + + if ("" !== $output) + { + $this->io?->block( + trim(\sprintf("%s\n%s", $process->getErrorOutput(), $process->getOutput())), + prefix: " │ ", + ); + } + } +} diff --git a/src/Type/PackageType.php b/src/Type/PackageType.php deleted file mode 100644 index 1b9aa51..0000000 --- a/src/Type/PackageType.php +++ /dev/null @@ -1,25 +0,0 @@ - self::Symfony, - - "symfony-bundle", - "library" => self::Library, - - default => null, - }; - } -} diff --git a/vendor-bin/phpstan/composer.json b/vendor-bin/phpstan/composer.json index cf165ff..4eb9387 100644 --- a/vendor-bin/phpstan/composer.json +++ b/vendor-bin/phpstan/composer.json @@ -3,14 +3,14 @@ "php": "^8.3" }, "require-dev": { - "phpstan/extension-installer": "^1.3.1", - "phpstan/phpstan": "^1.11", - "phpstan/phpstan-deprecation-rules": "^1.2", - "phpstan/phpstan-doctrine": "^1.4", - "phpstan/phpstan-phpunit": "^1.4", - "phpstan/phpstan-symfony": "^1.4", + "phpstan/extension-installer": "^1.4.2", + "phpstan/phpstan": "^2.1.11", + "phpstan/phpstan-deprecation-rules": "^2.0.1", + "phpstan/phpstan-doctrine": "^2.0.2", + "phpstan/phpstan-phpunit": "^2.0.6", + "phpstan/phpstan-symfony": "^2.0.4", "roave/security-advisories": "dev-latest", - "staabm/phpstan-todo-by": "^0.1.25" + "staabm/phpstan-todo-by": "^0.2" }, "config": { "sort-packages": true, From c4e577fa101fb158e25cf6e3d413dee17199c001 Mon Sep 17 00:00:00 2001 From: Jannik Zschiesche Date: Thu, 26 Jun 2025 21:47:37 +0200 Subject: [PATCH 06/10] Finalize --- src/Command/InitializeCommand.php | 5 +++-- src/Composer/ComposerJson.php | 2 +- src/Composer/JanusPlugin.php | 3 --- src/Package/PackageType.php | 1 - 4 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/Command/InitializeCommand.php b/src/Command/InitializeCommand.php index c003185..ffe50d5 100644 --- a/src/Command/InitializeCommand.php +++ b/src/Command/InitializeCommand.php @@ -6,8 +6,8 @@ use Janus\Exception\InvalidCallException; use Janus\Exception\JanusException; use Janus\Package\PackageInitializer; -use Janus\Project\ProjectHelper; use Janus\Package\PackageType; +use Janus\Project\ProjectHelper; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; @@ -88,7 +88,7 @@ protected function execute (InputInterface $input, OutputInterface $output) : in if (!$composerJson->hasType()) { $io->writeln("• Your composer.json has no type set"); - $io->writeln(sprintf( + $io->writeln(\sprintf( "• Setting it to the type %s (according to your selection %s)", $packageType->getComposerType(), $packageType->value, @@ -157,6 +157,7 @@ private function fetchPackageType ( if (null !== $packageType) { $io->writeln("• Automatically detected type from the package type in your composer.json"); + return $packageType; } diff --git a/src/Composer/ComposerJson.php b/src/Composer/ComposerJson.php index 5826478..24f76eb 100644 --- a/src/Composer/ComposerJson.php +++ b/src/Composer/ComposerJson.php @@ -97,6 +97,6 @@ public function getType () : ?PackageType */ public function hasType () : bool { - return array_key_exists("type", $this->content); + return \array_key_exists("type", $this->content); } } diff --git a/src/Composer/JanusPlugin.php b/src/Composer/JanusPlugin.php index af90717..a277037 100644 --- a/src/Composer/JanusPlugin.php +++ b/src/Composer/JanusPlugin.php @@ -14,9 +14,7 @@ use Composer\Script\Event; use Composer\Script\ScriptEvents; use Janus\Command\InitializeCommand; -use Janus\Exception\ComposerNotFoundException; use Janus\Package\PackageType; -use Janus\Project\ProjectHelper; use Symfony\Component\Process\Process; /** @@ -135,7 +133,6 @@ public function afterAutoloadDump (Event $event) : void } } - /** * Runs Janus */ diff --git a/src/Package/PackageType.php b/src/Package/PackageType.php index afe4b7e..85c7d0e 100644 --- a/src/Package/PackageType.php +++ b/src/Package/PackageType.php @@ -7,7 +7,6 @@ enum PackageType : string case Symfony = "symfony"; case Library = "library"; - /** * */ From 449b144eaaad098f449142aaa0aadcde1a7c618d Mon Sep 17 00:00:00 2001 From: Jannik Zschiesche Date: Mon, 30 Jun 2025 10:41:52 +0200 Subject: [PATCH 07/10] Improve output when copying files --- src/Project/ProjectHelper.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Project/ProjectHelper.php b/src/Project/ProjectHelper.php index f945210..4ef79d0 100644 --- a/src/Project/ProjectHelper.php +++ b/src/Project/ProjectHelper.php @@ -12,7 +12,7 @@ final readonly class ProjectHelper { - private const string INIT_DIR = __DIR__ . "/../../_init"; + private string $initDir; private string $cwd; /** @@ -21,6 +21,7 @@ public function __construct ( private ?TorrStyle $io = null, ) { + $this->initDir = dirname(__DIR__, 2) . "/_init"; $this->cwd = (string) getcwd(); } @@ -29,7 +30,7 @@ public function __construct ( */ public function copyInitFilesIntoProject (PackageType $packageType) : void { - $sourceDir = self::INIT_DIR . "/{$packageType->value}/."; + $sourceDir = "{$this->initDir}/{$packageType->value}/."; $this->runProcessInProject([ "cp", From 29342c3e9b4ddfd7d78a9c056c04d55d2fffdf0e Mon Sep 17 00:00:00 2001 From: Jannik Zschiesche Date: Mon, 30 Jun 2025 10:43:25 +0200 Subject: [PATCH 08/10] Rename helper and add logic to detect janus path --- src/Command/InitializeCommand.php | 4 ++-- src/Composer/JanusPlugin.php | 17 ++++++++++++++++- .../PackageManager.php} | 4 ++-- 3 files changed, 20 insertions(+), 5 deletions(-) rename src/{Project/ProjectHelper.php => Package/PackageManager.php} (98%) diff --git a/src/Command/InitializeCommand.php b/src/Command/InitializeCommand.php index ffe50d5..5574ce4 100644 --- a/src/Command/InitializeCommand.php +++ b/src/Command/InitializeCommand.php @@ -7,7 +7,7 @@ use Janus\Exception\JanusException; use Janus\Package\PackageInitializer; use Janus\Package\PackageType; -use Janus\Project\ProjectHelper; +use Janus\Package\PackageManager; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; @@ -56,7 +56,7 @@ protected function configure () : void protected function execute (InputInterface $input, OutputInterface $output) : int { $io = new TorrStyle($input, $output); - $projectHelper = new ProjectHelper($io); + $projectHelper = new PackageManager($io); $packageInitializer = new PackageInitializer(); $io->title("Janus: Initialize"); diff --git a/src/Composer/JanusPlugin.php b/src/Composer/JanusPlugin.php index a277037..e08241f 100644 --- a/src/Composer/JanusPlugin.php +++ b/src/Composer/JanusPlugin.php @@ -143,7 +143,7 @@ private function runJanus ( ) : bool { $command = [ - "{$vendorDir}/bin/janus", + $this->findJanusExecutable($vendorDir), "init", ]; @@ -166,6 +166,21 @@ static function ($type, $buffer) use ($io) : void return $output->isSuccessful(); } + /** + * Finds the path to the janus executable + */ + private function findJanusExecutable (string $vendorDir) : string + { + // first check if it's installed in the project via composer + if (is_dir("{$vendorDir}/bin/janus")) + { + return "{$vendorDir}/bin/janus"; + } + + // otherwise just fetch the executable from the library and run it + return dirname(__DIR__, 2) . "/bin/janus"; + } + /** * @inheritDoc */ diff --git a/src/Project/ProjectHelper.php b/src/Package/PackageManager.php similarity index 98% rename from src/Project/ProjectHelper.php rename to src/Package/PackageManager.php index 4ef79d0..c0b2063 100644 --- a/src/Project/ProjectHelper.php +++ b/src/Package/PackageManager.php @@ -1,6 +1,6 @@ Date: Mon, 30 Jun 2025 10:43:44 +0200 Subject: [PATCH 09/10] CS --- src/Command/InitializeCommand.php | 2 +- src/Composer/JanusPlugin.php | 2 +- src/Package/PackageManager.php | 3 +-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Command/InitializeCommand.php b/src/Command/InitializeCommand.php index 5574ce4..caf0973 100644 --- a/src/Command/InitializeCommand.php +++ b/src/Command/InitializeCommand.php @@ -6,8 +6,8 @@ use Janus\Exception\InvalidCallException; use Janus\Exception\JanusException; use Janus\Package\PackageInitializer; -use Janus\Package\PackageType; use Janus\Package\PackageManager; +use Janus\Package\PackageType; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; diff --git a/src/Composer/JanusPlugin.php b/src/Composer/JanusPlugin.php index e08241f..f79d0ce 100644 --- a/src/Composer/JanusPlugin.php +++ b/src/Composer/JanusPlugin.php @@ -178,7 +178,7 @@ private function findJanusExecutable (string $vendorDir) : string } // otherwise just fetch the executable from the library and run it - return dirname(__DIR__, 2) . "/bin/janus"; + return \dirname(__DIR__, 2) . "/bin/janus"; } /** diff --git a/src/Package/PackageManager.php b/src/Package/PackageManager.php index c0b2063..fce92ff 100644 --- a/src/Package/PackageManager.php +++ b/src/Package/PackageManager.php @@ -5,7 +5,6 @@ use Janus\Composer\ComposerJson; use Janus\Exception\ComposerNotFoundException; use Janus\Exception\InvalidSetupException; -use Janus\Package\PackageType; use Symfony\Component\Process\ExecutableFinder; use Symfony\Component\Process\Process; use Torr\Cli\Console\Style\TorrStyle; @@ -21,7 +20,7 @@ public function __construct ( private ?TorrStyle $io = null, ) { - $this->initDir = dirname(__DIR__, 2) . "/_init"; + $this->initDir = \dirname(__DIR__, 2) . "/_init"; $this->cwd = (string) getcwd(); } From 57d9e06f832008cef3427313e3ed88070b38479a Mon Sep 17 00:00:00 2001 From: Jannik Zschiesche Date: Tue, 1 Jul 2025 11:51:26 +0200 Subject: [PATCH 10/10] Fix --- CHANGELOG.md | 1 + phpstan/symfony.neon | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1d06c54..ee7700e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ * (feature) Write back the package type, if none was set. * (improvement) Add option to not automatically run `composer update` after Janus finished. * (feature) Add composer plugin to run composer automatically. +* (bug) Update config to fix bug in PHPStan config reader. 1.5.1 diff --git a/phpstan/symfony.neon b/phpstan/symfony.neon index a53fb25..10330eb 100644 --- a/phpstan/symfony.neon +++ b/phpstan/symfony.neon @@ -15,8 +15,11 @@ parameters: identifier: return.type path: %currentWorkingDirectory%/src/Storyblok/Component/*Story.php + # If you're using PHP config files for Symfony 5.3+, you also need this for auto-loading of `Symfony\Config` scanDirectories: - - %currentWorkingDirectory%/var/cache/dev/Symfony/Config (?) + - %currentWorkingDirectory%/var/cache/dev/Symfony/Config + # If you're using PHP config files (including the ones under packages/*.php) for Symfony 5.3+, + # you need this to load the helper functions (i.e. service(), env()): scanFiles: - %currentWorkingDirectory%/vendor/symfony/dependency-injection/Loader/Configurator/ContainerConfigurator.php