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

NIT-Administrative-Systems / dynamic-forms / 11575916756

29 Oct 2024 02:23PM UTC coverage: 95.462% (-0.07%) from 95.532%
11575916756

push

github

web-flow
Fix `Currency` component validation (#468)

* docs: fix CHANGELOG links

* fix: allow nullable `Currency` values

3 of 3 new or added lines in 1 file covered. (100.0%)

1 existing line in 1 file now uncovered.

1241 of 1300 relevant lines covered (95.46%)

144.59 hits per line

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

87.1
/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);
38✔
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);
38✔
69

70
        match ($this->dataSource) {
38✔
71
            self::DATA_SRC_VALUES => $this->initSrcValues(),
38✔
UNCOV
72
            default => $this->initSrcOther(),
×
73
        };
38✔
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);
2✔
82
    }
83

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

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

94
            foreach ($value as $i => $singleValue) {
12✔
95
                if (is_array($singleValue)) {
12✔
96
                    $value[$i] = $singleValue;
×
97
                } else {
98
                    $value[$i] = (string) $singleValue;
12✔
99
                }
100
            }
101

102
            return $value;
12✔
103
        }
104

105
        return is_scalar($value) ? (string) $value : $value;
34✔
106
    }
107

108
    // TODO: a select with no values will error out
109
    protected function processValidations(string $fieldKey, string $fieldLabel, mixed $submissionValue, Factory $validator): MessageBag
110
    {
111
        $rules = new RuleBag($fieldKey, ['string']);
38✔
112

113
        // Required if that's selected, otherwise mark it optional so Rule::in() won't fail it
114
        $rules->addIfNotNull('required', $this->validation('required'));
38✔
115
        $rules->addIf('nullable', ! $this->validation('required'));
38✔
116

117
        $rules->addIf(Rule::in($this->optionValues()), $this->dataSource === self::DATA_SRC_VALUES);
38✔
118

119
        return $validator->make(
38✔
120
            [$fieldKey => $submissionValue],
38✔
121
            $rules->rules(),
38✔
122
            [],
38✔
123
            [$fieldKey => $fieldLabel]
38✔
124
        )->messages();
38✔
125
    }
126

127
    public function dataSource(): string
128
    {
129
        return $this->dataSource;
6✔
130
    }
131

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

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

152
    private function initSrcValues(): void
153
    {
154
        $options = collect(Arr::get($this->additional, 'data.values', []));
38✔
155

156
        $this->optionValues = $options
38✔
157
            ->map(function (array $pair) {
38✔
158
                $value = Arr::get($pair, 'value');
38✔
159

160
                return is_array($value) ? json_encode($value) : trim($value);
38✔
161
            })
38✔
162
            ->all();
38✔
163

164
        $this->optionValuesWithLabels = $options
38✔
165
            ->mapWithKeys(function (array $pair) {
38✔
166
                $value = Arr::get($pair, 'value');
38✔
167
                $label = trim(Arr::get($pair, 'label'));
38✔
168

169
                $key = is_array($value) ? json_encode($value) : trim($value);
38✔
170

171
                return [$key => $label];
38✔
172
            })
38✔
173
            ->all();
38✔
174
    }
175

176
    private function initSrcResources(array $additional, ResourceRegistry $resourceRegistry): void
177
    {
178
        //add in stuff for valueProperty
179
        $resourceList = $resourceRegistry->registered();
2✔
180
        $resource = $additional['data']['resource'];
2✔
181

182
        if (! isset($resourceList[$resource])) {
2✔
183
            throw new UnknownResourceError($resource);
×
184
        }
185

186
        $this->optionValues = collect($resourceList[$resource]::submissions(-1, 0, '', ''))->transform(function ($val) {
2✔
187
            return json_encode($val);
2✔
188
        })->all();
2✔
189
    }
190

191
    private function initSrcOther(): void
192
    {
193
        if ($this->dataSource == self::DATA_SRC_RESOURCE) {
2✔
194
            // This is left blank because initSrcResources cannot be called in the constructor
195
            // because resourceRegistry is initialized after calling the component's constructor in Form.php
196
        } else {
197
            $this->initSrcUnsupported(); // we still want to catch unsupported data sources
2✔
198
        }
199
    }
200

201
    private function initSrcUnsupported(): void
202
    {
203
        throw new InvalidDefinitionError(
×
204
            sprintf('Unsupported dataSrc "%s", must be [%s]', $this->dataSource, implode(', ', self::SUPPORTED_DATA_SRC)),
×
205
            'dataSrc'
×
206
        );
×
207
    }
208

209
    public function transformations(): array
210
    {
211
        // Field does not support transformations
212
        return [];
46✔
213
    }
214

215
    public function getResourceRegistry(): ResourceRegistry
216
    {
217
        return $this->resourceRegistry;
×
218
    }
219

220
    public function setResourceRegistry(ResourceRegistry $resourceRegistry): void
221
    {
222
        $this->resourceRegistry = $resourceRegistry;
8✔
223
        if ($this->dataSource() === self::DATA_SRC_RESOURCE) {
8✔
224
            $this->activateResources();
2✔
225
        }
226
    }
227
}
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