Issues (238)

src/Services/Translator.php (5 issues)

1
<?php
2
3
namespace Translation\Services;
4
5
use ArrayAccess;
6
use Illuminate\Database\Eloquent\Model;
7
use JsonSerializable;
8
9
class Translator implements ArrayAccess, JsonSerializable
10
{
11
    protected $model;
12
    protected $attributes = [];
13
    protected $locale;
14
15
    public function __construct(Model $model)
16
    {
17
        if (!$model->relationLoaded('translations')) {
18
            $model->load('translations');
19
        }
20
21
        $this->model = $model;
22
        $this->locale = \Illuminate\Support\Facades\Config::get('sitec.facilitador.multilingual.default', 'en');
23
        $attributes = [];
24
25
        foreach ($this->model->getAttributes() as $attribute => $value) {
26
            $attributes[$attribute] = [
27
                'value'    => $value,
28
                'locale'   => $this->locale,
29
                'exists'   => true,
30
                'modified' => false,
31
            ];
32
        }
33
34
        $this->attributes = $attributes;
35
    }
36
37
    public function translate($locale = null, $fallback = true)
38
    {
39
        $this->locale = $locale;
40
41
        foreach ($this->model->getTranslatableAttributes() as $attribute) {
42
            $this->translateAttribute($attribute, $locale, $fallback);
43
        }
44
45
        return $this;
46
    }
47
48
    /**
49
     * Save changes made to the translator attributes.
50
     *
51
     * @return bool
52
     */
53
    public function save()
54
    {
55
        $attributes = $this->getModifiedAttributes();
56
        $savings = [];
57
58
        foreach ($attributes as $key => $attribute) {
59
            if ($attribute['exists']) {
60
                $translation = $this->getTranslationModel($key);
61
            } else {
62
                $translation = TranslationFacade::model('Translation')->where('table_name', $this->model->getTable())
0 ignored issues
show
The type Translation\Services\TranslationFacade was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
63
                    ->where('column_name', $key)
64
                    ->where('foreign_key', $this->model->getKey())
65
                    ->where('locale', $this->locale)
66
                    ->first();
67
            }
68
69
            if (is_null($translation)) {
70
                $translation = TranslationFacade::model('Translation');
71
            }
72
73
            $translation->fill(
74
                [
75
                'table_name'  => $this->model->getTable(),
76
                'column_name' => $key,
77
                'foreign_key' => $this->model->getKey(),
78
                'value'       => $attribute['value'],
79
                'locale'      => $this->locale,
80
                ]
81
            );
82
83
            $savings[] = $translation->save();
84
85
            $this->attributes[$key]['locale'] = $this->locale;
86
            $this->attributes[$key]['exists'] = true;
87
            $this->attributes[$key]['modified'] = false;
88
        }
89
90
        return in_array(false, $savings);
91
    }
92
93
    public function getModel()
94
    {
95
        return $this->model;
96
    }
97
98
    public function getRawAttributes()
99
    {
100
        return $this->attributes;
101
    }
102
103
    public function getOriginalAttributes()
104
    {
105
        return $this->model->getAttributes();
106
    }
107
108
    public function getOriginalAttribute($key)
109
    {
110
        return $this->model->getAttribute($key);
111
    }
112
113
    public function getTranslationModel($key, $locale = null)
114
    {
115
        return $this->model->getRelation('translations')
116
            ->where('column_name', $key)
117
            ->where('locale', $locale ? $locale : $this->locale)
118
            ->first();
119
    }
120
121
    public function getModifiedAttributes()
122
    {
123
        return collect($this->attributes)->where('modified', 1)->all();
124
    }
125
126
    protected function translateAttribute($attribute, $locale = null, $fallback = true)
127
    {
128
        list($value, $locale, $exists) = $this->model->getTranslatedAttributeMeta($attribute, $locale, $fallback);
129
130
        $this->attributes[$attribute] = [
131
            'value'    => $value,
132
            'locale'   => $locale,
133
            'exists'   => $exists,
134
            'modified' => false,
135
        ];
136
137
        return $this;
138
    }
139
140
    protected function translateAttributeToOriginal($attribute)
141
    {
142
        $this->attributes[$attribute] = [
143
            'value'    => $this->model->attributes[$attribute],
144
            'locale'   => \Illuminate\Support\Facades\Config::get('sitec.facilitador.multilingual.default', 'pt_BR'),
145
            'exists'   => true,
146
            'modified' => false,
147
        ];
148
149
        return $this;
150
    }
151
152
    public function __get($name)
153
    {
154
        if (!isset($this->attributes[$name])) {
155
            if (isset($this->model->$name)) {
156
                return $this->model->$name;
157
            }
158
159
            return;
160
        }
161
162
        if (!$this->attributes[$name]['exists'] && !$this->attributes[$name]['modified']) {
163
            return $this->getOriginalAttribute($name);
164
        }
165
166
        return $this->attributes[$name]['value'];
167
    }
168
169
    public function __set($name, $value)
170
    {
171
        $this->attributes[$name]['value'] = $value;
172
173
        if (!in_array($name, $this->model->getTranslatableAttributes())) {
0 ignored issues
show
It seems like $this->model->getTranslatableAttributes() can also be of type Illuminate\Database\Eloquent\Builder; however, parameter $haystack of in_array() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

173
        if (!in_array($name, /** @scrutinizer ignore-type */ $this->model->getTranslatableAttributes())) {
Loading history...
174
            return $this->model->$name = $value;
175
        }
176
177
        $this->attributes[$name]['modified'] = true;
178
    }
179
180
    public function offsetGet($offset)
181
    {
182
        return $this->attributes[$offset]['value'];
183
    }
184
185
    public function offsetSet($offset, $value)
186
    {
187
        $this->attributes[$offset]['value'] = $value;
188
189
        if (!in_array($offset, $this->model->getTranslatableAttributes())) {
0 ignored issues
show
It seems like $this->model->getTranslatableAttributes() can also be of type Illuminate\Database\Eloquent\Builder; however, parameter $haystack of in_array() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

189
        if (!in_array($offset, /** @scrutinizer ignore-type */ $this->model->getTranslatableAttributes())) {
Loading history...
190
            return $this->model->$offset = $value;
191
        }
192
193
        $this->attributes[$offset]['modified'] = true;
194
    }
195
196
    public function offsetExists($offset)
197
    {
198
        return isset($this->attributes[$offset]);
199
    }
200
201
    public function offsetUnset($offset)
202
    {
203
        unset($this->attributes[$offset]);
204
    }
205
206
    public function getLocale()
207
    {
208
        return $this->locale;
209
    }
210
211
    public function translationAttributeExists($name)
212
    {
213
        if (!isset($this->attributes[$name])) {
214
            return false;
215
        }
216
217
        return $this->attributes[$name]['exists'];
218
    }
219
220
    public function translationAttributeModified($name)
221
    {
222
        if (!isset($this->attributes[$name])) {
223
            return false;
224
        }
225
226
        return $this->attributes[$name]['modified'];
227
    }
228
229
    /**
230
     * @param array-key $key
0 ignored issues
show
Documentation Bug introduced by
The doc comment array-key at position 0 could not be parsed: Unknown type name 'array-key' at position 0 in array-key.
Loading history...
231
     */
232
    public function createTranslation($key, $value)
233
    {
234
        if (!isset($this->attributes[$key])) {
235
            return false;
236
        }
237
238
        if (!in_array($key, $this->model->getTranslatableAttributes())) {
0 ignored issues
show
It seems like $this->model->getTranslatableAttributes() can also be of type Illuminate\Database\Eloquent\Builder; however, parameter $haystack of in_array() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

238
        if (!in_array($key, /** @scrutinizer ignore-type */ $this->model->getTranslatableAttributes())) {
Loading history...
239
            return false;
240
        }
241
242
        $translation = TranslationFacade::model('Translation');
243
        $translation->fill(
244
            [
245
            'table_name'  => $this->model->getTable(),
246
            'column_name' => $key,
247
            'foreign_key' => $this->model->getKey(),
248
            'value'       => $value,
249
            'locale'      => $this->locale,
250
            ]
251
        );
252
        $translation->save();
253
254
        $this->model->getRelation('translations')->add($translation);
255
256
        $this->attributes[$key]['exists'] = true;
257
        $this->attributes[$key]['value'] = $value;
258
259
        return $this->model->getRelation('translations')
260
            ->where('key', $key)
261
            ->where('locale', $this->locale)
262
            ->first();
263
    }
264
265
    public function createTranslations(array $translations)
266
    {
267
        foreach ($translations as $key => $value) {
268
            $this->createTranslation($key, $value);
269
        }
270
    }
271
272
    public function deleteTranslation($key)
273
    {
274
        if (!isset($this->attributes[$key])) {
275
            return false;
276
        }
277
278
        if (!$this->attributes[$key]['exists']) {
279
            return false;
280
        }
281
282
        $translations = $this->model->getRelation('translations');
283
        $locale = $this->locale;
284
285
        TranslationFacade::model('Translation')->where('table_name', $this->model->getTable())
286
            ->where('column_name', $key)
287
            ->where('foreign_key', $this->model->getKey())
288
            ->where('locale', $locale)
289
            ->delete();
290
291
        $this->model->setRelation(
292
            'translations', $translations->filter(
293
                function ($translation) use ($key, $locale) {
294
                    return $translation->column_name != $key && $translation->locale != $locale;
295
                }
296
            )
297
        );
298
299
        $this->attributes[$key]['value'] = null;
300
        $this->attributes[$key]['exists'] = false;
301
        $this->attributes[$key]['modified'] = false;
302
303
        return true;
304
    }
305
306
    public function deleteTranslations(array $keys)
307
    {
308
        foreach ($keys as $key) {
309
            $this->deleteTranslation($key);
310
        }
311
    }
312
313
    public function __call($method, array $arguments)
314
    {
315
        if (!$this->model->hasTranslatorMethod($method)) {
316
            throw new \Exception('Call to undefined method Translation\Translator::'.$method.'()');
317
        }
318
319
        return call_user_func_array([$this, 'runTranslatorMethod'], [$method, $arguments]);
320
    }
321
322
    public function runTranslatorMethod($method, array $arguments)
323
    {
324
        array_unshift($arguments, $this);
325
326
        $method = $this->model->getTranslatorMethod($method);
327
328
        return call_user_func_array([$this->model, $method], $arguments);
329
    }
330
331
    public function jsonSerialize()
332
    {
333
        return array_map(
334
            function ($array) {
335
                return $array['value'];
336
            }, $this->getRawAttributes()
337
        );
338
    }
339
}
340
341
/**
342
 * Veio do SIrael objets
343
 */
344
345
    // /**
346
    //  * Mapping of locales to their base locales
347
    //  *
348
    //  * @var array
349
    //  */
350
    // protected $baseLocaleMap = [
351
    //     'de_informal' => 'de',
352
    // ];
353
354
    // /**
355
    //  * Get the translation for a given key.
356
    //  *
357
    //  * @param  string $key
358
    //  * @param  array  $replace
359
    //  * @param  string $locale
360
    //  * @return string|array|null
361
    //  */
362
    // public function trans($key, array $replace = [], $locale = null)
363
    // {
364
    //     $translation = $this->get($key, $replace, $locale);
365
366
    //     if (is_array($translation)) {
367
    //         $translation = $this->mergeBackupTranslations($translation, $key, $locale);
368
    //     }
369
370
    //     return $translation;
371
    // }
372
373
    // /**
374
    //  * Merge the fallback translations, and base translations if existing,
375
    //  * into the provided core key => value array of translations content.
376
    //  *
377
    //  * @param  array  $translationArray
378
    //  * @param  string $key
379
    //  * @param  null   $locale
380
    //  * @return array
381
    //  */
382
    // protected function mergeBackupTranslations(array $translationArray, string $key, $locale = null)
383
    // {
384
    //     $fallback = $this->get($key, [], $this->fallback);
385
    //     $baseLocale = $this->getBaseLocale($locale ?? $this->locale);
386
    //     $baseTranslations = $baseLocale ? $this->get($key, [], $baseLocale) : [];
387
388
    //     return array_replace_recursive($fallback, $baseTranslations, $translationArray);
389
    // }
390
391
    // /**
392
    //  * Get the array of locales to be checked.
393
    //  *
394
    //  * @param  string|null $locale
395
    //  * @return array
396
    //  */
397
    // protected function localeArray($locale)
398
    // {
399
    //     $primaryLocale = $locale ?: $this->locale;
400
    //     return array_filter([$primaryLocale, $this->getBaseLocale($primaryLocale), $this->fallback]);
401
    // }
402
403
    // /**
404
    //  * Get the locale to extend for the given locale.
405
    //  *
406
    //  * @param  string $locale
407
    //  * @return string|null
408
    //  */
409
    // protected function getBaseLocale($locale)
410
    // {
411
    //     return $this->baseLocaleMap[$locale] ?? null;
412
    // }
413