Completed
Push — feature/high_five ( cf7883...85675c )
by Raúl
05:22
created

PoCompiler::cleanExport()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 19
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 19
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 11
nc 1
nop 1
1
<?php
2
3
namespace Sepia\PoParser;
4
5
use Sepia\PoParser\Catalog\Entry;
6
7
class PoCompiler
8
{
9
    const TOKEN_OBSOLETE = '#~ ';
10
    /** @var int */
11
    protected $wrappingColumn;
12
13
    /** @var string */
14
    protected $lineEnding;
15
16
    /**
17
     * PoCompiler constructor.
18
     *
19
     * @param int    $wrappingColumn
20
     * @param string $lineEnding
21
     */
22
    public function __construct($wrappingColumn = 80, $lineEnding = "\n")
23
    {
24
        $this->wrappingColumn = $wrappingColumn;
25
        $this->lineEnding = $lineEnding;
26
    }
27
28
    /**
29
     * Compiles entries into a string
30
     *
31
     * @param Catalog $catalog
32
     *
33
     * @return string
34
     * @throws \Exception
35
     * @todo Write obsolete messages at the end of the file.
36
     */
37
    public function compile(Catalog $catalog)
38
    {
39
        $output = '';
40
41
        if (count($catalog->getHeaders()) > 0) {
42
            $output .= 'msgid ""'.$this->eol();
43
            $output .= 'msgstr ""'.$this->eol();
44
            foreach ($catalog->getHeaders() as $header) {
45
                $output .= $header.$this->eol();
46
            }
47
            $output .= $this->eol();
48
        }
49
50
51
        $entriesCount = count($catalog->getEntries());
52
        $counter = 0;
53
        foreach ($catalog->getEntries() as $entry) {
54
            if ($entry->isObsolete() === false) {
55
                $output .= $this->buildPreviousEntry($entry);
56
                $output .= $this->buildTranslatorComment($entry);
57
                $output .= $this->buildDeveloperComment($entry);
58
                $output .= $this->buildReference($entry);
59
            }
60
61
            $output .= $this->buildFlags($entry);
62
63
//            if (isset($entry['@'])) {
64
//                $output .= "#@ ".$entry['@'].$this->eol();
65
//            }
66
67
            $output .= $this->buildContext($entry);
68
            $output .= $this->buildMsgId($entry);
69
            $output .= $this->buildMsgIdPlural($entry);
70
            $output .= $this->buildMsgStr($entry);
71
72
73
            $counter++;
74
            // Avoid inserting an extra newline at end of file
75
            if ($counter < $entriesCount) {
76
                $output .= $this->eol();
77
            }
78
        }
79
80
        return $output;
81
    }
82
83
    /**
84
     * @return string
85
     */
86
    protected function eol()
87
    {
88
        return $this->lineEnding;
89
    }
90
91
    /**
92
     * @param $entry
93
     *
94
     * @return string
95
     */
96
    protected function buildPreviousEntry(Entry $entry)
97
    {
98
        $previous = $entry->getPreviousEntry();
99
        if ($previous === null) {
100
            return '';
101
        }
102
103
        $output = '#| msgid '.$this->cleanExport($previous->getMsgId()).$this->eol();
104
105
        /*
106
        foreach ($entry['previous'] as $key => $data) {
107
108
            if (is_string($data)) {
109
                $output .= '#| '.$key.' '.$this->cleanExport($data).$this->eol();
110
            } elseif (is_array($data) && count($data) > 0) {
111
                foreach ($data as $line) {
112
                    $output .= '#| '.$key.' '.$this->cleanExport($line).$this->eol();
113
                }
114
            }
115
        }*/
116
117
        return $output;
118
    }
119
120
    /**
121
     * @param $entry
122
     *
123
     * @return string
124
     */
125
    protected function buildTranslatorComment(Entry $entry)
126
    {
127
        if ($entry->getTranslatorComments() === null) {
128
            return '';
129
        }
130
131
        $output = '';
132
        foreach ($entry->getTranslatorComments() as $comment) {
133
            $output .= '# '.$comment.$this->eol();
134
        }
135
136
        return $output;
137
    }
138
139
    protected function buildDeveloperComment(Entry $entry)
140
    {
141
        if ($entry->getDeveloperComments() === null) {
142
            return '';
143
        }
144
145
        $output = '';
146
        foreach ($entry->getDeveloperComments() as $comment) {
147
            $output .= '#. '.$comment.$this->eol();
148
        }
149
150
        return $output;
151
    }
152
153
    protected function buildReference(Entry $entry)
154
    {
155
        $reference = $entry->getReference();
156
        if ($reference === null || count($reference) === 0) {
157
            return '';
158
        }
159
160
        $output = '';
161
        foreach ($reference as $ref) {
162
            $output .= '#: '.$ref.$this->eol();
163
        }
164
165
        return $output;
166
    }
167
168
    protected function buildFlags(Entry $entry)
169
    {
170
        $flags = $entry->getFlags();
171
        if ($flags === null || count($flags) === 0) {
172
            return '';
173
        }
174
175
        return '#, '.implode(', ', $flags).$this->eol();
176
    }
177
178
    protected function buildContext(Entry $entry)
179
    {
180
        if ($entry->getMsgCtxt() === null) {
181
            return '';
182
        }
183
184
        return
185
            ($entry->isObsolete() ? '#~ ' : '' ).
186
            'msgctxt '.$this->cleanExport($entry->getMsgCtxt()).$this->eol();
187
    }
188
189
    protected function buildMsgId(Entry $entry)
190
    {
191
        if ($entry->getMsgId() === null) {
192
            return '';
193
        }
194
195
        $msgId = $entry->getMsgId();
196
197
        $output = '';
198
        $tokens = $this->wrapString($msgId);
199
200
        if (count($tokens) > 1) {
201
            array_unshift($tokens, '');
202
        }
203
204
        foreach ($tokens as $i => $token) {
205
            if ($entry->isObsolete()) {
206
                $output .= self::TOKEN_OBSOLETE;
207
            }
208
209
            if ($i === 0) {
210
                $output.= 'msgid ';
211
            }
212
213
            $output .= $this->cleanExport($token).$this->eol();
214
        }
215
216
        return $output;
217
    }
218
219
    protected function buildMsgStr(Entry $entry)
220
    {
221
        $value = $entry->getMsgStr();
222
        $plurals = $entry->getMsgStrPlurals();
223
224
        if ($value === null && $plurals === null) {
225
            return '';
226
        }
227
228
        if ($entry->isPlural()) {
229
            $output = '';
230
            foreach ($plurals as $i => $line) {
231
                $output .= 'msgstr['.$i.'] '.$this->cleanExport($line).$this->eol();
232
            }
233
234
            return $output;
235
        }
236
237
        $tokens = $this->wrapString($value);
238
239
        $output = '';
240
        if (count($tokens) > 1) {
241
            array_unshift($tokens, '');
242
        }
243
244
        foreach ($tokens as $i => $token) {
245
            if ($entry->isObsolete()) {
246
                $output .= self::TOKEN_OBSOLETE;
247
            }
248
249
            if ($i === 0) {
250
                $output.= 'msgstr ';
251
            }
252
253
            $output .= $this->cleanExport($token).$this->eol();
254
        }
255
256
        return $output;
257
        /*
258
        if (count(preg_grep('/^msgstr/', array_keys($entry)))) { // checks if there is a key starting with msgstr
259
            if ($isPlural) {
260
                $noTranslation = true;
261
                foreach ($entry as $key => $value) {
262
                    if (strpos($key, 'msgstr[') === false) {
263
                        continue;
264
                    }
265
                    $output .= $key." ";
266
                    $noTranslation = false;
267
                    foreach ($value as $i => $t) {
268
                        $output .= $this->cleanExport($t).$this->eol();
269
                    }
270
                }
271
                if ($noTranslation) {
272
                    $output .= 'msgstr[0] '.$this->cleanExport('').$this->eol();
273
                    $output .= 'msgstr[1] '.$this->cleanExport('').$this->eol();
274
                }
275
            } else {
276
                foreach ((array)$entry['msgstr'] as $i => $t) {
277
                    if ($i == 0) {
278
                        if ($entry->isObsolete()) {
279
                            $output .= "#~ ";
280
                        }
281
282
                        $output .= 'msgstr '.$this->cleanExport($t).$this->eol();
283
                    } else {
284
                        if ($entry->isObsolete()) {
285
                            $output .= "#~ ";
286
                        }
287
288
                        $output .= $this->cleanExport($t).$this->eol();
289
                    }
290
                }
291
            }
292
        }
293
        */
294
    }
295
296
    /**
297
     * @param Entry $entry
298
     *
299
     * @return string
300
     */
301
    protected function buildMsgIdPlural(Entry $entry)
302
    {
303
        $value = $entry->getMsgIdPlural();
304
        if ($value === null) {
305
            return '';
306
        }
307
308
        return 'msgid_plural '.$this->cleanExport($value).$this->eol();
309
    }
310
311
    /**
312
     * Prepares a string to be outputed into a file.
313
     *
314
     * @param string $string The string to be converted.
315
     *
316
     * @return string
317
     */
318
    protected function cleanExport($string)
319
    {
320
        $quote = '"';
321
        $slash = '\\';
322
        $newline = "\n";
323
324
        $replaces = array(
325
            "$slash" => "$slash$slash",
326
            "$quote" => "$slash$quote",
327
            "\t" => '\t',
328
        );
329
330
        $string = str_replace(array_keys($replaces), array_values($replaces), $string);
331
332
        $po = $quote.implode("${slash}n$quote$newline$quote", explode($newline, $string)).$quote;
333
334
        // remove empty strings
335
        return str_replace("$newline$quote$quote", '', $po);
336
    }
337
338
    /**
339
     * @param string $value
340
     *
341
     * @return array
342
     */
343
    private function wrapString($value)
344
    {
345
        if (strlen($value) > $this->wrappingColumn) {
346
            $tokens = str_split($value, $this->wrappingColumn);
347
        } else {
348
            $tokens = array($value);
349
        }
350
351
        return $tokens;
352
    }
353
}
354