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

conedevelopment / root / 20694177656

04 Jan 2026 02:13PM UTC coverage: 74.594% (-0.5%) from 75.049%
20694177656

push

github

iamgergo
version

3491 of 4680 relevant lines covered (74.59%)

32.44 hits per line

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

76.39
/src/Fields/Select.php
1
<?php
2

3
declare(strict_types=1);
4

5
namespace Cone\Root\Fields;
6

7
use Closure;
8
use Cone\Root\Filters\Filter;
9
use Cone\Root\Filters\RenderableFilter;
10
use Illuminate\Database\Eloquent\Builder;
11
use Illuminate\Database\Eloquent\Model;
12
use Illuminate\Http\Request;
13
use Illuminate\Support\Arr;
14
use Illuminate\Support\Collection;
15

16
use function Illuminate\Support\enum_value;
17

18
class Select extends Field
19
{
20
    /**
21
     * The Blade template.
22
     */
23
    protected string $template = 'root::fields.select';
24

25
    /**
26
     * The options resolver callback.
27
     */
28
    protected ?Closure $optionsResolver = null;
29

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

35
    /**
36
     * Set the nullable attribute.
37
     */
38
    public function nullable(bool $value = true): static
1✔
39
    {
40
        $this->nullable = $value;
1✔
41

42
        return $this;
1✔
43
    }
44

45
    /**
46
     * Determine if the field is nullable.
47
     */
48
    public function isNullable(): bool
5✔
49
    {
50
        return $this->nullable;
5✔
51
    }
52

53
    /**
54
     * Set the "multiple" HTML attribute.
55
     */
56
    public function multiple(bool $value = true): static
4✔
57
    {
58
        $name = match ($value) {
4✔
59
            true => $this->getAttribute('name').'[]',
1✔
60
            default => trim($this->getAttribute('name'), '[]'),
4✔
61
        };
4✔
62

63
        $this->setAttribute('name', $name);
4✔
64

65
        return $this->setAttribute('multiple', $value);
4✔
66
    }
67

68
    /**
69
     * Set the "size" HTML attribute.
70
     */
71
    public function size(int $value): static
1✔
72
    {
73
        return $this->setAttribute('size', $value);
1✔
74
    }
75

76
    /**
77
     * {@inheritdoc}
78
     */
79
    public function resolveFormat(Request $request, Model $model): ?string
6✔
80
    {
81
        if (is_null($this->formatResolver)) {
6✔
82
            $this->formatResolver = function (Request $request, Model $model, mixed $value): string {
6✔
83
                $options = array_column(
6✔
84
                    $this->resolveOptions($request, $model), 'label', 'value'
6✔
85
                );
6✔
86

87
                return Collection::make($value)
6✔
88
                    ->map(static function (mixed $value) use ($options): string {
6✔
89
                        $value = enum_value($value);
2✔
90

91
                        return $options[$value] ?? $value;
2✔
92
                    })
6✔
93
                    ->implode(', ');
6✔
94
            };
6✔
95
        }
96

97
        return parent::resolveFormat($request, $model);
6✔
98
    }
99

100
    /**
101
     * Set the options attribute.
102
     */
103
    public function options(array|Closure $value): static
196✔
104
    {
105
        $this->optionsResolver = is_array($value) ? static fn (): array => $value : $value;
196✔
106

107
        return $this;
196✔
108
    }
109

110
    /**
111
     * Resolve the options for the field.
112
     */
113
    public function resolveOptions(Request $request, Model $model): array
7✔
114
    {
115
        if (is_null($this->optionsResolver)) {
7✔
116
            return [];
2✔
117
        }
118

119
        $options = call_user_func_array($this->optionsResolver, [$request, $model]);
6✔
120

121
        $value = Arr::wrap($this->resolveValue($request, $model));
6✔
122

123
        $value = array_map(fn (mixed $v): mixed => enum_value($v), $value);
6✔
124

125
        return array_map(function (mixed $label, mixed $option) use ($value): array {
6✔
126
            $option = match (true) {
6✔
127
                $option instanceof Option => $option,
6✔
128
                is_array($label) => new OptGroup((string) $option, (array) $label),
6✔
129
                default => $this->newOption($option, $label),
6✔
130
            };
6✔
131

132
            $option->selected(static function (Option $option) use ($value): bool {
6✔
133
                return in_array($option->getAttribute('value'), $value);
6✔
134
            });
6✔
135

136
            return $option->toArray();
6✔
137
        }, $options, array_keys($options));
6✔
138
    }
139

140
    /**
141
     * Make a new option instance.
142
     */
143
    public function newOption(mixed $value, string $label): Option
6✔
144
    {
145
        return new Option($value, $label);
6✔
146
    }
147

148
    /**
149
     * {@inheritdoc}
150
     */
151
    public function toInput(Request $request, Model $model): array
4✔
152
    {
153
        return array_merge(parent::toInput($request, $model), [
4✔
154
            'nullable' => $this->isNullable(),
4✔
155
            'options' => $this->resolveOptions($request, $model),
4✔
156
        ]);
4✔
157
    }
158

159
    /**
160
     * Get the filter representation of the field.
161
     */
162
    public function toFilter(): Filter
×
163
    {
164
        return new class($this) extends RenderableFilter
×
165
        {
×
166
            protected Select $field;
167

168
            public function __construct(Select $field)
169
            {
170
                parent::__construct($field->getModelAttribute());
×
171

172
                $this->field = $field;
×
173
            }
174

175
            public function apply(Request $request, Builder $query, mixed $value): Builder
176
            {
177
                return $this->field->resolveFilterQuery($request, $query, $value);
×
178
            }
179

180
            public function toField(): Field
181
            {
182
                return Select::make($this->field->getLabel(), $this->getRequestKey())
×
183
                    ->value(fn (Request $request): mixed => $this->getValue($request))
×
184
                    ->nullable()
×
185
                    ->options(function (Request $request, Model $model): array {
×
186
                        return array_column(
×
187
                            $this->field->resolveOptions($request, $model),
×
188
                            'label',
×
189
                            'value',
×
190
                        );
×
191
                    });
×
192
            }
193
        };
×
194
    }
195
}
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

© 2026 Coveralls, Inc