Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
19 / 19
100.00% covered (success)
100.00%
6 / 6
CRAP
100.00% covered (success)
100.00%
1 / 1
Option
100.00% covered (success)
100.00%
19 / 19
100.00% covered (success)
100.00%
6 / 6
9
100.00% covered (success)
100.00%
1 / 1
 control
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 value
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 properties
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 structure
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 shape
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
2
 optionRules
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
3
1<?php
2
3declare(strict_types=1);
4
5namespace Cosray\Field;
6
7use Celema\Sire\Shape;
8use Cosray\Validation\Shapes;
9use Cosray\Validation\Validators;
10use Cosray\Value;
11use Override;
12
13class Option extends Field implements Capability\Selectable
14{
15    use Capability\IsSelectable;
16
17    #[Override]
18    public function control(): Control
19    {
20        return Control::option();
21    }
22
23    protected bool $hasLabel = false;
24
25    #[Override]
26    public function value(): Value\Option
27    {
28        return new Value\Option($this->owner, $this, $this->valueContext);
29    }
30
31    #[Override]
32    public function properties(): array
33    {
34        $result = parent::properties();
35        $result['hasLabel'] = $this->hasLabel;
36
37        return $result;
38    }
39
40    #[Override]
41    public function structure(mixed $value = null): array
42    {
43        return $this->getSimpleStructure('option', $value);
44    }
45
46    #[Override]
47    public function shape(): Shape
48    {
49        $shape = Shapes::create();
50        $this->addType($shape);
51
52        $value = $shape->add('value', $this->zxxShape('string', [...$this->validators, ...$this->optionRules()]));
53
54        if (!$this->isRequired()) {
55            $value->optional()->nullable();
56        }
57
58        $this->addMeta($shape);
59
60        return $shape;
61    }
62
63    /**
64     * Restricts the value to the declared options. A field without options
65     * declares no domain and accepts any string.
66     *
67     * @return list<string>
68     */
69    private function optionRules(): array
70    {
71        if ($this->options === []) {
72            return [];
73        }
74
75        return [Validators::in(array_values(array_map(
76            static fn(mixed $option): string => (string) (is_array($option) ? $option['value'] ?? '' : $option),
77            $this->options,
78        )))];
79    }
80}