APLBaseComponent::addEnumProperties()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 12
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 3.009

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 3
eloc 8
c 1
b 0
f 1
nc 3
nop 1
dl 0
loc 12
ccs 9
cts 10
cp 0.9
crap 3.009
rs 10
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) {
0 ignored issues
show
introduced by
The condition $this->opacity !== 1.0 is always true.
Loading history...
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