Completed
Pull Request — master (#69)
by Raúl
02:30 queued 01:15
created

PoCompiler::buildMsgStr()   B

Complexity

Conditions 5
Paths 4

Size

Total Lines 20
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 20
rs 8.8571
c 0
b 0
f 0
cc 5
eloc 11
nc 4
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
        return $this->buildProperty('msgid', $entry->getMsgId(), $entry->isObsolete());
196
    }
197
198
    protected function buildMsgStr(Entry $entry)
199
    {
200
        $value = $entry->getMsgStr();
201
        $plurals = $entry->getMsgStrPlurals();
202
203
        if ($value === null && $plurals === null) {
204
            return '';
205
        }
206
207
        if ($entry->isPlural()) {
208
            $output = '';
209
            foreach ($plurals as $i => $line) {
210
                $output .= 'msgstr['.$i.'] '.$this->cleanExport($line).$this->eol();
211
            }
212
213
            return $output;
214
        }
215
216
        return $this->buildProperty('msgstr', $value, $entry->isObsolete());
217
    }
218
219
    /**
220
     * @param Entry $entry
221
     *
222
     * @return string
223
     */
224
    protected function buildMsgIdPlural(Entry $entry)
225
    {
226
        $value = $entry->getMsgIdPlural();
227
        if ($value === null) {
228
            return '';
229
        }
230
231
        return 'msgid_plural '.$this->cleanExport($value).$this->eol();
232
    }
233
234
    protected function buildProperty($property, $value, $obsolete = false)
235
    {
236
        $tokens = $this->wrapString($value);
237
238
        $output = '';
239
        if (count($tokens) > 1) {
240
            array_unshift($tokens, '');
241
        }
242
243
        foreach ($tokens as $i => $token) {
244
            $output .= $obsolete ? self::TOKEN_OBSOLETE : '';
245
            $output .= ($i === 0) ? $property.' ' : '';
246
            $output .= $this->cleanExport($token).$this->eol();
247
        }
248
249
        return $output;
250
    }
251
252
    /**
253
     * Prepares a string to be outputed into a file.
254
     *
255
     * @param string $string The string to be converted.
256
     *
257
     * @return string
258
     */
259
    protected function cleanExport($string)
260
    {
261
        $quote = '"';
262
        $slash = '\\';
263
        $newline = "\n";
264
265
        $replaces = array(
266
            "$slash" => "$slash$slash",
267
            "$quote" => "$slash$quote",
268
            "\t" => '\t',
269
        );
270
271
        $string = str_replace(array_keys($replaces), array_values($replaces), $string);
272
273
        $po = $quote.implode("${slash}n$quote$newline$quote", explode($newline, $string)).$quote;
274
275
        // remove empty strings
276
        return str_replace("$newline$quote$quote", '', $po);
277
    }
278
279
    /**
280
     * @param string $value
281
     *
282
     * @return array
283
     */
284
    private function wrapString($value)
285
    {
286
        if (strlen($value) > $this->wrappingColumn) {
287
            $tokens = str_split($value, $this->wrappingColumn);
288
        } else {
289
            $tokens = array($value);
290
        }
291
292
        return $tokens;
293
    }
294
}
295