PluginProbe
Tableberg – Simple Gutenberg Table Block / 1.1.2
Tableberg – Simple Gutenberg Table Block v1.1.2
1.1.5 1.1.4 1.1.3 1.1.2 1.1.1 1.1.0 1.0.5 1.0.4 1.0.3 1.0.2 1.0.1 trunk 0.0.2 0.2.1 0.3.2 0.3.3 0.4.1 0.5.0 0.5.1 0.5.2 0.5.3 0.5.4 0.5.5 0.5.6 0.5.7 All 42 releases
tableberg / renderer / Table / TableAttrs.php

TableAttrs.php in Tableberg – Simple Gutenberg Table Block 1.1.2, at renderer/Table/TableAttrs.php

722 lines 19.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Tableberg\Renderer\Table;
4
5 use Tableberg\Renderer\Attrs\NumberAttr;
6 use Tableberg\Renderer\Attrs\BoolAttr;
7 use Tableberg\Renderer\Attrs\StringAttr;
8 use Tableberg\Renderer\Attrs\Sides;
9 use Tableberg\Renderer\Attrs\Corners;
10
11 use function Tableberg\Renderer\getOrNull;
12
13 class TableAttrs {
14 /** @var NumberAttr */
15 public $version;
16
17 /** @var BoolAttr */
18 public $isExample;
19
20 /** @var TableConfig */
21 public $table;
22
23 /** @var array<int, RowConfig> */
24 public $rows;
25
26 /** @var array<int, ColumnConfig> */
27 public $columns;
28
29 /** @var array<string, CellData> */
30 public $cells;
31
32 /** @var array<string, array<string, mixed>> */
33 public $bindings;
34
35 /** @var CellDefaults */
36 public $cellDefaults;
37
38 /**
39 * Every attribute the table block carried, untouched. Pro registers
40 * table-level attributes of its own, so its renderer reads them from
41 * here rather than free having to know their names — mirrors
42 * CellData->attrs.
43 *
44 * @var array<string, mixed>
45 */
46 public $attrs;
47
48 /**
49 * @param array $data
50 * @return self
51 */
52 public static function from_array($data) {
53 $data = is_array($data) ? $data : [];
54 $defaults = Defaults::get_defaults();
55
56 $instance = new self();
57 $instance->attrs = $data;
58 $instance->version = new NumberAttr(
59 getOrNull($data['version']),
60 $defaults['version']
61 );
62 $instance->isExample = new BoolAttr(getOrNull($data['isExample']), $defaults['isExample']);
63 $instance->table = TableConfig::from_array(getOrNull($data['table']));
64 $instance->rows = self::parse_row_configs(getOrNull($data['rows']));
65 $instance->columns = self::parse_columns(getOrNull($data['columns']));
66 $instance->cells = self::parse_cells(getOrNull($data['cells']));
67 $instance->bindings = self::parse_bindings(getOrNull($data['bindings']));
68 $instance->cellDefaults = CellDefaults::from_array(getOrNull($data['cellDefaults']));
69
70 return $instance;
71 }
72
73 /** @return array<string, mixed> */
74 public static function get_table_defaults() {
75 $defaults = Defaults::get_defaults();
76
77 if (isset($defaults['table']) && is_array($defaults['table'])) {
78 return $defaults['table'];
79 }
80
81 if (isset($defaults['tableConfig']) && is_array($defaults['tableConfig'])) {
82 return $defaults['tableConfig'];
83 }
84
85 return [];
86 }
87
88 /** @return array<string, mixed> */
89 public static function get_cell_style_defaults() {
90 $defaults = Defaults::get_defaults();
91
92 if (
93 isset($defaults['cellDefaults']) &&
94 is_array($defaults['cellDefaults']) &&
95 isset($defaults['cellDefaults']['styles']) &&
96 is_array($defaults['cellDefaults']['styles'])
97 ) {
98 return array_merge(
99 ['cells' => []],
100 $defaults['cellDefaults']['styles']
101 );
102 }
103
104 if (isset($defaults['cellStyles']) && is_array($defaults['cellStyles'])) {
105 return array_merge(['cells' => []], $defaults['cellStyles']);
106 }
107
108 return ['cells' => []];
109 }
110
111 /** @return array<int, array{array{int, int}, array<int, mixed>}> */
112 public static function get_data_defaults() {
113 $defaults = Defaults::get_defaults();
114
115 if (
116 isset($defaults['data']) &&
117 is_array($defaults['data']) &&
118 isset($defaults['data']['cells']) &&
119 is_array($defaults['data']['cells'])
120 ) {
121 return $defaults['data']['cells'];
122 }
123
124 return [];
125 }
126
127 /** @return array<int, RowConfig> */
128 private static function parse_row_configs($data) {
129 if (!is_array($data)) {
130 return [];
131 }
132
133 $row_configs = [];
134
135 foreach ($data as $row => $row_config) {
136 $row_configs[(int) $row] = RowConfig::from_array($row_config);
137 }
138
139 return $row_configs;
140 }
141
142 /** @return array<int, ColumnConfig> */
143 private static function parse_columns($data) {
144 if (!is_array($data)) {
145 return [];
146 }
147
148 $columns = [];
149
150 foreach ($data as $column => $column_config) {
151 $columns[(int) $column] = ColumnConfig::from_array($column_config);
152 }
153
154 return $columns;
155 }
156
157 /** @return array<string, CellData> */
158 private static function parse_cells($data) {
159 if (!is_array($data)) {
160 return [];
161 }
162
163 $cells = [];
164
165 foreach ($data as $key => $cell) {
166 if (!is_string($key)) {
167 continue;
168 }
169
170 $cells[$key] = CellData::from_array($cell);
171 }
172
173 return $cells;
174 }
175
176 /** @return array<string, array<string, mixed>> */
177 private static function parse_bindings($data) {
178 if (!is_array($data)) {
179 return [];
180 }
181
182 $bindings = [];
183
184 foreach ($data as $key => $binding) {
185 if (!is_string($key) || !is_array($binding)) {
186 continue;
187 }
188
189 $bindings[$key] = $binding;
190 }
191
192 return $bindings;
193 }
194 }
195
196 class Data {
197 /** @var array<int, array{array{int, int}, array<int, CellElement>}> */
198 public $cells;
199
200 /** @return self */
201 public static function from_array($data) {
202 $data = is_array($data) ? $data : [];
203 $default_cells = TableAttrs::get_data_defaults();
204
205 $instance = new self();
206 $instance->cells = self::parse_cells(getOrNull($data['cells']), $default_cells);
207
208 return $instance;
209 }
210
211 /** @return array<int, array{array{int, int}, array<int, CellElement>}> */
212 private static function parse_cells($data, $default) {
213 if (!is_array($data)) {
214 return $default;
215 }
216
217 $cells = [];
218
219 foreach ($data as $cell) {
220 if (!is_array($cell[0])) {
221 continue;
222 }
223
224 $coords = [(int) $cell[0][0], (int) $cell[0][1]];
225 $elements = [];
226
227 if (is_array($cell[1])) {
228 foreach ($cell[1] as $element) {
229 $elements[] = CellElement::from_array($element);
230 }
231 }
232
233 $cells[] = [$coords, $elements];
234 }
235
236 return $cells;
237 }
238 }
239
240 class PaginationConfig {
241 /** @var BoolAttr */
242 public $enabled;
243
244 /** @var NumberAttr */
245 public $pageSize;
246
247 /** @var BoolAttr */
248 public $showPageNumbers;
249
250 /** @var BoolAttr */
251 public $showPrevNext;
252
253 /** @return self */
254 public static function from_array($data) {
255 $data = is_array($data) ? $data : [];
256 $table_defaults = TableAttrs::get_table_defaults();
257 $d = isset($table_defaults['pagination']) && is_array($table_defaults['pagination'])
258 ? $table_defaults['pagination']
259 : [];
260
261 $instance = new self();
262 $instance->enabled = new BoolAttr(getOrNull($data['enabled']), $d['enabled']);
263 $instance->pageSize = new NumberAttr(getOrNull($data['pageSize']), $d['pageSize']);
264 $instance->showPageNumbers = new BoolAttr(getOrNull($data['showPageNumbers']), $d['showPageNumbers']);
265 $instance->showPrevNext = new BoolAttr(getOrNull($data['showPrevNext']), $d['showPrevNext']);
266
267 return $instance;
268 }
269 }
270
271 class ResponsiveBreakpointConfig {
272 /** @var BoolAttr */
273 public $enabled;
274
275 /** @var NumberAttr */
276 public $maxWidth;
277
278 /** @var StringAttr */
279 public $mode;
280
281 /** @var BoolAttr */
282 public $transpose;
283
284 /** @var NumberAttr */
285 public $stackCount;
286
287 /** @var BoolAttr */
288 public $repeatFirstCol;
289
290 /**
291 * @param array|null $data
292 * @param array<string, mixed> $defaults
293 * @return self
294 */
295 public static function from_array($data, $defaults) {
296 $data = is_array($data) ? $data : [];
297
298 $instance = new self();
299 $instance->enabled = new BoolAttr(getOrNull($data['enabled']), $defaults['enabled']);
300 $instance->maxWidth = new NumberAttr(getOrNull($data['maxWidth']), $defaults['maxWidth']);
301 $instance->mode = new StringAttr(
302 getOrNull($data['mode']),
303 $defaults['mode'],
304 ['', 'scroll', 'stack']
305 );
306 $transposeInput = getOrNull($data['transpose']);
307 $legacyDirectionInput = getOrNull($data['direction']);
308 if ($transposeInput === null && is_string($legacyDirectionInput)) {
309 $transposeInput = $legacyDirectionInput === 'row';
310 }
311
312 $instance->transpose = new BoolAttr(
313 $transposeInput,
314 $defaults['transpose']
315 );
316 $instance->stackCount = new NumberAttr(
317 getOrNull($data['stackCount']),
318 $defaults['stackCount']
319 );
320
321 $repeatFirstColInput = getOrNull($data['repeatFirstCol']);
322 if ($repeatFirstColInput === null) {
323 $repeatFirstColInput = getOrNull($data['headerAsCol']);
324 }
325
326 $instance->repeatFirstCol = new BoolAttr(
327 $repeatFirstColInput,
328 $defaults['repeatFirstCol']
329 );
330
331 return $instance;
332 }
333 }
334
335 class ResponsiveConfig {
336 /** @var ResponsiveBreakpointConfig */
337 public $tablet;
338
339 /** @var ResponsiveBreakpointConfig */
340 public $mobile;
341
342 /** @return self */
343 public static function from_array($data) {
344 $data = is_array($data) ? $data : [];
345 $table_defaults = TableAttrs::get_table_defaults();
346 $defaults = isset($table_defaults['responsive']) && is_array($table_defaults['responsive'])
347 ? $table_defaults['responsive']
348 : [];
349
350 $instance = new self();
351 $instance->tablet = ResponsiveBreakpointConfig::from_array(
352 getOrNull($data['tablet']),
353 $defaults['tablet']
354 );
355 $instance->mobile = ResponsiveBreakpointConfig::from_array(
356 getOrNull($data['mobile']),
357 $defaults['mobile']
358 );
359
360 return $instance;
361 }
362 }
363
364 class CellSpacingConfig {
365 /** @var StringAttr */
366 public $horizontal;
367
368 /** @var StringAttr */
369 public $vertical;
370
371 /** @return self */
372 public static function from_array($data) {
373 $data = is_array($data) ? $data : [];
374 $table_defaults = TableAttrs::get_table_defaults();
375 $defaults = isset($table_defaults['cellSpacing']) && is_array($table_defaults['cellSpacing'])
376 ? $table_defaults['cellSpacing']
377 : [];
378
379 $instance = new self();
380 $instance->horizontal = new StringAttr(
381 getOrNull($data['horizontal']),
382 $defaults['horizontal']
383 );
384 $instance->vertical = new StringAttr(
385 getOrNull($data['vertical']),
386 $defaults['vertical']
387 );
388
389 return $instance;
390 }
391 }
392
393 class CellDefaults {
394 /** @var CellStyles */
395 public $styles;
396
397 /** @return self */
398 public static function from_array($data) {
399 $data = is_array($data) ? $data : [];
400
401 $instance = new self();
402 $instance->styles = CellStyles::from_array(getOrNull($data['styles']));
403
404 return $instance;
405 }
406 }
407
408 class CellData {
409 /** @var Span */
410 public $span;
411
412 /** @var StringAttr */
413 public $className;
414
415 /** @var array<int, CellElement> */
416 public $elements;
417
418 /** @var array<string, mixed>|null */
419 public $styles;
420
421 /** @var array<string, mixed>|null */
422 public $ribbon;
423
424 /**
425 * Every attribute the cell block carried, untouched. Pro registers cell
426 * attributes of its own, so its renderer reads them from here rather
427 * than free having to know their names.
428 *
429 * @var array<string, mixed>
430 */
431 public $attrs;
432
433 /** @return self */
434 public static function from_array($data) {
435 $data = is_array($data) ? $data : [];
436
437 $instance = new self();
438 $instance->attrs = $data;
439 $instance->span = Span::from_array(getOrNull($data['span']));
440 $instance->className = new StringAttr(getOrNull($data['className']), '');
441 $instance->elements = [];
442
443 $elements = getOrNull($data['elements']);
444 if (is_array($elements)) {
445 foreach ($elements as $element) {
446 $instance->elements[] = CellElement::from_array($element);
447 }
448 }
449
450 $styles = getOrNull($data['styles']);
451 $instance->styles = is_array($styles) ? $styles : null;
452
453 $ribbon = getOrNull($data['ribbon']);
454 $instance->ribbon = is_array($ribbon) ? $ribbon : null;
455
456 return $instance;
457 }
458 }
459
460 class TableConfig {
461 /** @var NumberAttr */
462 public $rows;
463
464 /** @var NumberAttr */
465 public $cols;
466
467 /** @var StringAttr */
468 public $className;
469
470 /** @var BoolAttr */
471 public $headerEnabled;
472
473 /** @var BoolAttr */
474 public $footerEnabled;
475
476 /** @var StringAttr */
477 public $caption;
478
479 /** @var StringAttr */
480 public $tableWidth;
481
482 /** @var StringAttr */
483 public $tableAlignment;
484
485 /** @var CellSpacingConfig */
486 public $cellSpacing;
487
488 /** @var Sides */
489 public $tableBorder;
490
491 /** @var Sides */
492 public $margin;
493
494 /** @var Sides */
495 public $padding;
496
497 /** @var BoolAttr */
498 public $fixedColumnWidths;
499
500 /** @var PaginationConfig */
501 public $pagination;
502
503 /** @var ResponsiveConfig */
504 public $responsive;
505
506 /** @return self */
507 public static function from_array($data) {
508 $data = is_array($data) ? $data : [];
509 $d = TableAttrs::get_table_defaults();
510
511 $instance = new self();
512 $instance->rows = new NumberAttr(getOrNull($data['rows']), $d['rows']);
513 $instance->cols = new NumberAttr(getOrNull($data['cols']), $d['cols']);
514 $instance->className = new StringAttr(getOrNull($data['className']), '');
515 $instance->headerEnabled = new BoolAttr(getOrNull($data['headerEnabled']), $d['headerEnabled']);
516 $instance->footerEnabled = new BoolAttr(getOrNull($data['footerEnabled']), $d['footerEnabled']);
517 $instance->caption = new StringAttr(getOrNull($data['caption']), $d['caption']);
518 $instance->tableWidth = new StringAttr(
519 getOrNull($data['tableWidth']),
520 $d['tableWidth']
521 );
522 $instance->tableAlignment = new StringAttr(
523 getOrNull($data['tableAlignment']),
524 $d['tableAlignment'],
525 ['left', 'center', 'right']
526 );
527 $instance->cellSpacing = CellSpacingConfig::from_array(getOrNull($data['cellSpacing']));
528 $instance->tableBorder = Sides::from_array(
529 getOrNull($data['tableBorder']),
530 $d['tableBorder']
531 );
532 $emptySides = ['top' => '', 'right' => '', 'bottom' => '', 'left' => ''];
533 $instance->margin = Sides::from_array(
534 getOrNull($data['margin']),
535 isset($d['margin']) && is_array($d['margin']) ? $d['margin'] : $emptySides
536 );
537 $instance->padding = Sides::from_array(
538 getOrNull($data['padding']),
539 isset($d['padding']) && is_array($d['padding']) ? $d['padding'] : $emptySides
540 );
541 $instance->fixedColumnWidths = new BoolAttr(
542 getOrNull($data['fixedColumnWidths']),
543 $d['fixedColumnWidths']
544 );
545 $instance->pagination = PaginationConfig::from_array(getOrNull($data['pagination']));
546 $instance->responsive = ResponsiveConfig::from_array(getOrNull($data['responsive']));
547
548 return $instance;
549 }
550 }
551
552 class CellStyles {
553 /** @var Sides */
554 public $padding;
555
556 /** @var StringAttr */
557 public $elementGap;
558
559 /** @var StringAttr */
560 public $verticalAlign;
561
562 /** @var StringAttr */
563 public $backgroundColor;
564
565 /** @var Sides */
566 public $border;
567
568 /** @var Corners */
569 public $borderRadius;
570
571 /** @var array<int, array{array{int, int}, array<string, mixed>}> */
572 public $cells;
573
574 /** @return self */
575 public static function from_array($data) {
576 $data = is_array($data) ? $data : [];
577 $d = TableAttrs::get_cell_style_defaults();
578
579 $instance = new self();
580 $instance->padding = Sides::from_array(getOrNull($data['padding']), $d['padding']);
581 $instance->elementGap = new StringAttr(
582 getOrNull($data['elementGap']),
583 $d['elementGap']
584 );
585 $instance->verticalAlign = new StringAttr(
586 getOrNull($data['verticalAlign']),
587 $d['verticalAlign'],
588 ['top', 'middle', 'bottom']
589 );
590 $instance->backgroundColor = new StringAttr(getOrNull($data['backgroundColor']), $d['backgroundColor']);
591 $instance->border = Sides::from_array(getOrNull($data['border']), $d['border']);
592 $instance->borderRadius = Corners::from_array(getOrNull($data['borderRadius']), $d['borderRadius']);
593 $instance->cells = is_array(getOrNull($data['cells'])) ? $data['cells'] : $d['cells'];
594
595 return $instance;
596 }
597 }
598
599 class Span {
600 /** @var NumberAttr */
601 public $rowSpan;
602
603 /** @var NumberAttr */
604 public $colSpan;
605
606 /**
607 * @param array|null $data
608 * @param array<string, int> $defaults
609 * @return self
610 */
611 public static function from_array($data, $defaults = ['rowSpan' => 1, 'colSpan' => 1]) {
612 $data = is_array($data) ? $data : [];
613
614 $defaultRowSpan = $defaults['rowSpan'];
615 $defaultColSpan = $defaults['colSpan'];
616
617 $instance = new self();
618 $instance->rowSpan = new NumberAttr(getOrNull($data['rowSpan']), $defaultRowSpan);
619 $instance->colSpan = new NumberAttr(getOrNull($data['colSpan']), $defaultColSpan);
620
621 return $instance;
622 }
623 }
624
625 class ColumnConfig {
626 /** @var StringAttr|null */
627 public $width;
628
629 /** @return self */
630 public static function from_array($data) {
631 $data = is_array($data) ? $data : [];
632 $width = getOrNull($data['width']);
633
634 $instance = new self();
635
636 if ($width === null || $width === '') {
637 $instance->width = null;
638 } else {
639 $instance->width = new StringAttr($width, '');
640 }
641
642 return $instance;
643 }
644 }
645
646 class RowConfig {
647 /** @var StringAttr|null */
648 public $height;
649
650 /**
651 * Every attribute the row block carried, untouched. Pro registers row
652 * attributes of its own (e.g. backgroundColor), so its renderer reads
653 * them from here rather than free having to know their names.
654 *
655 * @var array<string, mixed>
656 */
657 public $attrs;
658
659 /**
660 * @param array|null $data
661 * @return self
662 */
663 public static function from_array($data) {
664 $data = is_array($data) ? $data : [];
665 $height = getOrNull($data['height']);
666
667 $instance = new self();
668 $instance->attrs = $data;
669
670 if ($height === null || $height === '') {
671 $instance->height = null;
672 } else {
673 $instance->height = new StringAttr($height, '');
674 }
675
676 return $instance;
677 }
678 }
679
680 class CellElement {
681 /** @var StringAttr */
682 public $name;
683
684 /** @var array<string, mixed> */
685 public $attributes;
686
687 /** @var array<string, mixed>|null */
688 public $bindings;
689
690 /**
691 * @param array|null $data
692 * @param string $defaultName
693 * @param array<int, string>|null $allowedNames
694 * @return self
695 */
696 public static function from_array($data, $defaultName = 'text', $allowedNames = null) {
697 $data = is_array($data) ? $data : [];
698
699 if (!is_array($allowedNames)) {
700 $allowedNames = [
701 'text',
702 'button',
703 'image',
704 'list',
705 'icon',
706 'star-rating',
707 'custom-html',
708 'styled-list',
709 ];
710 }
711
712 $instance = new self();
713 $instance->name = new StringAttr(getOrNull($data['name']), $defaultName, $allowedNames);
714 $attributes = getOrNull($data['attributes']);
715 $instance->attributes = is_array($attributes) ? $attributes : [];
716 $bindings = getOrNull($data['bindings']);
717 $instance->bindings = is_array($bindings) ? $bindings : null;
718
719 return $instance;
720 }
721 }
722