Completed
Push — v5-dev ( a42eb3 )
by Oscar
01:56
created

PoLoader::loadString()   F

Complexity

Conditions 32
Paths 702

Size

Total Lines 158

Duplication

Lines 14
Ratio 8.86 %

Importance

Changes 0
Metric Value
cc 32
nc 702
nop 2
dl 14
loc 158
rs 0.3311
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
3
namespace Gettext\Loader;
4
5
use Gettext\Translations;
6
use Gettext\Translation;
7
8
/**
9
 * Class to load a PO file
10
 */
11
final class PoLoader extends Loader
12
{
13
    use HeadersLoaderTrait;
14
15
    public function loadString(string $string, Translations $translations = null): Translations
16
    {
17
        $translations = parent::loadString($string, $translations);
18
19
        $lines = explode("\n", $string);
20
        $i = 0;
21
        $append = null;
22
23
        $translation = $this->createTranslation(null, '');
24
25
        for ($n = count($lines); $i < $n; ++$i) {
26
            $line = trim($lines[$i]);
27
            $line = self::fixMultiLines($line, $lines, $i);
28
29
            if ($line === '') {
30
                if (!self::isEmpty($translation)) {
31
                    $translations->add($translation);
32
                }
33
34
                $translation = $this->createTranslation(null, '');
35
                continue;
36
            }
37
38
            $splitLine = preg_split('/\s+/', $line, 2);
39
            $key = $splitLine[0];
40
            $data = isset($splitLine[1]) ? $splitLine[1] : '';
41
42
            if ($key === '#~') {
43
                $translation->setDisabled(true);
0 ignored issues
show
Bug introduced by
The method setDisabled() does not exist on Gettext\Translation. Did you maybe mean disable()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
44
45
                $splitLine = preg_split('/\s+/', $data, 2);
46
                $key = $splitLine[0];
47
                $data = isset($splitLine[1]) ? $splitLine[1] : '';
48
            }
49
50
            if ($data === '') {
51
                continue;
52
            }
53
54
            switch ($key) {
55
                case '#':
56
                    $translation->getComments()->add($data);
57
                    $append = null;
58
                    break;
59
60
                case '#.':
61
                    $translation->getExtractedComments()->add($data);
62
                    $append = null;
63
                    break;
64
65
                case '#,':
66
                    foreach (array_map('trim', explode(',', trim($data))) as $value) {
67
                        $translation->getFlags()->add($value);
68
                    }
69
                    $append = null;
70
                    break;
71
72
                case '#:':
73
                    foreach (preg_split('/\s+/', trim($data)) as $value) {
74
                        if (preg_match('/^(.+)(:(\d*))?$/U', $value, $matches)) {
75
                            $translation->getReferences()->add($matches[1], isset($matches[3]) ? $matches[3] : null);
76
                        }
77
                    }
78
                    $append = null;
79
                    break;
80
81
                case 'msgctxt':
82
                    $translation = $translation->withContext(static::decode($data));
83
                    $append = 'Context';
84
                    break;
85
86
                case 'msgid':
87
                    $translation = $translation->withOriginal(static::decode($data));
88
                    $append = 'Original';
89
                    break;
90
91
                case 'msgid_plural':
92
                    $translation->setPlural(static::decode($data));
93
                    $append = 'Plural';
94
                    break;
95
96
                case 'msgstr':
97
                case 'msgstr[0]':
98
                    $translation->translate(static::decode($data));
99
                    $append = 'Translation';
100
                    break;
101
102
                case 'msgstr[1]':
103
                    $translation->translatePlural(static::decode($data));
104
                    $append = 'PluralTranslation';
105
                    break;
106
107
                default:
108 View Code Duplication
                    if (strpos($key, 'msgstr[') === 0) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
109
                        $p = $translation->getPluralTranslations();
110
                        $p[] = static::decode($data);
111
112
                        $translation->translatePlural(...$p);
113
                        $append = 'PluralTranslation';
114
                        break;
115
                    }
116
117
                    if (isset($append)) {
118
                        if ($append === 'Context') {
119
                            $context = $translation->getContext()."\n".static::decode($data);
120
                            $translation = $translation->withContext($context);
121
                            break;
122
                        }
123
124
                        if ($append === 'Original') {
125
                            $original = $translation->getOriginal()."\n".static::decode($data);
126
                            $translation = $translation->withOriginal($original);
127
                            break;
128
                        }
129
130
                        if ($append === 'Plural') {
131
                            $plural = $translation->getPlural()."\n".static::decode($data);
132
                            $translation->setPlural($plural);
133
                            break;
134
                        }
135
136
                        if ($append === 'Translation') {
137
                            $text = $translation->getTranslation()."\n".static::decode($data);
138
                            $translation->translate($text);
139
                            break;
140
                        }
141
142 View Code Duplication
                        if ($append === 'PluralTranslation') {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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
                            $p = $translation->getPluralTranslations();
144
                            $p[] = array_pop($p)."\n".static::decode($data);
145
                            $translation->translatePlural(...$p);
146
                            break;
147
                        }
148
                    }
149
                    break;
150
            }
151
        }
152
153
        if (!self::isEmpty($translation)) {
154
            $translations->add($translation);
155
        }
156
157
        //Headers
158
        $translation = $translations->find(null, '');
159
160
        if (!$translation) {
161
            return $translations;
162
        }
163
164
        $translations->remove($translation);
165
        $headers = $translations->getHeaders();
166
167
        foreach (static::parseHeaders($translation->getTranslation()) as $name => $value) {
0 ignored issues
show
Comprehensibility introduced by
Since Gettext\Loader\PoLoader is declared final, using late-static binding will have no effect. You might want to replace static with self instead.

Late static binding only has effect in subclasses. A final class cannot be extended anymore so late static binding cannot occurr. Consider replacing static:: with self::.

To learn more about late static binding, please refer to the PHP core documentation.

Loading history...
168
            $headers->set($name, $value);
169
        }
170
171
        return $translations;
172
    }
173
174
    /**
175
     * Gets one string from multiline strings.
176
     */
177
    private static function fixMultiLines(string $line, array $lines, int &$i): string
178
    {
179
        for ($j = $i, $t = count($lines); $j < $t; ++$j) {
180
            if (substr($line, -1, 1) == '"'
181
                && isset($lines[$j + 1])
182
                && substr(trim($lines[$j + 1]), 0, 1) == '"'
183
            ) {
184
                $line = substr($line, 0, -1).substr(trim($lines[$j + 1]), 1);
185
            } else {
186
                $i = $j;
187
                break;
188
            }
189
        }
190
191
        return $line;
192
    }
193
194
    /**
195
     * Convert a string from its PO representation.
196
     */
197
    public static function decode(string $value): string
198
    {
199
        if (!$value) {
200
            return '';
201
        }
202
203
        if ($value[0] === '"') {
204
            $value = substr($value, 1, -1);
205
        }
206
207
        return strtr(
208
            $value,
209
            [
210
                '\\\\' => '\\',
211
                '\\a' => "\x07",
212
                '\\b' => "\x08",
213
                '\\t' => "\t",
214
                '\\n' => "\n",
215
                '\\v' => "\x0b",
216
                '\\f' => "\x0c",
217
                '\\r' => "\r",
218
                '\\"' => '"',
219
            ]
220
        );
221
    }
222
223
    private static function isEmpty(Translation $translation): bool
224
    {
225
        if (!empty($translation->getOriginal())) {
226
            return false;
227
        }
228
229
        if (!empty($translation->getTranslation())) {
230
            return false;
231
        }
232
233
        return true;
234
    }
235
}
236