Issues (238)

src/Traits/Translatable.php (14 issues)

1
<?php
2
3
namespace Translation\Traits;
4
5
use App\Models\SiravelModel;
0 ignored issues
show
The type App\Models\SiravelModel 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...
6
use Translation\Models\Translation;
7
use Translation\Models\ModelTranslation;
8
use Translation\Repositories\TranslationRepository;
9
use Templeiro\Services\CmsService;
0 ignored issues
show
The type Templeiro\Services\CmsService 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...
10
use Exception;
11
use Illuminate\Support\Facades\Config;
12
use Illuminate\Support\Str;
13
use Log;
14
use Translation\GoogleTranslate;
0 ignored issues
show
The type Translation\GoogleTranslate 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...
15
16
trait Translatable
17
{
18
    /**
19
     * Get a translation.
20
     *
21
     * @param string $lang
22
     *
23
     * @return mixed
24
     */
25
    public function translation($lang)
26
    {
27
        return ModelTranslation::where('entity_id', $this->id)
28
            ->where('entity_type', get_class($this))
29
            ->where('entity_data', 'LIKE', '%"lang":"'.$lang.'"%')
30
            ->first();
31
    }
32
33
    /**
34
     * Get translation data.
35
     *
36
     * @param string $lang
37
     *
38
     * @return array|null
39
     */
40
    public function translationData($lang)
41
    {
42
        $translation = $this->translation($lang);
43
44
        if ($translation) {
45
            return json_decode($translation->entity_data);
46
        }
47
48
        return null;
49
    }
50
51
    /**
52
     * Get a translations attribute.
53
     *
54
     * @return array
55
     */
56
    public function getTranslationsAttribute(): array
57
    {
58
        $translationData = [];
59
        $translations = ModelTranslation::where('entity_id', $this->id)->where('entity_type', get_class($this))->get();
60
61
        foreach ($translations as $translation) {
62
            $translationData[] = $translation->data->attributes;
63
        }
64
65
        return $translationData;
66
    }
67
    /**
68
     * COmentado .. Essa funcao é a equivalente do Spatie @todo
69
     *
70
     * @return array
71
     */
72
    // public function getTranslationsAttribute(): array
73
    // {
74
    //     return collect($this->getTranslatableAttributes())
75
    //         ->mapWithKeys(function (string $key) {
76
    //             return [$key => $this->getTranslations($key)];
77
    //         })
78
    //         ->toArray();
79
    // }
80
81
    /**
82
     * After the item is created in the database.
83
     *
84
     * @param object $payload
85
     */
86
    public function afterCreate($payload)
87
    {
88
        if (config('cms.auto-translate', false)) {
89
            $entry = $payload->toArray();
90
91
            unset($entry['created_at']);
92
            unset($entry['updated_at']);
93
            unset($entry['translations']);
94
            unset($entry['is_published']);
95
            unset($entry['published_at']);
96
            unset($entry['id']);
97
98
            foreach (config('cms.languages') as $code => $language) {
99
                if ($code != config('cms.default-language')) {
0 ignored issues
show
The call to config() has too few arguments starting with defaultValue. ( Ignorable by Annotation )

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

99
                if ($code != /** @scrutinizer ignore-call */ config('cms.default-language')) {

This check compares calls to functions or methods with their respective definitions. If the call has less arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
100
                    $tr = new GoogleTranslate(config('cms.default-language'), $code);
101
                    $translation = [
102
                        'lang' => $code,
103
                        'template' => 'show',
104
                    ];
105
106
                    foreach ($entry as $key => $value) {
107
                        if (!empty($value)) {
108
                            try {
109
                                $translation[$key] = json_decode(json_encode($tr->translate(strip_tags($value))));
110
                            } catch (Exception $e) {
111
                                Log::info('[Translate] Erro> '.$e->getMessage());
112
                                unset($translation[$key]);
113
                            }
114
                        }
115
                    }
116
117
                    if (isset($translation['url'])) {
118
                        $translation['url'] = app(CmsService::class)->convertToURL($translation['url']);
0 ignored issues
show
The function app was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

118
                        $translation['url'] = /** @scrutinizer ignore-call */ app(CmsService::class)->convertToURL($translation['url']);
Loading history...
119
                    }
120
121
                    $entityId = $payload->id;
122
                    $entityType = get_class($payload);
123
                    app(TranslationRepository::class)->createOrUpdate($entityId, $entityType, $code, $translation);
124
                }
125
            }
126
        }
127
    }
128
    
129
    /**
130
     * Peguei da Spatie
131
     */
132
133
    public function getAttributeValue($key)
134
    {
135
        if (! $this->isTranslatableAttribute($key)) {
136
            return parent::getAttributeValue($key);
137
        }
138
139
        return $this->getTranslation($key, $this->getLocale());
140
    }
141
142
    public function setAttribute($key, $value)
143
    {
144
        // Pass arrays and untranslatable attributes to the parent method.
145
        if (! $this->isTranslatableAttribute($key) || is_array($value)) {
146
            return parent::setAttribute($key, $value);
147
        }
148
149
        // If the attribute is translatable and not already translated, set a
150
        // translation for the current app locale.
151
        return $this->setTranslation($key, $this->getLocale(), $value);
152
    }
153
154
    public function translate(string $key, string $locale = ''): string
155
    {
156
        return $this->getTranslation($key, $locale);
157
    }
158
159
    public function getTranslation(string $key, string $locale, bool $useFallbackLocale = true)
160
    {
161
        $locale = $this->normalizeLocale($key, $locale, $useFallbackLocale);
162
163
        $translations = $this->getTranslations($key);
164
165
        $translation = $translations[$locale] ?? '';
166
167
        if ($this->hasGetMutator($key)) {
0 ignored issues
show
It seems like hasGetMutator() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

167
        if ($this->/** @scrutinizer ignore-call */ hasGetMutator($key)) {
Loading history...
168
            return $this->mutateAttribute($key, $translation);
0 ignored issues
show
It seems like mutateAttribute() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

168
            return $this->/** @scrutinizer ignore-call */ mutateAttribute($key, $translation);
Loading history...
169
        }
170
171
        return $translation;
172
    }
173
174
    public function getTranslationWithFallback(string $key, string $locale): string
175
    {
176
        return $this->getTranslation($key, $locale, true);
177
    }
178
179
    public function getTranslationWithoutFallback(string $key, string $locale)
180
    {
181
        return $this->getTranslation($key, $locale, false);
182
    }
183
184
    public function getTranslations(string $key = null) : array
185
    {
186
        if ($key !== null) {
187
            $this->guardAgainstNonTranslatableAttribute($key);
188
189
            return array_filter(
190
                json_decode($this->getAttributes()[$key] ?? '' ?: '{}', true) ?: [], function ($value) {
0 ignored issues
show
The method getAttributes() does not exist on Translation\Traits\Translatable. Did you maybe mean getAttributeValue()? ( Ignorable by Annotation )

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

190
                json_decode($this->/** @scrutinizer ignore-call */ getAttributes()[$key] ?? '' ?: '{}', true) ?: [], function ($value) {

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
191
                    return $value !== null && $value !== '';
192
                }
193
            );
194
        }
195
196
        return array_reduce(
197
            $this->getTranslatableAttributes(), function ($result, $item) {
198
                $result[$item] = $this->getTranslations($item);
199
200
                return $result;
201
            }
202
        );
203
    }
204
205
    public function setTranslation(string $key, string $locale, $value): HasTranslations
206
    {
207
        $this->guardAgainstNonTranslatableAttribute($key);
208
209
        $translations = $this->getTranslations($key);
210
211
        $oldValue = $translations[$locale] ?? '';
212
213
        if ($this->hasSetMutator($key)) {
0 ignored issues
show
It seems like hasSetMutator() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

213
        if ($this->/** @scrutinizer ignore-call */ hasSetMutator($key)) {
Loading history...
214
            $method = 'set'.Str::studly($key).'Attribute';
215
216
            $this->{$method}($value, $locale);
217
218
            $value = $this->attributes[$key];
219
        }
220
221
        $translations[$locale] = $value;
222
223
        $this->attributes[$key] = $this->asJson($translations);
0 ignored issues
show
Bug Best Practice introduced by
The property attributes does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
It seems like asJson() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

223
        /** @scrutinizer ignore-call */ 
224
        $this->attributes[$key] = $this->asJson($translations);
Loading history...
224
225
        event(new TranslationHasBeenSet($this, $key, $locale, $oldValue, $value));
0 ignored issues
show
The type Translation\Traits\TranslationHasBeenSet 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...
The function event was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

225
        /** @scrutinizer ignore-call */ 
226
        event(new TranslationHasBeenSet($this, $key, $locale, $oldValue, $value));
Loading history...
226
227
        return $this;
228
    }
229
230
    public function setTranslations(string $key, array $translations): HasTranslations
231
    {
232
        $this->guardAgainstNonTranslatableAttribute($key);
233
234
        foreach ($translations as $locale => $translation) {
235
            $this->setTranslation($key, $locale, $translation);
236
        }
237
238
        return $this;
239
    }
240
241
    public function forgetTranslation(string $key, string $locale): HasTranslations
242
    {
243
        $translations = $this->getTranslations($key);
244
245
        unset($translations[$locale]);
246
247
        $this->setAttribute($key, $translations);
248
249
        return $this;
250
    }
251
252
    public function forgetAllTranslations(string $locale): HasTranslations
253
    {
254
        collect($this->getTranslatableAttributes())->each(
255
            function (string $attribute) use ($locale) {
256
                $this->forgetTranslation($attribute, $locale);
257
            }
258
        );
259
260
        return $this;
261
    }
262
263
    public function getTranslatedLocales(string $key) : array
264
    {
265
        return array_keys($this->getTranslations($key));
266
    }
267
268
    public function isTranslatableAttribute(string $key) : bool
269
    {
270
        return in_array($key, $this->getTranslatableAttributes());
271
    }
272
273
    public function hasTranslation(string $key, string $locale = null): bool
274
    {
275
        $locale = $locale ?: $this->getLocale();
276
277
        return isset($this->getTranslations($key)[$locale]);
278
    }
279
280
    protected function guardAgainstNonTranslatableAttribute(string $key)
281
    {
282
        if (! $this->isTranslatableAttribute($key)) {
283
            throw AttributeIsNotTranslatable::make($key, $this);
0 ignored issues
show
The type Translation\Traits\AttributeIsNotTranslatable 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...
284
        }
285
    }
286
287
    protected function normalizeLocale(string $key, string $locale, bool $useFallbackLocale) : string
288
    {
289
        if (in_array($locale, $this->getTranslatedLocales($key))) {
290
            return $locale;
291
        }
292
293
        if (! $useFallbackLocale) {
294
            return $locale;
295
        }
296
297
        if (! is_null($fallbackLocale = Config::get('translatable.fallback_locale'))) {
298
            return $fallbackLocale;
299
        }
300
301
        if (! is_null($fallbackLocale = Config::get('app.fallback_locale'))) {
302
            return $fallbackLocale;
303
        }
304
305
        return $locale;
306
    }
307
308
    protected function getLocale() : string
309
    {
310
        return Config::get('app.locale');
311
    }
312
313
    public function getTranslatableAttributes() : array
314
    {
315
        return is_array($this->translatable)
316
            ? $this->translatable
317
            : [];
318
    }
319
320
    public function getCasts() : array
321
    {
322
        return array_merge(
323
            parent::getCasts(),
324
            array_fill_keys($this->getTranslatableAttributes(), 'array')
325
        );
326
    }
327
}
328