PluginProbe
ShopBuilder – WooCommerce Builder For Elementor / 3.4.0
ShopBuilder – WooCommerce Builder For Elementor v3.4.0
3.4.2 3.4.1 3.4.0 2.0.1 2.0.2 2.0.3 2.1.0 2.1.1 2.1.10 2.1.11 2.1.12 2.1.13 2.1.14 2.1.15 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.1.9 2.2.0 2.2.1 2.2.2 All 63 releases
shopbuilder / app / Elementor / Render / GeneralAddons.php

GeneralAddons.php in ShopBuilder – WooCommerce Builder For Elementor 3.4.0, at app/Elementor/Render/GeneralAddons.php

687 lines 21.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Elementor GeneralAddons Class.
4 *
5 * This class contains render logics & output for general addons.
6 *
7 * @package RadiusTheme\SB
8 */
9
10 namespace RadiusTheme\SB\Elementor\Render;
11
12 use RadiusTheme\SB\Elementor\Helper\RenderHelpers;
13 use RadiusTheme\SB\Helpers\Fns;
14
15 // Do not allow directly accessing this file.
16 if ( ! defined( 'ABSPATH' ) ) {
17 exit( 'This script cannot be accessed directly.' );
18 }
19
20 /**
21 * Elementor Render Class.
22 */
23 class GeneralAddons extends Render {
24 /**
25 * HTML.
26 *
27 * @var string
28 */
29 private $addon_html = null;
30
31 /**
32 * Element ID.
33 *
34 * @var string
35 */
36 private $id = null;
37
38 /**
39 * Unique name.
40 *
41 * @var string
42 */
43 public $unique_name = '';
44
45 /**
46 * Template name.
47 *
48 * @var string
49 */
50 public $template_name = '';
51
52 /**
53 * Settings.
54 *
55 * @var array
56 */
57 public $settings = [];
58
59 /**
60 * Carousel check.
61 *
62 * @var bool
63 */
64 public $is_carousel = false;
65
66 /**
67 * Blog Post check.
68 *
69 * @var bool
70 */
71 public $is_post_query = false;
72
73 /**
74 * Blog Post Pagination.
75 *
76 * @var bool
77 */
78 public $is_post_pagination = false;
79
80 /**
81 * Grid check.
82 *
83 * @var bool
84 */
85 public $is_grid = false;
86
87 /**
88 * Content classes.
89 *
90 * @var bool
91 */
92 public $content_classes = [
93 'rtsb-col-grid',
94 ];
95
96 /**
97 * Renders the addon view.
98 *
99 * @param array $data The addon data.
100 * @param array $settings The addon settings.
101 *
102 * @return string
103 */
104 public function addon_view( $data, $settings = [] ) {
105 $this->id = $data['id'];
106 $this->unique_name = $data['unique_name'];
107 $this->template_name = $data['template'];
108 $this->settings = $settings;
109 $this->is_carousel = $data['is_carousel'] ?? false;
110 $this->is_post_query = $data['is_post_query'] ?? false;
111 $this->is_grid = $data['is_grid'] ?? false;
112 $this->is_post_pagination = $data['is_post_pagination'] ?? false;
113 $content = $data['content'];
114
115 if ( ! ( $this->is_grid || empty( $data['content_class'] ) ) ) {
116 $this->content_classes[] = $data['content_class'];
117 $this->content_classes = implode( ' ', $this->content_classes );
118 }
119
120 // Container.
121 $this->addon_container( $content, $data );
122
123 return $this->addon_html;
124 }
125
126 /**
127 * Generates the container HTML.
128 *
129 * @param string $content The content inside the container.
130 * @param array $args Additional arguments for the container.
131 *
132 * @return string
133 */
134 public function addon_container( $content, $args = [] ) {
135 $container_id = 'rtsb-container-' . $this->id;
136 $container_classes = $this->get_container_classes( $args['container_class'] ?? '' );
137 $raw_layout = $args['layout'] ?? '';
138 $template = $args['template'];
139 $layout = RenderHelpers::filter_layout( $raw_layout, $template );
140 $style_attr = '--rtsb-default-columns: ' . esc_attr( RenderHelpers::default_columns( $layout ) );
141 $container_attributes = [
142 'id' => $container_id,
143 'class' => $container_classes,
144 'data-layout' => $layout,
145 ];
146 if ( $this->is_grid ) {
147 $container_attributes['style'] = apply_filters( 'rtsb/general_widget/container/attr', $style_attr, $this->settings );
148 }
149
150 if ( ! empty( $args['container_attr'] ) ) {
151 $container_attributes = array_merge( $container_attributes, $args['container_attr'] );
152 }
153
154 $row_args = wp_parse_args(
155 $this->get_row_args(),
156 [
157 'layout' => $raw_layout,
158 'template' => $template,
159 'content_class' => $args['content_class'] ?? '',
160 'post_query' => $args['post_query'] ?? '',
161 ]
162 );
163
164 // Adding render attributes.
165 $this->add_attribute( 'rtsb_addon_container_attr_' . $this->id, $container_attributes );
166
167 // Generate HTML for the container.
168 $this->addon_html = '<div ' . $this->get_attribute_string( 'rtsb_addon_container_attr_' . $this->id ) . '>';
169 $this->addon_row( $content, $row_args );
170 $this->addon_html .= '</div><!-- .rtsb-container -->';
171
172 return $this->addon_html;
173 }
174
175 /**
176 * Generates the row HTML.
177 *
178 * @param string $content The content inside the row.
179 * @param array $args Additional arguments for the row.
180 *
181 * @return string
182 */
183 public function addon_row( $content, $args = [] ) {
184 $layout = RenderHelpers::filter_layout( $args['layout'] ?? '' );
185 $row_classes = $this->get_row_classes( $layout );
186
187 // Adding render attributes.
188 $this->add_attribute( 'rtsb_addon_row_attr_' . $this->id, 'class', $row_classes );
189
190 // Start rendering the row.
191 $this->addon_html .= '<div ' . $this->get_attribute_string( 'rtsb_addon_row_attr_' . $this->id ) . '>';
192 if ( $this->is_carousel ) {
193 $this->slider_wrapper_start();
194 }
195
196 // Rendering the content.
197 $this->get_content( $content, $args );
198
199 if ( $this->is_carousel ) {
200 $this->slider_wrapper_end();
201 }
202 $this->addon_html .= '</div><!-- .rtsb-row -->';
203
204 if ( $this->is_post_query && $this->is_post_pagination && ! empty( $args['post_query'] ) ) {
205 $this->addon_html .= $this->render_posts_pagination( $args );
206 }
207 // Preloader.
208
209 $this->addon_html .= $this->pre_loader();
210
211 return $this->addon_html;
212 }
213
214 /**
215 * Renders the content inside the row.
216 *
217 * @param string $content The content.
218 * @param array $args Additional arguments for the content.
219 *
220 * @return void
221 */
222 protected function get_content( $content, $args = [] ) {
223 // Adding render attributes.
224 $this->add_attribute( 'rtsb_addon_content_attr_' . $this->id, 'class', $this->content_classes );
225
226 // Render content HTML.
227 $this->addon_html .= ! $this->is_grid ? '<div ' . $this->get_attribute_string( 'rtsb_addon_content_attr_' . $this->id ) . '>' : '';
228 $this->addon_html .= $content;
229 $this->addon_html .= ! $this->is_grid ? '</div><!-- .rtsb-col-grid -->' : '';
230 }
231
232 /**
233 * Gets container classes.
234 *
235 * @param string $custom Optional custom classes.
236 *
237 * @return string
238 */
239 protected function get_container_classes( $custom = '' ) {
240 $classes = [
241 'rtsb-elementor-container',
242 'rtsb-pos-r',
243 $this->unique_name,
244 ];
245
246 if ( ! empty( $custom ) ) {
247 $classes[] = $custom;
248 }
249 if ( ! empty( $this->settings['slider_slide_animation'] ) ) {
250 $classes[] = 'has-slide-animation';
251 }
252 $classes = implode( ' ', $classes );
253
254 return apply_filters( 'rtsb/general/addon_container/class', $classes, $this->settings );
255 }
256
257 /**
258 * Gets row classes.
259 *
260 * @param string $layout Optional layout name.
261 *
262 * @return string
263 */
264 protected function get_row_classes( $layout = '' ) {
265 $classes = [
266 'rtsb-row',
267 'rtsb-content-loader',
268 ];
269
270 if ( ! empty( $layout ) ) {
271 $classes[] = $layout;
272 }
273
274 if ( $this->is_carousel ) {
275 $classes[] = 'rtsb-slider-layout';
276 }
277 if ( $this->is_carousel && ! empty( $this->settings['always_show_nav'] ) ) {
278 $classes[] = 'always-show-nav';
279 }
280 if ( ! empty( $this->settings['cols_mobile'] ) && '1' == $this->settings['cols_mobile'] ) {
281 $classes[] = ' rtsb-mobile-flex-row';
282 }
283 $classes = implode( ' ', $classes );
284
285 return apply_filters( 'rtsb/general/addon_row/class', $classes, $this->settings );
286 }
287
288 /**
289 * Gets row arguments.
290 *
291 * @return array Row arguments.
292 */
293 protected function get_row_args() {
294 return [];
295 }
296
297 /**
298 * Starts the carousel slider wrapper.
299 *
300 * @return void
301 */
302 private function slider_wrapper_start() {
303 if ( 'rtsb-hero-slider' === $this->unique_name ) {
304 $slider_data = self::get_hero_slider_data( $this->settings );
305 } else {
306 $slider_data = $this->get_slider_data();
307 $slider_options = $slider_data['data'] ?? '';
308 $slider_classes = $slider_data['class'] ?? '';
309 $slider_data = [
310 'class' => 'rtsb-carousel-slider swiper ' . $slider_classes,
311 'data' => $slider_options,
312 ];
313 }
314
315 // Adding slider attributes.
316 $this->add_attribute(
317 'rtsb_slider_attr_' . $this->id,
318 [
319 'class' => 'rtsb-col-grid ' . $slider_data['class'],
320 'data-options' => $slider_data['data'],
321 ]
322 );
323
324 // Render slider wrapper.
325 $this->addon_html .= '<div ' . $this->get_attribute_string( 'rtsb_slider_attr_' . $this->id ) . '>';
326 $this->addon_html .= '<div class="swiper-wrapper">';
327 }
328
329 /**
330 * Ends the carousel slider wrapper.
331 *
332 * @return void
333 */
334 private function slider_wrapper_end() {
335 $this->addon_html .= '</div><!-- .swiper-wrapper -->';
336 $this->addon_html .= $this->slider_buttons( $this->settings );
337 $this->addon_html .= '</div><!-- .rtsb-carousel-slider -->';
338 }
339
340 /**
341 * Gets slider data for the carousel.
342 *
343 * @return array
344 */
345 protected function get_slider_data() {
346 $metas = $this->get_slider_meta_dataset( $this->settings, $this->template_name, $this->settings );
347
348 return RenderHelpers::slider_data( (array) $metas, $this->settings );
349 }
350
351 /**
352 * Prepares and returns slider configuration dataset for rendering in Elementor or frontend use.
353 *
354 * This method collects various slider-related metadata settings, normalizes them using helper
355 * functions, and returns a structured dataset used to initialize and render a responsive slider.
356 *
357 * @since 1.0.0
358 *
359 * @param array $meta Metadata array containing configuration values for the slider.
360 * Example keys: 'cols', 'cols_tablet', 'slider_loop', etc.
361 * @param string $template The template identifier or slug used for rendering slider content.
362 * @param array $raw_settings Raw settings passed directly from Elementor widget settings or similar source.
363 *
364 * @return array|null Returns an array of slider settings suitable for frontend use,
365 * optionally modified by the 'rtsb/elementor/render/slider_dataset_final' filter.
366 */
367 protected function get_slider_meta_dataset( array $meta, $template = '', $raw_settings = [] ) {
368 $data = [
369 'widget' => 'custom',
370 'widget_name' => $this->unique_name,
371 'template' => RenderHelpers::get_data( $template, '', '' ),
372 'raw_settings' => $raw_settings,
373 'd_cols' => RenderHelpers::get_data( $meta, 'cols', 0 ),
374 't_cols' => RenderHelpers::get_data( $meta, 'cols_tablet', 2 ),
375 'm_cols' => RenderHelpers::get_data( $meta, 'cols_mobile', 1 ),
376 'd_group' => RenderHelpers::get_data( $meta, 'cols_group', 1 ),
377 't_group' => RenderHelpers::get_data( $meta, 'cols_group_tablet', 1 ),
378 'm_group' => RenderHelpers::get_data( $meta, 'cols_group_mobile', 1 ),
379 'layout' => RenderHelpers::get_data( $meta, 'layout_style', 'layout1' ),
380 'auto_play' => ! empty( $meta['slide_autoplay'] ),
381 'stop_on_hover' => ! empty( $meta['pause_hover'] ),
382 'slider_nav' => ! empty( $meta['slider_nav'] ),
383 'slider_dot' => ! empty( $meta['slider_pagi'] ),
384 'slider_dynamic_dot' => ! empty( $meta['slider_dynamic_pagi'] ),
385 'loop' => ! empty( $meta['slider_loop'] ),
386 'lazy_load' => ! empty( $meta['slider_lazy_load'] ),
387 'auto_height' => ! empty( $meta['slider_auto_height'] ),
388 'speed' => RenderHelpers::get_data( $meta, 'slide_speed', 2000 ),
389 'space_between' => isset( $meta['grid_gap']['size'] ) && strlen( $meta['grid_gap']['size'] ) ? $meta['grid_gap']['size'] : 30,
390 'auto_play_timeout' => RenderHelpers::get_data( $meta, 'autoplay_timeout', 5000 ),
391 'nav_position' => RenderHelpers::get_data( $meta, 'slider_nav_position', 'standard' ),
392 'left_arrow_icon' => RenderHelpers::get_data( $meta, 'slider_left_arrow_icon', [] ),
393 'right_arrow_icon' => RenderHelpers::get_data( $meta, 'slider_right_arrow_icon', [] ),
394 ];
395 if ( ! empty( $meta['cols_widescreen'] ) ) {
396 $data['w_cols'] = $meta['cols_widescreen'];
397 }
398
399 if ( ! empty( $meta['cols_laptop'] ) ) {
400 $data['l_cols'] = $meta['cols_laptop'];
401 }
402
403 if ( ! empty( $meta['cols_tablet_extra'] ) ) {
404 $data['te_cols'] = $meta['cols_tablet_extra'];
405 }
406
407 if ( ! empty( $meta['cols_mobile_extra'] ) ) {
408 $data['me_cols'] = $meta['cols_mobile_extra'];
409 }
410
411 return apply_filters( 'rtsb/elementor/render/slider_dataset_final', $data, $meta, $raw_settings );
412 }
413
414 /**
415 * Generates the configuration and CSS class for the hero slider carousel.
416 *
417 * Prepares Swiper-compatible slider options and associated class names based on
418 * the provided metadata. This includes autoplay settings, pagination type,
419 * lazy loading, effects (e.g., parallax, fade), and responsive breakpoints.
420 *
421 * @since 1.0.0
422 *
423 * @param array $meta Metadata array for the slider settings, including keys like
424 * 'slide_speed', 'slider_loop', 'slider_pagi_type', etc.
425 *
426 * @return array Returns an associative array containing:
427 * - 'data' (string): JSON-encoded slider options for Swiper.
428 * - 'class' (string): Additional CSS class names for the carousel container.
429 */
430 protected function get_hero_slider_data( array $meta ) {
431 $has_dots = $meta['slider_pagi'] ? ' has-dot' : ' no-dot';
432 $has_dots .= $meta['slider_nav'] ? ' has-nav' : ' no-nav';
433 $has_dynamic_dots = $meta['slider_dynamic_pagi'] ? true : false;
434 $breakpoints = [
435 0 => [
436 'slidesPerView' => 1,
437 'slidesPerGroup' => 1,
438 'pagination' => [
439 'dynamicBullets' => $has_dynamic_dots,
440 'type' => RenderHelpers::get_data( $meta, 'slider_pagi_type', 'bullet' ),
441 ],
442 ],
443 768 => [
444 'slidesPerView' => 1,
445 'slidesPerGroup' => 1,
446 'pagination' => [
447 'dynamicBullets' => $has_dynamic_dots,
448 'type' => RenderHelpers::get_data( $meta, 'slider_pagi_type', 'bullet' ),
449 ],
450 ],
451 1025 => [
452 'slidesPerView' => 1,
453 'slidesPerGroup' => 1,
454 'pagination' => [
455 'dynamicBullets' => $has_dynamic_dots,
456 'type' => RenderHelpers::get_data( $meta, 'slider_pagi_type', 'bullet' ),
457 ],
458 ],
459 ];
460 $slider_options = [
461 'slidesPerView' => 1,
462 'slidesPerGroup' => 1,
463 'speed' => absint( RenderHelpers::get_data( $meta, 'slide_speed', 2000 ) ),
464 'loop' => ! empty( $meta['slider_loop'] ),
465 'autoHeight' => ! empty( $meta['slider_auto_height'] ),
466 'preloadImages' => ! empty( $meta['slider_lazy_load'] ),
467 'lazy' => ! empty( $meta['slider_lazy_load'] ),
468 'breakpoints' => $breakpoints,
469 ];
470 if ( $meta['slide_autoplay'] ) {
471 $slider_options['autoplay'] = [
472 'delay' => absint( RenderHelpers::get_data( $meta, 'autoplay_timeout', 5000 ) ),
473 'pauseOnMouseEnter' => ! empty( $meta['pause_hover'] ),
474 'disableOnInteraction' => false,
475 ];
476 }
477 if ( 'fraction' === $meta['slider_pagi_type'] ) {
478 unset( $slider_options['pagination']['dynamicBullets'] );
479 }
480 if ( 'parallax' === $meta['slider_effect'] ) {
481 $slider_options['parallax'] = true;
482 } else {
483 $slider_options['effect'] = $meta['slider_effect'];
484 }
485 if ( 'fade' === $meta['slider_effect'] ) {
486 $slider_options['crossFade'] = true;
487 }
488
489 $slider_options = apply_filters( 'rtsb/elementor/render/hero_slider_dataset', $slider_options, $this->settings );
490 $carouselClass = 'rtsb-hero-carousel-slider slider-loading rtsb-pos-s ' . $has_dots;
491 return [
492 'data' => esc_js( wp_json_encode( $slider_options ) ),
493 'class' => $carouselClass,
494 ];
495 }
496
497
498 /**
499 * Renders the carousel slider navigation arrows and pagination markup.
500 *
501 * This method returns HTML for Swiper navigation buttons (left/right arrows)
502 * and optional pagination dots, depending on the provided slider settings.
503 *
504 * @since 1.0.0
505 *
506 * @param array $settings Slider configuration options. Expected keys:
507 * - 'slider_left_arrow_icon' (string) Icon for the left arrow.
508 * - 'slider_right_arrow_icon' (string) Icon for the right arrow.
509 * - 'slider_nav' (bool) Whether to show navigation arrows.
510 * - 'slider_pagi' (bool) Whether to show pagination.
511 * - 'slider_pagi_type' (string) (Optional) Pagination style (e.g., 'bullets', 'fraction').
512 *
513 * @return string HTML markup for the slider navigation and pagination.
514 */
515 protected function slider_buttons( $settings ) {
516 $html = '';
517 $pagination_type = '';
518 $left_icon = $settings['slider_left_arrow_icon'] ?? '';
519 $right_icon = $settings['slider_right_arrow_icon'] ?? '';
520 $is_hero_carousel = 'rtsb-hero-slider' === $this->unique_name;
521 if ( $is_hero_carousel && ! empty( $settings['slider_pagi_type'] ) ) {
522 $pagination_type = $settings['slider_pagi_type'];
523 }
524 if ( ! empty( $settings['slider_nav'] ) ) {
525 $html .=
526 '<div class="swiper-nav">
527 <div class="swiper-arrow swiper-button-next">
528 ' . Fns::icons_manager( $right_icon ) . '
529 </div>
530 <div class="swiper-arrow swiper-button-prev">
531 ' . Fns::icons_manager( $left_icon ) . '
532 </div>
533 </div>';
534 }
535
536 $html .= ! empty( $settings['slider_pagi'] ) ? '<div class="swiper-pagination rtsb-pos-s ' . esc_attr( $pagination_type ) . '"></div>' : '';
537
538 /**
539 * Filters the slider navigation + pagination markup.
540 *
541 * @param string $html Slider buttons (arrows + pagination) HTML.
542 * @param array $settings Widget settings.
543 * @param GeneralAddons $instance Current render instance (exposes unique_name, id, etc.).
544 */
545 return apply_filters( 'rtsb/general/slider_buttons/html', $html, $settings, $this );
546 }
547 /**
548 * Preloader.
549 *
550 * @return string
551 */
552 public function pre_loader() {
553 if ( ! Fns::enable_loader() ) {
554 return '';
555 }
556 if ( $this->is_carousel ) {
557 return '<div class="rtsb-elements-loading rtsb-ball-clip-rotate"><div></div></div>';
558 }
559 return '';
560 }
561 /**
562 * No posts message.
563 *
564 * @return string
565 */
566 public function no_posts_msg() {
567 return '<div class="rtsb-notice">
568 <div class="woocommerce-info">' . esc_html__( 'No posts were found matching your selection.', 'shopbuilder' ) . '</div>
569 </div>';
570 }
571 /**
572 * Renders posts pagination
573 *
574 * @param array $args Pagination args.
575 *
576 * @return string
577 */
578 public function render_posts_pagination( $args ) {
579 list(
580 'post_query' => $query,
581 'posts_limit' => $limit,
582 'posts_per_page' => $per_page
583 ) = $args;
584 $html_utility = null;
585 $html = null;
586 $posts_per_page = $query->query_vars['posts_per_page'];
587 $found_posts = $query->found_posts;
588 $total_page = $query->max_num_pages;
589 if ( $limit ) {
590 if ( ( empty( $wp_query->query['tax_query'] ) ) ) {
591 $found_posts = $query->found_posts;
592 }
593
594 if ( $per_page && $found_posts > $per_page ) {
595 $found_posts = $limit;
596 $total_page = ceil( $found_posts / $per_page );
597 }
598 }
599
600 $total_page = absint( $total_page );
601
602 $html_utility .= Fns::custom_pagination(
603 $total_page,
604 $posts_per_page
605 );
606
607 if ( $html_utility ) {
608 $rand = wp_rand();
609
610 // Adding pagination render attributes.
611 $this->add_attribute(
612 'rtsb_pagination_attr_' . $rand,
613 [
614 'class' => 'rtsb-pagination-wrap element-loading',
615 'data-total-pages' => $total_page,
616 'data-posts-per-page' => $posts_per_page,
617 'data-type' => 'pagination',
618 ]
619 );
620
621 // Start rendering.
622 $html = '<div ' . $this->get_attribute_string( 'rtsb_pagination_attr_' . $rand ) . '>';
623 $html .= $html_utility;
624 $html .= '</div><!-- .rtsb-pagination-wrap -->';
625 }
626
627 return $html;
628 }
629
630 /**
631 * Function to render buttom html.
632 *
633 * @param array $args Button Arguments.
634 *
635 * @return void
636 */
637 public static function render_buttom_html( $args ) {
638 $default_args = [
639 'button_attributes' => '',
640 'sb_button_icon' => '',
641 'sb_button_icon_position' => 'right',
642 'sb_button_content' => esc_html__( 'ShopBuilder Button', 'shopbuilder' ),
643 ];
644 $args = wp_parse_args( $args, $default_args );
645 ?>
646 <a <?php Fns::print_html( $args['button_attributes'] ); ?>>
647 <span class="text-wrap <?php echo esc_attr( 'icon-' . $args['sb_button_icon_position'] ); ?>">
648 <?php
649 Fns::print_html( self::render_button_icon( 'left', $args['sb_button_icon'], $args['sb_button_icon_position'] ) );
650 Fns::print_html( '<span class="text">' );
651 Fns::print_html( $args['sb_button_content'] );
652 Fns::print_html( '</span>' );
653 Fns::print_html( '<span class="hover-text">' );
654 Fns::print_html( $args['sb_button_content'] );
655 Fns::print_html( '</span>' );
656 Fns::print_html( self::render_button_icon( 'right', $args['sb_button_icon'], $args['sb_button_icon_position'] ) );
657 ?>
658 </span>
659 </a>
660 <?php
661 }
662 /**
663 * Renders an icon HTML markup based on position match.
664 *
665 * Compares the desired icon position with the configured position
666 * and renders the icon HTML if they match.
667 *
668 * @since 1.0.0
669 *
670 * @param string $position Desired position to render the icon ('left' or 'right').
671 * @param string $icon Icon identifier or SVG markup.
672 * @param string $icon_position Actual position set in the settings ('left' or 'right').
673 *
674 * @return string Icon HTML if position matches; otherwise, an empty string.
675 */
676 public static function render_button_icon( $position, $icon, $icon_position ) {
677 $html = '';
678
679 // Render the left icon.
680 if ( $position === $icon_position ) {
681 $html .= '<span class="icon">' . Fns::icons_manager( $icon ) . '</span>';
682 }
683
684 return $html;
685 }
686 }
687