8000 [Console] Add completion to debug:translation command · symfony/symfony@1529f97 · GitHub
[go: up one dir, main page]

Skip to content

Commit 1529f97

Browse files
[Console] Add completion to debug:translation command
1 parent 0dc7fa1 commit 1529f97

File tree

3 files changed

+136
-23
lines changed

3 files changed

+136
-23
lines changed

src/Symfony/Bundle/FrameworkBundle/Command/TranslationDebugCommand.php

Lines changed: 61 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,17 @@
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;
1820
use Symfony\Component\Console\Input\InputOption;
1921
use Symfony\Component\Console\Output\OutputInterface;
2022
use Symfony\Component\Console\Style\SymfonyStyle;
23+
use Symfony\Component\HttpKernel\Bundle\BundleInterface;
2124
use Symfony\Component\HttpKernel\KernelInterface;
25+
use Symfony\Component\Intl\Locales;
2226
use Symfony\Component\Translation\Catalogue\MergeOperation;
2327
use Symfony\Component\Translation\DataCollectorTranslator;
2428
use Symfony\Component\Translation\Extractor\ExtractorInterface;
@@ -56,8 +60,9 @@ class TranslationDebugCommand extends Command
5660
private $defaultViewsPath;
5761
private $transPaths;
5862
private $codePaths;
63+
private $enabledLocales;
5964

60-
public function __construct(TranslatorInterface $translator, TranslationReaderInterface $reader, ExtractorInterface $extractor, string $defaultTransPath = null, string $defaultViewsPath = null, array $transPaths = [], array $codePaths = [])
65+
public function __construct(TranslatorInterface $translator, TranslationReaderInterface $reader, ExtractorInterface $extractor, string $defaultTransPath = null, string $defaultViewsPath = null, array $transPaths = [], array $codePaths = [], array $enabledLocales = [])
6166
{
6267
parent::__construct();
6368

@@ -68,6 +73,7 @@ public function __construct(TranslatorInterface $translator, TranslationReaderIn
6873
$this->defaultViewsPath = $defaultViewsPath;
6974
$this->transPaths = $transPaths;
7075
$this->codePaths = $codePaths;
76+
$this->enabledLocales = $enabledLocales;
7177
}
7278

7379
/**
@@ -135,15 +141,8 @@ protected function execute(InputInterface $input, OutputInterface $output): int
135141
$kernel = $this->getApplication()->getKernel();
136142

137143
// 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-
}
144+
$transPaths = $this->getRootTransPaths();
145+
$codePaths = $this->getRootCodePaths($kernel);
147146

148147
// Override with provided Bundle info
149148
if (null !== $input->getArgument('bundle')) {
@@ -259,6 +258,37 @@ protected function execute(InputInterface $input, OutputInterface $output): int
259258
return $exitCode;
260259
}
261260

261+
public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
262+
{
263+
if ($input->mustSuggestArgumentValuesFor('locale')) {
264+
$suggestions->suggestValues($this->enabledLocales);
265+
266+
return;
267+
}
268+
269+
/** @var KernelInterface $kernel */
270+
$kernel = $this->getApplication()->getKernel();
271+
272+
if ($input->mustSuggestArgumentValuesFor('bundle')) {
273+
$suggestions->suggestValues(array_map(function (BundleInterface $bundle) {
274+
return $bundle->getName();
275+
}, $kernel->getBundles()));
276+
277+
return;
278+
}
279+
280+
if ($input->mustSuggestOptionValuesFor('domain')) {
281+
$locale = $input->getArgument('locale');
282+
283+
$mergeOperation = new MergeOperation(
284+
$this->extractMessages($locale, $this->getRootCodePaths($kernel)),
285+
$this->loadCurrentMessages($locale, $this->getRootTransPaths())
286+
);
287+
288+
$suggestions->suggestValues($mergeOperation->getDomains());
289+
}
290+
}
291+
262292
private function formatState(int $state): string
263293
{
264294
if (self::MESSAGE_MISSING === $state) {
@@ -354,4 +384,25 @@ private function loadFallbackCatalogues(string $locale, array $transPaths): arra
354384

355385
return $fallbackCatalogues;
356386
}
387+
388+
private function getRootTransPaths(): array
389+
{
390+
$transPaths = $this->transPaths;
391+
if ($this->defaultTransPath) {
392+
$transPaths[] = $this->defaultTransPath;
393+
}
394+
395+
return $transPaths;
396+
}
397+
398+
private function getRootCodePaths(KernelInterface $kernel): array
399+
{
400+
$codePaths = $this->codePaths;
401+
$codePaths[] = $kernel->getProjectDir().'/src';
402+
if ($this->defaultViewsPath) {
403+
$codePaths[] = $this->defaultViewsPath;
404+
}
405+
406+
return $codePaths;
407+
}
357408
}

src/Symfony/Bundle/FrameworkBundle/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

src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationDebugCommandTest.php

Lines changed: 74 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,14 @@
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\Fixtures\BaseBundle\BaseBundle;
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;
2022
use Symfony\Component\HttpKernel\Bundle\BundleInterface;
2123
use Symfony\Component\HttpKernel\KernelInterface;
24+
use Symfony\Component\Intl\Locales;
2225
use Symfony\Component\Translation\Extractor\ExtractorInterface;
2326
use Symfony\Component\Translation\Reader\TranslationReader;
2427
use Symfony\Component\Translation\Translator;
@@ -139,23 +142,30 @@ protected function tearDown(): void
139142
$this->fs->remove($this->translationDir);
140143
}
141144

142-
private function createCommandTester($extractedMessages = [], $loadedMessages = [], $kernel = null, array $transPaths = [], array $codePaths = []): CommandTester
145+
private function createCommandTester(array $extractedMessages = [], array $loadedMessages = [], KernelInterface $kernel = null, array $transPaths = [], array $codePaths = []): CommandTester
146+
{
147+
return new CommandTester($this->createCommand($extractedMessages, $loadedMessages, $kernel, $transPaths, $codePaths));
148+
}
149+
150+
private function createCommand(array $extractedMessages = [], array $loadedMessages = [], KernelInterface $kernel = null, array $transPaths = [], array $codePaths = [], ExtractorInterface $extractor = null, array $bundles = [], array $enabledLocales = []): TranslationDebugCommand
143151
{
144152
$translator = $this->createMock(Translator::class);
145153
$translator
146154
->expects($this->any())
147155
->method('getFallbackLocales')
148156
->willReturn(['en']);
149157

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-
);
158+
if (!$extractor) {
159+
$extractor = $this->createMock(ExtractorInterface::class);
160+
$extractor
161+
->expects($this->any())
162+
->method('extract')
163+
->willReturnCallback(
164+
function ($path, $catalogue) use ($extractedMessages) {
165+
$catalogue->add($extractedMessages);
166+
}
167+
);
168+
}
159169

160170
$loader = $this->createMock(TranslationReader::class);
161171
$loader
@@ -182,20 +192,20 @@ function ($path, $catalogue) use ($loadedMessages) {
182192
$kernel
183193
->expects($this->any())
184194
->method('getBundles')
185-
->willReturn([]);
195+
->willReturn($bundles);
186196

187197
$container = new Container();
188198
$kernel
189199
->expects($this->any())
190200
->method('getContainer')
191201
->willReturn($container);
192202

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

195205
$application = new Application($kernel);
196206
$application->add($command);
197207

198-
return new CommandTester($application->find('debug:translation'));
208+
return $application->find('debug:translation');
199209
}
200210

201211
private function getBundle($path)
@@ -209,4 +219,55 @@ private function getBundle($path)
209219

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

0 commit comments

Comments
 (0)
0