PluginProbe
Tableberg – Simple Gutenberg Table Block / 1.1.5
Tableberg – Simple Gutenberg Table Block v1.1.5
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
← All changes | renderer/Table/TableRenderer.php +85 -24 1.1.31.1.5 View file →
@@ -69,8 +69,19 @@
69 69 );
70 70 $stickyHeader = !empty($stickySettings['stickyHeader']);
71 71 $stickyFirstCol = !empty($stickySettings['stickyFirstCol']);
72 72
73 + // Row-only/column-only is Pro-owned. Free's empty default preserves
74 + // the attribute without enabling its editor or frontend behavior.
75 + $innerBorderType = apply_filters(
76 + 'tableberg/inner_border_type',
77 + '',
78 + $attrs->attrs
79 + );
80 + if (!in_array($innerBorderType, ['row', 'col'], true)) {
81 + $innerBorderType = '';
82 + }
83 +
73 84 $caption = $attrs->table->caption;
74 85 $tableWidth = trim($attrs->table->tableWidth->asAttr());
75 86 $tableAlignment = $attrs->table->tableAlignment->asAttr();
76 87 $cellSpacingHorizontal = trim($attrs->table->cellSpacing->horizontal->asAttr());
@@ -79,8 +90,24 @@
79 90 $tableBorderRight = trim($attrs->table->tableBorder->right->asAttr());
80 91 $tableBorderBottom = trim($attrs->table->tableBorder->bottom->asAttr());
81 92 $tableBorderLeft = trim($attrs->table->tableBorder->left->asAttr());
82 93 $fixedColumnWidths = $attrs->table->fixedColumnWidths->value();
94 + $tableRadius = [
95 + 'topLeft' => $attrs->cellDefaults->styles->borderRadius->topLeft->asAttr(),
96 + 'topRight' => $attrs->cellDefaults->styles->borderRadius->topRight->asAttr(),
97 + 'bottomRight' => $attrs->cellDefaults->styles->borderRadius->bottomRight->asAttr(),
98 + 'bottomLeft' => $attrs->cellDefaults->styles->borderRadius->bottomLeft->asAttr(),
99 + ];
100 + $isZeroRadius = function ($value) {
101 + $trimmed = trim((string) $value);
102 + return $trimmed === '' || preg_match('/^0(?:\.0+)?[a-z%]*$/i', $trimmed) === 1;
103 + };
104 + $hasRoundedCorners = count(array_filter(
105 + $tableRadius,
106 + function ($value) use ($isZeroRadius) {
107 + return !$isZeroRadius($value);
108 + }
109 + )) > 0;
83 110
84 111 $isHorizontalSpacingZero = $cellSpacingHorizontal === '0';
85 112 $isVerticalSpacingZero = $cellSpacingVertical === '0';
86 113 $hasCellSpacing = !$isHorizontalSpacingZero || !$isVerticalSpacingZero;
@@ -106,8 +133,11 @@
106 133 );
107 134
108 135 $tableStyles = [
109 136 'border-collapse: ' . ($hasCellSpacing ? 'separate' : 'collapse'),
137 + // Neutralize theme-level table borders. Tableberg owns its
138 + // borders through the table/cell controls and rounded wrapper.
139 + 'border: 0',
110 140 ];
111 141
112 142 if ($hasCellSpacing) {
113 143 $tableStyles[] = "border-spacing: {$cellSpacingHorizontal} {$cellSpacingVertical}";
@@ -119,21 +149,21 @@
119 149 } else {
120 150 $tableStyles[] = 'width: 100%';
121 151 }
122 152
123 - if ($tableBorderTop !== '') {
153 + if (!$hasRoundedCorners && $tableBorderTop !== '') {
124 154 $tableStyles[] = "border-top: {$tableBorderTop}";
125 155 }
126 156
127 - if ($tableBorderRight !== '') {
157 + if (!$hasRoundedCorners && $tableBorderRight !== '') {
128 158 $tableStyles[] = "border-right: {$tableBorderRight}";
129 159 }
130 160
131 - if ($tableBorderBottom !== '') {
161 + if (!$hasRoundedCorners && $tableBorderBottom !== '') {
132 162 $tableStyles[] = "border-bottom: {$tableBorderBottom}";
133 163 }
134 164
135 - if ($tableBorderLeft !== '') {
165 + if (!$hasRoundedCorners && $tableBorderLeft !== '') {
136 166 $tableStyles[] = "border-left: {$tableBorderLeft}";
137 167 }
138 168
139 169 $tableStyleAttr = "style='" . implode('; ', $tableStyles) . ";'";
@@ -244,13 +274,18 @@
244 274 'bottomLeft' => $attrs->cellDefaults->styles->borderRadius->bottomLeft->asAttr(),
245 275 ],
246 276 ];
247 277
248 - // The table border radius rounds the whole table's outer corners.
249 - // border-radius on collapsed-border tables/cells is ignored by
250 - // browsers, so it is rendered on the wrapper (with overflow:hidden)
251 - // and removed from the individual cells here.
252 - $tableRadius = $globalCellStyles['borderRadius'];
278 + // A collapsed table cannot reliably round its own explicit border.
279 + // The wrapper owns only the table border and clips the cell grid to
280 + // it. Cell borders stay on cells; copying them to the wrapper would
281 + // add an outline that the user did not configure as a table border.
282 + $tableOuterBorder = [
283 + 'top' => $tableBorderTop,
284 + 'right' => $tableBorderRight,
285 + 'bottom' => $tableBorderBottom,
286 + 'left' => $tableBorderLeft,
287 + ];
253 288 $globalCellStyles['borderRadius'] = [
254 289 'topLeft' => '',
255 290 'topRight' => '',
256 291 'bottomRight' => '',
@@ -368,9 +403,12 @@
368 403 $stickyHeader,
369 404 $stickyFirstCol,
370 405 $this->getCellClassName($cell),
371 406 $cell instanceof CellData ? $cell->attrs : [],
372 - $this->isCellEmpty($cell)
407 + $this->isCellEmpty($cell),
408 + $innerBorderType,
409 + $rows,
410 + $cols
373 411 )
374 412 );
375 413 }
376 414
@@ -408,27 +446,29 @@
408 446 'sortable' => $sortType,
409 447 ];
410 448 }
411 449
412 - $columnsJson = json_encode($columnsData);
450 + $columnsJson = wp_json_encode($columnsData);
413 451 if (!is_string($columnsJson)) {
414 452 $columnsJson = '{}';
415 453 }
454 + $columnsJson = esc_attr($columnsJson);
416 455
417 - $paginationJson = json_encode($paginationConfig);
456 + $paginationJson = wp_json_encode($paginationConfig);
418 457 if (!is_string($paginationJson)) {
419 458 $paginationJson = '{}';
420 459 }
460 + $paginationJson = esc_attr($paginationJson);
421 461
462 + $searchPlaceholderAttr = esc_attr($searchPlaceholder);
463 + $searchPositionAttr = esc_attr($searchPosition);
464 + $searchHighlightColorAttr = esc_attr($searchHighlightColor);
465 +
422 466 $wrapperClass = trim("tableberg-table-wrapper {$wrapperAlignmentClass}");
423 467
424 - // Round the whole table's outer corners by clipping the wrapper.
468 + // Round the whole table's outer corners on the wrapper.
425 469 // Zero radii are skipped so a table without any actual rounding does
426 470 // not carry pointless border-radius declarations.
427 - $isZeroRadius = function ($value) {
428 - $trimmed = trim((string) $value);
429 - return $trimmed === '' || preg_match('/^0(?:\.0+)?[a-z%]*$/i', $trimmed) === 1;
430 - };
431 471 $wrapperStyles = [];
432 472 if (!$isZeroRadius($tableRadius['topLeft'])) {
433 473 $wrapperStyles[] = 'border-top-left-radius:' . $tableRadius['topLeft'];
434 474 }
@@ -441,8 +481,24 @@
441 481 if (!$isZeroRadius($tableRadius['bottomLeft'])) {
442 482 $wrapperStyles[] = 'border-bottom-left-radius:' . $tableRadius['bottomLeft'];
443 483 }
444 484
485 + if (!empty($wrapperStyles)) {
486 + if ($tableOuterBorder['top'] !== '') {
487 + $wrapperStyles[] = 'border-top:' . $tableOuterBorder['top'];
488 + }
489 + if ($tableOuterBorder['right'] !== '') {
490 + $wrapperStyles[] = 'border-right:' . $tableOuterBorder['right'];
491 + }
492 + if ($tableOuterBorder['bottom'] !== '') {
493 + $wrapperStyles[] = 'border-bottom:' . $tableOuterBorder['bottom'];
494 + }
495 + if ($tableOuterBorder['left'] !== '') {
496 + $wrapperStyles[] = 'border-left:' . $tableOuterBorder['left'];
497 + }
498 + $wrapperStyles[] = 'box-sizing:border-box';
499 + }
500 +
445 501 // A table wider than its wrapper must scroll inside the wrapper
446 502 // instead of pushing the whole page sideways, so the wrapper is a
447 503 // scroll container by default.
448 504 //
@@ -454,10 +510,8 @@
454 510 // scrolling wins and the header sticks within the wrapper.
455 511 //
456 512 // A rounded wrapper always needs the clip, so it opts in regardless.
457 513 $pageStickyHeader = $stickyHeader && !$stickyFirstCol;
458 - $hasRoundedCorners = !empty($wrapperStyles);
459 -
460 514 if ($hasRoundedCorners || !$pageStickyHeader) {
461 515 // `auto`, not `hidden`: both clip to the rounded corners, but
462 516 // `hidden` would also swallow a table wider than the wrapper.
463 517 // Inline, so it also wins over the `.tableberg-scroll-x` rule.
@@ -517,11 +571,11 @@
517 571 data-tableberg-sortable='$sortingBoolAsStr'
518 572 data-tableberg-columns='$columnsJson'
519 573 data-tableberg-pagination='$paginationJson'
520 574 data-tableberg-search-enabled='$searchEnabledAsStr'
521 - data-tableberg-search-placeholder='$searchPlaceholder'
522 - data-tableberg-search-position='$searchPosition'
523 - data-tableberg-search-highlight-color='$searchHighlightColor'
575 + data-tableberg-search-placeholder='$searchPlaceholderAttr'
576 + data-tableberg-search-position='$searchPositionAttr'
577 + data-tableberg-search-highlight-color='$searchHighlightColorAttr'
524 578 data-tableberg-header='$headerBoolAsStr'
525 579 data-tableberg-footer='$footerBoolAsStr'
526 580 {$responsiveDataAttrs}
527 581 >
@@ -593,8 +647,15 @@
593 647 $mobileMaxWidth = max(1, (int) $mobile->maxWidth->value());
594 648 $tabletStackCount = max(1, (int) $tablet->stackCount->value());
595 649 $mobileStackCount = max(1, (int) $mobile->stackCount->value());
596 650
651 + // Repeating the first column in every stack row is a pro option. Only
652 + // the licensed pro plugin turns this filter on, so the saved value is
653 + // ignored without a valid licence.
654 + $proActive = (bool) apply_filters('tableberg/is_pro_runtime_active', false);
655 + $tabletRepeatFirstCol = $proActive ? $tablet->repeatFirstCol->asAttr() : '';
656 + $mobileRepeatFirstCol = $proActive ? $mobile->repeatFirstCol->asAttr() : '';
657 +
597 658 return "
598 659 data-tableberg-responsive='true'
599 660 data-tableberg-rows='{$rows}'
600 661 data-tableberg-cols='{$cols}'
@@ -602,15 +663,15 @@
602 663 data-tableberg-tablet-width='{$tabletMaxWidth}'
603 664 data-tableberg-tablet-mode='{$tablet->mode->asAttr()}'
604 665 data-tableberg-tablet-transpose='{$tablet->transpose->asAttr()}'
605 666 data-tableberg-tablet-count='{$tabletStackCount}'
606 - data-tableberg-tablet-repeat-first-col='{$tablet->repeatFirstCol->asAttr()}'
667 + data-tableberg-tablet-repeat-first-col='{$tabletRepeatFirstCol}'
607 668 data-tableberg-mobile-enabled='{$mobile->enabled->asAttr()}'
608 669 data-tableberg-mobile-width='{$mobileMaxWidth}'
609 670 data-tableberg-mobile-mode='{$mobile->mode->asAttr()}'
610 671 data-tableberg-mobile-transpose='{$mobile->transpose->asAttr()}'
611 672 data-tableberg-mobile-count='{$mobileStackCount}'
612 - data-tableberg-mobile-repeat-first-col='{$mobile->repeatFirstCol->asAttr()}'
673 + data-tableberg-mobile-repeat-first-col='{$mobileRepeatFirstCol}'
613 674 ";
614 675 }
615 676
616 677 private function getCell($row, $col, $cells) {