PluginProbe
ShopBuilder – WooCommerce Builder For Elementor / 2.1.13
ShopBuilder – WooCommerce Builder For Elementor v2.1.13
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 +294 -25 2.1.7 → 2.1.13 View file →
@@ -44,9 +44,58 @@
44 44
45 45 return false;
46 46 }
47 47
48 + public static function get_nonce() {
49 + // phpcs:ignore WordPress.Security.NonceVerification.Recommended
50 + return isset( $_REQUEST[ rtsb()->nonceId ] ) ? sanitize_text_field( $_REQUEST[ rtsb()->nonceId ] ) : null;
51 + }
52 +
53 +
48 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 + // session_write_close();
65 + } else {
66 + $_SESSION[ $name ] = $value;
67 + }
68 + }
69 + /**
70 + * Get Cookie or Session
71 + *
72 + * @param $name
73 + *
74 + * @return bool
75 + */
76 + public static function getSession( $name ) {
77 + if ( ! headers_sent() && session_status() == PHP_SESSION_NONE ) {
78 + session_start();
79 + }
80 + return $_SESSION[ $name ] ?? null;
81 + }
82 + /**
83 + * Remove Session Variable
84 + *
85 + * @param string $name The name of the session variable to remove.
86 + */
87 + public static function removeSession( $name ) {
88 + if ( ! headers_sent() && session_status() == PHP_SESSION_NONE ) {
89 + session_start();
90 + unset( $_SESSION[ $name ] );
91 + // session_write_close();
92 + } else {
93 + unset( $_SESSION[ $name ] );
94 + }
95 + }
96 +
97 + /**
49 98 * @param $plugin_slug
50 99 *
51 100 * @return bool
52 101 */
@@ -120,14 +169,15 @@
120 169
121 170 /**
122 171 * @param string $template_name Template name.
123 172 * @param string $template_path Template path. (default: '').
124 - * @param string $plugin_path Plugin path. (default: ''). fallback file from plugin
173 + * @param string $plugin_path Plugin path. (default: ''). fallback file from plugin.
125 174 *
126 175 * @return mixed|void
127 176 */
128 177 public static function locate_template( $template_name, $template_path = '', $plugin_path = '' ) {
129 - $template_name = $template_name . '.php';
178 + $template_name = self::sanitize_file_name( $template_name ) . '.php';
179 +
130 180 if ( ! $template_path ) {
131 181 $template_path = rtsb()->get_template_path();
132 182 }
133 183 if ( ! $plugin_path ) {
@@ -170,8 +220,19 @@
170 220 return apply_filters( 'rtsb/core/locate_template', $located, $template_name );
171 221 }
172 222
173 223 /**
224 + * Remove any character that is not alphanumeric, /, _, or -.
225 + *
226 + * @param string $name Name to sanitize.
227 + *
228 + * @return array|string|string[]|null
229 + */
230 + private static function sanitize_file_name( $name ) {
231 + return preg_replace( '/[^a-zA-Z0-9\/_\-]/', '', $name );
232 + }
233 +
234 + /**
174 235 * Template Content
175 236 *
176 237 * @param string $template_name Template name.
177 238 * @param array $args Arguments. (default: array).
@@ -319,8 +380,9 @@
319 380 $cache_key = 'rtsb_prepared_product_id';
320 381 $_post_id = wp_cache_get( $cache_key );
321 382
322 383 if ( false === $_post_id || 'publish' !== get_post_status( $_post_id ) ) {
384 + // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
323 385 $_post_id = $wpdb->get_var(
324 386 $wpdb->prepare( "SELECT MAX(ID) FROM {$wpdb->prefix}posts WHERE post_type = %s AND post_status IN('publish', 'draft')", 'product' )
325 387 );
326 388 wp_cache_set( $cache_key, $_post_id, '', 12 * HOUR_IN_SECONDS );
@@ -361,9 +423,9 @@
361 423 * @return void
362 424 */
363 425 public static function doing_it_wrong( $function, $message, $version ) {
364 426 $message .= ' Backtrace: ' . wp_debug_backtrace_summary();
365 - _doing_it_wrong( $function, $message, $version );
427 + _doing_it_wrong( esc_html( $function ), wp_kses_post( $message ), esc_html( $version ) );
366 428 }
367 429
368 430 /**
369 431 * @return array
@@ -494,13 +556,14 @@
494 556 }
495 557
496 558 if ( strlen( $page_content ) > 0 ) {
497 559 // Search for an existing page with the specified page content (typically a shortcode).
498 - $shortcode = str_replace( [ '<!-- wp:shortcode -->', '<!-- /wp:shortcode -->' ], '', $page_content );
560 + $shortcode = str_replace( [ '<!-- wp:shortcode -->', '<!-- /wp:shortcode -->' ], '', $page_content );
561 + // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
499 562 $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}%" ) );
500 563 } else {
501 564 // Search for an existing page with the specified page slug.
502 - $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 ) );
565 + $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
503 566 }
504 567
505 568 $valid_page_found = apply_filters( 'rtsb/core/create_page_id', $valid_page_found, $slug, $page_content, $options );
506 569
@@ -522,12 +585,12 @@
522 585
523 586 // Search for a matching valid trashed page.
524 587 if ( strlen( $page_content ) > 0 ) {
525 588 // Search for an existing page with the specified page content (typically a shortcode).
526 - $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}%" ) );
589 + $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
527 590 } else {
528 591 // Search for an existing page with the specified page slug.
529 - $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 ) );
592 + $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
530 593 }
531 594
532 595 if ( $trashed_page_found ) {
533 596 $page_id = $trashed_page_found;
@@ -1029,9 +1092,14 @@
1029 1092 if ( isset( self::$cache[ $cache_key ] ) ) {
1030 1093 return self::$cache[ $cache_key ];
1031 1094 }
1032 1095
1033 - $termList = get_terms( [ $taxonomy ], [ 'hide_empty' => 0 ] );
1096 + $termList = get_terms(
1097 + [
1098 + 'taxonomy' => $taxonomy,
1099 + 'hide_empty' => false,
1100 + ]
1101 + );
1034 1102
1035 1103 if ( is_array( $termList ) && ! empty( $termList ) && empty( $termList['errors'] ) ) {
1036 1104 if ( $placeholder ) {
1037 1105 $terms = [
@@ -1060,9 +1128,9 @@
1060 1128
1061 1129 if ( $attributes ) {
1062 1130 foreach ( $attributes as $tax ) {
1063 1131 if ( taxonomy_exists( wc_attribute_taxonomy_name( $tax->attribute_name ) ) ) {
1064 - $termList[ $tax->attribute_name ] = get_terms( wc_attribute_taxonomy_name( $tax->attribute_name ), 'orderby=name&hide_empty=0' );
1132 + $termList[ $tax->attribute_name ] = get_terms( wc_attribute_taxonomy_name( $tax->attribute_name ) );
1065 1133 }
1066 1134 }
1067 1135 }
1068 1136
@@ -1257,8 +1325,23 @@
1257 1325
1258 1326 self::print_html( $html, true );
1259 1327 }
1260 1328
1329 + public static function get_product_simple_rating_html() {
1330 + global $product;
1331 + $html = null;
1332 + $rating_count = $product->get_rating_count();
1333 + $average_rating = $product->get_average_rating();
1334 + $html .= '<div class="product-rating">';
1335 + $html .= wc_get_rating_html( $average_rating, $rating_count );
1336 + $html .= ! empty( $html ) ? '<span class="rtsb-count">(' . $average_rating . ')</span>' : '';
1337 + $html .= '</div>';
1338 +
1339 + self::print_html( $html, true );
1340 + }
1341 +
1342 +
1343 +
1261 1344 /**
1262 1345 * Text truncation.
1263 1346 *
1264 1347 * @param string $text_to_truncate Text.
@@ -1741,10 +1824,10 @@
1741 1824 *
1742 1825 * @return string
1743 1826 */
1744 1827 public static function custom_pagination( $pages = '', $range = 4, $ajax = false ) {
1745 - $html = null;
1746 - $showitems = ( $range * 2 ) + 1;
1828 + $html = null;
1829 + $visible_range = apply_filters( 'rtsb/elements/pagination/visible_range', ( $range * 2 ) + 1 );
1747 1830
1748 1831 global $paged;
1749 1832
1750 1833 if ( is_front_page() ) {
@@ -1772,8 +1855,9 @@
1772 1855
1773 1856 if ( $ajax ) {
1774 1857 $ajaxClass = ' rtsb-pagination-ajax';
1775 1858 $dataAttr = "data-paged='1'";
1859 + $dataAttr .= ' data-visible-range="' . esc_attr( $visible_range ) . '"';
1776 1860 }
1777 1861
1778 1862 if ( 1 !== $pages ) {
1779 1863 $html .= '<div class="rtsb-pagination' . $ajaxClass . '" ' . $dataAttr . '>';
@@ -1778,29 +1862,29 @@
1778 1862 if ( 1 !== $pages ) {
1779 1863 $html .= '<div class="rtsb-pagination' . $ajaxClass . '" ' . $dataAttr . '>';
1780 1864 $html .= '<ul class="pagination-list">';
1781 1865
1782 - if ( $paged > 2 && $paged > $range + 1 && $showitems < $pages ) {
1866 + if ( $paged > 2 && $paged > $visible_range + 1 && $visible_range < $pages ) {
1783 1867 $html .= "<li><a data-paged='1' href='" . get_pagenum_link( 1 ) . "' aria-label='First'>&laquo;</a></li>";
1784 1868 }
1785 1869
1786 - if ( $paged > 1 && $showitems < $pages ) {
1870 + if ( $paged > 1 && $visible_range < $pages ) {
1787 1871 $p = $paged - 1;
1788 1872 $html .= "<li><a data-paged='{$p}' href='" . get_pagenum_link( $p ) . "' aria-label='Previous'>&lsaquo;</a></li>";
1789 1873 }
1790 1874
1791 1875 for ( $i = 1; $i <= $pages; $i++ ) {
1792 - if ( 1 != $pages && ( ! ( $i >= $paged + $range + 1 || $i <= $paged - $range - 1 ) || $pages <= $showitems ) ) {
1876 + if ( 1 != $pages && ( ! ( $i >= $paged + $visible_range + 1 || $i <= $paged - $visible_range - 1 ) || $pages <= $visible_range ) ) {
1793 1877 $html .= ( $paged == $i ) ? '<li class="active"><span>' . $i . '</span></li>' : "<li><a data-paged='{$i}' href='" . get_pagenum_link( $i ) . "'>" . $i . '</a></li>';
1794 1878 }
1795 1879 }
1796 1880
1797 - if ( $paged < $pages && $showitems < $pages ) {
1881 + if ( $paged < $pages && $visible_range < $pages ) {
1798 1882 $p = $paged + 1;
1799 1883 $html .= "<li><a data-paged='{$p}' href=\"" . get_pagenum_link( $paged + 1 ) . "\" aria-label='Next'>&rsaquo;</a></li>";
1800 1884 }
1801 1885
1802 - if ( $paged < $pages - 1 && $paged + $range - 1 < $pages && $showitems < $pages ) {
1886 + if ( $paged < $pages - 1 && $paged + $range - 1 < $pages && $visible_range < $pages ) {
1803 1887 $html .= "<li><a data-paged='{$pages}' href='" . get_pagenum_link( $pages ) . "' aria-label='Last'>&raquo;</a></li>";
1804 1888 }
1805 1889
1806 1890 $html .= '</ul>';
@@ -2158,9 +2242,8 @@
2158 2242 return true;
2159 2243 }
2160 2244 }
2161 2245
2162 -
2163 2246 /***
2164 2247 * Save Settings data
2165 2248 *
2166 2249 * @param $section_id
@@ -2172,10 +2255,9 @@
2172 2255 public static function set_options( $section_id = '', $block_id = '', $rawOptions = [] ) {
2173 2256 $section_id = ! empty( $section_id ) ? sanitize_text_field( wp_unslash( $section_id ) ) : '';
2174 2257 $block_id = ! empty( $block_id ) ? sanitize_text_field( wp_unslash( $block_id ) ) : '';
2175 2258 $rawOptions = ! empty( $rawOptions ) ? $rawOptions : [];
2176 -
2177 - $results = [
2259 + $results = [
2178 2260 'status' => true,
2179 2261 'message' => '',
2180 2262 ];
2181 2263 if ( ! $section_id || ! $block_id ) {
@@ -2228,10 +2310,16 @@
2228 2310 } else {
2229 2311 $value = [];
2230 2312 }
2231 2313 } else {
2232 - if ( ! empty( $field['sanitize_fn'] ) && is_callable( $field['sanitize_fn'] ) ) {
2233 - $value = $field['sanitize_fn']( $raw_value );
2314 + if ( ! empty( $field['sanitize_fn'] ) ) {
2315 + if ( is_callable( $field['sanitize_fn'] ) ) {
2316 + $value = $field['sanitize_fn']( $raw_value );
2317 + } elseif ( 'pass_all' === $field['sanitize_fn'] ) {
2318 + $value = $raw_value;
2319 + } else {
2320 + $value = $field['sanitize_fn']( $raw_value );
2321 + }
2234 2322 } else {
2235 2323 $value = sanitize_text_field( $raw_value );
2236 2324 }
2237 2325 }
@@ -2328,8 +2416,9 @@
2328 2416
2329 2417 foreach ( $elmap->get_widget_data( 'rtsb-ajax-product-filters', [], $id ) as $data ) {
2330 2418 $ajax[] = isset( $data['settings']['ajax_mode'] ) ? false : true;
2331 2419 }
2420 +
2332 2421 self::$cache[ $cache_key ] = ! empty( $ajax[0] );
2333 2422 return ! empty( $ajax[0] );
2334 2423 }
2335 2424
@@ -2387,14 +2476,14 @@
2387 2476 WHERE tt.taxonomy = 'product_cat'";
2388 2477
2389 2478 if ( $search_query ) {
2390 2479 $sql .= ' AND t.name LIKE %s';
2391 - $prepared_sql = $wpdb->prepare( $sql, '%' . $wpdb->esc_like( $search_query ) . '%' ); // Escaping and wildcard
2480 + $prepared_sql = $wpdb->prepare( $sql, '%' . $wpdb->esc_like( $search_query ) . '%' ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
2392 2481 } else {
2393 2482 $prepared_sql = $sql; // No need for placeholders.
2394 2483 }
2395 2484
2396 - $results = $wpdb->get_results( $prepared_sql );
2485 + $results = $wpdb->get_results( $prepared_sql ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.PreparedSQL.NotPrepared
2397 2486 // Cache the results in the object cache for future use.
2398 2487 wp_cache_set( $cache_key, $results ); // Adjust the expiration time as needed.
2399 2488 }
2400 2489
@@ -2487,8 +2576,9 @@
2487 2576 'post_type' => 'any',
2488 2577 'posts_per_page' => 20,
2489 2578 'orderby' => 'ID',
2490 2579 'order' => 'DESC',
2580 + // 'suppress_filters' => false, // WPML Support, Remove Others Languages.
2491 2581 ]
2492 2582 );
2493 2583
2494 2584 if ( 'archive' !== $args['post_type'] ) {
@@ -2499,9 +2589,9 @@
2499 2589 $query_results = get_posts( $args );
2500 2590 foreach ( $query_results as $post ) {
2501 2591 $posts[] = [
2502 2592 'value' => $post->ID,
2503 - 'label' => $post->post_title,
2593 + 'label' => $post->post_title . ' (' . $post->ID . ')',
2504 2594 ];
2505 2595 }
2506 2596 if ( $search_query ) {
2507 2597 if ( strpos( '-error 404', $search_query ) ) {
@@ -2599,9 +2689,9 @@
2599 2689 ",
2600 2690 $minimum_sale,
2601 2691 $limit
2602 2692 );
2603 - $best_selling = $wpdb->get_col( $sql );
2693 + $best_selling = $wpdb->get_col( $sql ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared
2604 2694 // Cache the result for future use.
2605 2695 set_transient( $cache_key, $best_selling, DAY_IN_SECONDS );
2606 2696 self::$cache[ $cache_key ] = $best_selling;
2607 2697 return $best_selling;
@@ -2671,6 +2761,185 @@
2671 2761 echo '<div class="rtsb-notice">';
2672 2762 woocommerce_output_all_notices();
2673 2763 echo '</div>';
2674 2764 endif;
2765 + }
2766 +
2767 + /**
2768 + * @param object $product Product.
2769 + * @return bool
2770 + */
2771 + public static function is_visible_qty_input( $product = null ) {
2772 + $is_visible_qty = true;
2773 + if ( $product instanceof \WC_Product ) {
2774 + if ( $product->is_sold_individually() ) {
2775 + $is_visible_qty = false;
2776 + } elseif ( $product->managing_stock() ) {
2777 + if ( in_array( $product->get_backorders(), [ 'notify' , 'yes' ], true ) ) {
2778 + $is_visible_qty = true;
2779 + } elseif ( $product->get_stock_quantity() < 2 ) {
2780 + $is_visible_qty = false;
2781 + }
2782 + }
2783 + }
2784 + return $is_visible_qty;
2785 + }
2786 +
2787 + /**
2788 + * @param int $object_id Object id.
2789 + * @param string $element_type element type.
2790 + * @param string|null $current_lang null for current language, default for default languages.
2791 + * @return false|mixed|null
2792 + */
2793 + public static function wpml_object_id( $object_id, $element_type, $current_lang = 'default' ) {
2794 + if ( ! defined( 'ICL_SITEPRESS_VERSION' ) ) {
2795 + return $object_id;
2796 + }
2797 + if ( ! $object_id || ! $element_type ) {
2798 + return $object_id;
2799 + }
2800 + if ( 'default' === $current_lang ) {
2801 + $lang = apply_filters( 'wpml_default_language', null );
2802 + } else {
2803 + $lang = null;
2804 + }
2805 + return apply_filters( 'wpml_object_id', $object_id, $element_type, false, $lang );
2806 + }
2807 +
2808 + /**
2809 + * @return string
2810 + */
2811 + public static function wpml_current_language() {
2812 + $current = apply_filters( 'wpml_current_language', null );
2813 + $default = apply_filters( 'wpml_default_language', null );
2814 + return $default !== $current ? $current : null;
2815 + }
2816 +
2817 + /**
2818 + * Custom icons.
2819 + *
2820 + * @return string[]
2821 + */
2822 + public static function get_custom_icon_names() {
2823 + return [
2824 + 'heart-empty',
2825 + 'heart',
2826 + 'eye',
2827 + 'exchange',
2828 + 'plus',
2829 + 'minus',
2830 + 'avatar',
2831 + 'pay',
2832 + 'share',
2833 + 'clock',
2834 + 'check-alt',
2835 + 'check',
2836 + 'delete',
2837 + 'marker',
2838 + 'list',
2839 + 'list-2',
2840 + 'power',
2841 + 'cart',
2842 + 'cart-2',
2843 + 'cart-3',
2844 + 'downloads',
2845 + 'zoom',
2846 + 'user-edit',
2847 + 'grid',
2848 + 'filter',
2849 + 'billing',
2850 + 'login',
2851 + 'payment',
2852 + 'search',
2853 + 'edit',
2854 + 'coupon',
2855 + 'arrows-cw',
2856 + 'trash-empty',
2857 + ];
2858 + }
2859 +
2860 + /**
2861 + * Flushes rewrite rules.
2862 + *
2863 + * @return void
2864 + */
2865 + public static function maybe_flush_rewrite_rules() {
2866 + add_action( 'wp_loaded', [ __CLASS__, 'flush_rewrite_rules' ] );
2867 + add_action( 'shutdown', [ __CLASS__, 'flush_rewrite_rules_once_more' ] );
2868 + }
2869 +
2870 + /**
2871 + * Flushes rewrite rules if needed.
2872 + *
2873 + * @return void
2874 + */
2875 + public static function flush_rewrite_rules() {
2876 + if ( get_option( 'rtsb_permalinks_need_flush' ) === 'yes' ) {
2877 + flush_rewrite_rules();
2878 + }
2879 +
2880 + if ( get_option( 'rtsb_permalinks_flushed' ) === 'yes' ) {
2881 + flush_rewrite_rules();
2882 + delete_option( 'rtsb_permalinks_flushed' );
2883 + }
2884 + }
2885 +
2886 + /**
2887 + * Flushes rewrite rules if needed for second time.
2888 + *
2889 + * @return void
2890 + */
2891 + public static function flush_rewrite_rules_once_more() {
2892 + if ( get_option( 'rtsb_permalinks_need_flush' ) === 'yes' ) {
2893 + flush_rewrite_rules();
2894 + update_option( 'rtsb_permalinks_flushed', 'yes' );
2895 + delete_option( 'rtsb_permalinks_need_flush' );
2896 + }
2897 + }
2898 +
2899 + /**
2900 + * Social Share Platforms.
2901 + *
2902 + * @return mixed|null
2903 + */
2904 + public static function set_repeater_options( $section_id, $block_id, $option_key, $compare_key, $compare_value, $values ) {
2905 + // $options = self::get_options( $section_id, $block_id );
2906 + $modules = DataModel::source()->get_option( $section_id, [], false );
2907 + if ( empty( $modules[ $block_id ] ) ) {
2908 + return;
2909 + }
2910 + $options = $modules[ $block_id ];
2911 + if ( empty( $options[ $option_key ] ) ) {
2912 + return;
2913 + }
2914 + $repeater_options = json_decode( $options[ $option_key ], true );
2915 + // Check if options are not empty and are in array format.
2916 + if ( ! is_array( $repeater_options ) ) {
2917 + return;
2918 + }
2919 + // Use array_column to get an array of values from $compare_key.
2920 + $column_values = array_column( $repeater_options, $compare_key );
2921 + // Use array_search to find the index of the $compare_value.
2922 + $index = array_search( $compare_value, $column_values, true );
2923 + if ( false === $index ) {
2924 + return;
2925 + }
2926 + $repeater_options[ $index ] = wp_parse_args( $values, $repeater_options[ $index ] );
2927 + $options[ $option_key ] = wp_json_encode( $repeater_options );
2928 + self::set_options( $section_id, $block_id, $options );
2929 + }
2930 +
2931 +
2932 + /**
2933 + * @param array $ids products id.
2934 + * @return array
2935 + */
2936 + public static function get_available_products_by_ids( $ids = [] ) {
2937 + $ids = array_filter(
2938 + $ids,
2939 + function ( $id ) {
2940 + return 'product' === get_post_type( $id ) && 'publish' === get_post_status( $id );
2941 + }
2942 + );
2943 + return $ids;
2675 2944 }
2676 2945 }