Completed
Pull Request — master (#100)
by ARCANEDEV
14:05
created

HasTranslations::trans()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 2
dl 0
loc 4
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php namespace Arcanedev\Localization\Traits;
2
3
use Arcanedev\Localization\Events\TranslationHasBeenSet;
4
use Arcanedev\Localization\Exceptions\UntranslatableAttributeException;
5
use Illuminate\Support\Str;
6
7
/**
8
 * Trait     HasTranslations
9
 *
10
 * @package  Arcanedev\Localization\Traits
11
 * @author   ARCANEDEV <[email protected]>
12
 */
13
trait HasTranslations
14
{
15
    /* -----------------------------------------------------------------
16
     |  Main Methods
17
     | -----------------------------------------------------------------
18
     */
19
20
    /**
21
     * Get the translatable attributes.
22
     *
23
     * @return array
24
     */
25
    abstract public function getTranslatableAttributes();
26
27
    /**
28
     * Get the translated attribute value.
29
     *
30
     * @param  string  $key
31
     *
32
     * @return mixed
33
     */
34 18
    public function getAttributeValue($key)
35
    {
36 18
        return $this->isTranslatableAttribute($key)
37 18
            ? $this->getTranslation($key, config('app.locale'))
38 18
            : parent::getAttributeValue($key);
39
    }
40
41
    /**
42
     * Get the translated attribute (alias).
43
     *
44
     * @param  string  $key
45
     * @param  string  $locale
46
     *
47
     * @return mixed
48
     */
49 6
    public function trans($key, $locale = '')
50
    {
51 6
        return $this->getTranslation($key, $locale);
52
    }
53
54
    /***
55
     * Get the translated attribute.
56
     *
57
     * @param  string  $key
58
     * @param  string  $locale
59
     * @param  bool    $useFallback
60
     *
61
     * @return mixed
62
     */
63 33
    public function getTranslation($key, $locale, $useFallback = true)
64
    {
65 33
        $locale       = $this->normalizeLocale($key, $locale, $useFallback);
66 33
        $translations = $this->getTranslations($key);
67 33
        $translation  = isset($translations[$locale]) ? $translations[$locale] : '';
68
69 33
        return $this->hasGetMutator($key)
70 31
            ? $this->mutateAttribute($key, $translation)
71 33
            : $translation;
72
    }
73
74
    /**
75
     * Get the translations for the given key.
76
     *
77
     * @param  string  $key
78
     *
79
     * @return array
80
     */
81 48
    public function getTranslations($key)
82
    {
83 48
        $this->guardAgainstUntranslatableAttribute($key);
84
85 48
        return json_decode($this->getAttributeFromArray($key) ?: '{}', true);
86
    }
87
88
    /**
89
     * Set a translation.
90
     *
91
     * @param  string  $key
92
     * @param  string  $locale
93
     * @param  string  $value
94
     *
95
     * @return $this
96
     */
97 48
    public function setTranslation($key, $locale, $value)
98
    {
99 48
        $this->guardAgainstUntranslatableAttribute($key);
100
101 45
        $translations = $this->getTranslations($key);
102 45
        $oldValue     = isset($translations[$locale]) ? $translations[$locale] : '';
103
104 45
        if ($this->hasSetMutator($key))
105 19
            $value = $this->{'set'.Str::studly($key).'Attribute'}($value);
106
107 45
        $translations[$locale]  = $value;
108 45
        $this->attributes[$key] = json_encode($translations);
0 ignored issues
show
Bug introduced by
The property attributes does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
109
110 45
        event(new TranslationHasBeenSet($this, $key, $locale, $oldValue, $value));
111
112 45
        return $this;
113
    }
114
115
    /**
116
     * Set the translations.
117
     *
118
     * @param  string  $key
119
     * @param  array   $translations
120
     *
121
     * @return self
122
     */
123 3
    public function setTranslations($key, array $translations)
124
    {
125 3
        $this->guardAgainstUntranslatableAttribute($key);
126
127 3
        foreach ($translations as $locale => $translation) {
128 3
            $this->setTranslation($key, $locale, $translation);
129 1
        }
130
131 3
        return $this;
132
    }
133
134
    /**
135
     * Forget a translation.
136
     *
137
     * @param  string  $key
138
     * @param  string  $locale
139
     *
140
     * @return self
141
     */
142 6
    public function forgetTranslation($key, $locale)
143
    {
144 6
        $translations = $this->getTranslations($key);
145 6
        unset($translations[$locale]);
146
147 6
        if ($this->hasSetMutator($key))
148 4
            $this->attributes[$key] = json_encode($this->mutateTranslations($key, $translations));
149
        else
150 6
            $this->setAttribute($key, $translations);
151
152 6
        return $this;
153
    }
154
155
    /**
156
     * Forget all the translations by the given locale.
157
     *
158
     * @param  string  $locale
159
     */
160 3
    public function flushTranslations($locale)
161
    {
162
        collect($this->getTranslatableAttributes())->each(function ($attribute) use ($locale) {
163 3
            $this->forgetTranslation($attribute, $locale);
164 3
        });
165 3
    }
166
167
    /**
168
     * Get the translated attribute's locales
169
     *
170
     * @param  string  $key
171
     *
172
     * @return array
173
     */
174 36
    public function getTranslatedLocales($key)
175
    {
176 36
        return array_keys($this->getTranslations($key));
177
    }
178
179
    /**
180
     * Check if the attribute is translatable.
181
     *
182
     * @param  string  $key
183
     *
184
     * @return bool
185
     */
186 54
    public function isTranslatableAttribute($key)
187
    {
188 54
        return in_array($key, $this->getTranslatableAttributes());
189
    }
190
191
    /* -----------------------------------------------------------------
192
     |  Other Methods
193
     | -----------------------------------------------------------------
194
     */
195
196
    /**
197
     * Guard against untranslatable attribute.
198
     *
199
     * @param  string  $key
200
     *
201
     * @throws \Arcanedev\Localization\Exceptions\UntranslatableAttributeException
202
     */
203 51
    protected function guardAgainstUntranslatableAttribute($key)
204
    {
205 51
        if ( ! $this->isTranslatableAttribute($key)) {
206 3
            $translatable = implode(', ', $this->getTranslatableAttributes());
207
208 3
            throw new UntranslatableAttributeException(
209 3
                "The attribute `{$key}` is untranslatable because it's not available in the translatable array: `$translatable`"
210 1
            );
211
        }
212 48
    }
213
214
    /**
215
     * Normalize the locale.
216
     *
217
     * @param  string  $key
218
     * @param  string  $locale
219
     * @param  bool    $useFallback
220
     *
221
     * @return string
222
     */
223 33
    protected function normalizeLocale($key, $locale, $useFallback)
224
    {
225 33
        if (in_array($locale, $this->getTranslatedLocales($key)) || ! $useFallback)
226 29
            return $locale;
227
228 9
        return is_null($fallbackLocale = config('app.fallback_locale')) ? $locale : $fallbackLocale;
229
    }
230
231
    /**
232
     * Mutate many translations.
233
     *
234
     * @param  string  $key
235
     * @param  array   $translations
236
     *
237
     * @return string
238
     */
239 3
    protected function mutateTranslations($key, array $translations)
240
    {
241 3
        $method = 'set'.Str::studly($key).'Attribute';
242
243 3
        return array_map(function ($value) use ($method) {
244 3
            return $this->{$method}($value);
245 3
        }, $translations);
246
    }
247
248
    /* -----------------------------------------------------------------
249
     |  Eloquent Methods
250
     | -----------------------------------------------------------------
251
     */
252
253
    /**
254
     * Get the casts array.
255
     *
256
     * @return array
257
     */
258 39
    public function getCasts()
259
    {
260 39
        return array_merge(
261 39
            parent::getCasts(), array_fill_keys($this->getTranslatableAttributes(), 'array')
262 13
        );
263
    }
264
265
    /**
266
     * Determine if a get mutator exists for an attribute.
267
     *
268
     * @param  string  $key
269
     *
270
     * @return bool
271
     */
272
    abstract public function hasGetMutator($key);
273
274
    /**
275
     * Get the value of an attribute using its mutator.
276
     *
277
     * @param  string  $key
278
     * @param  mixed  $value
279
     * @return mixed
280
     */
281
    abstract protected function mutateAttribute($key, $value);
282
283
    /**
284
     * Get an attribute from the $attributes array.
285
     *
286
     * @param  string  $key
287
     *
288
     * @return mixed
289
     */
290
    abstract protected function getAttributeFromArray($key);
291
292
    /**
293
     * Set a given attribute on the model.
294
     *
295
     * @param  string  $key
296
     * @param  mixed  $value
297
     * @return $this
298
     */
299
    abstract public function setAttribute($key, $value);
300
301
    /**
302
     * Determine if a set mutator exists for an attribute.
303
     *
304
     * @param  string  $key
305
     *
306
     * @return bool
307
     */
308
    abstract public function hasSetMutator($key);
309
310
    /**
311
     * Encode the given value as JSON.
312
     *
313
     * @param  mixed  $value
314
     *
315
     * @return string
316
     */
317
    abstract protected function asJson($value);
318
}
319