Completed
Push — master ( 1397d3...9c4f1a )
by Oscar
02:50
created

Translations   B

Complexity

Total Complexity 39

Size/Duplication

Total Lines 343
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 3

Importance

Changes 20
Bugs 3 Features 3
Metric Value
c 20
b 3
f 3
dl 0
loc 343
rs 8.2857
wmc 39
lcom 2
cbo 3

21 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 19 2
A __callStatic() 0 8 2
B __call() 0 22 4
A __clone() 0 10 2
A offsetSet() 0 18 3
A setPluralForms() 0 6 1
A getPluralForms() 0 8 3
A setHeader() 0 7 1
A getHeader() 0 4 2
A getHeaders() 0 6 1
A deleteHeaders() 0 6 1
A deleteHeader() 0 6 1
A getLanguage() 0 4 1
A setLanguage() 0 10 2
A hasLanguage() 0 6 3
A setDomain() 0 6 1
A getDomain() 0 4 1
A hasDomain() 0 6 3
A find() 0 10 3
A insert() 0 4 1
A mergeWith() 0 7 1
1
<?php
2
3
namespace Gettext;
4
5
use Gettext\Languages\Language;
6
use BadMethodCallException;
7
use InvalidArgumentException;
8
9
/**
10
 * Class to manage a collection of translations.
11
 * 
12
 * @method addFromCsvFile(string $filename, array $options = [])
13
 * @method addFromCsvString(array $options = [])
14
 * @method toCsvFile(string $filename, array $options = [])
15
 * @method toCsvString(array $options = [])
16
 * @method addFromCsvDictionaryFile(string $filename, array $options = [])
17
 * @method addFromCsvDictionaryString(array $options = [])
18
 * @method toCsvDictionaryFile(string $filename, array $options = [])
19
 * @method toCsvDictionaryString(array $options = [])
20
 * @method addFromJedFile(string $filename, array $options = [])
21
 * @method addFromJedString(array $options = [])
22
 * @method toJedFile(string $filename, array $options = [])
23
 * @method toJedString(array $options = [])
24
 * @method addFromJsonFile(string $filename, array $options = [])
25
 * @method addFromJsonString(array $options = [])
26
 * @method toJsonFile(string $filename, array $options = [])
27
 * @method toJsonString(array $options = [])
28
 * @method addFromJsonDictionaryFile(string $filename, array $options = [])
29
 * @method addFromJsonDictionaryString(array $options = [])
30
 * @method toJsonDictionaryFile(string $filename, array $options = [])
31
 * @method toJsonDictionaryString(array $options = [])
32
 * @method addFromMoFile(string $filename, array $options = [])
33
 * @method addFromMoString(array $options = [])
34
 * @method toMoFile(string $filename, array $options = [])
35
 * @method toMoString(array $options = [])
36
 * @method addFromPhpArrayFile(string $filename, array $options = [])
37
 * @method addFromPhpArrayString(array $options = [])
38
 * @method toPhpArrayFile(string $filename, array $options = [])
39
 * @method toPhpArrayString(array $options = [])
40
 * @method addFromPoFile(string $filename, array $options = [])
41
 * @method addFromPoString(array $options = [])
42
 * @method toPoFile(string $filename, array $options = [])
43
 * @method toPoString(array $options = [])
44
 * @method addFromXliffFile(string $filename, array $options = [])
45
 * @method addFromXliffString(array $options = [])
46
 * @method toXliffFile(string $filename, array $options = [])
47
 * @method toXliffString(array $options = [])
48
 * @method addFromYamlFile(string $filename, array $options = [])
49
 * @method addFromYamlString(array $options = [])
50
 * @method toYamlFile(string $filename, array $options = [])
51
 * @method toYamlString(array $options = [])
52
 * @method addFromYamlDictionaryFile(string $filename, array $options = [])
53
 * @method addFromYamlDictionaryString(array $options = [])
54
 * @method toYamlDictionaryFile(string $filename, array $options = [])
55
 * @method toYamlDictionaryString(array $options = [])
56
 */
57
class Translations extends \ArrayObject
58
{
59
    const HEADER_LANGUAGE = 'Language';
60
    const HEADER_PLURAL = 'Plural-Forms';
61
    const HEADER_DOMAIN = 'X-Domain';
62
63
    public static $insertDate = true;
64
65
    private $headers;
66
67
    /**
68
     * @see \ArrayObject::__construct()
69
     */
70
    public function __construct($input = [], $flags = 0, $iterator_class = 'ArrayIterator')
71
    {
72
        $this->headers = [
73
            'Project-Id-Version' => '',
74
            'Report-Msgid-Bugs-To' => '',
75
            'Last-Translator' => '',
76
            'Language-Team' => '',
77
            'MIME-Version' => '1.0',
78
            'Content-Type' => 'text/plain; charset=UTF-8',
79
            'Content-Transfer-Encoding' => '8bit',
80
        ];
81
82
        if (static::$insertDate) {
83
            $this->headers['POT-Creation-Date'] = $this->headers['PO-Revision-Date'] = date('c');
84
        }
85
86
        $this->headers[self::HEADER_LANGUAGE] = '';
87
        parent::__construct($input, $flags, $iterator_class);
88
    }
89
90
    /**
91
     * Magic method to create new instances using extractors
92
     * For example: Translations::fromMoFile($filename, $options);.
93
     *
94
     * @return Translations
95
     */
96
    public static function __callStatic($name, $arguments)
97
    {
98
        if (!preg_match('/^from(\w+)(File|String)$/i', $name, $matches)) {
99
            throw new BadMethodCallException("The method $name does not exists");
100
        }
101
102
        return call_user_func_array([new static(), 'add'.ucfirst($name)], $arguments);
103
    }
104
105
    /**
106
     * Magic method to import/export the translations to a specific format
107
     * For example: $translations->toMoFile($filename, $options);
108
     * For example: $translations->addFromMoFile($filename, $options);.
109
     *
110
     * @return self|bool
111
     */
112
    public function __call($name, $arguments)
113
    {
114
        if (!preg_match('/^(addFrom|to)(\w+)(File|String)$/i', $name, $matches)) {
115
            throw new BadMethodCallException("The method $name does not exists");
116
        }
117
118
        if ($matches[1] === 'addFrom') {
119
            $extractor = 'Gettext\\Extractors\\'.$matches[2].'::from'.$matches[3];
120
            $source = array_shift($arguments);
121
            $options = array_shift($arguments) ?: [];
122
123
            call_user_func($extractor, $source, $this, $options);
124
125
            return $this;
126
        }
127
128
        $generator = 'Gettext\\Generators\\'.$matches[2].'::to'.$matches[3];
129
130
        array_unshift($arguments, $this);
131
132
        return call_user_func_array($generator, $arguments);
133
    }
134
135
    /**
136
     * Magic method to clone each translation on clone the translations object.
137
     */
138
    public function __clone()
139
    {
140
        $array = [];
141
142
        foreach ($this as $key => $translation) {
143
            $array[$key] = clone $translation;
144
        }
145
146
        $this->exchangeArray($array);
147
    }
148
149
    /**
150
     * Control the new translations added.
151
     *
152
     * @param mixed       $index
153
     * @param Translation $value
154
     *
155
     * @throws InvalidArgumentException If the value is not an instance of Gettext\Translation
156
     *
157
     * @return Translation
158
     */
159
    public function offsetSet($index, $value)
160
    {
161
        if (!($value instanceof Translation)) {
162
            throw new InvalidArgumentException('Only instances of Gettext\\Translation must be added to a Gettext\\Translations');
163
        }
164
165
        $id = $value->getId();
166
167
        if ($this->offsetExists($id)) {
168
            $this[$id]->mergeWith($value);
169
170
            return $this[$id];
171
        }
172
173
        parent::offsetSet($id, $value);
174
175
        return $value;
176
    }
177
178
    /**
179
     * Set the plural definition.
180
     *
181
     * @param int    $count
182
     * @param string $rule
183
     * 
184
     * @return self
185
     */
186
    public function setPluralForms($count, $rule)
187
    {
188
        $this->setHeader(self::HEADER_PLURAL, "nplurals={$count}; plural={$rule};");
189
190
        return $this;
191
    }
192
193
    /**
194
     * Returns the parsed plural definition.
195
     *
196
     * @param null|array [count, rule]
197
     */
198
    public function getPluralForms()
199
    {
200
        $header = $this->getHeader(self::HEADER_PLURAL);
201
202
        if (!empty($header) && preg_match('/^nplurals\s*=\s*(\d+)\s*;\s*plural\s*=\s*([^;]+)\s*;$/', $header, $matches)) {
203
            return [intval($matches[1]), $matches[2]];
204
        }
205
    }
206
207
    /**
208
     * Set a new header.
209
     *
210
     * @param string $name
211
     * @param string $value
212
     * 
213
     * @return self
214
     */
215
    public function setHeader($name, $value)
216
    {
217
        $name = trim($name);
218
        $this->headers[$name] = trim($value);
219
220
        return $this;
221
    }
222
223
    /**
224
     * Returns a header value.
225
     *
226
     * @param string $name
227
     *
228
     * @return null|string
229
     */
230
    public function getHeader($name)
231
    {
232
        return isset($this->headers[$name]) ? $this->headers[$name] : null;
233
    }
234
235
    /**
236
     * Returns all header for this translations (in alphabetic order).
237
     *
238
     * @return array
239
     */
240
    public function getHeaders()
241
    {
242
        ksort($this->headers);
243
244
        return $this->headers;
245
    }
246
247
    /**
248
     * Removes all headers.
249
     * 
250
     * @return self
251
     */
252
    public function deleteHeaders()
253
    {
254
        $this->headers = [];
255
256
        return $this;
257
    }
258
259
    /**
260
     * Removes one header.
261
     *
262
     * @param string $name
263
     * 
264
     * @return self
265
     */
266
    public function deleteHeader($name)
267
    {
268
        unset($this->headers[$name]);
269
270
        return $this;
271
    }
272
273
    /**
274
     * Returns the language value.
275
     *
276
     * @return string $language
277
     */
278
    public function getLanguage()
279
    {
280
        return $this->getHeader(self::HEADER_LANGUAGE);
281
    }
282
283
    /**
284
     * Sets the language and the plural forms.
285
     *
286
     * @param string $language
287
     * 
288
     * @throws InvalidArgumentException if the language hasn't been recognized
289
     *
290
     * @return self
291
     */
292
    public function setLanguage($language)
293
    {
294
        $this->setHeader(self::HEADER_LANGUAGE, trim($language));
295
296
        if (($info = Language::getById($language))) {
297
            return $this->setPluralForms(count($info->categories), $info->formula);
298
        }
299
300
        throw new InvalidArgumentException(sprintf('The language "%s" is not valid', $language));
301
    }
302
303
    /**
304
     * Checks whether the language is empty or not.
305
     *
306
     * @return bool
307
     */
308
    public function hasLanguage()
309
    {
310
        $language = $this->getLanguage();
311
312
        return (is_string($language) && ($language !== '')) ? true : false;
313
    }
314
315
    /**
316
     * Set a new domain for this translations.
317
     *
318
     * @param string $domain
319
     * 
320
     * @return self
321
     */
322
    public function setDomain($domain)
323
    {
324
        $this->setHeader(self::HEADER_DOMAIN, trim($domain));
325
326
        return $this;
327
    }
328
329
    /**
330
     * Returns the domain.
331
     *
332
     * @return string
333
     */
334
    public function getDomain()
335
    {
336
        return $this->getHeader(self::HEADER_DOMAIN);
337
    }
338
339
    /**
340
     * Checks whether the domain is empty or not.
341
     *
342
     * @return bool
343
     */
344
    public function hasDomain()
345
    {
346
        $domain = $this->getDomain();
347
348
        return (is_string($domain) && ($domain !== '')) ? true : false;
349
    }
350
351
    /**
352
     * Search for a specific translation.
353
     *
354
     * @param string|Translation $context  The context of the translation or a translation instance
355
     * @param string             $original The original string
356
     *
357
     * @return Translation|false
358
     */
359
    public function find($context, $original = '')
360
    {
361
        if ($context instanceof Translation) {
362
            $id = $context->getId();
363
        } else {
364
            $id = Translation::generateId($context, $original);
365
        }
366
367
        return $this->offsetExists($id) ? $this[$id] : false;
368
    }
369
370
    /**
371
     * Creates and insert/merges a new translation.
372
     *
373
     * @param string $context  The translation context
374
     * @param string $original The translation original string
375
     * @param string $plural   The translation original plural string
376
     *
377
     * @return Translation The translation created
378
     */
379
    public function insert($context, $original, $plural = '')
380
    {
381
        return $this->offsetSet(null, new Translation($context, $original, $plural));
382
    }
383
384
    /**
385
     * Merges this translations with other translations.
386
     *
387
     * @param Translations $translations The translations instance to merge with
388
     * @param int          $options
389
     * 
390
     * @return self
391
     */
392
    public function mergeWith(Translations $translations, $options = Merge::DEFAULTS)
393
    {
394
        Merge::mergeHeaders($translations, $this, $options);
395
        Merge::mergeTranslations($translations, $this, $options);
396
397
        return $this;
398
    }
399
}
400