Completed
Pull Request — master (#1)
by Pascal
03:53 queued 20s
created

TranslationConverterCommand::configure()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 14
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 14
rs 9.4285
cc 1
eloc 11
nc 1
nop 0
1
<?php
2
3
namespace Itkg\TranslationBundle\Command;
4
5
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
6
use Symfony\Component\Console\Input\InputOption;
7
use Symfony\Component\Console\Input\InputInterface;
8
use Symfony\Component\Console\Output\OutputInterface;
9
use Symfony\Component\Filesystem\Filesystem;
10
use Symfony\Component\Finder\Finder;
11
use Symfony\Component\Translation\MessageCatalogue;
12
use Symfony\Component\Translation\Writer\TranslationWriter;
13
14
/**
15
 * Class TranslationConverterCommand
16
 */
17
class TranslationConverterCommand extends ContainerAwareCommand
18
{
19
    /**
20
     * @var Finder
21
     */
22
    protected $finder;
23
24
    /**
25
     * @var Filesystem
26
     */
27
    protected $filesystem;
28
29
    /**
30
     * @param Finder      $finder
31
     * @param Filesystem  $filesystem
32
     * @param null|string $name
33
     */
34
    public function __construct(Finder $finder, Filesystem $filesystem, $name = null)
35
    {
36
        $this->finder = $finder;
37
        $this->filesystem = $filesystem;
38
39
        parent::__construct($name);
40
    }
41
42
    /**
43
     * {@inheritDoc}
44
     */
45
    protected function configure()
46
    {
47
        parent::configure();
48
49
        $this
50
            ->setName('itkg:translation:convert')
51
            ->setDescription('Translation convert command from an input format to another format')
52
            ->setHelp('You must specify a path using the --path option.')
53
            ->addOption('path', null, InputOption::VALUE_REQUIRED, 'Specify a path of files')
54
            ->addOption('input', null, InputOption::VALUE_REQUIRED, 'Specifiy a input translation format')
55
            ->addOption('output', null, InputOption::VALUE_OPTIONAL, 'Specifiy an output translation format (default: xliff)')
56
            ->addOption('domain', null, InputOption::VALUE_OPTIONAL, 'All domains if not specified')
57
            ->addOption('output-path', null, InputOption::VALUE_OPTIONAL, 'Specify a path of output translations');
58
    }
59
60
    /**
61
     * {@inheritDoc}
62
     */
63
    protected function execute(InputInterface $input, OutputInterface $output)
64
    {
65
        $path = $input->getOption('path');
66
        $inputFormat = $input->getOption('input');
67
        $outputFormat = $input->getOption('output') ?: 'xliff';
68
69
        $catalogs = [];
70
71
        if (!$inputFormat) {
72
            throw new \InvalidArgumentException('You must specify a --input format option.');
73
        }
74
75
        if (!$path || !$this->filesystem->exists($path)) {
76
            throw new \InvalidArgumentException('You must specify a valid --path option.');
77
        }
78
79
        $dumper = $this->getDumper($outputFormat);
80
        $this->getTranslationWriter()->addDumper($outputFormat, $dumper);
81
82
        $files = $this->finder->files()->name('/[a-z]+\.[a-z]{2}\.'.$inputFormat.'/')->in($path);
83
84
        foreach ($files as $file) {
85
            list($domain, $language) = explode('.', $file->getFilename());
86
            if ($input->getOption('domain') && $domain !== $input->getOption('domain')) {
87
                continue;
88
            }
89
            $output->writeln(sprintf('Starts importing file %s', $file->getRealPath()));
90
            try {
91
                $msgCatalog = $this->getLoader($inputFormat)->load($file->getRealPath(), $language, $domain);
92
93
                $messages = $msgCatalog->all();
94
95
                if (!$messages) {
96
                    $output->writeln('No translations found in this file.');
97
98
                    continue;
99
                }
100
101
                if (isset($catalogs[$language])) {
102
                    $catalogs[$language]->addCatalogue($msgCatalog);
103
                } else {
104
                    $catalogs[$language] = $msgCatalog;
105
                }
106
107
                $output->writeln('Translation file saved.');
108
            } catch (\Exception $e) {
109
                $output->writeln(sprintf('An error has occured while trying to write translations: %s', $e->getMessage()));
110
            }
111
        }
112
113
        /** @var MessageCatalogue $catalog */
114
        foreach ($catalogs as $catalog) {
115
            $this->getTranslationWriter()->writeTranslations($catalog, $outputFormat, array(
116
                    'path' => $this->getTranslationPath($input->getOption('output-path')))
117
            );
118
        }
119
120
121
    }
122
123
    /**
124
     * Returns Symfony translation writer service
125
     *
126
     * @return TranslationWriter
127
     */
128
    protected function getTranslationWriter()
129
    {
130
        return $this->getContainer()->get('translation.writer');
131
    }
132
133
    /**
134
     * Returns Symfony requested format loader
135
     *
136
     * @param string $format
137
     *
138
     * @return \Symfony\Component\Translation\Loader\LoaderInterface
139
     *
140
     * @throws \InvalidArgumentException
141
     */
142 View Code Duplication
    protected function getLoader($format)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
143
    {
144
        $service = sprintf('translation.loader.%s', $format);
145
146
        if (!$this->getContainer()->has($service)) {
147
            throw new \InvalidArgumentException(sprintf('Unable to find Symfony Translation loader for format "%s"', $format));
148
        }
149
150
        return $this->getContainer()->get($service);
151
    }
152
153
    /**
154
     * Returns Symfony requested format dumper
155
     *
156
     * @param string $format
157
     *
158
     * @return \Symfony\Component\Translation\Dumper\DumperInterface
159
     *
160
     * @throws \InvalidArgumentException
161
     */
162 View Code Duplication
    protected function getDumper($format)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
163
    {
164
        $service = sprintf('translation.dumper.%s', $format);
165
166
        if (!$this->getContainer()->has($service)) {
167
            throw new \InvalidArgumentException(sprintf('Unable to find Symfony Translation dumper for format "%s"', $format));
168
        }
169
170
        return $this->getContainer()->get($service);
171
    }
172
173
    /**
174
     * Returns translation path
175
     *
176
     * @param string $outputPath
177
     *
178
     * @return string
179
     */
180
    protected function getTranslationPath($outputPath = null)
181
    {
182
        if ($outputPath) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $outputPath of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
183
            return $outputPath;
184
        }
185
186
        return $this->getContainer()->get('kernel')->getRootDir() . '/Resources/translations';
187
    }
188
}
189