Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add composer command yii-config-info #175

Merged
merged 23 commits into from
Apr 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@

## 1.5.1 under development

- New #175: Add `yii-config-info` composer command (@vjik)
- New #173: Allow to use option "config-plugin-file" in packages (@vjik)
- Enh #172, #173: Refactoring: extract config settings reader to separate class (@vjik)
- Chg #175: Raise minimum Composer version to 2.3 (@vjik)
- Enh #175: Minor refactoring of internal classes `Options` and `ProcessHelper` (@vjik)

## 1.5.0 December 25, 2023

Expand Down
11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ The package becomes a plugin holding both the code and its default configuration
## Requirements

- PHP 8.0 or higher.
- Composer 2.0 or higher.
- Composer 2.3 or higher.

## Installation

Expand Down Expand Up @@ -641,6 +641,15 @@ command:
composer yii-config-rebuild
```

### `yii-config-info`

The `yii-config-rebuild` command displays application or package configuration details.

```shell
composer yii-config-info
composer yii-config-info yiisoft/widget
```

## Testing

### Unit testing
Expand Down
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,14 @@
"require": {
"php": "^8.0",
"composer-plugin-api": "^2.0",
"symfony/console": "^5.4.11|^6.0.11|^7",
"yiisoft/arrays": "^3.0",
"yiisoft/strings": "^2.0",
"yiisoft/var-dumper": "^1.1"
},
"require-dev": {
"ext-json": "*",
"composer/composer": "^2.0",
"composer/composer": "^2.3",
"maglnet/composer-require-checker": "^4.4",
"phpunit/phpunit": "^9.5",
"rector/rector": "^1.0.0",
Expand Down
1 change: 1 addition & 0 deletions src/Command/ConfigCommandProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ public function getCommands(): array
return [
new CopyCommand(),
new RebuildCommand(),
new InfoCommand(),
];
}
}
6 changes: 1 addition & 5 deletions src/Command/CopyCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
/** @var string[] $selectedFileNames */
$selectedFileNames = $input->getArgument('files');

/**
* @psalm-suppress PossiblyNullArgument
* @psalm-suppress DeprecatedMethod
*/
$builder = new PackageFilesProcess($this->getComposer(), [$package]);
$builder = new PackageFilesProcess($this->requireComposer(), [$package]);

$filesystem = new Filesystem();
$targetPath = $builder
Expand Down
165 changes: 165 additions & 0 deletions src/Command/InfoCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Config\Command;

use Composer\Command\BaseCommand;
use Composer\Composer;
use Composer\Package\BasePackage;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Yiisoft\Config\Composer\ConfigSettings;
use Yiisoft\Config\Composer\Options;

final class InfoCommand extends BaseCommand
{
protected function configure(): void
{
$this
->setName('yii-config-info')
->addArgument('package', InputArgument::OPTIONAL);
}

protected function execute(InputInterface $input, OutputInterface $output): int
{
$io = new SymfonyStyle($input, $output);
$composer = $this->requireComposer();

$packageName = $input->getArgument('package');
if (is_string($packageName)) {
$package = $composer->getRepositoryManager()->getLocalRepository()->findPackage($packageName, '*');
if ($package === null) {
$io->error('Package "' . $packageName . '" not found.');
return 1;
}
return $this->vendorPackage($composer, $package, $io);
}

return $this->rootPackage($composer, $io);
}

private function vendorPackage(Composer $composer, BasePackage $package, SymfonyStyle $io): int
{
$settings = ConfigSettings::forVendorPackage($composer, $package);
if (empty($settings->packageConfiguration())) {
$io->writeln('');
$io->writeln('<fg=gray>Configuration don\'t found in package "' . $package->getName() . '".</>');
return 0;
}

$io->title('Yii Config — Package "' . $package->getName() . '"');

$io->writeln('Source directory: ' . $settings->path() . '/' . $settings->options()->sourceDirectory());

$io->section('Configuration groups');
$this->writeConfiguration($io, $settings->packageConfiguration());

return 0;
}

private function rootPackage(Composer $composer, SymfonyStyle $io): int
{
$settings = ConfigSettings::forRootPackage($composer);
$options = $settings->options();
$sourceDirectory = $settings->options()->sourceDirectory();
$mergePlanFilePath = $settings->path() . '/'
. (empty($sourceDirectory) ? '' : ($sourceDirectory . '/'))
. $options->mergePlanFile();

$io->title('Yii Config — Root Configuration');

$io->section('Options');

Check warning on line 74 in src/Command/InfoCommand.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.2-ubuntu-latest

Escaped Mutant for Mutator "MethodCallRemoval": --- Original +++ New @@ @@ $sourceDirectory = $settings->options()->sourceDirectory(); $mergePlanFilePath = $settings->path() . '/' . (empty($sourceDirectory) ? '' : $sourceDirectory . '/') . $options->mergePlanFile(); $io->title('Yii Config — Root Configuration'); - $io->section('Options'); + $io->table([], [['Build merge plan', $options->buildMergePlan() ? '<fg=green>yes</>' : '<fg=red>no</>'], ['Merge plan file path', file_exists($mergePlanFilePath) ? '<fg=green>' . $mergePlanFilePath . '</>' : '<fg=red>' . $mergePlanFilePath . ' (not exists)</>'], ['Package types', empty($options->packageTypes()) ? '<fg=red>not set</>' : implode(', ', $options->packageTypes())], ['Source directory', $settings->path() . '/' . $options->sourceDirectory()], ['Vendor override layer packages', empty($options->vendorOverrideLayerPackages()) ? '<fg=gray>not set</>' : implode(', ', $options->vendorOverrideLayerPackages())]]); $io->section('Configuration groups'); $this->writeConfiguration($io, $settings->packageConfiguration());
$io->table([], [
[
'Build merge plan',
$options->buildMergePlan() ? '<fg=green>yes</>' : '<fg=red>no</>',
],
[
'Merge plan file path',
file_exists($mergePlanFilePath)

Check warning on line 82 in src/Command/InfoCommand.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.2-ubuntu-latest

Escaped Mutant for Mutator "Ternary": --- Original +++ New @@ @@ $mergePlanFilePath = $settings->path() . '/' . (empty($sourceDirectory) ? '' : $sourceDirectory . '/') . $options->mergePlanFile(); $io->title('Yii Config — Root Configuration'); $io->section('Options'); - $io->table([], [['Build merge plan', $options->buildMergePlan() ? '<fg=green>yes</>' : '<fg=red>no</>'], ['Merge plan file path', file_exists($mergePlanFilePath) ? '<fg=green>' . $mergePlanFilePath . '</>' : '<fg=red>' . $mergePlanFilePath . ' (not exists)</>'], ['Package types', empty($options->packageTypes()) ? '<fg=red>not set</>' : implode(', ', $options->packageTypes())], ['Source directory', $settings->path() . '/' . $options->sourceDirectory()], ['Vendor override layer packages', empty($options->vendorOverrideLayerPackages()) ? '<fg=gray>not set</>' : implode(', ', $options->vendorOverrideLayerPackages())]]); + $io->table([], [['Build merge plan', $options->buildMergePlan() ? '<fg=green>yes</>' : '<fg=red>no</>'], ['Merge plan file path', file_exists($mergePlanFilePath) ? '<fg=red>' . $mergePlanFilePath . ' (not exists)</>' : '<fg=green>' . $mergePlanFilePath . '</>'], ['Package types', empty($options->packageTypes()) ? '<fg=red>not set</>' : implode(', ', $options->packageTypes())], ['Source directory', $settings->path() . '/' . $options->sourceDirectory()], ['Vendor override layer packages', empty($options->vendorOverrideLayerPackages()) ? '<fg=gray>not set</>' : implode(', ', $options->vendorOverrideLayerPackages())]]); $io->section('Configuration groups'); $this->writeConfiguration($io, $settings->packageConfiguration()); $io->section('Environments');
? '<fg=green>' . $mergePlanFilePath . '</>'
: '<fg=red>' . $mergePlanFilePath . ' (not exists)</>',
],
[
'Package types',
empty($options->packageTypes()) ? '<fg=red>not set</>' : implode(', ', $options->packageTypes()),
],
[
'Source directory',
$settings->path() . '/' . $options->sourceDirectory(),
],
[
'Vendor override layer packages',
empty($options->vendorOverrideLayerPackages())
? '<fg=gray>not set</>'
: implode(', ', $options->vendorOverrideLayerPackages()),
],
]);

$io->section('Configuration groups');
$this->writeConfiguration($io, $settings->packageConfiguration());

$io->section('Environments');
$environmentsConfiguration = $settings->environmentsConfiguration();
if (empty($environmentsConfiguration)) {
$io->writeln('<fg=gray>not set</>');
} else {
$isFirst = true;
foreach ($environmentsConfiguration as $environment => $groups) {
if ($isFirst) {
$isFirst = false;
} else {
$io->newLine();
}
$io->write(' <fg=bright-magenta>' . $environment . '</>');
if (empty($groups)) {
$io->writeln(' <fg=gray>(empty)</>');
} else {
$io->newLine();
$this->writeConfiguration($io, $groups, offset: 2, addSeparateLine: false);
}
}
}

return 0;

Check warning on line 127 in src/Command/InfoCommand.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.2-ubuntu-latest

Escaped Mutant for Mutator "DecrementInteger": --- Original +++ New @@ @@ } } } - return 0; + return -1; } /** * @psalm-param array<string, string|string[]> $configuration
}

/**
* @psalm-param array<string, string|string[]> $configuration
*/
private function writeConfiguration(
SymfonyStyle $io,
array $configuration,
int $offset = 1,
bool $addSeparateLine = true,
): void {
foreach ($configuration as $group => $values) {
$this->writeGroup($io, $group, $values, $offset);
if ($addSeparateLine) {
$io->newLine();
}
}
}

/**
* @param string|string[] $items
*/
private function writeGroup(SymfonyStyle $io, string $group, array|string $items, int $offset): void
{
$prefix = str_repeat(' ', $offset);
$items = (array) $items;
$io->write($prefix . '<fg=cyan>' . $group . '</>');

Check warning on line 154 in src/Command/InfoCommand.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.2-ubuntu-latest

Escaped Mutant for Mutator "Concat": --- Original +++ New @@ @@ { $prefix = str_repeat(' ', $offset); $items = (array) $items; - $io->write($prefix . '<fg=cyan>' . $group . '</>'); + $io->write($prefix . $group . '<fg=cyan>' . '</>'); if (empty($items)) { $io->write(' <fg=gray>(empty)</>'); } else {
if (empty($items)) {
$io->write(' <fg=gray>(empty)</>');
} else {
foreach ($items as $item) {
$io->newLine();

Check warning on line 159 in src/Command/InfoCommand.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.2-ubuntu-latest

Escaped Mutant for Mutator "MethodCallRemoval": --- Original +++ New @@ @@ $io->write(' <fg=gray>(empty)</>'); } else { foreach ($items as $item) { - $io->newLine(); + $io->write($prefix . ' - ' . (Options::isVariable($item) ? '<fg=green>' . $item . '</>' : $item)); } }
$io->write($prefix . ' - ' . (Options::isVariable($item) ? '<fg=green>' . $item . '</>' : $item));

Check warning on line 160 in src/Command/InfoCommand.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.2-ubuntu-latest

Escaped Mutant for Mutator "Concat": --- Original +++ New @@ @@ } else { foreach ($items as $item) { $io->newLine(); - $io->write($prefix . ' - ' . (Options::isVariable($item) ? '<fg=green>' . $item . '</>' : $item)); + $io->write($prefix . ' - ' . (Options::isVariable($item) ? '<fg=green>' . '</>' . $item : $item)); } } $io->newLine(); } }
}
}
$io->newLine();

Check warning on line 163 in src/Command/InfoCommand.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.2-ubuntu-latest

Escaped Mutant for Mutator "MethodCallRemoval": --- Original +++ New @@ @@ $io->write($prefix . ' - ' . (Options::isVariable($item) ? '<fg=green>' . $item . '</>' : $item)); } } - $io->newLine(); + } }
}
}
6 changes: 1 addition & 5 deletions src/Command/RebuildCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,7 @@

protected function execute(InputInterface $input, OutputInterface $output): int
{
/**
* @psalm-suppress PossiblyNullArgument
* @psalm-suppress DeprecatedMethod
*/
new MergePlanProcess($this->getComposer());
new MergePlanProcess($this->requireComposer());
return 0;

Check warning on line 29 in src/Command/RebuildCommand.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.2-ubuntu-latest

Escaped Mutant for Mutator "DecrementInteger": --- Original +++ New @@ @@ protected function execute(InputInterface $input, OutputInterface $output) : int { new MergePlanProcess($this->requireComposer()); - return 0; + return -1; } }

Check warning on line 29 in src/Command/RebuildCommand.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.2-ubuntu-latest

Escaped Mutant for Mutator "IncrementInteger": --- Original +++ New @@ @@ protected function execute(InputInterface $input, OutputInterface $output) : int { new MergePlanProcess($this->requireComposer()); - return 0; + return 1; } }
}
}
26 changes: 24 additions & 2 deletions src/Composer/Options.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Yiisoft\Config\Composer;

use function is_array;
use function is_string;
use function str_replace;
use function trim;

Expand All @@ -23,8 +24,17 @@ final class Options

private string $mergePlanFile = self::DEFAULT_MERGE_PLAN_FILE;
private bool $buildMergePlan = true;

/**
* @var string[]
*/
private array $vendorOverrideLayerPackages = [];

private string $sourceDirectory = self::DEFAULT_CONFIG_DIRECTORY;

/**
* @var string[]
*/
private array $packageTypes = self::DEFAULT_PACKAGE_TYPES;

public function __construct(array $extra)
Expand All @@ -44,15 +54,21 @@ public function __construct(array $extra)
}

if (isset($options['vendor-override-layer'])) {
$this->vendorOverrideLayerPackages = (array) $options['vendor-override-layer'];
$this->vendorOverrideLayerPackages = array_filter(
(array) $options['vendor-override-layer'],
static fn(mixed $value): bool => is_string($value),
);
}

if (isset($options['source-directory'])) {
$this->sourceDirectory = $this->normalizePath((string) $options['source-directory']);
}

if (isset($options['package-types'])) {
$this->packageTypes = (array) $options['package-types'];
$this->packageTypes = array_filter(
(array) $options['package-types'],
static fn(mixed $value): bool => is_string($value),
);
}
}

Expand Down Expand Up @@ -81,6 +97,9 @@ public function buildMergePlan(): bool
return $this->buildMergePlan;
}

/**
* @return string[]
*/
public function vendorOverrideLayerPackages(): array
{
return $this->vendorOverrideLayerPackages;
Expand All @@ -91,6 +110,9 @@ public function sourceDirectory(): string
return $this->sourceDirectory;
}

/**
* @return string[]
*/
public function packageTypes(): array
{
return $this->packageTypes;
Expand Down
5 changes: 0 additions & 5 deletions src/Composer/ProcessHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
use Yiisoft\Config\ConfigPaths;
use Yiisoft\Strings\WildcardPattern;

use function is_string;
use function str_replace;

/**
Expand Down Expand Up @@ -202,10 +201,6 @@ private function getPackageRootDirectoryPath(PackageInterface $package): string
private function isVendorOverridePackage(string $package): bool
{
foreach ($this->appConfigSettings->options()->vendorOverrideLayerPackages() as $pattern) {
if (!is_string($pattern)) {
continue;
}

if ($package === $pattern || (new WildcardPattern($pattern))->match($package)) {
return true;
}
Expand Down
6 changes: 5 additions & 1 deletion tests/Command/ConfigCommandProviderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Symfony\Component\Console\Command\Command;
use Yiisoft\Config\Command\ConfigCommandProvider;
use Yiisoft\Config\Command\CopyCommand;
use Yiisoft\Config\Command\InfoCommand;
use Yiisoft\Config\Command\RebuildCommand;

final class ConfigCommandProviderTest extends TestCase
Expand All @@ -17,12 +18,15 @@ public function testGetCommands(): void
{
$provider = new ConfigCommandProvider();

$this->assertCount(2, $provider->getCommands());
$this->assertCount(3, $provider->getCommands());
$this->assertInstanceOf(BaseCommand::class, $provider->getCommands()[0]);
$this->assertInstanceOf(BaseCommand::class, $provider->getCommands()[1]);
$this->assertInstanceOf(BaseCommand::class, $provider->getCommands()[2]);
$this->assertInstanceOf(Command::class, $provider->getCommands()[0]);
$this->assertInstanceOf(Command::class, $provider->getCommands()[1]);
$this->assertInstanceOf(Command::class, $provider->getCommands()[2]);
$this->assertEquals($provider->getCommands()[0], new CopyCommand());
$this->assertEquals($provider->getCommands()[1], new RebuildCommand());
$this->assertEquals($provider->getCommands()[2], new InfoCommand());
}
}
Loading
Loading