PluginProbe
TableKit – WordPress Table Builder for Data Tables, WooCommerce Product Tables & Post Tables / 2.2.10
TableKit – WordPress Table Builder for Data Tables, WooCommerce Product Tables & Post Tables v2.2.10
2.3.0 2.2.14 2.2.13 2.2.12 2.2.11 2.2.10 2.2.9 2.2.8 2.2.7 2.2.6 2.2.5 2.2.4 2.2.3 trunk 1.0.0 1.0.1 2.0.0 2.0.1 2.1.0 2.1.1 2.1.2 2.2.0 2.2.1 2.2.2
table-builder-block / includes / Render / BlockRenderer.php

BlockRenderer.php in TableKit – WordPress Table Builder for Data Tables, WooCommerce Product Tables & Post Tables 2.2.10, at includes/Render/BlockRenderer.php

178 lines 7.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Server-side rendering for the table-builder block and its rows/cells
4 *
5 * @package TableKit
6 */
7
8 namespace TableBuilder\Render;
9
10 defined( 'ABSPATH' ) || exit;
11
12 /**
13 * Renders table-builder block markup in PHP (used by the shortcode and
14 * dynamic-block rendering paths).
15 */
16 class BlockRenderer {
17
18 /**
19 * Renders static table-builder block structure in PHP.
20 *
21 * @param array $attributes Block attributes.
22 * @param array $row_blocks Parsed row inner blocks to render as tbody content.
23 * @param string $tbody_content Pre-rendered tbody HTML; used instead of $row_blocks when given.
24 * @return string Rendered block HTML.
25 */
26 public static function render_table_builder( array $attributes = array(), array $row_blocks = array(), string $tbody_content = '' ): string {
27 $caption = $attributes['caption'] ?? '';
28 $headers = is_array( $attributes['headers'] ?? null ) ? $attributes['headers'] : array();
29 $footers = is_array( $attributes['footers'] ?? null ) ? $attributes['footers'] : array();
30 $has_header = ! empty( $attributes['hasHeader'] );
31 $has_footer = ! empty( $attributes['hasFooter'] );
32 $show_caption = ! empty( $attributes['showCaption'] );
33 $is_empty = ! empty( $attributes['isEmpty'] );
34 $block_class = trim( (string) ( $attributes['blockClass'] ?? '' ) );
35 $block_id = (string) ( $attributes['blockID'] ?? '' );
36 $col_widths = is_array( $attributes['columnWidths'] ?? null ) ? $attributes['columnWidths'] : array();
37
38 $settings = array(
39 'enableSorting' => ! empty( $attributes['enableSorting'] ),
40 'tableConditionalFormat' => is_array( $attributes['tableConditionalFormat'] ?? null ) ? $attributes['tableConditionalFormat'] : array(),
41 'mergeTableCell' => $attributes['mergeTableCell'] ?? array(),
42 'freezeSettings' => $attributes['freezeSettings'] ?? array(),
43 'blockClass' => $block_class,
44 'enableFreeze' => ! empty( $attributes['enableFreeze'] ),
45 'columnWidths' => $col_widths,
46 'rowHeights' => is_array( $attributes['rowHeights'] ?? null ) ? $attributes['rowHeights'] : array(),
47 'headerHeight' => absint( $attributes['headerHeight'] ?? 0 ),
48 'resizerEnabled' => isset( $attributes['resizerEnabled'] ) ? (bool) $attributes['resizerEnabled'] : true,
49 );
50
51 $figure_classes = trim( 'wp-block-tablebuilder-table-builder table-builder-block ' . $block_class );
52 $figure_id = ! empty( $block_id ) ? 'block-' . sanitize_html_class( $block_id ) : '';
53
54 $has_widths = ! empty( $col_widths ) && array_sum( array_map( 'floatval', $col_widths ) ) > 0;
55 $table_style = $has_widths ? 'table-layout:fixed;width:100%;' : '';
56
57 $rendered_tbody = '';
58 if ( ! empty( $tbody_content ) ) {
59 $rendered_tbody = wp_kses_post( $tbody_content );
60 } elseif ( ! empty( $row_blocks ) ) {
61 $rendered_tbody = self::render_table_rows( $row_blocks );
62 }
63
64 ob_start();
65 ?>
66 <figure class="<?php echo esc_attr( $figure_classes ); ?>" data-block="tablebuilder/table-builder" data-settings="<?php echo esc_attr( wp_json_encode( $settings ) ); ?>"<?php echo ! empty( $figure_id ) ? ' id="' . esc_attr( $figure_id ) . '"' : ''; ?>>
67 <?php if ( ! $is_empty ) : ?>
68 <table class="gkit-table"<?php echo ! empty( $table_style ) ? ' style="' . esc_attr( $table_style ) . '"' : ''; ?>>
69 <?php if ( $has_header ) : ?>
70 <thead class="gkit-table__header">
71 <tr>
72 <?php foreach ( $headers as $index => $header ) : ?>
73 <?php $col_style = self::get_column_style( $col_widths, $index ); ?>
74 <th class="gkit-table__header-content"<?php echo ! empty( $col_style ) ? ' style="' . esc_attr( $col_style ) . '"' : ''; ?>>
75 <div><?php echo wp_kses_post( $header['title'] ?? '' ); ?></div>
76 </th>
77 <?php endforeach; ?>
78 </tr>
79 </thead>
80 <?php endif; ?>
81
82 <tbody class="gkit-table__body"><?php echo $rendered_tbody; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- built above via wp_kses_post() or from esc_attr()-escaped attributes plus core's render_block(). ?></tbody>
83
84 <?php if ( $has_footer ) : ?>
85 <tfoot class="gkit-table__footer">
86 <tr>
87 <?php foreach ( $footers as $index => $footer ) : ?>
88 <?php $col_style = self::get_column_style( $col_widths, $index ); ?>
89 <td class="gkit-table__footer-content"<?php echo ! empty( $col_style ) ? ' style="' . esc_attr( $col_style ) . '"' : ''; ?>>
90 <div><?php echo wp_kses_post( $footer['title'] ?? '' ); ?></div>
91 </td>
92 <?php endforeach; ?>
93 </tr>
94 </tfoot>
95 <?php endif; ?>
96 </table>
97
98 <?php if ( $show_caption ) : ?>
99 <figcaption class="gkit-table__caption"><?php echo wp_kses_post( $caption ); ?></figcaption>
100 <?php endif; ?>
101 <?php endif; ?>
102 </figure>
103 <?php
104
105 return (string) ob_get_clean();
106 }
107
108 /**
109 * Renders row and cell inner blocks for tbody markup.
110 *
111 * @param array $row_blocks Parsed "tablebuilder/table-builder-row" inner blocks.
112 * @return string Rendered <tr> markup.
113 */
114 private static function render_table_rows( array $row_blocks ): string {
115 $output = '';
116
117 foreach ( $row_blocks as $row_block ) {
118 if ( ( $row_block['blockName'] ?? '' ) !== 'tablebuilder/table-builder-row' ) {
119 continue;
120 }
121
122 $row_class = trim( 'wp-block-tablebuilder-table-builder-row gkit-table__body-row ' . ( $row_block['attrs']['blockClass'] ?? '' ) );
123 $output .= '<tr class="' . esc_attr( $row_class ) . '">';
124
125 foreach ( $row_block['innerBlocks'] ?? array() as $item_block ) {
126 if ( ( $item_block['blockName'] ?? '' ) !== 'tablebuilder/table-builder-item' ) {
127 continue;
128 }
129
130 $item_class = trim( 'wp-block-tablebuilder-table-builder-item gkit-table__body-content ' . ( $item_block['attrs']['blockClass'] ?? '' ) );
131 $item_markup = self::render_nested_inner_blocks( $item_block['innerBlocks'] ?? array() );
132 $output .= '<td class="' . esc_attr( $item_class ) . '"><div>' . $item_markup . '</div></td>';
133 }
134
135 $output .= '</tr>';
136 }
137
138 return $output;
139 }
140
141 /**
142 * Renders nested inner blocks of a cell.
143 *
144 * @param array $blocks Parsed inner blocks to render via core's render_block().
145 * @return string Combined rendered HTML.
146 */
147 private static function render_nested_inner_blocks( array $blocks ): string {
148 $output = '';
149
150 foreach ( $blocks as $inner ) {
151 $output .= render_block( $inner );
152 }
153
154 return $output;
155 }
156
157 /**
158 * Converts stored column widths into percentages for saved frontend parity.
159 *
160 * @param array $column_widths Stored column width values, keyed by column index.
161 * @param int $index Column index to compute the style for.
162 * @return string An inline "width:N%;" style, or an empty string if not applicable.
163 */
164 private static function get_column_style( array $column_widths, int $index ): string {
165 if ( empty( $column_widths[ $index ] ) ) {
166 return '';
167 }
168
169 $total_width = array_sum( array_map( 'floatval', $column_widths ) );
170 if ( $total_width <= 0 ) {
171 return '';
172 }
173
174 $percentage = ( (float) $column_widths[ $index ] / $total_width ) * 100;
175 return 'width:' . round( $percentage, 4 ) . '%;';
176 }
177 }
178