PluginProbe
aBlocks – Gutenberg Blocks, User Dashboard Builder, Popup Builder, Form Builder & Animation Builder / 2.14.0
aBlocks – Gutenberg Blocks, User Dashboard Builder, Popup Builder, Form Builder & Animation Builder v2.14.0
2.14.0 2.13.0 2.13.1 2.12.0 2.11.1 2.11.0 2.10.0 2.9.0 2.7.4 2.7.5 2.7.6 2.7.7 2.8.0 2.8.1 2.9.1 trunk 1.0 1.0-beta1 1.0-beta2 1.0-beta3 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 All 81 releases
← All changes | includes/blocks/table-of-content/block.php +183 -85 2.9.1 → 2.14.0 View file →
@@ -6,8 +6,9 @@
6 6 }
7 7
8 8 use ABlocks\Classes\BlockBaseAbstract;
9 9 use ABlocks\Classes\CssGenerator;
10 +use ABlocks\Classes\CssGeneratorV2;
10 11 use ABlocks\Helper;
11 12 use ABlocks\Controls\Typography;
12 13 use ABlocks\Controls\Background;
13 14 use ABlocks\Controls\Border;
@@ -13,14 +14,16 @@
13 14 use ABlocks\Controls\Border;
14 15 use ABlocks\Controls\Dimensions;
15 16 use ABlocks\Controls\Alignment;
16 17 use ABlocks\Controls\Range;
18 +use ABlocks\Controls\Color;
19 +use ABlocks\Controls\BoxShadow;
17 20
18 21 class Block extends BlockBaseAbstract {
19 22 protected $block_name = 'table-of-content';
20 23
21 24
22 - public function build_css( $attributes ) {
25 + public function build_css_v1( $attributes ) {
23 26 $css_generator = new CssGenerator( $attributes );
24 27
25 28 $css_generator->add_class_styles(
26 29 '{{WRAPPER}} .ablocks-toc__header-title',
@@ -25,103 +28,184 @@
25 28 $css_generator->add_class_styles(
26 29 '{{WRAPPER}} .ablocks-toc__header-title',
27 30 $this->get_toc_title_css( $attributes ),
28 31 $this->get_toc_title_css( $attributes, 'Tablet' ),
29 - $this->get_toc_title_css( $attributes, 'Mobile' )
32 + $this->get_toc_title_css( $attributes, 'Mobile' ),
33 + $css_generator->custom_device_map( function ( $device ) use ( $attributes ) { return $this->get_toc_title_css( $attributes, $device ); } )
30 34 );
31 35 $css_generator->add_class_styles(
32 36 '{{WRAPPER}} .ablocks-toc__header',
33 37 $this->get_toc_header_css( $attributes ),
34 38 $this->get_toc_header_css( $attributes, 'Tablet' ),
35 - $this->get_toc_header_css( $attributes, 'Mobile' )
39 + $this->get_toc_header_css( $attributes, 'Mobile' ),
40 + $css_generator->custom_device_map( function ( $device ) use ( $attributes ) { return $this->get_toc_header_css( $attributes, $device ); } )
36 41 );
37 42 $css_generator->add_class_styles(
38 43 '{{WRAPPER}} .ablocks-toc-body',
39 44 $this->get_toc_body_css( $attributes ),
40 45 $this->get_toc_body_css( $attributes, 'Tablet' ),
41 - $this->get_toc_body_css( $attributes, 'Mobile' )
46 + $this->get_toc_body_css( $attributes, 'Mobile' ),
47 + $css_generator->custom_device_map( function ( $device ) use ( $attributes ) { return $this->get_toc_body_css( $attributes, $device ); } )
42 48 );
43 49 $css_generator->add_class_styles(
44 - '{{WRAPPER}} .ablocks-toc__header-toggle-icon svg',
50 + '{{WRAPPER}} .ablocks-toc__header-toggle-icon .ablocks-toc__show',
45 51 $this->get_toc_header_icon_css( $attributes ),
46 52 $this->get_toc_header_icon_css( $attributes, 'Tablet' ),
47 - $this->get_toc_header_icon_css( $attributes, 'Mobile' )
53 + $this->get_toc_header_icon_css( $attributes, 'Mobile' ),
54 + $css_generator->custom_device_map( function ( $device ) use ( $attributes ) { return $this->get_toc_header_icon_css( $attributes, $device ); } )
48 55 );
49 56 $css_generator->add_class_styles(
57 + '{{WRAPPER}} .ablocks-toc__header-toggle-icon .ablocks-toc__show:hover',
58 + $this->get_toc_header_icon_hover_css( $attributes ),
59 + $this->get_toc_header_icon_hover_css( $attributes, 'Tablet' ),
60 + $this->get_toc_header_icon_hover_css( $attributes, 'Mobile' ),
61 + $css_generator->custom_device_map( function ( $device ) use ( $attributes ) { return $this->get_toc_header_icon_hover_css( $attributes, $device ); } )
62 + );
63 + $css_generator->add_class_styles(
50 64 '{{WRAPPER}} .ablocks-block-container .ablocks-toc-list,
51 65 {{WRAPPER}} .ablocks-block-container .ablocks-toc-list li a',
52 66 $this->get_list_item_css( $attributes ),
53 67 $this->get_list_item_css( $attributes, 'Tablet' ),
54 - $this->get_list_item_css( $attributes, 'Mobile' )
68 + $this->get_list_item_css( $attributes, 'Mobile' ),
69 + $css_generator->custom_device_map( function ( $device ) use ( $attributes ) { return $this->get_list_item_css( $attributes, $device ); } )
55 70 );
56 71
57 72 return $css_generator->generate_css();
58 73 }
74 + public function build_css_v2( $attributes ) {
75 + $css_generator = new CssGeneratorV2( $attributes, $this->block_name );
59 76
77 + $css_generator->add_class_styles(
78 + '{{WRAPPER}} .ablocks-toc__header-title',
79 + $this->get_toc_title_css( $attributes ),
80 + $this->get_toc_title_css( $attributes, 'Tablet' ),
81 + $this->get_toc_title_css( $attributes, 'Mobile' ),
82 + $css_generator->custom_device_map( function ( $device ) use ( $attributes ) { return $this->get_toc_title_css( $attributes, $device ); } )
83 + );
84 + $css_generator->add_class_styles(
85 + '{{WRAPPER}} .ablocks-toc__header',
86 + $this->get_toc_header_css( $attributes ),
87 + $this->get_toc_header_css( $attributes, 'Tablet' ),
88 + $this->get_toc_header_css( $attributes, 'Mobile' ),
89 + $css_generator->custom_device_map( function ( $device ) use ( $attributes ) { return $this->get_toc_header_css( $attributes, $device ); } )
90 + );
91 + $css_generator->add_class_styles(
92 + '{{WRAPPER}} .ablocks-toc-body',
93 + $this->get_toc_body_css( $attributes ),
94 + $this->get_toc_body_css( $attributes, 'Tablet' ),
95 + $this->get_toc_body_css( $attributes, 'Mobile' ),
96 + $css_generator->custom_device_map( function ( $device ) use ( $attributes ) { return $this->get_toc_body_css( $attributes, $device ); } )
97 + );
98 + $css_generator->add_class_styles(
99 + '{{WRAPPER}} .ablocks-toc__header-toggle-icon .ablocks-toc__show',
100 + $this->get_toc_header_icon_css( $attributes ),
101 + $this->get_toc_header_icon_css( $attributes, 'Tablet' ),
102 + $this->get_toc_header_icon_css( $attributes, 'Mobile' ),
103 + $css_generator->custom_device_map( function ( $device ) use ( $attributes ) { return $this->get_toc_header_icon_css( $attributes, $device ); } )
104 + );
105 + $css_generator->add_class_styles(
106 + '{{WRAPPER}} .ablocks-toc__header-toggle-icon .ablocks-toc__show:hover',
107 + $this->get_toc_header_icon_hover_css( $attributes ),
108 + $this->get_toc_header_icon_hover_css( $attributes, 'Tablet' ),
109 + $this->get_toc_header_icon_hover_css( $attributes, 'Mobile' ),
110 + $css_generator->custom_device_map( function ( $device ) use ( $attributes ) { return $this->get_toc_header_icon_hover_css( $attributes, $device ); } )
111 + );
112 + $css_generator->add_class_styles(
113 + '{{WRAPPER}} .ablocks-toc-body .ablocks-toc-list',
114 + $this->get_marker_list_style_css( $attributes ),
115 + $this->get_marker_list_style_css( $attributes, 'Tablet' ),
116 + $this->get_marker_list_style_css( $attributes, 'Mobile' ),
117 + $css_generator->custom_device_map( function ( $device ) use ( $attributes ) { return $this->get_marker_list_style_css( $attributes, $device ); } )
118 + );
119 + $css_generator->add_class_styles(
120 + '{{WRAPPER}} .ablocks-toc-list,
121 + {{WRAPPER}} .ablocks-toc-list li a',
122 + $this->get_list_item_css( $attributes ),
123 + $this->get_list_item_css( $attributes, 'Tablet' ),
124 + $this->get_list_item_css( $attributes, 'Mobile' ),
125 + $css_generator->custom_device_map( function ( $device ) use ( $attributes ) { return $this->get_list_item_css( $attributes, $device ); } )
126 + );
127 + $css_generator->add_class_styles(
128 + '{{WRAPPER}} .ablocks-toc-body .ablocks-toc-list li a',
129 + $this->get_list_item_gap_css( $attributes ),
130 + $this->get_list_item_gap_css( $attributes, 'Tablet' ),
131 + $this->get_list_item_gap_css( $attributes, 'Mobile' ),
132 + $css_generator->custom_device_map( function ( $device ) use ( $attributes ) { return $this->get_list_item_gap_css( $attributes, $device ); } )
133 + );
134 + $css_generator->add_class_styles(
135 + '{{WRAPPER}} a.ablocks-toc-item-link.active',
136 + $this->get_active_list_item_css( $attributes ),
137 + $this->get_active_list_item_css( $attributes, 'Tablet' ),
138 + $this->get_active_list_item_css( $attributes, 'Mobile' ),
139 + $css_generator->custom_device_map( function ( $device ) use ( $attributes ) { return $this->get_active_list_item_css( $attributes, $device ); } )
140 + );
60 141
142 + return $css_generator->generate_css();
143 + }
61 144
145 + public function build_css( $attributes ) {
146 + if ( isset( $attributes['blockVersion'] ) && (int) $attributes['blockVersion'] === 2 ) {
147 + return $this->build_css_v2( $attributes );
148 + }
149 + return $this->build_css_v1( $attributes );
150 + }
151 +
152 +
62 153 public function get_toc_title_css( $attributes, $device = '' ) {
63 - $css = array();
64 - $toc_title_typography_css = ! empty( $attributes['titleTypography'] ) ? Typography::get_css( $attributes['titleTypography'], '', $device ) : array();
65 - if ( isset( $attributes['titleColor'] ) ) {
66 - $css['color'] = $attributes['titleColor'];
67 - }
68 - return array_merge( $toc_title_typography_css, $css );
154 + $typographyValueGlobal = ! empty( $attributes['titleTypographyGlobal'] ) ? $attributes['titleTypographyGlobal'] : array();
155 + $toc_title_typography_css = ! empty( $attributes['titleTypography'] ) ? Typography::get_css( $attributes['titleTypography'], '', $device, $typographyValueGlobal ) : array();
156 + return array_merge( $toc_title_typography_css,
157 + [ 'color' => Color::get_css( isset( $attributes['titleColor'] ) ? $attributes['titleColor'] : '' ) ], );
69 158 }
70 159 public function get_toc_header_css( $attributes, $device = '' ) {
71 - $css = array();
72 160 $headerorder = ! empty( $attributes['headerBorder'] ) ? Border::get_css( $attributes['headerBorder'], '', $device ) : array();
73 161 $header_padding_css = ! empty( $attributes['header_padding'] ) ? Dimensions::get_css( $attributes['header_padding'], 'padding', $device ) : array();
74 - if ( isset( $attributes['headerBG'] ) ) {
75 - $css['background'] = $attributes['headerBG'];
76 - }
77 - return array_merge( $css, $headerorder, $header_padding_css );
162 + return array_merge(
163 + [ 'background' => Color::get_css( isset( $attributes['headerBG'] ) ? $attributes['headerBG'] : '' ) ],
164 + $headerorder, $header_padding_css );
78 165 }
79 166 public function get_toc_body_css( $attributes, $device = '' ) {
80 - $css = array();
81 167 $listing_padding_css = ! empty( $attributes['list_padding'] ) ? Dimensions::get_css( $attributes['list_padding'], 'padding', $device ) : array();
82 - if ( isset( $attributes['bodyBG'] ) ) {
83 - $css['background'] = $attributes['bodyBG'];
84 - }
85 - return array_merge( $listing_padding_css, $css );
168 + return array_merge(
169 + [ 'background' => Color::get_css( isset( $attributes['bodyBG'] ) ? $attributes['bodyBG'] : '' ) ],
170 + $listing_padding_css, );
86 171 }
87 172 public function get_toc_header_icon_css( $attributes, $device = '' ) {
88 173 $css = array_merge(
174 + [ 'fill' => Color::get_css( isset( $attributes['iconColor'] ) ? $attributes['iconColor'] : '' ) ],
89 175 Range::get_css([
90 - 'attributeValue' => $attributes['iconSize'],
176 + 'attributeValue' => $attributes['iconSize'] ?? null,
91 177 'isResponsive' => false,
92 178 'defaultValue' => 20,
93 179 'unitDefaultValue' => 'px',
94 - 'property' => 'width',
180 + 'property' => 'font-size',
95 181 'device' => $device,
96 182 ]),
97 - Range::get_css([
98 - 'attributeValue' => $attributes['iconSize'],
99 - 'isResponsive' => false,
100 - 'defaultValue' => 20,
101 - 'unitDefaultValue' => 'px',
102 - 'property' => 'height',
103 - 'device' => $device,
104 - ]),
183 + Dimensions::get_css( $attributes['icon_padding'] ?? [], 'padding', $device ),
184 + Border::get_css( $attributes['iconBorder'] ?? [], '', $device ),
185 + BoxShadow::get_css( $attributes['iconBoxShadow'] ?? [], $device ),
105 186 );
106 - if ( ! empty( $attributes['iconSize'] ) ) {
107 - $css['width'] = $attributes['iconSize'] . 'px';
108 - $css['height'] = $attributes['iconSize'] . 'px';
109 - }
110 - if ( isset( $attributes['iconColor'] ) ) {
111 - $css['fill'] = $attributes['iconColor'];
112 - }
113 187 return $css;
114 188 }
115 189
190 + public function get_toc_header_icon_hover_css( $attributes, $device = '' ) {
191 + $css = array_merge(
192 + Border::get_hover_css( $attributes['iconBorder'], $device ),
193 + BoxShadow::get_hover_css( $attributes['iconBoxShadow'], $device )
194 + );
195 + return $css;
196 + }
197 +
116 198 public function get_list_item_css( $attributes, $device = '' ) {
117 - $css = array();
199 + $typographyValueGlobal = ! empty( $attributes['contentTypographyGlobal'] ) ? $attributes['contentTypographyGlobal'] : array();
200 + $contentTypography = ! empty( $attributes['contentTypography'] ) ? Typography::get_css( $attributes['contentTypography'], '', $device, $typographyValueGlobal ) : array();
201 + return array_merge(
202 + [ 'color' => Color::get_css( isset( $attributes['itemColor'] ) ? $attributes['itemColor'] : '' ) ],
203 + $contentTypography,
204 + );
205 + }
118 206
119 - $contentTypography = ! empty( $attributes['contentTypography'] ) ? Typography::get_css( $attributes['contentTypography'], '', $device ) : array();
120 -
121 - if ( ! empty( $attributes['itemColor'] ) ) {
122 - $css['color'] = $attributes['itemColor'];
123 - }
207 + public function get_list_item_gap_css( $attributes, $device = '' ) {
124 208 return array_merge(
125 209 Range::get_css([
126 210 'attributeValue' => $attributes['listItemGap'],
127 211 'attribute_object_key' => 'value',
@@ -131,16 +215,36 @@
131 215 'property' => 'line-height',
132 216 'hasUnit' => true,
133 217 'device' => $device,
134 218 ]),
135 - $contentTypography,
136 - $css,
137 219 );
138 220 }
221 + public function get_active_list_item_css( $attributes, $device = '' ) {
222 + return array_merge(
223 + [ 'color' => Color::get_css( isset( $attributes['activeColor'] ) ? $attributes['activeColor'] : '' ) ],
224 + );
225 + }
139 226
140 227
228 + public function get_marker_list_style_css( $attributes ) {
229 + $css = [];
230 + $allowed_list_types = [
231 + 'decimal',
232 + 'disc',
233 + 'circle',
234 + 'square',
235 + 'lower-alpha',
236 + 'lower-roman',
237 + 'none'
238 + ];
239 + if ( ! empty( $attributes['markerView'] ) && in_array( $attributes['markerView'], $allowed_list_types, true ) ) {
240 + $css['list-style-type'] = $attributes['markerView'];
241 + }
242 + return $css;
243 + }
141 244
142 245
246 +
143 247 public function add_toc_to_post_content( $content ) {
144 248
145 249 $content = preg_replace_callback('/<h([1-6])(.*?)>(.*?)<\/h\1>/i', function ( $matches ) {
146 250 $level = $matches[1]; // Heading level (1-6)
@@ -169,9 +273,9 @@
169 273 // Sanitize and escape icon attributes
170 274 $open_icon_attributes = array(
171 275 'path' => esc_attr( $attributes['openIconSvgPath'] ),
172 276 'viewBox' => esc_attr( $attributes['openIconSvgViewBox'] ),
173 - 'className' => esc_attr( $attributes['openIconClass'] ),
277 + 'className' => sanitize_text_field( $attributes['openIconClass'] ),
174 278 'width' => '20',
175 279 'height' => '20',
176 280 );
177 281 $close_icon_attributes = array(
@@ -176,9 +280,9 @@
176 280 );
177 281 $close_icon_attributes = array(
178 282 'path' => esc_attr( $attributes['closeIconSvgPath'] ),
179 283 'viewBox' => esc_attr( $attributes['closeIconSvgViewBox'] ),
180 - 'className' => esc_attr( $attributes['closeIconClass'] ),
284 + 'className' => sanitize_text_field( $attributes['closeIconClass'] ),
181 285 'width' => '20',
182 286 'height' => '20',
183 287 );
184 288
@@ -185,21 +289,8 @@
185 289 $post_content = $post->post_content;
186 290 preg_match_all( '/<h([1-6])[^>]*>(.*?)<\/h\1>/', $post_content, $matches, PREG_SET_ORDER );
187 291 $toc = '';
188 292
189 - // Build TOC header
190 - if ( (bool) $attributes['hideTitle'] === true ) :
191 - $toc = '<div class="ablocks-toc__header">';
192 - $toc .= '<span class="ablocks-toc__header-title">' . esc_html( $attributes['tocTableTitle'] ) . '</span>';
193 - if ( $attributes['collapSible'] ) :
194 - $toc .= '<div class="ablocks-toc__header-toggle-icon">';
195 - $toc .= '<span class="ablocks-toc__show">' . Helper::render_svg_icon_using_attr( $close_icon_attributes ) . '</span>';
196 - $toc .= '<span class="ablocks-toc__hide">' . Helper::render_svg_icon_using_attr( $open_icon_attributes ) . '</span>';
197 - $toc .= '</div>';
198 - endif;
199 - $toc .= '</div>';
200 - endif;
201 -
202 293 $headings = [];
203 294 $unique_anchors = [];
204 295
205 296 // Process headings
@@ -204,30 +295,31 @@
204 295
205 296 // Process headings
206 297 foreach ( $matches as $match ) {
207 298 $level = intval( $match[1] );
208 - $heading = trim( $match[2] );
299 + $heading_html = trim( $match[2] );
300 + $heading = esc_html( wp_strip_all_tags( $heading_html ) );
301 +
209 302 $base_anchor = strtolower( sanitize_title( $heading ) );
210 303 $anchor = $base_anchor;
211 304 $count = 1;
212 305
213 - // Ensure unique anchors
214 306 while ( in_array( $anchor, $unique_anchors, true ) ) {
215 307 $anchor = $base_anchor . '-' . $count;
216 308 $count++;
217 309 }
218 310
219 - // Add heading if enabled in attributes
220 311 if ( (
221 - ( $level === 1 && $attributes['H1'] ) ||
222 - ( $level === 2 && $attributes['H2'] ) ||
223 - ( $level === 3 && $attributes['H3'] ) ||
224 - ( $level === 4 && $attributes['H4'] ) ||
225 - ( $level === 5 && $attributes['H5'] ) ||
226 - ( $level === 6 && $attributes['H6'] ) ) ) {
312 + ( $level === 1 && $attributes['H1'] ) ||
313 + ( $level === 2 && $attributes['H2'] ) ||
314 + ( $level === 3 && $attributes['H3'] ) ||
315 + ( $level === 4 && $attributes['H4'] ) ||
316 + ( $level === 5 && $attributes['H5'] ) ||
317 + ( $level === 6 && $attributes['H6'] ) ) ) {
318 +
227 319 $headings[] = [
228 320 'level' => $level,
229 - 'heading' => esc_html( $heading ),
321 + 'heading' => $heading,
230 322 'anchor' => esc_attr( $anchor ),
231 323 ];
232 324 $unique_anchors[] = $anchor;
233 325 }
@@ -232,11 +324,27 @@
232 324 $unique_anchors[] = $anchor;
233 325 }
234 326 }//end foreach
235 327
328 + $toc_list = $this->generate_toc_list( $attributes, $headings );
329 + $has_toc = $toc_list !== '';
330 +
331 + // Build TOC header
332 + if ( (bool) $attributes['hideTitle'] === true ) :
333 + $toc .= '<div class="ablocks-toc__header">';
334 + $toc .= $has_toc ? '<span class="ablocks-toc__header-title">' . esc_html( $attributes['tocTableTitle'] ) . '</span>' : '';
335 + if ( $attributes['collapSible'] ) :
336 + $toc .= '<div class="ablocks-toc__header-toggle-icon">';
337 + $toc .= '<span class="ablocks-toc__show">' . Helper::render_svg_icon_using_attr( $close_icon_attributes ) . '</span>';
338 + $toc .= '<span class="ablocks-toc__hide">' . Helper::render_svg_icon_using_attr( $open_icon_attributes ) . '</span>';
339 + $toc .= '</div>';
340 + endif;
341 + $toc .= '</div>';
342 + endif;
343 +
236 344 // Build TOC body
237 345 $toc .= '<div class="ablocks-toc-body">';
238 - $toc .= $this->generate_toc_list( $attributes, $headings );
346 + $toc .= $toc_list;
239 347 $toc .= '</div>';
240 348
241 349 return $toc;
242 350 }
@@ -246,12 +354,11 @@
246 354 return '';
247 355 }
248 356
249 357 $toc = '';
250 - $marker_view = in_array( $attributes['markerView'], [ 'ul', 'ol' ], true ) ? $attributes['markerView'] : 'ul';
358 + $marker_view = 'ol';
251 359 $current_level = 0;
252 360 $open_lists = [];
253 -
254 361 foreach ( $headings as $index => $heading ) {
255 362 if ( ! isset( $heading['level'], $heading['heading'], $heading['anchor'] ) ) {
256 363 continue;
257 364 }
@@ -294,14 +401,5 @@
294 401 }
295 402
296 403 return $toc;
297 404 }
298 -
299 -
300 -
301 -
302 -
303 -
304 -
305 -
306 -
307 405 }