Completed
Push — v5-dev ( a42eb3...269a1b )
by Oscar
01:14
created

PoLoader   A

Complexity

Total Complexity 32

Size/Duplication

Total Lines 175
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 8

Importance

Changes 0
Metric Value
dl 0
loc 175
rs 9.84
c 0
b 0
f 0
wmc 32
lcom 1
cbo 8

3 Methods

Rating   Name   Duplication   Size   Complexity  
F loadString() 0 128 26
A decode() 0 25 3
A isEmpty() 0 12 3
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
        $line = current($lines);
21
        $translation = $this->createTranslation(null, '');
22
23
        while ($line !== false) {
24
            $line = trim($line);
25
            $nextLine = next($lines);
26
            
27
            //Multiline
28
            while (
29
                substr($line, -1, 1) === '"'
30
                && $nextLine !== false
31
                && substr(trim($nextLine), 0, 1) === '"'
32
            ) {
33
                $line = substr($line, 0, -1).substr(trim($nextLine), 1);
34
                $nextLine = next($lines);
35
            }
36
37
            //End of translation
38
            if ($line === '') {
39
                if (!self::isEmpty($translation)) {
40
                    $translations->add($translation);
41
                }
42
43
                $translation = $this->createTranslation(null, '');
44
                $line = $nextLine;
45
                continue;
46
            }
47
48
            $splitLine = preg_split('/\s+/', $line, 2);
49
            $key = $splitLine[0];
50
            $data = $splitLine[1] ?? '';
51
52
            if ($key === '#~') {
53
                $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...
54
55
                $splitLine = preg_split('/\s+/', $data, 2);
56
                $key = $splitLine[0];
57
                $data = $splitLine[1] ?? '';
58
            }
59
60
            if ($data === '') {
61
                $line = $nextLine;
62
                continue;
63
            }
64
65
            switch ($key) {
66
                case '#':
67
                    $translation->getComments()->add($data);
68
                    break;
69
70
                case '#.':
71
                    $translation->getExtractedComments()->add($data);
72
                    break;
73
74
                case '#,':
75
                    foreach (array_map('trim', explode(',', trim($data))) as $value) {
76
                        $translation->getFlags()->add($value);
77
                    }
78
                    break;
79
80
                case '#:':
81
                    foreach (preg_split('/\s+/', trim($data)) as $value) {
82
                        if (preg_match('/^(.+)(:(\d*))?$/U', $value, $matches)) {
83
                            $translation->getReferences()->add($matches[1], $matches[3] ?? null);
84
                        }
85
                    }
86
                    break;
87
88
                case 'msgctxt':
89
                    $translation = $translation->withContext(static::decode($data));
90
                    break;
91
92
                case 'msgid':
93
                    $translation = $translation->withOriginal(static::decode($data));
94
                    break;
95
96
                case 'msgid_plural':
97
                    $translation->setPlural(static::decode($data));
98
                    break;
99
100
                case 'msgstr':
101
                case 'msgstr[0]':
102
                    $translation->translate(static::decode($data));
103
                    break;
104
105
                case 'msgstr[1]':
106
                    $translation->translatePlural(static::decode($data));
107
                    break;
108
109
                default:
110
                    if (strpos($key, 'msgstr[') === 0) {
111
                        $p = $translation->getPluralTranslations();
112
                        $p[] = static::decode($data);
113
114
                        $translation->translatePlural(...$p);
115
                        break;
116
                    }
117
                    break;
118
            }
119
120
            $line = $nextLine;
121
        }
122
123
        if (!self::isEmpty($translation)) {
124
            $translations->add($translation);
125
        }
126
127
        //Headers
128
        $translation = $translations->find(null, '');
129
130
        if (!$translation) {
131
            return $translations;
132
        }
133
134
        $translations->remove($translation);
135
        $headers = $translations->getHeaders();
136
137
        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...
138
            $headers->set($name, $value);
139
        }
140
141
        return $translations;
142
    }
143
144
    /**
145
     * Convert a string from its PO representation.
146
     */
147
    public static function decode(string $value): string
148
    {
149
        if (!$value) {
150
            return '';
151
        }
152
153
        if ($value[0] === '"') {
154
            $value = substr($value, 1, -1);
155
        }
156
157
        return strtr(
158
            $value,
159
            [
160
                '\\\\' => '\\',
161
                '\\a' => "\x07",
162
                '\\b' => "\x08",
163
                '\\t' => "\t",
164
                '\\n' => "\n",
165
                '\\v' => "\x0b",
166
                '\\f' => "\x0c",
167
                '\\r' => "\r",
168
                '\\"' => '"',
169
            ]
170
        );
171
    }
172
173
    private static function isEmpty(Translation $translation): bool
174
    {
175
        if (!empty($translation->getOriginal())) {
176
            return false;
177
        }
178
179
        if (!empty($translation->getTranslation())) {
180
            return false;
181
        }
182
183
        return true;
184
    }
185
}
186