PluginProbe
ShopBuilder – WooCommerce Builder For Elementor / 1.0.0
ShopBuilder – WooCommerce Builder For Elementor v1.0.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
← All changes | app/Helpers/Fns.php +1970 -2990 2.2.2 → 1.0.0 View file →
@@ -1,2990 +1,1970 @@
1 -<?php
2 -/**
3 - * Fns Helpers class
4 - *
5 - * @package RadiusTheme\SB
6 - */
7 -
8 -namespace RadiusTheme\SB\Helpers;
9 -
10 -// Do not allow directly accessing this file.
11 -if ( ! defined( 'ABSPATH' ) ) {
12 - exit( 'This script cannot be accessed directly.' );
13 -}
14 -
15 -use WC_Product;
16 -use WC_Product_Query;
17 -use Elementor\Icons_Manager;
18 -use RadiusTheme\SB\Models\ReSizer;
19 -use RadiusTheme\SB\Models\DataModel;
20 -use RadiusTheme\SB\Models\ModuleList;
21 -use RadiusTheme\SB\Models\Settings;
22 -
23 -/**
24 - * Fns class
25 - */
26 -class Fns {
27 -
28 - /**
29 - * @var array
30 - */
31 - private static $cache = [];
32 -
33 - /**
34 - * Verify nonce.
35 - *
36 - * @return bool
37 - */
38 - public static function verify_nonce() {
39 - $nonce = isset( $_REQUEST[ rtsb()->nonceId ] ) ? sanitize_text_field( wp_unslash( $_REQUEST[ rtsb()->nonceId ] ) ) : null;
40 - $nonceText = rtsb()->nonceText;
41 - if ( wp_verify_nonce( $nonce, $nonceText ) ) {
42 - return true;
43 - }
44 -
45 - return false;
46 - }
47 -
48 - public static function get_nonce() {
49 - // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
50 - return isset( $_REQUEST[ rtsb()->nonceId ] ) ? sanitize_text_field( $_REQUEST[ rtsb()->nonceId ] ) : null;
51 - }
52 -
53 -
54 - /**
55 - * Set Cookie or Session
56 - *
57 - * @param $name
58 - * @param $value
59 - */
60 - public static function setSession( $name, $value ) {
61 - if ( ! headers_sent() && session_status() == PHP_SESSION_NONE ) {
62 - session_start();
63 - $_SESSION[ $name ] = $value;
64 - } else {
65 - $_SESSION[ $name ] = $value;
66 - }
67 - }
68 - /**
69 - * Get Cookie or Session
70 - *
71 - * @param $name
72 - *
73 - * @return bool
74 - */
75 - public static function getSession( $name ) {
76 - if ( ! headers_sent() && session_status() == PHP_SESSION_NONE ) {
77 - session_start();
78 - }
79 - return $_SESSION[ $name ] ?? null; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
80 - }
81 - /**
82 - * Remove Session Variable
83 - *
84 - * @param string $name The name of the session variable to remove.
85 - */
86 - public static function removeSession( $name ) {
87 - if ( ! headers_sent() && session_status() == PHP_SESSION_NONE ) {
88 - session_start();
89 - unset( $_SESSION[ $name ] );
90 - } else {
91 - unset( $_SESSION[ $name ] );
92 - }
93 - }
94 -
95 - /**
96 - * @param $plugin_slug
97 - *
98 - * @return bool
99 - */
100 - public static function check_plugin_installed( $plugin_slug ): bool {
101 - $installed_plugins = get_plugins();
102 -
103 - return array_key_exists( $plugin_slug, $installed_plugins ) || in_array( $plugin_slug, $installed_plugins, true );
104 - }
105 -
106 - /**
107 - * @param $plugin_slug
108 - *
109 - * @return bool
110 - */
111 - public static function check_plugin_active( $plugin_slug ): bool {
112 - if ( is_plugin_active( $plugin_slug ) ) {
113 - return true;
114 - }
115 -
116 - return false;
117 - }
118 -
119 - /**
120 - * @param $data
121 - *
122 - * @return mixed|string
123 - */
124 - public static function stripslashes_value( $data ) {
125 - if ( is_string( $data ) && strpos( $data, '\\' ) !== false ) {
126 - return stripslashes( $data );
127 - } elseif ( is_array( $data ) ) {
128 - foreach ( $data as $key => $value ) {
129 - $data[ $key ] = self::stripslashes_value( $value );
130 - }
131 - }
132 -
133 - return $data;
134 - }
135 -
136 - /**
137 - * @param $string
138 - *
139 - * @return array
140 - */
141 - public static function multiselect_settings_field_value( $string ) {
142 -
143 - $values = [];
144 - if ( empty( $string ) ) {
145 - return $values;
146 - }
147 -
148 - $stripslashes_data = self::stripslashes_value( $string );
149 - if ( is_array( $stripslashes_data ) && count( $stripslashes_data ) ) {
150 - foreach ( $stripslashes_data as $item ) {
151 - $item = is_array( $item ) ? $item : json_decode( $item, true );
152 - $values[] = $item['value'];
153 - }
154 - }
155 -
156 - return $values;
157 - }
158 -
159 - /**
160 - * @return bool
161 - */
162 - public static function check_is_block_theme(): bool {
163 - global $wp_version;
164 -
165 - return version_compare( $wp_version, '5.9', '>=' ) && function_exists( 'wp_is_block_theme' ) && wp_is_block_theme();
166 - }
167 -
168 - /**
169 - * @param string $template_name Template name.
170 - * @param string $template_path Template path. (default: '').
171 - * @param string $plugin_path Plugin path. (default: ''). fallback file from plugin.
172 - *
173 - * @return mixed|void
174 - */
175 - public static function locate_template( $template_name, $template_path = '', $plugin_path = '' ) {
176 - $template_name = self::sanitize_file_name( $template_name ) . '.php';
177 -
178 - if ( ! $template_path ) {
179 - $template_path = rtsb()->get_template_path();
180 - }
181 - if ( ! $plugin_path ) {
182 - $plugin_path = RTSB_ABSPATH . 'templates/';
183 - }
184 -
185 - $template_rtsb_path = trailingslashit( $template_path ) . $template_name;
186 - $template_path = '/' . $template_name;
187 - $plugin_path = $plugin_path . $template_name;
188 - $pro_plugin_path = rtsb()->has_pro() ? RTSBPRO_PATH . 'templates/' . $template_name : '';
189 -
190 - $located = locate_template(
191 - apply_filters(
192 - 'rtsb/core/locate_template_files',
193 - [
194 - $template_rtsb_path, // Search in <theme>/shopbuilder/.
195 - $template_path, // Search in <theme>/.
196 - ]
197 - )
198 - );
199 -
200 - if ( ! $located ) {
201 - if ( file_exists( $plugin_path ) ) {
202 - return apply_filters( 'rtsb/core/locate_template', $plugin_path, $template_name );
203 - } elseif ( $pro_plugin_path && rtsb()->has_pro() && file_exists( $pro_plugin_path ) ) {
204 - return apply_filters( 'rtsb/core/locate_template', $pro_plugin_path, $template_name );
205 - }
206 - }
207 -
208 - /**
209 - * APPLY_FILTERS: rtsb/core/locate_template
210 - *
211 - * Filter the location of the templates.
212 - *
213 - * @param string $located Template found
214 - * @param string $path Template path
215 - *
216 - * @return string
217 - */
218 - return apply_filters( 'rtsb/core/locate_template', $located, $template_name );
219 - }
220 -
221 - /**
222 - * Remove any character that is not alphanumeric, /, _, or -.
223 - *
224 - * @param string $name Name to sanitize.
225 - *
226 - * @return array|string|string[]|null
227 - */
228 - private static function sanitize_file_name( $name ) {
229 - return preg_replace( '/[^a-zA-Z0-9\/_\-]/', '', $name );
230 - }
231 -
232 - /**
233 - * Template Content
234 - *
235 - * @param string $template_name Template name.
236 - * @param array $args Arguments. (default: array).
237 - * @param bool $return Whether to return or print the template.
238 - * @param string $template_path Template path. (default: '').
239 - * @param string $plugin_path Fallback path from where file will load if fail to load from template. (default: '').
240 - *
241 - * @return false|string|void
242 - */
243 - public static function load_template( $template_name, array $args = null, $return = false, $template_path = '', $plugin_path = '' ) {
244 - $cache_key = sanitize_key( implode( '-', [ 'template', $template_name, $template_path ] ) );
245 - $located = (string) wp_cache_get( $cache_key, 'shopbuilder' );
246 - if ( ! $located ) {
247 - $located = self::locate_template( $template_name, $template_path, $plugin_path );
248 - // Don't cache the absolute path so that it can be shared between web servers with different paths.
249 - $cache_path = wc_tokenize_path( $located, wc_get_path_define_tokens() );
250 - Cache::set_template_cache( $cache_key, $cache_path );
251 - } else {
252 - // Make sure that the absolute path to the template is resolved.
253 - $located = wc_untokenize_path( $located, wc_get_path_define_tokens() );
254 - }
255 - if ( ! file_exists( $located ) ) {
256 - // translators: %s template.
257 - self::doing_it_wrong( __FUNCTION__, sprintf( __( '%s does not exist.', 'shopbuilder' ), '<code>' . $located . '</code>' ), '1.0' );
258 -
259 - return;
260 - }
261 -
262 - if ( ! empty( $args ) && is_array( $args ) ) {
263 - $atts = $args;
264 - extract( $args ); // @codingStandardsIgnoreLine
265 - }
266 -
267 - // Allow 3rd party plugin filter template file from their plugin.
268 - $located = apply_filters( 'rtsb/core/get_template', $located, $template_name, $args );
269 -
270 - if ( $return ) {
271 - ob_start();
272 - }
273 -
274 - do_action( 'rtsb/core/before_template_part', $template_name, $located, $args );
275 - include $located;
276 -
277 - do_action( 'rtsb/core/after_template_part', $template_name, $located, $args );
278 -
279 - if ( $return ) {
280 - return ob_get_clean();
281 - }
282 - }
283 -
284 - /**
285 - * Verify nonce.
286 - *
287 - * @return string
288 - */
289 - public static function is_woocommerce() {
290 - return is_woocommerce() || is_cart() || is_checkout() || is_account_page();
291 - }
292 -
293 - /**
294 - * Page builder
295 - *
296 - * @param int $post_id post id.
297 - *
298 - * @return string
299 - */
300 - public static function page_edit_with( $post_id ) {
301 - if ( ! $post_id ) {
302 - return '';
303 - }
304 -
305 - $edit_with = get_post_meta( $post_id, '_elementor_edit_mode', true );
306 -
307 - if ( 'builder' === $edit_with ) {
308 - $edit_by = 'elementor';
309 - } else {
310 - $edit_by = 'gutenberg';
311 - }
312 -
313 - return $edit_by;
314 - }
315 -
316 - /**
317 - * Returns default expiration for wishlist cookie
318 - *
319 - * @return int Number of seconds the cookie should last.
320 - */
321 - public static function get_cookie_expiration() {
322 - return intval( apply_filters( 'rtsb/cookie_expiration', 60 * 60 * 24 * 30 ) );
323 - }
324 -
325 - /**
326 - * Create a cookie.
327 - *
328 - * @param string $name Cookie name.
329 - * @param mixed $value Cookie value.
330 - * @param int $time Cookie expiration time.
331 - * @param bool $secure Whether cookie should be available to secured connection only.
332 - * @param bool $httponly Whether cookie should be available to HTTP request only (no js handling).
333 - *
334 - * @return bool
335 - * @since 1.0.0
336 - */
337 - public static function setcookie( $name, $value = [], $time = null, $secure = false, $httponly = false ) {
338 -
339 - if ( ! apply_filters( 'rtsb/set_cookie', true ) || empty( $name ) ) {
340 - return false;
341 - }
342 -
343 - $time = ! empty( $time ) ? $time : time() + self::get_cookie_expiration();
344 -
345 - $value = wp_json_encode( stripslashes_deep( $value ) );
346 - $expiration = apply_filters( 'rtsb/cookie_expiration_time', $time ); // Default 30 days.
347 -
348 - $_COOKIE[ $name ] = $value;
349 - wc_setcookie( $name, $value, $expiration, $secure, $httponly );
350 -
351 - return true;
352 - }
353 -
354 - /**
355 - * Retrieve the value of a cookie.
356 - *
357 - * @param string $name Cookie name.
358 - *
359 - * @return mixed
360 - * @since 1.0.0
361 - */
362 - public static function getcookie( $name ) {
363 - if ( isset( $_COOKIE[ $name ] ) ) {
364 - return json_decode( sanitize_text_field( wp_unslash( $_COOKIE[ $name ] ) ), true );
365 - }
366 -
367 - return [];
368 - }
369 -
370 - /**
371 - * Woocommerce Last product id return
372 - */
373 - public static function get_prepared_product_id() {
374 - if ( is_singular( 'product' ) ) {
375 - return get_the_ID();
376 - }
377 - // Return the Builder Template id.
378 -
379 - if ( get_post_type( get_the_ID() ) == BuilderFns::$post_type_tb ) {
380 - $product_id = get_post_meta( get_the_ID(), BuilderFns::$product_template_meta, true );
381 - if ( $product_id && get_post_status( $product_id ) ) {
382 - return $product_id;
383 - }
384 - }
385 -
386 - global $wpdb;
387 - $cache_key = 'rtsb_prepared_product_id';
388 - $_post_id = wp_cache_get( $cache_key, 'shopbuilder' );
389 - if ( false === $_post_id || 'publish' !== get_post_status( $_post_id ) ) {
390 - // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
391 - $_post_id = $wpdb->get_var(
392 - $wpdb->prepare( "SELECT MAX(ID) FROM {$wpdb->prefix}posts WHERE post_type = %s AND post_status IN('publish', 'draft')", 'product' )
393 - );
394 - wp_cache_set( $cache_key, $_post_id, 'shopbuilder', 12 * HOUR_IN_SECONDS );
395 - Cache::set_data_cache_key( $cache_key );
396 - }
397 -
398 - return $_post_id;
399 - }
400 -
401 - /**
402 - * Get the product function. Only used in single page widgets.
403 - *
404 - * @return object
405 - */
406 - public static function get_product() {
407 - global $product;
408 -
409 - if ( is_singular( 'product' ) && $product instanceof WC_Product ) {
410 - // do_action( 'rtsb_before_product_template_render' );.
411 - return $product;
412 - }
413 - $cache_key = 'prepared_product_for_preview';
414 - if ( isset( self::$cache[ $cache_key ] ) ) {
415 - return self::$cache[ $cache_key ];
416 - }
417 - $product = wc_get_product( self::get_prepared_product_id() );
418 - self::$cache[ $cache_key ] = $product;
419 - do_action( 'rtsb_before_product_template_render' );
420 - return $product;
421 - }
422 -
423 - /**
424 - * Error function
425 - *
426 - * @param [type] $function function name.
427 - * @param [type] $message message.
428 - * @param [type] $version version.
429 - *
430 - * @return void
431 - */
432 - public static function doing_it_wrong( $function, $message, $version ) {
433 - $message .= ' Backtrace: ' . wp_debug_backtrace_summary();
434 - _doing_it_wrong( esc_html( $function ), wp_kses_post( $message ), esc_html( $version ) );
435 - }
436 -
437 - /**
438 - * @return array
439 - */
440 - public static function get_pages() {
441 - $pages = [];
442 - $rawPages = get_pages();
443 - if ( ! empty( $rawPages ) ) {
444 - foreach ( $rawPages as $page ) {
445 - $pages[ $page->ID ] = $page->post_title;
446 - }
447 - }
448 -
449 - return $pages;
450 - }
451 -
452 - public static function get_section_items( $section_id ) {
453 - if ( ! $section_id ) {
454 - return [];
455 - }
456 -
457 - return DataModel::source()->get_option( $section_id, [] );
458 - }
459 -
460 - public static function get_options( $section_id, $item_id ) {
461 - if ( ! $section_id || ! $item_id ) {
462 - return [];
463 - }
464 - $sections = self::get_section_items( $section_id );
465 -
466 - return isset( $sections[ $item_id ] ) ? $sections[ $item_id ] : [];
467 - }
468 -
469 - /**
470 - * Get options value with default value if options doesn't exist.
471 - *
472 - * @param $group
473 - * @param $option_key
474 - * @param $default_value
475 - *
476 - * @return mixed|string
477 - */
478 - public static function get_options_by_default_val( $group, $option_key, $default_value = '' ) {
479 -
480 - if ( ! $option_key || ! isset( $group[ $option_key ] ) ) {
481 - return $default_value;
482 - }
483 -
484 - return $group[ $option_key ];
485 - }
486 -
487 - /**
488 - * @param string $section_id
489 - * @param string $item_id
490 - * @param string $option_id
491 - * @param null $default EXCEPT multi_checkbox you can provide default value if given option does not set any value
492 - * @param null $type checkbox, multi_checkbox, number
493 - *
494 - * @return bool|int|mixed|null
495 - */
496 - public static function get_option( $section_id, $item_id, $option_id, $default = null, $type = null ) {
497 - $options = self::get_options( $section_id, $item_id );
498 -
499 - if ( $type === 'checkbox' ) {
500 - if ( isset( $options[ $option_id ] ) ) {
501 - return $options[ $option_id ] === 'on';
502 - }
503 -
504 - return $default;
505 - } elseif ( $type === 'multi_checkbox' ) {
506 - return isset( $options[ $option_id ] ) && is_array( $options[ $option_id ] ) && in_array( $default, $options[ $option_id ] );
507 - } elseif ( $type === 'number' ) {
508 - return isset( $options[ $option_id ] ) ? absint( $options[ $option_id ] ) : absint( $default );
509 - }
510 -
511 - return isset( $options[ $option_id ] ) && ! empty( $options[ $option_id ] ) ? $options[ $option_id ] : $default;
512 - }
513 -
514 -
515 - /**
516 - * Create a page and store the ID in an option.
517 - *
518 - * @param mixed $slug Slug for the new page.
519 - * @param array $options ['section_id', 'item_id', 'option_id']Option name to store the page's ID.
520 - * @param string $page_title (default: '') Title for the new page.
521 - * @param string $page_content (default: '') Content for the new page.
522 - * @param int $post_parent (default: 0) Parent for the new page.
523 - * @param string $post_status (default: publish) The post status of the new page.
524 - *
525 - * @return int page ID.
526 - */
527 - public static function create_page( $slug, $options = '', $page_title = '', $page_content = '', $post_parent = 0, $post_status = 'publish' ) {
528 - global $wpdb;
529 -
530 - $option_value = 0;
531 - if ( ! empty( $options ) ) {
532 - if ( is_array( $options ) ) {
533 - $options = wp_parse_args(
534 - $options,
535 - [
536 - 'section_id' => '',
537 - 'item_id' => '',
538 - 'option_id' => '',
539 - ]
540 - );
541 - $option_value = self::get_option( $options['section_id'], $options['item_id'], $options['option_id'], 0, 'number' );
542 - } else {
543 - $option_value = absint( get_option( $options ) );
544 - }
545 - }
546 -
547 - if ( $option_value > 0 ) {
548 - $page_object = get_post( $option_value );
549 -
550 - if ( $page_object && 'page' === $page_object->post_type && ! in_array(
551 - $page_object->post_status,
552 - [
553 - 'pending',
554 - 'trash',
555 - 'future',
556 - 'auto-draft',
557 - ],
558 - true
559 - ) ) {
560 - // Valid page is already in place.
561 - return $page_object->ID;
562 - }
563 - }
564 -
565 - if ( strlen( $page_content ) > 0 ) {
566 - // Search for an existing page with the specified page content (typically a shortcode).
567 - $shortcode = str_replace( [ '<!-- wp:shortcode -->', '<!-- /wp:shortcode -->' ], '', $page_content );
568 - // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
569 - $valid_page_found = $wpdb->get_var( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_type='page' AND post_status NOT IN ( 'pending', 'trash', 'future', 'auto-draft' ) AND post_content LIKE %s LIMIT 1;", "%{$shortcode}%" ) );
570 - } else {
571 - // Search for an existing page with the specified page slug.
572 - $valid_page_found = $wpdb->get_var( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_type='page' AND post_status NOT IN ( 'pending', 'trash', 'future', 'auto-draft' ) AND post_name = %s LIMIT 1;", $slug ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
573 - }
574 -
575 - $valid_page_found = apply_filters( 'rtsb/core/create_page_id', $valid_page_found, $slug, $page_content, $options );
576 -
577 - if ( $valid_page_found ) {
578 - if ( is_array( $options ) ) {
579 - if ( ! empty( $options['section_id'] ) && $options['item_id'] && $options['option_id'] ) {
580 - $section_items = DataModel::source()->get_option( $options['section_id'], [] );
581 - $section_items[ $options['item_id'] ][ $options['option_id'] ] = $valid_page_found;
582 - DataModel::source()->set_option( $options['section_id'], $section_items );
583 - }
584 - } else {
585 - if ( $options ) {
586 - update_option( $options, $valid_page_found );
587 - }
588 - }
589 -
590 - return $valid_page_found;
591 - }
592 -
593 - // Search for a matching valid trashed page.
594 - if ( strlen( $page_content ) > 0 ) {
595 - // Search for an existing page with the specified page content (typically a shortcode).
596 - $trashed_page_found = $wpdb->get_var( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_type='page' AND post_status = 'trash' AND post_content LIKE %s LIMIT 1;", "%{$page_content}%" ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
597 - } else {
598 - // Search for an existing page with the specified page slug.
599 - $trashed_page_found = $wpdb->get_var( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_type='page' AND post_status = 'trash' AND post_name = %s LIMIT 1;", $slug ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
600 - }
601 -
602 - if ( $trashed_page_found ) {
603 - $page_id = $trashed_page_found;
604 - $page_data = [
605 - 'ID' => $page_id,
606 - 'post_status' => $post_status,
607 - ];
608 - wp_update_post( $page_data );
609 - } else {
610 - $page_data = [
611 - 'post_status' => $post_status,
612 - 'post_type' => 'page',
613 - 'post_author' => 1,
614 - 'post_name' => $slug,
615 - 'post_title' => $page_title,
616 - 'post_content' => $page_content,
617 - 'post_parent' => $post_parent,
618 - 'comment_status' => 'closed',
619 - ];
620 - $page_id = wp_insert_post( $page_data );
621 -
622 - do_action( 'rtsb/core/page_created', $page_id, $page_data );
623 - }
624 -
625 - if ( is_array( $options ) ) {
626 - if ( ! empty( $options['section_id'] ) && $options['item_id'] && $options['option_id'] ) {
627 - $section_items = DataModel::source()->get_option( $options['section_id'], [] );
628 - $section_items[ $options['item_id'] ][ $options['option_id'] ] = $page_id;
629 - DataModel::source()->set_option( $options['section_id'], $section_items );
630 - }
631 - } else {
632 - if ( $options ) {
633 - update_option( $options, $page_id );
634 - }
635 - }
636 -
637 - return $page_id;
638 - }
639 -
640 - public static function get_kses_array() {
641 - return [
642 - 'a' => [
643 - 'class' => [],
644 - 'href' => [],
645 - 'rel' => [],
646 - 'title' => [],
647 - ],
648 - 'abbr' => [
649 - 'title' => [],
650 - ],
651 - 'b' => [],
652 - 'blockquote' => [
653 - 'cite' => [],
654 - ],
655 - 'cite' => [
656 - 'title' => [],
657 - ],
658 - 'code' => [],
659 - 'del' => [
660 - 'datetime' => [],
661 - 'title' => [],
662 - ],
663 - 'dd' => [],
664 - 'div' => [
665 - 'class' => [],
666 - 'title' => [],
667 - 'style' => [],
668 - ],
669 - 'dl' => [],
670 - 'dt' => [],
671 - 'em' => [],
672 - 'h1' => [
673 - 'class' => [],
674 - ],
675 - 'h2' => [
676 - 'class' => [],
677 - ],
678 - 'h3' => [
679 - 'class' => [],
680 - ],
681 - 'h4' => [
682 - 'class' => [],
683 - ],
684 - 'h5' => [
685 - 'class' => [],
686 - ],
687 - 'h6' => [
688 - 'class' => [],
689 - ],
690 - 'i' => [
691 - 'class' => [],
692 - ],
693 - 'img' => [
694 - 'alt' => [],
695 - 'class' => [],
696 - 'height' => [],
697 - 'src' => [],
698 - 'width' => [],
699 - ],
700 - 'li' => [
701 - 'class' => [],
702 - ],
703 - 'ol' => [
704 - 'class' => [],
705 - ],
706 - 'p' => [
707 - 'class' => [],
708 - ],
709 - 'q' => [
710 - 'cite' => [],
711 - 'title' => [],
712 - ],
713 - 'span' => [
714 - 'class' => [],
715 - 'title' => [],
716 - 'style' => [],
717 - ],
718 - 'iframe' => [
719 - 'width' => [],
720 - 'height' => [],
721 - 'scrolling' => [],
722 - 'frameborder' => [],
723 - 'allow' => [],
724 - 'src' => [],
725 - ],
726 - 'strike' => [],
727 - 'br' => [],
728 - 'strong' => [],
729 - 'data-wow-duration' => [],
730 - 'data-wow-delay' => [],
731 - 'data-wallpaper-options' => [],
732 - 'data-stellar-background-ratio' => [],
733 - 'ul' => [
734 - 'class' => [],
735 - ],
736 - ];
737 - }
738 -
739 -
740 - /*
741 - * Escape output of wishlist icon
742 - *
743 - * @param string $data Data to escape.
744 - * @return string Escaped data
745 - */
746 - public static function print_icon( $data ) {
747 - /**
748 - * APPLY_FILTERS: rtsb/core/allowed_icon_html
749 - *
750 - * Filter the allowed HTML for the icons.
751 - *
752 - * @param array $allowed_icon_html Allowed HTML
753 - *
754 - * @return array
755 - */
756 - $allowed_icon_html = apply_filters(
757 - 'rtsb/core/allowed_icon_html',
758 - [
759 - 'i' => [
760 - 'class' => true,
761 - ],
762 - 'img' => [
763 - 'src' => true,
764 - 'alt' => true,
765 - 'width' => true,
766 - 'height' => true,
767 - ],
768 - 'svg' => [
769 - 'class' => true,
770 - 'aria-hidden' => true,
771 - 'aria-labelledby' => true,
772 - 'role' => true,
773 - 'xmlns' => true,
774 - 'width' => true,
775 - 'height' => true,
776 - 'viewbox' => true,
777 - 'stroke' => true,
778 - 'fill' => true,
779 - ],
780 - 'g' => [
781 - 'fill' => true,
782 - ],
783 - 'title' => [
784 - 'title' => true,
785 - ],
786 - 'path' => [
787 - 'd' => true,
788 - 'fill' => true,
789 - 'stroke' => true,
790 - 'stroke-width' => true,
791 - 'stroke-linecap' => true,
792 - 'stroke-linejoin' => true,
793 - 'fill-rule' => true,
794 - 'clip-rule' => true,
795 - ],
796 - ]
797 - );
798 -
799 - echo wp_kses( $data, $allowed_icon_html );
800 - }
801 -
802 - /**
803 - * Prints HTMl.
804 - *
805 - * @param string $html HTML.
806 - * @param bool $allHtml All HTML.
807 - *
808 - * @return void
809 - */
810 - public static function print_html( $html, $allHtml = false ) {
811 - if ( ! $html ) {
812 - return;
813 - }
814 - if ( $allHtml ) {
815 - echo stripslashes_deep( $html ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
816 - } else {
817 - echo wp_kses_post( stripslashes_deep( $html ) );
818 - }
819 - }
820 -
821 - /**
822 - * Allowed HTML for wp_kses.
823 - *
824 - * @param string $level Tag level.
825 - *
826 - * @return mixed
827 - */
828 - public static function allowedHtml( $level = 'basic' ) {
829 - $allowed_html = [];
830 - // TODO:: Need Optimize.
831 - switch ( $level ) {
832 - case 'basic':
833 - $allowed_html = [
834 - 'b' => [
835 - 'class' => [],
836 - 'id' => [],
837 - ],
838 - 'i' => [
839 - 'class' => [],
840 - 'id' => [],
841 - ],
842 - 'u' => [
843 - 'class' => [],
844 - 'id' => [],
845 - ],
846 - 'br' => [
847 - 'class' => [],
848 - 'id' => [],
849 - ],
850 - 'em' => [
851 - 'class' => [],
852 - 'id' => [],
853 - ],
854 - 'span' => [
855 - 'class' => [],
856 - 'id' => [],
857 - ],
858 - 'strong' => [
859 - 'class' => [],
860 - 'id' => [],
861 - ],
862 - 'hr' => [
863 - 'class' => [],
864 - 'id' => [],
865 - ],
866 - 'div' => [
867 - 'class' => [],
868 - 'id' => [],
869 - ],
870 - 'a' => [
871 - 'href' => [],
872 - 'title' => [],
873 - 'class' => [],
874 - 'id' => [],
875 - 'target' => [],
876 - ],
877 - ];
878 - break;
879 -
880 - case 'advanced':
881 - $allowed_html = [
882 - 'b' => [
883 - 'class' => [],
884 - 'id' => [],
885 - ],
886 - 'i' => [
887 - 'class' => [],
888 - 'id' => [],
889 - ],
890 - 'u' => [
891 - 'class' => [],
892 - 'id' => [],
893 - ],
894 - 'br' => [
895 - 'class' => [],
896 - 'id' => [],
897 - ],
898 - 'em' => [
899 - 'class' => [],
900 - 'id' => [],
901 - ],
902 - 'span' => [
903 - 'class' => [],
904 - 'id' => [],
905 - ],
906 - 'strong' => [
907 - 'class' => [],
908 - 'id' => [],
909 - ],
910 - 'hr' => [
911 - 'class' => [],
912 - 'id' => [],
913 - ],
914 - 'a' => [
915 - 'href' => [],
916 - 'title' => [],
917 - 'class' => [],
918 - 'id' => [],
919 - 'target' => [],
920 - ],
921 - 'input' => [
922 - 'type' => [],
923 - 'name' => [],
924 - 'class' => [],
925 - 'value' => [],
926 - ],
927 - ];
928 - break;
929 -
930 - case 'image':
931 - $allowed_html = [
932 - 'img' => [
933 - 'src' => [],
934 - 'data-src' => [],
935 - 'alt' => [],
936 - 'height' => [],
937 - 'width' => [],
938 - 'class' => [],
939 - 'id' => [],
940 - 'style' => [],
941 - 'srcset' => [],
942 - 'loading' => [],
943 - 'sizes' => [],
944 - ],
945 - 'div' => [
946 - 'class' => [],
947 - ],
948 - ];
949 - break;
950 -
951 - case 'anchor':
952 - $allowed_html = [
953 - 'a' => [
954 - 'href' => [],
955 - 'title' => [],
956 - 'class' => [],
957 - 'id' => [],
958 - 'style' => [],
959 - ],
960 - ];
961 - break;
962 -
963 - default:
964 - // code...
965 - break;
966 - }
967 -
968 - return $allowed_html;
969 - }
970 -
971 - /**
972 - * Safe get a validated HTML tag.
973 - *
974 - * @param string $tag HTML tag.
975 - *
976 - * @return string
977 - */
978 - public static function get_validated_html_tag( $tag ) {
979 - $allowed_html_wrapper_tags = [
980 - 'a',
981 - 'article',
982 - 'aside',
983 - 'button',
984 - 'div',
985 - 'footer',
986 - 'h1',
987 - 'h2',
988 - 'h3',
989 - 'h4',
990 - 'h5',
991 - 'h6',
992 - 'header',
993 - 'main',
994 - 'nav',
995 - 'p',
996 - 'section',
997 - 'span',
998 - ];
999 -
1000 - return in_array( strtolower( $tag ), $allowed_html_wrapper_tags, true ) ? $tag : 'div';
1001 - }
1002 -
1003 - /**
1004 - * Safe print a validated HTML tag.
1005 - *
1006 - * @param string $tag HTML tag.
1007 - *
1008 - * @return void
1009 - */
1010 - public static function print_validated_html_tag( $tag ) {
1011 - self::print_html( self::get_validated_html_tag( $tag ) );
1012 - }
1013 -
1014 - /**
1015 - * Insert Some array element
1016 - *
1017 - * @param [type] $key The elements will insert nearby this key.
1018 - * @param [type] $main_array Original array.
1019 - * @param [type] $insert_array some element will insert in original array.
1020 - * @param boolean $is_after array insert position base on the key.
1021 - *
1022 - * @return array
1023 - */
1024 - public static function insert_controls( $key, $main_array, $insert_array, $is_after = false ) {
1025 - $index = array_search( $key, array_keys( $main_array ), true );
1026 - if ( 'integer' === gettype( $index ) ) {
1027 - if ( $is_after ) {
1028 - $index++;
1029 - }
1030 - $main_array = array_merge(
1031 - array_slice( $main_array, 0, $index ),
1032 - $insert_array,
1033 - array_slice( $main_array, $index )
1034 - );
1035 - }
1036 -
1037 - return $main_array;
1038 - }
1039 -
1040 - /**
1041 - * Image Sizes
1042 - *
1043 - * @return array
1044 - */
1045 - public static function get_image_sizes() {
1046 - global $_wp_additional_image_sizes;
1047 -
1048 - $sizes = [];
1049 -
1050 - foreach ( get_intermediate_image_sizes() as $_size ) {
1051 - if ( in_array( $_size, [ 'thumbnail', 'medium', 'large' ], true ) ) {
1052 - $sizes[ $_size ]['width'] = get_option( "{$_size}_size_w" );
1053 - $sizes[ $_size ]['height'] = get_option( "{$_size}_size_h" );
1054 - $sizes[ $_size ]['crop'] = (bool) get_option( "{$_size}_crop" );
1055 - } elseif ( isset( $_wp_additional_image_sizes[ $_size ] ) ) {
1056 - $sizes[ $_size ] = [
1057 - 'width' => $_wp_additional_image_sizes[ $_size ]['width'],
1058 - 'height' => $_wp_additional_image_sizes[ $_size ]['height'],
1059 - 'crop' => $_wp_additional_image_sizes[ $_size ]['crop'],
1060 - ];
1061 - }
1062 - }
1063 -
1064 - $imgSize = [];
1065 -
1066 - foreach ( $sizes as $key => $img ) {
1067 - $imgSize[ $key ] = ucfirst( $key ) . " ({$img['width']}*{$img['height']})";
1068 - }
1069 -
1070 - $imgSize['full'] = esc_html__( 'Full size', 'shopbuilder' );
1071 - $imgSize['rtsb_custom'] = esc_html__( 'Custom image size', 'shopbuilder' );
1072 -
1073 - return $imgSize;
1074 - }
1075 -
1076 - /**
1077 - * Free Layouts
1078 - *
1079 - * @return array
1080 - */
1081 - public static function free_layouts() {
1082 - $layouts = [
1083 - 'grid-layout1' => esc_html__( 'Grid Layout 1', 'shopbuilder' ),
1084 - 'grid-layout2' => esc_html__( 'Grid Layout 2', 'shopbuilder' ),
1085 - 'list-layout1' => esc_html__( 'List Layout 1', 'shopbuilder' ),
1086 - 'list-layout2' => esc_html__( 'List Layout 2', 'shopbuilder' ),
1087 - 'slider-layout1' => esc_html__( 'Slider Layout 1', 'shopbuilder' ),
1088 - 'slider-layout2' => esc_html__( 'Slider Layout 2', 'shopbuilder' ),
1089 - 'category-single-layout1' => esc_html__( 'Category Single Layout 1', 'shopbuilder' ),
1090 - 'category-layout1' => esc_html__( 'Category Layout 1', 'shopbuilder' ),
1091 - 'category-layout2' => esc_html__( 'Category Layout 2', 'shopbuilder' ),
1092 - ];
1093 -
1094 - return apply_filters( 'rtsb/elements/elementor/free_layouts', $layouts );
1095 - }
1096 -
1097 - /**
1098 - * Get all terms by taxonomy
1099 - *
1100 - * @param string $taxonomy Taxonomy name.
1101 - * @param bool $placeholder Placeholder..
1102 - *
1103 - * @return array
1104 - */
1105 - public static function get_all_terms( $taxonomy, $placeholder = false ) {
1106 - $terms = [];
1107 -
1108 - if ( empty( $taxonomy ) ) {
1109 - return $terms;
1110 - }
1111 - $cache_key = 'rtsb_get_all_terms_by_tax_name_' . $taxonomy;
1112 - if ( isset( self::$cache[ $cache_key ] ) ) {
1113 - return self::$cache[ $cache_key ];
1114 - }
1115 -
1116 - $termList = get_terms(
1117 - [
1118 - 'taxonomy' => $taxonomy,
1119 - 'hide_empty' => false,
1120 - ]
1121 - );
1122 -
1123 - if ( is_array( $termList ) && ! empty( $termList ) && empty( $termList['errors'] ) ) {
1124 - if ( $placeholder ) {
1125 - $terms = [
1126 - 'all' => __( 'All Products', 'shopbuilder' ),
1127 - ];
1128 - }
1129 -
1130 - foreach ( $termList as $term ) {
1131 - $terms[ $term->term_id ] = esc_html( $term->name );
1132 - }
1133 - }
1134 - self::$cache[ $cache_key ] = $terms;
1135 - return $terms;
1136 - }
1137 -
1138 - /**
1139 - * Get all terms by attributes
1140 - *
1141 - * @return array
1142 - */
1143 - public static function get_all_attributes() {
1144 - $terms = [];
1145 - $termList = [];
1146 -
1147 - $attributes = wc_get_attribute_taxonomies();
1148 -
1149 - if ( $attributes ) {
1150 - foreach ( $attributes as $tax ) {
1151 - if ( taxonomy_exists( wc_attribute_taxonomy_name( $tax->attribute_name ) ) ) {
1152 - $termList[ $tax->attribute_name ] = get_terms( wc_attribute_taxonomy_name( $tax->attribute_name ) );
1153 - }
1154 - }
1155 - }
1156 -
1157 - if ( ! empty( $termList ) && empty( $termList['errors'] ) && is_array( $termList ) ) {
1158 - foreach ( $termList as $name => $atts ) {
1159 - foreach ( $atts as $term ) {
1160 - $terms[ $term->term_id ] = esc_html( ucwords( str_replace( '-', ' ', $name ) ) . ' - ' . $term->name );
1161 - }
1162 - }
1163 - }
1164 -
1165 - return $terms;
1166 - }
1167 -
1168 - /**
1169 - * Get all attributes name
1170 - *
1171 - * @return array
1172 - */
1173 - public static function get_all_attributes_name() {
1174 - $attributes_name = [];
1175 -
1176 - $attributes = wc_get_attribute_taxonomies();
1177 -
1178 - if ( $attributes ) {
1179 - foreach ( $attributes as $tax ) {
1180 - if ( taxonomy_exists( wc_attribute_taxonomy_name( $tax->attribute_name ) ) ) {
1181 - $attributes_name[ wc_attribute_taxonomy_name( $tax->attribute_name ) ] = ucwords( $tax->attribute_name );
1182 - }
1183 - }
1184 - }
1185 -
1186 - return $attributes_name;
1187 - }
1188 -
1189 - /**
1190 - * Get User list
1191 - *
1192 - * @return array
1193 - */
1194 - public static function get_users() {
1195 - $users = [];
1196 - $u = get_users();
1197 -
1198 - if ( ! empty( $u ) ) {
1199 - foreach ( $u as $user ) {
1200 - $users[ $user->ID ] = $user->display_name;
1201 - }
1202 - }
1203 -
1204 - return $users;
1205 - }
1206 -
1207 - /**
1208 - * Get Taxonomy List.
1209 - *
1210 - * @return array
1211 - */
1212 - public static function get_tax_list() {
1213 - return apply_filters(
1214 - 'rtsb/elements/tax_list',
1215 - [
1216 - 'product_cat' => esc_html__( 'Product Category', 'shopbuilder' ),
1217 - ]
1218 - );
1219 - }
1220 -
1221 - /**
1222 - * Get Category Query List.
1223 - *
1224 - * @return array
1225 - */
1226 - public static function get_cat_list() {
1227 - return [
1228 - 'all' => esc_html__( 'All Categories', 'shopbuilder' ),
1229 - 'specific_parent' => esc_html__( 'Sub-Categories by Parent', 'shopbuilder' ),
1230 - 'cat_ids' => esc_html__( 'Select by ID', 'shopbuilder' ),
1231 - 'selection' => esc_html__( 'Manual Selection', 'shopbuilder' ),
1232 - ];
1233 - }
1234 -
1235 - /**
1236 - * Get Term List.
1237 - *
1238 - * @param string $taxonomy Taxonomy.
1239 - * @param bool $first_term First term.
1240 - * @param bool $only_parents Only parent terms.
1241 - * @param bool $return_slug Return with slug.
1242 - *
1243 - * @return int|array
1244 - */
1245 - public static function get_terms( $taxonomy, $first_term = false, $only_parents = false, $return_slug = false ) {
1246 - if ( ! is_admin() ) {
1247 - return [];
1248 - }
1249 -
1250 - // TODO:: Return Slug always true for all settings.
1251 - $term_list = [];
1252 - $args = [
1253 - 'taxonomy' => $taxonomy,
1254 - 'hide_empty' => false,
1255 - ];
1256 -
1257 - if ( $only_parents ) {
1258 - $args['parent'] = 0;
1259 - }
1260 -
1261 - $terms = get_terms( $args );
1262 -
1263 - if ( empty( $terms ) ) {
1264 - return [ esc_html__( 'Nothing found', 'shopbuilder' ) ];
1265 - }
1266 -
1267 - foreach ( $terms as $term ) {
1268 - if ( $return_slug ) {
1269 - $term_list[ $term->slug ] = $term->name;
1270 - } else {
1271 - $term_list[ $term->term_id ] = $term->name;
1272 - }
1273 - }
1274 -
1275 - if ( $first_term ) {
1276 - return array_keys( $term_list )[0];
1277 - } else {
1278 - return $term_list;
1279 - }
1280 - }
1281 -
1282 - /**
1283 - * Get product rating.
1284 - *
1285 - * @param array $args Arguments.
1286 - *
1287 - * @return string|void
1288 - */
1289 - public static function get_product_rating_html( $args = [] ) {
1290 - global $product;
1291 -
1292 - $html = '';
1293 - $rating_count = $product->get_rating_count();
1294 - $average_rating = $product->get_average_rating();
1295 -
1296 - if ( ! rtsb()->has_pro() || empty( $args ) ) {
1297 - if ( ! $rating_count || empty( wc_get_rating_html( $average_rating, $rating_count ) ) ) {
1298 - return $html;
1299 - }
1300 -
1301 - $html .= '<div class="product-rating">';
1302 - $html .= wc_get_rating_html( $average_rating, $rating_count );
1303 - $html .= ! empty( $html ) ? '<span class="rtsb-count">(' . $average_rating . ')</span>' : '';
1304 - $html .= '</div>';
1305 -
1306 - self::print_html( $html, true );
1307 -
1308 - return;
1309 - }
1310 -
1311 - if ( empty( $rating_count ) && ! $args['show_empty_rating'] ) {
1312 - return '';
1313 - }
1314 -
1315 - $preset = ! empty( $args['preset'] ) ? $args['preset'] : 'preset1';
1316 - $average = $args['show_average_rating'] ? '<span class="rtsb-count">(' . $average_rating . ')</span>' : '';
1317 - $count = '';
1318 -
1319 - if ( $args['show_rating_count'] ) {
1320 - $count .= '<div class="rtsb-count">';
1321 - $count .= sprintf(
1322 - /* translators: %s is the number of reviews */
1323 - _n( '%s Review', '%s Reviews', $rating_count, 'shopbuilder' ),
1324 - $rating_count
1325 - );
1326 - $count .= '</div>';
1327 - }
1328 -
1329 - if ( 'preset2' === $preset ) {
1330 - $average = $args['show_average_rating'] ? '<div class="inner-wrapper"><span class="star-icon"></span><span class="average-rating">' . $average_rating . '</span></div>' : '';
1331 - }
1332 -
1333 - $html .= '<div class="product-rating ' . esc_attr( $preset ) . '">';
1334 -
1335 - if ( 'preset1' === $preset ) {
1336 - $html .= wc_get_rating_html( $average_rating, $rating_count );
1337 - $html .= $average;
1338 - $html .= $count;
1339 - } elseif ( 'preset2' === $preset ) {
1340 - $html .= $average;
1341 - $html .= $count;
1342 - }
1343 -
1344 - $html .= '</div>';
1345 -
1346 - self::print_html( $html, true );
1347 - }
1348 -
1349 - public static function get_product_simple_rating_html() {
1350 - global $product;
1351 - $html = null;
1352 - $rating_count = $product->get_rating_count();
1353 - $average_rating = $product->get_average_rating();
1354 - $html .= '<div class="product-rating">';
1355 - $html .= wc_get_rating_html( $average_rating, $rating_count );
1356 - $html .= ! empty( $html ) ? '<span class="rtsb-count">(' . $average_rating . ')</span>' : '';
1357 - $html .= '</div>';
1358 -
1359 - self::print_html( $html, true );
1360 - }
1361 -
1362 -
1363 -
1364 - /**
1365 - * Text truncation.
1366 - *
1367 - * @param string $text_to_truncate Text.
1368 - * @param int $limit Limit.
1369 - * @param string $after After text.
1370 - *
1371 - * @return string
1372 - */
1373 - public static function text_truncation( $text_to_truncate, $limit, $after = '&#8230;' ) {
1374 - if ( empty( $limit ) ) {
1375 - return $text_to_truncate;
1376 - }
1377 -
1378 - $limit++;
1379 -
1380 - $text = '';
1381 -
1382 - if ( mb_strlen( $text_to_truncate ) > $limit ) {
1383 - $subex = mb_substr( wp_strip_all_tags( $text_to_truncate ), 0, $limit );
1384 - $exwords = explode( ' ', $subex );
1385 - $excut = - ( mb_strlen( $exwords[ count( $exwords ) - 1 ] ) );
1386 -
1387 - if ( $excut < 0 ) {
1388 - $text .= mb_substr( $subex, 0, $excut ) . $after;
1389 - } else {
1390 - $text .= $subex . $after;
1391 - }
1392 - } else {
1393 - $text .= $text_to_truncate;
1394 - }
1395 -
1396 - return $text;
1397 - }
1398 -
1399 - /**
1400 - * Promo Badge HTML
1401 - *
1402 - * @param string $text Text.
1403 - * @param string $class Class.
1404 - *
1405 - * @return void
1406 - */
1407 - public static function get_badge_html( $text, $class = 'fill' ) {
1408 - if ( self::is_module_active( 'product_badges' ) && 'rtsb_yes' === $text ) {
1409 - do_action( 'rtsb/modules/product_badges/frontend/display' );
1410 -
1411 - return;
1412 - }
1413 -
1414 - if ( empty( $text ) ) {
1415 - return;
1416 - }
1417 - ob_start();
1418 - ?>
1419 -
1420 - <ul class="rtsb-promotion-list">
1421 - <li class="rtsb-promotion-list-item">
1422 - <span class="rtsb-tag-<?php echo ! empty( $class ) ? esc_attr( $class ) : ''; ?>"><?php echo esc_html( $text ); ?></span>
1423 - </li>
1424 - </ul>
1425 -
1426 - <?php
1427 - self::print_html( ob_get_clean() );
1428 - }
1429 -
1430 - /**
1431 - * Categories HTML
1432 - *
1433 - * @param int $id Product ID.
1434 - * @param string $class Custom class.
1435 - *
1436 - * @return void|string
1437 - */
1438 - public static function get_categories_list( $id, $class = 'rtsb-category-outline' ) {
1439 - if ( empty( $id ) ) {
1440 - return '';
1441 - }
1442 -
1443 - ob_start();
1444 - ?>
1445 -
1446 - <ul class="rtsb-category-list <?php echo esc_attr( $class ); ?>">
1447 - <?php
1448 - self::print_html(
1449 - wc_get_product_category_list(
1450 - $id,
1451 - '</li><li class="rtsb-category-list-item">',
1452 - '<li class="rtsb-category-list-item">',
1453 - '</li>'
1454 - )
1455 - );
1456 - ?>
1457 - </ul>
1458 -
1459 - <?php
1460 - self::print_html( ob_get_clean() );
1461 - }
1462 -
1463 - /**
1464 - * Get Featured Image HTML.
1465 - *
1466 - * @param string $type Image type.
1467 - * @param int $post_id Post ID.
1468 - * @param string $f_img_size Image size.
1469 - * @param null $default_img_id Default image ID.
1470 - * @param array $custom_img_size Custom image size.
1471 - * @param bool $lazy Lazy load check.
1472 - * @param bool $hover Hover image.
1473 - * @param bool $gallery Gallery image.
1474 - * @param bool $custom_image_id Custom category image ID.
1475 - *
1476 - * @return string|null
1477 - */
1478 - public static function get_product_image_html( $type = 'product', $post_id = null, $f_img_size = 'medium', $default_img_id = null, $custom_img_size = [], $lazy = false, $hover = false, $gallery = false, $custom_image_id = 0 ) {
1479 - $img_html = null;
1480 - $attachment_id = null;
1481 - $c_size = false;
1482 - $hover_class = '';
1483 - $post_title = '';
1484 -
1485 - if ( 'rtsb_custom' === $f_img_size ) {
1486 - $f_img_size = 'full';
1487 - $c_size = true;
1488 - }
1489 -
1490 - if ( ! rtsb()->has_pro() ) {
1491 - $gallery = false;
1492 - }
1493 -
1494 - if ( $hover ) {
1495 - $a_id = $post_id;
1496 - $hover_class = ' rtsb-img-hover';
1497 - } elseif ( $gallery ) {
1498 - $a_id = $post_id;
1499 - } else {
1500 - if ( 'product' === $type ) {
1501 - $a_id = get_post_thumbnail_id( $post_id );
1502 - $post_title = get_the_title( $post_id );
1503 - } elseif ( 'category' === $type ) {
1504 - $a_id = $custom_image_id ? $custom_image_id : get_term_meta( $post_id, 'thumbnail_id', true );
1505 - $post_title = get_term( $post_id )->name;
1506 - } else {
1507 - $a_id = $default_img_id;
1508 - }
1509 - }
1510 -
1511 - $img_alt = trim( wp_strip_all_tags( get_post_meta( $a_id, '_wp_attachment_image_alt', true ) ) );
1512 - $alt_tag = ! empty( $img_alt ) ? $img_alt : wp_strip_all_tags( $post_title );
1513 - $lazy_class = $lazy ? ' swiper-lazy' : '';
1514 - $attr = [
1515 - 'class' => 'img-responsive rtsb-product-image' . $lazy_class . $hover_class,
1516 - 'alt' => $alt_tag,
1517 - ];
1518 -
1519 - if ( $a_id ) {
1520 - $img_html = wp_get_attachment_image( $a_id, $f_img_size, false, $attr );
1521 - $attachment_id = $a_id;
1522 - }
1523 -
1524 - if ( ! $img_html && $default_img_id ) {
1525 - $img_html = wp_get_attachment_image( $default_img_id, $f_img_size, false, $attr );
1526 - $attachment_id = $default_img_id;
1527 - }
1528 -
1529 - if ( $img_html && $c_size ) {
1530 - preg_match( '@src="([^"]+)"@', $img_html, $match );
1531 - $img_src = array_pop( $match );
1532 - $w = ! empty( $custom_img_size['width'] ) ? absint( $custom_img_size['width'] ) : null;
1533 - $h = ! empty( $custom_img_size['height'] ) ? absint( $custom_img_size['height'] ) : null;
1534 - $c = ! empty( $custom_img_size['crop'] ) && 'soft' === $custom_img_size['crop'] ? false : true;
1535 -
1536 - if ( $w && $h ) {
1537 - $image = self::image_resize( $img_src, $w, $h, $c, false );
1538 -
1539 - if ( ! empty( $image ) ) {
1540 - [ $src, $width, $height ] = $image;
1541 -
1542 - $hwstring = image_hwstring( $width, $height );
1543 - $attachment = get_post( $attachment_id );
1544 - $attr = apply_filters( 'wp_get_attachment_image_attributes', $attr, $attachment, $f_img_size );
1545 -
1546 - if ( $lazy ) {
1547 - $attr['data-src'] = $src;
1548 - } else {
1549 - $attr['src'] = $src;
1550 - }
1551 -
1552 - $attr = array_map( 'esc_attr', $attr );
1553 - $img_html = rtrim( "<img $hwstring" );
1554 -
1555 - foreach ( $attr as $name => $value ) {
1556 - $img_html .= " $name=" . '"' . $value . '"';
1557 - }
1558 -
1559 - $img_html .= ' />';
1560 - }
1561 - }
1562 - }
1563 -
1564 - if ( ! $img_html ) {
1565 - $hwstring = image_hwstring( 160, 160 );
1566 - $attr = isset( $attr['src'] ) ? apply_filters( 'wp_get_attachment_image_attributes', $attr, false, $f_img_size ) : [];
1567 - $attr['class'] = 'default-img';
1568 - $attr['src'] = esc_url( rtsb()->get_assets_uri( 'images/demo.png' ) );
1569 - $attr['alt'] = esc_html__( 'Default Image', 'shopbuilder' );
1570 - $img_html = rtrim( "<img $hwstring" );
1571 -
1572 - foreach ( $attr as $name => $value ) {
1573 - $img_html .= " $name=" . '"' . $value . '"';
1574 - }
1575 -
1576 - $img_html .= ' />';
1577 - }
1578 -
1579 - if ( $lazy ) {
1580 - $img_html = $img_html . '<div class="swiper-lazy-preloader swiper-lazy-preloader"></div>';
1581 - }
1582 -
1583 - return $img_html;
1584 - }
1585 -
1586 - /**
1587 - * Call the Image resize model for resize function
1588 - *
1589 - * @param string $url URL.
1590 - * @param int $width Width.
1591 - * @param int $height Height.
1592 - * @param string $crop Crop.
1593 - * @param bool|true $single Single.
1594 - * @param bool|false $upscale Upscale.
1595 - *
1596 - * @return array|bool|string
1597 - */
1598 - public static function image_resize( $url, $width = null, $height = null, $crop = null, $single = true, $upscale = false ) {
1599 - $rtResize = new ReSizer();
1600 -
1601 - return $rtResize->process( $url, $width, $height, $crop, $single, $upscale );
1602 - }
1603 -
1604 - /**
1605 - * Get Product Image
1606 - *
1607 - * @param string $f_image Featured Image.
1608 - * @param string $h_image Hover Image.
1609 - *
1610 - * @return void
1611 - */
1612 - public static function get_product_image( $f_image, $h_image = null ) {
1613 - if ( empty( $f_image ) ) {
1614 - return;
1615 - }
1616 -
1617 - echo wp_kses( $f_image, self::allowedHtml( 'image' ) );
1618 -
1619 - if ( ! empty( $h_image ) ) {
1620 - echo wp_kses( $h_image, self::allowedHtml( 'image' ) );
1621 - }
1622 - }
1623 -
1624 - /**
1625 - * Post Custom Field value.
1626 - *
1627 - * @param int $post_id Post id.
1628 - * @param string $field_key Custom Field Key.
1629 - * @param string $field_fallback FallBack text.
1630 - *
1631 - * @return string|void
1632 - */
1633 - public static function get_post_custom_field_value( $post_id, $field_key = '', $field_fallback = '' ) {
1634 - if ( ! $post_id || ! $field_key ) {
1635 - return;
1636 - }
1637 - $field_value = get_post_meta( $post_id, $field_key, true );
1638 - if ( empty( $field_value ) ) {
1639 - $field_value = ! empty( $field_fallback ) ? $field_fallback : $field_value;
1640 - }
1641 - $field_value = apply_filters( 'rtsb/get_post_custom_field_value/' . $field_key, $field_value, $field_key );
1642 -
1643 - return sprintf( '<span class="rtsb-woo-custom-field">%s</span>', $field_value );
1644 - }
1645 -
1646 - /**
1647 - * Elementor Icon
1648 - *
1649 - * @param array $control Elementor Control array.
1650 - * @param string $class Custom class.
1651 - * @param string $builder Builder name.
1652 - *
1653 - * @return string
1654 - */
1655 - public static function icons_manager( $control, $class = '', $builder = 'elementor' ): string {
1656 - if ( empty( $control['value'] ) ) {
1657 - return '';
1658 - }
1659 - if ( is_array( $control['value'] ) ) {
1660 - $cache_key = 'icons_managet_' . str_replace( ' ', '', md5( serialize( $control['value'] ) ) );
1661 - } else {
1662 - $cache_key = 'icons_managet_' . str_replace( ' ', '', $control['value'] );
1663 - }
1664 - if ( isset( self::$cache[ $cache_key ] ) ) {
1665 - return self::$cache[ $cache_key ];
1666 - }
1667 -
1668 - $attributes = [
1669 - 'aria-hidden' => 'true',
1670 - ];
1671 -
1672 - if ( ! empty( $class ) ) {
1673 - $attributes['class'] = esc_attr( $class );
1674 - }
1675 -
1676 - ob_start();
1677 -
1678 - if ( defined( 'ELEMENTOR_VERSION' ) && ! empty( $control ) && 'elementor' === $builder ) {
1679 - Icons_Manager::render_icon( $control, $attributes );
1680 - }
1681 -
1682 - $icons = ob_get_clean();
1683 - self::$cache[ $cache_key ] = $icons;
1684 - return $icons;
1685 - }
1686 -
1687 - /**
1688 - * Get product swatches.
1689 - *
1690 - * @param string $type Swatch type.
1691 - *
1692 - * @return void
1693 - */
1694 - public static function get_product_swatches( $type ) {
1695 - ?>
1696 - <div class="rtsb-swatches <?php echo esc_attr( $type ); ?>-layout">
1697 - <?php
1698 - do_action( 'rtwpvs_show_archive_variation' );
1699 - ?>
1700 - </div>
1701 - <?php
1702 - }
1703 -
1704 - /**
1705 - * Get sale badge
1706 - *
1707 - * @param string $type Badge type.
1708 - * @param string $text Badge text.
1709 - * @param string $out_of_stock_text Out of stock text.
1710 - *
1711 - * @return string
1712 - */
1713 - public static function get_sale_badge( $type, $text, $out_of_stock_text ) {
1714 - global $product;
1715 -
1716 - if ( ! $product->is_in_stock() ) {
1717 - return $out_of_stock_text;
1718 - }
1719 -
1720 - if ( ! $product->is_on_sale() ) {
1721 - return '';
1722 - }
1723 -
1724 - $badge_text = '';
1725 - $percentage = self::calculate_sale_percentage( $product );
1726 -
1727 - if ( $percentage > 0 ) {
1728 - $badge_text = '-' . round( $percentage ) . '%';
1729 - }
1730 -
1731 - if ( 'text' === $type ) {
1732 - $badge_text = $text;
1733 - }
1734 -
1735 - return $badge_text;
1736 - }
1737 -
1738 - /**
1739 - * Get sale badge
1740 - *
1741 - * @param object $product Product Object.
1742 - * @param string $type Badge type.
1743 - * @param string $text Badge text.
1744 - * @param string $out_of_stock_text Out of stock text.
1745 - *
1746 - * @return string
1747 - */
1748 - public static function get_promo_badge( $product, $type, $text, $out_of_stock_text ) {
1749 - $disable_badges = self::get_option( 'general', 'guest_user', 'hide_badges', '' );
1750 - $badges_visibility = rtsb()->has_pro() && ! is_user_logged_in() && $disable_badges;
1751 -
1752 - if ( $badges_visibility ) {
1753 - return '';
1754 - }
1755 -
1756 - if ( is_null( $product ) ) {
1757 - global $product;
1758 - }
1759 -
1760 - if ( ! $product instanceof WC_Product ) {
1761 - return '';
1762 - }
1763 -
1764 - if ( ! $product->is_in_stock() ) {
1765 - return $out_of_stock_text;
1766 - }
1767 -
1768 - if ( ! $product->is_on_sale() ) {
1769 - return '';
1770 - }
1771 -
1772 - $badge_text = '';
1773 - $percentage = self::calculate_sale_percentage( $product );
1774 -
1775 - if ( $percentage > 0 ) {
1776 - $badge_text = '-' . round( $percentage ) . '%';
1777 - }
1778 -
1779 - if ( 'text' === $type ) {
1780 - $badge_text = $text;
1781 - }
1782 -
1783 - return $badge_text;
1784 - }
1785 -
1786 - /**
1787 - * Calculate Sale Percentage
1788 - *
1789 - * @param object $product Product object.
1790 - *
1791 - * @return float|int|string
1792 - */
1793 - public static function calculate_sale_percentage( $product = null ) {
1794 - if ( is_null( $product ) ) {
1795 - global $product;
1796 - }
1797 -
1798 - if ( ! $product instanceof WC_Product ) {
1799 - return '';
1800 - }
1801 -
1802 - if ( ! $product->is_on_sale() ) {
1803 - return '';
1804 - }
1805 -
1806 - $percentage = null;
1807 - $max_percentage = '';
1808 -
1809 - if ( $product->is_type( 'simple' ) ) {
1810 - $max_percentage = ( ( $product->get_regular_price() - $product->get_sale_price() ) / $product->get_regular_price() ) * 100;
1811 - } elseif ( $product->is_type( 'variable' ) ) {
1812 - $max_percentage = 0;
1813 -
1814 - foreach ( $product->get_children() as $child_id ) {
1815 -
1816 - $variation = wc_get_product( $child_id );
1817 -
1818 - $price = $variation->get_regular_price();
1819 - $sale = $variation->get_sale_price();
1820 -
1821 - if ( 0 !== $price && ! empty( $sale ) ) {
1822 - $percentage = ( $price - $sale ) / $price * 100;
1823 - }
1824 -
1825 - if ( $percentage > $max_percentage ) {
1826 - $max_percentage = $percentage;
1827 - }
1828 - }
1829 - }
1830 -
1831 - if ( $max_percentage > 0 ) {
1832 - return round( $max_percentage );
1833 - }
1834 -
1835 - return 0;
1836 - }
1837 -
1838 - /**
1839 - * Pagination
1840 - *
1841 - * @param string $pages Pages.
1842 - * @param integer $range Range.
1843 - * @param boolean $ajax Ajax.
1844 - *
1845 - * @return string
1846 - */
1847 - public static function custom_pagination( $pages = '', $range = 4, $ajax = false ) {
1848 - $html = null;
1849 - $visible_range = apply_filters( 'rtsb/elements/pagination/visible_range', ( $range * 2 ) + 1 );
1850 -
1851 - global $paged;
1852 -
1853 - if ( is_front_page() ) {
1854 - $paged = ( get_query_var( 'page' ) ) ? get_query_var( 'page' ) : 1;
1855 - } else {
1856 - $paged = ( get_query_var( 'paged' ) ) ? get_query_var( 'paged' ) : 1;
1857 - }
1858 -
1859 - if ( empty( $paged ) ) {
1860 - $paged = 1;
1861 - }
1862 -
1863 - if ( '' === $pages ) {
1864 - global $wp_query;
1865 -
1866 - $pages = $wp_query->max_num_pages;
1867 -
1868 - if ( ! $pages ) {
1869 - $pages = 1;
1870 - }
1871 - }
1872 -
1873 - $ajaxClass = null;
1874 - $dataAttr = null;
1875 -
1876 - if ( $ajax ) {
1877 - $ajaxClass = ' rtsb-pagination-ajax';
1878 - $dataAttr = "data-paged='1'";
1879 - $dataAttr .= ' data-visible-range="' . esc_attr( $visible_range ) . '"';
1880 - }
1881 -
1882 - if ( 1 !== $pages ) {
1883 - $html .= '<div class="rtsb-pagination' . $ajaxClass . '" ' . $dataAttr . '>';
1884 - $html .= '<ul class="pagination-list">';
1885 -
1886 - if ( $paged > 2 && $paged > $visible_range + 1 && $visible_range < $pages ) {
1887 - $html .= "<li><a data-paged='1' href='" . get_pagenum_link( 1 ) . "' aria-label='First'>&laquo;</a></li>";
1888 - }
1889 -
1890 - if ( $paged > 1 && $visible_range < $pages ) {
1891 - $p = $paged - 1;
1892 - $html .= "<li><a data-paged='{$p}' href='" . get_pagenum_link( $p ) . "' aria-label='Previous'>&lsaquo;</a></li>";
1893 - }
1894 -
1895 - for ( $i = 1; $i <= $pages; $i++ ) {
1896 - if ( 1 != $pages && ( ! ( $i >= $paged + $visible_range + 1 || $i <= $paged - $visible_range - 1 ) || $pages <= $visible_range ) ) {
1897 - $html .= ( $paged == $i ) ? '<li class="active"><span>' . $i . '</span></li>' : "<li><a data-paged='{$i}' href='" . get_pagenum_link( $i ) . "'>" . $i . '</a></li>';
1898 - }
1899 - }
1900 -
1901 - if ( $paged < $pages && $visible_range < $pages ) {
1902 - $p = $paged + 1;
1903 - $html .= "<li><a data-paged='{$p}' href=\"" . get_pagenum_link( $paged + 1 ) . "\" aria-label='Next'>&rsaquo;</a></li>";
1904 - }
1905 -
1906 - if ( $paged < $pages - 1 && $paged + $range - 1 < $pages && $visible_range < $pages ) {
1907 - $html .= "<li><a data-paged='{$pages}' href='" . get_pagenum_link( $pages ) . "' aria-label='Last'>&raquo;</a></li>";
1908 - }
1909 -
1910 - $html .= '</ul>';
1911 - $html .= '</div>';
1912 - }
1913 -
1914 - return $html;
1915 - }
1916 -
1917 - /**
1918 - * Action Buttons HTMl
1919 - *
1920 - * @param array $items Items.
1921 - * @param array $ajax_cart Ajax cart HTML.
1922 - * @param string $preset Button preset.
1923 - * @param array $position Position.
1924 - * @param string $placement Placement.
1925 - *
1926 - * @return void|string
1927 - */
1928 - public static function get_formatted_action_buttons( $items, $ajax_cart = '', $preset = 'preset1', $position = 'above', $placement = 'top' ) {
1929 - if ( empty( $items ) ) {
1930 - return;
1931 - }
1932 -
1933 - $html = '';
1934 - $class = '';
1935 - $args = [ $items, $ajax_cart, $preset, $position, $placement ];
1936 -
1937 - if ( ( 'top' === $placement && 'after' === $position ) || ( 'bottom' === $placement && 'above' === $position ) ) {
1938 - return apply_filters( 'rtsb/elements/elementor/formatted_action_buttons', $html, $args );
1939 - }
1940 -
1941 - if ( 'preset2' === $preset ) {
1942 - $class = 'rtsb-action-buttons-vertical vertical-delay-effect ' . $preset;
1943 - } elseif ( 'preset4' === $preset ) {
1944 - $class = 'rtsb-action-buttons-vertical rtsb-action-buttons-vertical-left vertical-delay-effect ' . $preset;
1945 - } elseif ( 'preset1' === $preset || 'preset3' === $preset ) {
1946 - $class = 'rtsb-action-buttons-cart-box-width-auto horizontal-floating-btn ' . $preset;
1947 - }
1948 -
1949 - if ( 'after' === $position && 'preset1' === $preset ) {
1950 - $class .= ' after-content';
1951 - }
1952 -
1953 - if ( 'preset3' === $preset ) {
1954 - $html .= '<div class="rtsb-action-buttons top-part ' . esc_attr( $preset ) . '">';
1955 - $html .= '<ul class="rtsb-action-button-list">';
1956 -
1957 - ob_start();
1958 - /**
1959 - * Additional formatted action buttons hook.
1960 - */
1961 - do_action( 'rtsb/elements/elementor/additional_action_buttons', $items );
1962 - $html .= ob_get_clean();
1963 -
1964 - $html .= self::get_action_button_by_type( $items, 'wishlist' );
1965 - $html .= self::get_action_button_by_type( $items, 'compare' );
1966 - $html .= self::get_action_button_by_type( $items, 'quick_view' );
1967 - $html .= '</ul>';
1968 - $html .= '</div>';
1969 - $html .= '<div class="rtsb-action-buttons bottom-part ' . esc_attr( $preset ) . '">';
1970 - $html .= '<ul class="rtsb-action-button-list">';
1971 - $html .= self::get_action_button_by_type( $items, 'add_to_cart', $ajax_cart );
1972 - $html .= '</ul>';
1973 - $html .= '</div>';
1974 - } elseif ( 'preset1' === $preset || 'preset2' === $preset || 'preset4' === $preset ) {
1975 - $html .= '<div class="rtsb-action-buttons ' . esc_attr( $class ) . '">';
1976 - $html .= '<ul class="rtsb-action-button-list">';
1977 - $html .= self::get_action_button_by_type( $items, 'add_to_cart', $ajax_cart );
1978 -
1979 - ob_start();
1980 - /**
1981 - * Additional formatted action buttons hook.
1982 - */
1983 - do_action( 'rtsb/elements/elementor/additional_action_buttons', $items );
1984 - $html .= ob_get_clean();
1985 -
1986 - $html .= self::get_action_button_by_type( $items, 'wishlist' );
1987 - $html .= self::get_action_button_by_type( $items, 'compare' );
1988 - $html .= self::get_action_button_by_type( $items, 'quick_view' );
1989 - $html .= '</ul>';
1990 - $html .= '</div>';
1991 - }
1992 -
1993 - return apply_filters( 'rtsb/elements/elementor/formatted_action_buttons', $html, $args );
1994 - }
1995 -
1996 - /**
1997 - * Get Action Button HTML
1998 - *
1999 - * @param array $items Items.
2000 - * @param string $type Button type.
2001 - * @param string $cart_html Ajax cart HTML.
2002 - * @param string $wrapper Wrapper tag.
2003 - *
2004 - * @return void|string
2005 - */
2006 - public static function get_action_button_by_type( $items, $type, $cart_html = '', $wrapper = 'li' ) {
2007 - if ( ! in_array( $type, $items, true ) ) {
2008 - return;
2009 - }
2010 -
2011 - $html = '';
2012 - $class = 'rtsb-action-button-item';
2013 -
2014 - if ( 'add_to_cart' === $type ) {
2015 - $class .= ' rtsb-cart' . ( empty( $cart_html ) ? esc_attr( ' no-cart-button' ) : '' );
2016 - } else {
2017 - $class .= ' rtsb-' . esc_attr( str_replace( '_', '-', $type ) );
2018 - }
2019 -
2020 - $html .= '<' . esc_attr( $wrapper ) . ' class="' . esc_attr( $class ) . '">';
2021 -
2022 - if ( ( 'add_to_cart' === $type ) && ( ! empty( $cart_html ) ) ) {
2023 - $html .= $cart_html;
2024 - } else {
2025 - $html .= shortcode_exists( 'rtsb_' . $type . '_button' ) ? do_shortcode( '[rtsb_' . $type . '_button]' ) : null;
2026 - }
2027 -
2028 - $html .= '</' . esc_attr( $wrapper ) . '>';
2029 -
2030 - return apply_filters( 'rtsb/elements/elementor/get_action_button_by_type', $html );
2031 - }
2032 -
2033 - /**
2034 - * Social Share Platforms.
2035 - *
2036 - * @return mixed|null
2037 - */
2038 - public static function social_share_platforms_list() {
2039 - return apply_filters(
2040 - 'rtsb/settings/social_share/platforms',
2041 - [
2042 - [
2043 - 'value' => 'facebook',
2044 - 'label' => esc_html__( 'Facebook', 'shopbuilder' ),
2045 - ],
2046 - [
2047 - 'value' => 'twitter',
2048 - 'label' => esc_html__( 'Twitter', 'shopbuilder' ),
2049 - ],
2050 - [
2051 - 'value' => 'linkedin',
2052 - 'label' => esc_html__( 'Linkedin', 'shopbuilder' ),
2053 - ],
2054 - [
2055 - 'value' => 'pinterest',
2056 - 'label' => esc_html__( 'Pinterest', 'shopbuilder' ),
2057 - ],
2058 - [
2059 - 'value' => 'skype',
2060 - 'label' => esc_html__( 'Skype', 'shopbuilder' ),
2061 - ],
2062 - [
2063 - 'value' => 'whatsapp',
2064 - 'label' => esc_html__( 'Whatsapp', 'shopbuilder' ),
2065 - ],
2066 - [
2067 - 'value' => 'reddit',
2068 - 'label' => esc_html__( 'Reddit', 'shopbuilder' ),
2069 - ],
2070 - [
2071 - 'value' => 'telegram',
2072 - 'label' => esc_html__( 'Telegram', 'shopbuilder' ),
2073 - ],
2074 - ]
2075 - );
2076 - }
2077 -
2078 - /**
2079 - * Get Social Share link HTML.
2080 - *
2081 - * @param int $id Post ID.
2082 - * @param array $types Preset type.
2083 - * @param string $preset Style type.
2084 - * @param boolean $show_icon Show icon.
2085 - * @param boolean $show_text Show text.
2086 - *
2087 - * @return string
2088 - */
2089 - public static function get_social_share_html( int $id, array $types, string $preset = 'default', $show_icon = true, $show_text = true ) {
2090 - $attr = [ 'postid' => $id ];
2091 - $output = '';
2092 -
2093 - if ( empty( $types ) ) {
2094 - return $output;
2095 - }
2096 -
2097 - foreach ( $types as $type ) {
2098 - $link = [];
2099 - $link['type'] = $type['share_items'];
2100 - $link['class'] = '';
2101 - $link['img'] = apply_filters( 'rtsb/elements/share/default_img', '', $id, $link );
2102 -
2103 - if ( 'site' === $id ) {
2104 - $link['url'] = home_url();
2105 - $link['title'] = wp_strip_all_tags( get_bloginfo( 'name' ) );
2106 - } elseif ( 0 === strpos( $id, 'http' ) ) {
2107 - $link['url'] = $id;
2108 - $link['title'] = '';
2109 - } else {
2110 - $link['url'] = get_permalink( $id );
2111 - $link['title'] = wp_strip_all_tags( get_the_title( $id ) );
2112 -
2113 - if ( has_post_thumbnail( $id ) ) {
2114 - $link['img'] = wp_get_attachment_image_url( get_post_thumbnail_id( $id ), 'full' );
2115 - }
2116 -
2117 - $link['img'] = apply_filters( 'rtsb/elements/share/single_img', $link['img'], $id, $link );
2118 - }
2119 -
2120 - $link['url'] = apply_filters( 'rtsb/elements/share/url', $link['url'], $link );
2121 -
2122 - switch ( $type['share_items'] ) {
2123 - case 'facebook':
2124 - $link['link'] = esc_url( 'https://www.facebook.com/sharer/sharer.php?u=' . $link['url'] . '&display=popup&ref=plugin&src=share_button' );
2125 - $link['icon'] = '<svg xmlns="http://www.w3.org/2000/svg" width="18.8125" height="32" viewBox="0 0 602 1024"><path d="M548 6.857v150.857h-89.714q-49.143 0-66.286 20.571t-17.143 61.714v108h167.429l-22.286 169.143h-145.143v433.714h-174.857v-433.714h-145.714v-169.143h145.714v-124.571q0-106.286 59.429-164.857t158.286-58.571q84 0 130.286 6.857z"></path></svg>';
2126 - $link['attr_title'] = esc_html__( 'Share on Facebook', 'shopbuilder' );
2127 - $link['social_network'] = 'Facebook';
2128 - $link['social_action'] = 'Share';
2129 - break;
2130 - case 'twitter':
2131 - $link['link'] = esc_url( 'https://twitter.com/intent/tweet?text=' . htmlspecialchars( rawurlencode( html_entity_decode( $link['title'], ENT_COMPAT, 'UTF-8' ) ), ENT_COMPAT, 'UTF-8' ) . '&url=' . $link['url'] );
2132 - $link['icon'] = '<svg width="24" height="24" viewBox="0 0 1200 1227" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M714.163 519.284L1160.89 0H1055.03L667.137 450.887L357.328 0H0L468.492 681.821L0 1226.37H105.866L515.491 750.218L842.672 1226.37H1200L714.137 519.284H714.163ZM569.165 687.828L521.697 619.934L144.011 79.6944H306.615L611.412 515.685L658.88 583.579L1055.08 1150.3H892.476L569.165 687.854V687.828Z" /></svg>';
2133 - $link['attr_title'] = esc_html__( 'Share on Twitter', 'shopbuilder' );
2134 - $link['social_network'] = 'Twitter';
2135 - $link['social_action'] = 'Tweet';
2136 - break;
2137 - case 'pinterest':
2138 - $link['link'] = esc_url( 'https://pinterest.com/pin/create/button/?url=' . $link['url'] . '&media=' . $link['img'] . '&description=' . $link['title'] );
2139 - $link['icon'] = '<svg xmlns="http://www.w3.org/2000/svg" width="22.84375" height="32" viewBox="0 0 731 1024"><path d="M0 341.143q0-61.714 21.429-116.286t59.143-95.143 86.857-70.286 105.714-44.571 115.429-14.857q90.286 0 168 38t126.286 110.571 48.571 164q0 54.857-10.857 107.429t-34.286 101.143-57.143 85.429-82.857 58.857-108 22q-38.857 0-77.143-18.286t-54.857-50.286q-5.714 22.286-16 64.286t-13.429 54.286-11.714 40.571-14.857 40.571-18.286 35.714-26.286 44.286-35.429 49.429l-8 2.857-5.143-5.714q-8.571-89.714-8.571-107.429 0-52.571 12.286-118t38-164.286 29.714-116q-18.286-37.143-18.286-96.571 0-47.429 29.714-89.143t75.429-41.714q34.857 0 54.286 23.143t19.429 58.571q0 37.714-25.143 109.143t-25.143 106.857q0 36 25.714 59.714t62.286 23.714q31.429 0 58.286-14.286t44.857-38.857 32-54.286 21.714-63.143 11.429-63.429 3.714-56.857q0-98.857-62.571-154t-163.143-55.143q-114.286 0-190.857 74t-76.571 187.714q0 25.143 7.143 48.571t15.429 37.143 15.429 26 7.143 17.429q0 16-8.571 41.714t-21.143 25.714q-1.143 0-9.714-1.714-29.143-8.571-51.714-32t-34.857-54-18.571-61.714-6.286-60.857z"></path></svg>';
2140 - $link['attr_title'] = esc_html__( 'Share on Pinterest', 'shopbuilder' );
2141 - $link['social_network'] = 'Pinterest';
2142 - $link['social_action'] = 'Pin';
2143 - break;
2144 - case 'linkedin':
2145 - $link['link'] = esc_url( 'https://www.linkedin.com/shareArticle?url=' . $link['url'] . '&title=' . $link['title'] );
2146 - $link['icon'] = '<svg xmlns="http://www.w3.org/2000/svg" width="27.4375" height="32" viewBox="0 0 878 1024"><path d="M199.429 357.143v566.286h-188.571v-566.286h188.571zM211.429 182.286q0.571 41.714-28.857 69.714t-77.429 28h-1.143q-46.857 0-75.429-28t-28.571-69.714q0-42.286 29.429-70t76.857-27.714 76 27.714 29.143 70zM877.714 598.857v324.571h-188v-302.857q0-60-23.143-94t-72.286-34q-36 0-60.286 19.714t-36.286 48.857q-6.286 17.143-6.286 46.286v316h-188q1.143-228 1.143-369.714t-0.571-169.143l-0.571-27.429h188v82.286h-1.143q11.429-18.286 23.429-32t32.286-29.714 49.714-24.857 65.429-8.857q97.714 0 157.143 64.857t59.429 190z"></path></svg>';
2147 - $link['attr_title'] = esc_html__( 'Share on LinkedIn', 'shopbuilder' );
2148 - $link['social_network'] = 'LinkedIn';
2149 - $link['social_action'] = 'Share';
2150 - break;
2151 - case 'skype':
2152 - $link['link'] = esc_url( 'https://web.skype.com/share?url=' . $link['url'] );
2153 - $link['icon'] = '<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px" height="24px" viewBox="0 0 24 24" enable-background="new 0 0 24 24" xml:space="preserve" class="eapps-social-share-buttons-item-icon"> <path d="M23.016,13.971c0.111-0.638,0.173-1.293,0.173-1.963 c0-6.213-5.014-11.249-11.199-11.249c-0.704,0-1.393,0.068-2.061,0.193C8.939,0.348,7.779,0,6.536,0C2.926,0,0,2.939,0,6.565 c0,1.264,0.357,2.443,0.973,3.445c-0.116,0.649-0.18,1.316-0.18,1.999c0,6.212,5.014,11.25,11.198,11.25 c0.719,0,1.419-0.071,2.099-0.201C15.075,23.656,16.229,24,17.465,24C21.074,24,24,21.061,24,17.435 C24,16.163,23.639,14.976,23.016,13.971z M12.386,19.88c-3.19,0-6.395-1.453-6.378-3.953c0.005-0.754,0.565-1.446,1.312-1.446 c1.877,0,1.86,2.803,4.85,2.803c2.098,0,2.814-1.15,2.814-1.95c0-2.894-9.068-1.12-9.068-6.563c0-2.945,2.409-4.977,6.196-4.753 c3.61,0.213,5.727,1.808,5.932,3.299c0.102,0.973-0.543,1.731-1.662,1.731c-1.633,0-1.8-2.188-4.613-2.188 c-1.269,0-2.341,0.53-2.341,1.679c0,2.402,9.014,1.008,9.014,6.295C18.441,17.882,16.012,19.88,12.386,19.88z"></path> </svg>';
2154 - $link['attr_title'] = esc_html__( 'Share on Skype', 'shopbuilder' );
2155 - $link['social_network'] = 'Skype';
2156 - $link['social_action'] = 'Skype';
2157 - break;
2158 - case 'whatsapp':
2159 - $link['link'] = esc_url( 'https://wa.me/?text=' . $link['title'] . ' ' . $link['url'] );
2160 - $link['icon'] = '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-whatsapp" viewBox="0 0 16 16"> <path d="M13.601 2.326A7.854 7.854 0 0 0 7.994 0C3.627 0 .068 3.558.064 7.926c0 1.399.366 2.76 1.057 3.965L0 16l4.204-1.102a7.933 7.933 0 0 0 3.79.965h.004c4.368 0 7.926-3.558 7.93-7.93A7.898 7.898 0 0 0 13.6 2.326zM7.994 14.521a6.573 6.573 0 0 1-3.356-.92l-.24-.144-2.494.654.666-2.433-.156-.251a6.56 6.56 0 0 1-1.007-3.505c0-3.626 2.957-6.584 6.591-6.584a6.56 6.56 0 0 1 4.66 1.931 6.557 6.557 0 0 1 1.928 4.66c-.004 3.639-2.961 6.592-6.592 6.592zm3.615-4.934c-.197-.099-1.17-.578-1.353-.646-.182-.065-.315-.099-.445.099-.133.197-.513.646-.627.775-.114.133-.232.148-.43.05-.197-.1-.836-.308-1.592-.985-.59-.525-.985-1.175-1.103-1.372-.114-.198-.011-.304.088-.403.087-.088.197-.232.296-.346.1-.114.133-.198.198-.33.065-.134.034-.248-.015-.347-.05-.099-.445-1.076-.612-1.47-.16-.389-.323-.335-.445-.34-.114-.007-.247-.007-.38-.007a.729.729 0 0 0-.529.247c-.182.198-.691.677-.691 1.654 0 .977.71 1.916.81 2.049.098.133 1.394 2.132 3.383 2.992.47.205.84.326 1.129.418.475.152.904.129 1.246.08.38-.058 1.171-.48 1.338-.943.164-.464.164-.86.114-.943-.049-.084-.182-.133-.38-.232z"/> </svg>';
2161 - $link['attr_title'] = esc_html__( 'Share on Whatsapp', 'shopbuilder' );
2162 - $link['social_network'] = 'Whatsapp';
2163 - $link['social_action'] = 'Share';
2164 - break;
2165 - case 'reddit':
2166 - $link['link'] = esc_url( 'https://reddit.com/submit?url=' . $link['url'] . '&title=' . $link['title'] );
2167 - $link['icon'] = '<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512"><title>ionicons-v5_logos</title><path d="M324,256a36,36,0,1,0,36,36A36,36,0,0,0,324,256Z"/><circle cx="188" cy="292" r="36" transform="translate(-97.43 94.17) rotate(-22.5)"/><path d="M496,253.77c0-31.19-25.14-56.56-56-56.56a55.72,55.72,0,0,0-35.61,12.86c-35-23.77-80.78-38.32-129.65-41.27l22-79L363.15,103c1.9,26.48,24,47.49,50.65,47.49,28,0,50.78-23,50.78-51.21S441,48,413,48c-19.53,0-36.31,11.19-44.85,28.77l-90-17.89L247.05,168.4l-4.63.13c-50.63,2.21-98.34,16.93-134.77,41.53A55.38,55.38,0,0,0,72,197.21c-30.89,0-56,25.37-56,56.56a56.43,56.43,0,0,0,28.11,49.06,98.65,98.65,0,0,0-.89,13.34c.11,39.74,22.49,77,63,105C146.36,448.77,199.51,464,256,464s109.76-15.23,149.83-42.89c40.53-28,62.85-65.27,62.85-105.06a109.32,109.32,0,0,0-.84-13.3A56.32,56.32,0,0,0,496,253.77ZM414,75a24,24,0,1,1-24,24A24,24,0,0,1,414,75ZM42.72,253.77a29.6,29.6,0,0,1,29.42-29.71,29,29,0,0,1,13.62,3.43c-15.5,14.41-26.93,30.41-34.07,47.68A30.23,30.23,0,0,1,42.72,253.77ZM390.82,399c-35.74,24.59-83.6,38.14-134.77,38.14S157,423.61,121.29,399c-33-22.79-51.24-52.26-51.24-83A78.5,78.5,0,0,1,75,288.72c5.68-15.74,16.16-30.48,31.15-43.79a155.17,155.17,0,0,1,14.76-11.53l.3-.21,0,0,.24-.17c35.72-24.52,83.52-38,134.61-38s98.9,13.51,134.62,38l.23.17.34.25A156.57,156.57,0,0,1,406,244.92c15,13.32,25.48,28.05,31.16,43.81a85.44,85.44,0,0,1,4.31,17.67,77.29,77.29,0,0,1,.6,9.65C442.06,346.77,423.86,376.24,390.82,399Zm69.6-123.92c-7.13-17.28-18.56-33.29-34.07-47.72A29.09,29.09,0,0,1,440,224a29.59,29.59,0,0,1,29.41,29.71A30.07,30.07,0,0,1,460.42,275.1Z"/><path d="M323.23,362.22c-.25.25-25.56,26.07-67.15,26.27-42-.2-66.28-25.23-67.31-26.27h0a4.14,4.14,0,0,0-5.83,0l-13.7,13.47a4.15,4.15,0,0,0,0,5.89h0c3.4,3.4,34.7,34.23,86.78,34.45,51.94-.22,83.38-31.05,86.78-34.45h0a4.16,4.16,0,0,0,0-5.9l-13.71-13.47a4.13,4.13,0,0,0-5.81,0Z"/></svg>';
2168 - $link['attr_title'] = esc_html__( 'Share on Reddit', 'shopbuilder' );
2169 - $link['social_network'] = 'Reddit';
2170 - $link['social_action'] = 'Share';
2171 - break;
2172 - case 'telegram':
2173 - $link['link'] = esc_url( 'https://telegram.me/share/url?text=' . $link['title'] . '&url=' . $link['url'] );
2174 - $link['icon'] = '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-telegram" viewBox="0 0 16 16"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8.287 5.906c-.778.324-2.334.994-4.666 2.01-.378.15-.577.298-.595.442-.03.243.275.339.69.47l.175.055c.408.133.958.288 1.243.294.26.006.549-.1.868-.32 2.179-1.471 3.304-2.214 3.374-2.23.05-.012.12-.026.166.016.047.041.042.12.037.141-.03.129-1.227 1.241-1.846 1.817-.193.18-.33.307-.358.336a8.154 8.154 0 0 1-.188.186c-.38.366-.664.64.015 1.088.327.216.589.393.85.571.284.194.568.387.936.629.093.06.183.125.27.187.331.236.63.448.997.414.214-.02.435-.22.547-.82.265-1.417.786-4.486.906-5.751a1.426 1.426 0 0 0-.013-.315.337.337 0 0 0-.114-.217.526.526 0 0 0-.31-.093c-.3.005-.763.166-2.984 1.09z"/> </svg>';
2175 - $link['attr_title'] = esc_html__( 'Share on Telegram', 'shopbuilder' );
2176 - $link['social_network'] = 'Telegram';
2177 - $link['social_action'] = 'Share';
2178 - break;
2179 - }
2180 -
2181 - $link['label'] = $type['share_text'];
2182 - $link['target'] = '_blank';
2183 - $link['rel'] = 'nofollow noopener noreferrer';
2184 -
2185 - $data = '';
2186 - $link = apply_filters( 'rtsb/elements/share/share_link', $link, $id, $preset );
2187 - $icon = apply_filters( 'rtsb/elements/share/share_icon', $link['icon'], $preset );
2188 - $target = ! empty( $link['target'] ) ? ' target="' . esc_attr( $link['target'] ) . '" ' : '';
2189 - $rel = ! empty( $link['rel'] ) ? ' rel="' . esc_attr( $link['rel'] ) . '" ' : '';
2190 - $attr_title = ! empty( $link['attr_title'] ) ? ' title="' . esc_attr( $link['attr_title'] ) . '" ' : '';
2191 - $elements = [];
2192 -
2193 - // Add classes.
2194 - $css_classes = [
2195 - 'rtsb-share-btn',
2196 - sanitize_html_class( $link['type'] ),
2197 - ];
2198 - $css_classes = array_merge( $css_classes, explode( ' ', $link['class'] ) );
2199 - $css_classes = array_map( 'sanitize_html_class', $css_classes );
2200 - $css_classes = implode( ' ', array_filter( $css_classes ) );
2201 -
2202 - unset( $attr['pin-do'], $attr['action'] );
2203 -
2204 - if ( 'pinterest' === $type['share_items'] ) {
2205 - $attr['pin-do'] = 'none';
2206 - }
2207 -
2208 - if ( 'whatsapp' === $type['share_items'] ) {
2209 - $attr['action'] = 'share/whatsapp/share';
2210 - }
2211 -
2212 - $attr = apply_filters( 'rtsb/elements/share/link_data', $attr, $link, $id );
2213 -
2214 - if ( ! empty( $attr ) ) {
2215 - foreach ( $attr as $key => $val ) {
2216 - $data .= ' data-' . sanitize_html_class( $key ) . '="' . esc_attr( $val ) . '"';
2217 - }
2218 - }
2219 -
2220 - $additional_attr = apply_filters( 'rtsb/elements/share/additional_attr', [], $link, $id, $preset );
2221 -
2222 - if ( ! empty( $additional_attr ) ) {
2223 - $attr_output = join( ' ', $additional_attr );
2224 -
2225 - if ( ! empty( $data ) ) {
2226 - $attr_output = ' ' . $attr_output;
2227 - }
2228 -
2229 - $data .= $attr_output;
2230 - }
2231 -
2232 - $elements['wrapper_start'] = sprintf(
2233 - '<li class="rtsb-share-item"><a href="%s"%s%s%s class="%s"%s>',
2234 - ! empty( $link['link'] ) ? esc_attr( $link['link'] ) : '',
2235 - $attr_title,
2236 - $target,
2237 - $rel,
2238 - $css_classes,
2239 - $data
2240 - );
2241 - $elements['wrapper_end'] = '</a></li>';
2242 -
2243 - $elements['icon'] = $show_icon ? '<span class="rtsb-share-icon">' . ( ! empty( $icon ) ? $icon : null ) . '</span>' : null;
2244 - $elements['label'] = $show_text && ! empty( $link['label'] ) ? '<span class="rtsb-share-label">' . $link['label'] . '</span>' : null;
2245 - $elements['icon_label'] = '<span class="rtsb-share-icon-label">' . $elements['icon'] . $elements['label'] . '</span>';
2246 - $elements = apply_filters( 'rtsb/elements/share/output_elements', $elements, $link, $id );
2247 -
2248 - $output .= $elements['wrapper_start'] . $elements['icon_label'] . $elements['wrapper_end'];
2249 - }
2250 -
2251 - return apply_filters( 'rtsb/elements/share/list_output', $output );
2252 - }
2253 -
2254 - /**
2255 - * Social Share Platforms.
2256 - *
2257 - * @return mixed|null
2258 - */
2259 - public static function is_module_active( $module ) {
2260 - $modulelist = ModuleList::instance()->get_data();
2261 - if ( ! empty( $modulelist[ $module ]['active'] ) ) {
2262 - return true;
2263 - }
2264 - }
2265 -
2266 - /***
2267 - * Save Settings data
2268 - *
2269 - * @param $section_id
2270 - * @param $block_id
2271 - * @param $rawOptions
2272 - *
2273 - * @return array
2274 - */
2275 - public static function set_options( $section_id = '', $block_id = '', $rawOptions = [] ) {
2276 - $section_id = ! empty( $section_id ) ? sanitize_text_field( wp_unslash( $section_id ) ) : '';
2277 - $block_id = ! empty( $block_id ) ? sanitize_text_field( wp_unslash( $block_id ) ) : '';
2278 - $rawOptions = ! empty( $rawOptions ) ? $rawOptions : [];
2279 - $results = [
2280 - 'status' => true,
2281 - 'message' => '',
2282 - ];
2283 - if ( ! $section_id || ! $block_id ) {
2284 - $results['status'] = false;
2285 - $results['message'] = esc_html__( 'Section , block or options may be empty', 'shopbuilder' );
2286 -
2287 - return $results;
2288 - }
2289 - $sections = Settings::instance()->get_sections();
2290 - if ( empty( $sections[ $section_id ] ) || empty( $sections[ $section_id ]['list'][ $block_id ] ) ) {
2291 - $results['status'] = false;
2292 - $results['message'] = esc_html__( 'No section or block found with given data', 'shopbuilder' );
2293 -
2294 - return $results;
2295 - }
2296 -
2297 - $options = DataModel::source()->get_option( $section_id, [], false );
2298 - $changed = false;
2299 - $fields = [];
2300 - if ( isset( $sections[ $section_id ]['list'][ $block_id ]['fields'] ) && ! empty( $sections[ $section_id ]['list'][ $block_id ]['fields'] ) ) {
2301 - $fields = $sections[ $section_id ]['list'][ $block_id ]['fields'];
2302 - }
2303 -
2304 - if ( empty( $fields ) ) {
2305 - if ( isset( $rawOptions['active'] ) ) {
2306 - $changed = true;
2307 - $options[ $block_id ]['active'] = 'on' === $rawOptions['active'] ? 'on' : '';
2308 - }
2309 - } else {
2310 - foreach ( $rawOptions as $raw_option_key => $raw_value ) {
2311 - if ( $raw_option_key === 'active' ) {
2312 - $changed = true;
2313 - $options[ $block_id ]['active'] = $sections[ $section_id ]['list'][ $block_id ]['active'] = 'on' === $raw_value ? 'on' : '';
2314 - } else {
2315 - if ( isset( $fields[ $raw_option_key ] ) ) {
2316 - $field = $fields[ $raw_option_key ];
2317 - if ( $field['type'] === 'switch' ) {
2318 - $value = 'on' === $raw_value ? 'on' : '';
2319 - } elseif ( 'repeaters' === $field['type'] ) {
2320 - $the_value = [];
2321 - $rep_title = [];
2322 - if ( ! empty( $raw_value ) && is_array( $raw_value ) ) {
2323 - foreach ( $raw_value as $key => $value ) {
2324 - $the_value_decoded = json_decode( stripslashes_deep( $value ) );
2325 - $cr = $the_value_decoded->title ?? '';
2326 - if ( in_array( $cr, $rep_title, true ) ) {
2327 - continue;
2328 - }
2329 - $rep_title[] = $cr;
2330 - $the_value[] = $the_value_decoded;
2331 - }
2332 - } elseif ( ! empty( $raw_value ) && is_string( $raw_value ) ) {
2333 - $the_value = $raw_value;
2334 - }
2335 - $value = wp_json_encode( $the_value );
2336 - } elseif ( 'product_addons_special_settings' === $field['type'] ) {
2337 - $paddons_value = [];
2338 - // error_log(print_r( $raw_value , true) . "\n\n", 3, __DIR__ . '/log.txt');
2339 - if ( is_array( $raw_value ) ) {
2340 - foreach ( $raw_value as $key => $value ) {
2341 - $paddons_value[] = json_decode( stripslashes( $value ), true );
2342 - }
2343 - }
2344 - $value = wp_json_encode( $paddons_value );
2345 - } else {
2346 - if ( ! empty( $field['multiple'] ) || in_array( $field['type'], [ 'checkbox', 'search_and_multi_select' ] ) ) {
2347 - if ( isset( $raw_value ) && is_array( $raw_value ) ) {
2348 - if ( ! empty( $field['sanitize_fn'] ) && is_callable( $field['sanitize_fn'] ) ) {
2349 - $value = array_map( $field['sanitize_fn'], $raw_value );
2350 - } else {
2351 - $value = array_map( 'sanitize_text_field', $raw_value );
2352 - }
2353 - } else {
2354 - $value = [];
2355 - }
2356 - } else {
2357 - if ( ! empty( $field['sanitize_fn'] ) ) {
2358 - if ( is_callable( $field['sanitize_fn'] ) ) {
2359 - $value = $field['sanitize_fn']( $raw_value );
2360 - } elseif ( 'pass_all' === $field['sanitize_fn'] ) {
2361 - $value = $raw_value;
2362 - } else {
2363 - $value = $field['sanitize_fn']( $raw_value );
2364 - }
2365 - } else {
2366 - $value = sanitize_text_field( $raw_value );
2367 - }
2368 - }
2369 - }
2370 - $options[ $block_id ][ $raw_option_key ] = $sections[ $section_id ]['list'][ $block_id ]['fields'][ $raw_option_key ]['value'] = $value ?? null;
2371 - $changed = true;
2372 - }
2373 - }
2374 - }
2375 - }
2376 - if ( ! $changed ) {
2377 - $results['status'] = false;
2378 - $results['message'] = esc_html__( 'No changes found for update', 'shopbuilder' );
2379 -
2380 - return $results;
2381 - }
2382 -
2383 - DataModel::source()->set_option( $section_id, $options );
2384 -
2385 - $results['status'] = true;
2386 - $results['message'] = esc_html__( 'Successfully Saved', 'shopbuilder' );
2387 - $results['sections'] = $sections;
2388 -
2389 - return $results;
2390 - }
2391 -
2392 - /***
2393 - * @param $meta_key
2394 - * @param $meta_value
2395 - *
2396 - * @return mixed|void
2397 - *
2398 - *
2399 - * public static function get_post_id_by_meta_key_and_value( $meta_key, $meta_value ) {
2400 - * if( ! $meta_key || ! $meta_value ){
2401 - * return;
2402 - * }
2403 - * global $wpdb;
2404 - * $prepare_guery = $wpdb->prepare( "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '%s' and meta_value = '%d'", $meta_key, $meta_value );
2405 - * $the_products = $wpdb->get_col( $prepare_guery );
2406 - * if( count( $the_products ) > 0 ){
2407 - * return $the_products[0];
2408 - * }
2409 - * return;
2410 - * }
2411 - */
2412 - public static function count_products_by_taxonomies( $terms, $taxonomy = 'product_cat' ) {
2413 - if ( empty( $terms ) || ! is_array( $terms ) ) {
2414 - return;
2415 - }
2416 -
2417 - $args = [
2418 - 'limit' => -1,
2419 - 'return' => 'ids',
2420 - ];
2421 -
2422 - if ( 'product_cat' === $taxonomy ) {
2423 - $args['product_category_id'] = $terms;
2424 - } else {
2425 - $args['product_tag_id'] = $terms;
2426 - }
2427 -
2428 - $query = new WC_Product_Query( $args );
2429 - return ! empty( $query->get_products() ) ? count( $query->get_products() ) : 0;
2430 - }
2431 -
2432 - /**
2433 - * Check if product filters widget has ajax.
2434 - *
2435 - * @param string $page Page name.
2436 - *
2437 - * @return bool
2438 - */
2439 - public static function product_filters_has_ajax( $page ) {
2440 - if ( empty( $page ) ) {
2441 - return false;
2442 - }
2443 -
2444 - if ( 'page' === get_post_type() ) {
2445 - return false;
2446 - }
2447 -
2448 - $id = BuilderFns::is_builder_preview() ? get_the_ID() : BuilderFns::builder_page_id_by_type( $page );
2449 - if ( ! $id ) {
2450 - return false;
2451 - }
2452 - $cache_key = 'product_filters_has_ajax_' . $id;
2453 - if ( isset( self::$cache[ $cache_key ] ) ) {
2454 - return self::$cache[ $cache_key ];
2455 - }
2456 - $elmap = ElementorDataMap::instance();
2457 - $ajax = [];
2458 -
2459 - foreach ( $elmap->get_widget_data( 'rtsb-ajax-product-filters', [], $id ) as $data ) {
2460 - $ajax[] = isset( $data['settings']['ajax_mode'] ) ? false : true;
2461 - }
2462 -
2463 - self::$cache[ $cache_key ] = ! empty( $ajax[0] );
2464 - return ! empty( $ajax[0] );
2465 - }
2466 -
2467 - /**
2468 - * Check if product has applied filter.
2469 - *
2470 - * @param string $page Page name.
2471 - *
2472 - * @return bool
2473 - */
2474 - public static function product_has_applied_filters( $page ) {
2475 - if ( empty( $page ) ) {
2476 - return false;
2477 - }
2478 -
2479 - $id = BuilderFns::is_builder_preview() ? get_the_ID() : BuilderFns::builder_page_id_by_type( $page );
2480 - $elmap = ElementorDataMap::instance();
2481 - $ajax = [];
2482 - if ( ! $id ) {
2483 - return false;
2484 - }
2485 - foreach ( $elmap->get_widget_data( 'rtsb-ajax-product-filters', [], $id ) as $data ) {
2486 - $ajax[] = ! isset( $data['settings']['active_filter'] );
2487 -
2488 - }
2489 -
2490 - return ! empty( $ajax[0] );
2491 - }
2492 -
2493 - /**
2494 - * Get WooCommerce product categories.
2495 - *
2496 - * @param string|null $search_query The search string for category names.
2497 - *
2498 - * @return array An array of product categories with 'value' and 'label' keys.
2499 - */
2500 - public static function products_category_query( $search_query = null ) {
2501 - if ( ! is_admin() ) {
2502 - return [];
2503 - }
2504 -
2505 - $cache_key = 'rtsb_product_categories_' . md5( serialize( $search_query ) );
2506 -
2507 - if ( isset( self::$cache[ $cache_key ] ) ) {
2508 - return self::$cache[ $cache_key ];
2509 - }
2510 - $results = wp_cache_get( $cache_key, 'shopbuilder' );
2511 - if ( ! $results ) {
2512 - global $wpdb;
2513 - $sql = "SELECT t.term_id, t.name
2514 - FROM {$wpdb->terms} t
2515 - JOIN {$wpdb->term_taxonomy} tt ON t.term_id = tt.term_id
2516 - WHERE tt.taxonomy = 'product_cat'";
2517 -
2518 - if ( $search_query ) {
2519 - $sql .= ' AND t.name LIKE %s';
2520 - $prepared_sql = $wpdb->prepare( $sql, '%' . $wpdb->esc_like( $search_query ) . '%' ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
2521 - } else {
2522 - $prepared_sql = $sql; // No need for placeholders.
2523 - }
2524 -
2525 - $results = $wpdb->get_results( $prepared_sql ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.PreparedSQL.NotPrepared
2526 - // Cache the results in the object cache for future use.
2527 - wp_cache_set( $cache_key, $results, 'shopbuilder' ); // Adjust the expiration time as needed.
2528 - Cache::set_data_cache_key( $cache_key );
2529 - }
2530 -
2531 - $cats = [];
2532 - if ( ! is_array( $results ) && ! count( $results ) ) {
2533 - return $cats;
2534 - }
2535 - foreach ( $results as $row ) {
2536 - $category_id = $row->term_id;
2537 - $category_title = $row->name;
2538 -
2539 - $cats[] = [
2540 - 'value' => $category_id,
2541 - 'label' => $category_title,
2542 - ];
2543 - }
2544 -
2545 - // Cache the results in a static variable for the next call.
2546 - self::$cache[ $cache_key ] = $cats;
2547 - return $cats;
2548 - }
2549 -
2550 - /**
2551 - * @param string $search_query Search query.
2552 - *
2553 - * @return array
2554 - */
2555 - public static function get_registered_post_types( $search_query = null ) {
2556 - // Get all registered post types.
2557 - $registered_post_types = get_post_types(
2558 - [
2559 - 'public' => true,
2560 - '_builtin' => false,
2561 - ],
2562 - 'objects'
2563 - );
2564 -
2565 - unset( $registered_post_types['elementor_library'] );
2566 - unset( $registered_post_types['e-landing-page'] );
2567 - unset( $registered_post_types['rtsb_builder'] );
2568 -
2569 - $post_types = [];
2570 -
2571 - // Check if a search query is provided.
2572 - if ( ! empty( $search_query ) ) {
2573 - // Filter post types based on the search query.
2574 - $registered_post_types = array_filter(
2575 - $registered_post_types,
2576 - function ( $post_type ) use ( $search_query ) {
2577 - return stripos( $post_type->labels->singular_name, $search_query ) !== false;
2578 - }
2579 - );
2580 - // Check if 'post' match the search query and include them if they do.
2581 - if ( stripos( 'post', $search_query ) !== false ) {
2582 - $post_types[] = [
2583 - 'value' => 'post',
2584 - 'label' => 'Post',
2585 - ];
2586 - }
2587 - } else {
2588 - $post_types[] = [
2589 - 'value' => 'post',
2590 - 'label' => 'Post',
2591 - ];
2592 - }
2593 -
2594 - // Convert the filtered post types to an array.
2595 - foreach ( $registered_post_types as $post_type ) {
2596 - $post_types[] = [
2597 - 'value' => $post_type->name,
2598 - 'label' => $post_type->labels->singular_name,
2599 - ];
2600 - }
2601 -
2602 - return $post_types;
2603 - }
2604 -
2605 - /**
2606 - * Get Post Types.
2607 - *
2608 - * @param string $search_query Search query.
2609 - *
2610 - * @return array
2611 - */
2612 - public static function get_post_types( $search_query = null, $args = [] ) {
2613 -
2614 - $args = wp_parse_args(
2615 - $args,
2616 - [
2617 - 'post_type' => 'any',
2618 - 'posts_per_page' => 20,
2619 - 'orderby' => 'ID',
2620 - 'order' => 'DESC',
2621 - // 'suppress_filters' => false, // WPML Support, Remove Others Languages.
2622 - ]
2623 - );
2624 -
2625 - if ( 'archive' !== $args['post_type'] ) {
2626 - if ( $search_query ) {
2627 - $args['s'] = $search_query;
2628 - }
2629 - $posts = [];
2630 - $query_results = get_posts( $args );
2631 - foreach ( $query_results as $post ) {
2632 - $posts[] = [
2633 - 'value' => $post->ID,
2634 - 'label' => $post->post_title . ' ( ID ' . $post->ID . ')',
2635 - ];
2636 - }
2637 -
2638 - if ( $search_query ) {
2639 - if ( strpos( '-error 404', $search_query ) ) {
2640 - $posts[] = [
2641 - 'value' => 'error',
2642 - 'label' => __( '404 Error', 'shopbuilder' ),
2643 - ];
2644 - }
2645 - } else {
2646 - if ( 'page' === $args['post_type'] ) {
2647 - $posts[] = [
2648 - 'value' => 'error',
2649 - 'label' => __( '404 Error', 'shopbuilder' ),
2650 - ];
2651 - }
2652 - }
2653 - } else {
2654 - $posts = self::get_registered_post_types( $search_query );
2655 - }
2656 -
2657 - return $posts;
2658 - }
2659 -
2660 - /**
2661 - * Get all Elementor breakpoints.
2662 - *
2663 - * @return array
2664 - */
2665 - public static function get_elementor_breakpoints() {
2666 - return ( new \Elementor\Core\Breakpoints\Manager() )->get_breakpoints_config();
2667 - }
2668 -
2669 - /**
2670 - * Render view.
2671 - *
2672 - * @param string $viewName View name.
2673 - * @param array $args View args.
2674 - * @param boolean $return View return.
2675 - * @return string|void
2676 - */
2677 - public static function renderView( $viewName, $args = [], $return = false ) {
2678 - $viewName = str_replace( '.', '/', $viewName );
2679 -
2680 - if ( ! empty( $args ) && is_array( $args ) ) {
2681 - extract( $args );
2682 - }
2683 -
2684 - $view_file = rtsb()->plugin_path() . '/resources/' . $viewName . '.php';
2685 -
2686 - if ( ! file_exists( $view_file ) ) {
2687 - _doing_it_wrong( __FUNCTION__, sprintf( '<code>%s</code> does not exist.', esc_html( $view_file ) ), '1.7.0' );
2688 -
2689 - return;
2690 - }
2691 -
2692 - if ( $return ) {
2693 - ob_start();
2694 - include $view_file;
2695 -
2696 - return ob_get_clean();
2697 - } else {
2698 - include $view_file;
2699 - }
2700 - }
2701 -
2702 - /**
2703 - * Best selling product query.
2704 - *
2705 - * @param int $minimum_sale Minimum sale/
2706 - * @param int $limit Total limit.
2707 - *
2708 - * @return array|mixed
2709 - */
2710 - public static function best_selling_products_ids( $minimum_sale = 1, $limit = 10 ) {
2711 - $cache_key = 'rtsb_best_selling_products_' . $minimum_sale . '_' . $limit;
2712 - // Check if the data is in the cache.
2713 - if ( isset( self::$cache[ $cache_key ] ) ) {
2714 - return self::$cache[ $cache_key ];
2715 - }
2716 - $cached_data = get_transient( $cache_key );
2717 - if ( $cached_data ) {
2718 - self::$cache[ $cache_key ] = $cached_data;
2719 - return $cached_data;
2720 - }
2721 - global $wpdb;
2722 - $sql = $wpdb->prepare(
2723 - "
2724 - SELECT ID
2725 - FROM {$wpdb->posts} AS p
2726 - LEFT JOIN {$wpdb->postmeta} AS pm ON p.ID = pm.post_id
2727 - WHERE p.post_type = 'product'
2728 - AND p.post_status = 'publish'
2729 - AND pm.meta_key = 'total_sales'
2730 - AND pm.meta_value >= %d
2731 - ORDER BY pm.meta_value + 0 DESC
2732 - LIMIT %d
2733 - ",
2734 - $minimum_sale,
2735 - $limit
2736 - );
2737 - $best_selling = $wpdb->get_col( $sql ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared
2738 - // Cache the result for future use.
2739 - set_transient( $cache_key, $best_selling, DAY_IN_SECONDS );
2740 - self::$cache[ $cache_key ] = $best_selling;
2741 - return $best_selling;
2742 - }
2743 -
2744 - /**
2745 - * @param null|Object $product Product Object.
2746 - * @param int $days_threshold Date String.
2747 - *
2748 - * @return bool
2749 - */
2750 - public static function is_new_product( $product = null, $days_threshold = 30 ) {
2751 - if ( is_null( $product ) ) {
2752 - global $product;
2753 - }
2754 - if ( ! $product instanceof WC_Product ) {
2755 - return false;
2756 - }
2757 -
2758 - $product_id = $product->get_id();
2759 - $days_threshold = ! empty( $days_threshold ) ? $days_threshold : 30;
2760 - $cache_key = 'is_new_product_' . $product_id . '_' . $days_threshold;
2761 -
2762 - if ( isset( self::$cache[ $cache_key ] ) ) {
2763 - return self::$cache[ $cache_key ];
2764 - }
2765 -
2766 - // Get the product publish date.
2767 - $publish_timestamp = strtotime( $product->get_date_created()->date_i18n( 'Y-m-d H:i:s' ) );
2768 -
2769 - // Calculate the difference in days.
2770 - $days_difference = abs( time() - $publish_timestamp ) / ( 60 * 60 * 24 );
2771 -
2772 - // Check if the product is considered new.
2773 - $is_new = $days_difference <= $days_threshold;
2774 -
2775 - // Cache the result for a day.
2776 - self::$cache[ $cache_key ] = $is_new;
2777 -
2778 - return $is_new;
2779 - }
2780 -
2781 - /**
2782 - * Checks if a feature is disabled for guest users based on the provided option.
2783 - *
2784 - * @param string $option The option to retrieve from the item.
2785 - * @param mixed $default The default value if the option is not found.
2786 - *
2787 - * @return bool
2788 - */
2789 - public static function is_guest_feature_disabled( $option, $default ) {
2790 - $disabled = self::get_option( 'general', 'guest_user', $option, $default );
2791 -
2792 - return ! is_user_logged_in() && $disabled;
2793 - }
2794 -
2795 - /**
2796 - * Checks if a feature is disabled for guest users based on the provided option.
2797 - *
2798 - * @param string $option The option to retrieve from the item.
2799 - * @param mixed $default The default value if the option is not found.
2800 - *
2801 - * @return bool
2802 - */
2803 - public static function woocommerce_output_all_notices() {
2804 - if ( function_exists( 'wc_print_notices' ) ) :
2805 - echo '<div class="rtsb-notice">';
2806 - woocommerce_output_all_notices();
2807 - echo '</div>';
2808 - endif;
2809 - }
2810 -
2811 - /**
2812 - * @param object $product Product.
2813 - * @return bool
2814 - */
2815 - public static function is_visible_qty_input( $product = null ) {
2816 - $is_visible_qty = true;
2817 - if ( $product instanceof \WC_Product ) {
2818 - if ( $product->is_sold_individually() ) {
2819 - $is_visible_qty = false;
2820 - } elseif ( $product->managing_stock() ) {
2821 - if ( in_array( $product->get_backorders(), [ 'notify' , 'yes' ], true ) ) {
2822 - $is_visible_qty = true;
2823 - } elseif ( $product->get_stock_quantity() < 2 ) {
2824 - $is_visible_qty = false;
2825 - }
2826 - }
2827 - }
2828 - return $is_visible_qty;
2829 - }
2830 -
2831 - /**
2832 - * @param int $object_id Object id.
2833 - * @param string $element_type element type.
2834 - * @param string|null $current_lang null for current language, default for default languages.
2835 - * @return false|mixed|null
2836 - */
2837 - public static function wpml_object_id( $object_id, $element_type, $current_lang = 'default' ) {
2838 - if ( ! defined( 'ICL_SITEPRESS_VERSION' ) ) {
2839 - return $object_id;
2840 - }
2841 - if ( ! $object_id || ! $element_type ) {
2842 - return $object_id;
2843 - }
2844 - if ( 'default' === $current_lang ) {
2845 - $lang = apply_filters( 'wpml_default_language', null );
2846 - } else {
2847 - $lang = null;
2848 - }
2849 - return apply_filters( 'wpml_object_id', $object_id, $element_type, false, $lang );
2850 - }
2851 -
2852 - /**
2853 - * @return string
2854 - */
2855 - public static function wpml_current_language() {
2856 - $current = apply_filters( 'wpml_current_language', null );
2857 - $default = apply_filters( 'wpml_default_language', null );
2858 - return $default !== $current ? $current : null;
2859 - }
2860 -
2861 - /**
2862 - * Custom icons.
2863 - *
2864 - * @return string[]
2865 - */
2866 - public static function get_custom_icon_names() {
2867 - return [
2868 - 'heart-empty',
2869 - 'heart',
2870 - 'eye',
2871 - 'exchange',
2872 - 'plus',
2873 - 'minus',
2874 - 'avatar',
2875 - 'pay',
2876 - 'share',
2877 - 'clock',
2878 - 'check-alt',
2879 - 'check',
2880 - 'delete',
2881 - 'marker',
2882 - 'list',
2883 - 'list-2',
2884 - 'power',
2885 - 'cart',
2886 - 'cart-2',
2887 - 'cart-3',
2888 - 'downloads',
2889 - 'zoom',
2890 - 'user-edit',
2891 - 'grid',
2892 - 'filter',
2893 - 'billing',
2894 - 'login',
2895 - 'payment',
2896 - 'search',
2897 - 'edit',
2898 - 'coupon',
2899 - 'arrows-cw',
2900 - 'trash-empty',
2901 - ];
2902 - }
2903 -
2904 - /**
2905 - * Flushes rewrite rules.
2906 - *
2907 - * @return void
2908 - */
2909 - public static function maybe_flush_rewrite_rules() {
2910 - add_action( 'wp_loaded', [ __CLASS__, 'flush_rewrite_rules' ] );
2911 - add_action( 'shutdown', [ __CLASS__, 'flush_rewrite_rules_once_more' ] );
2912 - }
2913 -
2914 - /**
2915 - * Flushes rewrite rules if needed.
2916 - *
2917 - * @return void
2918 - */
2919 - public static function flush_rewrite_rules() {
2920 - if ( get_option( 'rtsb_permalinks_need_flush' ) === 'yes' ) {
2921 - flush_rewrite_rules();
2922 - }
2923 -
2924 - if ( get_option( 'rtsb_permalinks_flushed' ) === 'yes' ) {
2925 - flush_rewrite_rules();
2926 - delete_option( 'rtsb_permalinks_flushed' );
2927 - }
2928 - }
2929 -
2930 - /**
2931 - * Flushes rewrite rules if needed for second time.
2932 - *
2933 - * @return void
2934 - */
2935 - public static function flush_rewrite_rules_once_more() {
2936 - if ( get_option( 'rtsb_permalinks_need_flush' ) === 'yes' ) {
2937 - flush_rewrite_rules();
2938 - update_option( 'rtsb_permalinks_flushed', 'yes' );
2939 - delete_option( 'rtsb_permalinks_need_flush' );
2940 - }
2941 - }
2942 -
2943 - /**
2944 - * Social Share Platforms.
2945 - *
2946 - * @return mixed|null
2947 - */
2948 - public static function set_repeater_options( $section_id, $block_id, $option_key, $compare_key, $compare_value, $values ) {
2949 - // $options = self::get_options( $section_id, $block_id );
2950 - $modules = DataModel::source()->get_option( $section_id, [], false );
2951 - if ( empty( $modules[ $block_id ] ) ) {
2952 - return;
2953 - }
2954 - $options = $modules[ $block_id ];
2955 - if ( empty( $options[ $option_key ] ) ) {
2956 - return;
2957 - }
2958 - $repeater_options = json_decode( $options[ $option_key ], true );
2959 - // Check if options are not empty and are in array format.
2960 - if ( ! is_array( $repeater_options ) ) {
2961 - return;
2962 - }
2963 - // Use array_column to get an array of values from $compare_key.
2964 - $column_values = array_column( $repeater_options, $compare_key );
2965 - // Use array_search to find the index of the $compare_value.
2966 - $index = array_search( $compare_value, $column_values, true );
2967 - if ( false === $index ) {
2968 - return;
2969 - }
2970 - $repeater_options[ $index ] = wp_parse_args( $values, $repeater_options[ $index ] );
2971 - $options[ $option_key ] = wp_json_encode( $repeater_options );
2972 - $modules[ $block_id ] = $options;
2973 - DataModel::source()->set_option( $section_id, $modules );
2974 - }
2975 -
2976 -
2977 - /**
2978 - * @param array $ids products id.
2979 - * @return array
2980 - */
2981 - public static function get_available_products_by_ids( $ids = [] ) {
2982 - $ids = array_filter(
2983 - $ids,
2984 - function ( $id ) {
2985 - return 'product' === get_post_type( $id ) && 'publish' === get_post_status( $id );
2986 - }
2987 - );
2988 - return $ids;
2989 - }
2990 -}
1 +<?php
2 +/**
3 + * Fns Helpers class
4 + *
5 + * @package RadiusTheme\SB
6 + */
7 +
8 +namespace RadiusTheme\SB\Helpers;
9 +
10 +// Do not allow directly accessing this file.
11 +if ( ! defined( 'ABSPATH' ) ) {
12 + exit( 'This script cannot be accessed directly.' );
13 +}
14 +
15 +use Elementor\Icons_Manager;
16 +use RadiusTheme\SB\Models\ReSizer;
17 +use RadiusTheme\SB\Models\DataModel;
18 +use RadiusTheme\SB\Models\ModuleList;
19 +use RadiusTheme\SB\Models\Settings;
20 +use WC_Product;
21 +
22 +/**
23 + * Fns class
24 + */
25 +class Fns {
26 + /**
27 + * @param $plugin_slug
28 + * @return bool
29 + */
30 + public static function check_plugin_installed( $plugin_slug ): bool {
31 + $installed_plugins = get_plugins();
32 + return array_key_exists( $plugin_slug, $installed_plugins ) || in_array( $plugin_slug, $installed_plugins, true );
33 + }
34 +
35 + /**
36 + * @param $plugin_slug
37 + * @return bool
38 + */
39 + public static function check_plugin_active( $plugin_slug ): bool {
40 + if ( is_plugin_active( $plugin_slug ) ) {
41 + return true;
42 + }
43 + return false;
44 + }
45 +
46 + /**
47 + * @return bool
48 + */
49 + public static function check_is_block_theme(): bool {
50 + global $wp_version;
51 + return version_compare( $wp_version, '5.9', '>=' ) && function_exists( 'wp_is_block_theme' ) && wp_is_block_theme();
52 + }
53 +
54 + /**
55 + * Verify nonce.
56 + *
57 + * @return bool
58 + */
59 + public static function verify_nonce() {
60 + $nonce = isset( $_REQUEST[ rtsb()->nonceId ] ) ? $_REQUEST[ rtsb()->nonceId ] : null;
61 + $nonceText = rtsb()->nonceText;
62 + if ( wp_verify_nonce( $nonce, $nonceText ) ) {
63 + return true;
64 + }
65 +
66 + return false;
67 + }
68 +
69 + /**
70 + * @param string $template_name Template name.
71 + * @param string $template_path Template path. (default: '').
72 + * @param string $plugin_path Plugin path. (default: ''). fallback file from plugin
73 + *
74 + * @return mixed|void
75 + */
76 + public static function locate_template( $template_name, $template_path = '', $plugin_path = '' ) {
77 + $template_name = $template_name . '.php';
78 + if ( ! $template_path ) {
79 + $template_path = rtsb()->get_template_path();
80 + }
81 + if ( ! $plugin_path ) {
82 + $plugin_path = RTSB_ABSPATH . 'templates/';
83 + }
84 +
85 + $template_rtsb_path = trailingslashit( $template_path ) . $template_name;
86 + $template_path = '/' . $template_name;
87 + $plugin_path = $plugin_path . $template_name;
88 +
89 + $located = locate_template(
90 + apply_filters(
91 + 'rtsb/core/locate_template_files',
92 + [
93 + $template_rtsb_path, // Search in <theme>/shopbuilder/.
94 + $template_path, // Search in <theme>/.
95 + ]
96 + )
97 + );
98 +
99 + if ( ! $located && file_exists( $plugin_path ) ) {
100 + return apply_filters( 'rtsb/core/locate_template', $plugin_path, $template_name );
101 + }
102 +
103 + /**
104 + * APPLY_FILTERS: rtsb/core/locate_template
105 + *
106 + * Filter the location of the templates.
107 + *
108 + * @param string $located Template found
109 + * @param string $path Template path
110 + *
111 + * @return string
112 + */
113 + return apply_filters( 'rtsb/core/locate_template', $located, $template_name );
114 + }
115 +
116 + /**
117 + * Template Content
118 + *
119 + * @param string $template_name Template name.
120 + * @param array $args Arguments. (default: array).
121 + * @param bool $return Whether to return or print the template.
122 + * @param string $template_path Template path. (default: '').
123 + * @param string $plugin_path Fallback path from where file will load if fail to load from template. (default: '').
124 + *
125 + * @return false|string|void
126 + */
127 + public static function load_template( $template_name, array $args = null, $return = false, $template_path = '', $plugin_path = '' ) {
128 + $located = self::locate_template( $template_name, $template_path, $plugin_path );
129 +
130 + if ( ! file_exists( $located ) ) {
131 + // translators: %s template.
132 + self::doing_it_wrong( __FUNCTION__, sprintf( __( '%s does not exist.', 'shopbuilder' ), '<code>' . $located . '</code>' ), '1.0' );
133 +
134 + return;
135 + }
136 +
137 + if ( ! empty( $args ) && is_array( $args ) ) {
138 + $atts = $args;
139 + extract( $args ); // @codingStandardsIgnoreLine
140 + }
141 +
142 + // Allow 3rd party plugin filter template file from their plugin.
143 + $located = apply_filters( 'rtsb/core/get_template', $located, $template_name, $args );
144 +
145 + if ( $return ) {
146 + ob_start();
147 + }
148 +
149 + do_action( 'rtsb/core/before_template_part', $template_name, $located, $args );
150 + include $located;
151 + do_action( 'rtsb/core/after_template_part', $template_name, $located, $args );
152 +
153 + if ( $return ) {
154 + return ob_get_clean();
155 + }
156 + }
157 +
158 + /**
159 + * Verify nonce.
160 + *
161 + * @return string
162 + */
163 + public static function is_woocommerce() {
164 + return is_woocommerce() || is_cart() || is_checkout() || is_account_page();
165 + }
166 +
167 + /**
168 + * Page builder
169 + *
170 + * @param int $post_id post id.
171 + *
172 + * @return string
173 + */
174 + public static function page_edit_with( $post_id ) {
175 + if ( ! $post_id ) {
176 + return '';
177 + }
178 +
179 + $edit_with = get_post_meta( $post_id, '_elementor_edit_mode', true );
180 +
181 + if ( 'builder' === $edit_with ) {
182 + $edit_by = 'elementor';
183 + } else {
184 + $edit_by = 'gutenberg';
185 + }
186 +
187 + return $edit_by;
188 + }
189 +
190 + /**
191 + * Returns default expiration for wishlist cookie
192 + *
193 + * @return int Number of seconds the cookie should last.
194 + */
195 + public static function get_cookie_expiration() {
196 + return intval( apply_filters( 'rtsb/cookie_expiration', 60 * 60 * 24 * 30 ) );
197 + }
198 +
199 + /**
200 + * Create a cookie.
201 + *
202 + * @param string $name Cookie name.
203 + * @param mixed $value Cookie value.
204 + * @param int $time Cookie expiration time.
205 + * @param bool $secure Whether cookie should be available to secured connection only.
206 + * @param bool $httponly Whether cookie should be available to HTTP request only (no js handling).
207 + *
208 + * @return bool
209 + * @since 1.0.0
210 + */
211 + public static function setcookie( $name, $value = [], $time = null, $secure = false, $httponly = false ) {
212 +
213 + if ( ! apply_filters( 'rtsb/set_cookie', true ) || empty( $name ) ) {
214 + return false;
215 + }
216 +
217 + $time = ! empty( $time ) ? $time : time() + self::get_cookie_expiration();
218 +
219 + $value = wp_json_encode( stripslashes_deep( $value ) );
220 + $expiration = apply_filters( 'rtsb/cookie_expiration_time', $time ); // Default 30 days.
221 +
222 + $_COOKIE[ $name ] = $value;
223 + wc_setcookie( $name, $value, $expiration, $secure, $httponly );
224 +
225 + return true;
226 + }
227 +
228 + /**
229 + * Retrieve the value of a cookie.
230 + *
231 + * @param string $name Cookie name.
232 + *
233 + * @return mixed
234 + * @since 1.0.0
235 + */
236 + public static function getcookie( $name ) {
237 + if ( isset( $_COOKIE[ $name ] ) ) {
238 + return json_decode( sanitize_text_field( wp_unslash( $_COOKIE[ $name ] ) ), true );
239 + }
240 +
241 + return [];
242 + }
243 +
244 + /**
245 + * Woocommerce Last product id return
246 + */
247 + public static function get_prepared_product_id() {
248 + // TODO:: Get Product List for select in Create Template Modal .
249 + if ( is_singular( 'product' ) ) {
250 + return get_the_ID();
251 + }
252 + global $wpdb;
253 + $cache_key = 'rtsb_prepared_product_id';
254 + $_post_id = get_transient( $cache_key );
255 + if ( false === $_post_id || 'publish' !== get_post_status( $_post_id ) ) {
256 + delete_transient( $cache_key );
257 + $_post_id = $wpdb->get_var(
258 + $wpdb->prepare( "SELECT MAX(ID) FROM {$wpdb->prefix}posts WHERE post_type = %s AND post_status = %s", 'product', 'publish' )
259 + );
260 + set_transient( $cache_key, $_post_id, 12 * HOUR_IN_SECONDS );
261 + }
262 +
263 + return $_post_id;
264 + }
265 +
266 + /**
267 + * Get the product function.
268 + *
269 + * @return object
270 + */
271 + public static function get_product() {
272 + global $post, $product;
273 + if ( is_singular( 'product' ) && $product instanceof WC_Product ) {
274 + return $product;
275 + }
276 +
277 + return wc_get_product( self::get_prepared_product_id() );
278 + }
279 +
280 + /**
281 + * Error function
282 + *
283 + * @param [type] $function function name.
284 + * @param [type] $message message.
285 + * @param [type] $version version.
286 + *
287 + * @return void
288 + */
289 + public static function doing_it_wrong( $function, $message, $version ) {
290 + $message .= ' Backtrace: ' . wp_debug_backtrace_summary();
291 + _doing_it_wrong( $function, $message, $version );
292 + }
293 +
294 + /**
295 + * @return array
296 + */
297 + public static function get_pages() {
298 + $pages = [];
299 + $rawPages = get_pages();
300 + if ( ! empty( $rawPages ) ) {
301 + foreach ( $rawPages as $page ) {
302 + $pages[ $page->ID ] = $page->post_title;
303 + }
304 + }
305 +
306 + return $pages;
307 + }
308 +
309 + public static function get_section_items( $section_id ) {
310 + if ( ! $section_id ) {
311 + return [];
312 + }
313 +
314 + return DataModel::source()->get_option( $section_id, [] );
315 + }
316 +
317 + public static function get_options( $section_id, $item_id ) {
318 + if ( ! $section_id || ! $item_id ) {
319 + return [];
320 + }
321 + $sections = self::get_section_items( $section_id );
322 +
323 + return isset( $sections[ $item_id ] ) ? $sections[ $item_id ] : [];
324 + }
325 +
326 + /**
327 + * @param string $section_id
328 + * @param string $item_id
329 + * @param string $option_id
330 + * @param null $default EXCEPT multi_checkbox you can provide default value if given option does not set any value
331 + * @param null $type checkbox, multi_checkbox, number
332 + *
333 + * @return bool|int|mixed|null
334 + */
335 + public static function get_option( $section_id, $item_id, $option_id, $default = null, $type = null ) {
336 + $options = self::get_options( $section_id, $item_id );
337 +
338 + if ( $type === 'checkbox' ) {
339 + if ( isset( $options[ $option_id ] ) ) {
340 + return $options[ $option_id ] === 'on';
341 + }
342 +
343 + return $default;
344 + } elseif ( $type === 'multi_checkbox' ) {
345 + return isset( $options[ $option_id ] ) && is_array( $options[ $option_id ] ) && in_array( $default, $options[ $option_id ] );
346 + } elseif ( $type === 'number' ) {
347 + return isset( $options[ $option_id ] ) ? absint( $options[ $option_id ] ) : absint( $default );
348 + }
349 +
350 + return isset( $options[ $option_id ] ) && ! empty( $options[ $option_id ] ) ? $options[ $option_id ] : $default;
351 + }
352 +
353 +
354 + /**
355 + * Create a page and store the ID in an option.
356 + *
357 + * @param mixed $slug Slug for the new page.
358 + * @param array $options ['section_id', 'item_id', 'option_id']Option name to store the page's ID.
359 + * @param string $page_title (default: '') Title for the new page.
360 + * @param string $page_content (default: '') Content for the new page.
361 + * @param int $post_parent (default: 0) Parent for the new page.
362 + * @param string $post_status (default: publish) The post status of the new page.
363 + *
364 + * @return int page ID.
365 + */
366 + public static function create_page( $slug, $options = '', $page_title = '', $page_content = '', $post_parent = 0, $post_status = 'publish' ) {
367 + global $wpdb;
368 +
369 + $option_value = 0;
370 + if ( ! empty( $options ) ) {
371 + if ( is_array( $options ) ) {
372 + $options = wp_parse_args(
373 + $options,
374 + [
375 + 'section_id' => '',
376 + 'item_id' => '',
377 + 'option_id' => '',
378 + ]
379 + );
380 + $option_value = self::get_option( $options['section_id'], $options['item_id'], $options['option_id'], 0, 'number' );
381 + } else {
382 + $option_value = absint( get_option( $options ) );
383 + }
384 + }
385 +
386 + if ( $option_value > 0 ) {
387 + $page_object = get_post( $option_value );
388 +
389 + if ( $page_object && 'page' === $page_object->post_type && ! in_array(
390 + $page_object->post_status,
391 + [
392 + 'pending',
393 + 'trash',
394 + 'future',
395 + 'auto-draft',
396 + ],
397 + true
398 + ) ) {
399 + // Valid page is already in place.
400 + return $page_object->ID;
401 + }
402 + }
403 +
404 + if ( strlen( $page_content ) > 0 ) {
405 + // Search for an existing page with the specified page content (typically a shortcode).
406 + $shortcode = str_replace( [ '<!-- wp:shortcode -->', '<!-- /wp:shortcode -->' ], '', $page_content );
407 + $valid_page_found = $wpdb->get_var( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_type='page' AND post_status NOT IN ( 'pending', 'trash', 'future', 'auto-draft' ) AND post_content LIKE %s LIMIT 1;", "%{$shortcode}%" ) );
408 + } else {
409 + // Search for an existing page with the specified page slug.
410 + $valid_page_found = $wpdb->get_var( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_type='page' AND post_status NOT IN ( 'pending', 'trash', 'future', 'auto-draft' ) AND post_name = %s LIMIT 1;", $slug ) );
411 + }
412 +
413 + $valid_page_found = apply_filters( 'rtsb/core/create_page_id', $valid_page_found, $slug, $page_content, $options );
414 +
415 + if ( $valid_page_found ) {
416 + if ( is_array( $options ) ) {
417 + if ( ! empty( $options['section_id'] ) && $options['item_id'] && $options['option_id'] ) {
418 + $section_items = DataModel::source()->get_option( $options['section_id'], [] );
419 + $section_items[ $options['item_id'] ][ $options['option_id'] ] = $valid_page_found;
420 + DataModel::source()->set_option( $options['section_id'], $section_items );
421 + }
422 + } else {
423 + if ( $options ) {
424 + update_option( $options, $valid_page_found );
425 + }
426 + }
427 +
428 + return $valid_page_found;
429 + }
430 +
431 + // Search for a matching valid trashed page.
432 + if ( strlen( $page_content ) > 0 ) {
433 + // Search for an existing page with the specified page content (typically a shortcode).
434 + $trashed_page_found = $wpdb->get_var( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_type='page' AND post_status = 'trash' AND post_content LIKE %s LIMIT 1;", "%{$page_content}%" ) );
435 + } else {
436 + // Search for an existing page with the specified page slug.
437 + $trashed_page_found = $wpdb->get_var( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_type='page' AND post_status = 'trash' AND post_name = %s LIMIT 1;", $slug ) );
438 + }
439 +
440 + if ( $trashed_page_found ) {
441 + $page_id = $trashed_page_found;
442 + $page_data = [
443 + 'ID' => $page_id,
444 + 'post_status' => $post_status,
445 + ];
446 + wp_update_post( $page_data );
447 + } else {
448 + $page_data = [
449 + 'post_status' => $post_status,
450 + 'post_type' => 'page',
451 + 'post_author' => 1,
452 + 'post_name' => $slug,
453 + 'post_title' => $page_title,
454 + 'post_content' => $page_content,
455 + 'post_parent' => $post_parent,
456 + 'comment_status' => 'closed',
457 + ];
458 + $page_id = wp_insert_post( $page_data );
459 +
460 + do_action( 'rtsb/core/page_created', $page_id, $page_data );
461 + }
462 +
463 + if ( is_array( $options ) ) {
464 + if ( ! empty( $options['section_id'] ) && $options['item_id'] && $options['option_id'] ) {
465 + $section_items = DataModel::source()->get_option( $options['section_id'], [] );
466 + $section_items[ $options['item_id'] ][ $options['option_id'] ] = $page_id;
467 + DataModel::source()->set_option( $options['section_id'], $section_items );
468 + }
469 + } else {
470 + if ( $options ) {
471 + update_option( $options, $page_id );
472 + }
473 + }
474 +
475 + return $page_id;
476 + }
477 +
478 + // TODO:: Need to remove if not used.
479 + public static function get_kses_array() {
480 + return [
481 + 'a' => [
482 + 'class' => [],
483 + 'href' => [],
484 + 'rel' => [],
485 + 'title' => [],
486 + ],
487 + 'abbr' => [
488 + 'title' => [],
489 + ],
490 + 'b' => [],
491 + 'blockquote' => [
492 + 'cite' => [],
493 + ],
494 + 'cite' => [
495 + 'title' => [],
496 + ],
497 + 'code' => [],
498 + 'del' => [
499 + 'datetime' => [],
500 + 'title' => [],
501 + ],
502 + 'dd' => [],
503 + 'div' => [
504 + 'class' => [],
505 + 'title' => [],
506 + 'style' => [],
507 + ],
508 + 'dl' => [],
509 + 'dt' => [],
510 + 'em' => [],
511 + 'h1' => [
512 + 'class' => [],
513 + ],
514 + 'h2' => [
515 + 'class' => [],
516 + ],
517 + 'h3' => [
518 + 'class' => [],
519 + ],
520 + 'h4' => [
521 + 'class' => [],
522 + ],
523 + 'h5' => [
524 + 'class' => [],
525 + ],
526 + 'h6' => [
527 + 'class' => [],
528 + ],
529 + 'i' => [
530 + 'class' => [],
531 + ],
532 + 'img' => [
533 + 'alt' => [],
534 + 'class' => [],
535 + 'height' => [],
536 + 'src' => [],
537 + 'width' => [],
538 + ],
539 + 'li' => [
540 + 'class' => [],
541 + ],
542 + 'ol' => [
543 + 'class' => [],
544 + ],
545 + 'p' => [
546 + 'class' => [],
547 + ],
548 + 'q' => [
549 + 'cite' => [],
550 + 'title' => [],
551 + ],
552 + 'span' => [
553 + 'class' => [],
554 + 'title' => [],
555 + 'style' => [],
556 + ],
557 + 'iframe' => [
558 + 'width' => [],
559 + 'height' => [],
560 + 'scrolling' => [],
561 + 'frameborder' => [],
562 + 'allow' => [],
563 + 'src' => [],
564 + ],
565 + 'strike' => [],
566 + 'br' => [],
567 + 'strong' => [],
568 + 'data-wow-duration' => [],
569 + 'data-wow-delay' => [],
570 + 'data-wallpaper-options' => [],
571 + 'data-stellar-background-ratio' => [],
572 + 'ul' => [
573 + 'class' => [],
574 + ],
575 + ];
576 + }
577 +
578 + // TODO:: Need to remove if not used.
579 + public static function kses( $raw, $allowDanger = false ) {
580 +
581 + if ( function_exists( 'wp_kses' ) && ! $allowDanger ) { // WP is here
582 + return wp_kses( $raw, self::get_kses_array() );
583 + } else {
584 + return $raw;
585 + }
586 + }
587 +
588 + /*
589 + * Escape output of wishlist icon
590 + *
591 + * @param string $data Data to escape.
592 + * @return string Escaped data
593 + */
594 + public static function print_icon( $data ) {
595 + /**
596 + * APPLY_FILTERS: rtsb/core/allowed_icon_html
597 + *
598 + * Filter the allowed HTML for the icons.
599 + *
600 + * @param array $allowed_icon_html Allowed HTML
601 + *
602 + * @return array
603 + */
604 + $allowed_icon_html = apply_filters(
605 + 'rtsb/core/allowed_icon_html',
606 + [
607 + 'i' => [
608 + 'class' => true,
609 + ],
610 + 'img' => [
611 + 'src' => true,
612 + 'alt' => true,
613 + 'width' => true,
614 + 'height' => true,
615 + ],
616 + 'svg' => [
617 + 'class' => true,
618 + 'aria-hidden' => true,
619 + 'aria-labelledby' => true,
620 + 'role' => true,
621 + 'xmlns' => true,
622 + 'width' => true,
623 + 'height' => true,
624 + 'viewbox' => true,
625 + 'stroke' => true,
626 + 'fill' => true,
627 + ],
628 + 'g' => [
629 + 'fill' => true,
630 + ],
631 + 'title' => [
632 + 'title' => true,
633 + ],
634 + 'path' => [
635 + 'd' => true,
636 + 'fill' => true,
637 + 'stroke-width' => true,
638 + 'stroke-linecap' => true,
639 + 'stroke-linejoin' => true,
640 + ],
641 + ]
642 + );
643 +
644 + echo wp_kses( $data, $allowed_icon_html );
645 + }
646 +
647 + /**
648 + * Prints HTMl.
649 + *
650 + * @param string $html HTML.
651 + * @param bool $allHtml All HTML.
652 + *
653 + * @return void
654 + */
655 + public static function print_html( $html, $allHtml = false ) {
656 + if ( $allHtml ) {
657 + echo stripslashes_deep( $html ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
658 + } else {
659 + echo wp_kses_post( stripslashes_deep( $html ) );
660 + }
661 + }
662 +
663 + /**
664 + * Allowed HTML for wp_kses.
665 + *
666 + * @param string $level Tag level.
667 + *
668 + * @return mixed
669 + */
670 + public static function allowedHtml( $level = 'basic' ) {
671 + $allowed_html = [];
672 + // TODO:: Need Optimize.
673 + switch ( $level ) {
674 + case 'basic':
675 + $allowed_html = [
676 + 'b' => [
677 + 'class' => [],
678 + 'id' => [],
679 + ],
680 + 'i' => [
681 + 'class' => [],
682 + 'id' => [],
683 + ],
684 + 'u' => [
685 + 'class' => [],
686 + 'id' => [],
687 + ],
688 + 'br' => [
689 + 'class' => [],
690 + 'id' => [],
691 + ],
692 + 'em' => [
693 + 'class' => [],
694 + 'id' => [],
695 + ],
696 + 'span' => [
697 + 'class' => [],
698 + 'id' => [],
699 + ],
700 + 'strong' => [
701 + 'class' => [],
702 + 'id' => [],
703 + ],
704 + 'hr' => [
705 + 'class' => [],
706 + 'id' => [],
707 + ],
708 + 'div' => [
709 + 'class' => [],
710 + 'id' => [],
711 + ],
712 + 'a' => [
713 + 'href' => [],
714 + 'title' => [],
715 + 'class' => [],
716 + 'id' => [],
717 + 'target' => [],
718 + ],
719 + ];
720 + break;
721 +
722 + case 'advanced':
723 + $allowed_html = [
724 + 'b' => [
725 + 'class' => [],
726 + 'id' => [],
727 + ],
728 + 'i' => [
729 + 'class' => [],
730 + 'id' => [],
731 + ],
732 + 'u' => [
733 + 'class' => [],
734 + 'id' => [],
735 + ],
736 + 'br' => [
737 + 'class' => [],
738 + 'id' => [],
739 + ],
740 + 'em' => [
741 + 'class' => [],
742 + 'id' => [],
743 + ],
744 + 'span' => [
745 + 'class' => [],
746 + 'id' => [],
747 + ],
748 + 'strong' => [
749 + 'class' => [],
750 + 'id' => [],
751 + ],
752 + 'hr' => [
753 + 'class' => [],
754 + 'id' => [],
755 + ],
756 + 'a' => [
757 + 'href' => [],
758 + 'title' => [],
759 + 'class' => [],
760 + 'id' => [],
761 + 'target' => [],
762 + ],
763 + 'input' => [
764 + 'type' => [],
765 + 'name' => [],
766 + 'class' => [],
767 + 'value' => [],
768 + ],
769 + ];
770 + break;
771 +
772 + case 'image':
773 + $allowed_html = [
774 + 'img' => [
775 + 'src' => [],
776 + 'data-src' => [],
777 + 'alt' => [],
778 + 'height' => [],
779 + 'width' => [],
780 + 'class' => [],
781 + 'id' => [],
782 + 'style' => [],
783 + 'srcset' => [],
784 + 'loading' => [],
785 + 'sizes' => [],
786 + ],
787 + 'div' => [
788 + 'class' => [],
789 + ],
790 + ];
791 + break;
792 +
793 + case 'anchor':
794 + $allowed_html = [
795 + 'a' => [
796 + 'href' => [],
797 + 'title' => [],
798 + 'class' => [],
799 + 'id' => [],
800 + 'style' => [],
801 + ],
802 + ];
803 + break;
804 +
805 + default:
806 + // code...
807 + break;
808 + }
809 +
810 + return $allowed_html;
811 + }
812 +
813 + /**
814 + * Definition for wp_kses.
815 + *
816 + * @param string $string String to check.
817 + * @param string $level Tag level.
818 + *
819 + * @return string|void
820 + */
821 + // TODO:: Need to remove if not used.
822 + public static function htmlKses( $string, $level ) {
823 + if ( empty( $string ) ) {
824 + return;
825 + }
826 +
827 + return wp_kses( $string, self::allowedHtml( $level ) );
828 + }
829 +
830 + /**
831 + * Insert Some array element
832 + *
833 + * @param [type] $key The elements will insert nearby this key.
834 + * @param [type] $main_array Original array.
835 + * @param [type] $insert_array some element will insert in original array.
836 + * @param boolean $is_after array insert position base on the key.
837 + *
838 + * @return array
839 + */
840 + public static function insert_controls( $key, $main_array, $insert_array, $is_after = false ) {
841 + $index = array_search( $key, array_keys( $main_array ), true );
842 + if ( 'integer' === gettype( $index ) ) {
843 + if ( $is_after ) {
844 + $index ++;
845 + }
846 + $main_array = array_merge(
847 + array_slice( $main_array, 0, $index ),
848 + $insert_array,
849 + array_slice( $main_array, $index )
850 + );
851 + }
852 +
853 + return $main_array;
854 + }
855 +
856 + /**
857 + * Image Sizes
858 + *
859 + * @return array
860 + */
861 + public static function get_image_sizes() {
862 + global $_wp_additional_image_sizes;
863 +
864 + $sizes = [];
865 +
866 + foreach ( get_intermediate_image_sizes() as $_size ) {
867 + if ( in_array( $_size, [ 'thumbnail', 'medium', 'large' ], true ) ) {
868 + $sizes[ $_size ]['width'] = get_option( "{$_size}_size_w" );
869 + $sizes[ $_size ]['height'] = get_option( "{$_size}_size_h" );
870 + $sizes[ $_size ]['crop'] = (bool) get_option( "{$_size}_crop" );
871 + } elseif ( isset( $_wp_additional_image_sizes[ $_size ] ) ) {
872 + $sizes[ $_size ] = [
873 + 'width' => $_wp_additional_image_sizes[ $_size ]['width'],
874 + 'height' => $_wp_additional_image_sizes[ $_size ]['height'],
875 + 'crop' => $_wp_additional_image_sizes[ $_size ]['crop'],
876 + ];
877 + }
878 + }
879 +
880 + $imgSize = [];
881 +
882 + foreach ( $sizes as $key => $img ) {
883 + $imgSize[ $key ] = ucfirst( $key ) . " ({$img['width']}*{$img['height']})";
884 + }
885 +
886 + $imgSize['full'] = esc_html__( 'Full size', 'shopbuilder' );
887 + $imgSize['rtsb_custom'] = esc_html__( 'Custom image size', 'shopbuilder' );
888 +
889 + return $imgSize;
890 + }
891 +
892 + /**
893 + * Free Layouts
894 + *
895 + * @return array
896 + */
897 + public static function free_layouts() {
898 + $layouts = [
899 + 'grid-layout1' => esc_html__( 'Grid Layout 1', 'shopbuilder' ),
900 + 'grid-layout2' => esc_html__( 'Grid Layout 2', 'shopbuilder' ),
901 + 'list-layout1' => esc_html__( 'List Layout 1', 'shopbuilder' ),
902 + 'list-layout2' => esc_html__( 'List Layout 2', 'shopbuilder' ),
903 + 'slider-layout1' => esc_html__( 'Slider Layout 1', 'shopbuilder' ),
904 + 'slider-layout2' => esc_html__( 'Slider Layout 2', 'shopbuilder' ),
905 + 'category-single-layout1' => esc_html__( 'Category Single Layout 1', 'shopbuilder' ),
906 + 'category-layout1' => esc_html__( 'Category Layout 1', 'shopbuilder' ),
907 + 'category-layout2' => esc_html__( 'Category Layout 2', 'shopbuilder' ),
908 + 'category-layout3' => esc_html__( 'Category Layout 2', 'shopbuilder' ),
909 + ];
910 +
911 + return apply_filters( 'rtsb/elements/elementor/free_layouts', $layouts );
912 + }
913 +
914 + /**
915 + * Get all terms by taxonomy
916 + *
917 + * @param string $taxonomy Taxonomy name.
918 + *
919 + * @return array
920 + */
921 + public static function get_all_terms( $taxonomy ) {
922 + $terms = [];
923 +
924 + if ( empty( $taxonomy ) ) {
925 + return $terms;
926 + }
927 +
928 + $termList = get_terms( [ $taxonomy ], [ 'hide_empty' => 0 ] );
929 +
930 + if ( is_array( $termList ) && ! empty( $termList ) && empty( $termList['errors'] ) ) {
931 + foreach ( $termList as $term ) {
932 + $terms[ $term->term_id ] = esc_html( $term->name );
933 + }
934 + }
935 +
936 + return $terms;
937 + }
938 +
939 + /**
940 + * Get all terms by attributes
941 + *
942 + * @return array
943 + */
944 + public static function get_all_attributes() {
945 + $terms = [];
946 + $termList = [];
947 +
948 + $attributes = wc_get_attribute_taxonomies();
949 +
950 + if ( $attributes ) {
951 + foreach ( $attributes as $tax ) {
952 + if ( taxonomy_exists( wc_attribute_taxonomy_name( $tax->attribute_name ) ) ) {
953 + $termList[ $tax->attribute_name ] = get_terms( wc_attribute_taxonomy_name( $tax->attribute_name ), 'orderby=name&hide_empty=0' );
954 + }
955 + }
956 + }
957 +
958 + if ( ! empty( $termList ) && empty( $termList['errors'] ) && is_array( $termList ) ) {
959 + foreach ( $termList as $name => $atts ) {
960 + foreach ( $atts as $term ) {
961 + $terms[ $term->term_id ] = esc_html( ucwords( str_replace( '-', ' ', $name ) ) . ' - ' . $term->name );
962 + }
963 + }
964 + }
965 +
966 + return $terms;
967 + }
968 +
969 + /**
970 + * Get User list
971 + *
972 + * @return array
973 + */
974 + public static function get_users() {
975 + $users = [];
976 + $u = get_users();
977 +
978 + if ( ! empty( $u ) ) {
979 + foreach ( $u as $user ) {
980 + $users[ $user->ID ] = $user->display_name;
981 + }
982 + }
983 +
984 + return $users;
985 + }
986 +
987 + /**
988 + * Get products list.
989 + *
990 + * @return array
991 + */
992 + public static function get_products_list() {
993 + $products = [];
994 + // TODO:: Need To replace with $wpdb.
995 + $query = get_posts(
996 + [
997 + 'post_type' => 'product',
998 + 'post_status' => 'publish',
999 + 'posts_per_page' => - 1,
1000 + 'orderby' => 'title',
1001 + 'order' => 'ASC',
1002 + ]
1003 + );
1004 +
1005 + if ( ! empty( $query ) && is_array( $query ) ) {
1006 + foreach ( $query as $product ) {
1007 + $products[ $product->ID ] = $product->post_title;
1008 + }
1009 + }
1010 +
1011 + return $products;
1012 + }
1013 +
1014 + /**
1015 + * Get Taxonomy List.
1016 + *
1017 + * @return array
1018 + */
1019 + public static function get_tax_list() {
1020 + return [
1021 + 'product_cat' => esc_html__( 'Product Category', 'shopbuilder' ),
1022 + // 'product_tag' => esc_html__( 'Product Tag', 'shopbuilder' ), // Pro.
1023 + // 'product_attr' => esc_html__( 'Product Attr', 'shopbuilder' ), // Pro.
1024 + ];
1025 + }
1026 +
1027 + /**
1028 + * Get Category Query List.
1029 + *
1030 + * @return array
1031 + */
1032 + public static function get_cat_list() {
1033 + return [
1034 + 'all' => esc_html__( 'All Categories', 'shopbuilder' ),
1035 + 'specific_parent' => esc_html__( 'Sub-Categories by Parent', 'shopbuilder' ),
1036 + 'cat_ids' => esc_html__( 'Select by ID', 'shopbuilder' ),
1037 + 'selection' => esc_html__( 'Manual Selection', 'shopbuilder' ),
1038 + ];
1039 + }
1040 +
1041 + /**
1042 + * Get Term List.
1043 + *
1044 + * @param string $taxonomy Taxonomy.
1045 + * @param bool $first_term First term.
1046 + * @param bool $only_parents Only parent terms.
1047 + * @param bool $return_slug Return with slug.
1048 + *
1049 + * @return int|array
1050 + */
1051 + public static function get_terms( $taxonomy, $first_term = false, $only_parents = false, $return_slug = false ) {
1052 + // TODO:: Return Slug always true for all settings.
1053 + $term_list = [];
1054 + $args = [
1055 + 'taxonomy' => $taxonomy,
1056 + 'hide_empty' => false,
1057 + ];
1058 +
1059 + if ( $only_parents ) {
1060 + $args['parent'] = 0;
1061 + }
1062 +
1063 + $terms = get_terms( $args );
1064 +
1065 + if ( empty( $terms ) ) {
1066 + return [ esc_html__( 'Nothing found', 'shopbuilder' ) ];
1067 + }
1068 +
1069 + foreach ( $terms as $term ) {
1070 + if ( $return_slug ) {
1071 + $term_list[ $term->slug ] = $term->name;
1072 + } else {
1073 + $term_list[ $term->term_id ] = $term->name;
1074 + }
1075 + }
1076 +
1077 + if ( $first_term ) {
1078 + return array_keys( $term_list )[0];
1079 + } else {
1080 + return $term_list;
1081 + }
1082 + }
1083 +
1084 + /**
1085 + * Get product rating.
1086 + *
1087 + * @return string|void
1088 + */
1089 + public static function get_product_rating_html() {
1090 + global $product;
1091 +
1092 + $html = '';
1093 + $rating_count = $product->get_rating_count();
1094 + $average = $product->get_average_rating();
1095 +
1096 + if ( empty( wc_get_rating_html( $average, $rating_count ) ) ) {
1097 + return $html;
1098 + }
1099 +
1100 + $html .= '<div class="product-rating">';
1101 + $html .= wc_get_rating_html( $average, $rating_count );
1102 + // TODO:: Disable Rating Count option need to apply.
1103 + $html .= ! empty( $html ) ? '<span class="count">(' . $average . ')</span>' : '';
1104 + $html .= '</div>';
1105 +
1106 + self::print_html( $html, true );
1107 + }
1108 +
1109 + /**
1110 + * Text truncation.
1111 + *
1112 + * @param string $text_to_truncate Text.
1113 + * @param int $limit Limit.
1114 + * @param string $after After text.
1115 + *
1116 + * @return string
1117 + */
1118 + public static function text_truncation( $text_to_truncate, $limit, $after = '&#8230;' ) {
1119 + if ( empty( $limit ) ) {
1120 + return $text_to_truncate;
1121 + }
1122 +
1123 + $limit ++;
1124 +
1125 + $text = '';
1126 +
1127 + if ( mb_strlen( $text_to_truncate ) > $limit ) {
1128 + $subex = mb_substr( wp_strip_all_tags( $text_to_truncate ), 0, $limit );
1129 + $exwords = explode( ' ', $subex );
1130 + $excut = - ( mb_strlen( $exwords[ count( $exwords ) - 1 ] ) );
1131 +
1132 + if ( $excut < 0 ) {
1133 + $text .= mb_substr( $subex, 0, $excut ) . $after;
1134 + } else {
1135 + $text .= $subex . $after;
1136 + }
1137 + } else {
1138 + $text .= $text_to_truncate;
1139 + }
1140 +
1141 + return $text;
1142 + }
1143 +
1144 + /**
1145 + * Promo Badge HTML
1146 + *
1147 + * @param string $text Text.
1148 + * @param string $class Class.
1149 + *
1150 + * @return void
1151 + */
1152 + public static function get_badge_html( $text, $class = 'fill' ) {
1153 + ob_start();
1154 + ?>
1155 +
1156 + <ul class="rtsb-promotion-list">
1157 + <li class="rtsb-promotion-list-item">
1158 + <span class="rtsb-tag-<?php echo ! empty( $class ) ? esc_attr( $class ) : ''; ?>"><?php echo esc_html( $text ); ?></span>
1159 + </li>
1160 + </ul>
1161 +
1162 + <?php
1163 + self::print_html( ob_get_clean() );
1164 + }
1165 +
1166 + /**
1167 + * Categories HTML
1168 + *
1169 + * @param int $id Product ID.
1170 + * @param string $class Custom class.
1171 + *
1172 + * @return void|string
1173 + */
1174 + public static function get_categories_list( $id, $class = 'rtsb-category-outline' ) {
1175 + if ( empty( $id ) ) {
1176 + return '';
1177 + }
1178 +
1179 + ob_start();
1180 + ?>
1181 +
1182 + <ul class="rtsb-category-list <?php echo esc_attr( $class ); ?>">
1183 + <?php
1184 + self::print_html(
1185 + wc_get_product_category_list(
1186 + $id,
1187 + '</li><li class="rtsb-category-list-item">',
1188 + '<li class="rtsb-category-list-item">',
1189 + '</li>'
1190 + )
1191 + );
1192 + ?>
1193 + </ul>
1194 +
1195 + <?php
1196 + self::print_html( ob_get_clean() );
1197 + }
1198 +
1199 +
1200 + /**
1201 + * Get Featured Image HTML.
1202 + *
1203 + * @param string $type Image type.
1204 + * @param int $post_id Post ID.
1205 + * @param string $f_img_size Image size.
1206 + * @param null $default_img_id Default image ID.
1207 + * @param array $custom_img_size Custom image size.
1208 + * @param bool $lazy Lazy load check.
1209 + * @param bool $hover Hover image.
1210 + *
1211 + * @return string|null
1212 + */
1213 + public static function get_product_image_html( $type = 'product', $post_id = null, $f_img_size = 'medium', $default_img_id = null, $custom_img_size = [], $lazy = false, $hover = false ) {
1214 + $img_html = null;
1215 + $attachment_id = null;
1216 + $c_size = false;
1217 + $hover_class = '';
1218 + $post_title = '';
1219 +
1220 + if ( 'rtsb_custom' === $f_img_size ) {
1221 + $f_img_size = 'full';
1222 + $c_size = true;
1223 + }
1224 +
1225 + if ( $hover ) {
1226 + $a_id = $post_id;
1227 + $hover_class = ' rtsb-img-hover';
1228 + } else {
1229 + if ( 'product' === $type ) {
1230 + $a_id = get_post_thumbnail_id( $post_id );
1231 + $post_title = get_the_title( $post_id );
1232 + } elseif ( 'category' === $type ) {
1233 + $a_id = get_term_meta( $post_id, 'thumbnail_id', true );
1234 + $post_title = get_term( $post_id )->name;
1235 + } else {
1236 + $a_id = $default_img_id;
1237 + }
1238 + }
1239 +
1240 + $img_alt = trim( wp_strip_all_tags( get_post_meta( $a_id, '_wp_attachment_image_alt', true ) ) );
1241 + $alt_tag = ! empty( $img_alt ) ? $img_alt : wp_strip_all_tags( $post_title );
1242 + $lazy_class = $lazy ? ' swiper-lazy' : '';
1243 + $attr = [
1244 + 'class' => 'img-responsive rtsb-product-image' . $lazy_class . $hover_class,
1245 + 'alt' => $alt_tag,
1246 + ];
1247 +
1248 + if ( $a_id ) {
1249 + $img_html = wp_get_attachment_image( $a_id, $f_img_size, false, $attr );
1250 + $attachment_id = $a_id;
1251 + }
1252 +
1253 + if ( ! $img_html && $default_img_id ) {
1254 + $img_html = wp_get_attachment_image( $default_img_id, $f_img_size, false, $attr );
1255 + $attachment_id = $default_img_id;
1256 + }
1257 +
1258 + if ( $img_html && $c_size ) {
1259 + preg_match( '@src="([^"]+)"@', $img_html, $match );
1260 + $img_src = array_pop( $match );
1261 + $w = ! empty( $custom_img_size['width'] ) ? absint( $custom_img_size['width'] ) : null;
1262 + $h = ! empty( $custom_img_size['height'] ) ? absint( $custom_img_size['height'] ) : null;
1263 + $c = ! empty( $custom_img_size['crop'] ) && 'soft' === $custom_img_size['crop'] ? false : true;
1264 +
1265 + if ( $w && $h ) {
1266 + $image = self::image_resize( $img_src, $w, $h, $c, false );
1267 +
1268 + if ( ! empty( $image ) ) {
1269 + [ $src, $width, $height ] = $image;
1270 +
1271 + $hwstring = image_hwstring( $width, $height );
1272 + $attachment = get_post( $attachment_id );
1273 + $attr = apply_filters( 'wp_get_attachment_image_attributes', $attr, $attachment, $f_img_size );
1274 +
1275 + if ( $lazy ) {
1276 + $attr['data-src'] = $src;
1277 + } else {
1278 + $attr['src'] = $src;
1279 + }
1280 +
1281 + $attr = array_map( 'esc_attr', $attr );
1282 + $img_html = rtrim( "<img $hwstring" );
1283 +
1284 + foreach ( $attr as $name => $value ) {
1285 + $img_html .= " $name=" . '"' . $value . '"';
1286 + }
1287 +
1288 + $img_html .= ' />';
1289 + }
1290 + }
1291 + }
1292 +
1293 + if ( ! $img_html ) {
1294 + $hwstring = image_hwstring( 160, 160 );
1295 + $attr = isset( $attr['src'] ) ? apply_filters( 'wp_get_attachment_image_attributes', $attr, false, $f_img_size ) : [];
1296 + $attr['class'] = 'default-img';
1297 + $attr['src'] = esc_url( rtsb()->get_assets_uri( 'images/demo.png' ) );
1298 + $attr['alt'] = esc_html__( 'Default Image', 'shopbuilder' );
1299 + $img_html = rtrim( "<img $hwstring" );
1300 +
1301 + foreach ( $attr as $name => $value ) {
1302 + $img_html .= " $name=" . '"' . $value . '"';
1303 + }
1304 +
1305 + $img_html .= ' />';
1306 + }
1307 +
1308 + if ( $lazy ) {
1309 + $img_html = $img_html . '<div class="swiper-lazy-preloader swiper-lazy-preloader"></div>';
1310 + }
1311 +
1312 + return $img_html;
1313 + }
1314 +
1315 + /**
1316 + * Call the Image resize model for resize function
1317 + *
1318 + * @param string $url URL.
1319 + * @param int $width Width.
1320 + * @param int $height Height.
1321 + * @param string $crop Crop.
1322 + * @param bool|true $single Single.
1323 + * @param bool|false $upscale Upscale.
1324 + *
1325 + * @return array|bool|string
1326 + */
1327 + public static function image_resize( $url, $width = null, $height = null, $crop = null, $single = true, $upscale = false ) {
1328 + $rtResize = new ReSizer();
1329 +
1330 + return $rtResize->process( $url, $width, $height, $crop, $single, $upscale );
1331 + }
1332 +
1333 + /**
1334 + * Get Product Image
1335 + *
1336 + * @param string $f_image Featured Image.
1337 + * @param string $h_image Hover Image.
1338 + *
1339 + * @return void
1340 + */
1341 + public static function get_product_image( $f_image, $h_image = null ) {
1342 + echo wp_kses( $f_image, self::allowedHtml( 'image' ) );
1343 +
1344 + if ( ! empty( $h_image ) ) {
1345 + echo wp_kses( $h_image, self::allowedHtml( 'image' ) );
1346 + }
1347 + }
1348 +
1349 + /**
1350 + * Post Custom Field value.
1351 + *
1352 + * @param int $post_id Post id.
1353 + * @param string $field_key Custom Field Key.
1354 + * @param string $field_fallback FallBack text.
1355 + *
1356 + * @return string|void
1357 + */
1358 + public static function get_post_custom_field_value( $post_id, $field_key = '', $field_fallback = '' ) {
1359 + if ( ! $post_id || ! $field_key ) {
1360 + return;
1361 + }
1362 + $field_value = get_post_meta( $post_id, $field_key, true );
1363 + if ( empty( $field_value ) ) {
1364 + $field_value = ! empty( $field_fallback ) ? $field_fallback : $field_value;
1365 + }
1366 + $field_value = apply_filters( 'rtsb/get_post_custom_field_value/' . $field_key, $field_value, $field_key );
1367 +
1368 + return sprintf( '<span class="rtsb-woo-custom-field">%s</span>', $field_value );
1369 + }
1370 +
1371 + /**
1372 + * Elementor Icon
1373 + *
1374 + * @param array $control Elementor Control array.
1375 + * @param string $class Custom class.
1376 + * @param string $builder Builder name.
1377 + *
1378 + * @return string
1379 + */
1380 + public static function icons_manager( $control, $class = '', $builder = 'elementor' ): string {
1381 + $attributes = [
1382 + 'aria-hidden' => 'true',
1383 + ];
1384 +
1385 + if ( ! empty( $class ) ) {
1386 + $attributes['class'] = esc_attr( $class );
1387 + }
1388 +
1389 + ob_start();
1390 +
1391 + if ( defined( 'ELEMENTOR_VERSION' ) && ! empty( $control ) && 'elementor' === $builder ) {
1392 + Icons_Manager::render_icon( $control, $attributes );
1393 + }
1394 +
1395 + return ob_get_clean();
1396 + }
1397 +
1398 + /**
1399 + * Get sale badge
1400 + *
1401 + * @param string $type Badge type.
1402 + * @param string $text Badge text.
1403 + * @param string $out_of_stock_text Out of stock text.
1404 + *
1405 + * @return string
1406 + */
1407 + public static function get_sale_badge( $type, $text, $out_of_stock_text ) {
1408 + global $product;
1409 +
1410 + if ( ! $product->is_in_stock() ) {
1411 + return $out_of_stock_text;
1412 + }
1413 +
1414 + if ( ! $product->is_on_sale() ) {
1415 + return '';
1416 + }
1417 +
1418 + $badge_text = '';
1419 + $percentage = null;
1420 + $max_percentage = '';
1421 +
1422 + if ( $product->is_type( 'simple' ) ) {
1423 + $max_percentage = ( ( $product->get_regular_price() - $product->get_sale_price() ) / $product->get_regular_price() ) * 100;
1424 + } elseif ( $product->is_type( 'variable' ) ) {
1425 + $max_percentage = 0;
1426 +
1427 + foreach ( $product->get_children() as $child_id ) {
1428 + $variation = wc_get_product( $child_id );
1429 + $price = $variation->get_regular_price();
1430 + $sale = $variation->get_sale_price();
1431 +
1432 + if ( 0 !== $price && ! empty( $sale ) ) {
1433 + $percentage = ( $price - $sale ) / $price * 100;
1434 + }
1435 +
1436 + if ( $percentage > $max_percentage ) {
1437 + $max_percentage = $percentage;
1438 + }
1439 + }
1440 + }
1441 +
1442 + if ( $max_percentage > 0 ) {
1443 + $badge_text = '-' . round( $max_percentage ) . '%';
1444 + }
1445 +
1446 + if ( 'text' === $type ) {
1447 + $badge_text = $text;
1448 + }
1449 +
1450 + return $badge_text;
1451 + }
1452 +
1453 + /**
1454 + * Pagination
1455 + *
1456 + * @param string $pages Pages.
1457 + * @param integer $range Range.
1458 + * @param boolean $ajax Ajax.
1459 + *
1460 + * @return string
1461 + */
1462 + public static function custom_pagination( $pages = '', $range = 4, $ajax = false ) {
1463 + $html = null;
1464 + $showitems = ( $range * 2 ) + 1;
1465 +
1466 + global $paged;
1467 +
1468 + if ( is_front_page() ) {
1469 + $paged = ( get_query_var( 'page' ) ) ? get_query_var( 'page' ) : 1;
1470 + } else {
1471 + $paged = ( get_query_var( 'paged' ) ) ? get_query_var( 'paged' ) : 1;
1472 + }
1473 +
1474 + if ( empty( $paged ) ) {
1475 + $paged = 1;
1476 + }
1477 +
1478 + if ( $pages == '' ) {
1479 + global $wp_query;
1480 + $pages = $wp_query->max_num_pages;
1481 +
1482 + if ( ! $pages ) {
1483 + $pages = 1;
1484 + }
1485 + }
1486 +
1487 + $ajaxClass = null;
1488 + $dataAttr = null;
1489 +
1490 + if ( $ajax ) {
1491 + $ajaxClass = ' rtsb-ajax';
1492 + $dataAttr = "data-paged='1'";
1493 + }
1494 +
1495 + if ( 1 != $pages ) {
1496 + $html .= '<div class="rtsb-pagination' . $ajaxClass . '" ' . $dataAttr . '>';
1497 + $html .= '<ul class="pagination-list">';
1498 +
1499 + if ( $paged > 2 && $paged > $range + 1 && $showitems < $pages ) {
1500 + $html .= "<li><a data-paged='1' href='" . get_pagenum_link( 1 ) . "' aria-label='First'>&laquo;</a></li>";
1501 + }
1502 +
1503 + if ( $paged > 1 && $showitems < $pages ) {
1504 + $p = $paged - 1;
1505 + $html .= "<li><a data-paged='{$p}' href='" . get_pagenum_link( $p ) . "' aria-label='Previous'>&lsaquo;</a></li>";
1506 + }
1507 +
1508 + for ( $i = 1; $i <= $pages; $i ++ ) {
1509 + if ( 1 != $pages && ( ! ( $i >= $paged + $range + 1 || $i <= $paged - $range - 1 ) || $pages <= $showitems ) ) {
1510 + $html .= ( $paged == $i ) ? '<li class="active"><span>' . $i . '</span></li>' : "<li><a data-paged='{$i}' href='" . get_pagenum_link( $i ) . "'>" . $i . '</a></li>';
1511 + }
1512 + }
1513 +
1514 + if ( $paged < $pages && $showitems < $pages ) {
1515 + $p = $paged + 1;
1516 + $html .= "<li><a data-paged='{$p}' href=\"" . get_pagenum_link( $paged + 1 ) . "\" aria-label='Next'>&rsaquo;</a></li>";
1517 + }
1518 +
1519 + if ( $paged < $pages - 1 && $paged + $range - 1 < $pages && $showitems < $pages ) {
1520 + $html .= "<li><a data-paged='{$pages}' href='" . get_pagenum_link( $pages ) . "' aria-label='Last'>&raquo;</a></li>";
1521 + }
1522 +
1523 + $html .= '</ul>';
1524 + $html .= '</div>';
1525 + }
1526 +
1527 + return $html;
1528 + }
1529 +
1530 + /**
1531 + * Action Buttons HTMl
1532 + *
1533 + * @param array $items Items.
1534 + * @param array $ajax_cart Ajax cart HTML.
1535 + * @param string $preset Button preset.
1536 + * @param array $position Position.
1537 + *
1538 + * @return void|string
1539 + */
1540 + public static function get_formatted_action_buttons( $items, $ajax_cart = '', $preset = 'preset1', $position = 'above' ) {
1541 + if ( empty( $items ) ) {
1542 + return;
1543 + }
1544 +
1545 + $html = '';
1546 + $class = '';
1547 +
1548 + if ( 'after' === $position ) {
1549 + $class .= 'after-content';
1550 + }
1551 +
1552 + if ( 'preset2' === $preset ) {
1553 + $class .= ' rtsb-action-buttons-vertical vertical-delay-effect';
1554 + } elseif ( 'preset4' === $preset ) {
1555 + $class .= 'rtsb-action-buttons-vertical rtsb-action-buttons-vertical-left vertical-delay-effect';
1556 + } elseif ( 'preset5' === $preset ) {
1557 + $class .= ' action-buttons-outline horizontal-floating-btn';
1558 + } else {
1559 + $class .= ' rtsb-action-buttons-cart-box-width-auto horizontal-floating-btn';
1560 + }
1561 +
1562 + if ( 'preset3' === $preset ) {
1563 + $html .= '<div class="rtsb-action-buttons top-part">';
1564 + $html .= '<ul class="rtsb-action-button-list">';
1565 + $html .= self::get_action_button_by_type( $items, 'wishlist' );
1566 + $html .= self::get_action_button_by_type( $items, 'compare' );
1567 + $html .= self::get_action_button_by_type( $items, 'quick_view' );
1568 + $html .= '</ul>';
1569 + $html .= '</div>';
1570 +
1571 + $html .= '<div class="rtsb-action-buttons bottom-part">';
1572 + $html .= '<ul class="rtsb-action-button-list">';
1573 + $html .= self::get_action_button_by_type( $items, 'add_to_cart', $ajax_cart );
1574 + } else {
1575 + $html .= '<div class="rtsb-action-buttons ' . esc_attr( $class ) . '">';
1576 + $html .= '<ul class="rtsb-action-button-list">';
1577 + $html .= self::get_action_button_by_type( $items, 'add_to_cart', $ajax_cart );
1578 + $html .= self::get_action_button_by_type( $items, 'wishlist' );
1579 + $html .= self::get_action_button_by_type( $items, 'compare' );
1580 + $html .= self::get_action_button_by_type( $items, 'quick_view' );
1581 + }
1582 +
1583 + $html .= '</ul>';
1584 + $html .= '</div>';
1585 +
1586 + return apply_filters( 'rtsb/elements/elementor/get_formatted_action_buttons', $html );
1587 + }
1588 +
1589 + /**
1590 + * Get Action Button HTML
1591 + *
1592 + * @param array $items Items.
1593 + * @param string $type Button type.
1594 + * @param string $cart_html Ajax cart HTML.
1595 + * @param string $wrapper Wrapper tag.
1596 + *
1597 + * @return void|string
1598 + */
1599 + public static function get_action_button_by_type( $items, $type, $cart_html = '', $wrapper = 'li' ) {
1600 + if ( ! in_array( $type, $items, true ) ) {
1601 + return;
1602 + }
1603 +
1604 + $html = '';
1605 + $class = 'rtsb-action-button-item';
1606 +
1607 + if ( 'add_to_cart' === $type ) {
1608 + $class .= ' rtsb-cart' . ( empty( $cart_html ) ? esc_attr( ' no-cart-button' ) : '' );
1609 + } else {
1610 + $class .= ' rtsb-' . esc_attr( str_replace( '_', '-', $type ) );
1611 + }
1612 +
1613 + $html .= '<' . esc_attr( $wrapper ) . ' class="' . esc_attr( $class ) . '">';
1614 +
1615 + if ( ( 'add_to_cart' === $type ) && ( ! empty( $cart_html ) ) ) {
1616 + $html .= $cart_html;
1617 + } else {
1618 + $html .= do_shortcode( '[rtsb_' . $type . '_button]' );
1619 + }
1620 +
1621 + $html .= '</' . esc_attr( $wrapper ) . '>';
1622 +
1623 + return apply_filters( 'rtsb/elements/elementor/get_action_button_by_type', $html );
1624 + }
1625 +
1626 + /**
1627 + * Social Share Platforms.
1628 + *
1629 + * @return mixed|null
1630 + */
1631 + public static function social_share_platforms_list() {
1632 + return apply_filters(
1633 + 'rtsb/settings/social_share/platforms',
1634 + [
1635 + [
1636 + 'value' => 'facebook',
1637 + 'label' => esc_html__( 'Facebook', 'shopbuilder' ),
1638 + ],
1639 + [
1640 + 'value' => 'twitter',
1641 + 'label' => esc_html__( 'Twitter', 'shopbuilder' ),
1642 + ],
1643 + [
1644 + 'value' => 'linkedin',
1645 + 'label' => esc_html__( 'Linkedin', 'shopbuilder' ),
1646 + ],
1647 + [
1648 + 'value' => 'pinterest',
1649 + 'label' => esc_html__( 'Pinterest', 'shopbuilder' ),
1650 + ],
1651 + [
1652 + 'value' => 'skype',
1653 + 'label' => esc_html__( 'Skype', 'shopbuilder' ),
1654 + ],
1655 + [
1656 + 'value' => 'whatsapp',
1657 + 'label' => esc_html__( 'Whatsapp', 'shopbuilder' ),
1658 + ],
1659 + [
1660 + 'value' => 'reddit',
1661 + 'label' => esc_html__( 'Reddit', 'shopbuilder' ),
1662 + ],
1663 + [
1664 + 'value' => 'telegram',
1665 + 'label' => esc_html__( 'Telegram', 'shopbuilder' ),
1666 + ],
1667 + ]
1668 + );
1669 + }
1670 +
1671 + /**
1672 + * Get Social Share link HTML.
1673 + *
1674 + * @param int $id Post ID.
1675 + * @param array $types Preset type.
1676 + * @param string $preset Style type.
1677 + * @param string $show_icon Show icon.
1678 + *
1679 + * @return string
1680 + */
1681 + public static function get_social_share_html( int $id, array $types, string $preset = 'default', $show_icon = 'yes' ) {
1682 + $attr = [ 'postid' => $id ];
1683 + $output = '';
1684 +
1685 + if ( empty( $types ) ) {
1686 + return $output;
1687 + }
1688 +
1689 + foreach ( $types as $type ) {
1690 + $link = [];
1691 + $link['type'] = $type['share_items'];
1692 + $link['class'] = '';
1693 + $link['img'] = apply_filters( 'rtsb/elements/share/default_img', '', $id, $link );
1694 +
1695 + if ( 'site' === $id ) {
1696 + $link['url'] = esc_url( home_url() );
1697 + $link['title'] = wp_strip_all_tags( get_bloginfo( 'name' ) );
1698 + } elseif ( 0 === strpos( $id, 'http' ) ) {
1699 + $link['url'] = esc_url( $id );
1700 + $link['title'] = '';
1701 + } else {
1702 + $link['url'] = esc_url( get_permalink( $id ) );
1703 + $link['title'] = wp_strip_all_tags( get_the_title( $id ) );
1704 +
1705 + if ( has_post_thumbnail( $id ) ) {
1706 + $link['img'] = wp_get_attachment_image_url( get_post_thumbnail_id( $id ), 'full' );
1707 + }
1708 +
1709 + $link['img'] = apply_filters( 'rtsb/elements/share/single_img', $link['img'], $id, $link );
1710 + }
1711 +
1712 + $link['url'] = apply_filters( 'rtsb/elements/share/url', $link['url'], $link );
1713 +
1714 + switch ( $type['share_items'] ) {
1715 + case 'facebook':
1716 + $link['link'] = 'https://www.facebook.com/sharer/sharer.php?u=' . $link['url'] . '&display=popup&ref=plugin&src=share_button';
1717 + $link['icon'] = '<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="18.8125" height="32" viewBox="0 0 602 1024"><path d="M548 6.857v150.857h-89.714q-49.143 0-66.286 20.571t-17.143 61.714v108h167.429l-22.286 169.143h-145.143v433.714h-174.857v-433.714h-145.714v-169.143h145.714v-124.571q0-106.286 59.429-164.857t158.286-58.571q84 0 130.286 6.857z"></path></svg>';
1718 + $link['attr_title'] = esc_html__( 'Share on Facebook', 'shopbuilder' );
1719 + $link['social_network'] = 'Facebook';
1720 + $link['social_action'] = 'Share';
1721 + break;
1722 + case 'twitter':
1723 + $link['link'] = 'https://twitter.com/intent/tweet?text=' . htmlspecialchars( rawurlencode( html_entity_decode( $link['title'], ENT_COMPAT, 'UTF-8' ) ), ENT_COMPAT, 'UTF-8' ) . '&url=' . $link['url'];
1724 + $link['icon'] = '<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="29.71875" height="32" viewBox="0 0 951 1024"><path d="M925.714 233.143q-38.286 56-92.571 95.429 0.571 8 0.571 24 0 74.286-21.714 148.286t-66 142-105.429 120.286-147.429 83.429-184.571 31.143q-154.857 0-283.429-82.857 20 2.286 44.571 2.286 128.571 0 229.143-78.857-60-1.143-107.429-36.857t-65.143-91.143q18.857 2.857 34.857 2.857 24.571 0 48.571-6.286-64-13.143-106-63.714t-42-117.429v-2.286q38.857 21.714 83.429 23.429-37.714-25.143-60-65.714t-22.286-88q0-50.286 25.143-93.143 69.143 85.143 168.286 136.286t212.286 56.857q-4.571-21.714-4.571-42.286 0-76.571 54-130.571t130.571-54q80 0 134.857 58.286 62.286-12 117.143-44.571-21.143 65.714-81.143 101.714 53.143-5.714 106.286-28.571z"></path></svg>';
1725 + $link['attr_title'] = esc_html__( 'Share on Twitter', 'shopbuilder' );
1726 + $link['social_network'] = 'Twitter';
1727 + $link['social_action'] = 'Tweet';
1728 + break;
1729 + case 'pinterest':
1730 + $link['link'] = 'https://pinterest.com/pin/create/button/?url=' . $link['url'] . '&media=' . $link['img'] . '&description=' . $link['title'];
1731 + $link['icon'] = '<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="22.84375" height="32" viewBox="0 0 731 1024"><path d="M0 341.143q0-61.714 21.429-116.286t59.143-95.143 86.857-70.286 105.714-44.571 115.429-14.857q90.286 0 168 38t126.286 110.571 48.571 164q0 54.857-10.857 107.429t-34.286 101.143-57.143 85.429-82.857 58.857-108 22q-38.857 0-77.143-18.286t-54.857-50.286q-5.714 22.286-16 64.286t-13.429 54.286-11.714 40.571-14.857 40.571-18.286 35.714-26.286 44.286-35.429 49.429l-8 2.857-5.143-5.714q-8.571-89.714-8.571-107.429 0-52.571 12.286-118t38-164.286 29.714-116q-18.286-37.143-18.286-96.571 0-47.429 29.714-89.143t75.429-41.714q34.857 0 54.286 23.143t19.429 58.571q0 37.714-25.143 109.143t-25.143 106.857q0 36 25.714 59.714t62.286 23.714q31.429 0 58.286-14.286t44.857-38.857 32-54.286 21.714-63.143 11.429-63.429 3.714-56.857q0-98.857-62.571-154t-163.143-55.143q-114.286 0-190.857 74t-76.571 187.714q0 25.143 7.143 48.571t15.429 37.143 15.429 26 7.143 17.429q0 16-8.571 41.714t-21.143 25.714q-1.143 0-9.714-1.714-29.143-8.571-51.714-32t-34.857-54-18.571-61.714-6.286-60.857z"></path></svg>';
1732 + $link['attr_title'] = esc_html__( 'Share on Pinterest', 'shopbuilder' );
1733 + $link['social_network'] = 'Pinterest';
1734 + $link['social_action'] = 'Pin';
1735 + break;
1736 + case 'linkedin':
1737 + $link['link'] = 'https://www.linkedin.com/shareArticle?url=' . $link['url'] . '&title=' . $link['title'];
1738 + $link['icon'] = '<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="27.4375" height="32" viewBox="0 0 878 1024"><path d="M199.429 357.143v566.286h-188.571v-566.286h188.571zM211.429 182.286q0.571 41.714-28.857 69.714t-77.429 28h-1.143q-46.857 0-75.429-28t-28.571-69.714q0-42.286 29.429-70t76.857-27.714 76 27.714 29.143 70zM877.714 598.857v324.571h-188v-302.857q0-60-23.143-94t-72.286-34q-36 0-60.286 19.714t-36.286 48.857q-6.286 17.143-6.286 46.286v316h-188q1.143-228 1.143-369.714t-0.571-169.143l-0.571-27.429h188v82.286h-1.143q11.429-18.286 23.429-32t32.286-29.714 49.714-24.857 65.429-8.857q97.714 0 157.143 64.857t59.429 190z"></path></svg>';
1739 + $link['attr_title'] = esc_html__( 'Share on LinkedIn', 'shopbuilder' );
1740 + $link['social_network'] = 'LinkedIn';
1741 + $link['social_action'] = 'Share';
1742 + break;
1743 + case 'skype':
1744 + $link['link'] = 'https://web.skype.com/share?url=' . $link['url'];
1745 + $link['icon'] = '<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px" height="24px" viewBox="0 0 24 24" enable-background="new 0 0 24 24" xml:space="preserve" class="eapps-social-share-buttons-item-icon"> <path d="M23.016,13.971c0.111-0.638,0.173-1.293,0.173-1.963 c0-6.213-5.014-11.249-11.199-11.249c-0.704,0-1.393,0.068-2.061,0.193C8.939,0.348,7.779,0,6.536,0C2.926,0,0,2.939,0,6.565 c0,1.264,0.357,2.443,0.973,3.445c-0.116,0.649-0.18,1.316-0.18,1.999c0,6.212,5.014,11.25,11.198,11.25 c0.719,0,1.419-0.071,2.099-0.201C15.075,23.656,16.229,24,17.465,24C21.074,24,24,21.061,24,17.435 C24,16.163,23.639,14.976,23.016,13.971z M12.386,19.88c-3.19,0-6.395-1.453-6.378-3.953c0.005-0.754,0.565-1.446,1.312-1.446 c1.877,0,1.86,2.803,4.85,2.803c2.098,0,2.814-1.15,2.814-1.95c0-2.894-9.068-1.12-9.068-6.563c0-2.945,2.409-4.977,6.196-4.753 c3.61,0.213,5.727,1.808,5.932,3.299c0.102,0.973-0.543,1.731-1.662,1.731c-1.633,0-1.8-2.188-4.613-2.188 c-1.269,0-2.341,0.53-2.341,1.679c0,2.402,9.014,1.008,9.014,6.295C18.441,17.882,16.012,19.88,12.386,19.88z"></path> </svg>';
1746 + $link['attr_title'] = esc_html__( 'Share on Skype', 'shopbuilder' );
1747 + $link['social_network'] = 'Skype';
1748 + $link['social_action'] = 'Skype';
1749 + break;
1750 + case 'whatsapp':
1751 + $link['link'] = 'https://wa.me/?text=' . $link['title'] . ' ' . $link['url'];
1752 + $link['icon'] = '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-whatsapp" viewBox="0 0 16 16"> <path d="M13.601 2.326A7.854 7.854 0 0 0 7.994 0C3.627 0 .068 3.558.064 7.926c0 1.399.366 2.76 1.057 3.965L0 16l4.204-1.102a7.933 7.933 0 0 0 3.79.965h.004c4.368 0 7.926-3.558 7.93-7.93A7.898 7.898 0 0 0 13.6 2.326zM7.994 14.521a6.573 6.573 0 0 1-3.356-.92l-.24-.144-2.494.654.666-2.433-.156-.251a6.56 6.56 0 0 1-1.007-3.505c0-3.626 2.957-6.584 6.591-6.584a6.56 6.56 0 0 1 4.66 1.931 6.557 6.557 0 0 1 1.928 4.66c-.004 3.639-2.961 6.592-6.592 6.592zm3.615-4.934c-.197-.099-1.17-.578-1.353-.646-.182-.065-.315-.099-.445.099-.133.197-.513.646-.627.775-.114.133-.232.148-.43.05-.197-.1-.836-.308-1.592-.985-.59-.525-.985-1.175-1.103-1.372-.114-.198-.011-.304.088-.403.087-.088.197-.232.296-.346.1-.114.133-.198.198-.33.065-.134.034-.248-.015-.347-.05-.099-.445-1.076-.612-1.47-.16-.389-.323-.335-.445-.34-.114-.007-.247-.007-.38-.007a.729.729 0 0 0-.529.247c-.182.198-.691.677-.691 1.654 0 .977.71 1.916.81 2.049.098.133 1.394 2.132 3.383 2.992.47.205.84.326 1.129.418.475.152.904.129 1.246.08.38-.058 1.171-.48 1.338-.943.164-.464.164-.86.114-.943-.049-.084-.182-.133-.38-.232z"/> </svg>';
1753 + $link['attr_title'] = esc_html__( 'Share on Whatsapp', 'shopbuilder' );
1754 + $link['social_network'] = 'Whatsapp';
1755 + $link['social_action'] = 'Share';
1756 + break;
1757 + case 'reddit':
1758 + $link['link'] = 'https://reddit.com/submit?url=' . $link['url'] . '&title=' . $link['title'];
1759 + $link['icon'] = '<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512"><title>ionicons-v5_logos</title><path d="M324,256a36,36,0,1,0,36,36A36,36,0,0,0,324,256Z"/><circle cx="188" cy="292" r="36" transform="translate(-97.43 94.17) rotate(-22.5)"/><path d="M496,253.77c0-31.19-25.14-56.56-56-56.56a55.72,55.72,0,0,0-35.61,12.86c-35-23.77-80.78-38.32-129.65-41.27l22-79L363.15,103c1.9,26.48,24,47.49,50.65,47.49,28,0,50.78-23,50.78-51.21S441,48,413,48c-19.53,0-36.31,11.19-44.85,28.77l-90-17.89L247.05,168.4l-4.63.13c-50.63,2.21-98.34,16.93-134.77,41.53A55.38,55.38,0,0,0,72,197.21c-30.89,0-56,25.37-56,56.56a56.43,56.43,0,0,0,28.11,49.06,98.65,98.65,0,0,0-.89,13.34c.11,39.74,22.49,77,63,105C146.36,448.77,199.51,464,256,464s109.76-15.23,149.83-42.89c40.53-28,62.85-65.27,62.85-105.06a109.32,109.32,0,0,0-.84-13.3A56.32,56.32,0,0,0,496,253.77ZM414,75a24,24,0,1,1-24,24A24,24,0,0,1,414,75ZM42.72,253.77a29.6,29.6,0,0,1,29.42-29.71,29,29,0,0,1,13.62,3.43c-15.5,14.41-26.93,30.41-34.07,47.68A30.23,30.23,0,0,1,42.72,253.77ZM390.82,399c-35.74,24.59-83.6,38.14-134.77,38.14S157,423.61,121.29,399c-33-22.79-51.24-52.26-51.24-83A78.5,78.5,0,0,1,75,288.72c5.68-15.74,16.16-30.48,31.15-43.79a155.17,155.17,0,0,1,14.76-11.53l.3-.21,0,0,.24-.17c35.72-24.52,83.52-38,134.61-38s98.9,13.51,134.62,38l.23.17.34.25A156.57,156.57,0,0,1,406,244.92c15,13.32,25.48,28.05,31.16,43.81a85.44,85.44,0,0,1,4.31,17.67,77.29,77.29,0,0,1,.6,9.65C442.06,346.77,423.86,376.24,390.82,399Zm69.6-123.92c-7.13-17.28-18.56-33.29-34.07-47.72A29.09,29.09,0,0,1,440,224a29.59,29.59,0,0,1,29.41,29.71A30.07,30.07,0,0,1,460.42,275.1Z"/><path d="M323.23,362.22c-.25.25-25.56,26.07-67.15,26.27-42-.2-66.28-25.23-67.31-26.27h0a4.14,4.14,0,0,0-5.83,0l-13.7,13.47a4.15,4.15,0,0,0,0,5.89h0c3.4,3.4,34.7,34.23,86.78,34.45,51.94-.22,83.38-31.05,86.78-34.45h0a4.16,4.16,0,0,0,0-5.9l-13.71-13.47a4.13,4.13,0,0,0-5.81,0Z"/></svg>';
1760 + $link['attr_title'] = esc_html__( 'Share on Reddit', 'shopbuilder' );
1761 + $link['social_network'] = 'Reddit';
1762 + $link['social_action'] = 'Share';
1763 + break;
1764 + case 'telegram':
1765 + $link['link'] = 'https://telegram.me/share/url?text=' . $link['title'] . '&url=' . $link['url'];
1766 + $link['icon'] = '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-telegram" viewBox="0 0 16 16"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8.287 5.906c-.778.324-2.334.994-4.666 2.01-.378.15-.577.298-.595.442-.03.243.275.339.69.47l.175.055c.408.133.958.288 1.243.294.26.006.549-.1.868-.32 2.179-1.471 3.304-2.214 3.374-2.23.05-.012.12-.026.166.016.047.041.042.12.037.141-.03.129-1.227 1.241-1.846 1.817-.193.18-.33.307-.358.336a8.154 8.154 0 0 1-.188.186c-.38.366-.664.64.015 1.088.327.216.589.393.85.571.284.194.568.387.936.629.093.06.183.125.27.187.331.236.63.448.997.414.214-.02.435-.22.547-.82.265-1.417.786-4.486.906-5.751a1.426 1.426 0 0 0-.013-.315.337.337 0 0 0-.114-.217.526.526 0 0 0-.31-.093c-.3.005-.763.166-2.984 1.09z"/> </svg>';
1767 + $link['attr_title'] = esc_html__( 'Share on Telegram', 'shopbuilder' );
1768 + $link['social_network'] = 'Telegram';
1769 + $link['social_action'] = 'Share';
1770 + break;
1771 + }
1772 +
1773 + $link['label'] = $type['share_text'];
1774 + $link['target'] = '_blank';
1775 + $link['rel'] = 'nofollow noopener noreferrer';
1776 +
1777 + $data = '';
1778 + $link = apply_filters( 'rtsb/elements/share/share_link', $link, $id, $preset );
1779 + $icon = apply_filters( 'rtsb/elements/share/share_icon', $link['icon'], $preset );
1780 + $target = ! empty( $link['target'] ) ? ' target="' . esc_attr( $link['target'] ) . '" ' : '';
1781 + $rel = ! empty( $link['rel'] ) ? ' rel="' . esc_attr( $link['rel'] ) . '" ' : '';
1782 + $attr_title = ! empty( $link['attr_title'] ) ? ' title="' . esc_attr( $link['attr_title'] ) . '" ' : '';
1783 + $elements = [];
1784 +
1785 + // Add classes.
1786 + $css_classes = [
1787 + 'rtsb-share-btn',
1788 + sanitize_html_class( $link['type'] ),
1789 + ];
1790 + $css_classes = array_merge( $css_classes, explode( ' ', $link['class'] ) );
1791 + $css_classes = array_map( 'sanitize_html_class', $css_classes );
1792 + $css_classes = implode( ' ', array_filter( $css_classes ) );
1793 +
1794 + unset( $attr['pin-do'], $attr['action'] );
1795 +
1796 + if ( 'pinterest' === $type['share_items'] ) {
1797 + $attr['pin-do'] = 'none';
1798 + }
1799 +
1800 + if ( 'whatsapp' === $type['share_items'] ) {
1801 + $attr['action'] = 'share/whatsapp/share';
1802 + }
1803 +
1804 + $attr = apply_filters( 'rtsb/elements/share/link_data', $attr, $link, $id );
1805 +
1806 + if ( ! empty( $attr ) ) {
1807 + foreach ( $attr as $key => $val ) {
1808 + $data .= ' data-' . sanitize_html_class( $key ) . '="' . esc_attr( $val ) . '"';
1809 + }
1810 + }
1811 +
1812 + $additional_attr = apply_filters( 'rtsb/elements/share/additional_attr', [], $link, $id, $preset );
1813 +
1814 + if ( ! empty( $additional_attr ) ) {
1815 + $attr_output = join( ' ', $additional_attr );
1816 +
1817 + if ( ! empty( $data ) ) {
1818 + $attr_output = ' ' . $attr_output;
1819 + }
1820 +
1821 + $data .= $attr_output;
1822 + }
1823 +
1824 + $elements['wrapper_start'] = sprintf(
1825 + '<li class="rtsb-share-item"><a href="%s"%s%s%s class="%s"%s>',
1826 + ! empty( $link['link'] ) ? esc_attr( $link['link'] ) : '',
1827 + $attr_title,
1828 + $target,
1829 + $rel,
1830 + $css_classes,
1831 + $data
1832 + );
1833 + $elements['wrapper_end'] = '</a></li>';
1834 +
1835 + $elements['icon'] = ! empty( $show_icon ) ? '<span class="rtsb-share-icon">' . ( ! empty( $icon ) ? $icon : null ) . '</span>' : null;
1836 + $elements['label'] = ! empty( $link['label'] ) ? '<span class="rtsb-share-label">' . $link['label'] . '</span>' : null;
1837 + $elements['icon_label'] = '<span class="rtsb-share-icon-label">' . $elements['icon'] . $elements['label'] . '</span>';
1838 + $elements = apply_filters( 'rtsb/elements/share/output_elements', $elements, $link, $id );
1839 +
1840 + $output .= $elements['wrapper_start'] . $elements['icon_label'] . $elements['wrapper_end'];
1841 + }
1842 +
1843 + // error_log( print_r( $output , true ) . "\n\n" , 3, __DIR__ . '/log.txt' );
1844 + return apply_filters( 'rtsb/elements/share/list_output', $output );
1845 + }
1846 +
1847 + /**
1848 + * Social Share Platforms.
1849 + *
1850 + * @return mixed|null
1851 + */
1852 + public static function is_module_active( $module ) {
1853 + $modulelist = ModuleList::instance()->get_data();
1854 + if ( ! empty( $modulelist[ $module ]['active'] ) ) {
1855 + return true;
1856 + }
1857 + }
1858 +
1859 + /**
1860 + * @param array $links default plugin action link
1861 + *
1862 + * @return array [array] plugin action link
1863 + */
1864 + public static function plugins_setting_links( $links ) {
1865 + $links[] = '<a href="' . admin_url( 'admin.php?page=rtsb-settings' ) . '">' . esc_html__( 'Settings', 'shopbuilder' ) . '</a>';
1866 + // TODO:: This function will apply after pro version.
1867 + if ( ! is_plugin_active( 'shopbuilder/shopbuilder.php' ) ) {
1868 + $links['shopbuilder_pro'] = sprintf( '<a href="#" target="_blank" style="color: #39b54a; font-weight: bold;">' . esc_html__( 'Go Pro', 'shopbuilder' ) . '</a>' );
1869 + }
1870 +
1871 + return $links;
1872 + }
1873 +
1874 + /***
1875 + * Save Settings data
1876 + *
1877 + * @param $section_id
1878 + * @param $block_id
1879 + * @param $rawOptions
1880 + *
1881 + * @return array
1882 + */
1883 + public static function set_options( $section_id = '', $block_id = '', $rawOptions = [] ) {
1884 + $section_id = ! empty( $section_id ) ? sanitize_text_field( wp_unslash( $section_id ) ) : '';
1885 + $block_id = ! empty( $block_id ) ? sanitize_text_field( wp_unslash( $block_id ) ) : '';
1886 + $rawOptions = ! empty( $rawOptions ) ? $rawOptions : [];
1887 +
1888 + $results = [
1889 + 'status' => true,
1890 + 'message' => '',
1891 + ];
1892 + if ( ! $section_id || ! $block_id ) {
1893 + $results['status'] = false;
1894 + $results['message'] = esc_html__( 'Section , block or options may be empty', 'shopbuilder' );
1895 +
1896 + return $results;
1897 + }
1898 + $sections = Settings::instance()->get_sections();
1899 + if ( empty( $sections[ $section_id ] ) || empty( $sections[ $section_id ]['list'][ $block_id ] ) ) {
1900 + $results['status'] = false;
1901 + $results['message'] = esc_html__( 'No section or block found with given data', 'shopbuilder' );
1902 +
1903 + return $results;
1904 + }
1905 +
1906 + $options = DataModel::source()->get_option( $section_id, [] );
1907 + $changed = false;
1908 + $fields = [];
1909 + if ( isset( $sections[ $section_id ]['list'][ $block_id ]['fields'] ) && ! empty( $sections[ $section_id ]['list'][ $block_id ]['fields'] ) ) {
1910 + $fields = $sections[ $section_id ]['list'][ $block_id ]['fields'];
1911 + }
1912 +
1913 + if ( empty( $fields ) ) {
1914 + if ( isset( $rawOptions['active'] ) ) {
1915 + $changed = true;
1916 + $options[ $block_id ]['active'] = 'on' === $rawOptions['active'] ? 'on' : '';
1917 + }
1918 + } else {
1919 + foreach ( $rawOptions as $raw_option_key => $raw_value ) {
1920 + if ( $raw_option_key === 'active' ) {
1921 + $changed = true;
1922 + $options[ $block_id ]['active'] = $sections[ $section_id ]['list'][ $block_id ]['active'] = 'on' === $raw_value ? 'on' : '';
1923 + } else {
1924 + if ( isset( $fields[ $raw_option_key ] ) ) {
1925 + $field = $fields[ $raw_option_key ];
1926 + if ( $field['type'] === 'switch' ) {
1927 + $value = 'on' === $raw_value ? 'on' : '';
1928 + } else {
1929 + if ( ! empty( $field['multiple'] ) || 'checkbox' === $field['type'] ) {
1930 + if ( isset( $raw_value ) && is_array( $raw_value ) ) {
1931 + if ( ! empty( $field['sanitize_fn'] ) && is_callable( $field['sanitize_fn'] ) ) {
1932 + $value = array_map( $field['sanitize_fn'], $raw_value );
1933 + } else {
1934 + $value = array_map( 'sanitize_text_field', $raw_value );
1935 + }
1936 + } else {
1937 + $value = [];
1938 + }
1939 + } else {
1940 + if ( ! empty( $field['sanitize_fn'] ) && is_callable( $field['sanitize_fn'] ) ) {
1941 + $value = $field['sanitize_fn']( $raw_value );
1942 + } else {
1943 + $value = sanitize_text_field( $raw_value );
1944 + }
1945 + }
1946 + }
1947 + $options[ $block_id ][ $raw_option_key ] = $sections[ $section_id ]['list'][ $block_id ]['fields'][ $raw_option_key ]['value'] = $value;
1948 + $changed = true;
1949 + }
1950 + }
1951 + }
1952 + }
1953 + if ( ! $changed ) {
1954 + $results['status'] = false;
1955 + $results['message'] = esc_html__( 'No changes found for update', 'shopbuilder' );
1956 +
1957 + return $results;
1958 + }
1959 +
1960 + DataModel::source()->set_option( $section_id, $options );
1961 +
1962 + $results['status'] = true;
1963 + $results['message'] = esc_html__( 'Successfully Saved', 'shopbuilder' );
1964 + $results['sections'] = $sections;
1965 +
1966 + return $results;
1967 + }
1968 +
1969 +
1970 +}