Skip to content

Commit 93340c8

Browse files
committed
feature #43644 [FrameworkBundle] Add completion to debug:translation command (alexandre-daubois)
This PR was merged into the 5.4 branch. Discussion ---------- [FrameworkBundle] Add completion to debug:translation command | Q | A | ------------- | --- | Branch? | 5.4 | Bug fix? | no | New feature? | yes | Deprecations? | no | Tickets | Part of #43594 | License | MIT | Doc PR | _NA_ Commits ------- 086a8b473f [Console] Add completion to debug:translation command
2 parents a9c9a15 + aa37f0e commit 93340c8

File tree

3 files changed

+140
-23
lines changed

3 files changed

+140
-23
lines changed

Command/TranslationDebugCommand.php

Lines changed: 66 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
namespace Symfony\Bundle\FrameworkBundle\Command;
1313

1414
use Symfony\Component\Console\Command\Command;
15+
use Symfony\Component\Console\Completion\CompletionInput;
16+
use Symfony\Component\Console\Completion\CompletionSuggestions;
1517
use Symfony\Component\Console\Exception\InvalidArgumentException;
1618
use Symfony\Component\Console\Input\InputArgument;
1719
use Symfony\Component\Console\Input\InputInterface;
@@ -56,8 +58,9 @@ class TranslationDebugCommand extends Command
5658
private $defaultViewsPath;
5759
private $transPaths;
5860
private $codePaths;
61+
private $enabledLocales;
5962

60-
public function __construct(TranslatorInterface $translator, TranslationReaderInterface $reader, ExtractorInterface $extractor, string $defaultTransPath = null, string $defaultViewsPath = null, array $transPaths = [], array $codePaths = [])
63+
public function __construct(TranslatorInterface $translator, TranslationReaderInterface $reader, ExtractorInterface $extractor, string $defaultTransPath = null, string $defaultViewsPath = null, array $transPaths = [], array $codePaths = [], array $enabledLocales = [])
6164
{
6265
parent::__construct();
6366

@@ -68,6 +71,7 @@ public function __construct(TranslatorInterface $translator, TranslationReaderIn
6871
$this->defaultViewsPath = $defaultViewsPath;
6972
$this->transPaths = $transPaths;
7073
$this->codePaths = $codePaths;
74+
$this->enabledLocales = $enabledLocales;
7175
}
7276

7377
/**
@@ -135,15 +139,8 @@ protected function execute(InputInterface $input, OutputInterface $output): int
135139
$kernel = $this->getApplication()->getKernel();
136140

137141
// Define Root Paths
138-
$transPaths = $this->transPaths;
139-
if ($this->defaultTransPath) {
140-
$transPaths[] = $this->defaultTransPath;
141-
}
142-
$codePaths = $this->codePaths;
143-
$codePaths[] = $kernel->getProjectDir().'/src';
144-
if ($this->defaultViewsPath) {
145-
$codePaths[] = $this->defaultViewsPath;
146-
}
142+
$transPaths = $this->getRootTransPaths();
143+
$codePaths = $this->getRootCodePaths($kernel);
147144

148145
// Override with provided Bundle info
149146
if (null !== $input->getArgument('bundle')) {
@@ -259,6 +256,44 @@ protected function execute(InputInterface $input, OutputInterface $output): int
259256
return $exitCode;
260257
}
261258

259+
public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
260+
{
261+
if ($input->mustSuggestArgumentValuesFor('locale')) {
262+
$suggestions->suggestValues($this->enabledLocales);
263+
264+
return;
265+
}
266+
267+
/** @var KernelInterface $kernel */
268+
$kernel = $this->getApplication()->getKernel();
269+
270+
if ($input->mustSuggestArgumentValuesFor('bundle')) {
271+
$availableBundles = [];
272+
foreach ($kernel->getBundles() as $bundle) {
273+
$availableBundles[] = $bundle->getName();
274+
275+
if ($extension = $bundle->getContainerExtension()) {
276+
$availableBundles[] = $extension->getAlias();
277+
}
278+
}
279+
280+
$suggestions->suggestValues($availableBundles);
281+
282+
return;
283+
}
284+
285+
if ($input->mustSuggestOptionValuesFor('domain')) {
286+
$locale = $input->getArgument('locale');
287+
288+
$mergeOperation = new MergeOperation(
289+
$this->extractMessages($locale, $this->getRootCodePaths($kernel)),
290+
$this->loadCurrentMessages($locale, $this->getRootTransPaths())
291+
);
292+
293+
$suggestions->suggestValues($mergeOperation->getDomains());
294+
}
295+
}
296+
262297
private function formatState(int $state): string
263298
{
264299
if (self::MESSAGE_MISSING === $state) {
@@ -354,4 +389,25 @@ private function loadFallbackCatalogues(string $locale, array $transPaths): arra
354389

355390
return $fallbackCatalogues;
356391
}
392+
393+
private function getRootTransPaths(): array
394+
{
395+
$transPaths = $this->transPaths;
396+
if ($this->defaultTransPath) {
397+
$transPaths[] = $this->defaultTransPath;
398+
}
399+
400+
return $transPaths;
401+
}
402+
403+
private function getRootCodePaths(KernelInterface $kernel): array
404+
{
405+
$codePaths = $this->codePaths;
406+
$codePaths[] = $kernel->getProjectDir().'/src';
407+
if ($this->defaultViewsPath) {
408+
$codePaths[] = $this->defaultViewsPath;
409+
}
410+
411+
return $codePaths;
412+
}
357413
}

Resources/config/console.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@
221221
null, // twig.default_path
222222
[], // Translator paths
223223
[], // Twig paths
224+
param('kernel.enabled_locales'),
224225
])
225226
->tag('console.command')
226227

Tests/Command/TranslationDebugCommandTest.php

Lines changed: 73 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
use PHPUnit\Framework\TestCase;
1515
use Symfony\Bundle\FrameworkBundle\Command\TranslationDebugCommand;
1616
use Symfony\Bundle\FrameworkBundle\Console\Application;
17+
use Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\ExtensionWithoutConfigTestBundle\ExtensionWithoutConfigTestBundle;
18+
use Symfony\Component\Console\Tester\CommandCompletionTester;
1719
use Symfony\Component\Console\Tester\CommandTester;
1820
use Symfony\Component\DependencyInjection\Container;
1921
use Symfony\Component\Filesystem\Filesystem;
@@ -139,23 +141,30 @@ protected function tearDown(): void
139141
$this->fs->remove($this->translationDir);
140142
}
141143

142-
private function createCommandTester($extractedMessages = [], $loadedMessages = [], $kernel = null, array $transPaths = [], array $codePaths = []): CommandTester
144+
private function createCommandTester(array $extractedMessages = [], array $loadedMessages = [], KernelInterface $kernel = null, array $transPaths = [], array $codePaths = []): CommandTester
145+
{
146+
return new CommandTester($this->createCommand($extractedMessages, $loadedMessages, $kernel, $transPaths, $codePaths));
147+
}
148+
149+
private function createCommand(array $extractedMessages = [], array $loadedMessages = [], KernelInterface $kernel = null, array $transPaths = [], array $codePaths = [], ExtractorInterface $extractor = null, array $bundles = [], array $enabledLocales = []): TranslationDebugCommand
143150
{
144151
$translator = $this->createMock(Translator::class);
145152
$translator
146153
->expects($this->any())
147154
->method('getFallbackLocales')
148155
->willReturn(['en']);
149156

150-
$extractor = $this->createMock(ExtractorInterface::class);
151-
$extractor
152-
->expects($this->any())
153-
->method('extract')
154-
->willReturnCallback(
155-
function ($path, $catalogue) use ($extractedMessages) {
156-
$catalogue->add($extractedMessages);
157-
}
158-
);
157+
if (!$extractor) {
158+
$extractor = $this->createMock(ExtractorInterface::class);
159+
$extractor
160+
->expects($this->any())
161+
->method('extract')
162+
->willReturnCallback(
163+
function ($path, $catalogue) use ($extractedMessages) {
164+
$catalogue->add($extractedMessages);
165+
}
166+
);
167+
}
159168

160169
$loader = $this->createMock(TranslationReader::class);
161170
$loader
@@ -182,20 +191,20 @@ function ($path, $catalogue) use ($loadedMessages) {
182191
$kernel
183192
->expects($this->any())
184193
->method('getBundles')
185-
->willReturn([]);
194+
->willReturn($bundles);
186195

187196
$container = new Container();
188197
$kernel
189198
->expects($this->any())
190199
->method('getContainer')
191200
->willReturn($container);
192201

193-
$command = new TranslationDebugCommand($translator, $loader, $extractor, $this->translationDir.'/translations', $this->translationDir.'/templates', $transPaths, $codePaths);
202+
$command = new TranslationDebugCommand($translator, $loader, $extractor, $this->translationDir.'/translations', $this->translationDir.'/templates', $transPaths, $codePaths, $enabledLocales);
194203

195204
$application = new Application($kernel);
196205
$application->add($command);
197206

198-
return new CommandTester($application->find('debug:translation'));
207+
return $application->find('debug:translation');
199208
}
200209

201210
private function getBundle($path)
@@ -209,4 +218,55 @@ private function getBundle($path)
209218

210219
return $bundle;
211220
}
221+
222+
/**
223+
* @dataProvider provideCompletionSuggestions
224+
*/
225+
public function testComplete(array $input, array $expectedSuggestions)
226+
{
227+
$extractedMessagesWithDomains = [
228+
'messages' => [
229+
'foo' => 'foo',
230+
],
231+
'validators' => [
232+
'foo' => 'foo',
233+
],
234+
'custom_domain' => [
235+
'foo' => 'foo',
236+
],
237+
];
238+
$extractor = $this->createMock(ExtractorInterface::class);
239+
$extractor
240+
->expects($this->any())
241+
->method('extract')
242+
->willReturnCallback(
243+
function ($path, $catalogue) use ($extractedMessagesWithDomains) {
244+
foreach ($extractedMessagesWithDomains as $domain => $message) {
245+
$catalogue->add($message, $domain);
246+
}
247+
}
248+
);
249+
250+
$tester = new CommandCompletionTester($this->createCommand([], [], null, [], [], $extractor, [new ExtensionWithoutConfigTestBundle()], ['fr', 'nl']));
251+
$suggestions = $tester->complete($input);
252+
$this->assertSame($expectedSuggestions, $suggestions);
253+
}
254+
255+
public function provideCompletionSuggestions()
256+
{
257+
yield 'locale' => [
258+
[''],
259+
['fr', 'nl'],
260+
];
261+
262+
yield 'bundle' => [
263+
['fr', '--domain', 'messages', ''],
264+
['ExtensionWithoutConfigTestBundle', 'extension_without_config_test'],
265+
];
266+
267+
yield 'option --domain' => [
268+
['en', '--domain', ''],
269+
['messages', 'validators', 'custom_domain'],
270+
];
271+
}
212272
}

0 commit comments

Comments
 (0)