• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

conedevelopment / root / 15084089635

17 May 2025 10:00AM UTC coverage: 77.93% (+0.04%) from 77.891%
15084089635

push

github

web-flow
Modernize back-end.yml (#240)

3291 of 4223 relevant lines covered (77.93%)

36.04 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

83.1
/src/Fields/Slug.php
1
<?php
2

3
namespace Cone\Root\Fields;
4

5
use Closure;
6
use Illuminate\Database\Eloquent\Builder;
7
use Illuminate\Database\Eloquent\Model;
8
use Illuminate\Database\Eloquent\SoftDeletes;
9
use Illuminate\Http\Request;
10
use Illuminate\Support\Str;
11
use Illuminate\Validation\Rule;
12

13
class Slug extends Text
14
{
15
    /**
16
     * The Blade template.
17
     */
18
    protected string $template = 'root::fields.slug';
19

20
    /**
21
     * The attributes that the slug is created from.
22
     */
23
    protected array $from = ['id'];
24

25
    /**
26
     * The slug separator.
27
     */
28
    protected string $separator = '-';
29

30
    /**
31
     * Indicates if the slug should be unique.
32
     */
33
    protected bool $unique = false;
34

35
    /**
36
     * Indicates if the slug field is nullable.
37
     */
38
    protected bool $nullable = false;
39

40
    /**
41
     * Indicates if the slug should be generated always.
42
     */
43
    protected bool $always = false;
44

45
    /**
46
     * The slug resolver.
47
     */
48
    protected ?Closure $generatorResolver = null;
49

50
    /**
51
     * Create a new field instance.
52
     */
53
    public function __construct(?string $label = null, Closure|string $modelAttribute = 'slug')
3✔
54
    {
55
        parent::__construct($label ?: __('Slug'), $modelAttribute);
3✔
56

57
        $this->readonly();
3✔
58
        $this->unique();
3✔
59
    }
60

61
    /**
62
     * Set the "nullable" property.
63
     */
64
    public function nullable(bool $value = true): static
1✔
65
    {
66
        $this->nullable = $value;
1✔
67

68
        return $this;
1✔
69
    }
70

71
    /**
72
     * Determine if the field is nullable.
73
     */
74
    public function isNullable(): bool
2✔
75
    {
76
        return $this->nullable;
2✔
77
    }
78

79
    /**
80
     * Set the "always" property.
81
     */
82
    public function always(bool $value = true): static
×
83
    {
84
        $this->always = $value;
×
85

86
        return $this;
×
87
    }
88

89
    /**
90
     * {@inheritdoc}
91
     */
92
    public function persist(Request $request, Model $model, mixed $value): void
1✔
93
    {
94
        if (! $model->exists || $this->always) {
1✔
95
            $model->saved(function (Model $model) use ($request): void {
1✔
96
                $value = $this->generate($request, $model);
1✔
97

98
                $this->resolveHydrate($request, $model, $value);
1✔
99

100
                Model::withoutEvents(static function () use ($model): void {
1✔
101
                    $model->save();
1✔
102
                });
1✔
103
            });
1✔
104
        }
105

106
        parent::persist($request, $model, $value);
1✔
107
    }
108

109
    /**
110
     * {@inheritdoc}
111
     */
112
    public function getValueForHydrate(Request $request): string
1✔
113
    {
114
        $value = parent::getValueForHydrate($request);
1✔
115

116
        if (empty($value) && ! $this->isNullable()) {
1✔
117
            $value = Str::random();
1✔
118
        }
119

120
        return Str::slug($value, $this->separator);
1✔
121
    }
122

123
    /**
124
     * Set the "from" property.
125
     */
126
    public function from(array|string $attributes): static
1✔
127
    {
128
        $this->from = (array) $attributes;
1✔
129

130
        return $this;
1✔
131
    }
132

133
    /**
134
     * Set the "separator" property.
135
     */
136
    public function separator(string $value): static
1✔
137
    {
138
        $this->separator = $value;
1✔
139

140
        return $this;
1✔
141
    }
142

143
    /**
144
     * Set the "unique" property.
145
     */
146
    public function unique(bool $value = true): static
3✔
147
    {
148
        $this->unique = $value;
3✔
149

150
        if ($value) {
3✔
151
            $this->createRules(
3✔
152
                static fn (Request $request, Model $model): array => [Rule::unique($model->getTable())]
3✔
153
            )->updateRules(static fn (Request $request, Model $model): array => [Rule::unique($model->getTable())->ignoreModel($model)]);
3✔
154
        }
155

156
        return $this;
3✔
157
    }
158

159
    /**
160
     * Set the generator resolve callback.
161
     */
162
    public function generateUsing(Closure $callback): static
×
163
    {
164
        $this->generatorResolver = $callback;
×
165

166
        return $this;
×
167
    }
168

169
    /**
170
     * Generate the slug.
171
     */
172
    protected function generate(Request $request, Model $model): string
1✔
173
    {
174
        $value = Str::of(implode($this->separator, $model->only($this->from)))
1✔
175
            ->slug($this->separator)
1✔
176
            ->value();
1✔
177

178
        if (! is_null($this->generatorResolver)) {
1✔
179
            return call_user_func_array($this->generatorResolver, [$request, $model, $value]);
×
180
        }
181

182
        if (! $this->unique) {
1✔
183
            return $value;
×
184
        }
185

186
        $match = $model
1✔
187
            ->newQuery()
1✔
188
            ->when(
1✔
189
                in_array(SoftDeletes::class, class_uses_recursive($model)),
1✔
190
                static fn (Builder $query): Builder => $query->withTrashed()
1✔
191
            )
1✔
192
            ->where($this->modelAttribute, 'like', $value.'%')
1✔
193
            ->orderByDesc($this->modelAttribute)
1✔
194
            ->limit(1)
1✔
195
            ->value($this->modelAttribute);
1✔
196

197
        $value = is_null($match) ? $value : preg_replace_callback(
1✔
198
            sprintf('/%s([\d]+)?$/', preg_quote($this->separator)),
1✔
199
            static fn (array $match): string => str_replace($match[1], (string) (((int) $match[1]) + 1), $match[0]),
1✔
200
            $match
1✔
201
        );
1✔
202

203
        return $value === $match ? sprintf('%s%s1', $value, $this->separator) : $value;
1✔
204
    }
205

206
    /**
207
     * {@inheritdoc}
208
     */
209
    public function toInput(Request $request, Model $model): array
×
210
    {
211
        return array_merge(parent::toInput($request, $model), [
×
212
            'help' => $this->help ?: __('Leave it empty for auto-generated slug.'),
×
213
        ]);
×
214
    }
215
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc