diff --git a/Catalogue/CatalogueManager.php b/Catalogue/CatalogueManager.php index 8c9a3135..3d646ad3 100644 --- a/Catalogue/CatalogueManager.php +++ b/Catalogue/CatalogueManager.php @@ -82,6 +82,7 @@ public function findMessages(array $config = []): array $isNew = $config['isNew'] ?? null; $isObsolete = $config['isObsolete'] ?? null; $isApproved = $config['isApproved'] ?? null; + $isEmpty = $config['isEmpty'] ?? null; $messages = []; $catalogues = []; @@ -106,7 +107,7 @@ public function findMessages(array $config = []): array } } - $messages = \array_filter($messages, static function (CatalogueMessage $m) use ($isNew, $isObsolete, $isApproved) { + $messages = \array_filter($messages, static function (CatalogueMessage $m) use ($isNew, $isObsolete, $isApproved, $isEmpty) { if (null !== $isNew && $m->isNew() !== $isNew) { return false; } @@ -116,6 +117,9 @@ public function findMessages(array $config = []): array if (null !== $isApproved && $m->isApproved() !== $isApproved) { return false; } + if (null !== $isEmpty && empty($m->getMessage()) !== $isEmpty) { + return false; + } return true; }); diff --git a/Command/DeleteEmptyCommand.php b/Command/DeleteEmptyCommand.php new file mode 100644 index 00000000..67c4e97a --- /dev/null +++ b/Command/DeleteEmptyCommand.php @@ -0,0 +1,131 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Translation\Bundle\Command; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Helper\ProgressBar; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Question\ConfirmationQuestion; +use Translation\Bundle\Catalogue\CatalogueFetcher; +use Translation\Bundle\Catalogue\CatalogueManager; +use Translation\Bundle\Service\ConfigurationManager; +use Translation\Bundle\Service\StorageManager; + +/** + * @author Tobias Nyholm + */ +class DeleteEmptyCommand extends Command +{ + use BundleTrait; + use StorageTrait; + + protected static $defaultName = 'translation:delete-empty'; + + /** + * @var ConfigurationManager + */ + private $configurationManager; + + /** + * @var CatalogueManager + */ + private $catalogueManager; + + /** + * @var CatalogueFetcher + */ + private $catalogueFetcher; + + public function __construct( + StorageManager $storageManager, + ConfigurationManager $configurationManager, + CatalogueManager $catalogueManager, + CatalogueFetcher $catalogueFetcher + ) { + $this->storageManager = $storageManager; + $this->configurationManager = $configurationManager; + $this->catalogueManager = $catalogueManager; + $this->catalogueFetcher = $catalogueFetcher; + parent::__construct(); + } + + protected function configure(): void + { + $this + ->setName(self::$defaultName) + ->setDescription('Delete all translations currently empty.') + ->addArgument('configuration', InputArgument::OPTIONAL, 'The configuration to use', 'default') + ->addArgument('locale', InputArgument::OPTIONAL, 'The locale to use. If omitted, we use all configured locales.', null) + ->addOption('bundle', 'b', InputOption::VALUE_REQUIRED, 'The bundle you want remove translations from.') + ; + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + $configName = $input->getArgument('configuration'); + $locales = []; + if (null !== $inputLocale = $input->getArgument('locale')) { + $locales = [$inputLocale]; + } + + $config = $this->configurationManager->getConfiguration($configName); + $this->configureBundleDirs($input, $config); + $this->catalogueManager->load($this->catalogueFetcher->getCatalogues($config, $locales)); + + $storage = $this->getStorage($configName); + $messages = $this->catalogueManager->findMessages(['locale' => $inputLocale, 'isEmpty' => true]); + + $messageCount = \count($messages); + if (0 === $messageCount) { + $output->writeln('No messages are empty'); + + return 0; + } + + if ($input->isInteractive()) { + $helper = $this->getHelper('question'); + $question = new ConfirmationQuestion(\sprintf('You are about to remove %d translations. Do you wish to continue? (y/N) ', $messageCount), false); + if (!$helper->ask($input, $output, $question)) { + return 0; + } + } + + $progress = null; + if (OutputInterface::VERBOSITY_NORMAL === $output->getVerbosity() && OutputInterface::VERBOSITY_QUIET !== $output->getVerbosity()) { + $progress = new ProgressBar($output, $messageCount); + } + foreach ($messages as $message) { + $storage->delete($message->getLocale(), $message->getDomain(), $message->getKey()); + if ($output->getVerbosity() > OutputInterface::VERBOSITY_NORMAL) { + $output->writeln(\sprintf( + 'Deleted empty message "%s" from domain "%s" and locale "%s"', + $message->getKey(), + $message->getDomain(), + $message->getLocale() + )); + } + + if ($progress) { + $progress->advance(); + } + } + + if ($progress) { + $progress->finish(); + } + + return 0; + } +} diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index e0a36220..e26ad678 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1,5 +1,10 @@ parameters: ignoreErrors: + - + message: "#^Call to an undefined method Symfony\\\\Component\\\\Console\\\\Application\\:\\:getKernel\\(\\)\\.$#" + count: 1 + path: Command/DeleteEmptyCommand.php + - message: "#^Call to an undefined method Symfony\\\\Component\\\\Console\\\\Application\\:\\:getKernel\\(\\)\\.$#" count: 1