Test Setup Failed
Push — master ( 485b33...0980dd )
by Tom
06:34 queued 10s
created

src/Translatable/Translatable.php (2 issues)

Labels

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace Dimsav\Translatable;
4
5
use Illuminate\Database\Eloquent\Model;
6
use Illuminate\Database\Eloquent\Builder;
7
use Illuminate\Database\Query\JoinClause;
8
use Illuminate\Database\Eloquent\Relations\Relation;
9
use Illuminate\Database\Query\Builder as QueryBuilder;
10
11
trait Translatable
12
{
13
    protected static $autoloadTranslations = null;
14
15
    protected $defaultLocale;
16
17 480
    public static function bootTranslatable(): void
18
    {
19
        static::saved(function (Model $model) {
20
            /* @var Translatable $model */
21 480
            return $model->saveTranslations();
22 480
        });
23 480
    }
24
25
    /**
26
     * Alias for getTranslation().
27
     *
28
     * @param string|null $locale
29
     * @param bool        $withFallback
30
     *
31
     * @return \Illuminate\Database\Eloquent\Model|null
32
     */
33 52
    public function translate($locale = null, $withFallback = false)
34
    {
35 52
        return $this->getTranslation($locale, $withFallback);
36
    }
37
38
    /**
39
     * Alias for getTranslation().
40
     *
41
     * @param string $locale
42
     *
43
     * @return \Illuminate\Database\Eloquent\Model|null
44
     */
45 4
    public function translateOrDefault($locale = null)
46
    {
47 4
        return $this->getTranslation($locale, true);
48
    }
49
50
    /**
51
     * Alias for getTranslationOrNew().
52
     *
53
     * @param string $locale
54
     *
55
     * @return \Illuminate\Database\Eloquent\Model|null
56
     */
57 4
    public function translateOrNew($locale = null)
58
    {
59 4
        return $this->getTranslationOrNew($locale);
60
    }
61
62
    /**
63
     * @param string|null $locale
64
     * @param bool        $withFallback
65
     *
66
     * @return \Illuminate\Database\Eloquent\Model|null
67
     */
68 252
    public function getTranslation($locale = null, $withFallback = null)
69
    {
70 252
        $configFallbackLocale = $this->getFallbackLocale();
71 252
        $locale = $locale ?: $this->locale();
72 252
        $withFallback = $withFallback === null ? $this->useFallback() : $withFallback;
73 252
        $fallbackLocale = $this->getFallbackLocale($locale);
74
75 252
        if ($translation = $this->getTranslationByLocaleKey($locale)) {
76 144
            return $translation;
77
        }
78 172
        if ($withFallback && $fallbackLocale) {
79 28
            if ($translation = $this->getTranslationByLocaleKey($fallbackLocale)) {
80 16
                return $translation;
81
            }
82 12
            if ($fallbackLocale !== $configFallbackLocale && $translation = $this->getTranslationByLocaleKey($configFallbackLocale)) {
83 8
                return $translation;
84
            }
85
        }
86
87 168
        return null;
88
    }
89
90
    /**
91
     * @param string|null $locale
92
     *
93
     * @return bool
94
     */
95 12
    public function hasTranslation($locale = null)
96
    {
97 12
        $locale = $locale ?: $this->locale();
98
99 12
        foreach ($this->translations as $translation) {
100 4
            if ($translation->getAttribute($this->getLocaleKey()) == $locale) {
101 4
                return true;
102
            }
103
        }
104
105 12
        return false;
106
    }
107
108
    /**
109
     * @return string
110
     */
111 316
    public function getTranslationModelName()
112
    {
113 316
        return $this->translationModel ?: $this->getTranslationModelNameDefault();
114
    }
115
116
    /**
117
     * @return string
118
     */
119 304
    public function getTranslationModelNameDefault()
120
    {
121 304
        $modelName = get_class($this);
122
123 304
        if ($namespace = $this->getTranslationModelNamespace()) {
124 4
            $modelName = $namespace.'\\'.class_basename(get_class($this));
125
        }
126
127 304
        return $modelName.config('translatable.translation_suffix', 'Translation');
128
    }
129
130
    /**
131
     * @return string|null
132
     */
133 304
    public function getTranslationModelNamespace()
134
    {
135 304
        return config('translatable.translation_model_namespace');
136
    }
137
138
    /**
139
     * @return string
140
     */
141 316
    public function getRelationKey()
142
    {
143 316
        if ($this->translationForeignKey) {
144 28
            return $this->translationForeignKey;
0 ignored issues
show
The property translationForeignKey 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...
145
        }
146
147 292
        return $this->getForeignKey();
0 ignored issues
show
It seems like getForeignKey() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
148
    }
149
150
    /**
151
     * @return string
152
     */
153 296
    public function getLocaleKey()
154
    {
155 296
        return $this->localeKey ?: config('translatable.locale_key', 'locale');
156
    }
157
158
    /**
159
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
160
     */
161 296
    public function translations()
162
    {
163 296
        return $this->hasMany($this->getTranslationModelName(), $this->getRelationKey());
164
    }
165
166
    /**
167
     * @return bool
168
     */
169 16
    private function usePropertyFallback()
170
    {
171 16
        return $this->useFallback() && config('translatable.use_property_fallback', false);
172
    }
173
174
    /**
175
     * Returns the attribute value from fallback translation if value of attribute
176
     * is empty and the property fallback is enabled in the configuration.
177
     * in model.
178
     * @param $locale
179
     * @param $attribute
180
     * @return mixed
181
     */
182 96
    private function getAttributeOrFallback($locale, $attribute)
183
    {
184 96
        $translation = $this->getTranslation($locale);
185
186
        if (
187
            (
188 96
                ! $translation instanceof Model ||
189 96
                $this->isEmptyTranslatableAttribute($attribute, $translation->$attribute)
190
            ) &&
191 96
            $this->usePropertyFallback()
192
        ) {
193 12
            $translation = $this->getTranslation($this->getFallbackLocale(), false);
194
        }
195
196 96
        if ($translation instanceof Model) {
197 92
            return $translation->$attribute;
198
        }
199
200 8
        return null;
201
    }
202
203 88
    protected function isEmptyTranslatableAttribute(string $key, $value): bool
204
    {
205 88
        return empty($value);
206
    }
207
208
    /**
209
     * @param string $key
210
     *
211
     * @return mixed
212
     */
213 480
    public function getAttribute($key)
214
    {
215 480
        [$attribute, $locale] = $this->getAttributeAndLocale($key);
216
217 480
        if ($this->isTranslationAttribute($attribute)) {
218 76
            if ($this->getTranslation($locale) === null) {
219 12
                return $this->getAttributeValue($attribute);
220
            }
221
222
            // If the given $attribute has a mutator, we push it to $attributes and then call getAttributeValue
223
            // on it. This way, we can use Eloquent's checking for Mutation, type casting, and
224
            // Date fields.
225 64
            if ($this->hasGetMutator($attribute)) {
226 4
                $this->attributes[$attribute] = $this->getAttributeOrFallback($locale, $attribute);
227
228 4
                return $this->getAttributeValue($attribute);
229
            }
230
231 60
            return $this->getAttributeOrFallback($locale, $attribute);
232
        }
233
234 480
        return parent::getAttribute($key);
235
    }
236
237
    /**
238
     * @param string $key
239
     * @param mixed  $value
240
     *
241
     * @return $this
242
     */
243 480
    public function setAttribute($key, $value)
244
    {
245 480
        [$attribute, $locale] = $this->getAttributeAndLocale($key);
246
247 480
        if ($this->isTranslationAttribute($attribute)) {
248 40
            $this->getTranslationOrNew($locale)->$attribute = $value;
249
        } else {
250 480
            return parent::setAttribute($key, $value);
251
        }
252
253 40
        return $this;
254
    }
255
256
    /**
257
     * @param string $locale
258
     *
259
     * @return \Illuminate\Database\Eloquent\Model
260
     */
261 144
    protected function getTranslationOrNew($locale = null)
262
    {
263 144
        $locale = $locale ?: $this->locale();
264
265 144
        if (($translation = $this->getTranslation($locale, false)) === null) {
266 128
            $translation = $this->getNewTranslation($locale);
267
        }
268
269 144
        return $translation;
270
    }
271
272
    /**
273
     * @param array $attributes
274
     *
275
     * @throws \Illuminate\Database\Eloquent\MassAssignmentException
276
     * @return $this
277
     */
278 480
    public function fill(array $attributes)
279
    {
280 480
        foreach ($attributes as $key => $values) {
281 112
            if ($this->isKeyALocale($key)) {
282 52
                $this->getTranslationOrNew($key)->fill($values);
283 44
                unset($attributes[$key]);
284
            } else {
285 104
                [$attribute, $locale] = $this->getAttributeAndLocale($key);
286 104
                if ($this->isTranslationAttribute($attribute) and $this->isKeyALocale($locale)) {
287 48
                    $this->getTranslationOrNew($locale)->fill([$attribute => $values]);
288 48
                    unset($attributes[$key]);
289
                }
290
            }
291
        }
292
293 480
        return parent::fill($attributes);
294
    }
295
296
    /**
297
     * @param string $key
298
     */
299 252
    private function getTranslationByLocaleKey($key)
300
    {
301 252
        foreach ($this->translations as $translation) {
302 200
            if ($translation->getAttribute($this->getLocaleKey()) == $key) {
303 168
                return $translation;
304
            }
305
        }
306
307 172
        return null;
308
    }
309
310
    /**
311
     * @param null $locale
312
     *
313
     * @return string
314
     */
315 256
    private function getFallbackLocale($locale = null)
316
    {
317 256
        if ($locale && $this->isLocaleCountryBased($locale)) {
318 28
            if ($fallback = $this->getLanguageFromCountryBasedLocale($locale)) {
319 28
                return $fallback;
320
            }
321
        }
322
323 256
        return config('translatable.fallback_locale');
324
    }
325
326 252
    private function isLocaleCountryBased(string $locale): bool
327
    {
328 252
        return $this->getLocalesHelper()->isLocaleCountryBased($locale);
329
    }
330
331 28
    private function getLanguageFromCountryBasedLocale(string $locale): string
332
    {
333 28
        return $this->getLocalesHelper()->getLanguageFromCountryBasedLocale($locale);
334
    }
335
336
    /**
337
     * @return bool|null
338
     */
339 148
    private function useFallback()
340
    {
341 148
        if (isset($this->useTranslationFallback) && $this->useTranslationFallback !== null) {
342 12
            return $this->useTranslationFallback;
343
        }
344
345 136
        return config('translatable.use_fallback');
346
    }
347
348
    /**
349
     * @param string $key
350
     *
351
     * @return bool
352
     */
353 480
    public function isTranslationAttribute($key)
354
    {
355 480
        return in_array($key, $this->translatedAttributes);
356
    }
357
358 112
    protected function isKeyALocale(string $key): bool
359
    {
360 112
        return $this->getLocalesHelper()->has($key);
361
    }
362
363
    protected function getLocales(): array
364
    {
365
        return $this->getLocalesHelper()->all();
366
    }
367
368
    protected function getLocaleSeparator(): string
369
    {
370
        return $this->getLocalesHelper()->getLocaleSeparator();
371
    }
372
373
    /**
374
     * @return bool
375
     */
376 480
    protected function saveTranslations()
377
    {
378 480
        $saved = true;
379
380 480
        if (! $this->relationLoaded('translations')) {
381 480
            return $saved;
382
        }
383
384 104
        foreach ($this->translations as $translation) {
385 104
            if ($saved && $this->isTranslationDirty($translation)) {
386 104
                if (! empty($connectionName = $this->getConnectionName())) {
387 104
                    $translation->setConnection($connectionName);
388
                }
389
390 104
                $translation->setAttribute($this->getRelationKey(), $this->getKey());
391 104
                $saved = $translation->save();
392
            }
393
        }
394
395 100
        return $saved;
396
    }
397
398
    /**
399
     * @param array
400
     *
401
     * @return \Illuminate\Database\Eloquent\Model
402
     */
403 4
    public function replicateWithTranslations(array $except = null)
404
    {
405 4
        $newInstance = parent::replicate($except);
406
407 4
        unset($newInstance->translations);
408 4
        foreach ($this->translations as $translation) {
409 4
            $newTranslation = $translation->replicate();
410 4
            $newInstance->translations->add($newTranslation);
411
        }
412
413 4
        return  $newInstance;
414
    }
415
416
    /**
417
     * @param \Illuminate\Database\Eloquent\Model $translation
418
     *
419
     * @return bool
420
     */
421 104
    protected function isTranslationDirty(Model $translation)
422
    {
423 104
        $dirtyAttributes = $translation->getDirty();
424 104
        unset($dirtyAttributes[$this->getLocaleKey()]);
425
426 104
        return count($dirtyAttributes) > 0;
427
    }
428
429
    /**
430
     * @param string $locale
431
     *
432
     * @return \Illuminate\Database\Eloquent\Model
433
     */
434 132
    public function getNewTranslation($locale)
435
    {
436 132
        $modelName = $this->getTranslationModelName();
437 132
        $translation = new $modelName();
438 132
        $translation->setAttribute($this->getLocaleKey(), $locale);
439 132
        $this->translations->add($translation);
440
441 132
        return $translation;
442
    }
443
444
    /**
445
     * @param $key
446
     *
447
     * @return bool
448
     */
449 152
    public function __isset($key)
450
    {
451 152
        return $this->isTranslationAttribute($key) || parent::__isset($key);
452
    }
453
454
    /**
455
     * @param \Illuminate\Database\Eloquent\Builder $query
456
     * @param string                                $locale
457
     *
458
     * @return \Illuminate\Database\Eloquent\Builder|static
459
     */
460 8
    public function scopeTranslatedIn(Builder $query, $locale = null)
461
    {
462 8
        $locale = $locale ?: $this->locale();
463
464
        return $query->whereHas('translations', function (Builder $q) use ($locale) {
465 8
            $q->where($this->getLocaleKey(), '=', $locale);
466 8
        });
467
    }
468
469
    /**
470
     * @param \Illuminate\Database\Eloquent\Builder $query
471
     * @param string                                $locale
472
     *
473
     * @return \Illuminate\Database\Eloquent\Builder|static
474
     */
475 8
    public function scopeNotTranslatedIn(Builder $query, $locale = null)
476
    {
477 8
        $locale = $locale ?: $this->locale();
478
479
        return $query->whereDoesntHave('translations', function (Builder $q) use ($locale) {
480 8
            $q->where($this->getLocaleKey(), '=', $locale);
481 8
        });
482
    }
483
484
    /**
485
     * @param \Illuminate\Database\Eloquent\Builder $query
486
     *
487
     * @return \Illuminate\Database\Eloquent\Builder|static
488
     */
489 4
    public function scopeTranslated(Builder $query)
490
    {
491 4
        return $query->has('translations');
492
    }
493
494
    /**
495
     * Adds scope to get a list of translated attributes, using the current locale.
496
     * Example usage: Country::listsTranslations('name')->get()->toArray()
497
     * Will return an array with items:
498
     *  [
499
     *      'id' => '1',                // The id of country
500
     *      'name' => 'Griechenland'    // The translated name
501
     *  ].
502
     *
503
     * @param \Illuminate\Database\Eloquent\Builder $query
504
     * @param string                                $translationField
505
     */
506 12
    public function scopeListsTranslations(Builder $query, $translationField)
507
    {
508 12
        $withFallback = $this->useFallback();
509 12
        $translationTable = $this->getTranslationsTable();
510 12
        $localeKey = $this->getLocaleKey();
511
512
        $query
513 12
            ->select($this->getTable().'.'.$this->getKeyName(), $translationTable.'.'.$translationField)
514 12
            ->leftJoin($translationTable, $translationTable.'.'.$this->getRelationKey(), '=', $this->getTable().'.'.$this->getKeyName())
515 12
            ->where($translationTable.'.'.$localeKey, $this->locale());
516 12
        if ($withFallback) {
517
            $query->orWhere(function (Builder $q) use ($translationTable, $localeKey) {
518 4
                $q->where($translationTable.'.'.$localeKey, $this->getFallbackLocale())
519
                  ->whereNotIn($translationTable.'.'.$this->getRelationKey(), function (QueryBuilder $q) use (
520 4
                      $translationTable,
521 4
                      $localeKey
522
                  ) {
523 4
                      $q->select($translationTable.'.'.$this->getRelationKey())
524 4
                        ->from($translationTable)
525 4
                        ->where($translationTable.'.'.$localeKey, $this->locale());
526 4
                  });
527 4
            });
528
        }
529 12
    }
530
531
    /**
532
     * This scope eager loads the translations for the default and the fallback locale only.
533
     * We can use this as a shortcut to improve performance in our application.
534
     *
535
     * @param Builder $query
536
     */
537 12
    public function scopeWithTranslation(Builder $query)
538
    {
539 12
        $query->with([
540
            'translations' => function (Relation $query) {
541 12
                if ($this->useFallback()) {
542 8
                    $locale = $this->locale();
543 8
                    $countryFallbackLocale = $this->getFallbackLocale($locale); // e.g. de-DE => de
544 8
                    $locales = array_unique([$locale, $countryFallbackLocale, $this->getFallbackLocale()]);
545
546 8
                    return $query->whereIn($this->getTranslationsTable().'.'.$this->getLocaleKey(), $locales);
547
                }
548
549 4
                return $query->where($this->getTranslationsTable().'.'.$this->getLocaleKey(), $this->locale());
550 12
            },
551
        ]);
552 12
    }
553
554
    /**
555
     * This scope filters results by checking the translation fields.
556
     *
557
     * @param \Illuminate\Database\Eloquent\Builder $query
558
     * @param string                                $key
559
     * @param string                                $value
560
     * @param string                                $locale
561
     *
562
     * @return \Illuminate\Database\Eloquent\Builder|static
563
     */
564 12
    public function scopeWhereTranslation(Builder $query, $key, $value, $locale = null)
565
    {
566
        return $query->whereHas('translations', function (Builder $query) use ($key, $value, $locale) {
567 12
            $query->where($this->getTranslationsTable().'.'.$key, $value);
568 12
            if ($locale) {
569 4
                $query->where($this->getTranslationsTable().'.'.$this->getLocaleKey(), $locale);
570
            }
571 12
        });
572
    }
573
574
    /**
575
     * This scope filters results by checking the translation fields.
576
     *
577
     * @param \Illuminate\Database\Eloquent\Builder $query
578
     * @param string                                $key
579
     * @param string                                $value
580
     * @param string                                $locale
581
     *
582
     * @return \Illuminate\Database\Eloquent\Builder|static
583
     */
584 4
    public function scopeOrWhereTranslation(Builder $query, $key, $value, $locale = null)
585
    {
586
        return $query->orWhereHas('translations', function (Builder $query) use ($key, $value, $locale) {
587 4
            $query->where($this->getTranslationsTable().'.'.$key, $value);
588 4
            if ($locale) {
589
                $query->where($this->getTranslationsTable().'.'.$this->getLocaleKey(), $locale);
590
            }
591 4
        });
592
    }
593
594
    /**
595
     * This scope filters results by checking the translation fields.
596
     *
597
     * @param \Illuminate\Database\Eloquent\Builder $query
598
     * @param string                                $key
599
     * @param string                                $value
600
     * @param string                                $locale
601
     *
602
     * @return \Illuminate\Database\Eloquent\Builder|static
603
     */
604 12
    public function scopeWhereTranslationLike(Builder $query, $key, $value, $locale = null)
605
    {
606
        return $query->whereHas('translations', function (Builder $query) use ($key, $value, $locale) {
607 12
            $query->where($this->getTranslationsTable().'.'.$key, 'LIKE', $value);
608 12
            if ($locale) {
609 4
                $query->where($this->getTranslationsTable().'.'.$this->getLocaleKey(), 'LIKE', $locale);
610
            }
611 12
        });
612
    }
613
614
    /**
615
     * This scope filters results by checking the translation fields.
616
     *
617
     * @param \Illuminate\Database\Eloquent\Builder $query
618
     * @param string                                $key
619
     * @param string                                $value
620
     * @param string                                $locale
621
     *
622
     * @return \Illuminate\Database\Eloquent\Builder|static
623
     */
624 4
    public function scopeOrWhereTranslationLike(Builder $query, $key, $value, $locale = null)
625
    {
626
        return $query->orWhereHas('translations', function (Builder $query) use ($key, $value, $locale) {
627 4
            $query->where($this->getTranslationsTable().'.'.$key, 'LIKE', $value);
628 4
            if ($locale) {
629
                $query->where($this->getTranslationsTable().'.'.$this->getLocaleKey(), 'LIKE', $locale);
630
            }
631 4
        });
632
    }
633
634
    /**
635
     * This scope sorts results by the given translation field.
636
     *
637
     * @param \Illuminate\Database\Eloquent\Builder $query
638
     * @param string                                $key
639
     * @param string                                $sortmethod
640
     *
641
     * @return \Illuminate\Database\Eloquent\Builder|static
642
     */
643 8
    public function scopeOrderByTranslation(Builder $query, $key, $sortmethod = 'asc')
644
    {
645 8
        $translationTable = $this->getTranslationsTable();
646 8
        $localeKey = $this->getLocaleKey();
647 8
        $table = $this->getTable();
648 8
        $keyName = $this->getKeyName();
649
650
        return $query
651
            ->join($translationTable, function (JoinClause $join) use ($translationTable, $localeKey, $table, $keyName) {
652
                $join
653 8
                    ->on($translationTable.'.'.$this->getRelationKey(), '=', $table.'.'.$keyName)
654 8
                    ->where($translationTable.'.'.$localeKey, $this->locale());
655 8
            })
656 8
            ->orderBy($translationTable.'.'.$key, $sortmethod)
657 8
            ->select($table.'.*')
658 8
            ->with('translations');
659
    }
660
661
    /**
662
     * @return array
663
     */
664 48
    public function attributesToArray()
665
    {
666 48
        $attributes = parent::attributesToArray();
667
668
        if (
669 48
            (! $this->relationLoaded('translations') && ! $this->toArrayAlwaysLoadsTranslations() && is_null(self::$autoloadTranslations))
670 48
            || self::$autoloadTranslations === false
671
        ) {
672 16
            return $attributes;
673
        }
674
675 32
        $hiddenAttributes = $this->getHidden();
676
677 32
        foreach ($this->translatedAttributes as $field) {
678 32
            if (in_array($field, $hiddenAttributes)) {
679 4
                continue;
680
            }
681
682 32
            $attributes[$field] = $this->getAttributeOrFallback(null, $field);
683
        }
684
685 32
        return $attributes;
686
    }
687
688
    /**
689
     * @return array
690
     */
691 4
    public function getTranslationsArray()
692
    {
693 4
        $translations = [];
694
695 4
        foreach ($this->translations as $translation) {
696 4
            foreach ($this->translatedAttributes as $attr) {
697 4
                $translations[$translation->{$this->getLocaleKey()}][$attr] = $translation->{$attr};
698
            }
699
        }
700
701 4
        return $translations;
702
    }
703
704
    /**
705
     * @return string
706
     */
707 56
    private function getTranslationsTable()
708
    {
709 56
        return app()->make($this->getTranslationModelName())->getTable();
710
    }
711
712 480
    protected function locale(): string
713
    {
714 480
        if ($this->defaultLocale) {
715 4
            return $this->defaultLocale;
716
        }
717
718 480
        return $this->getLocalesHelper()->current();
719
    }
720
721
    /**
722
     * Set the default locale on the model.
723
     *
724
     * @param $locale
725
     *
726
     * @return $this
727
     */
728 4
    public function setDefaultLocale($locale)
729
    {
730 4
        $this->defaultLocale = $locale;
731
732 4
        return $this;
733
    }
734
735
    /**
736
     * Get the default locale on the model.
737
     *
738
     * @return mixed
739
     */
740
    public function getDefaultLocale()
741
    {
742
        return $this->defaultLocale;
743
    }
744
745
    /**
746
     * Deletes all translations for this model.
747
     *
748
     * @param string|array|null $locales The locales to be deleted (array or single string)
749
     *                                   (e.g., ["en", "de"] would remove these translations).
750
     */
751 12
    public function deleteTranslations($locales = null)
752
    {
753 12
        if ($locales === null) {
754 4
            $translations = $this->translations()->get();
755
        } else {
756 8
            $locales = (array) $locales;
757 8
            $translations = $this->translations()->whereIn($this->getLocaleKey(), $locales)->get();
758
        }
759 12
        foreach ($translations as $translation) {
760 8
            $translation->delete();
761
        }
762
763
        // we need to manually "reload" the collection built from the relationship
764
        // otherwise $this->translations()->get() would NOT be the same as $this->translations
765 12
        $this->load('translations');
766 12
    }
767
768
    /**
769
     * @param $key
770
     *
771
     * @return array
772
     */
773 480
    private function getAttributeAndLocale($key)
774
    {
775 480
        if (str_contains($key, ':')) {
776 44
            return explode(':', $key);
777
        }
778
779 480
        return [$key, $this->locale()];
780
    }
781
782
    /**
783
     * @return bool
784
     */
785 32
    private function toArrayAlwaysLoadsTranslations()
786
    {
787 32
        return config('translatable.to_array_always_loads_translations', true);
788
    }
789
790
    public static function enableAutoloadTranslations()
791
    {
792
        self::$autoloadTranslations = true;
793
    }
794
795 4
    public static function defaultAutoloadTranslations()
796
    {
797 4
        self::$autoloadTranslations = null;
798 4
    }
799
800 4
    public static function disableAutoloadTranslations()
801
    {
802 4
        self::$autoloadTranslations = false;
803 4
    }
804
805 480
    protected function getLocalesHelper(): Locales
806
    {
807 480
        return app(Locales::class);
808
    }
809
}
810