Passed
Branch master (a6f152)
by Mathieu
06:09 queued 11s
created

Translation::setVal()   C

Complexity

Conditions 7
Paths 5

Size

Total Lines 27
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 17
nc 5
nop 1
dl 0
loc 27
rs 6.7272
c 0
b 0
f 0
1
<?php
2
3
namespace Charcoal\Translator;
4
5
use ArrayAccess;
6
use DomainException;
7
use InvalidArgumentException;
8
use JsonSerializable;
9
10
// From 'charcoal-translator'
11
use Charcoal\Translator\LocalesManager;
12
13
/**
14
 * A translation object holds a localized message in all available locales.
15
 *
16
 * Available locales is provided with a locales manager.
17
 */
18
class Translation implements
19
    ArrayAccess,
20
    JsonSerializable
21
{
22
    /**
23
     * The object's translations.
24
     *
25
     * Stored as a `[ $lang => $val ]` hash.
26
     *
27
     * @var string[]
28
     */
29
    private $val = [];
30
31
    /**
32
     * @var LocalesManager
33
     */
34
    private $manager;
35
36
    /**
37
     * @param Translation|array|string $val     The translation values.
38
     * @param LocalesManager           $manager A LocalesManager instance.
39
     */
40
    public function __construct($val, LocalesManager $manager)
41
    {
42
        $this->manager = $manager;
43
        $this->setVal($val);
44
    }
45
46
    /**
47
     * Output the current language's value, when cast to string.
48
     *
49
     * @return string
50
     */
51
    public function __toString()
52
    {
53
        $lang = $this->manager->currentLocale();
54
        if (isset($this->val[$lang])) {
55
            return $this->val[$lang];
56
        } else {
57
            return '';
58
        }
59
    }
60
61
    /**
62
     * Get the array of translations in all languages.
63
     *
64
     * @return string[]
65
     */
66
    public function data()
67
    {
68
        return $this->val;
69
    }
70
71
    /**
72
     * @param  string $lang A language identifier.
73
     * @return boolean
74
     * @see    ArrayAccess::offsetExists()
75
     * @throws InvalidArgumentException If array key isn't a string.
76
     */
77
    public function offsetExists($lang)
78
    {
79
        if (!is_string($lang)) {
0 ignored issues
show
introduced by
The condition is_string($lang) is always true.
Loading history...
80
            throw new InvalidArgumentException(sprintf(
81
                'Invalid language; must be a string, received %s',
82
                (is_object($lang) ? get_class($lang) : gettype($lang))
83
            ));
84
        }
85
86
        return isset($this->val[$lang]);
87
    }
88
89
    /**
90
     * @param  string $lang A language identifier.
91
     * @return string A translated string.
92
     * @see    ArrayAccess::offsetGet()
93
     * @throws InvalidArgumentException If array key isn't a string.
94
     * @throws DomainException If the array key is not found.
95
     */
96
    public function offsetGet($lang)
97
    {
98
        if (!is_string($lang)) {
0 ignored issues
show
introduced by
The condition is_string($lang) is always true.
Loading history...
99
            throw new InvalidArgumentException(sprintf(
100
                'Invalid language; must be a string, received %s',
101
                (is_object($lang) ? get_class($lang) : gettype($lang))
102
            ));
103
        }
104
105
        if (!isset($this->val[$lang])) {
106
            throw new DomainException(sprintf(
107
                'Translation for "%s" is not defined.',
108
                $lang
109
            ));
110
        }
111
112
        return $this->val[$lang];
113
    }
114
115
    /**
116
     * @param  string $lang A language identifier.
117
     * @param  string $val  A translation value.
118
     * @return void
119
     * @see    ArrayAccess::offsetSet()
120
     * @throws InvalidArgumentException If array key isn't a string.
121
     */
122
    public function offsetSet($lang, $val)
123
    {
124
        if (!is_string($lang)) {
0 ignored issues
show
introduced by
The condition is_string($lang) is always true.
Loading history...
125
            throw new InvalidArgumentException(sprintf(
126
                'Invalid language; must be a string, received %s',
127
                (is_object($lang) ? get_class($lang) : gettype($lang))
128
            ));
129
        }
130
131
        if (!is_string($val)) {
0 ignored issues
show
introduced by
The condition is_string($val) is always true.
Loading history...
132
            throw new InvalidArgumentException(sprintf(
133
                'Translation must be a string, received %s',
134
                (is_object($val) ? get_class($val) : gettype($val))
135
            ));
136
        }
137
138
        $this->val[$lang] = $val;
139
    }
140
141
    /**
142
     * @param  string $lang A language identifier.
143
     * @return void
144
     * @see    ArrayAccess::offsetUnset()
145
     * @throws InvalidArgumentException If array key isn't a string.
146
     */
147
    public function offsetUnset($lang)
148
    {
149
        if (!is_string($lang)) {
0 ignored issues
show
introduced by
The condition is_string($lang) is always true.
Loading history...
150
            throw new InvalidArgumentException(sprintf(
151
                'Invalid language; must be a string, received %s',
152
                (is_object($lang) ? get_class($lang) : gettype($lang))
153
            ));
154
        }
155
156
        unset($this->val[$lang]);
157
    }
158
159
    /**
160
     * Retrieve translations that can be serialized natively by json_encode().
161
     *
162
     * @return string[]
163
     * @see    JsonSerializable::jsonSerialize()
164
     */
165
    public function jsonSerialize()
166
    {
167
        return $this->data();
168
    }
169
170
    /**
171
     * Sanitize each language's string with a callback function.
172
     *
173
     * The callback method signature is to take a string as parameter and return the sanitized string.
174
     *
175
     * @param callable $sanitizeCallback The sanitizing function callback.
176
     * @return self
177
     */
178
    public function sanitize(callable $sanitizeCallback)
179
    {
180
        foreach ($this->val as $lang => $val) {
181
            $this->val[$lang] = call_user_func($sanitizeCallback, $val);
182
        }
183
        return $this;
184
    }
185
186
    /**
187
     * Assign the current translation value(s).
188
     *
189
     * @param Translation|array|string $val The translation value(s).
190
     *     Add one or more translation values.
191
     *
192
     *     Accept 3 types of arguments:
193
     *     - object (TranslationInterface): The data will be copied from the object's.
194
     *     - array: All languages available in the array. The format of the array should
195
     *       be a hash in the `lang` => `string` format.
196
     *     - string: The value will be assigned to the current language.
197
     * @return self
198
     * @throws InvalidArgumentException If language or value are invalid.
199
     */
200
    private function setVal($val)
201
    {
202
        if ($val instanceof Translation) {
203
            $this->val = $val->data();
204
        } elseif (is_array($val)) {
205
            $this->val = [];
206
            foreach ($val as $lang => $l10n) {
207
                if (!is_string($lang)) {
208
                    throw new InvalidArgumentException(sprintf(
209
                        'Invalid language; must be a string, received %s',
210
                        (is_object($lang) ? get_class($lang) : gettype($lang))
211
                    ));
212
                }
213
214
                $this->val[$lang] = (string)$l10n;
215
            }
216
        } elseif (is_string($val)) {
0 ignored issues
show
introduced by
The condition is_string($val) is always true.
Loading history...
217
            $lang = $this->manager->currentLocale();
218
219
            $this->val[$lang] = $val;
220
        } else {
221
            throw new InvalidArgumentException(
222
                'Invalid localized value.'
223
            );
224
        }
225
226
        return $this;
227
    }
228
}
229