1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
declare(strict_types=1); |
4
|
|
|
|
5
|
|
|
namespace MaxBeckers\AmazonAlexa\Response\Directives\APL\Component; |
6
|
|
|
|
7
|
|
|
use MaxBeckers\AmazonAlexa\Response\Directives\APL\Document\APLComponentType; |
8
|
|
|
use MaxBeckers\AmazonAlexa\Response\Directives\APL\Document\Bind; |
9
|
|
|
use MaxBeckers\AmazonAlexa\Response\Directives\APL\Document\Display; |
10
|
|
|
use MaxBeckers\AmazonAlexa\Response\Directives\APL\Document\LayoutDirection; |
11
|
|
|
use MaxBeckers\AmazonAlexa\Response\Directives\APL\Document\PointerEvents; |
12
|
|
|
use MaxBeckers\AmazonAlexa\Response\Directives\APL\Document\Role; |
13
|
|
|
use MaxBeckers\AmazonAlexa\Response\Directives\APL\Document\TickHandler; |
14
|
|
|
use MaxBeckers\AmazonAlexa\Response\Directives\APL\Document\VisibilityChangeHandler; |
15
|
|
|
use MaxBeckers\AmazonAlexa\Response\Directives\APL\StandardCommand\AbstractStandardCommand; |
16
|
|
|
|
17
|
|
|
abstract class APLBaseComponent implements \JsonSerializable |
18
|
|
|
{ |
19
|
|
|
/** |
20
|
|
|
* @param APLComponentType $type The type of the component |
21
|
|
|
* @param string|null $accessibilityLabel Voice-over reads this string when the user selects this component |
22
|
|
|
* @param Action|null $action Single programmatic equivalent for complex touch interaction |
23
|
|
|
* @param Action[]|null $actions Array of programmatic equivalents for complex touch interactions |
24
|
|
|
* @param Bind[]|null $bind Expressions to add to the data binding context |
25
|
|
|
* @param string|null $description Optional description of this component |
26
|
|
|
* @param bool $checked When true, this component has the checked state set |
27
|
|
|
* @param bool $disabled When true, this component doesn't respond to touch or focus |
28
|
|
|
* @param Display|null $display Determines whether the component displays on the screen |
29
|
|
|
* @param Entity[]|null $entities Array of opaque data used to clarify references in Alexa |
30
|
|
|
* @param Entity|null $entity Single opaque data used to clarify references in Alexa |
31
|
|
|
* @param TickHandler[]|null $handleTick Tick handlers to invoke as time passes |
32
|
|
|
* @param VisibilityChangeHandler[]|null $handleVisibilityChange Visibility handlers to invoke when visibility changes |
33
|
|
|
* @param string|null $height The requested height of the component |
34
|
|
|
* @param string|null $id Reference name of the component, used for navigation and events |
35
|
|
|
* @param bool $inheritParentState When true, replace the component state with the state of the parent component |
36
|
|
|
* @param LayoutDirection|null $layoutDirection The direction in which the component renders |
37
|
|
|
* @param string|null $maxHeight The maximum allowed height of this component |
38
|
|
|
* @param string|null $maxWidth The maximum allowed width of this component |
39
|
|
|
* @param string|null $minHeight The minimum allowed height of this component |
40
|
|
|
* @param string|null $minWidth The minimum allowed width of this component |
41
|
|
|
* @param AbstractStandardCommand[]|null $onMount Commands to run when the component is first displayed |
42
|
|
|
* @param AbstractStandardCommand[]|null $onCursorEnter Commands to run when a cursor enters the active region |
43
|
|
|
* @param AbstractStandardCommand[]|null $onCursorExit Commands to run when a cursor exits the active region |
44
|
|
|
* @param AbstractStandardCommand[]|null $onCursorMove Commands to run when a cursor moves in the active region |
45
|
|
|
* @param AbstractStandardCommand[]|null $onSpeechMark Commands to run when encountering a speech mark |
46
|
|
|
* @param AbstractStandardCommand[]|null $onLayout Commands to run when the layout calculation changes |
47
|
|
|
* @param float $opacity Opacity of this component and children |
48
|
|
|
* @param string[]|null $padding Space to add on the sides of the component |
49
|
|
|
* @param string|null $paddingBottom Space to add to the bottom of this component |
50
|
|
|
* @param string|null $paddingEnd Space to add to the end edge of this component |
51
|
|
|
* @param string|null $paddingLeft Space to add to the left of this component |
52
|
|
|
* @param string|null $paddingRight Space to add to the right of this component |
53
|
|
|
* @param string|null $paddingStart Space to add to the start edge of this component |
54
|
|
|
* @param string|null $paddingTop Space to add to the top of this component |
55
|
|
|
* @param PointerEvents|null $pointerEvents Controls whether the component can be the target of touch events |
56
|
|
|
* @param string[]|null $preserve Properties to save when reinflating the document |
57
|
|
|
* @param Role|null $role Role or purpose of the component |
58
|
|
|
* @param string|null $shadowColor Shadow color |
59
|
|
|
* @param string|null $shadowHorizontalOffset Horizontal offset of the shadow |
60
|
|
|
* @param string|null $shadowRadius Shadow blur radius |
61
|
|
|
* @param string|null $shadowVerticalOffset Vertical offset of the shadow |
62
|
|
|
* @param mixed $speech Transformed speech information for audio playback |
63
|
|
|
* @param array|null $style Named style or styles to apply |
64
|
|
|
* @param string[]|null $trackChanges Properties to track and report changes in the visual context |
65
|
|
|
* @param array|null $transform Array of transformations |
66
|
|
|
* @param bool $when If it evaluates to false, this component doesn't inflate |
67
|
|
|
* @param string|null $width The requested width of this component |
68
|
|
|
*/ |
69
|
140 |
|
public function __construct( |
70
|
|
|
public APLComponentType $type, |
71
|
|
|
public ?string $accessibilityLabel = null, |
72
|
|
|
public ?Action $action = null, |
73
|
|
|
public ?array $actions = null, |
74
|
|
|
public ?array $bind = null, |
75
|
|
|
public ?string $description = null, |
76
|
|
|
public bool $checked = false, |
77
|
|
|
public bool $disabled = false, |
78
|
|
|
public ?Display $display = null, |
79
|
|
|
public ?array $entities = null, |
80
|
|
|
public ?Entity $entity = null, |
81
|
|
|
public ?array $handleTick = null, |
82
|
|
|
public ?array $handleVisibilityChange = null, |
83
|
|
|
public ?string $height = 'auto', |
84
|
|
|
public ?string $id = null, |
85
|
|
|
public bool $inheritParentState = false, |
86
|
|
|
public ?LayoutDirection $layoutDirection = null, |
87
|
|
|
public ?string $maxHeight = null, |
88
|
|
|
public ?string $maxWidth = null, |
89
|
|
|
public ?string $minHeight = '0', |
90
|
|
|
public ?string $minWidth = '0', |
91
|
|
|
public ?array $onMount = null, |
92
|
|
|
public ?array $onCursorEnter = null, |
93
|
|
|
public ?array $onCursorExit = null, |
94
|
|
|
public ?array $onCursorMove = null, |
95
|
|
|
public ?array $onSpeechMark = null, |
96
|
|
|
public ?array $onLayout = null, |
97
|
|
|
public float $opacity = 1.0, |
98
|
|
|
public ?array $padding = null, |
99
|
|
|
public ?string $paddingBottom = '0', |
100
|
|
|
public ?string $paddingEnd = null, |
101
|
|
|
public ?string $paddingLeft = '0', |
102
|
|
|
public ?string $paddingRight = '0', |
103
|
|
|
public ?string $paddingStart = null, |
104
|
|
|
public ?string $paddingTop = '0', |
105
|
|
|
public ?PointerEvents $pointerEvents = null, |
106
|
|
|
public ?array $preserve = null, |
107
|
|
|
public ?Role $role = null, |
108
|
|
|
public ?string $shadowColor = 'transparent', |
109
|
|
|
public ?string $shadowHorizontalOffset = '0', |
110
|
|
|
public ?string $shadowRadius = '0', |
111
|
|
|
public ?string $shadowVerticalOffset = '0', |
112
|
|
|
public mixed $speech = null, |
113
|
|
|
public ?array $style = null, |
114
|
|
|
public ?array $trackChanges = null, |
115
|
|
|
public ?array $transform = null, |
116
|
|
|
public bool $when = true, |
117
|
|
|
public ?string $width = 'auto', |
118
|
|
|
) { |
119
|
140 |
|
} |
120
|
|
|
|
121
|
79 |
|
public function jsonSerialize(): array |
122
|
|
|
{ |
123
|
79 |
|
$data = ['type' => $this->type->value]; |
124
|
|
|
|
125
|
79 |
|
$this->addSimpleProperties($data); |
126
|
79 |
|
$this->addEnumProperties($data); |
127
|
79 |
|
$this->addBooleanFlags($data); |
128
|
79 |
|
$this->addDimensionsAndStyling($data); |
129
|
79 |
|
$this->addOpacity($data); |
130
|
|
|
|
131
|
79 |
|
return $data; |
132
|
|
|
} |
133
|
|
|
|
134
|
|
|
/** |
135
|
|
|
* @param array<string,mixed> $data |
136
|
|
|
*/ |
137
|
79 |
|
private function addSimpleProperties(array &$data): void |
138
|
|
|
{ |
139
|
79 |
|
$simple = [ |
140
|
79 |
|
'accessibilityLabel', 'action', 'actions', 'bind', 'description', 'entities', 'entity', |
141
|
79 |
|
'handleTick', 'handleVisibilityChange', 'id', 'onMount', 'onCursorEnter', 'onCursorExit', |
142
|
79 |
|
'onCursorMove', 'onSpeechMark', 'onLayout', 'padding', 'preserve', 'style', 'trackChanges', |
143
|
79 |
|
'transform', 'speech', |
144
|
79 |
|
]; |
145
|
|
|
|
146
|
79 |
|
foreach ($simple as $prop) { |
147
|
79 |
|
$value = $this->$prop; |
148
|
79 |
|
if ($this->isExportable($value)) { |
149
|
6 |
|
$data[$prop] = $value; |
150
|
|
|
} |
151
|
|
|
} |
152
|
|
|
} |
153
|
|
|
|
154
|
|
|
/** |
155
|
|
|
* @param array<string,mixed> $data |
156
|
|
|
*/ |
157
|
79 |
|
private function addEnumProperties(array &$data): void |
158
|
|
|
{ |
159
|
79 |
|
$enums = [ |
160
|
79 |
|
'display' => $this->display, |
161
|
79 |
|
'layoutDirection' => $this->layoutDirection, |
162
|
79 |
|
'pointerEvents' => $this->pointerEvents, |
163
|
79 |
|
'role' => $this->role, |
164
|
79 |
|
]; |
165
|
|
|
|
166
|
79 |
|
foreach ($enums as $key => $enum) { |
167
|
79 |
|
if ($enum !== null) { |
168
|
|
|
$data[$key] = $enum->value; |
169
|
|
|
} |
170
|
|
|
} |
171
|
|
|
} |
172
|
|
|
|
173
|
|
|
/** |
174
|
|
|
* @param array<string,mixed> $data |
175
|
|
|
*/ |
176
|
79 |
|
private function addBooleanFlags(array &$data): void |
177
|
|
|
{ |
178
|
79 |
|
if ($this->checked) { |
179
|
|
|
$data['checked'] = true; |
180
|
|
|
} |
181
|
79 |
|
if ($this->disabled) { |
182
|
|
|
$data['disabled'] = true; |
183
|
|
|
} |
184
|
79 |
|
if ($this->inheritParentState) { |
185
|
|
|
$data['inheritParentState'] = true; |
186
|
|
|
} |
187
|
79 |
|
if (!$this->when) { |
188
|
|
|
$data['when'] = false; |
189
|
|
|
} |
190
|
|
|
} |
191
|
|
|
|
192
|
|
|
/** |
193
|
|
|
* @param array<string,mixed> $data |
194
|
|
|
*/ |
195
|
79 |
|
private function addDimensionsAndStyling(array &$data): void |
196
|
|
|
{ |
197
|
79 |
|
$withDefaults = [ |
198
|
79 |
|
'height' => 'auto', |
199
|
79 |
|
'width' => 'auto', |
200
|
79 |
|
'minHeight' => '0', |
201
|
79 |
|
'minWidth' => '0', |
202
|
79 |
|
'paddingBottom' => '0', |
203
|
79 |
|
'paddingLeft' => '0', |
204
|
79 |
|
'paddingRight' => '0', |
205
|
79 |
|
'paddingTop' => '0', |
206
|
79 |
|
'shadowColor' => 'transparent', |
207
|
79 |
|
'shadowHorizontalOffset' => '0', |
208
|
79 |
|
'shadowRadius' => '0', |
209
|
79 |
|
'shadowVerticalOffset' => '0', |
210
|
79 |
|
]; |
211
|
|
|
|
212
|
79 |
|
foreach ($withDefaults as $prop => $default) { |
213
|
79 |
|
$value = $this->$prop; |
214
|
79 |
|
if ($value !== null && $value !== $default) { |
215
|
|
|
$data[$prop] = $value; |
216
|
|
|
} |
217
|
|
|
} |
218
|
|
|
|
219
|
|
|
// Properties without defaults (include if not null) |
220
|
79 |
|
foreach (['maxHeight', 'maxWidth', 'paddingEnd', 'paddingStart'] as $prop) { |
221
|
79 |
|
if ($this->$prop !== null) { |
222
|
|
|
$data[$prop] = $this->$prop; |
223
|
|
|
} |
224
|
|
|
} |
225
|
|
|
} |
226
|
|
|
|
227
|
|
|
/** |
228
|
|
|
* @param array<string,mixed> $data |
229
|
|
|
*/ |
230
|
79 |
|
private function addOpacity(array &$data): void |
231
|
|
|
{ |
232
|
79 |
|
if ($this->opacity !== 1.0) { |
|
|
|
|
233
|
|
|
$data['opacity'] = $this->opacity; |
234
|
|
|
} |
235
|
|
|
} |
236
|
|
|
|
237
|
79 |
|
private function isExportable(mixed $value): bool |
238
|
|
|
{ |
239
|
79 |
|
if ($value === null) { |
240
|
79 |
|
return false; |
241
|
|
|
} |
242
|
11 |
|
if (is_array($value)) { |
243
|
11 |
|
return !empty($value); |
244
|
|
|
} |
245
|
|
|
|
246
|
1 |
|
return true; |
247
|
|
|
} |
248
|
|
|
} |
249
|
|
|
|