-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathAddressFieldSet.php
More file actions
138 lines (127 loc) · 4.8 KB
/
Copy pathAddressFieldSet.php
File metadata and controls
138 lines (127 loc) · 4.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
<?php namespace johnbarrett\Google_Address_Autocomplete;
/**
* One configured address field set: a search box and the REDCap fields it fills.
*
* REDCap hands sub-settings back as a plain associative array per configured set.
* This turns one of those arrays into a checked, named shape exactly once, at the
* boundary, so the rest of the module reads properties instead of re-deriving the
* same trim/cast/default on every access.
*
* Readonly because a set is configuration: it is read many times while emitting a
* page and never modified.
*/
final readonly class AddressFieldSet
{
public function __construct(
/** Position in config.json, 0-based. Fixes this set's element-id prefix. */
public int $index,
public string $description,
public bool $disabled,
/** Instruments this set applies to. Empty means "any form with the source field". */
public array $forms,
/** The field the search box attaches to. A set without one is not configured. */
public string $autocomplete,
public string $streetNumber,
public string $street,
public string $city,
public string $county,
public string $state,
public string $zip,
public string $country,
public string $latitude,
public string $longitude,
public string $placeName,
public bool $recoverUnit,
public string $regionCodes,
public string $primaryTypes,
) {}
/**
* Build a set from one raw REDCap sub-setting array.
*
* Every read is defensive, and that is load-bearing rather than merely cautious.
* Sub-settings are stored flat, one parallel array per child key, so a key added
* to config.json after a project was configured is simply ABSENT from the array
* REDCap returns. No parameter here may become required: that would turn a
* routine settings addition into a fatal on already-configured projects.
*/
public static function fromSubSetting(array $raw, int $index): self
{
return new self(
index: $index,
description: self::text($raw, 'set-description'),
disabled: !empty($raw['set-disabled']),
forms: self::formList($raw, 'set-form'),
// Not trimmed: preserved exactly as configured, because it is compared
// against the claimed-source map and emitted as the lookup name.
autocomplete: (string)($raw['set-autocomplete'] ?? ''),
streetNumber: self::text($raw, 'set-street-number'),
street: self::text($raw, 'set-street'),
city: self::text($raw, 'set-city'),
county: self::text($raw, 'set-county'),
state: self::text($raw, 'set-state'),
zip: self::text($raw, 'set-zip'),
country: self::text($raw, 'set-country'),
latitude: self::text($raw, 'set-latitude'),
longitude: self::text($raw, 'set-longitude'),
placeName: self::text($raw, 'set-place-name'),
recoverUnit: !empty($raw['set-recover-unit']),
regionCodes: (string)($raw['set-region-codes'] ?? ''),
primaryTypes: (string)($raw['set-primary-types'] ?? ''),
);
}
/** A missing key and a key holding whitespace both mean "not mapped". */
private static function text(array $raw, string $key): string
{
return trim((string)($raw[$key] ?? ''));
}
/**
* A repeatable form-list setting, which REDCap may return as a bare scalar when
* only one entry was chosen.
*/
private static function formList(array $raw, string $key): array
{
$forms = $raw[$key] ?? [];
if (!is_array($forms)) { $forms = [$forms]; }
$forms = array_map(trim(...), array_map(strval(...), $forms));
return array_values(array_filter($forms, static fn(string $form): bool => $form !== ''));
}
/**
* Whether this set should run at all. A set with no source field was added in the
* configuration dialog but never filled in.
*/
public function isActive(): bool
{
return !$this->disabled && $this->sourceKey() !== '';
}
/**
* The source field, trimmed, for comparing one set against another.
*
* The property itself is stored untrimmed because that is the value emitted into
* the script and looked up by name; this is only for identity comparisons.
*/
public function sourceKey(): string
{
return trim($this->autocomplete);
}
/**
* Whether this set applies to the given instrument. No configured instrument means
* "any form containing the source field", which the emitted script still guards.
*/
public function appliesTo(string $instrument): bool
{
return !$this->forms || in_array($instrument, $this->forms, true);
}
/**
* How this set identifies itself in the browser console, so two sets on one page
* can be told apart when debugging.
*/
public function label(): string
{
return '#' . ($this->index + 1) . ($this->description !== '' ? ' ' . $this->description : '');
}
/** Element-id prefix. Unique per set — this is what keeps two sets apart. */
public function elementPrefix(): string
{
return 'googleSearch_' . $this->index . '_';
}
}