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

NIT-Administrative-Systems / dynamic-forms / 3874968769

pending completion
3874968769

push

github

GitHub
PHP 8.2 Support (#383)

1182 of 1279 relevant lines covered (92.42%)

62.59 hits per line

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

82.76
/src/Components/Inputs/Select.php
1
<?php
2

3
namespace Northwestern\SysDev\DynamicForms\Components\Inputs;
4

5
use Illuminate\Contracts\Support\MessageBag;
6
use Illuminate\Support\Arr;
7
use Illuminate\Validation\Factory;
8
use Illuminate\Validation\Rule;
9
use Northwestern\SysDev\DynamicForms\Components\BaseComponent;
10
use Northwestern\SysDev\DynamicForms\Components\ResourceValues;
11
use Northwestern\SysDev\DynamicForms\Errors\InvalidDefinitionError;
12
use Northwestern\SysDev\DynamicForms\Errors\UnknownResourceError;
13
use Northwestern\SysDev\DynamicForms\ResourceRegistry;
14
use Northwestern\SysDev\DynamicForms\RuleBag;
15

16
class Select extends BaseComponent implements ResourceValues
17
{
18
    const TYPE = 'select';
19
    protected ResourceRegistry $resourceRegistry;
20

21
    const DATA_SRC_VALUES = 'values';
22
    const DATA_SRC_URL = 'url';
23
    const DATA_SRC_RESOURCE = 'resource';
24
    const DATA_SRC_CUSTOM = 'custom';
25
    const DATA_SRC_JSON = 'json';
26
    const DATA_SRC_INDEXED_DB = 'indexeddb';
27

28
    /**
29
     * Supported Data -> Source values.
30
     *
31
     * @var string[]
32
     */
33
    const SUPPORTED_DATA_SRC = [
34
        self::DATA_SRC_VALUES,
35
        self::DATA_SRC_RESOURCE,
36
    ];
37

38
    protected string $dataSource;
39

40
    /**
41
     * Valid values from the definition, for DATA_SRC_VALUES mode.
42
     */
43
    protected array $optionValues;
44
    protected ?array $optionValuesWithLabels = null;
45

46
    /**
47
     * Valid resources from the definition, for DATA_SRC_RESOURCE mode.
48
     */
49
    protected array $optionResources;
50

51
    public function __construct(
52
        string $key,
53
        ?string $label,
54
        ?string $errorLabel,
55
        array $components,
56
        array $validations,
57
        bool $hasMultipleValues,
58
        ?array $conditional,
59
        ?string $customConditional,
60
        string $case,
61
        null|array|string $calculateValue,
62
        mixed $defaultValue,
63
        array $additional,
64
    ) {
65
        parent::__construct($key, $label, $errorLabel, $components, $validations, $hasMultipleValues, $conditional, $customConditional, $case, $calculateValue, $defaultValue, $additional);
1✔
66

67
        // formiojs omits the dataSrc prop when it's 'values'; assume that's the mode when not present
68
        $this->dataSource = Arr::get($this->additional, 'dataSrc', self::DATA_SRC_VALUES);
1✔
69

70
        match ($this->dataSource) {
1✔
71
            self::DATA_SRC_VALUES => $this->initSrcValues($additional),
1✔
72
            default => $this->initSrcOther(),
1✔
73
        };
1✔
74
    }
75

76
    /**
77
     * This function must be run during component or form instantiation. Allows user's application to use the resources they've registered.
78
     */
79
    public function activateResources(): void
80
    {
81
        $this->initSrcResources($this->additional, $this->resourceRegistry);
1✔
82
    }
83

84
    /**
85
     * {@inheritDoc}
86
     */
87
    public function submissionValue(): mixed
88
    {
89
        $value = parent::submissionValue();
9✔
90

91
        if ($this->hasMultipleValues()) {
9✔
92
            $value ??= [];
×
93

94
            foreach ($value as $i => $singleValue) {
×
95
                $value[$i] = (string) $singleValue;
×
96
            }
97

98
            return $value;
×
99
        }
100

101
        return is_scalar($value) ? (string) $value : $value;
9✔
102
    }
103

104
    // TODO: a select with no values will error out
105
    protected function processValidations(string $fieldKey, string $fieldLabel, mixed $submissionValue, Factory $validator): MessageBag
106
    {
107
        $rules = new RuleBag($fieldKey, ['string']);
17✔
108

109
        // Required if that's selected, otherwise mark it optional so Rule::in() won't fail it
110
        $rules->addIfNotNull('required', $this->validation('required'));
17✔
111
        $rules->addIf('nullable', ! $this->validation('required'));
17✔
112

113
        $rules->addIf(Rule::in($this->optionValues()), $this->dataSource === self::DATA_SRC_VALUES);
17✔
114

115
        return $validator->make(
17✔
116
            [$fieldKey => $submissionValue],
17✔
117
            $rules->rules(),
17✔
118
            [],
17✔
119
            [$fieldKey => $fieldLabel]
17✔
120
        )->messages();
17✔
121
    }
122

123
    public function dataSource(): string
124
    {
125
        return $this->dataSource;
1✔
126
    }
127

128
    /**
129
     * List of valid option values.
130
     *
131
     * Will be empty when the data source is not {@see Select::DATA_SRC_VALUES}.
132
     */
133
    public function optionValues(): array
134
    {
135
        return $this->optionValues;
6✔
136
    }
137

138
    /**
139
     * Values and their corresponding labels.
140
     *
141
     * Will be null when the datasource is not {@see Select::DATA_SRC_VALUES}.
142
     */
143
    public function options(): ?array
144
    {
145
        return $this->optionValuesWithLabels;
1✔
146
    }
147

148
    private function initSrcValues(array $additional): void
149
    {
150
        $options = collect($this->additional['data']['values']);
1✔
151

152
        $this->optionValues = $options
1✔
153
            ->map(function (array $pair) {
1✔
154
                return trim(Arr::get($pair, 'value'));
1✔
155
            })
1✔
156
            ->all();
1✔
157

158
        $this->optionValuesWithLabels = $options
1✔
159
            ->mapWithKeys(function (array $pair) {
1✔
160
                $value = trim(Arr::get($pair, 'value'));
1✔
161
                $label = trim(Arr::get($pair, 'label'));
1✔
162

163
                return [$value => $label];
1✔
164
            })
1✔
165
            ->all();
1✔
166
    }
167

168
    private function initSrcResources(array $additional, ResourceRegistry $resourceRegistry): void
169
    {
170
        //add in stuff for valueProperty
171
        $resourceList = $resourceRegistry->registered();
1✔
172
        $resource = $additional['data']['resource'];
1✔
173

174
        if (! isset($resourceList[$resource])) {
1✔
175
            throw new UnknownResourceError($resource);
×
176
        }
177

178
        $this->optionValues = collect($resourceList[$resource]::submissions(-1, 0, '', ''))->transform(function ($val) {
1✔
179
            return json_encode($val);
1✔
180
        })->all();
1✔
181
    }
182

183
    private function initSrcOther(): void
184
    {
185
        if ($this->dataSource == self::DATA_SRC_RESOURCE) {
1✔
186
            // This is left blank because initSrcResources cannot be called in the constructor
187
            // because resourceRegistry is initialized after calling the component's constructor in Form.php
188
        } else {
189
            $this->initSrcUnsupported(); // we still want to catch unsupported data sources
1✔
190
        }
191
    }
192

193
    private function initSrcUnsupported(): void
194
    {
195
        throw new InvalidDefinitionError(
×
196
            sprintf('Unsupported dataSrc "%s", must be [%s]', $this->dataSource, implode(', ', self::SUPPORTED_DATA_SRC)),
×
197
            'dataSrc'
×
198
        );
×
199
    }
200

201
    public function transformations(): array
202
    {
203
        // Field does not support transformations
204
        return [];
5✔
205
    }
206

207
    public function getResourceRegistry(): ResourceRegistry
208
    {
209
        return $this->resourceRegistry;
×
210
    }
211

212
    public function setResourceRegistry(ResourceRegistry $resourceRegistry): void
213
    {
214
        $this->resourceRegistry = $resourceRegistry;
2✔
215
        if ($this->dataSource() === self::DATA_SRC_RESOURCE) {
2✔
216
            $this->activateResources();
1✔
217
        }
218
    }
219
}
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