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\Model;
6
use Illuminate\Support\Str;
7
use Spatie\Sluggable\Exceptions\InvalidOption;
8
 
9
trait HasSlug
10
{
11
    protected SlugOptions $slugOptions;
12
 
13
    abstract public function getSlugOptions(): SlugOptions;
14
 
15
    protected static function bootHasSlug(): void
16
    {
17
        static::creating(function (Model $model) {
18
            $model->generateSlugOnCreate();
19
        });
20
 
21
        static::updating(function (Model $model) {
22
            $model->generateSlugOnUpdate();
23
        });
24
    }
25
 
26
    protected function generateSlugOnCreate(): void
27
    {
28
        $this->slugOptions = $this->getSlugOptions();
29
 
30
        if ($this->slugOptions->skipGenerate) {
31
            return;
32
        }
33
 
34
        if (! $this->slugOptions->generateSlugsOnCreate) {
35
            return;
36
        }
37
 
38
        if ($this->slugOptions->preventOverwrite) {
39
            if ($this->{$this->slugOptions->slugField} !== null) {
40
                return;
41
            }
42
        }
43
 
44
        $this->addSlug();
45
    }
46
 
47
    protected function generateSlugOnUpdate(): void
48
    {
49
        $this->slugOptions = $this->getSlugOptions();
50
 
51
        if ($this->slugOptions->skipGenerate) {
52
            return;
53
        }
54
 
55
        if (! $this->slugOptions->generateSlugsOnUpdate) {
56
            return;
57
        }
58
 
59
        if ($this->slugOptions->preventOverwrite) {
60
            if ($this->{$this->slugOptions->slugField} !== null) {
61
                return;
62
            }
63
        }
64
 
65
        $this->addSlug();
66
    }
67
 
68
    public function generateSlug(): void
69
    {
70
        $this->slugOptions = $this->getSlugOptions();
71
 
72
        $this->addSlug();
73
    }
74
 
75
    protected function addSlug(): void
76
    {
77
        $this->ensureValidSlugOptions();
78
 
79
        $slug = $this->generateNonUniqueSlug();
80
 
81
        if ($this->slugOptions->generateUniqueSlugs) {
82
            $slug = $this->makeSlugUnique($slug);
83
        }
84
 
85
        $slugField = $this->slugOptions->slugField;
86
 
87
        $this->$slugField = $slug;
88
    }
89
 
90
    protected function generateNonUniqueSlug(): string
91
    {
92
        $slugField = $this->slugOptions->slugField;
93
 
94
        if ($this->hasCustomSlugBeenUsed() && ! empty($this->$slugField)) {
95
            return $this->$slugField;
96
        }
97
 
98
        return Str::slug($this->getSlugSourceString(), $this->slugOptions->slugSeparator, $this->slugOptions->slugLanguage);
99
    }
100
 
101
    protected function hasCustomSlugBeenUsed(): bool
102
    {
103
        $slugField = $this->slugOptions->slugField;
104
 
105
        return $this->getOriginal($slugField) != $this->$slugField;
106
    }
107
 
108
    protected function getSlugSourceString(): string
109
    {
110
        if (is_callable($this->slugOptions->generateSlugFrom)) {
111
            $slugSourceString = $this->getSlugSourceStringFromCallable();
112
 
113
            return $this->generateSubstring($slugSourceString);
114
        }
115
 
116
        $slugSourceString = collect($this->slugOptions->generateSlugFrom)
117
            ->map(fn (string $fieldName): string => data_get($this, $fieldName, ''))
118
            ->implode($this->slugOptions->slugSeparator);
119
 
120
        return $this->generateSubstring($slugSourceString);
121
    }
122
 
123
    protected function getSlugSourceStringFromCallable(): string
124
    {
125
        return call_user_func($this->slugOptions->generateSlugFrom, $this);
126
    }
127
 
128
    protected function makeSlugUnique(string $slug): string
129
    {
130
        $originalSlug = $slug;
131
        $i = $this->slugOptions->startSlugSuffixFrom;
132
 
133
        while ($this->otherRecordExistsWithSlug($slug) || $slug === '') {
134
            $slug = $originalSlug.$this->slugOptions->slugSeparator.$i++;
135
        }
136
 
137
        return $slug;
138
    }
139
 
140
    protected function otherRecordExistsWithSlug(string $slug): bool
141
    {
142
        $query = static::where($this->slugOptions->slugField, $slug)
143
            ->withoutGlobalScopes();
144
 
145
        if ($this->slugOptions->extraScopeCallback) {
146
            $query->where($this->slugOptions->extraScopeCallback);
147
        }
148
 
149
        if ($this->exists) {
150
            $query->where($this->getKeyName(), '!=', $this->getKey());
151
        }
152
 
153
        if ($this->usesSoftDeletes()) {
154
            $query->withTrashed();
155
        }
156
 
157
        return $query->exists();
158
    }
159
 
160
    protected function usesSoftDeletes(): bool
161
    {
162
        return in_array('Illuminate\Database\Eloquent\SoftDeletes', class_uses($this), true);
163
    }
164
 
165
    protected function ensureValidSlugOptions(): void
166
    {
167
        if (is_array($this->slugOptions->generateSlugFrom) && ! count($this->slugOptions->generateSlugFrom)) {
168
            throw InvalidOption::missingFromField();
169
        }
170
 
171
        if (! strlen($this->slugOptions->slugField)) {
172
            throw InvalidOption::missingSlugField();
173
        }
174
 
175
        if ($this->slugOptions->maximumLength <= 0) {
176
            throw InvalidOption::invalidMaximumLength();
177
        }
178
    }
179
 
180
    /**
181
     * Helper function to handle multi-bytes strings if the module mb_substr is present,
182
     * default to substr otherwise.
183
     */
184
    protected function generateSubstring($slugSourceString)
185
    {
186
        if (function_exists('mb_substr')) {
187
            return mb_substr($slugSourceString, 0, $this->slugOptions->maximumLength);
188
        }
189
 
190
        return substr($slugSourceString, 0, $this->slugOptions->maximumLength);
191
    }
192
}