Passed
Pull Request — master (#81)
by Dante
01:14
created

GettextCommand::parseFile()   C

Complexity

Conditions 12
Paths 40

Size

Total Lines 78
Code Lines 50

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 12
eloc 50
nc 40
nop 2
dl 0
loc 78
rs 6.9666
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
declare(strict_types=1);
3
4
/**
5
 * BEdita, API-first content management framework
6
 * Copyright 2022 Atlas Srl, Chialab Srl
7
 *
8
 * This file is part of BEdita: you can redistribute it and/or modify
9
 * it under the terms of the GNU Lesser General Public License as published
10
 * by the Free Software Foundation, either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * See LICENSE.LGPL or <http://gnu.org/licenses/lgpl-3.0.html> for more details.
14
 */
15
16
namespace BEdita\I18n\Command;
17
18
use BEdita\I18n\Filesystem\File;
19
use BEdita\I18n\Filesystem\Gettext;
20
use BEdita\I18n\Filesystem\Paths;
21
use BEdita\I18n\Filesystem\Ttag;
22
use Cake\Command\Command;
23
use Cake\Console\Arguments;
24
use Cake\Console\ConsoleIo;
25
use Cake\Console\ConsoleOptionParser;
26
use Cake\Core\Configure;
27
use Cake\Utility\Hash;
28
29
/**
30
 * Gettext command.
31
 */
32
class GettextCommand extends Command
33
{
34
    /**
35
     * @var int
36
     */
37
    public const CODE_CHANGES = 2;
38
39
    /**
40
     * The Po results
41
     *
42
     * @var array
43
     */
44
    private $poResult = [];
45
46
    /**
47
     * The template paths
48
     *
49
     * @var array
50
     */
51
    private $templatePaths = [];
52
53
    /**
54
     * The locale path
55
     *
56
     * @var string
57
     */
58
    private $localePath = '';
59
60
    /**
61
     * The name of default domain if not specified. Used for pot and po file names.
62
     *
63
     * @var string
64
     */
65
    private $defaultDomain = 'default';
66
67
    /**
68
     * The locales to generate.
69
     *
70
     * @var array
71
     */
72
    private $locales = [];
73
74
    /**
75
     * @inheritDoc
76
     */
77
    public function buildOptionParser(ConsoleOptionParser $parser): ConsoleOptionParser
78
    {
79
        return parent::buildOptionParser($parser)
80
            ->setDescription([
81
                'Create or update i18n po/pot files',
82
                '',
83
                '`bin/cake gettext`: update files for current app',
84
                '`bin/cake gettext -app <app path>`: update files for the app',
85
                '`bin/cake gettext -plugin <plugin name>`: update files for the plugin',
86
            ])
87
            ->addOption('app', [
88
                'help' => 'The app path, for i18n update.',
89
                'short' => 'a',
90
                'required' => false,
91
            ])
92
            ->addOption('plugin', [
93
                'help' => 'The plugin name, for i18n update.',
94
                'short' => 'p',
95
                'required' => false,
96
            ])
97
            ->addOption('plugins', [
98
                'help' => 'All plugins',
99
                'required' => false,
100
                'boolean' => true,
101
            ])
102
            ->addOption('ci', [
103
                'help' => 'Run in CI mode. Exit with error if PO files are changed.',
104
                'required' => false,
105
                'boolean' => true,
106
            ])
107
            ->addOption('locales', [
108
                'help' => 'Comma separated list of locales to generate. Leave empty to use configuration `I18n.locales`',
109
                'short' => 'l',
110
                'default' => implode(',', array_keys((array)Configure::read('I18n.locales'))),
111
            ]);
112
    }
113
114
    /**
115
     * Update gettext po files.
116
     *
117
     * @param \Cake\Console\Arguments $args The command arguments.
118
     * @param \Cake\Console\ConsoleIo $io The console io
119
     * @return null|void|int The exit code or null for success
120
     */
121
    public function execute(Arguments $args, ConsoleIo $io)
122
    {
123
        $resCmd = [];
124
        exec('which msgmerge 2>&1', $resCmd);
125
        $msg = empty($resCmd[0]) ? 'ERROR: msgmerge not available. Please install gettext utilities.' : 'OK: msgmerge found';
126
        $method = empty($resCmd[0]) ? 'abort' : 'out';
127
        $io->{$method}($msg);
128
129
        $io->out('Updating .pot and .po files...');
130
        $this->locales = array_filter(explode(',', $args->getOption('locales')));
0 ignored issues
show
Bug introduced by
It seems like $args->getOption('locales') can also be of type boolean and null; however, parameter $string of explode() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

130
        $this->locales = array_filter(explode(',', /** @scrutinizer ignore-type */ $args->getOption('locales')));
Loading history...
131
        Paths::setup($this->templatePaths, $this->localePath, $this->defaultDomain, $args->getOptions());
132
        foreach ($this->templatePaths as $path) {
133
            $io->out(sprintf('Search in: %s', $path));
134
            File::parseDir($path, $this->defaultDomain, $this->poResult);
135
        }
136
137
        $io->out('Creating master .pot file');
138
        $result = Gettext::writeMasterPot($this->localePath, $this->poResult);
139
        foreach ($result['info'] as $info) {
140
            $io->out($info);
141
        }
142
        $hasChanges = Hash::get($result, 'updated') === true;
143
144
        $io->out('Extracting ttag translations from javascript files');
145
        $result = Ttag::extract($this->locales, $this->localePath, (string)$args->getOption('plugin'));
146
        foreach ($result['info'] as $info) {
147
            $io->out($info);
148
        }
149
        $io->out(sprintf('Ttag extracted: %s', $result['extracted']));
150
151
        $io->hr();
152
        $io->out('Merging master .pot with current .po files');
153
        $io->hr();
154
155
        $io->out('Writing po files');
156
        $result = Gettext::writePoFiles($this->locales, $this->localePath, $this->poResult);
157
        foreach ($result['info'] as $info) {
158
            $io->out($info);
159
        }
160
161
        $io->out('Done');
162
163
        if ($args->getOption('ci') && $hasChanges) {
164
            return GettextCommand::CODE_CHANGES;
165
        }
166
167
        return GettextCommand::CODE_SUCCESS;
168
    }
169
}
170