From 2e2c9af2f48524546699bf865ca3207da0aa0290 Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Fri, 31 Jul 2026 17:33:16 +0300 Subject: [PATCH 1/6] Cleanup GitHub workflows + Add PHP CS Fixer --- .github/workflows/build.yml | 42 ++--- .github/workflows/rector-cs.yml | 27 +++ .github/workflows/rector.yml | 24 --- .github/workflows/zizmor.yml | 20 +-- .php-cs-fixer.dist.php | 25 +++ .styleci.yml | 85 --------- composer.json | 10 +- rector.php | 10 +- runtime/.gitignore | 2 + src/App/Command/AddChangelogCommand.php | 14 +- .../ComposerFixDependenciesCommand.php | 10 +- src/App/Command/Composer/UpdateCommand.php | 10 +- src/App/Command/DisableCommand.php | 7 +- src/App/Command/EnableCommand.php | 6 +- src/App/Command/ExecCommand.php | 4 +- src/App/Command/Git/CheckoutCommand.php | 4 +- src/App/Command/Git/CommitCommand.php | 2 +- src/App/Command/Git/PullCommand.php | 2 +- src/App/Command/Git/PushCommand.php | 2 +- src/App/Command/Git/RequestPullCommand.php | 2 +- src/App/Command/Git/StatusCommand.php | 4 +- src/App/Command/Github/BuildStatusCommand.php | 4 +- .../Github/ForksRepositoriesCommand.php | 5 +- .../SyncUpstreamRepositoriesCommand.php | 10 +- src/App/Command/IdeCommand.php | 2 + src/App/Command/InstallCommand.php | 6 +- src/App/Command/ListCommand.php | 5 +- src/App/Command/Release/MakeCommand.php | 15 +- src/App/Command/Release/MissingCommand.php | 105 +++++------ .../Command/Release/ReleaseDescription.php | 2 +- src/App/Command/Release/ReleaseNews.php | 2 +- src/App/Command/Release/WhatCommand.php | 105 +++++------ .../ReplicateComposerConfigCommand.php | 3 +- .../Replicate/ReplicateCopyFileCommand.php | 7 +- .../Replicate/ReplicateFilesCommand.php | 130 +++++++------- src/App/Command/Stats/ContributorsCommand.php | 81 +++++---- src/App/Command/SwitchCommand.php | 9 +- src/App/Command/TestCommand.php | 2 +- src/App/Command/UpdateCommand.php | 10 +- src/App/Component/Console/OutputManager.php | 6 +- src/App/Component/Console/PackageCommand.php | 165 +++++++++--------- src/App/Component/Console/YiiDevToolStyle.php | 33 ++-- src/App/Component/Git/GitBranches.php | 8 +- src/App/Component/Git/GitException.php | 4 +- src/App/Component/Git/GitTags.php | 8 +- src/App/Component/Git/GitWorkingCopy.php | 31 ++-- src/App/Component/GitHubTokenAware.php | 3 +- src/App/Component/Package/Package.php | 37 ++-- src/App/Component/Package/PackageError.php | 4 +- .../Component/Package/PackageErrorList.php | 7 +- src/App/Component/Package/PackageList.php | 4 +- src/App/Component/Package/ReplicationSet.php | 8 +- src/App/Component/PhpStorm/Folders.php | 11 +- src/App/PackageService.php | 14 +- src/App/YiiDevToolApplication.php | 12 +- src/Infrastructure/Changelog.php | 16 +- src/Infrastructure/CodeUsage/CodeUsage.php | 4 + .../CodeUsage/NamespaceUsageFinder.php | 20 ++- .../NamespaceUsageFinderNameResolver.php | 2 +- .../Composer/ComposerInstallation.php | 2 + .../Composer/ComposerPackage.php | 6 +- .../Composer/ComposerPackageUsageAnalyzer.php | 2 + .../Composer/Config/ComposerConfig.php | 9 +- .../ComposerConfigDependenciesModifier.php | 14 +- .../Composer/Config/ComposerConfigMerger.php | 4 + .../Dependency/ComposerConfigDependency.php | 4 +- .../ComposerConfigDependencyList.php | 4 + src/Infrastructure/Version.php | 11 +- .../Release/ReleaseDescriptionTest.php | 20 +-- tests/App/Command/Release/ReleaseNewsTest.php | 4 +- tests/App/Command/Release/WhatCommandTest.php | 11 +- .../Component/Console/ProcessOutputTest.php | 4 +- .../CodeUsage/NamespaceUsageFinderTest.php | 26 +-- 73 files changed, 687 insertions(+), 646 deletions(-) create mode 100644 .github/workflows/rector-cs.yml delete mode 100644 .github/workflows/rector.yml create mode 100644 .php-cs-fixer.dist.php delete mode 100644 .styleci.yml create mode 100644 runtime/.gitignore diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5cc457d6..7d3bdb60 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,30 +1,24 @@ -permissions: - contents: read +name: build on: pull_request: - paths-ignore: - - 'docs/**' - - 'README.md' - - 'CHANGELOG.md' - - '.gitignore' - - '.gitattributes' - - 'infection.json.dist' - - 'psalm.xml' - + paths: &paths + - 'src/**' + - 'config/**' + - 'tests/**' + - 'phpunit.xml.dist' + - 'composer.json' + - '.github/workflows/build.yml' push: - branches: - - master - paths-ignore: - - 'docs/**' - - 'README.md' - - 'CHANGELOG.md' - - '.gitignore' - - '.gitattributes' - - 'infection.json.dist' - - 'psalm.xml' + branches: ['master'] + paths: *paths -name: build +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true jobs: phpunit: @@ -33,5 +27,7 @@ jobs: os: >- ['ubuntu-latest'] php: >- - ['8.0'] + ['8.0', '8.1', '8.2', '8.3', '8.4', '8.5'] composer-command: composer update --prefer-dist --no-interaction --no-progress --optimize-autoloader --ansi --no-security-blocking + secrets: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} diff --git a/.github/workflows/rector-cs.yml b/.github/workflows/rector-cs.yml new file mode 100644 index 00000000..29d8f1c9 --- /dev/null +++ b/.github/workflows/rector-cs.yml @@ -0,0 +1,27 @@ +name: Rector + PHP CS Fixer + +on: + pull_request: + paths: + - 'src/**' + - 'config/**' + - 'tests/**' + - 'rector.php' + - '.php-cs-fixer.dist.php' + - 'composer.json' + - '.github/workflows/rector-cs.yml' + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + rector-cs: + permissions: + contents: write # Required to commit formatting fixes back to the PR + uses: yiisoft/actions/.github/workflows/rector-cs.yml@master + with: + php: '8.0' diff --git a/.github/workflows/rector.yml b/.github/workflows/rector.yml deleted file mode 100644 index a3a85db8..00000000 --- a/.github/workflows/rector.yml +++ /dev/null @@ -1,24 +0,0 @@ -permissions: - contents: read - -on: - pull_request: - paths-ignore: - - 'docs/**' - - 'README.md' - - 'CHANGELOG.md' - - '.gitignore' - - '.gitattributes' - - 'infection.json.dist' - - 'psalm.xml' - -name: rector - -jobs: - rector: - uses: yiisoft/actions/.github/workflows/rector.yml@master - with: - os: >- - ['ubuntu-latest'] - php: >- - ['8.3'] diff --git a/.github/workflows/zizmor.yml b/.github/workflows/zizmor.yml index 430255de..6ff2a77d 100644 --- a/.github/workflows/zizmor.yml +++ b/.github/workflows/zizmor.yml @@ -1,21 +1,21 @@ name: GitHub Actions Security Analysis with zizmor 🌈 on: - push: - branches: - - master - - main - paths: - - '.github/**.yml' - - '.github/**.yaml' pull_request: - paths: + paths: &paths - '.github/**.yml' - '.github/**.yaml' + push: + branches: ['master'] + paths: *paths permissions: - actions: read # Required by zizmor when reading workflow metadata through the API. - contents: read # Required to read workflow files. + actions: read # Required by zizmor when reading workflow metadata through the API + contents: read # Required to read workflow files + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true jobs: zizmor: diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php new file mode 100644 index 00000000..d1c2e6b8 --- /dev/null +++ b/.php-cs-fixer.dist.php @@ -0,0 +1,25 @@ +in([ + __DIR__ . '/src', + __DIR__ . '/tests', + __DIR__ . '/config', + ]) + ->exclude('Infrastructure/CodeUsage/Fixture'); + +return ConfigBuilder::build() + ->setCacheFile(__DIR__ . '/runtime/.php-cs-fixer.cache') + ->setRiskyAllowed(true) + ->setParallelConfig(ParallelConfigFactory::detect()) + ->setRules([ + '@Yiisoft/Core' => true, + '@Yiisoft/Core:risky' => true, + ]) + ->setFinder($finder); diff --git a/.styleci.yml b/.styleci.yml deleted file mode 100644 index 1ab379b4..00000000 --- a/.styleci.yml +++ /dev/null @@ -1,85 +0,0 @@ -preset: psr12 -risky: true - -version: 8.1 - -finder: - exclude: - - docs - - vendor - -enabled: - - alpha_ordered_traits - - array_indentation - - array_push - - combine_consecutive_issets - - combine_consecutive_unsets - - combine_nested_dirname - - declare_strict_types - - dir_constant - - fully_qualified_strict_types - - function_to_constant - - hash_to_slash_comment - - is_null - - logical_operators - - magic_constant_casing - - magic_method_casing - - method_separation - - modernize_types_casting - - native_function_casing - - native_function_type_declaration_casing - - no_alias_functions - - no_empty_comment - - no_empty_phpdoc - - no_empty_statement - - no_extra_block_blank_lines - - no_short_bool_cast - - no_superfluous_elseif - - no_unneeded_control_parentheses - - no_unneeded_curly_braces - - no_unneeded_final_method - - no_unset_cast - - no_unused_imports - - no_unused_lambda_imports - - no_useless_else - - no_useless_return - - normalize_index_brace - - php_unit_dedicate_assert - - php_unit_dedicate_assert_internal_type - - php_unit_expectation - - php_unit_mock - - php_unit_mock_short_will_return - - php_unit_namespaced - - php_unit_no_expectation_annotation - - phpdoc_no_empty_return - - phpdoc_no_useless_inheritdoc - - phpdoc_order - - phpdoc_property - - phpdoc_scalar - - phpdoc_singular_inheritdoc - - phpdoc_trim - - phpdoc_trim_consecutive_blank_line_separation - - phpdoc_type_to_var - - phpdoc_types - - phpdoc_types_order - - print_to_echo - - regular_callable_call - - return_assignment - - self_accessor - - self_static_accessor - - set_type_to_cast - - short_array_syntax - - short_list_syntax - - simplified_if_return - - single_quote - - standardize_not_equals - - ternary_to_null_coalescing - - trailing_comma_in_multiline_array - - unalign_double_arrow - - unalign_equals - - empty_loop_body_braces - - integer_literal_case - - union_type_without_spaces - -disabled: - - function_declaration diff --git a/composer.json b/composer.json index 06cd03e2..c7dc0d22 100644 --- a/composer.json +++ b/composer.json @@ -46,7 +46,10 @@ }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", - "phpunit/phpunit": "^9.6.29" + "friendsofphp/php-cs-fixer": "^3.95", + "phpunit/phpunit": "^9.6.29", + "rector/rector": "^2.5", + "yiisoft/code-style": "^1.1" }, "autoload": { "psr-4": { @@ -58,6 +61,11 @@ "Yiisoft\\YiiDevTool\\Test\\": "tests" } }, + "scripts": { + "cs-fix": "php-cs-fixer fix", + "rector": "rector", + "test": "phpunit" + }, "extra": { "bamarni-bin": { "bin-links": true, diff --git a/rector.php b/rector.php index c2226bf1..5e772354 100644 --- a/rector.php +++ b/rector.php @@ -2,19 +2,19 @@ declare(strict_types=1); -use Rector\CodeQuality\Rector\Class_\InlineConstructorDefaultToPropertyRector; use Rector\Config\RectorConfig; -use Rector\Php74\Rector\Closure\ClosureToArrowFunctionRector; +use Yiisoft\CodeStyle\Rector\SetList; return RectorConfig::configure() ->withPaths([ __DIR__ . '/src', __DIR__ . '/tests', + __DIR__ . '/config', ]) ->withPhpSets(php80: true) - ->withRules([ - InlineConstructorDefaultToPropertyRector::class, + ->withSets([ + SetList::YII_CORE, ]) ->withSkip([ - ClosureToArrowFunctionRector::class, + __DIR__ . '/tests/Infrastructure/CodeUsage/Fixture', ]); diff --git a/runtime/.gitignore b/runtime/.gitignore new file mode 100644 index 00000000..d6b7ef32 --- /dev/null +++ b/runtime/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/src/App/Command/AddChangelogCommand.php b/src/App/Command/AddChangelogCommand.php index 57d8ac45..9b568960 100644 --- a/src/App/Command/AddChangelogCommand.php +++ b/src/App/Command/AddChangelogCommand.php @@ -11,6 +11,12 @@ use Yiisoft\YiiDevTool\App\Component\Package\Package; use Yiisoft\YiiDevTool\Infrastructure\Changelog; use Yiisoft\YiiDevTool\Infrastructure\Version; +use InvalidArgumentException; + +use function in_array; +use function sprintf; + +use const SORT_NATURAL; final class AddChangelogCommand extends PackageCommand { @@ -47,14 +53,14 @@ protected function processPackage(Package $package): void { $io = $this->getIO(); - $loweredTypes = array_map(fn (string $type) => strtolower($type), Changelog::TYPES); + $loweredTypes = array_map(fn(string $type) => strtolower($type), Changelog::TYPES); if (!in_array(strtolower($this->type), $loweredTypes, true)) { $io->error( sprintf( 'The type argument value must be one of the following: %s. "%s" given', implode(', ', Changelog::TYPES), - $this->type - ) + $this->type, + ), ); return; } @@ -89,7 +95,7 @@ protected function processPackage(Package $package): void )); try { $changelog->addEntry($text); - } catch (\InvalidArgumentException $e) { + } catch (InvalidArgumentException $e) { $io->error($e); $this->registerPackageError($package, $e->getMessage(), 'adding an changelog entry'); diff --git a/src/App/Command/Composer/ComposerFixDependenciesCommand.php b/src/App/Command/Composer/ComposerFixDependenciesCommand.php index ad97ccf3..d8e5a8f4 100644 --- a/src/App/Command/Composer/ComposerFixDependenciesCommand.php +++ b/src/App/Command/Composer/ComposerFixDependenciesCommand.php @@ -14,10 +14,11 @@ use Yiisoft\YiiDevTool\Infrastructure\Composer\Config\ComposerConfig; use Yiisoft\YiiDevTool\Infrastructure\Composer\Config\ComposerConfigDependenciesModifier; +use function count; +use function sprintf; + final class ComposerFixDependenciesCommand extends PackageCommand { - private array $skippedPackageIds = []; - private const DEV_PATHS = [ 'tests', 'config/params-test.php', @@ -30,6 +31,7 @@ final class ComposerFixDependenciesCommand extends PackageCommand 'src', 'public/index.php', ]; + private array $skippedPackageIds = []; protected function configure(): void { @@ -98,8 +100,8 @@ protected function processPackage(Package $package): void $dependencyPackages = $composerInstallation->getInstalledDependencyPackages(); - $namespaceUsages = - (new NamespaceUsageFinder()) + $namespaceUsages + = (new NamespaceUsageFinder()) ->addTargetPaths(CodeUsageEnvironment::DEV, self::DEV_PATHS, $composerPackage->getPath()) ->addTargetPaths(CodeUsageEnvironment::PRODUCTION, self::PRODUCTION_PATHS, $composerPackage->getPath()) ->getUsages(); diff --git a/src/App/Command/Composer/UpdateCommand.php b/src/App/Command/Composer/UpdateCommand.php index c1e660a8..1c31cc17 100644 --- a/src/App/Command/Composer/UpdateCommand.php +++ b/src/App/Command/Composer/UpdateCommand.php @@ -13,7 +13,7 @@ #[AsCommand( name: 'composer:update', - description: 'Update composer dependencies in packages' + description: 'Update composer dependencies in packages', )] final class UpdateCommand extends PackageCommand { @@ -32,20 +32,20 @@ protected function configure(): void 'no-plugins', null, InputOption::VALUE_NONE, - 'Use --no-plugins during composer update' + 'Use --no-plugins during composer update', ) ->addOption( 'ignore-platform-reqs', null, InputOption::VALUE_NONE, - 'Use --ignore-platform-reqs during composer update' + 'Use --ignore-platform-reqs during composer update', ) ->addOption( 'no-symlinks', null, InputOption::VALUE_OPTIONAL, 'Do not create symbolic links after process', - false + false, ); parent::configure(); @@ -88,7 +88,7 @@ protected function processPackage(Package $package): void $package, $this->additionalComposerUpdateOptions, $this->getErrorsList(), - $io + $io, ); if (!$io->isVerbose()) { diff --git a/src/App/Command/DisableCommand.php b/src/App/Command/DisableCommand.php index 1817b0d2..9438cae9 100644 --- a/src/App/Command/DisableCommand.php +++ b/src/App/Command/DisableCommand.php @@ -13,9 +13,11 @@ use Yiisoft\VarDumper\VarDumper; use Yiisoft\YiiDevTool\App\Component\Console\PackageCommand; +use function dirname; + #[AsCommand( name: 'disable', - description: 'Disable packages' + description: 'Disable packages', )] final class DisableCommand extends PackageCommand { @@ -28,7 +30,7 @@ protected function configure() Package names separated by commas. For example: rbac,di,demo,db-mysql Array keys from package.php configuration can be specified. If packages are not specified, then command will be applied to all packages. - DESCRIPTION + DESCRIPTION, ); $this->addOption('all', 'a', InputOption::VALUE_NONE, 'Disable all packages'); } @@ -77,7 +79,6 @@ protected function execute(InputInterface $input, OutputInterface $output): int fwrite($handle, 'return ' . $dump . ';'); fclose($handle); - if (empty($alreadyDisabledPackages) && empty($disabledPackages)) { $io->info('Packages not found.'); return Command::SUCCESS; diff --git a/src/App/Command/EnableCommand.php b/src/App/Command/EnableCommand.php index ed38b6a3..d37aae06 100644 --- a/src/App/Command/EnableCommand.php +++ b/src/App/Command/EnableCommand.php @@ -13,9 +13,11 @@ use Yiisoft\VarDumper\VarDumper; use Yiisoft\YiiDevTool\App\Component\Console\PackageCommand; +use function dirname; + #[AsCommand( name: 'enable', - description: 'Enable packages' + description: 'Enable packages', )] final class EnableCommand extends PackageCommand { @@ -28,7 +30,7 @@ protected function configure() Package names separated by commas. For example: rbac,di,demo,db-mysql Array keys from package.php configuration can be specified. If packages are not specified, then command will be applied to all packages. - DESCRIPTION + DESCRIPTION, ); $this->addOption('all', 'a', InputOption::VALUE_NONE, 'Enable all packages'); } diff --git a/src/App/Command/ExecCommand.php b/src/App/Command/ExecCommand.php index 7ded0e4b..cf2c314e 100644 --- a/src/App/Command/ExecCommand.php +++ b/src/App/Command/ExecCommand.php @@ -14,7 +14,7 @@ #[AsCommand( name: 'exec', - description: 'Execute the specified console command in each package' + description: 'Execute the specified console command in each package', )] final class ExecCommand extends PackageCommand { @@ -30,7 +30,7 @@ protected function configure() <<'git commit --message="Feature X" --amend' - DESCRIPTION + DESCRIPTION, ); parent::configure(); diff --git a/src/App/Command/Git/CheckoutCommand.php b/src/App/Command/Git/CheckoutCommand.php index c096f350..2e6a0b87 100644 --- a/src/App/Command/Git/CheckoutCommand.php +++ b/src/App/Command/Git/CheckoutCommand.php @@ -11,9 +11,11 @@ use Yiisoft\YiiDevTool\App\Component\Console\ProcessOutput; use Yiisoft\YiiDevTool\App\Component\Package\Package; +use function in_array; + #[AsCommand( name: 'git:checkout', - description: 'Create a branch if does not exist, checkout a branch if it exists' + description: 'Create a branch if does not exist, checkout a branch if it exists', )] final class CheckoutCommand extends PackageCommand { diff --git a/src/App/Command/Git/CommitCommand.php b/src/App/Command/Git/CommitCommand.php index 72421933..9547ea71 100644 --- a/src/App/Command/Git/CommitCommand.php +++ b/src/App/Command/Git/CommitCommand.php @@ -14,7 +14,7 @@ #[AsCommand( name: 'git:commit', - description: 'Add and commit changes into each package repository' + description: 'Add and commit changes into each package repository', )] final class CommitCommand extends PackageCommand { diff --git a/src/App/Command/Git/PullCommand.php b/src/App/Command/Git/PullCommand.php index 82c04a51..fc824b3a 100644 --- a/src/App/Command/Git/PullCommand.php +++ b/src/App/Command/Git/PullCommand.php @@ -12,7 +12,7 @@ #[AsCommand( name: 'git:pull', - description: 'Pull changes from package repositories' + description: 'Pull changes from package repositories', )] final class PullCommand extends PackageCommand { diff --git a/src/App/Command/Git/PushCommand.php b/src/App/Command/Git/PushCommand.php index 78843556..7117c926 100644 --- a/src/App/Command/Git/PushCommand.php +++ b/src/App/Command/Git/PushCommand.php @@ -12,7 +12,7 @@ #[AsCommand( name: 'git:push', - description: 'Push changes into package repositories' + description: 'Push changes into package repositories', )] final class PushCommand extends PackageCommand { diff --git a/src/App/Command/Git/RequestPullCommand.php b/src/App/Command/Git/RequestPullCommand.php index a4c19572..8e19058b 100644 --- a/src/App/Command/Git/RequestPullCommand.php +++ b/src/App/Command/Git/RequestPullCommand.php @@ -15,7 +15,7 @@ #[AsCommand( name: 'git:pr:create', - description: 'Create a GitHub pull request' + description: 'Create a GitHub pull request', )] final class RequestPullCommand extends PackageCommand { diff --git a/src/App/Command/Git/StatusCommand.php b/src/App/Command/Git/StatusCommand.php index b3e2bcf0..25911134 100644 --- a/src/App/Command/Git/StatusCommand.php +++ b/src/App/Command/Git/StatusCommand.php @@ -9,9 +9,11 @@ use Yiisoft\YiiDevTool\App\Component\Console\PackageCommand; use Yiisoft\YiiDevTool\App\Component\Package\Package; +use const PHP_EOL; + #[AsCommand( name: 'git:status', - description: 'Show git status of packages' + description: 'Show git status of packages', )] final class StatusCommand extends PackageCommand { diff --git a/src/App/Command/Github/BuildStatusCommand.php b/src/App/Command/Github/BuildStatusCommand.php index 02875623..5caf7868 100644 --- a/src/App/Command/Github/BuildStatusCommand.php +++ b/src/App/Command/Github/BuildStatusCommand.php @@ -38,8 +38,6 @@ protected function processPackage(Package $package): void $io = $this->getIO(); $io->preparePackageHeader($package, 'Gettting status for {package} commit ' . $currentCommit); - - $client = new Client(); $client->authenticate($this->getGitHubToken(), null, AuthMethod::ACCESS_TOKEN); @@ -48,7 +46,7 @@ protected function processPackage(Package $package): void $checks = $checksRunsApi->allForReference( username: $package->getVendor(), repository: $package->getId(), - ref: $currentCommit + ref: $currentCommit, ); foreach ($checks['check_runs'] as $check) { diff --git a/src/App/Command/Github/ForksRepositoriesCommand.php b/src/App/Command/Github/ForksRepositoriesCommand.php index c333d58c..01ee218e 100644 --- a/src/App/Command/Github/ForksRepositoriesCommand.php +++ b/src/App/Command/Github/ForksRepositoriesCommand.php @@ -17,6 +17,9 @@ use Yiisoft\YiiDevTool\App\Component\Console\YiiDevToolStyle; use Yiisoft\YiiDevTool\App\Component\GitHubTokenAware; +use const DIRECTORY_SEPARATOR; +use const PHP_EOL; + final class ForksRepositoriesCommand extends Command { use GitHubTokenAware; @@ -71,7 +74,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int "Error when forking a repository $repository: {$e->getMessage()}", 'Check if the nickname of the owner and the name of the repository are correct' . PHP_EOL, ], - true + true, ); } } diff --git a/src/App/Command/Github/SyncUpstreamRepositoriesCommand.php b/src/App/Command/Github/SyncUpstreamRepositoriesCommand.php index 3cdc8378..248a16cf 100644 --- a/src/App/Command/Github/SyncUpstreamRepositoriesCommand.php +++ b/src/App/Command/Github/SyncUpstreamRepositoriesCommand.php @@ -18,7 +18,7 @@ #[AsCommand( name: 'github:sync', - description: 'Sync forks from upstream repositories' + description: 'Sync forks from upstream repositories', )] final class SyncUpstreamRepositoriesCommand extends PackageCommand { @@ -41,7 +41,7 @@ protected function configure() 'b', InputOption::VALUE_REQUIRED, 'Name of the branch to be synchronized', - 'master' + 'master', ); parent::configure(); @@ -59,12 +59,12 @@ protected function processPackage(Package $package): void $this->getIO()->important()->success("Repository successfully synced: {$package->getName()}"); } else { $this->getIO()->error( - $this->errorMessage($package->getName()) + $this->errorMessage($package->getName()), ); } } catch (GithubRuntimeException $e) { $this->getIO()->error( - $this->errorMessage($package->getName(), $e->getMessage()) + $this->errorMessage($package->getName(), $e->getMessage()), ); } } @@ -89,7 +89,7 @@ public function mergeUpstream($username, $repository, $branchName = null) { return $this->post( '/repos/' . rawurlencode($username) . '/' . rawurlencode($repository) . '/merge-upstream', - ['branch' => $branchName ?? 'main'] + ['branch' => $branchName ?? 'main'], ); } }; diff --git a/src/App/Command/IdeCommand.php b/src/App/Command/IdeCommand.php index 31bdf816..14efe412 100644 --- a/src/App/Command/IdeCommand.php +++ b/src/App/Command/IdeCommand.php @@ -10,6 +10,8 @@ use Yiisoft\YiiDevTool\App\Component\PhpStorm\Folders; use Symfony\Component\Console\Input\InputInterface; +use function dirname; + #[AsCommand( name: 'ide', description: 'Adjust PhpStorm configs', diff --git a/src/App/Command/InstallCommand.php b/src/App/Command/InstallCommand.php index 4ed469b8..a0a4fa3e 100644 --- a/src/App/Command/InstallCommand.php +++ b/src/App/Command/InstallCommand.php @@ -14,7 +14,7 @@ #[AsCommand( name: 'install', - description: 'Clone packages repositories and install composer dependencies' + description: 'Clone packages repositories and install composer dependencies', )] final class InstallCommand extends PackageCommand { @@ -33,14 +33,14 @@ protected function configure(): void 'no-plugins', null, InputOption::VALUE_NONE, - 'Use --no-plugins during composer install' + 'Use --no-plugins during composer install', ) ->addOption( 'no-symlinks', null, InputOption::VALUE_OPTIONAL, 'Do not create symbolic links after process', - false + false, ); parent::configure(); diff --git a/src/App/Command/ListCommand.php b/src/App/Command/ListCommand.php index 95630332..a4769b6c 100644 --- a/src/App/Command/ListCommand.php +++ b/src/App/Command/ListCommand.php @@ -8,9 +8,12 @@ use Yiisoft\YiiDevTool\App\Component\Console\PackageCommand; use Yiisoft\YiiDevTool\App\Component\Package\Package; +use function sprintf; +use function strlen; + #[AsCommand( name: 'list', - description: 'List all packages' + description: 'List all packages', )] final class ListCommand extends PackageCommand { diff --git a/src/App/Command/Release/MakeCommand.php b/src/App/Command/Release/MakeCommand.php index 36b838bc..d33d7c2d 100644 --- a/src/App/Command/Release/MakeCommand.php +++ b/src/App/Command/Release/MakeCommand.php @@ -23,14 +23,16 @@ use function is_file; use function sprintf; +use const SORT_NATURAL; + final class MakeCommand extends PackageCommand { use GitHubTokenAware; - private ?string $tag = null; - private const MAIN_BRANCHES = ['master', 'main']; + private ?string $tag = null; + protected function configure() { $this @@ -112,7 +114,6 @@ protected function processPackage(Package $package): void $io->info("Current version is $currentVersion."); } - $versionToRelease = $this->getVersionToRelease($currentVersion); $io->info("Going to release $versionToRelease."); @@ -191,7 +192,7 @@ protected function processPackage(Package $package): void package: $package, composerConfig: $composerConfig, changelog: $changelog, - versionToRelease: $versionToRelease + versionToRelease: $versionToRelease, ); } } @@ -244,7 +245,7 @@ private function releaseOnGithub( string $token, Package $package, Version $previousVersion, - Version $versionToRelease + Version $versionToRelease, ): void { $io = $this->getIO(); $io->info("Creating release on GitHub for $versionToRelease.\n"); @@ -260,7 +261,7 @@ private function releaseOnGithub( $previousVersion, $versionToRelease, $changelog->getReleaseNotes($versionToRelease), - is_file($package->getPath() . '/UPGRADE.md') + is_file($package->getPath() . '/UPGRADE.md'), ); $release->create($package->getVendor(), $package->getId(), [ @@ -284,7 +285,7 @@ private function displayReleaseSummary(Package $package, ComposerConfig $compose $changes = implode( "\n", - (new ReleaseNews())->getChanges($changelog->getReleaseNotes($versionToRelease)) + (new ReleaseNews())->getChanges($changelog->getReleaseNotes($versionToRelease)), ); $text = <<io; } - private function initPackageList(): void - { - $io = $this->getIO(); - - try { - $ownerPackages = require $this->getAppRootDir() . 'owner-packages.php'; - if (!preg_match('/^[a-z0-9][a-z0-9-]*[a-z0-9]$/i', $ownerPackages)) { - $io->error([ - 'The packages owner can only contain the characters [a-z0-9-], and the character \'-\' cannot appear at the beginning or at the end.', - 'See owner-packages.php to set the packages owner.', - ]); - - exit(1); - } - - $this->packageList = new PackageList( - $ownerPackages, - $this->getAppRootDir() . 'packages.php', - $this->getAppRootDir() . 'dev', - ); - } catch (InvalidArgumentException $e) { - $io->error([ - 'Invalid local package configuration packages.local.php', - $e->getMessage(), - 'See packages.local.php.example for configuration examples.', - ]); - - exit(1); - } - } - protected function execute(InputInterface $input, OutputInterface $output) { $this->initPackageList(); @@ -124,6 +98,55 @@ protected function execute(InputInterface $input, OutputInterface $output) return Command::SUCCESS; } + /** + * Use this method to get a root directory of the tool. + * + * Commands and components can be moved as a result of refactoring, + * so you should not rely on their location in the file system. + * + * @return string Path to the root directory of the tool WITH a TRAILING SLASH. + */ + protected function getAppRootDir(): string + { + return rtrim( + $this + ->getApplication() + ->getRootDir(), + DIRECTORY_SEPARATOR, + ) . DIRECTORY_SEPARATOR; + } + + private function initPackageList(): void + { + $io = $this->getIO(); + + try { + $ownerPackages = require $this->getAppRootDir() . 'owner-packages.php'; + if (!preg_match('/^[a-z0-9][a-z0-9-]*[a-z0-9]$/i', $ownerPackages)) { + $io->error([ + 'The packages owner can only contain the characters [a-z0-9-], and the character \'-\' cannot appear at the beginning or at the end.', + 'See owner-packages.php to set the packages owner.', + ]); + + exit(1); + } + + $this->packageList = new PackageList( + $ownerPackages, + $this->getAppRootDir() . 'packages.php', + $this->getAppRootDir() . 'dev', + ); + } catch (InvalidArgumentException $e) { + $io->error([ + 'Invalid local package configuration packages.local.php', + $e->getMessage(), + 'See packages.local.php.example for configuration examples.', + ]); + + exit(1); + } + } + private function hasRelease(Package $package): bool { $gitWorkingCopy = $package->getGitWorkingCopy(); @@ -143,22 +166,4 @@ private function getPackageList(): PackageList { return $this->packageList; } - - /** - * Use this method to get a root directory of the tool. - * - * Commands and components can be moved as a result of refactoring, - * so you should not rely on their location in the file system. - * - * @return string Path to the root directory of the tool WITH a TRAILING SLASH. - */ - protected function getAppRootDir(): string - { - return rtrim( - $this - ->getApplication() - ->getRootDir(), - DIRECTORY_SEPARATOR - ) . DIRECTORY_SEPARATOR; - } } diff --git a/src/App/Command/Release/ReleaseDescription.php b/src/App/Command/Release/ReleaseDescription.php index f2724867..336dd687 100644 --- a/src/App/Command/Release/ReleaseDescription.php +++ b/src/App/Command/Release/ReleaseDescription.php @@ -18,7 +18,7 @@ public function getBody( Version $previousVersion, Version $versionToRelease, array $releaseNotes, - bool $hasUpgradeNotes = false + bool $hasUpgradeNotes = false, ): string { $body = implode("\n", $releaseNotes); diff --git a/src/App/Command/Release/ReleaseNews.php b/src/App/Command/Release/ReleaseNews.php index fe9afd23..4e6dc64a 100644 --- a/src/App/Command/Release/ReleaseNews.php +++ b/src/App/Command/Release/ReleaseNews.php @@ -27,7 +27,7 @@ public function getChanges(array $releaseNotes): array $note = preg_replace( '~^- (?:' . implode('|', Changelog::TYPES) . ')(?: #\d+(?:, #\d+)*)?:\s+~', '', - $note + $note, ); $note = preg_replace('~^- \s*~', '', $note); $note = preg_replace('~\s+\(@[^)]*\)$~', '', $note); diff --git a/src/App/Command/Release/WhatCommand.php b/src/App/Command/Release/WhatCommand.php index b0c8d687..c384ed1f 100644 --- a/src/App/Command/Release/WhatCommand.php +++ b/src/App/Command/Release/WhatCommand.php @@ -20,6 +20,9 @@ use Yiisoft\YiiDevTool\Infrastructure\Composer\Config\ComposerConfig; use function array_key_exists; +use function count; + +use const DIRECTORY_SEPARATOR; final class WhatCommand extends Command { @@ -49,39 +52,6 @@ protected function getIO(): OutputManager return $this->io; } - private function initPackageList(): void - { - $io = $this->getIO(); - - try { - $ownerPackages = require $this->getAppRootDir() . 'owner-packages.php'; - if (!preg_match('/^[a-z0-9][a-z0-9-]*[a-z0-9]$/i', $ownerPackages)) { - $io->error([ - 'The packages owner can only contain the characters [a-z0-9-], and the character \'-\' cannot appear at the beginning or at the end.', - 'See owner-packages.php to set the packages owner.', - ]); - - exit(1); - } - - $packagesRootDir = $this->getApplication()->getConfig('packagesRootDir') ?? $this->getAppRootDir() . 'dev'; - - $this->packageList = new PackageList( - $ownerPackages, - $this->getAppRootDir() . 'packages.php', - $packagesRootDir, - ); - } catch (InvalidArgumentException $e) { - $io->error([ - 'Invalid local package configuration packages.local.php', - $e->getMessage(), - 'See packages.local.php.example for configuration examples.', - ]); - - exit(1); - } - } - protected function execute(InputInterface $input, OutputInterface $output) { $this->initPackageList(); @@ -141,7 +111,7 @@ protected function execute(InputInterface $input, OutputInterface $output) uasort( $packagesWithoutRelease, - static fn ($a, $b) => [$a['dependencies'], -$a['dependents']] <=> [$b['dependencies'], -$b['dependents']] + static fn($a, $b) => [$a['dependencies'], -$a['dependents']] <=> [$b['dependencies'], -$b['dependents']], ); $successStyle = new TableCellStyle(['fg' => 'green']); @@ -199,12 +169,60 @@ protected function execute(InputInterface $input, OutputInterface $output) Out deps – count unreleased packages from which the package depends In deps – count unreleased packages which depends on the package Out packages – unreleased packages from which the package depends - TEXT + TEXT, ); return Command::SUCCESS; } + /** + * Use this method to get a root directory of the tool. + * + * Commands and components can be moved as a result of refactoring, + * so you should not rely on their location in the file system. + * + * @return string Path to the root directory of the tool WITH a TRAILING SLASH. + */ + protected function getAppRootDir(): string + { + return rtrim($this + ->getApplication() + ->getRootDir(), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR; + } + + private function initPackageList(): void + { + $io = $this->getIO(); + + try { + $ownerPackages = require $this->getAppRootDir() . 'owner-packages.php'; + if (!preg_match('/^[a-z0-9][a-z0-9-]*[a-z0-9]$/i', $ownerPackages)) { + $io->error([ + 'The packages owner can only contain the characters [a-z0-9-], and the character \'-\' cannot appear at the beginning or at the end.', + 'See owner-packages.php to set the packages owner.', + ]); + + exit(1); + } + + $packagesRootDir = $this->getApplication()->getConfig('packagesRootDir') ?? $this->getAppRootDir() . 'dev'; + + $this->packageList = new PackageList( + $ownerPackages, + $this->getAppRootDir() . 'packages.php', + $packagesRootDir, + ); + } catch (InvalidArgumentException $e) { + $io->error([ + 'Invalid local package configuration packages.local.php', + $e->getMessage(), + 'See packages.local.php.example for configuration examples.', + ]); + + exit(1); + } + } + private function hasRelease(Package $package): bool { $gitWorkingCopy = $package->getGitWorkingCopy(); @@ -243,21 +261,6 @@ private function getDependencyNames(Package $package): array return array_unique($names); } - /** - * Use this method to get a root directory of the tool. - * - * Commands and components can be moved as a result of refactoring, - * so you should not rely on their location in the file system. - * - * @return string Path to the root directory of the tool WITH a TRAILING SLASH. - */ - protected function getAppRootDir(): string - { - return rtrim($this - ->getApplication() - ->getRootDir(), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR; - } - private function removeVendorName(string $packageName): string|array { return preg_replace('/^[a-z0-9][a-z0-9-]*[a-z0-9]\//i', '', $packageName); @@ -265,6 +268,6 @@ private function removeVendorName(string $packageName): string|array private function concatDependencies($deps): string { - return implode("\n", array_map(fn (array $array) => implode(', ', $array), array_chunk($deps, 7))); + return implode("\n", array_map(fn(array $array) => implode(', ', $array), array_chunk($deps, 7))); } } diff --git a/src/App/Command/Replicate/ReplicateComposerConfigCommand.php b/src/App/Command/Replicate/ReplicateComposerConfigCommand.php index 98dca11f..36c2ff0c 100644 --- a/src/App/Command/Replicate/ReplicateComposerConfigCommand.php +++ b/src/App/Command/Replicate/ReplicateComposerConfigCommand.php @@ -8,6 +8,7 @@ use Yiisoft\YiiDevTool\App\Component\Package\Package; use Yiisoft\YiiDevTool\Infrastructure\Composer\Config\ComposerConfig; use Yiisoft\YiiDevTool\Infrastructure\Composer\Config\ComposerConfigMerger; +use Throwable; final class ReplicateComposerConfigCommand extends PackageCommand { @@ -48,7 +49,7 @@ protected function processPackage(Package $package): void ComposerConfig::createByFilePath($targetPath), ComposerConfig::createByFilePath($this->getAppRootDir() . 'config/replicate/composer.json'), ); - } catch (\Throwable $e) { + } catch (Throwable $e) { $io->error([ "An error occurred while working on package \"{$package->getId()}\"", $e->getMessage(), diff --git a/src/App/Command/Replicate/ReplicateCopyFileCommand.php b/src/App/Command/Replicate/ReplicateCopyFileCommand.php index 4cc8851b..feb3d4fc 100644 --- a/src/App/Command/Replicate/ReplicateCopyFileCommand.php +++ b/src/App/Command/Replicate/ReplicateCopyFileCommand.php @@ -8,6 +8,7 @@ use Symfony\Component\Console\Input\InputInterface; use Yiisoft\YiiDevTool\App\Component\Console\PackageCommand; use Yiisoft\YiiDevTool\App\Component\Package\Package; +use InvalidArgumentException; final class ReplicateCopyFileCommand extends PackageCommand { @@ -29,11 +30,11 @@ protected function configure(): void protected function beforeProcessingPackages(InputInterface $input): void { - $this->source = (string)$input->getArgument('source'); - $this->destination = (string)$input->getArgument('destination'); + $this->source = (string) $input->getArgument('source'); + $this->destination = (string) $input->getArgument('destination'); if (realpath($this->source) === false) { - throw new \InvalidArgumentException("File \"{$this->source}\" not found."); + throw new InvalidArgumentException("File \"{$this->source}\" not found."); } } diff --git a/src/App/Command/Replicate/ReplicateFilesCommand.php b/src/App/Command/Replicate/ReplicateFilesCommand.php index 8dcae34f..ef1b448e 100644 --- a/src/App/Command/Replicate/ReplicateFilesCommand.php +++ b/src/App/Command/Replicate/ReplicateFilesCommand.php @@ -12,6 +12,10 @@ use Yiisoft\YiiDevTool\App\Component\Package\Package; use Yiisoft\YiiDevTool\App\Component\Package\ReplicationSet; +use function array_key_exists; + +use const DIRECTORY_SEPARATOR; + final class ReplicateFilesCommand extends PackageCommand { private array $sets = []; @@ -27,27 +31,6 @@ protected function configure() parent::configure(); } - private function getReplicationSet(string $name): ?ReplicationSet - { - if ($this->replicationConfig === null) { - /** @noinspection PhpIncludeInspection */ - $this->replicationConfig = require $this->getAppRootDir() . 'config/replicate/files.php'; - } - - if (!array_key_exists($name, $this->replicationConfig)) { - return null; - } - - $setConfig = $this->replicationConfig[$name]; - - return new ReplicationSet( - $setConfig['source'], - $setConfig['files'], - $setConfig['packages']['include'], - $setConfig['packages']['exclude'], - ); - } - protected function beforeProcessingPackages(InputInterface $input): void { $this->sets = $input->getOption('sets'); @@ -61,47 +44,6 @@ protected function getMessageWhenNothingHasBeenOutput(): ?string return '✔ Done'; } - private function checkReplicationSet(string $set): void - { - $replicationSet = $this->getReplicationSet($set); - - $io = $this->getIO(); - - if ($replicationSet === null) { - $io->error("There is no \"$set\" replication set."); - - exit(1); - } - - $packageList = $this->getPackageList(); - $replicationSourcePackageId = $replicationSet->getSourcePackage(); - - if (!$packageList->hasPackage($replicationSourcePackageId)) { - $io->error([ - "Package $replicationSourcePackageId is configured as replication source.", - 'But such a package is not declared in packages configuration.', - 'Replication aborted.', - ]); - - exit(1); - } - - $replicationSourcePackage = $packageList->getPackage($replicationSourcePackageId); - if (!$replicationSourcePackage->isGitRepositoryCloned()) { - $io->error([ - "Package $replicationSourcePackageId is configured as replication source.", - 'But such a package is not installed.', - 'To fix, run the following command:', - '', - " {$this->getExampleCommandPrefix()}yii-dev install $replicationSourcePackageId", - '', - 'Replication aborted.', - ]); - - exit(1); - } - } - protected function processPackage(Package $package): void { $io = $this->getIO(); @@ -140,7 +82,7 @@ protected function processPackage(Package $package): void $fs->copy( $sourceFilePath, $targetFilePath, - true + true, ); } catch (Throwable $e) { $io->error([ @@ -158,4 +100,66 @@ protected function processPackage(Package $package): void $io->done(); } + + private function getReplicationSet(string $name): ?ReplicationSet + { + if ($this->replicationConfig === null) { + /** @noinspection PhpIncludeInspection */ + $this->replicationConfig = require $this->getAppRootDir() . 'config/replicate/files.php'; + } + + if (!array_key_exists($name, $this->replicationConfig)) { + return null; + } + + $setConfig = $this->replicationConfig[$name]; + + return new ReplicationSet( + $setConfig['source'], + $setConfig['files'], + $setConfig['packages']['include'], + $setConfig['packages']['exclude'], + ); + } + + private function checkReplicationSet(string $set): void + { + $replicationSet = $this->getReplicationSet($set); + + $io = $this->getIO(); + + if ($replicationSet === null) { + $io->error("There is no \"$set\" replication set."); + + exit(1); + } + + $packageList = $this->getPackageList(); + $replicationSourcePackageId = $replicationSet->getSourcePackage(); + + if (!$packageList->hasPackage($replicationSourcePackageId)) { + $io->error([ + "Package $replicationSourcePackageId is configured as replication source.", + 'But such a package is not declared in packages configuration.', + 'Replication aborted.', + ]); + + exit(1); + } + + $replicationSourcePackage = $packageList->getPackage($replicationSourcePackageId); + if (!$replicationSourcePackage->isGitRepositoryCloned()) { + $io->error([ + "Package $replicationSourcePackageId is configured as replication source.", + 'But such a package is not installed.', + 'To fix, run the following command:', + '', + " {$this->getExampleCommandPrefix()}yii-dev install $replicationSourcePackageId", + '', + 'Replication aborted.', + ]); + + exit(1); + } + } } diff --git a/src/App/Command/Stats/ContributorsCommand.php b/src/App/Command/Stats/ContributorsCommand.php index 00b1a4a0..640684c9 100644 --- a/src/App/Command/Stats/ContributorsCommand.php +++ b/src/App/Command/Stats/ContributorsCommand.php @@ -14,6 +14,11 @@ use Yiisoft\YiiDevTool\App\Component\Console\YiiDevToolStyle; use Yiisoft\YiiDevTool\App\Component\Package\PackageList; +use function array_key_exists; + +use const DIRECTORY_SEPARATOR; +use const PREG_SPLIT_NO_EMPTY; + final class ContributorsCommand extends Command { private ?OutputManager $io = null; @@ -43,37 +48,6 @@ protected function getIO(): OutputManager return $this->io; } - private function initPackageList(): void - { - $io = $this->getIO(); - - try { - $ownerPackages = require $this->getAppRootDir() . 'owner-packages.php'; - if (!preg_match('/^[a-z0-9][a-z0-9-]*[a-z0-9]$/i', $ownerPackages)) { - $io->error([ - 'The packages owner can only contain the characters [a-z0-9-], and the character \'-\' cannot appear at the beginning or at the end.', - 'See owner-packages.php to set the packages owner.', - ]); - - exit(1); - } - - $this->packageList = new PackageList( - $ownerPackages, - $this->getAppRootDir() . 'packages.php', - $this->getAppRootDir() . 'dev', - ); - } catch (InvalidArgumentException $e) { - $io->error([ - 'Invalid local package configuration packages.local.php', - $e->getMessage(), - 'See packages.local.php.example for configuration examples.', - ]); - - exit(1); - } - } - protected function execute(InputInterface $input, OutputInterface $output) { $since = (string) $input->getOption('since'); @@ -103,9 +77,9 @@ protected function execute(InputInterface $input, OutputInterface $output) [$commits, $name] = preg_split('~\t~', $line, -1, PREG_SPLIT_NO_EMPTY); if (array_key_exists($name, $contributors)) { - $contributors[$name] += (int)$commits; + $contributors[$name] += (int) $commits; } else { - $contributors[$name] = (int)$commits; + $contributors[$name] = (int) $commits; } } } @@ -119,11 +93,6 @@ protected function execute(InputInterface $input, OutputInterface $output) return Command::SUCCESS; } - private function getPackageList(): PackageList - { - return $this->packageList; - } - /** * Use this method to get a root directory of the tool. * @@ -138,4 +107,40 @@ protected function getAppRootDir(): string ->getApplication() ->getRootDir(), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR; } + + private function initPackageList(): void + { + $io = $this->getIO(); + + try { + $ownerPackages = require $this->getAppRootDir() . 'owner-packages.php'; + if (!preg_match('/^[a-z0-9][a-z0-9-]*[a-z0-9]$/i', $ownerPackages)) { + $io->error([ + 'The packages owner can only contain the characters [a-z0-9-], and the character \'-\' cannot appear at the beginning or at the end.', + 'See owner-packages.php to set the packages owner.', + ]); + + exit(1); + } + + $this->packageList = new PackageList( + $ownerPackages, + $this->getAppRootDir() . 'packages.php', + $this->getAppRootDir() . 'dev', + ); + } catch (InvalidArgumentException $e) { + $io->error([ + 'Invalid local package configuration packages.local.php', + $e->getMessage(), + 'See packages.local.php.example for configuration examples.', + ]); + + exit(1); + } + } + + private function getPackageList(): PackageList + { + return $this->packageList; + } } diff --git a/src/App/Command/SwitchCommand.php b/src/App/Command/SwitchCommand.php index 2d43983a..97009e18 100644 --- a/src/App/Command/SwitchCommand.php +++ b/src/App/Command/SwitchCommand.php @@ -12,9 +12,12 @@ use Yiisoft\VarDumper\VarDumper; use Yiisoft\YiiDevTool\App\Component\Console\PackageCommand; +use function dirname; +use function in_array; + #[AsCommand( name: 'switch', - description: 'Enable specified packages and disable others' + description: 'Enable specified packages and disable others', )] final class SwitchCommand extends PackageCommand { @@ -26,7 +29,7 @@ protected function configure(): void <<rbac,di,demo,db-mysql Array keys from package.php configuration can be specified. - DESCRIPTION + DESCRIPTION, ); } @@ -37,7 +40,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $packageList = $this->getPackageList(); $enablePackageIds = array_unique(explode(',', (string) $input->getArgument('packages'))); - $enablePackageIds = array_filter($enablePackageIds, static fn ($id) => !empty($id)); + $enablePackageIds = array_filter($enablePackageIds, static fn($id) => !empty($id)); if (empty($enablePackageIds)) { $io->error('Please, specify packages separated by commas.'); return Command::FAILURE; diff --git a/src/App/Command/TestCommand.php b/src/App/Command/TestCommand.php index 04081b7a..9a2a9f19 100644 --- a/src/App/Command/TestCommand.php +++ b/src/App/Command/TestCommand.php @@ -14,7 +14,7 @@ #[AsCommand( name: 'test', - description: 'Test packages' + description: 'Test packages', )] final class TestCommand extends PackageCommand { diff --git a/src/App/Command/UpdateCommand.php b/src/App/Command/UpdateCommand.php index 2ca46a47..77409ab1 100644 --- a/src/App/Command/UpdateCommand.php +++ b/src/App/Command/UpdateCommand.php @@ -16,7 +16,7 @@ #[AsCommand( name: 'update', - description: 'Pull changes from packages repositories and update composer dependencies' + description: 'Pull changes from packages repositories and update composer dependencies', )] final class UpdateCommand extends PackageCommand { @@ -35,20 +35,20 @@ protected function configure(): void 'no-plugins', null, InputOption::VALUE_NONE, - 'Use --no-plugins during composer update' + 'Use --no-plugins during composer update', ) ->addOption( 'ignore-platform-reqs', null, InputOption::VALUE_NONE, - 'Use --ignore-platform-reqs during composer update' + 'Use --ignore-platform-reqs during composer update', ) ->addOption( 'no-symlinks', null, InputOption::VALUE_OPTIONAL, 'Do not create symbolic links after process', - false + false, ); parent::configure(); @@ -93,7 +93,7 @@ protected function processPackage(Package $package): void $package, $this->additionalComposerUpdateOptions, $this->getErrorsList(), - $io + $io, ); if (!$io->isVerbose()) { diff --git a/src/App/Component/Console/OutputManager.php b/src/App/Component/Console/OutputManager.php index aef37fc3..34a479f8 100644 --- a/src/App/Component/Console/OutputManager.php +++ b/src/App/Component/Console/OutputManager.php @@ -6,6 +6,8 @@ use Yiisoft\YiiDevTool\App\Component\Package\Package; +use function call_user_func_array; + /** * Determines whether to output messages in the current environment. * If a console command operates in a verbose mode, output all messages. @@ -17,9 +19,7 @@ class OutputManager private bool $nextMessageIsImportant = false; private bool $outputDone = false; - public function __construct(private YiiDevToolStyle $io) - { - } + public function __construct(private YiiDevToolStyle $io) {} public function hasColorSupport(): bool { diff --git a/src/App/Component/Console/PackageCommand.php b/src/App/Component/Console/PackageCommand.php index b499ef2e..2fe5b4c7 100644 --- a/src/App/Component/Console/PackageCommand.php +++ b/src/App/Component/Console/PackageCommand.php @@ -16,6 +16,11 @@ use Yiisoft\YiiDevTool\App\Component\Package\PackageList; use Yiisoft\YiiDevTool\App\YiiDevToolApplication; +use function count; +use function in_array; + +use const DIRECTORY_SEPARATOR; + /** * @method YiiDevToolApplication getApplication() */ @@ -33,9 +38,7 @@ class PackageCommand extends Command * Override this method in a subclass if you want to do something before processing the packages. * For example, check the input arguments. */ - protected function beforeProcessingPackages(InputInterface $input): void - { - } + protected function beforeProcessingPackages(InputInterface $input): void {} /** * This method in a subclass should implement the processing logic of each package. @@ -51,9 +54,7 @@ protected function processPackage(Package $package): void * Override this method in a subclass if you want to do something after processing the packages. * For example, link the packages with each other. */ - protected function afterProcessingPackages(InputInterface $input): void - { - } + protected function afterProcessingPackages(InputInterface $input): void {} /** * Override this method in a subclass if you want to output something to the console @@ -90,7 +91,7 @@ protected function configure() Package names separated by commas. For example: rbac,di,demo,db-mysql Array keys from package.php configuration can be specified. If packages are not specified, then command will be applied to all packages. - DESCRIPTION + DESCRIPTION, ); } @@ -193,53 +194,6 @@ protected function initTargetPackages(InputInterface $input): void $this->targetPackages = $targetPackages; } - private function isCurrentInstallationValid(Package $package): bool - { - $io = $this->getIO(); - - if (!$package->isGitRepositoryCloned()) { - // TODO: Implement extensible validation instead of checking command names - if (in_array($this->getName(), ['install', 'update', 'git:clone'], true)) { - return true; - } - - $io->error([ - "Package {$package->getId()} repository is not cloned.", - 'To fix, run the command:', - '', - " {$this->getExampleCommandPrefix()}yii-dev install {$package->getId()}", - ]); - - if (!$this->areTargetPackagesSpecifiedExplicitly()) { - $io->error([ - 'You can also disable the package in packages.local.php', - 'See packages.local.php.example for configuration examples.', - ]); - } - - return false; - } - - $gitWorkingCopy = $package->getGitWorkingCopy(); - $remoteOriginUrl = $gitWorkingCopy->getRemoteUrl('origin'); - if ($package->getConfiguredRepositoryUrl() !== $remoteOriginUrl) { - $io->error([ - "Package {$package->getId()} repository is cloned from {$remoteOriginUrl}, but url {$package->getConfiguredRepositoryUrl()} is configured.", - 'To fix, delete the existing working copy of the repository and run the command:', - '', - " {$this->getExampleCommandPrefix()}yii-dev install {$package->getId()}", - '', - 'Before deleting, make sure that you do not have local changes, branches and tags that are not sent to remote repository.', - 'You can also reconfigure the package repository url in packages.local.php', - 'See packages.local.php.example for configuration examples.', - ]); - - return false; - } - - return true; - } - protected function execute(InputInterface $input, OutputInterface $output): int { $this->initPackageList(); @@ -310,34 +264,6 @@ protected function doesPackageContainErrors(Package $package): bool return $this->errorList->has($package); } - private function showPackageErrors(): void - { - $io = $this->getIO(); - - if (($this->errorList === null ? 0 : count($this->errorList)) > 0) { - $io - ->important() - ->info([ - '', - '=======================================================================', - 'SUMMARY OF ERRORS THAT OCCURRED', - '=======================================================================', - '', - ]); - - foreach ($this->errorList as $packageError) { - $io->preparePackageHeader( - $packageError->getPackage(), - "Package {package} error occurred during {$packageError->getDuring()}:" - ); - - $io - ->important() - ->info($packageError->getMessage()); - } - } - } - /** * @return string Console command prefix that works in current environment. */ @@ -370,4 +296,79 @@ protected function checkSSHConnection(): bool return true; } + + private function isCurrentInstallationValid(Package $package): bool + { + $io = $this->getIO(); + + if (!$package->isGitRepositoryCloned()) { + // TODO: Implement extensible validation instead of checking command names + if (in_array($this->getName(), ['install', 'update', 'git:clone'], true)) { + return true; + } + + $io->error([ + "Package {$package->getId()} repository is not cloned.", + 'To fix, run the command:', + '', + " {$this->getExampleCommandPrefix()}yii-dev install {$package->getId()}", + ]); + + if (!$this->areTargetPackagesSpecifiedExplicitly()) { + $io->error([ + 'You can also disable the package in packages.local.php', + 'See packages.local.php.example for configuration examples.', + ]); + } + + return false; + } + + $gitWorkingCopy = $package->getGitWorkingCopy(); + $remoteOriginUrl = $gitWorkingCopy->getRemoteUrl('origin'); + if ($package->getConfiguredRepositoryUrl() !== $remoteOriginUrl) { + $io->error([ + "Package {$package->getId()} repository is cloned from {$remoteOriginUrl}, but url {$package->getConfiguredRepositoryUrl()} is configured.", + 'To fix, delete the existing working copy of the repository and run the command:', + '', + " {$this->getExampleCommandPrefix()}yii-dev install {$package->getId()}", + '', + 'Before deleting, make sure that you do not have local changes, branches and tags that are not sent to remote repository.', + 'You can also reconfigure the package repository url in packages.local.php', + 'See packages.local.php.example for configuration examples.', + ]); + + return false; + } + + return true; + } + + private function showPackageErrors(): void + { + $io = $this->getIO(); + + if (($this->errorList === null ? 0 : count($this->errorList)) > 0) { + $io + ->important() + ->info([ + '', + '=======================================================================', + 'SUMMARY OF ERRORS THAT OCCURRED', + '=======================================================================', + '', + ]); + + foreach ($this->errorList as $packageError) { + $io->preparePackageHeader( + $packageError->getPackage(), + "Package {package} error occurred during {$packageError->getDuring()}:", + ); + + $io + ->important() + ->info($packageError->getMessage()); + } + } + } } diff --git a/src/App/Component/Console/YiiDevToolStyle.php b/src/App/Component/Console/YiiDevToolStyle.php index 3234ec03..31c55b53 100644 --- a/src/App/Component/Console/YiiDevToolStyle.php +++ b/src/App/Component/Console/YiiDevToolStyle.php @@ -9,6 +9,9 @@ use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Style\SymfonyStyle; +use function count; +use function is_array; + class YiiDevToolStyle extends SymfonyStyle { private bool $hasColorSupport; @@ -36,21 +39,6 @@ public function hasColorSupport(): bool return $this->hasColorSupport; } - protected function wrap($message, string $tag) - { - if (!is_array($message)) { - $message = [$message]; - } - - $count = count($message); - if ($count) { - $message[0] = "{$tag}{$message[0]}"; - $message[$count - 1] .= ''; - } - - return $message; - } - public function error($message): void { $this->writeln($this->wrap($message, '')); @@ -82,4 +70,19 @@ public function header(string $message): void $this->newLine(); } + + protected function wrap($message, string $tag) + { + if (!is_array($message)) { + $message = [$message]; + } + + $count = count($message); + if ($count) { + $message[0] = "{$tag}{$message[0]}"; + $message[$count - 1] .= ''; + } + + return $message; + } } diff --git a/src/App/Component/Git/GitBranches.php b/src/App/Component/Git/GitBranches.php index 34817c52..994a4e59 100644 --- a/src/App/Component/Git/GitBranches.php +++ b/src/App/Component/Git/GitBranches.php @@ -12,9 +12,7 @@ */ final class GitBranches implements IteratorAggregate { - public function __construct(private GitWorkingCopy $gitWorkingCopy) - { - } + public function __construct(private GitWorkingCopy $gitWorkingCopy) {} /** * @return string[] @@ -48,8 +46,8 @@ private function fetchBranches(): array } return array_map( - static fn (string $branch): string => ltrim($branch, ' *'), - preg_split('~\R~', $output) ?: [] + static fn(string $branch): string => ltrim($branch, ' *'), + preg_split('~\R~', $output) ?: [], ); } } diff --git a/src/App/Component/Git/GitException.php b/src/App/Component/Git/GitException.php index 4bd3e880..12416d71 100644 --- a/src/App/Component/Git/GitException.php +++ b/src/App/Component/Git/GitException.php @@ -6,6 +6,4 @@ use RuntimeException; -final class GitException extends RuntimeException -{ -} +final class GitException extends RuntimeException {} diff --git a/src/App/Component/Git/GitTags.php b/src/App/Component/Git/GitTags.php index e727a9f5..02d8b24f 100644 --- a/src/App/Component/Git/GitTags.php +++ b/src/App/Component/Git/GitTags.php @@ -12,9 +12,7 @@ */ final class GitTags implements IteratorAggregate { - public function __construct(private GitWorkingCopy $gitWorkingCopy) - { - } + public function __construct(private GitWorkingCopy $gitWorkingCopy) {} /** * @return string[] @@ -27,8 +25,8 @@ public function all(): array } return array_map( - static fn (string $tag): string => ltrim($tag, ' *'), - preg_split('~\R~', $output) ?: [] + static fn(string $tag): string => ltrim($tag, ' *'), + preg_split('~\R~', $output) ?: [], ); } diff --git a/src/App/Component/Git/GitWorkingCopy.php b/src/App/Component/Git/GitWorkingCopy.php index 2a852bb1..b9a47cd9 100644 --- a/src/App/Component/Git/GitWorkingCopy.php +++ b/src/App/Component/Git/GitWorkingCopy.php @@ -6,13 +6,18 @@ use Symfony\Component\Process\Process; +use function is_array; +use function is_int; +use function is_string; +use function sprintf; +use function strlen; + final class GitWorkingCopy { public function __construct( private string $gitBinary, private string $directory, - ) { - } + ) {} public function branch(mixed ...$argsOrOptions): string { @@ -108,6 +113,16 @@ public function runWithOutput(string $command, array $argsOrOptions, callable $c return $this->runCommand($command, $argsOrOptions, $callback); } + public function tag(mixed ...$argsOrOptions): string + { + return $this->run('tag', $argsOrOptions); + } + + public function tags(): GitTags + { + return new GitTags($this); + } + /** * @param mixed[] $argsOrOptions */ @@ -115,7 +130,7 @@ private function runCommand(string $command, array $argsOrOptions = [], ?callabl { $process = new Process( array_merge([$this->gitBinary, $command], $this->buildArguments($argsOrOptions)), - $this->directory + $this->directory, ); $process->setTimeout(null); $process->run($callback); @@ -128,16 +143,6 @@ private function runCommand(string $command, array $argsOrOptions = [], ?callabl return $process->getOutput(); } - public function tag(mixed ...$argsOrOptions): string - { - return $this->run('tag', $argsOrOptions); - } - - public function tags(): GitTags - { - return new GitTags($this); - } - /** * @param mixed[] $argsOrOptions * diff --git a/src/App/Component/GitHubTokenAware.php b/src/App/Component/GitHubTokenAware.php index 46ab9f87..1b4d7db7 100644 --- a/src/App/Component/GitHubTokenAware.php +++ b/src/App/Component/GitHubTokenAware.php @@ -7,6 +7,7 @@ use Symfony\Component\Console\Command\Command; use Github\Client; use Github\AuthMethod; +use Exception; trait GitHubTokenAware { @@ -44,7 +45,7 @@ public function getGitHubToken(): string try { $client->currentUser()->show(); - } catch (\Exception $e) { + } catch (Exception $e) { $io->error([ "Failed to authenticate with GitHub using the provided token from $tokenFile.", 'Please make sure the token is valid and has the required permissions.', diff --git a/src/App/Component/Package/Package.php b/src/App/Component/Package/Package.php index 2b095929..5ffaabf0 100644 --- a/src/App/Component/Package/Package.php +++ b/src/App/Component/Package/Package.php @@ -9,6 +9,13 @@ use Symfony\Component\Process\ExecutableFinder; use Yiisoft\YiiDevTool\App\Component\Git\GitWorkingCopy; +use function is_array; +use function is_bool; +use function is_string; +use function sprintf; + +use const DIRECTORY_SEPARATOR; + class Package { private static ?string $gitBinary = null; @@ -136,21 +143,6 @@ public function isVirtual(): bool return $this->rootPackage !== null; } - private static function getGitBinary(): string - { - if (static::$gitBinary === null) { - $finder = new ExecutableFinder(); - $gitBinary = $finder->find('git'); - if ($gitBinary === null) { - throw new RuntimeException('Could not find the "git" executable.'); - } - - static::$gitBinary = $gitBinary; - } - - return static::$gitBinary; - } - // TODO: Call all git commands through this interface public function getGitWorkingCopy(): GitWorkingCopy { @@ -183,4 +175,19 @@ public function isMonoRepository(): bool { return $this->isMonoRepository; } + + private static function getGitBinary(): string + { + if (static::$gitBinary === null) { + $finder = new ExecutableFinder(); + $gitBinary = $finder->find('git'); + if ($gitBinary === null) { + throw new RuntimeException('Could not find the "git" executable.'); + } + + static::$gitBinary = $gitBinary; + } + + return static::$gitBinary; + } } diff --git a/src/App/Component/Package/PackageError.php b/src/App/Component/Package/PackageError.php index 46ad4b2b..2ce43e41 100644 --- a/src/App/Component/Package/PackageError.php +++ b/src/App/Component/Package/PackageError.php @@ -6,9 +6,7 @@ class PackageError { - public function __construct(private Package $package, private string $message, private string $during) - { - } + public function __construct(private Package $package, private string $message, private string $during) {} public function getPackage(): Package { diff --git a/src/App/Component/Package/PackageErrorList.php b/src/App/Component/Package/PackageErrorList.php index 34cbc905..5a35da37 100644 --- a/src/App/Component/Package/PackageErrorList.php +++ b/src/App/Component/Package/PackageErrorList.php @@ -6,6 +6,9 @@ use Countable; use Iterator; +use ReturnTypeWillChange; + +use function count; class PackageErrorList implements Iterator, Countable { @@ -31,7 +34,7 @@ public function rewind(): void reset($this->list); } - #[\ReturnTypeWillChange] + #[ReturnTypeWillChange] public function current() { return current($this->list); @@ -42,7 +45,7 @@ public function key(): ?string return key($this->list); } - #[\ReturnTypeWillChange] + #[ReturnTypeWillChange] public function next() { return next($this->list); diff --git a/src/App/Component/Package/PackageList.php b/src/App/Component/Package/PackageList.php index 63dfd34c..af7ccbd6 100644 --- a/src/App/Component/Package/PackageList.php +++ b/src/App/Component/Package/PackageList.php @@ -5,6 +5,8 @@ namespace Yiisoft\YiiDevTool\App\Component\Package; use function array_key_exists; +use function is_array; +use function is_bool; class PackageList { @@ -81,7 +83,7 @@ public function getInstalledAndEnabledPackages(): array if ($this->installedAndEnabledList === null) { $this->installedAndEnabledList = array_filter( $this->getInstalledPackages(), - static fn (Package $package) => $package->enabled(), + static fn(Package $package) => $package->enabled(), ); } diff --git a/src/App/Component/Package/ReplicationSet.php b/src/App/Component/Package/ReplicationSet.php index 9455d0e9..7aa5d7ec 100644 --- a/src/App/Component/Package/ReplicationSet.php +++ b/src/App/Component/Package/ReplicationSet.php @@ -4,11 +4,11 @@ namespace Yiisoft\YiiDevTool\App\Component\Package; +use function in_array; + class ReplicationSet { - public function __construct(private string $sourcePackage, private array $files, private array $includedPackages, private array $excludedPackages) - { - } + public function __construct(private string $sourcePackage, private array $files, private array $includedPackages, private array $excludedPackages) {} public function getSourcePackage(): string { @@ -28,8 +28,6 @@ public function appliesToPackage(string $name): bool return !(in_array('*', $this->excludedPackages, true) || in_array($name, $this->excludedPackages, true)) - - ; } } diff --git a/src/App/Component/PhpStorm/Folders.php b/src/App/Component/PhpStorm/Folders.php index c783788e..abbc892c 100644 --- a/src/App/Component/PhpStorm/Folders.php +++ b/src/App/Component/PhpStorm/Folders.php @@ -4,6 +4,11 @@ namespace Yiisoft\YiiDevTool\App\Component\PhpStorm; +use InvalidArgumentException; +use RuntimeException; + +use function sprintf; + final class Folders { private string $ideaPath; @@ -15,7 +20,7 @@ final class Folders public function __construct(string $ideaPath) { if (!is_dir($ideaPath)) { - throw new \InvalidArgumentException("No .idea at $ideaPath."); + throw new InvalidArgumentException("No .idea at $ideaPath."); } $this->ideaPath = $ideaPath; } @@ -53,7 +58,7 @@ public function write(): void $modulesContent = file_get_contents($this->ideaPath . '/modules.xml'); if (!preg_match('~ideaPath . '/' . $matches[1]; @@ -62,7 +67,7 @@ public function write(): void $imlContent = preg_replace( '~.*~s', "\n" . $entries . ' ', - $imlContent + $imlContent, ); file_put_contents($imlPath, $imlContent); diff --git a/src/App/PackageService.php b/src/App/PackageService.php index e9357d39..3b2668dc 100644 --- a/src/App/PackageService.php +++ b/src/App/PackageService.php @@ -13,20 +13,22 @@ use Yiisoft\YiiDevTool\App\Component\Package\PackageErrorList; use Yiisoft\YiiDevTool\App\Component\Package\PackageList; +use const DIRECTORY_SEPARATOR; + final class PackageService { public function composerInstall( Package $package, array $additionalOptions, PackageErrorList $errorList, - OutputManager $io + OutputManager $io, ): void { $this->composerInstallOrUpdate( 'install', $package, $additionalOptions, $errorList, - $io + $io, ); } @@ -34,14 +36,14 @@ public function composerUpdate( Package $package, array $additionalOptions, PackageErrorList $errorList, - OutputManager $io + OutputManager $io, ): void { $this->composerInstallOrUpdate( 'update', $package, $additionalOptions, $errorList, - $io + $io, ); } @@ -49,7 +51,7 @@ public function gitClone( Package $package, string $commandName, PackageErrorList $errorList, - OutputManager $io + OutputManager $io, ): void { $io ->important() @@ -156,7 +158,7 @@ private function composerInstallOrUpdate( Package $package, array $additionalOptions, PackageErrorList $errorList, - OutputManager $io + OutputManager $io, ): void { $io ->important() diff --git a/src/App/YiiDevToolApplication.php b/src/App/YiiDevToolApplication.php index 4bdf05ac..d36c4eb9 100644 --- a/src/App/YiiDevToolApplication.php +++ b/src/App/YiiDevToolApplication.php @@ -59,7 +59,7 @@ final class YiiDevToolApplication extends Application HEADER; public function __construct( - private array $config + private array $config, ) { parent::__construct($this->header); $this->setDefaultCommand('list-commands'); @@ -81,6 +81,11 @@ public function getRootDir(): string return $this->rootDir; } + public function getConfig(string $name): mixed + { + return $this->config[$name] ?? null; + } + protected function getDefaultCommands(): array { $packageService = new PackageService(); @@ -132,9 +137,4 @@ protected function getDefaultInputDefinition(): InputDefinition new InputOption('--verbose', '-v', InputOption::VALUE_NONE, 'Increase the verbosity of messages'), ]); } - - public function getConfig(string $name): mixed - { - return $this->config[$name] ?? null; - } } diff --git a/src/Infrastructure/Changelog.php b/src/Infrastructure/Changelog.php index fea5673f..b41ff0da 100644 --- a/src/Infrastructure/Changelog.php +++ b/src/Infrastructure/Changelog.php @@ -6,6 +6,8 @@ use InvalidArgumentException; +use function sprintf; + final class Changelog { public const TYPES = [ @@ -15,9 +17,7 @@ final class Changelog 'Enh', ]; - public function __construct(private string $path) - { - } + public function __construct(private string $path) {} public function resort(): void { @@ -68,7 +68,7 @@ public function addEntry(string $text): void $1 - $text MARKDOWN, - $this->path + $this->path, ); if ($replaces === 0) { $this->replaceInFile( @@ -77,7 +77,7 @@ public function addEntry(string $text): void $1 - $text MARKDOWN, - $this->path + $this->path, ); } } @@ -87,7 +87,7 @@ public function close(Version $version): void $this->replaceInFile( '/\d+\.\d+\.\d+ under development/', $version . ' ' . date('F d, Y'), - $this->path + $this->path, ); } @@ -117,7 +117,7 @@ private function replaceInFile(string $pattern, string $replace, string $file): sprintf( 'File path "%s" is incorrect. The file does not exist.', $file, - ) + ), ); } file_put_contents($file, preg_replace($pattern, $replace, file_get_contents($file), count: $replaces)); @@ -151,7 +151,7 @@ private function splitChangelog(?string $version = null): array } if ($state === 'changelog' && isset($lines[$lineNumber + 1]) && str_starts_with( $lines[$lineNumber + 1], - '## ' + '## ', )) { $state = 'end'; } diff --git a/src/Infrastructure/CodeUsage/CodeUsage.php b/src/Infrastructure/CodeUsage/CodeUsage.php index 777b16a7..81f04690 100644 --- a/src/Infrastructure/CodeUsage/CodeUsage.php +++ b/src/Infrastructure/CodeUsage/CodeUsage.php @@ -6,6 +6,10 @@ use InvalidArgumentException; +use function count; +use function in_array; +use function is_string; + class CodeUsage { /** diff --git a/src/Infrastructure/CodeUsage/NamespaceUsageFinder.php b/src/Infrastructure/CodeUsage/NamespaceUsageFinder.php index 49534a8f..2f8bdd5c 100644 --- a/src/Infrastructure/CodeUsage/NamespaceUsageFinder.php +++ b/src/Infrastructure/CodeUsage/NamespaceUsageFinder.php @@ -13,6 +13,8 @@ use function array_key_exists; use function is_string; +use const PATHINFO_EXTENSION; + class NamespaceUsageFinder { /** @@ -62,6 +64,15 @@ public function getUsages(): array return $this->usages; } + public function registerNamespaceUsage(string $namespace, string $environment): void + { + if (!array_key_exists($namespace, $this->usages)) { + $this->usages[$namespace] = new CodeUsage($namespace, $environment); + } else { + $this->usages[$namespace]->registerUsageInEnvironment($environment); + } + } + private function find(): void { $this->usages = []; @@ -145,13 +156,4 @@ private function findNamespaceUsagesInPhpCode(string &$code, string $environment $nodeTraverser->addVisitor(new NamespaceUsageFinderNameResolver($this, $environment)); $nodeTraverser->traverse($stmts); } - - public function registerNamespaceUsage(string $namespace, string $environment): void - { - if (!array_key_exists($namespace, $this->usages)) { - $this->usages[$namespace] = new CodeUsage($namespace, $environment); - } else { - $this->usages[$namespace]->registerUsageInEnvironment($environment); - } - } } diff --git a/src/Infrastructure/CodeUsage/NamespaceUsageFinderNameResolver.php b/src/Infrastructure/CodeUsage/NamespaceUsageFinderNameResolver.php index a48d46d2..707cc374 100644 --- a/src/Infrastructure/CodeUsage/NamespaceUsageFinderNameResolver.php +++ b/src/Infrastructure/CodeUsage/NamespaceUsageFinderNameResolver.php @@ -14,7 +14,7 @@ public function __construct( protected NamespaceUsageFinder $namespaceUsageFinder, protected string $environment, ?ErrorHandler $errorHandler = null, - array $options = [] + array $options = [], ) { parent::__construct($errorHandler, $options); } diff --git a/src/Infrastructure/Composer/ComposerInstallation.php b/src/Infrastructure/Composer/ComposerInstallation.php index 4ffb1cc8..3ed2bce6 100644 --- a/src/Infrastructure/Composer/ComposerInstallation.php +++ b/src/Infrastructure/Composer/ComposerInstallation.php @@ -6,6 +6,8 @@ use Yiisoft\YiiDevTool\Infrastructure\Composer\Config\ComposerConfig; +use function count; + class ComposerInstallation { private array $installedDependencies; diff --git a/src/Infrastructure/Composer/ComposerPackage.php b/src/Infrastructure/Composer/ComposerPackage.php index 6f90552b..332ddc2e 100644 --- a/src/Infrastructure/Composer/ComposerPackage.php +++ b/src/Infrastructure/Composer/ComposerPackage.php @@ -7,13 +7,13 @@ use RuntimeException; use Yiisoft\YiiDevTool\Infrastructure\Composer\Config\ComposerConfig; +use function array_key_exists; + class ComposerPackage { private ?ComposerConfig $config = null; - public function __construct(private string $name, private string $path) - { - } + public function __construct(private string $name, private string $path) {} public function getName(): string { diff --git a/src/Infrastructure/Composer/ComposerPackageUsageAnalyzer.php b/src/Infrastructure/Composer/ComposerPackageUsageAnalyzer.php index 7ef4a317..22ac22a0 100644 --- a/src/Infrastructure/Composer/ComposerPackageUsageAnalyzer.php +++ b/src/Infrastructure/Composer/ComposerPackageUsageAnalyzer.php @@ -8,6 +8,8 @@ use RuntimeException; use Yiisoft\YiiDevTool\Infrastructure\CodeUsage\CodeUsage; +use function array_key_exists; + class ComposerPackageUsageAnalyzer { /** diff --git a/src/Infrastructure/Composer/Config/ComposerConfig.php b/src/Infrastructure/Composer/Config/ComposerConfig.php index c8f0ed36..672641d2 100644 --- a/src/Infrastructure/Composer/Config/ComposerConfig.php +++ b/src/Infrastructure/Composer/Config/ComposerConfig.php @@ -9,6 +9,11 @@ use Yiisoft\YiiDevTool\Infrastructure\Composer\Config\Dependency\ComposerConfigDependencyList; use function array_key_exists; +use function in_array; + +use const JSON_ERROR_NONE; +use const JSON_PRETTY_PRINT; +use const JSON_UNESCAPED_SLASHES; class ComposerConfig { @@ -19,9 +24,7 @@ class ComposerConfig public const SECTION_DESCRIPTION = 'description'; - private function __construct(private array $data) - { - } + private function __construct(private array $data) {} public static function getAllDependencySections(): array { diff --git a/src/Infrastructure/Composer/Config/ComposerConfigDependenciesModifier.php b/src/Infrastructure/Composer/Config/ComposerConfigDependenciesModifier.php index 09d83266..c7035ebb 100644 --- a/src/Infrastructure/Composer/Config/ComposerConfigDependenciesModifier.php +++ b/src/Infrastructure/Composer/Config/ComposerConfigDependenciesModifier.php @@ -6,11 +6,11 @@ use InvalidArgumentException; +use function is_string; + class ComposerConfigDependenciesModifier { - public function __construct(private ComposerConfig $config) - { - } + public function __construct(private ComposerConfig $config) {} /** * Remove dependencies from composer config. @@ -56,9 +56,9 @@ public function ensureDependenciesUsedOnlyInSection(array $packageNames, string $this->validatePackageNames($packageNames); ComposerConfig::validateDependencySection($targetSection); - $sectionForCleaning = $targetSection === ComposerConfig::SECTION_REQUIRE ? - ComposerConfig::SECTION_REQUIRE_DEV : - ComposerConfig::SECTION_REQUIRE; + $sectionForCleaning = $targetSection === ComposerConfig::SECTION_REQUIRE + ? ComposerConfig::SECTION_REQUIRE_DEV + : ComposerConfig::SECTION_REQUIRE; $config = $this->config; @@ -68,7 +68,7 @@ public function ensureDependenciesUsedOnlyInSection(array $packageNames, string if (!$targetDependencyList->hasDependency($packageName)) { $targetDependencyList->addDependency( $packageName, - $this->getDependencyConstraint($packageName, $sectionForCleaning) + $this->getDependencyConstraint($packageName, $sectionForCleaning), ); $dependenciesChanged = true; diff --git a/src/Infrastructure/Composer/Config/ComposerConfigMerger.php b/src/Infrastructure/Composer/Config/ComposerConfigMerger.php index 483fd75f..7bf77905 100644 --- a/src/Infrastructure/Composer/Config/ComposerConfigMerger.php +++ b/src/Infrastructure/Composer/Config/ComposerConfigMerger.php @@ -4,6 +4,10 @@ namespace Yiisoft\YiiDevTool\Infrastructure\Composer\Config; +use function array_key_exists; +use function is_array; +use function is_string; + class ComposerConfigMerger { public function merge(ComposerConfig $firstConfig, ComposerConfig $secondConfig): ComposerConfig diff --git a/src/Infrastructure/Composer/Config/Dependency/ComposerConfigDependency.php b/src/Infrastructure/Composer/Config/Dependency/ComposerConfigDependency.php index 32ff6686..13f6ea13 100644 --- a/src/Infrastructure/Composer/Config/Dependency/ComposerConfigDependency.php +++ b/src/Infrastructure/Composer/Config/Dependency/ComposerConfigDependency.php @@ -11,9 +11,7 @@ class ComposerConfigDependency */ private const PLATFORM_PACKAGE_REGEX = '{^(?:php(?:-64bit|-ipv6|-zts|-debug)?|hhvm|(?:ext|lib)-[a-z0-9](?:[_.-]?[a-z0-9]+)*|composer-(?:plugin|runtime)-api)$}iD'; - public function __construct(private string $packageName, private string $constraint) - { - } + public function __construct(private string $packageName, private string $constraint) {} public function getPackageName(): string { diff --git a/src/Infrastructure/Composer/Config/Dependency/ComposerConfigDependencyList.php b/src/Infrastructure/Composer/Config/Dependency/ComposerConfigDependencyList.php index 048b4413..74b9a619 100644 --- a/src/Infrastructure/Composer/Config/Dependency/ComposerConfigDependencyList.php +++ b/src/Infrastructure/Composer/Config/Dependency/ComposerConfigDependencyList.php @@ -7,6 +7,10 @@ use InvalidArgumentException; use RuntimeException; +use function array_key_exists; +use function count; +use function is_string; + class ComposerConfigDependencyList { /** diff --git a/src/Infrastructure/Version.php b/src/Infrastructure/Version.php index 9583782b..76278372 100644 --- a/src/Infrastructure/Version.php +++ b/src/Infrastructure/Version.php @@ -4,7 +4,10 @@ namespace Yiisoft\YiiDevTool\Infrastructure; -final class Version implements \Stringable +use RuntimeException; +use Stringable; + +final class Version implements Stringable { public const TYPE_MAJOR = 'Major - Incompatible API changes.'; public const TYPE_MINOR = 'Minor - Add functionality (backwards-compatible).'; @@ -12,9 +15,7 @@ final class Version implements \Stringable public const TYPES = [self::TYPE_PATCH, self::TYPE_MINOR, self::TYPE_MAJOR]; - public function __construct(private string $version) - { - } + public function __construct(private string $version) {} public function __toString(): string { @@ -47,7 +48,7 @@ public function getNext(string $type): self $parts[2]++; break; default: - throw new \RuntimeException('Unknown version type.'); + throw new RuntimeException('Unknown version type.'); } return new self(implode('.', $parts)); } diff --git a/tests/App/Command/Release/ReleaseDescriptionTest.php b/tests/App/Command/Release/ReleaseDescriptionTest.php index 4039018d..6f8cca4b 100644 --- a/tests/App/Command/Release/ReleaseDescriptionTest.php +++ b/tests/App/Command/Release/ReleaseDescriptionTest.php @@ -26,8 +26,8 @@ public function testGetBodyAddsFullChangelogCompareLink(): void 'yiisoft/html', new Version('3.10.0'), new Version('3.11.0'), - ['- Bug #1: Fixed issue (@samdark)'] - ) + ['- Bug #1: Fixed issue (@samdark)'], + ), ); } @@ -41,8 +41,8 @@ public function testGetBodyDoesNotAddFullChangelogLinkWithoutPreviousVersion(): 'yiisoft/html', new Version(''), new Version('1.0.0'), - ['- Initial release.'] - ) + ['- Initial release.'], + ), ); } @@ -65,8 +65,8 @@ public function testGetBodyAddsUpgradeNotesLinkForMajorReleaseWhenUpgradeNotesEx new Version('3.10.0'), new Version('4.0.0'), ['- Enh #1: Removed deprecated API (@samdark)'], - true - ) + true, + ), ); } @@ -87,8 +87,8 @@ public function testGetBodyDoesNotAddUpgradeNotesLinkForMinorRelease(): void new Version('3.10.0'), new Version('3.11.0'), ['- Enh #1: Added API (@samdark)'], - true - ) + true, + ), ); } @@ -108,8 +108,8 @@ public function testGetBodyDoesNotAddUpgradeNotesLinkWhenUpgradeNotesDoNotExist( 'yiisoft/html', new Version('3.10.0'), new Version('4.0.0'), - ['- Enh #1: Removed deprecated API (@samdark)'] - ) + ['- Enh #1: Removed deprecated API (@samdark)'], + ), ); } } diff --git a/tests/App/Command/Release/ReleaseNewsTest.php b/tests/App/Command/Release/ReleaseNewsTest.php index ed8c54f7..d62983b5 100644 --- a/tests/App/Command/Release/ReleaseNewsTest.php +++ b/tests/App/Command/Release/ReleaseNewsTest.php @@ -22,8 +22,8 @@ public function testGetChangesWithMultilineChangelogItem(): void [ "- Enh #47: Minor refactor `RequestBodyParser`: use `str_contains()` function instead of `strpos()`\n and `::class` instead\n of `get_class()` (@vjik)", '- Bug #44: Explicitly mark nullable parameters (@vjik)', - ] - ) + ], + ), ); } } diff --git a/tests/App/Command/Release/WhatCommandTest.php b/tests/App/Command/Release/WhatCommandTest.php index 9777965e..0a05f63a 100644 --- a/tests/App/Command/Release/WhatCommandTest.php +++ b/tests/App/Command/Release/WhatCommandTest.php @@ -10,6 +10,9 @@ use Symfony\Component\Process\Process; use Yiisoft\YiiDevTool\App\YiiDevToolApplication; +use const JSON_PRETTY_PRINT; +use const JSON_UNESCAPED_SLASHES; + final class WhatCommandTest extends TestCase { private string $rootDir; @@ -27,7 +30,7 @@ protected function setUp(): void file_put_contents($this->rootDir . '/owner-packages.php', "rootDir . '/packages.php', - " true,\n 'input-http' => true,\n 'request-model' => true,\n 'validator' => true,\n];\n" + " true,\n 'input-http' => true,\n 'request-model' => true,\n 'validator' => true,\n];\n", ); (new Filesystem())->mkdir($this->packagesRootDir . '/demo'); @@ -58,11 +61,11 @@ public function testListsOnlyOutgoingPackages(): void $this->assertStringContainsString('Out packages', $output); $this->assertMatchesRegularExpression( '/\| yiisoft\/request-model\s+\| 1\s+\| 1\s+\| validator\s+\|/', - $output + $output, ); $this->assertDoesNotMatchRegularExpression( '/\| yiisoft\/request-model\s+\| 1\s+\| 1\s+\|[^\n]*input-http/', - $output + $output, ); } @@ -78,7 +81,7 @@ private function createPackage(string $name, array $require = []): void file_put_contents( $packageDir . '/composer.json', - json_encode($composer, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) . "\n" + json_encode($composer, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) . "\n", ); (new Process(['git', 'init', '--quiet'], $packageDir))->mustRun(); diff --git a/tests/App/Component/Console/ProcessOutputTest.php b/tests/App/Component/Console/ProcessOutputTest.php index 1aac3613..c7afcc99 100644 --- a/tests/App/Component/Console/ProcessOutputTest.php +++ b/tests/App/Component/Console/ProcessOutputTest.php @@ -12,6 +12,8 @@ use Yiisoft\YiiDevTool\App\Component\Console\ProcessOutput; use Yiisoft\YiiDevTool\App\Component\Console\YiiDevToolStyle; +use const PHP_BINARY; + final class ProcessOutputTest extends TestCase { public function testRunStreamsOutputBeforeProcessFinishes(): void @@ -50,7 +52,7 @@ protected function doWrite(string $message, bool $newline): void ProcessOutput::run( $process, - new OutputManager(new YiiDevToolStyle(new ArrayInput([]), $output)) + new OutputManager(new YiiDevToolStyle(new ArrayInput([]), $output)), ); try { diff --git a/tests/Infrastructure/CodeUsage/NamespaceUsageFinderTest.php b/tests/Infrastructure/CodeUsage/NamespaceUsageFinderTest.php index 00257a92..c6408b35 100644 --- a/tests/Infrastructure/CodeUsage/NamespaceUsageFinderTest.php +++ b/tests/Infrastructure/CodeUsage/NamespaceUsageFinderTest.php @@ -7,18 +7,17 @@ use PHPUnit\Framework\TestCase; use Yiisoft\YiiDevTool\Infrastructure\CodeUsage\CodeUsageEnvironment; use Yiisoft\YiiDevTool\Infrastructure\CodeUsage\NamespaceUsageFinder; +use Custom\NonPSRNamespace\VarStorage; +use Production\Config\Config; +use SplFixedArray; +use SplStack; final class NamespaceUsageFinderTest extends TestCase { - protected function getFixturePath(string $name) - { - return __DIR__ . '/Fixture/' . $name; - } - public function testGetUsages() { - $namespaceUsages = - (new NamespaceUsageFinder()) + $namespaceUsages + = (new NamespaceUsageFinder()) ->addTargetPaths(CodeUsageEnvironment::PRODUCTION, [ 'config/prod.php', 'src', @@ -31,15 +30,15 @@ public function testGetUsages() $expectedResults = [ // Used in custom environment only - '\\' . \Custom\NonPSRNamespace\VarStorage::class => ['custom-environment'], + '\\' . VarStorage::class => ['custom-environment'], '\\' . \Custom\Storage\VarStorage::class => ['custom-environment'], - '\\' . \SplStack::class => ['custom-environment'], + '\\' . SplStack::class => ['custom-environment'], // Used in production environment only - '\\' . \Production\Config\Config::class => [CodeUsageEnvironment::PRODUCTION], + '\\' . Config::class => [CodeUsageEnvironment::PRODUCTION], '\\' . \Production\NonPSRNamespace\Config::class => [CodeUsageEnvironment::PRODUCTION], '\\' . \Production\Spl\SplFixedArray::class => [CodeUsageEnvironment::PRODUCTION], - '\\' . \SplFixedArray::class => [CodeUsageEnvironment::PRODUCTION], + '\\' . SplFixedArray::class => [CodeUsageEnvironment::PRODUCTION], // Used in both environments '\time' => [CodeUsageEnvironment::PRODUCTION, 'custom-environment'], @@ -53,4 +52,9 @@ public function testGetUsages() // Not used, replaced by local implementation $this->assertArrayNotHasKey('\count', $namespaceUsages); } + + protected function getFixturePath(string $name) + { + return __DIR__ . '/Fixture/' . $name; + } } From 913b61db11a2b9e1d39a0ac78abc4d275c401ac0 Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Fri, 31 Jul 2026 17:36:21 +0300 Subject: [PATCH 2/6] fix --- .github/workflows/build.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7d3bdb60..ed075a02 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -28,6 +28,5 @@ jobs: ['ubuntu-latest'] php: >- ['8.0', '8.1', '8.2', '8.3', '8.4', '8.5'] - composer-command: composer update --prefer-dist --no-interaction --no-progress --optimize-autoloader --ansi --no-security-blocking secrets: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} From b7604b0eddaa928fff4efa1a819dbcfa1e1d5bbf Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Fri, 31 Jul 2026 17:37:49 +0300 Subject: [PATCH 3/6] fix --- composer.json | 1 - tools/rector/composer.json | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/composer.json b/composer.json index c7dc0d22..d57f02bc 100644 --- a/composer.json +++ b/composer.json @@ -48,7 +48,6 @@ "bamarni/composer-bin-plugin": "^1.8.2", "friendsofphp/php-cs-fixer": "^3.95", "phpunit/phpunit": "^9.6.29", - "rector/rector": "^2.5", "yiisoft/code-style": "^1.1" }, "autoload": { diff --git a/tools/rector/composer.json b/tools/rector/composer.json index 75fb485f..c31581d4 100644 --- a/tools/rector/composer.json +++ b/tools/rector/composer.json @@ -1,5 +1,5 @@ { "require-dev": { - "rector/rector": "^2.2.3" + "rector/rector": "^2.5.9" } } From 911ab02d8e4fa139734defa01d1ad022c20ba686 Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Fri, 31 Jul 2026 17:45:00 +0300 Subject: [PATCH 4/6] fix --- .github/workflows/build.yml | 2 +- .github/workflows/rector-cs.yml | 2 +- README.md | 2 +- composer.json | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ed075a02..90e5f1b3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -27,6 +27,6 @@ jobs: os: >- ['ubuntu-latest'] php: >- - ['8.0', '8.1', '8.2', '8.3', '8.4', '8.5'] + ['8.1', '8.2', '8.3', '8.4', '8.5'] secrets: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} diff --git a/.github/workflows/rector-cs.yml b/.github/workflows/rector-cs.yml index 29d8f1c9..c985eb6e 100644 --- a/.github/workflows/rector-cs.yml +++ b/.github/workflows/rector-cs.yml @@ -24,4 +24,4 @@ jobs: contents: write # Required to commit formatting fixes back to the PR uses: yiisoft/actions/.github/workflows/rector-cs.yml@master with: - php: '8.0' + php: '8.1' diff --git a/README.md b/README.md index 62f3aa89..f12b076a 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ Requirements If you prefer manual install, you need: - GNU/Linux or Windows **with bash** -- PHP 8.0 or higher +- PHP 8.1 - 8.5 - [Composer](https://getcomposer.org/) installed and available [as `composer` on the command line](https://getcomposer.org/doc/00-intro.md#globally) diff --git a/composer.json b/composer.json index d57f02bc..e294856b 100644 --- a/composer.json +++ b/composer.json @@ -28,7 +28,7 @@ } ], "require": { - "php": "^8.0", + "php": "8.1 - 8.5", "ext-curl": "*", "ext-openssl": "*", "knplabs/github-api": "^3.2", @@ -46,7 +46,7 @@ }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", - "friendsofphp/php-cs-fixer": "^3.95", + "friendsofphp/php-cs-fixer": "^3.95.18", "phpunit/phpunit": "^9.6.29", "yiisoft/code-style": "^1.1" }, From c51e9a50dcc980813c3c53eaecf533d017a8394f Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Fri, 31 Jul 2026 17:48:34 +0300 Subject: [PATCH 5/6] fix --- rector.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rector.php b/rector.php index 5e772354..a3c3a946 100644 --- a/rector.php +++ b/rector.php @@ -11,7 +11,7 @@ __DIR__ . '/tests', __DIR__ . '/config', ]) - ->withPhpSets(php80: true) + ->withPhpSets(php81: true) ->withSets([ SetList::YII_CORE, ]) From ea15c8b5e9dfcd833637feba07b154db5b198d81 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 31 Jul 2026 14:49:15 +0000 Subject: [PATCH 6/6] Apply PHP CS Fixer and Rector changes (CI) --- src/App/Command/AddChangelogCommand.php | 2 +- src/Infrastructure/Composer/Config/ComposerConfigMerger.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/App/Command/AddChangelogCommand.php b/src/App/Command/AddChangelogCommand.php index 9b568960..4d4ebf69 100644 --- a/src/App/Command/AddChangelogCommand.php +++ b/src/App/Command/AddChangelogCommand.php @@ -53,7 +53,7 @@ protected function processPackage(Package $package): void { $io = $this->getIO(); - $loweredTypes = array_map(fn(string $type) => strtolower($type), Changelog::TYPES); + $loweredTypes = array_map(strtolower(...), Changelog::TYPES); if (!in_array(strtolower($this->type), $loweredTypes, true)) { $io->error( sprintf( diff --git a/src/Infrastructure/Composer/Config/ComposerConfigMerger.php b/src/Infrastructure/Composer/Config/ComposerConfigMerger.php index 7bf77905..720b8772 100644 --- a/src/Infrastructure/Composer/Config/ComposerConfigMerger.php +++ b/src/Infrastructure/Composer/Config/ComposerConfigMerger.php @@ -59,7 +59,7 @@ private function sortDependencies(array $config): array private function sortInternal(array $packages): array { - uksort($packages, 'strnatcmp'); + uksort($packages, strnatcmp(...)); $extensions = []; foreach ($packages as $package => $version) {