Subversion-Projekte lars-tiefland.laravel_shop

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
166 lars 1
<?php
2
 
3
namespace Spatie\Sluggable;
4
 
5
use Illuminate\Database\Eloquent\Builder;
6
use Illuminate\Database\Eloquent\Relations\Relation;
7
use Illuminate\Support\Collection;
8
use Illuminate\Support\Str;
9
use Illuminate\Support\Traits\Localizable;
10
 
11
trait HasTranslatableSlug
12
{
13
    use HasSlug;
14
    use Localizable;
15
 
16
    protected function getLocalesForSlug(): Collection
17
    {
18
        $generateSlugFrom = $this->slugOptions->generateSlugFrom;
19
 
20
        if (is_callable($generateSlugFrom)) {
21
            // returns a collection of locales that were given to the SlugOptions object
22
            // when it was instantiated with the 'createWithLocales' method.
23
            return Collection::make($this->slugOptions->translatableLocales);
24
        }
25
 
26
        // collects all locales for all translatable fields
27
        return Collection::wrap($generateSlugFrom)
28
            ->filter(fn ($fieldName) => $this->isTranslatableAttribute($fieldName))
29
            ->flatMap(fn ($fieldName) => $this->getTranslatedLocales($fieldName));
30
    }
31
 
32
    protected function addSlug(): void
33
    {
34
        $this->ensureValidSlugOptions();
35
 
36
        $this->getLocalesForSlug()->unique()->each(function ($locale) {
37
            $this->withLocale($locale, function () use ($locale) {
38
                $slug = $this->generateNonUniqueSlug();
39
 
40
                $slugField = $this->slugOptions->slugField;
41
 
42
                if ($this->slugOptions->generateUniqueSlugs) {
43
                    // temporarly change the 'slugField' of the SlugOptions
44
                    // so the 'otherRecordExistsWithSlug' method queries
45
                    // the locale JSON column instead of the 'slugField'.
46
                    $this->slugOptions->saveSlugsTo("{$slugField}->{$locale}");
47
 
48
                    $slug = $this->makeSlugUnique($slug);
49
 
50
                    // revert the change for the next iteration
51
                    $this->slugOptions->saveSlugsTo($slugField);
52
                }
53
 
54
                $this->setTranslation($slugField, $locale, $slug);
55
            });
56
        });
57
    }
58
 
59
    protected function generateNonUniqueSlug(): string
60
    {
61
        $slugField = $this->slugOptions->slugField;
62
        $slugString = $this->getSlugSourceString();
63
 
64
        $slug = $this->getTranslations($slugField)[$this->getLocale()] ?? null;
65
 
66
        $slugGeneratedFromCallable = is_callable($this->slugOptions->generateSlugFrom);
67
        $hasCustomSlug = $this->hasCustomSlugBeenUsed() && ! empty($slug);
68
        $hasNonChangedCustomSlug = ! $slugGeneratedFromCallable && ! empty($slug) && ! $this->slugIsBasedOnTitle();
69
 
70
        if ($hasCustomSlug || $hasNonChangedCustomSlug) {
71
            $slugString = $slug;
72
        }
73
 
74
        return Str::slug($slugString, $this->slugOptions->slugSeparator, $this->slugOptions->slugLanguage);
75
    }
76
 
77
    protected function getSlugSourceStringFromCallable(): string
78
    {
79
        return call_user_func($this->slugOptions->generateSlugFrom, $this, $this->getLocale());
80
    }
81
 
82
    protected function slugIsBasedOnTitle(): bool
83
    {
84
        $slugField = $this->slugOptions->slugField;
85
        $titleSlug = Str::slug($this->getOriginalSourceString(), $this->slugOptions->slugSeparator, $this->slugOptions->slugLanguage);
86
        $currentSlug = $this->getTranslations($slugField)[$this->getLocale()] ?? null;
87
 
88
        if (! str_starts_with($currentSlug, $titleSlug) || $titleSlug === '') {
89
            return false;
90
        }
91
 
92
        if ($titleSlug === $currentSlug) {
93
            return true;
94
        }
95
 
96
        $slugSeparator = $currentSlug[strlen($titleSlug)];
97
        $slugIdentifier = substr($currentSlug, strlen($titleSlug) + 1);
98
 
99
        return $slugSeparator === $this->slugOptions->slugSeparator && is_numeric($slugIdentifier);
100
    }
101
 
102
    protected function getOriginalSourceString(): string
103
    {
104
        if (is_callable($this->slugOptions->generateSlugFrom)) {
105
            $slugSourceString = $this->getSlugSourceStringFromCallable();
106
 
107
            return $this->generateSubstring($slugSourceString);
108
        }
109
 
110
        $slugSourceString = collect($this->slugOptions->generateSlugFrom)
111
            ->map(fn (string $fieldName): string => $this->getOriginal($fieldName)[$this->getLocale()] ?? '')
112
            ->implode($this->slugOptions->slugSeparator);
113
 
114
        return $this->generateSubstring($slugSourceString);
115
    }
116
 
117
    protected function hasCustomSlugBeenUsed(): bool
118
    {
119
        $slugField = $this->slugOptions->slugField;
120
        $originalSlug = $this->getOriginal($slugField)[$this->getLocale()] ?? null;
121
        $newSlug = $this->getTranslations($slugField)[$this->getLocale()] ?? null;
122
 
123
        return $originalSlug !== $newSlug;
124
    }
125
 
126
    public function resolveRouteBindingQuery($query, $value, $field = null): Builder|Relation
127
    {
128
        $field = $field ?? $this->getRouteKeyName();
129
 
130
        if ($field !== $this->getSlugOptions()->slugField) {
131
            return parent::resolveRouteBindingQuery($query, $value, $field);
132
        }
133
 
134
        return $query->where("{$field}->{$this->getLocale()}", $value);
135
    }
136
}