PluginProbe
Tableberg – Simple Gutenberg Table Block / 1.1.0
Tableberg – Simple Gutenberg Table Block v1.1.0
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.0, at renderer/Table/TableAttrs.php

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