8000 feature #58141 [AssetMapper] Search & filter assets in `debug:asset-m… · symfony/symfony@1b13c33 · GitHub
[go: up one dir, main page]

Skip to content

Commit 1b13c33

Browse files
committed
feature #58141 [AssetMapper] Search & filter assets in debug:asset-mapper command (smnandre)
This PR was squashed before being merged into the 7.2 branch. Discussion ---------- [AssetMapper] Search & filter assets in `debug:asset-mapper` command | Q | A | ------------- | --- | Branch? | 7.2 | Bug fix? | no | New feature? | yes | Deprecations? | no | Issues | Fix #... | License | MIT * Add `name` optional argument to filter paths & assets * Add `--ext` option to filter assets by extension (e.g "css") * Add `--vendor` option to only show assets from vendor packages (and `--no-vendor` to hide them) * Update command help Update: ~~* skip flappy test using chmod on Windows~~ (done by `@xabbuh` in #58152) Commits ------- 8806e24 [AssetMapper] Search & filter assets in `debug:asset-mapper` command
2 parents 464dd4b + 8806e24 commit 1b13c33

File tree

2 files changed

+150
-24
lines changed

2 files changed

+150
-24
lines changed

src/Symfony/Component/AssetMapper/Command/DebugAssetMapperCommand.php

Lines changed: 97 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@
1515
use Symfony\Component\AssetMapper\AssetMapperRepository;
1616
use Symfony\Component\Console\Attribute\AsCommand;
1717
use Symfony\Component\Console\Command\Command;
18+
use Symfony\Component\Console\Input\InputArgument;
1819
use Symfony\Component\Console\Input\InputInterface;
20+
use Symfony\Component\Console\Input\InputOption;
1921
use Symfony\Component\Console\Output\OutputInterface;
2022
use Symfony\Component\Console\Style\SymfonyStyle;
2123

@@ -40,10 +42,41 @@ public function __construct(
4042
protected function configure(): void
4143
{
4244
$this
45+
->addArgument('name', InputArgument::OPTIONAL, 'An asset name (or a path) to search for (e.g. "app")')
46+
->addOption('ext', null, InputOption::VALUE_REQUIRED, 'Filter assets by extension (e.g. "css")', null, ['js', 'css', 'png'])
4347
->addOption('full', null, null, 'Whether to show the full paths')
48+
->addOption('vendor', null, InputOption::VALUE_NEGATABLE, 'Only show assets from vendor packages')
4449
->setHelp(<<<'EOT'
45-
The <info>%command.name%</info> command outputs all of the assets in
46-
asset mapper for debugging purposes.
50+
The <info>%command.name%</info> command displays information about the Asset
51+
Mapper for debugging purposes.
52+
53+
To list all configured paths (with local paths and their namespace prefixes) and
54+
all mapped assets (with their logical path and filesystem path), run:
55+
56+
<info>php %command.full_name%</info>
57+
58+
You can filter the results by providing a name to search for in the asset name
59+
or path:
60+
61+
<info>php %command.full_name% bootstrap.js</info>
62+
<info>php %command.full_name% style/</info>
63+
64+
To filter the assets by extension, use the <info>--ext</info> option:
65+
66+
<info>php %command.full_name% --ex 8000 t=css</info>
67+
68+
To show only assets from vendor packages, use the <info>--vendor</info> option:
69+
70+
<info>php %command.full_name% --vendor</info>
71+
72+
To exclude assets from vendor packages, use the <info>--no-vendor</info> option:
73+
74+
<info>php %command.full_name% --no-vendor</info>
75+
76+
To see the full paths, use the <info>--full</info> option:
77+
78+
<info>php %command.full_name% --full</info>
79+
4780
EOT
4881
);
4982
}
@@ -52,43 +85,83 @@ protected function execute(InputInterface $input, OutputInterface $output): int
5285
{
5386
$io = new SymfonyStyle($input, $output);
5487

55-
$allAssets = $this->assetMapper->allAssets();
88+
$name = $input->getArgument('name');
89+
$extensionFilter = $input->getOption('ext');
90+
$vendorFilter = $input->getOption('vendor');
91+
92+
if (!$extensionFilter) {
93+
$io->section($name ? 'Matched Paths' : 'Asset Mapper Paths');
94+
$pathRows = [];
95+
foreach ($this->assetMapperRepository->allDirectories() as $path => $namespace) {
96+
$path = $this->relativizePath($path);
97+
if (!$input->getOption('full')) {
98+
$path = $this->shortenPath($path);
99+
}
100+
if ($name && !str_contains($path, $name) && !str_contains($namespace, $name)) {
101+
continue;
102+
}
103+
$pathRows[] = [$path, $namespace];
104+
}
105+
uasort($pathRows, static function (array $a, array $b): int {
106+
return [(bool) $a[1], ...$a] <=> [(bool) $b[1], ...$b];
107+
});
108+
if ($pathRows) {
109+
$io->table(['Path', 'Namespace prefix'], $pathRows);
110+
} else {
111+
$io->warning('No paths found.');
112+
}
113+
}
56114

57-
$pathRows = [];
58-
foreach ($this->assetMapperRepository->allDirectories() as $path => $namespace) {
59-
$path = $this->relativizePath($path);
115+
$io->section($name ? 'Matched Assets' : 'Mapped Assets');
116+
$rows = $this->searchAssets($name, $extensionFilter, $vendorFilter);
117+
if ($rows) {
60118
if (!$input->getOption('full')) {
61-
$path = $this->shortenPath($path);
119+
$rows = array_map(fn (array $row): array => [
120+
$this->shortenPath($row[0]),
121+
$this->shortenPath($row[1]),
122+
], $rows);
62123
}
63-
64-
$pathRows[] = [$path, $namespace];
124+
uasort($rows, static function (array $a, array $b): int {
125+
return [$a] <=> [$b];
126+
});
127+
$io->table(['Logical Path', 'Filesystem Path'], $rows);
128+
if ($this->didShortenPaths) {
129+
$io->note('To see the full paths, re-run with the --full option.');
130+
}
131+
} else {
132+
$io->warning('No assets found.');
65133
}
66-
$io->section('Asset Mapper Paths');
67-
$io->table(['Path', 'Namespace prefix'], $pathRows);
68134

135+
return 0;
136+
}
137+
138+
/**
139+
* @return list<array{0:string, 1:string}>
140+
*/
141+
private function searchAssets(?string $name, ?string $extension, ?bool $vendor): array
142+
{
69143
$rows = [];
70-
foreach ($allAssets as $asset) {
144+
foreach ($this->assetMapper->allAssets() as $asset) {
145+
if ($extension && $extension !== $asset->publicExtension) {
146+
continue;
147+
}
148+
if (null !== $vendor && $vendor !== $asset->isVendor) {
149+
continue;
150+
}
151+
if ($name && !str_contains($asset->logicalPath, $name) && !str_contains($asset->sourcePath, $name)) {
152+
continue;
153+
}
154+
71155
$logicalPath = $asset->logicalPath;
72156
$sourcePath = $this->relativizePath($asset->sourcePath);
73157

74-
if (!$input->getOption('full')) {
75-
$logicalPath = $this->shortenPath($logicalPath);
76-
$sourcePath = $this->shortenPath($sourcePath);
77-
}
78-
79158
$rows[] = [
80159
$logicalPath,
81160
$sourcePath,
82161
];
83162
}
84-
$io->section('Mapped Assets');
85-
$io->table(['Logical Path', 'Filesystem Path'], $rows);
86-
87-
if ($this->didShortenPaths) {
88-
$io->note('To see the full paths, re-run with the --full option.');
89-
}
90163

91-
return 0;
164+
return $rows;
92165
}
93166

94167
private function relativizePath(string $path): string

src/Symfony/Component/AssetMapper/Tests/Command/DebugAssetsMapperCommandTest.php

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,57 @@ public function testCommandDumpsInformation()
3131
$this->assertStringContainsString('subdir/file6.js', $tester->getDisplay());
3232
$this->assertStringContainsString('dir2'.\DIRECTORY_SEPARATOR.'subdir'.\DIRECTORY_SEPARATOR.'file6.js', $tester->getDisplay());
3333
}
34+
35+
public function testCommandFiltersName()
36+
{
37+
$application = new Application(new AssetMapperTestAppKernel('test', true));
38+
$command = $application->find('debug:asset-map');
39+
$tester = new CommandTester($command);
40+
$res = $tester->execute(['name' => 'stimulus']);
41+
42+
$this->assertSame(0, $res);
43+
$this->assertStringContainsString('stimulus', $tester->getDisplay());
44+
$this->assertStringNotContainsString('lodash', $tester->getDisplay());
45+
46+
$res = $tester->execute(['name' => 'lodash']);
47+
$this->assertSame(0, $res);
48+
$this->assertStringNotContainsString('stimulus', $tester->getDisplay());
49+
$this->assertStringContainsString('lodash', $tester->getDisplay());
50+
}
51+
52+
public function testCommandFiltersExtension()
53+
{
54+
$application = new Application(new AssetMapperTestAppKernel('test', true));
55+
$command = $application->find('debug:asset-map');
56+
$tester = new CommandTester($command);
57+
$res = $tester->execute(['--ext' => 'css']);
58+
59+
$this->assertSame(0, $res);
60+
$this->assertStringNotContainsString('.js', $tester->getDisplay());
61+
62+
$this->assertStringContainsString('file1.css', $tester->getDisplay());
63+
$this->assertStringContainsString('file3.css', $tester->getDisplay());
64+
}
65+
66+
public function testCommandFiltersVendor()
67+
{
68+
$application = new Application(new AssetMapperTestAppKernel('test', true));
69+
$command = $application->find('debug:asset-map');
70+
71+
$tester = new CommandTester($command);
72+
$res = $tester->execute(['--vendor' => true]);
73+
74+
$this->assertSame(0, $res);
75+
$this->assertStringContainsString('vendor/lodash/', $tester->getDisplay());
76+
$this->assertStringContainsString('@hotwired/stimulus', $tester->getDisplay());
77+
$this->assertStringNotContainsString('dir2'.\DIRECTORY_SEPARATOR, $tester->getDisplay());
78+
79+
$tester = new CommandTester($command);
80+
$res = $tester->execute(['--no-vendor' => true]);
81+
82+
$this->assertSame(0, $res);
83+
$this->assertStringNotContainsString('vendor/lodash/', $tester->getDisplay());
84+
$this->assertStringNotContainsString('@hotwired/stimulus', $tester->getDisplay());
85+
$this->assertStringContainsString('dir2'.\DIRECTORY_SEPARATOR, $tester->getDisplay());
86+
}
3487
}

0 commit comments

Comments
 (0)
0