| @@ -11,24 +11,15 @@ | ||
| 11 | 11 | if ( ! defined( 'ABSPATH' ) ) { |
| 12 | 12 | exit( 'This script cannot be accessed directly.' ); |
| 13 | 13 | } |
| 14 | 14 | |
| 15 | - | |
| 16 | -use RadiusTheme\SB\Dependencies\CodesVault\Howdyqb\DB; | |
| 17 | -use DateTime; | |
| 18 | -use WP_Query; | |
| 19 | -use WP_Styles; | |
| 20 | 15 | use WC_Product; |
| 21 | -use Elementor\Plugin; | |
| 22 | 16 | use WC_Product_Query; |
| 23 | 17 | use Elementor\Icons_Manager; |
| 24 | 18 | use RadiusTheme\SB\Models\ReSizer; |
| 25 | -use RadiusTheme\SB\Models\Settings; | |
| 26 | 19 | use RadiusTheme\SB\Models\DataModel; |
| 27 | 20 | use RadiusTheme\SB\Models\ModuleList; |
| 28 | -use RadiusTheme\SB\Models\GeneralList; | |
| 29 | -use RadiusTheme\SB\Models\ElementList; | |
| 30 | -use RadiusTheme\SB\Controllers\AssetRegistry; | |
| 21 | +use RadiusTheme\SB\Models\Settings; | |
| 31 | 22 | |
| 32 | 23 | /** |
| 33 | 24 | * Fns class |
| 34 | 25 | */ |
| @@ -39,89 +30,8 @@ | ||
| 39 | 30 | */ |
| 40 | 31 | private static $cache = []; |
| 41 | 32 | |
| 42 | 33 | /** |
| 43 | - * Whether asset bundling failed during this request. | |
| 44 | - * | |
| 45 | - * Set by AssetRegistry when AssetBundler::build() cannot produce a file, for | |
| 46 | - * example on the first request after a plugin upgrade while the autoloader | |
| 47 | - * still points at the removed files, or when the cache directory turns out | |
| 48 | - * not to be writable. Once set, is_optimization_enabled() reports false for | |
| 49 | - * the remainder of the request so the callers register and enqueue the plain | |
| 50 | - * unbundled assets instead of a stylesheet handle with an empty source. | |
| 51 | - * | |
| 52 | - * Request scoped on purpose: it must not be persisted, the next request | |
| 53 | - * retries the build. | |
| 54 | - * | |
| 55 | - * @var bool | |
| 56 | - */ | |
| 57 | - private static $optimization_unavailable = false; | |
| 58 | - | |
| 59 | - /** | |
| 60 | - * Flag that a bundle could not be produced during this request. | |
| 61 | - * | |
| 62 | - * @return void | |
| 63 | - */ | |
| 64 | - public static function mark_optimization_unavailable() { | |
| 65 | - self::$optimization_unavailable = true; | |
| 66 | - } | |
| 67 | - | |
| 68 | - /** | |
| 69 | - * Whether bundling has been marked unavailable for this request. | |
| 70 | - * | |
| 71 | - * @return bool | |
| 72 | - */ | |
| 73 | - public static function is_optimization_unavailable() { | |
| 74 | - return self::$optimization_unavailable; | |
| 75 | - } | |
| 76 | - | |
| 77 | - /** | |
| 78 | - * Check if the stored license is valid. Its Only Show Pro Label. | |
| 79 | - * | |
| 80 | - * @return bool | |
| 81 | - */ | |
| 82 | - public static function has_valid_license() { | |
| 83 | - static $cached_result = null; | |
| 84 | - // Return cached result if already calculated in this request. | |
| 85 | - if ( null !== $cached_result ) { | |
| 86 | - return $cached_result; | |
| 87 | - } | |
| 88 | - $license_status = rtsb()->has_pro() ? rtsbpro()->get_license( 'license_status' ) : ''; | |
| 89 | - return 'valid' === $license_status; | |
| 90 | - } | |
| 91 | - | |
| 92 | - /** | |
| 93 | - * Check if license is valid or bypassed by theme, | |
| 94 | - * | |
| 95 | - * @return bool | |
| 96 | - */ | |
| 97 | - public static function is_pro_authorized() { | |
| 98 | - static $cached_result = null; | |
| 99 | - if ( null !== $cached_result ) { | |
| 100 | - return $cached_result; | |
| 101 | - } | |
| 102 | - // ❗ Step 2: If Pro not installed → no access. | |
| 103 | - if ( ! function_exists( 'rtsbpro' ) ) { | |
| 104 | - $cached_result = false; | |
| 105 | - return $cached_result; | |
| 106 | - } | |
| 107 | - $current_theme = wp_get_theme()->get_stylesheet(); // Child theme And Parent Theme Need Check work or not. | |
| 108 | - /** | |
| 109 | - * Allowed themes (bypass license) | |
| 110 | - * | |
| 111 | - * @param array $themes | |
| 112 | - */ | |
| 113 | - $allowed_themes = apply_filters( 'rt_pro_access_allowed_themes', [] ); | |
| 114 | - // ✅ Step 1: Theme bypass (no license check). | |
| 115 | - if ( in_array( $current_theme, $allowed_themes, true ) ) { | |
| 116 | - $cached_result = true; | |
| 117 | - return true; | |
| 118 | - } | |
| 119 | - // ✅ Step 3: Normal license validation | |
| 120 | - $license_status = rtsbpro()->get_license( 'license_status' ); | |
| 121 | - return ( 'valid' === $license_status ); | |
| 122 | - } | |
| 123 | - /** | |
| 124 | 34 | * Verify nonce. |
| 125 | 35 | * |
| 126 | 36 | * @return bool |
| 127 | 37 | */ |
| @@ -134,36 +44,8 @@ | ||
| 134 | 44 | |
| 135 | 45 | return false; |
| 136 | 46 | } |
| 137 | 47 | |
| 138 | - /** | |
| 139 | - * Get nonce. | |
| 140 | - * | |
| 141 | - * @return string|null | |
| 142 | - */ | |
| 143 | - public static function enable_loader() { | |
| 144 | - return 'on' !== self::get_option( 'general', 'optimization', 'remove_pre_loader', '' ); | |
| 145 | - } | |
| 146 | - /** | |
| 147 | - * Get nonce. | |
| 148 | - * | |
| 149 | - * @return string|null | |
| 150 | - */ | |
| 151 | - public static function content_invisible() { | |
| 152 | - $wp_rocket_compatibility = 'on' !== self::get_option( 'general', 'optimization', 'wp_rocket_compatibility', '' ); | |
| 153 | - if ( $wp_rocket_compatibility ) { | |
| 154 | - return true; | |
| 155 | - } | |
| 156 | - if ( defined( 'WP_ROCKET_VERSION' ) ) { | |
| 157 | - return false; | |
| 158 | - } | |
| 159 | - return true; | |
| 160 | - } | |
| 161 | - /** | |
| 162 | - * Get nonce. | |
| 163 | - * | |
| 164 | - * @return string|null | |
| 165 | - */ | |
| 166 | 48 | public static function get_nonce() { |
| 167 | 49 | // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized |
| 168 | 50 | return isset( $_REQUEST[ rtsb()->nonceId ] ) ? sanitize_text_field( $_REQUEST[ rtsb()->nonceId ] ) : null; |
| 169 | 51 | } |
| @@ -168,12 +50,12 @@ | ||
| 168 | 50 | return isset( $_REQUEST[ rtsb()->nonceId ] ) ? sanitize_text_field( $_REQUEST[ rtsb()->nonceId ] ) : null; |
| 169 | 51 | } |
| 170 | 52 | |
| 171 | 53 | /** |
| 172 | - * Set Session | |
| 54 | + * Set Cookie or Session | |
| 173 | 55 | * |
| 174 | - * @param string $name Name. | |
| 175 | - * @param mixed $value Value. | |
| 56 | + * @param $name | |
| 57 | + * @param $value | |
| 176 | 58 | */ |
| 177 | 59 | public static function setSession( $name, $value ) { |
| 178 | 60 | if ( ! headers_sent() && session_status() == PHP_SESSION_NONE ) { |
| 179 | 61 | session_start(); |
| @@ -181,13 +63,12 @@ | ||
| 181 | 63 | } else { |
| 182 | 64 | $_SESSION[ $name ] = $value; |
| 183 | 65 | } |
| 184 | 66 | } |
| 185 | - | |
| 186 | 67 | /** |
| 187 | 68 | * Get Cookie or Session |
| 188 | 69 | * |
| 189 | - * @param string $name Name. | |
| 70 | + * @param $name | |
| 190 | 71 | * |
| 191 | 72 | * @return bool |
| 192 | 73 | */ |
| 193 | 74 | public static function getSession( $name ) { |
| @@ -208,43 +89,12 @@ | ||
| 208 | 89 | } else { |
| 209 | 90 | unset( $_SESSION[ $name ] ); |
| 210 | 91 | } |
| 211 | 92 | } |
| 93 | + | |
| 212 | 94 | /** |
| 213 | - * Gets the current timestamp in WordPress timezone. | |
| 95 | + * @param $plugin_slug | |
| 214 | 96 | * |
| 215 | - * @return int Current timestamp. | |
| 216 | - */ | |
| 217 | - public static function currentTimestampUTC() { | |
| 218 | - $wp_timezone = wp_timezone(); | |
| 219 | - $now = new DateTime( 'now', $wp_timezone ); // Current time in WP timezone. | |
| 220 | - return $now->getTimestamp(); | |
| 221 | - } | |
| 222 | - /** | |
| 223 | - * Action. | |
| 224 | - * | |
| 225 | - * @param string $action action. | |
| 226 | - * @return void | |
| 227 | - */ | |
| 228 | - public static function add_to_scheduled_hook_list( $action ) { | |
| 229 | - if ( empty( $action ) ) { | |
| 230 | - return; | |
| 231 | - } | |
| 232 | - $schedule = get_option( 'rtsb_cron_schedule_free', [] ); | |
| 233 | - $schedule[] = $action; | |
| 234 | - update_option( 'rtsb_cron_schedule_free', array_unique( $schedule ) ); | |
| 235 | - } | |
| 236 | - /** | |
| 237 | - * @return DB | |
| 238 | - */ | |
| 239 | - public static function DB() { | |
| 240 | - return new DB( 'wpdb' ); | |
| 241 | - } | |
| 242 | - /** | |
| 243 | - * Check if a plugin is installed. | |
| 244 | - * | |
| 245 | - * @param string $plugin_slug Plugin slug. | |
| 246 | - * | |
| 247 | 97 | * @return bool |
| 248 | 98 | */ |
| 249 | 99 | public static function check_plugin_installed( $plugin_slug ): bool { |
| 250 | 100 | $installed_plugins = get_plugins(); |
| @@ -252,12 +102,10 @@ | ||
| 252 | 102 | return array_key_exists( $plugin_slug, $installed_plugins ) || in_array( $plugin_slug, $installed_plugins, true ); |
| 253 | 103 | } |
| 254 | 104 | |
| 255 | 105 | /** |
| 256 | - * Check if a plugin is active. | |
| 106 | + * @param $plugin_slug | |
| 257 | 107 | * |
| 258 | - * @param string $plugin_slug Plugin slug. | |
| 259 | - * | |
| 260 | 108 | * @return bool |
| 261 | 109 | */ |
| 262 | 110 | public static function check_plugin_active( $plugin_slug ): bool { |
| 263 | 111 | if ( is_plugin_active( $plugin_slug ) ) { |
| @@ -268,9 +116,9 @@ | ||
| 268 | 116 | } |
| 269 | 117 | /** |
| 270 | 118 | * Get all user roles. |
| 271 | 119 | * |
| 272 | - * @return array | |
| 120 | + * @return array|false|mixed | |
| 273 | 121 | */ |
| 274 | 122 | public static function get_current_user_roles() { |
| 275 | 123 | $current_user = wp_get_current_user(); |
| 276 | 124 | return $current_user->roles; |
| @@ -280,20 +128,10 @@ | ||
| 280 | 128 | * |
| 281 | 129 | * @return array|false|mixed |
| 282 | 130 | */ |
| 283 | 131 | public static function get_all_user_roles() { |
| 284 | - // Memoized because the settings schema asks for the role list several | |
| 285 | - // times per request, and the miss path require_once()s an admin-only | |
| 286 | - // WordPress file. The static also covers the legitimate empty-result | |
| 287 | - // case, which wp_cache_get() alone cannot distinguish from a miss. | |
| 288 | - static $memo = null; | |
| 289 | - | |
| 290 | - if ( null !== $memo ) { | |
| 291 | - return $memo; | |
| 292 | - } | |
| 293 | - | |
| 294 | 132 | $cache_key = 'rtsb_get_user_roles'; |
| 295 | - $roles = wp_cache_get( $cache_key, Cache::group() ); | |
| 133 | + $roles = wp_cache_get( $cache_key, 'shopbuilder' ); | |
| 296 | 134 | |
| 297 | 135 | if ( empty( $roles ) ) { |
| 298 | 136 | if ( ! function_exists( 'get_editable_roles' ) ) { |
| 299 | 137 | require_once ABSPATH . 'wp-admin/includes/user.php'; |
| @@ -307,45 +145,26 @@ | ||
| 307 | 145 | continue; |
| 308 | 146 | } |
| 309 | 147 | $roles[ $key ] = $role['name']; |
| 310 | 148 | } |
| 311 | - | |
| 312 | - // Only prime the object cache on a miss. Re-writing it on every hit | |
| 313 | - // also re-appended the key to the tracked data-cache index. | |
| 314 | - wp_cache_set( $cache_key, $roles, Cache::group(), 12 * HOUR_IN_SECONDS ); | |
| 315 | - Cache::set_data_cache_key( $cache_key ); | |
| 316 | 149 | } |
| 317 | - | |
| 318 | - $memo = $roles; | |
| 319 | - | |
| 320 | - return $memo; | |
| 150 | + wp_cache_set( $cache_key, $roles, 'shopbuilder' ); | |
| 151 | + Cache::set_data_cache_key( $cache_key ); | |
| 152 | + return $roles; | |
| 321 | 153 | } |
| 322 | 154 | |
| 323 | 155 | /** |
| 324 | - * Stripslashes value. | |
| 156 | + * @param $data | |
| 325 | 157 | * |
| 326 | - * @param mixed $data Data. | |
| 327 | - * | |
| 328 | 158 | * @return mixed|string |
| 329 | 159 | */ |
| 330 | 160 | public static function stripslashes_value( $data ) { |
| 331 | - if ( is_array( $data ) ) { | |
| 161 | + if ( is_string( $data ) && strpos( $data, '\\' ) !== false ) { | |
| 162 | + return stripslashes( $data ); | |
| 163 | + } elseif ( is_array( $data ) ) { | |
| 332 | 164 | foreach ( $data as $key => $value ) { |
| 333 | 165 | $data[ $key ] = self::stripslashes_value( $value ); |
| 334 | 166 | } |
| 335 | - } elseif ( is_string( $data ) ) { | |
| 336 | - $trimmed = trim( $data ); | |
| 337 | - // Try to decode JSON. | |
| 338 | - $json = json_decode( $trimmed, true ); | |
| 339 | - if ( json_last_error() === JSON_ERROR_NONE && is_array( $json ) ) { | |
| 340 | - // Recursively stripslashes on decoded array. | |
| 341 | - $json = self::stripslashes_value( $json ); | |
| 342 | - return wp_json_encode( $json, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE ); | |
| 343 | - } | |
| 344 | - // Not valid JSON, just stripslashes if needed. | |
| 345 | - if ( strpos( $data, '\\' ) !== false ) { | |
| 346 | - return stripslashes( $data ); | |
| 347 | - } | |
| 348 | 167 | } |
| 349 | 168 | |
| 350 | 169 | return $data; |
| 351 | 170 | } |
| @@ -350,12 +169,10 @@ | ||
| 350 | 169 | return $data; |
| 351 | 170 | } |
| 352 | 171 | |
| 353 | 172 | /** |
| 354 | - * Multiselect settings field value | |
| 173 | + * @param $string | |
| 355 | 174 | * |
| 356 | - * @param string $string String. | |
| 357 | - * | |
| 358 | 175 | * @return array |
| 359 | 176 | */ |
| 360 | 177 | public static function multiselect_settings_field_value( $string ) { |
| 361 | 178 | |
| @@ -375,10 +192,8 @@ | ||
| 375 | 192 | return $values; |
| 376 | 193 | } |
| 377 | 194 | |
| 378 | 195 | /** |
| 379 | - * Check if is block theme | |
| 380 | - * | |
| 381 | 196 | * @return bool |
| 382 | 197 | */ |
| 383 | 198 | public static function check_is_block_theme(): bool { |
| 384 | 199 | global $wp_version; |
| @@ -386,10 +201,8 @@ | ||
| 386 | 201 | return version_compare( $wp_version, '5.9', '>=' ) && function_exists( 'wp_is_block_theme' ) && wp_is_block_theme(); |
| 387 | 202 | } |
| 388 | 203 | |
| 389 | 204 | /** |
| 390 | - * Locate template | |
| 391 | - * | |
| 392 | 205 | * @param string $template_name Template name. |
| 393 | 206 | * @param string $template_path Template path. (default: ''). |
| 394 | 207 | * @param string $plugin_path Plugin path. (default: ''). fallback file from plugin. |
| 395 | 208 | * |
| @@ -420,12 +233,12 @@ | ||
| 420 | 233 | ) |
| 421 | 234 | ); |
| 422 | 235 | |
| 423 | 236 | if ( ! $located ) { |
| 424 | - if ( $pro_plugin_path && rtsb()->has_pro() && file_exists( $pro_plugin_path ) ) { | |
| 237 | + if ( file_exists( $plugin_path ) ) { | |
| 238 | + return apply_filters( 'rtsb/core/locate_template', $plugin_path, $template_name ); | |
| 239 | + } elseif ( $pro_plugin_path && rtsb()->has_pro() && file_exists( $pro_plugin_path ) ) { | |
| 425 | 240 | return apply_filters( 'rtsb/core/locate_template', $pro_plugin_path, $template_name ); |
| 426 | - } elseif ( file_exists( $plugin_path ) ) { | |
| 427 | - return apply_filters( 'rtsb/core/locate_template', $plugin_path, $template_name ); | |
| 428 | 241 | } |
| 429 | 242 | } |
| 430 | 243 | |
| 431 | 244 | /** |
| @@ -462,11 +275,11 @@ | ||
| 462 | 275 | * @param string $plugin_path Fallback path from where file will load if fail to load from template. (default: ''). |
| 463 | 276 | * |
| 464 | 277 | * @return false|string|void |
| 465 | 278 | */ |
| 466 | - public static function load_template( $template_name, $args = null, $return = false, $template_path = '', $plugin_path = '' ) { | |
| 279 | + public static function load_template( $template_name, array $args = null, $return = false, $template_path = '', $plugin_path = '' ) { | |
| 467 | 280 | $cache_key = sanitize_key( implode( '-', [ 'template', $template_name, $template_path ] ) ); |
| 468 | - $located = (string) wp_cache_get( $cache_key, Cache::group() ); | |
| 281 | + $located = (string) wp_cache_get( $cache_key, 'shopbuilder' ); | |
| 469 | 282 | if ( ! $located ) { |
| 470 | 283 | $located = self::locate_template( $template_name, $template_path, $plugin_path ); |
| 471 | 284 | // Don't cache the absolute path so that it can be shared between web servers with different paths. |
| 472 | 285 | $cache_path = wc_tokenize_path( $located, wc_get_path_define_tokens() ); |
| @@ -475,14 +288,10 @@ | ||
| 475 | 288 | // Make sure that the absolute path to the template is resolved. |
| 476 | 289 | $located = wc_untokenize_path( $located, wc_get_path_define_tokens() ); |
| 477 | 290 | } |
| 478 | 291 | if ( ! file_exists( $located ) ) { |
| 479 | - // $located is empty when the template could not be found anywhere, | |
| 480 | - // so report the requested name instead of an empty path. | |
| 481 | - $reported = $located ? $located : $template_name; | |
| 482 | - | |
| 483 | 292 | // translators: %s template. |
| 484 | - self::doing_it_wrong( __FUNCTION__, sprintf( __( '%s does not exist.', 'shopbuilder' ), '<code>' . esc_html( $reported ) . '</code>' ), '1.0' ); | |
| 293 | + self::doing_it_wrong( __FUNCTION__, sprintf( __( '%s does not exist.', 'shopbuilder' ), '<code>' . $located . '</code>' ), '1.0' ); | |
| 485 | 294 | |
| 486 | 295 | return; |
| 487 | 296 | } |
| 488 | 297 | |
| @@ -604,9 +413,9 @@ | ||
| 604 | 413 | // Return the Builder Template id. |
| 605 | 414 | |
| 606 | 415 | if ( get_post_type( get_the_ID() ) == BuilderFns::$post_type_tb ) { |
| 607 | 416 | $product_id = get_post_meta( get_the_ID(), BuilderFns::$product_template_meta, true ); |
| 608 | - if ( $product_id && 'product' === get_post_type( $product_id ) && get_post_status( $product_id ) ) { | |
| 417 | + if ( $product_id && get_post_status( $product_id ) ) { | |
| 609 | 418 | return $product_id; |
| 610 | 419 | } |
| 611 | 420 | } |
| 612 | 421 | |
| @@ -611,15 +420,15 @@ | ||
| 611 | 420 | } |
| 612 | 421 | |
| 613 | 422 | global $wpdb; |
| 614 | 423 | $cache_key = 'rtsb_prepared_product_id'; |
| 615 | - $_post_id = wp_cache_get( $cache_key, Cache::group() ); | |
| 424 | + $_post_id = wp_cache_get( $cache_key, 'shopbuilder' ); | |
| 616 | 425 | if ( false === $_post_id || 'publish' !== get_post_status( $_post_id ) ) { |
| 617 | 426 | // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery |
| 618 | 427 | $_post_id = $wpdb->get_var( |
| 619 | 428 | $wpdb->prepare( "SELECT MAX(ID) FROM {$wpdb->prefix}posts WHERE post_type = %s AND post_status IN('publish', 'draft')", 'product' ) |
| 620 | 429 | ); |
| 621 | - wp_cache_set( $cache_key, $_post_id, Cache::group(), 12 * HOUR_IN_SECONDS ); | |
| 430 | + wp_cache_set( $cache_key, $_post_id, 'shopbuilder', 12 * HOUR_IN_SECONDS ); | |
| 622 | 431 | Cache::set_data_cache_key( $cache_key ); |
| 623 | 432 | } |
| 624 | 433 | |
| 625 | 434 | return $_post_id; |
| @@ -633,8 +442,9 @@ | ||
| 633 | 442 | public static function get_product() { |
| 634 | 443 | global $product; |
| 635 | 444 | |
| 636 | 445 | if ( is_singular( 'product' ) && $product instanceof WC_Product ) { |
| 446 | + // do_action( 'rtsb_before_product_template_render' );. | |
| 637 | 447 | return $product; |
| 638 | 448 | } |
| 639 | 449 | $cache_key = 'prepared_product_for_preview'; |
| 640 | 450 | if ( isset( self::$cache[ $cache_key ] ) ) { |
| @@ -664,17 +474,8 @@ | ||
| 664 | 474 | /** |
| 665 | 475 | * @return array |
| 666 | 476 | */ |
| 667 | 477 | public static function get_pages() { |
| 668 | - // Memoized because this only feeds admin select fields, yet the settings | |
| 669 | - // schema is built on every request and asks for it several times. Each | |
| 670 | - // miss runs a full get_pages() query and hydrates every page object. | |
| 671 | - static $memo = null; | |
| 672 | - | |
| 673 | - if ( null !== $memo ) { | |
| 674 | - return $memo; | |
| 675 | - } | |
| 676 | - | |
| 677 | 478 | $pages = []; |
| 678 | 479 | $rawPages = get_pages(); |
| 679 | 480 | if ( ! empty( $rawPages ) ) { |
| 680 | 481 | foreach ( $rawPages as $page ) { |
| @@ -681,20 +482,11 @@ | ||
| 681 | 482 | $pages[ $page->ID ] = $page->post_title; |
| 682 | 483 | } |
| 683 | 484 | } |
| 684 | 485 | |
| 685 | - $memo = $pages; | |
| 686 | - | |
| 687 | - return $memo; | |
| 486 | + return $pages; | |
| 688 | 487 | } |
| 689 | 488 | |
| 690 | - /** | |
| 691 | - * Get section items | |
| 692 | - * | |
| 693 | - * @param string $section_id Section ID. | |
| 694 | - * | |
| 695 | - * @return array | |
| 696 | - */ | |
| 697 | 489 | public static function get_section_items( $section_id ) { |
| 698 | 490 | if ( ! $section_id ) { |
| 699 | 491 | return []; |
| 700 | 492 | } |
| @@ -701,16 +493,8 @@ | ||
| 701 | 493 | |
| 702 | 494 | return DataModel::source()->get_option( $section_id, [] ); |
| 703 | 495 | } |
| 704 | 496 | |
| 705 | - /** | |
| 706 | - * Get options items | |
| 707 | - * | |
| 708 | - * @param string $section_id Section ID. | |
| 709 | - * @param string $item_id Item ID. | |
| 710 | - * | |
| 711 | - * @return array | |
| 712 | - */ | |
| 713 | 497 | public static function get_options( $section_id, $item_id ) { |
| 714 | 498 | if ( ! $section_id || ! $item_id ) { |
| 715 | 499 | return []; |
| 716 | 500 | } |
| @@ -721,11 +505,11 @@ | ||
| 721 | 505 | |
| 722 | 506 | /** |
| 723 | 507 | * Get options value with default value if options doesn't exist. |
| 724 | 508 | * |
| 725 | - * @param array $group Group. | |
| 726 | - * @param string $option_key Option key. | |
| 727 | - * @param string $default_value Default value. | |
| 509 | + * @param $group | |
| 510 | + * @param $option_key | |
| 511 | + * @param $default_value | |
| 728 | 512 | * |
| 729 | 513 | * @return mixed|string |
| 730 | 514 | */ |
| 731 | 515 | public static function get_options_by_default_val( $group, $option_key, $default_value = '' ) { |
| @@ -737,34 +521,32 @@ | ||
| 737 | 521 | return $group[ $option_key ]; |
| 738 | 522 | } |
| 739 | 523 | |
| 740 | 524 | /** |
| 741 | - * Get option. | |
| 525 | + * @param string $section_id | |
| 526 | + * @param string $item_id | |
| 527 | + * @param string $option_id | |
| 528 | + * @param null $default EXCEPT multi_checkbox you can provide default value if given option does not set any value | |
| 529 | + * @param null $type checkbox, multi_checkbox, number | |
| 742 | 530 | * |
| 743 | - * @param string $section_id Section ID. | |
| 744 | - * @param string $item_id Item ID. | |
| 745 | - * @param string $option_id Option ID. | |
| 746 | - * @param null $default EXCEPT multi_checkbox you can provide default value if given option does not set any value. | |
| 747 | - * @param null $type checkbox, multi_checkbox, number. | |
| 748 | - * | |
| 749 | 531 | * @return bool|int|mixed|null |
| 750 | 532 | */ |
| 751 | 533 | public static function get_option( $section_id, $item_id, $option_id, $default = null, $type = null ) { |
| 752 | 534 | $options = self::get_options( $section_id, $item_id ); |
| 753 | 535 | |
| 754 | - if ( 'checkbox' === $type ) { | |
| 536 | + if ( $type === 'checkbox' ) { | |
| 755 | 537 | if ( isset( $options[ $option_id ] ) ) { |
| 756 | - return 'on' === $options[ $option_id ]; | |
| 538 | + return $options[ $option_id ] === 'on'; | |
| 757 | 539 | } |
| 758 | 540 | |
| 759 | 541 | return $default; |
| 760 | - } elseif ( 'multi_checkbox' === $type ) { | |
| 761 | - return isset( $options[ $option_id ] ) && is_array( $options[ $option_id ] ) && in_array( $default, $options[ $option_id ] ); // phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict | |
| 762 | - } elseif ( 'number' === $type ) { | |
| 542 | + } elseif ( $type === 'multi_checkbox' ) { | |
| 543 | + return isset( $options[ $option_id ] ) && is_array( $options[ $option_id ] ) && in_array( $default, $options[ $option_id ] ); | |
| 544 | + } elseif ( $type === 'number' ) { | |
| 763 | 545 | return isset( $options[ $option_id ] ) ? absint( $options[ $option_id ] ) : absint( $default ); |
| 764 | 546 | } |
| 765 | 547 | |
| 766 | - return ! empty( $options[ $option_id ] ) ? $options[ $option_id ] : $default; | |
| 548 | + return isset( $options[ $option_id ] ) && ! empty( $options[ $option_id ] ) ? $options[ $option_id ] : $default; | |
| 767 | 549 | } |
| 768 | 550 | |
| 769 | 551 | |
| 770 | 552 | /** |
| @@ -891,13 +673,8 @@ | ||
| 891 | 673 | |
| 892 | 674 | return $page_id; |
| 893 | 675 | } |
| 894 | 676 | |
| 895 | - /** | |
| 896 | - * Get allowed HTML tags. | |
| 897 | - * | |
| 898 | - * @return array | |
| 899 | - */ | |
| 900 | 677 | public static function get_kses_array() { |
| 901 | 678 | return [ |
| 902 | 679 | 'a' => [ |
| 903 | 680 | 'class' => [], |
| @@ -996,14 +773,13 @@ | ||
| 996 | 773 | ]; |
| 997 | 774 | } |
| 998 | 775 | |
| 999 | 776 | |
| 1000 | - /** | |
| 777 | + /* | |
| 1001 | 778 | * Escape output of wishlist icon |
| 1002 | 779 | * |
| 1003 | 780 | * @param string $data Data to escape. |
| 1004 | - * | |
| 1005 | - * @return void | |
| 781 | + * @return string Escaped data | |
| 1006 | 782 | */ |
| 1007 | 783 | public static function print_icon( $data ) { |
| 1008 | 784 | /** |
| 1009 | 785 | * APPLY_FILTERS: rtsb/core/allowed_icon_html |
| @@ -1062,16 +838,8 @@ | ||
| 1062 | 838 | |
| 1063 | 839 | /** |
| 1064 | 840 | * Prints HTMl. |
| 1065 | 841 | * |
| 1066 | - * The full-markup branch is echoed as-is. It used to run stripslashes_deep(), | |
| 1067 | - * which corrupts already-rendered markup: product loop templates embed JSON in | |
| 1068 | - * attributes (e.g. the Variation Swatches `data-product_variations` payload), | |
| 1069 | - * and stripping backslashes turns `\"` into `"` and `\n` into `n`, so the JSON | |
| 1070 | - * no longer parses and every swatch renders disabled. Rendered HTML never | |
| 1071 | - * carries WordPress slashes — values that do are unslashed where they are read | |
| 1072 | - * (see stripslashes_value()), not at output time. | |
| 1073 | - * | |
| 1074 | 842 | * @param string $html HTML. |
| 1075 | 843 | * @param bool $allHtml All HTML. |
| 1076 | 844 | * |
| 1077 | 845 | * @return void |
| @@ -1080,9 +848,9 @@ | ||
| 1080 | 848 | if ( ! $html ) { |
| 1081 | 849 | return; |
| 1082 | 850 | } |
| 1083 | 851 | if ( $allHtml ) { |
| 1084 | - echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped | |
| 852 | + echo stripslashes_deep( $html ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped | |
| 1085 | 853 | } else { |
| 1086 | 854 | echo wp_kses_post( stripslashes_deep( $html ) ); |
| 1087 | 855 | } |
| 1088 | 856 | } |
| @@ -1095,9 +863,9 @@ | ||
| 1095 | 863 | * @return mixed |
| 1096 | 864 | */ |
| 1097 | 865 | public static function allowedHtml( $level = 'basic' ) { |
| 1098 | 866 | $allowed_html = []; |
| 1099 | - | |
| 867 | + // TODO:: Need Optimize. | |
| 1100 | 868 | switch ( $level ) { |
| 1101 | 869 | case 'basic': |
| 1102 | 870 | $allowed_html = [ |
| 1103 | 871 | 'b' => [ |
| @@ -1311,18 +1079,8 @@ | ||
| 1311 | 1079 | * |
| 1312 | 1080 | * @return array |
| 1313 | 1081 | */ |
| 1314 | 1082 | public static function get_image_sizes() { |
| 1315 | - // Memoized: called repeatedly while the settings schema is built, and each | |
| 1316 | - // call loops every registered size doing three get_option() lookups for | |
| 1317 | - // the core ones. Image sizes are registered on after_setup_theme, long | |
| 1318 | - // before anything here runs, so the list cannot change mid-request. | |
| 1319 | - static $memo = null; | |
| 1320 | - | |
| 1321 | - if ( null !== $memo ) { | |
| 1322 | - return $memo; | |
| 1323 | - } | |
| 1324 | - | |
| 1325 | 1083 | global $_wp_additional_image_sizes; |
| 1326 | 1084 | |
| 1327 | 1085 | $sizes = []; |
| 1328 | 1086 | |
| @@ -1342,31 +1100,23 @@ | ||
| 1342 | 1100 | |
| 1343 | 1101 | $imgSize = []; |
| 1344 | 1102 | |
| 1345 | 1103 | foreach ( $sizes as $key => $img ) { |
| 1346 | - $imgSize[ $key ] = esc_html( $key ) . " ({$img['width']}*{$img['height']})"; | |
| 1104 | + $imgSize[ $key ] = ucfirst( $key ) . " ({$img['width']}*{$img['height']})"; | |
| 1347 | 1105 | } |
| 1348 | 1106 | |
| 1349 | 1107 | $imgSize['full'] = esc_html__( 'Full size', 'shopbuilder' ); |
| 1350 | 1108 | $imgSize['rtsb_custom'] = esc_html__( 'Custom image size', 'shopbuilder' ); |
| 1351 | 1109 | |
| 1352 | - $memo = $imgSize; | |
| 1353 | - | |
| 1354 | - return $memo; | |
| 1110 | + return $imgSize; | |
| 1355 | 1111 | } |
| 1356 | 1112 | |
| 1357 | 1113 | /** |
| 1358 | 1114 | * Free Layouts |
| 1359 | 1115 | * |
| 1360 | - * @param string $layout Layout. | |
| 1361 | - * | |
| 1362 | 1116 | * @return array |
| 1363 | 1117 | */ |
| 1364 | - public static function free_layouts( $layout = '' ) { | |
| 1365 | - if ( ! empty( $layout ) && false !== strpos( $layout, 'rtsb-' ) ) { | |
| 1366 | - return [ $layout => esc_html__( 'Addon Layout', 'shopbuilder' ) ]; | |
| 1367 | - } | |
| 1368 | - | |
| 1118 | + public static function free_layouts() { | |
| 1369 | 1119 | $layouts = [ |
| 1370 | 1120 | 'grid-layout1' => esc_html__( 'Grid Layout 1', 'shopbuilder' ), |
| 1371 | 1121 | 'grid-layout2' => esc_html__( 'Grid Layout 2', 'shopbuilder' ), |
| 1372 | 1122 | 'list-layout1' => esc_html__( 'List Layout 1', 'shopbuilder' ), |
| @@ -1420,25 +1170,8 @@ | ||
| 1420 | 1170 | } |
| 1421 | 1171 | self::$cache[ $cache_key ] = $terms; |
| 1422 | 1172 | return $terms; |
| 1423 | 1173 | } |
| 1424 | - /** | |
| 1425 | - * Get all product attribute taxonomy by id | |
| 1426 | - * | |
| 1427 | - * @param array $term_ids Term id. | |
| 1428 | - * | |
| 1429 | - * @return array | |
| 1430 | - */ | |
| 1431 | - public static function tax_filter_attr_taxonomy( $term_ids ) { | |
| 1432 | - $taxonomies = []; | |
| 1433 | - foreach ( $term_ids as $id ) { | |
| 1434 | - $term = get_term( $id ); | |
| 1435 | - if ( ! is_wp_error( $term ) && $term ) { | |
| 1436 | - $taxonomies[] = $term->taxonomy; | |
| 1437 | - } | |
| 1438 | - } | |
| 1439 | - return array_unique( $taxonomies ); | |
| 1440 | - } | |
| 1441 | 1174 | |
| 1442 | 1175 | /** |
| 1443 | 1176 | * Get all terms by attributes |
| 1444 | 1177 | * |
| @@ -1444,17 +1177,8 @@ | ||
| 1444 | 1177 | * |
| 1445 | 1178 | * @return array |
| 1446 | 1179 | */ |
| 1447 | 1180 | public static function get_all_attributes() { |
| 1448 | - // Memoize per request: this runs once per product widget while Elementor | |
| 1449 | - // builds the editor control config, firing a get_terms() query per | |
| 1450 | - // attribute taxonomy each time. Caching avoids the repeated N queries. | |
| 1451 | - static $cached = null; | |
| 1452 | - | |
| 1453 | - if ( null !== $cached ) { | |
| 1454 | - return $cached; | |
| 1455 | - } | |
| 1456 | - | |
| 1457 | 1181 | $terms = []; |
| 1458 | 1182 | $termList = []; |
| 1459 | 1183 | |
| 1460 | 1184 | $attributes = wc_get_attribute_taxonomies(); |
| @@ -1474,10 +1198,8 @@ | ||
| 1474 | 1198 | } |
| 1475 | 1199 | } |
| 1476 | 1200 | } |
| 1477 | 1201 | |
| 1478 | - $cached = $terms; | |
| 1479 | - | |
| 1480 | 1202 | return $terms; |
| 1481 | 1203 | } |
| 1482 | 1204 | |
| 1483 | 1205 | /** |
| @@ -1561,8 +1283,9 @@ | ||
| 1561 | 1283 | if ( ! is_admin() ) { |
| 1562 | 1284 | return []; |
| 1563 | 1285 | } |
| 1564 | 1286 | |
| 1287 | + // TODO:: Return Slug always true for all settings. | |
| 1565 | 1288 | $term_list = []; |
| 1566 | 1289 | $args = [ |
| 1567 | 1290 | 'taxonomy' => $taxonomy, |
| 1568 | 1291 | 'hide_empty' => false, |
| @@ -1659,13 +1382,8 @@ | ||
| 1659 | 1382 | |
| 1660 | 1383 | self::print_html( $html, true ); |
| 1661 | 1384 | } |
| 1662 | 1385 | |
| 1663 | - /** | |
| 1664 | - * Get product simple rating. | |
| 1665 | - * | |
| 1666 | - * @return void | |
| 1667 | - */ | |
| 1668 | 1386 | public static function get_product_simple_rating_html() { |
| 1669 | 1387 | global $product; |
| 1670 | 1388 | $html = null; |
| 1671 | 1389 | $rating_count = $product->get_rating_count(); |
| @@ -1777,59 +1495,25 @@ | ||
| 1777 | 1495 | |
| 1778 | 1496 | <?php |
| 1779 | 1497 | self::print_html( ob_get_clean() ); |
| 1780 | 1498 | } |
| 1781 | - /** | |
| 1782 | - * Brands HTML | |
| 1783 | - * | |
| 1784 | - * @param int $id Product ID. | |
| 1785 | - * @param string $class Custom class. | |
| 1786 | - * | |
| 1787 | - * @return void|string | |
| 1788 | - */ | |
| 1789 | - public static function get_brands_list( $id, $class = 'rtsb-brand-outline' ) { | |
| 1790 | - $terms = get_the_terms( $id, 'product_brand' ); | |
| 1791 | - if ( empty( $id ) || empty( $terms ) || is_wp_error( $terms ) ) { | |
| 1792 | - return ''; | |
| 1793 | - } | |
| 1794 | - ob_start(); | |
| 1795 | - ?> | |
| 1796 | 1499 | |
| 1797 | - <ul class="rtsb-brand-list <?php echo esc_attr( $class ); ?>"> | |
| 1798 | - <?php | |
| 1799 | - $brand_list = get_the_term_list( | |
| 1800 | - $id, | |
| 1801 | - 'product_brand', | |
| 1802 | - '<li class="rtsb-brand-list-item">', | |
| 1803 | - '</li><li class="rtsb-brand-list-item">', | |
| 1804 | - '</li>' | |
| 1805 | - ); | |
| 1806 | - | |
| 1807 | - self::print_html( $brand_list ); | |
| 1808 | - ?> | |
| 1809 | - </ul> | |
| 1810 | - | |
| 1811 | - <?php | |
| 1812 | - self::print_html( ob_get_clean() ); | |
| 1813 | - } | |
| 1814 | - | |
| 1815 | 1500 | /** |
| 1816 | 1501 | * Get Featured Image HTML. |
| 1817 | 1502 | * |
| 1818 | - * @param string $type Image type. | |
| 1819 | - * @param int $post_id Post ID. | |
| 1820 | - * @param string $f_img_size Image size. | |
| 1821 | - * @param null $default_img_id Default image ID. | |
| 1822 | - * @param array $custom_img_size Custom image size. | |
| 1823 | - * @param bool $lazy Lazy load check. | |
| 1824 | - * @param bool $hover Hover image. | |
| 1825 | - * @param bool $gallery Gallery image. | |
| 1826 | - * @param bool $custom_image_id Custom category image ID. | |
| 1827 | - * @param bool|string $priority Eager/priority hint: 'high', 'eager', or false (default lazy). | |
| 1503 | + * @param string $type Image type. | |
| 1504 | + * @param int $post_id Post ID. | |
| 1505 | + * @param string $f_img_size Image size. | |
| 1506 | + * @param null $default_img_id Default image ID. | |
| 1507 | + * @param array $custom_img_size Custom image size. | |
| 1508 | + * @param bool $lazy Lazy load check. | |
| 1509 | + * @param bool $hover Hover image. | |
| 1510 | + * @param bool $gallery Gallery image. | |
| 1511 | + * @param bool $custom_image_id Custom category image ID. | |
| 1828 | 1512 | * |
| 1829 | 1513 | * @return string|null |
| 1830 | 1514 | */ |
| 1831 | - 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, $priority = false ) { | |
| 1515 | + 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 ) { | |
| 1832 | 1516 | $img_html = null; |
| 1833 | 1517 | $attachment_id = null; |
| 1834 | 1518 | $c_size = false; |
| 1835 | 1519 | $hover_class = ''; |
| @@ -1868,19 +1552,8 @@ | ||
| 1868 | 1552 | 'class' => 'img-responsive rtsb-product-image' . $lazy_class . $hover_class, |
| 1869 | 1553 | 'alt' => $alt_tag, |
| 1870 | 1554 | ]; |
| 1871 | 1555 | |
| 1872 | - // Eager-load above-the-fold images so the LCP candidate is fetched | |
| 1873 | - // immediately instead of being lazy-loaded after render-blocking CSS. | |
| 1874 | - // Only the first image is marked fetchpriority=high to avoid competing hints. | |
| 1875 | - if ( $priority ) { | |
| 1876 | - $attr['loading'] = 'eager'; | |
| 1877 | - | |
| 1878 | - if ( 'high' === $priority ) { | |
| 1879 | - $attr['fetchpriority'] = 'high'; | |
| 1880 | - } | |
| 1881 | - } | |
| 1882 | - | |
| 1883 | 1556 | if ( $a_id ) { |
| 1884 | 1557 | $img_html = wp_get_attachment_image( $a_id, $f_img_size, false, $attr ); |
| 1885 | 1558 | $attachment_id = $a_id; |
| 1886 | 1559 | } |
| @@ -1927,9 +1600,9 @@ | ||
| 1927 | 1600 | |
| 1928 | 1601 | if ( ! $img_html ) { |
| 1929 | 1602 | $hwstring = image_hwstring( 160, 160 ); |
| 1930 | 1603 | $attr = isset( $attr['src'] ) ? apply_filters( 'wp_get_attachment_image_attributes', $attr, false, $f_img_size ) : []; |
| 1931 | - $attr['class'] = 'default-img ' . $hover_class; | |
| 1604 | + $attr['class'] = 'default-img'; | |
| 1932 | 1605 | $attr['src'] = esc_url( rtsb()->get_assets_uri( 'images/demo.png' ) ); |
| 1933 | 1606 | $attr['alt'] = esc_html__( 'Default Image', 'shopbuilder' ); |
| 1934 | 1607 | $img_html = rtrim( "<img $hwstring" ); |
| 1935 | 1608 | |
| @@ -2020,9 +1693,9 @@ | ||
| 2020 | 1693 | if ( empty( $control['value'] ) ) { |
| 2021 | 1694 | return ''; |
| 2022 | 1695 | } |
| 2023 | 1696 | if ( is_array( $control['value'] ) ) { |
| 2024 | - $cache_key = 'icons_managet_' . str_replace( ' ', '', md5( serialize( $control['value'] ) ) ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_serialize | |
| 1697 | + $cache_key = 'icons_managet_' . str_replace( ' ', '', md5( serialize( $control['value'] ) ) ); | |
| 2025 | 1698 | } else { |
| 2026 | 1699 | $cache_key = 'icons_managet_' . str_replace( ' ', '', $control['value'] ); |
| 2027 | 1700 | } |
| 2028 | 1701 | if ( isset( self::$cache[ $cache_key ] ) ) { |
| @@ -2058,25 +1731,9 @@ | ||
| 2058 | 1731 | public static function get_product_swatches( $type ) { |
| 2059 | 1732 | ?> |
| 2060 | 1733 | <div class="rtsb-swatches <?php echo esc_attr( $type ); ?>-layout"> |
| 2061 | 1734 | <?php |
| 2062 | - /* | |
| 2063 | - * Hand off to the Variation Swatches plugin's own archive renderer when it | |
| 2064 | - * is listening, otherwise fall back to the built-in module. | |
| 2065 | - * | |
| 2066 | - * Detected with has_action() rather than a class name on purpose: this used | |
| 2067 | - * to test `class_exists( 'Rtwpvsp' )`, but the plugin moved its classes into | |
| 2068 | - * a namespace (`Rtwpvsp\Rtwpvsp`), so that check silently started failing. | |
| 2069 | - * The else branch then fired the built-in module's action — which is never | |
| 2070 | - * hooked while the plugin is active, because the module deliberately stands | |
| 2071 | - * down — leaving this wrapper rendered but empty. Asking whether anything is | |
| 2072 | - * actually listening is both the correct question and rename-proof. | |
| 2073 | - */ | |
| 2074 | - if ( has_action( 'rtwpvs_show_archive_variation' ) ) { | |
| 2075 | - do_action( 'rtwpvs_show_archive_variation' ); | |
| 2076 | - } else { | |
| 2077 | - do_action( 'rtsb/vs/showcase/variation' ); | |
| 2078 | - } | |
| 1735 | + do_action( 'rtwpvs_show_archive_variation' ); | |
| 2079 | 1736 | ?> |
| 2080 | 1737 | </div> |
| 2081 | 1738 | <?php |
| 2082 | 1739 | } |
| @@ -2100,18 +1757,20 @@ | ||
| 2100 | 1757 | if ( ! $product->is_on_sale() ) { |
| 2101 | 1758 | return ''; |
| 2102 | 1759 | } |
| 2103 | 1760 | |
| 1761 | + $badge_text = ''; | |
| 1762 | + $percentage = self::calculate_sale_percentage( $product ); | |
| 1763 | + | |
| 1764 | + if ( $percentage > 0 ) { | |
| 1765 | + $badge_text = '-' . round( $percentage ) . '%'; | |
| 1766 | + } | |
| 1767 | + | |
| 2104 | 1768 | if ( 'text' === $type ) { |
| 2105 | - return $text; | |
| 1769 | + $badge_text = $text; | |
| 2106 | 1770 | } |
| 2107 | 1771 | |
| 2108 | - $percentage = self::calculate_sale_percentage( $product ); | |
| 2109 | - | |
| 2110 | - // The product is on sale (checked above). When a percentage can be derived show | |
| 2111 | - // it; otherwise (e.g. some variable products where variation prices aren't | |
| 2112 | - // primed) fall back to the sale text so an on-sale product always shows a badge. | |
| 2113 | - return $percentage > 0 ? '-' . round( $percentage ) . '%' : $text; | |
| 1772 | + return $badge_text; | |
| 2114 | 1773 | } |
| 2115 | 1774 | |
| 2116 | 1775 | /** |
| 2117 | 1776 | * Get sale badge |
| @@ -2146,18 +1805,20 @@ | ||
| 2146 | 1805 | if ( ! $product->is_on_sale() ) { |
| 2147 | 1806 | return ''; |
| 2148 | 1807 | } |
| 2149 | 1808 | |
| 1809 | + $badge_text = ''; | |
| 1810 | + $percentage = self::calculate_sale_percentage( $product ); | |
| 1811 | + | |
| 1812 | + if ( $percentage > 0 ) { | |
| 1813 | + $badge_text = '-' . round( $percentage ) . '%'; | |
| 1814 | + } | |
| 1815 | + | |
| 2150 | 1816 | if ( 'text' === $type ) { |
| 2151 | - return $text; | |
| 1817 | + $badge_text = $text; | |
| 2152 | 1818 | } |
| 2153 | 1819 | |
| 2154 | - $percentage = self::calculate_sale_percentage( $product ); | |
| 2155 | - | |
| 2156 | - // The product is on sale (checked above). When a percentage can be derived show | |
| 2157 | - // it; otherwise (e.g. some variable products where variation prices aren't | |
| 2158 | - // primed) fall back to the sale text so an on-sale product always shows a badge. | |
| 2159 | - return $percentage > 0 ? '-' . round( $percentage ) . '%' : $text; | |
| 1820 | + return $badge_text; | |
| 2160 | 1821 | } |
| 2161 | 1822 | |
| 2162 | 1823 | /** |
| 2163 | 1824 | * Calculate Sale Percentage |
| @@ -2169,74 +1830,72 @@ | ||
| 2169 | 1830 | public static function calculate_sale_percentage( $product = null ) { |
| 2170 | 1831 | if ( is_null( $product ) ) { |
| 2171 | 1832 | global $product; |
| 2172 | 1833 | } |
| 1834 | + | |
| 2173 | 1835 | if ( ! $product instanceof WC_Product ) { |
| 2174 | 1836 | return ''; |
| 2175 | 1837 | } |
| 1838 | + | |
| 2176 | 1839 | if ( ! $product->is_on_sale() ) { |
| 2177 | 1840 | return ''; |
| 2178 | 1841 | } |
| 2179 | - $max_percentage = 0; | |
| 1842 | + | |
| 1843 | + $percentage = null; | |
| 1844 | + $max_percentage = ''; | |
| 1845 | + | |
| 2180 | 1846 | if ( $product->is_type( 'simple' ) ) { |
| 2181 | - $regular_price = (float) $product->get_regular_price(); | |
| 2182 | - $sale_price = (float) $product->get_sale_price(); | |
| 2183 | - if ( $regular_price > 0 && $sale_price > 0 ) { | |
| 2184 | - $max_percentage = ( ( $regular_price - $sale_price ) / $regular_price ) * 100; | |
| 2185 | - } | |
| 1847 | + $max_percentage = $product->get_sale_price() ? ( ( $product->get_regular_price() - $product->get_sale_price() ) / $product->get_regular_price() ) * 100 : 0; | |
| 2186 | 1848 | } elseif ( $product->is_type( 'variable' ) ) { |
| 2187 | - $prices = $product->get_variation_prices( true ); | |
| 2188 | - if ( ! empty( $prices['regular_price'] ) && ! empty( $prices['sale_price'] ) ) { | |
| 2189 | - foreach ( $prices['regular_price'] as $key => $regular_price ) { | |
| 2190 | - $sale_price = $prices['sale_price'][ $key ]; | |
| 1849 | + $max_percentage = 0; | |
| 2191 | 1850 | |
| 2192 | - if ( $regular_price > 0 && $sale_price > 0 && $regular_price > $sale_price ) { | |
| 2193 | - $percentage = ( ( $regular_price - $sale_price ) / $regular_price ) * 100; | |
| 2194 | - $max_percentage = max( $max_percentage, $percentage ); | |
| 2195 | - } | |
| 1851 | + foreach ( $product->get_children() as $child_id ) { | |
| 1852 | + | |
| 1853 | + $variation = wc_get_product( $child_id ); | |
| 1854 | + | |
| 1855 | + $price = $variation->get_regular_price(); | |
| 1856 | + $sale = $variation->get_sale_price(); | |
| 1857 | + | |
| 1858 | + if ( 0 !== $price && ! empty( $sale ) ) { | |
| 1859 | + $percentage = ( $price - $sale ) / $price * 100; | |
| 2196 | 1860 | } |
| 1861 | + | |
| 1862 | + if ( $percentage > $max_percentage ) { | |
| 1863 | + $max_percentage = $percentage; | |
| 1864 | + } | |
| 2197 | 1865 | } |
| 2198 | 1866 | } |
| 2199 | - return $max_percentage > 0 ? round( $max_percentage ) : 0; | |
| 1867 | + | |
| 1868 | + if ( $max_percentage > 0 ) { | |
| 1869 | + return round( $max_percentage ); | |
| 1870 | + } | |
| 1871 | + | |
| 1872 | + return 0; | |
| 2200 | 1873 | } |
| 2201 | 1874 | |
| 2202 | 1875 | /** |
| 2203 | 1876 | * Pagination |
| 2204 | 1877 | * |
| 2205 | - * @param string $pages Pages. | |
| 2206 | - * @param integer $per_page Per-page count (unused; kept for positional compatibility). | |
| 2207 | - * @param boolean $ajax Ajax. | |
| 2208 | - * @param int|null $visible_range Page links to show on each side of the current | |
| 2209 | - * page (from the widget's "Page Number Range" | |
| 2210 | - * control). Falls back to the filter default. | |
| 1878 | + * @param string $pages Pages. | |
| 1879 | + * @param integer $range Range. | |
| 1880 | + * @param boolean $ajax Ajax. | |
| 2211 | 1881 | * |
| 2212 | 1882 | * @return string |
| 2213 | 1883 | */ |
| 2214 | - public static function custom_pagination( $pages = '', $per_page = 4, $ajax = false, $visible_range = null ) { | |
| 2215 | - $html = null; | |
| 1884 | + public static function custom_pagination( $pages = '', $range = 4, $ajax = false ) { | |
| 1885 | + $html = null; | |
| 1886 | + $visible_range = apply_filters( 'rtsb/elements/pagination/visible_range', ( $range * 2 ) + 1 ); | |
| 2216 | 1887 | |
| 2217 | - // How many page links to show on each side of the current page. Driven by | |
| 2218 | - // the widget's "Page Number Range" control; the filter is the fallback | |
| 2219 | - // default. Keeping it small truncates long paginations (« ‹ 1 2 3 › ») | |
| 2220 | - // with jump-to-first/last arrows instead of listing every page number. | |
| 2221 | - // (The 2nd argument callers pass is the per-page count, not a window). | |
| 2222 | - if ( null === $visible_range ) { | |
| 2223 | - $visible_range = apply_filters( 'rtsb/elements/pagination/visible_range', 5 ); | |
| 2224 | - } | |
| 2225 | - | |
| 2226 | - $visible_range = max( 1, (int) $visible_range ); | |
| 2227 | - | |
| 2228 | 1888 | global $paged; |
| 2229 | 1889 | |
| 2230 | - // Prefer `paged` (archive pagination), fall back to `page` (paginated singular posts). | |
| 2231 | - // This handles the case where the shop/archive is set as the front page — `is_front_page()` | |
| 2232 | - // alone would force `page` and miss the archive `paged` value. | |
| 2233 | - $paged = get_query_var( 'paged' ); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited | |
| 2234 | - if ( ! $paged ) { | |
| 2235 | - $paged = get_query_var( 'page' ); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited | |
| 1890 | + if ( is_front_page() ) { | |
| 1891 | + $paged = ( get_query_var( 'page' ) ) ? get_query_var( 'page' ) : 1; | |
| 1892 | + } else { | |
| 1893 | + $paged = ( get_query_var( 'paged' ) ) ? get_query_var( 'paged' ) : 1; | |
| 2236 | 1894 | } |
| 2237 | - if ( ! $paged ) { | |
| 2238 | - $paged = 1; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited | |
| 1895 | + | |
| 1896 | + if ( empty( $paged ) ) { | |
| 1897 | + $paged = 1; | |
| 2239 | 1898 | } |
| 2240 | 1899 | |
| 2241 | 1900 | if ( '' === $pages ) { |
| 2242 | 1901 | global $wp_query; |
| @@ -2280,9 +1939,9 @@ | ||
| 2280 | 1939 | $p = $paged + 1; |
| 2281 | 1940 | $html .= "<li><a data-paged='{$p}' href=\"" . get_pagenum_link( $paged + 1 ) . "\" aria-label='Next'>›</a></li>"; |
| 2282 | 1941 | } |
| 2283 | 1942 | |
| 2284 | - if ( $paged < $pages - 1 && $paged + $visible_range < $pages && $visible_range < $pages ) { | |
| 1943 | + if ( $paged < $pages - 1 && $paged + $range - 1 < $pages && $visible_range < $pages ) { | |
| 2285 | 1944 | $html .= "<li><a data-paged='{$pages}' href='" . get_pagenum_link( $pages ) . "' aria-label='Last'>»</a></li>"; |
| 2286 | 1945 | } |
| 2287 | 1946 | |
| 2288 | 1947 | $html .= '</ul>'; |
| @@ -2394,8 +2053,10 @@ | ||
| 2394 | 2053 | } else { |
| 2395 | 2054 | $class .= ' rtsb-' . esc_attr( str_replace( '_', '-', $type ) ); |
| 2396 | 2055 | } |
| 2397 | 2056 | |
| 2057 | + $html .= '<' . esc_attr( $wrapper ) . ' class="' . esc_attr( $class ) . '">'; | |
| 2058 | + | |
| 2398 | 2059 | if ( ( 'add_to_cart' === $type ) && ( ! empty( $cart_html ) ) ) { |
| 2399 | 2060 | $html .= $cart_html; |
| 2400 | 2061 | } else { |
| 2401 | 2062 | $html .= shortcode_exists( 'rtsb_' . $type . '_button' ) ? do_shortcode( '[rtsb_' . $type . '_button]' ) : null; |
| @@ -2400,11 +2061,9 @@ | ||
| 2400 | 2061 | } else { |
| 2401 | 2062 | $html .= shortcode_exists( 'rtsb_' . $type . '_button' ) ? do_shortcode( '[rtsb_' . $type . '_button]' ) : null; |
| 2402 | 2063 | } |
| 2403 | 2064 | |
| 2404 | - if ( ! empty( $html ) ) { | |
| 2405 | - $html = '<' . esc_attr( $wrapper ) . ' class="' . esc_attr( $class ) . '">' . $html . '</' . esc_attr( $wrapper ) . '>'; | |
| 2406 | - } | |
| 2065 | + $html .= '</' . esc_attr( $wrapper ) . '>'; | |
| 2407 | 2066 | |
| 2408 | 2067 | return apply_filters( 'rtsb/elements/elementor/get_action_button_by_type', $html ); |
| 2409 | 2068 | } |
| 2410 | 2069 | |
| @@ -2505,9 +2164,9 @@ | ||
| 2505 | 2164 | $link['social_network'] = 'Facebook'; |
| 2506 | 2165 | $link['social_action'] = 'Share'; |
| 2507 | 2166 | break; |
| 2508 | 2167 | case 'twitter': |
| 2509 | - $link['link'] = esc_url( 'https://x.com/intent/tweet?text=' . htmlspecialchars( rawurlencode( html_entity_decode( $link['title'], ENT_COMPAT, 'UTF-8' ) ), ENT_COMPAT, 'UTF-8' ) . '&url=' . $link['url'] ); | |
| 2168 | + $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'] ); | |
| 2510 | 2169 | $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>'; |
| 2511 | 2170 | $link['attr_title'] = esc_html__( 'Share on Twitter', 'shopbuilder' ); |
| 2512 | 2171 | $link['social_network'] = 'Twitter'; |
| 2513 | 2172 | $link['social_action'] = 'Tweet'; |
| @@ -2631,83 +2290,27 @@ | ||
| 2631 | 2290 | |
| 2632 | 2291 | /** |
| 2633 | 2292 | * Social Share Platforms. |
| 2634 | 2293 | * |
| 2635 | - * @param string $module Module. | |
| 2636 | - * | |
| 2637 | - * @return true|void | |
| 2294 | + * @return mixed|null | |
| 2638 | 2295 | */ |
| 2639 | 2296 | public static function is_module_active( $module ) { |
| 2640 | - $modulelist = self::get_modules_list(); | |
| 2641 | - | |
| 2297 | + $modulelist = ModuleList::instance()->get_data(); | |
| 2642 | 2298 | if ( ! empty( $modulelist[ $module ]['active'] ) ) { |
| 2643 | 2299 | return true; |
| 2644 | 2300 | } |
| 2645 | 2301 | } |
| 2646 | - /** | |
| 2647 | - * Checks if catalog pro is active | |
| 2648 | - * | |
| 2649 | - * @return boolean | |
| 2650 | - */ | |
| 2651 | - public static function is_catalog_mode() { | |
| 2652 | - return function_exists( 'rtsbpro' ) && self::is_module_active( 'catalog_mode' ); | |
| 2653 | - } | |
| 2654 | - /** | |
| 2655 | - * Checks if back in stock notifier is active | |
| 2656 | - * | |
| 2657 | - * @return boolean | |
| 2658 | - */ | |
| 2659 | - public static function is_back_in_stock_notifier_enable() { | |
| 2660 | - return function_exists( 'rtsbpro' ) && self::is_module_active( 'back_in_stock_notifier' ); | |
| 2661 | - } | |
| 2662 | 2302 | |
| 2663 | - /** | |
| 2664 | - * Elementor Widget Active. | |
| 2665 | - * | |
| 2666 | - * @param string $widget Elementor Widget. | |
| 2667 | - * | |
| 2668 | - * @return true|void | |
| 2669 | - */ | |
| 2670 | - public static function is_elementor_widget_active( $widget ) { | |
| 2671 | - $element_list = self::get_widgets_list(); | |
| 2672 | - | |
| 2673 | - if ( ! empty( $element_list[ $widget ]['active'] ) ) { | |
| 2674 | - return true; | |
| 2675 | - } | |
| 2676 | - } | |
| 2677 | - | |
| 2678 | - /** | |
| 2679 | - * Sanitize a media (fileupload) control value into an { id, source } array. | |
| 2680 | - * | |
| 2681 | - * The control value is posted as an array (or a JSON string). Using it as a | |
| 2682 | - * `sanitize_fn` avoids it being flattened to an empty string by the default | |
| 2683 | - * sanitize_text_field() path in set_options(). | |
| 2684 | - * | |
| 2685 | - * @param mixed $raw_value Raw posted value. | |
| 2686 | - * | |
| 2687 | - * @return array|string | |
| 2688 | - */ | |
| 2689 | - public static function sanitize_fileupload_value( $raw_value ) { | |
| 2690 | - $decoded = is_string( $raw_value ) && '' !== $raw_value ? json_decode( wp_unslash( $raw_value ), true ) : $raw_value; | |
| 2691 | - if ( ! is_array( $decoded ) ) { | |
| 2692 | - return ''; | |
| 2693 | - } | |
| 2694 | - return [ | |
| 2695 | - 'id' => isset( $decoded['id'] ) ? absint( $decoded['id'] ) : 0, | |
| 2696 | - 'source' => isset( $decoded['source'] ) ? esc_url_raw( $decoded['source'] ) : '', | |
| 2697 | - ]; | |
| 2698 | - } | |
| 2699 | - | |
| 2700 | 2303 | /*** |
| 2701 | 2304 | * Save Settings data |
| 2702 | 2305 | * |
| 2703 | - * @param string $section_id Section ID. | |
| 2704 | - * @param string $block_id Block ID. | |
| 2705 | - * @param array $rawOptions Raw Options. | |
| 2306 | + * @param $section_id | |
| 2307 | + * @param $block_id | |
| 2308 | + * @param $rawOptions | |
| 2706 | 2309 | * |
| 2707 | 2310 | * @return array |
| 2708 | 2311 | */ |
| 2709 | - public static function set_options( $section_id = '', $block_id = '', $rawOptions = [] ) { // phpcs:ignore Generic.Metrics.NestingLevel.TooHigh | |
| 2312 | + public static function set_options( $section_id = '', $block_id = '', $rawOptions = [] ) { | |
| 2710 | 2313 | $section_id = ! empty( $section_id ) ? sanitize_text_field( wp_unslash( $section_id ) ) : ''; |
| 2711 | 2314 | $block_id = ! empty( $block_id ) ? sanitize_text_field( wp_unslash( $block_id ) ) : ''; |
| 2712 | 2315 | $rawOptions = ! empty( $rawOptions ) ? $rawOptions : []; |
| 2713 | 2316 | $results = [ |
| @@ -2733,9 +2336,9 @@ | ||
| 2733 | 2336 | $fields = []; |
| 2734 | 2337 | if ( isset( $sections[ $section_id ]['list'][ $block_id ]['fields'] ) && ! empty( $sections[ $section_id ]['list'][ $block_id ]['fields'] ) ) { |
| 2735 | 2338 | $fields = $sections[ $section_id ]['list'][ $block_id ]['fields']; |
| 2736 | 2339 | } |
| 2737 | - do_action( 'rtsb/before/save/options', $section_id, $block_id, $rawOptions ); | |
| 2340 | + | |
| 2738 | 2341 | if ( empty( $fields ) ) { |
| 2739 | 2342 | if ( isset( $rawOptions['active'] ) ) { |
| 2740 | 2343 | $changed = true; |
| 2741 | 2344 | $options[ $block_id ]['active'] = 'on' === $rawOptions['active'] ? 'on' : ''; |
| @@ -2741,15 +2344,15 @@ | ||
| 2741 | 2344 | $options[ $block_id ]['active'] = 'on' === $rawOptions['active'] ? 'on' : ''; |
| 2742 | 2345 | } |
| 2743 | 2346 | } else { |
| 2744 | 2347 | foreach ( $rawOptions as $raw_option_key => $raw_value ) { |
| 2745 | - if ( 'active' === $raw_option_key ) { | |
| 2348 | + if ( $raw_option_key === 'active' ) { | |
| 2746 | 2349 | $changed = true; |
| 2747 | - $options[ $block_id ]['active'] = $sections[ $section_id ]['list'][ $block_id ]['active'] = 'on' === $raw_value ? 'on' : ''; // phpcs:ignore Squiz.PHP.DisallowMultipleAssignments.Found | |
| 2350 | + $options[ $block_id ]['active'] = $sections[ $section_id ]['list'][ $block_id ]['active'] = 'on' === $raw_value ? 'on' : ''; | |
| 2748 | 2351 | } else { |
| 2749 | 2352 | if ( isset( $fields[ $raw_option_key ] ) ) { |
| 2750 | 2353 | $field = $fields[ $raw_option_key ]; |
| 2751 | - if ( 'switch' === $field['type'] ) { | |
| 2354 | + if ( $field['type'] === 'switch' ) { | |
| 2752 | 2355 | $value = 'on' === $raw_value ? 'on' : ''; |
| 2753 | 2356 | } elseif ( 'repeaters' === $field['type'] ) { |
| 2754 | 2357 | $the_value = []; |
| 2755 | 2358 | $rep_title = []; |
| @@ -2769,21 +2372,21 @@ | ||
| 2769 | 2372 | } |
| 2770 | 2373 | } elseif ( ! empty( $raw_value ) && is_string( $raw_value ) ) { |
| 2771 | 2374 | $the_value = $raw_value; |
| 2772 | 2375 | } |
| 2773 | - $value = wp_json_encode( $the_value, JSON_UNESCAPED_UNICODE ); | |
| 2774 | - } elseif ( in_array( $field['type'], [ 'product_addons_special_settings', 'checkout_fields' ] ) ) { // phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict | |
| 2376 | + $value = wp_json_encode( $the_value ); | |
| 2377 | + } elseif ( in_array( $field['type'], [ 'product_addons_special_settings', 'checkout_fields' ] ) ) { | |
| 2775 | 2378 | $manual_field_value = []; |
| 2776 | 2379 | if ( is_array( $raw_value ) ) { |
| 2777 | 2380 | foreach ( $raw_value as $key => $value ) { |
| 2778 | 2381 | $manual_field_value[] = json_decode( stripslashes( $value ), true ); |
| 2779 | 2382 | } |
| 2780 | - $value = wp_json_encode( $manual_field_value, JSON_UNESCAPED_UNICODE ); | |
| 2383 | + $value = wp_json_encode( $manual_field_value ); | |
| 2781 | 2384 | } elseif ( is_string( $raw_value ) ) { |
| 2782 | 2385 | $value = $raw_value; |
| 2783 | 2386 | } |
| 2784 | 2387 | } else { |
| 2785 | - if ( ! empty( $field['multiple'] ) || in_array( $field['type'], [ 'checkbox', 'search_and_multi_select' ] ) ) { // phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict | |
| 2388 | + if ( ! empty( $field['multiple'] ) || in_array( $field['type'], [ 'checkbox', 'search_and_multi_select' ] ) ) { | |
| 2786 | 2389 | if ( isset( $raw_value ) && is_array( $raw_value ) ) { |
| 2787 | 2390 | if ( ! empty( $field['sanitize_fn'] ) && is_callable( $field['sanitize_fn'] ) ) { |
| 2788 | 2391 | $value = array_map( $field['sanitize_fn'], $raw_value ); |
| 2789 | 2392 | } else { |
| @@ -2805,9 +2408,9 @@ | ||
| 2805 | 2408 | $value = sanitize_text_field( $raw_value ); |
| 2806 | 2409 | } |
| 2807 | 2410 | } |
| 2808 | 2411 | } |
| 2809 | - $options[ $block_id ][ $raw_option_key ] = $sections[ $section_id ]['list'][ $block_id ]['fields'][ $raw_option_key ]['value'] = $value ?? null; // phpcs:ignore Squiz.PHP.DisallowMultipleAssignments.Found | |
| 2412 | + $options[ $block_id ][ $raw_option_key ] = $sections[ $section_id ]['list'][ $block_id ]['fields'][ $raw_option_key ]['value'] = $value ?? null; | |
| 2810 | 2413 | $changed = true; |
| 2811 | 2414 | } |
| 2812 | 2415 | } |
| 2813 | 2416 | } |
| @@ -2827,52 +2430,28 @@ | ||
| 2827 | 2430 | |
| 2828 | 2431 | return $results; |
| 2829 | 2432 | } |
| 2830 | 2433 | |
| 2831 | - /** | |
| 2832 | - * Count published products matching a tax query. | |
| 2434 | + /*** | |
| 2435 | + * @param $meta_key | |
| 2436 | + * @param $meta_value | |
| 2833 | 2437 | * |
| 2834 | - * Filter badges must agree with the number of products the same filter lists. | |
| 2835 | - * The archive (and the Ajax filter response) runs a plain WP_Query, while | |
| 2836 | - * WC_Product_Query additionally restricts results to the registered | |
| 2837 | - * `product_type` terms — so a product imported without a `product_type` term | |
| 2838 | - * is listed on the archive but silently dropped from the count, making the | |
| 2839 | - * badge read lower than the result set (e.g. "Cat1 (4)" for 10 results). | |
| 2438 | + * @return mixed|void | |
| 2840 | 2439 | * |
| 2841 | - * @param array $tax_query Tax query clauses. | |
| 2842 | 2440 | * |
| 2843 | - * @return int Number of matching products. | |
| 2441 | + * public static function get_post_id_by_meta_key_and_value( $meta_key, $meta_value ) { | |
| 2442 | + * if( ! $meta_key || ! $meta_value ){ | |
| 2443 | + * return; | |
| 2444 | + * } | |
| 2445 | + * global $wpdb; | |
| 2446 | + * $prepare_guery = $wpdb->prepare( "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '%s' and meta_value = '%d'", $meta_key, $meta_value ); | |
| 2447 | + * $the_products = $wpdb->get_col( $prepare_guery ); | |
| 2448 | + * if( count( $the_products ) > 0 ){ | |
| 2449 | + * return $the_products[0]; | |
| 2450 | + * } | |
| 2451 | + * return; | |
| 2452 | + * } | |
| 2844 | 2453 | */ |
| 2845 | - public static function count_products_by_tax_query( array $tax_query ) { | |
| 2846 | - if ( empty( $tax_query ) ) { | |
| 2847 | - return 0; | |
| 2848 | - } | |
| 2849 | - | |
| 2850 | - $query = new WP_Query( | |
| 2851 | - [ | |
| 2852 | - 'post_type' => 'product', | |
| 2853 | - 'post_status' => 'publish', | |
| 2854 | - 'posts_per_page' => -1, | |
| 2855 | - 'fields' => 'ids', | |
| 2856 | - 'ignore_sticky_posts' => true, | |
| 2857 | - 'no_found_rows' => true, | |
| 2858 | - 'update_post_meta_cache' => false, | |
| 2859 | - 'update_post_term_cache' => false, | |
| 2860 | - 'tax_query' => $tax_query, // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query | |
| 2861 | - ] | |
| 2862 | - ); | |
| 2863 | - | |
| 2864 | - return count( $query->posts ); | |
| 2865 | - } | |
| 2866 | - | |
| 2867 | - /** | |
| 2868 | - * Count products by taxonomies. | |
| 2869 | - * | |
| 2870 | - * @param array $terms Terms. | |
| 2871 | - * @param string $taxonomy Taxonomy. | |
| 2872 | - * | |
| 2873 | - * @return int|void | |
| 2874 | - */ | |
| 2875 | 2454 | public static function count_products_by_taxonomies( $terms, $taxonomy = 'product_cat' ) { |
| 2876 | 2455 | if ( empty( $terms ) || ! is_array( $terms ) ) { |
| 2877 | 2456 | return; |
| 2878 | 2457 | } |
| @@ -2883,73 +2462,17 @@ | ||
| 2883 | 2462 | ]; |
| 2884 | 2463 | |
| 2885 | 2464 | if ( 'product_cat' === $taxonomy ) { |
| 2886 | 2465 | $args['product_category_id'] = $terms; |
| 2887 | - } elseif ( 'product_brand' === $taxonomy ) { | |
| 2888 | - $args['product_brand_id'] = $terms; | |
| 2889 | 2466 | } else { |
| 2890 | 2467 | $args['product_tag_id'] = $terms; |
| 2891 | 2468 | } |
| 2892 | 2469 | |
| 2893 | 2470 | $query = new WC_Product_Query( $args ); |
| 2894 | - | |
| 2895 | 2471 | return ! empty( $query->get_products() ) ? count( $query->get_products() ) : 0; |
| 2896 | 2472 | } |
| 2897 | 2473 | |
| 2898 | 2474 | /** |
| 2899 | - * Count products by attribute terms. | |
| 2900 | - * | |
| 2901 | - * @param array $term_ids Term IDs. | |
| 2902 | - * @param string $relation Relation. | |
| 2903 | - * | |
| 2904 | - * @return int | |
| 2905 | - */ | |
| 2906 | - public static function count_products_by_attribute_terms( $term_ids, $relation = 'AND' ) { | |
| 2907 | - if ( empty( $term_ids ) || ! is_array( $term_ids ) ) { | |
| 2908 | - return 0; | |
| 2909 | - } | |
| 2910 | - | |
| 2911 | - $terms_by_taxonomy = []; | |
| 2912 | - | |
| 2913 | - foreach ( $term_ids as $term_id ) { | |
| 2914 | - $term = get_term( $term_id ); | |
| 2915 | - if ( ! is_wp_error( $term ) && $term ) { | |
| 2916 | - if ( ! isset( $terms_by_taxonomy[ $term->taxonomy ] ) ) { | |
| 2917 | - $terms_by_taxonomy[ $term->taxonomy ] = []; | |
| 2918 | - } | |
| 2919 | - $terms_by_taxonomy[ $term->taxonomy ][] = $term_id; | |
| 2920 | - } | |
| 2921 | - } | |
| 2922 | - | |
| 2923 | - if ( empty( $terms_by_taxonomy ) ) { | |
| 2924 | - return 0; | |
| 2925 | - } | |
| 2926 | - | |
| 2927 | - $args = [ | |
| 2928 | - 'status' => 'publish', | |
| 2929 | - 'limit' => -1, | |
| 2930 | - 'return' => 'ids', | |
| 2931 | - 'tax_query' => [ // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query | |
| 2932 | - 'relation' => strtoupper( $relation ), | |
| 2933 | - ], | |
| 2934 | - ]; | |
| 2935 | - | |
| 2936 | - foreach ( $terms_by_taxonomy as $taxonomy => $terms ) { | |
| 2937 | - $args['tax_query'][] = [ | |
| 2938 | - 'taxonomy' => $taxonomy, | |
| 2939 | - 'field' => 'term_id', | |
| 2940 | - 'terms' => $terms, | |
| 2941 | - 'operator' => 'IN', | |
| 2942 | - ]; | |
| 2943 | - } | |
| 2944 | - | |
| 2945 | - $query = new WC_Product_Query( $args ); | |
| 2946 | - $products = $query->get_products(); | |
| 2947 | - | |
| 2948 | - return count( $products ); | |
| 2949 | - } | |
| 2950 | - | |
| 2951 | - /** | |
| 2952 | 2475 | * Check if product filters widget has ajax. |
| 2953 | 2476 | * |
| 2954 | 2477 | * @param string $page Page name. |
| 2955 | 2478 | * |
| @@ -2983,233 +2506,8 @@ | ||
| 2983 | 2506 | return ! empty( $ajax[0] ); |
| 2984 | 2507 | } |
| 2985 | 2508 | |
| 2986 | 2509 | /** |
| 2987 | - * Build the active filter chips HTML from the current request query string. | |
| 2988 | - * | |
| 2989 | - * Mirrors the markup produced by the JS `displayAppliedFilter()` method so | |
| 2990 | - * the chips are visible on initial page load (before AJAX hydration). | |
| 2991 | - * | |
| 2992 | - * @return string HTML for the active filter chips, or empty string if none. | |
| 2993 | - */ | |
| 2994 | - public static function get_active_filters_html() { | |
| 2995 | - // phpcs:disable WordPress.Security.NonceVerification.Recommended -- Read-only query string parsing for display. | |
| 2996 | - if ( empty( $_GET ) ) { | |
| 2997 | - return ''; | |
| 2998 | - } | |
| 2999 | - | |
| 3000 | - $skip_keys = [ | |
| 3001 | - 'displayview', | |
| 3002 | - 'orderby', | |
| 3003 | - 'paged', | |
| 3004 | - 'page', | |
| 3005 | - 'product-page', | |
| 3006 | - 'rtsb_archive_page', | |
| 3007 | - 'rtsb_grid_columns', | |
| 3008 | - 'min_price', | |
| 3009 | - 'max_price', | |
| 3010 | - '_pjax', | |
| 3011 | - ]; | |
| 3012 | - | |
| 3013 | - // When the "Product Categories" widget is already showing the active | |
| 3014 | - // category navigation, suppress the duplicate product_cat chip group. | |
| 3015 | - if ( self::is_product_categories_widget_active() ) { | |
| 3016 | - $skip_keys[] = 'product_cat'; | |
| 3017 | - } | |
| 3018 | - | |
| 3019 | - $groups = []; | |
| 3020 | - | |
| 3021 | - foreach ( $_GET as $raw_key => $raw_value ) { | |
| 3022 | - $key = sanitize_key( $raw_key ); | |
| 3023 | - | |
| 3024 | - if ( '' === $key || in_array( $key, $skip_keys, true ) ) { | |
| 3025 | - continue; | |
| 3026 | - } | |
| 3027 | - | |
| 3028 | - if ( 0 === strpos( $key, 'query_type_' ) ) { | |
| 3029 | - continue; | |
| 3030 | - } | |
| 3031 | - | |
| 3032 | - if ( is_array( $raw_value ) ) { | |
| 3033 | - continue; | |
| 3034 | - } | |
| 3035 | - | |
| 3036 | - $value = sanitize_text_field( wp_unslash( $raw_value ) ); | |
| 3037 | - | |
| 3038 | - if ( '' === $value ) { | |
| 3039 | - continue; | |
| 3040 | - } | |
| 3041 | - | |
| 3042 | - $taxonomy = $key; | |
| 3043 | - if ( 0 === strpos( $taxonomy, 'filter_' ) ) { | |
| 3044 | - $taxonomy = 'pa_' . substr( $taxonomy, 7 ); | |
| 3045 | - } | |
| 3046 | - | |
| 3047 | - $items = []; | |
| 3048 | - foreach ( explode( ',', $value ) as $slug ) { | |
| 3049 | - $slug = trim( $slug ); | |
| 3050 | - if ( '' === $slug ) { | |
| 3051 | - continue; | |
| 3052 | - } | |
| 3053 | - $items[] = [ | |
| 3054 | - 'slug' => $slug, | |
| 3055 | - 'name' => self::get_active_filter_term_label( $taxonomy, $slug, $key ), | |
| 3056 | - ]; | |
| 3057 | - } | |
| 3058 | - | |
| 3059 | - if ( empty( $items ) ) { | |
| 3060 | - continue; | |
| 3061 | - } | |
| 3062 | - | |
| 3063 | - $groups[ $key ] = [ | |
| 3064 | - 'label' => self::get_active_filter_group_label( $taxonomy, $key ), | |
| 3065 | - 'items' => $items, | |
| 3066 | - 'class' => $key, | |
| 3067 | - ]; | |
| 3068 | - } | |
| 3069 | - | |
| 3070 | - // Price range as a single combined chip. | |
| 3071 | - if ( isset( $_GET['min_price'] ) || isset( $_GET['max_price'] ) ) { | |
| 3072 | - $min = isset( $_GET['min_price'] ) ? sanitize_text_field( wp_unslash( $_GET['min_price'] ) ) : ''; | |
| 3073 | - $max = isset( $_GET['max_price'] ) ? sanitize_text_field( wp_unslash( $_GET['max_price'] ) ) : ''; | |
| 3074 | - | |
| 3075 | - if ( '' !== $min || '' !== $max ) { | |
| 3076 | - $symbol = function_exists( 'get_woocommerce_currency_symbol' ) ? get_woocommerce_currency_symbol() : ''; | |
| 3077 | - $groups['price_filter'] = [ | |
| 3078 | - 'label' => esc_html__( 'Price', 'shopbuilder' ), | |
| 3079 | - 'class' => 'price_filter', | |
| 3080 | - 'items' => [ | |
| 3081 | - [ | |
| 3082 | - 'slug' => $min . ',' . $max, | |
| 3083 | - 'name' => $symbol . $min . ' - ' . $symbol . $max, | |
| 3084 | - 'extra_class' => ' remove-price', | |
| 3085 | - ], | |
| 3086 | - ], | |
| 3087 | - ]; | |
| 3088 | - } | |
| 3089 | - } | |
| 3090 | - | |
| 3091 | - if ( empty( $groups ) ) { | |
| 3092 | - return ''; | |
| 3093 | - } | |
| 3094 | - | |
| 3095 | - $html = '<div class="rtsb-active-filters">'; | |
| 3096 | - | |
| 3097 | - foreach ( $groups as $key => $group ) { | |
| 3098 | - $html .= '<div class="active-filter ' . esc_attr( $group['class'] ) . '">'; | |
| 3099 | - | |
| 3100 | - if ( ! empty( $group['label'] ) ) { | |
| 3101 | - $html .= '<div class="filter-name">' . esc_html( $group['label'] ) . ': </div>'; | |
| 3102 | - } | |
| 3103 | - | |
| 3104 | - $html .= '<div class="filter-item-container">'; | |
| 3105 | - | |
| 3106 | - foreach ( $group['items'] as $item ) { | |
| 3107 | - $extra = isset( $item['extra_class'] ) ? $item['extra_class'] : ''; | |
| 3108 | - $html .= '<div class="filter-item">' . esc_html( $item['name'] ); | |
| 3109 | - $html .= '<span class="remove-filter' . esc_attr( $extra ) . '"'; | |
| 3110 | - $html .= ' title="' . esc_attr( sprintf( /* translators: %s: filter term name */ __( 'Remove %s', 'shopbuilder' ), $item['name'] ) ) . '"'; | |
| 3111 | - $html .= ' data-filter-name="' . esc_attr( $key ) . '"'; | |
| 3112 | - $html .= ' data-filter-value="' . esc_attr( $item['slug'] ) . '">'; | |
| 3113 | - $html .= '<i class="rtsb-icon rtsb-icon-delete"></i></span>'; | |
| 3114 | - $html .= '</div>'; | |
| 3115 | - } | |
| 3116 | - | |
| 3117 | - $html .= '</div></div>'; | |
| 3118 | - } | |
| 3119 | - | |
| 3120 | - $html .= '<a href="#" class="rtsb-clear-filters"><span class="icon-wrap"><i class="eicon-trash-o"></i></span><span>' . esc_html__( 'Reset Filters', 'shopbuilder' ) . '</span></a>'; | |
| 3121 | - $html .= '</div>'; | |
| 3122 | - | |
| 3123 | - return $html; | |
| 3124 | - // phpcs:enable | |
| 3125 | - } | |
| 3126 | - | |
| 3127 | - /** | |
| 3128 | - * Determine whether the "Product Categories" Elementor widget is present | |
| 3129 | - * on the current shop/archive layout. Used to avoid duplicating the | |
| 3130 | - * product_cat chip group when the widget already shows the active term. | |
| 3131 | - * | |
| 3132 | - * @return bool | |
| 3133 | - */ | |
| 3134 | - private static function is_product_categories_widget_active() { | |
| 3135 | - $elmap = ElementorDataMap::instance(); | |
| 3136 | - | |
| 3137 | - foreach ( [ 'shop', 'archive' ] as $page ) { | |
| 3138 | - $id = BuilderFns::is_builder_preview() ? get_the_ID() : BuilderFns::builder_page_id_by_type( $page ); | |
| 3139 | - | |
| 3140 | - if ( ! $id ) { | |
| 3141 | - continue; | |
| 3142 | - } | |
| 3143 | - | |
| 3144 | - $widgets = $elmap->get_widget_data( 'rtsb-product-categories-general', [], $id ); | |
| 3145 | - | |
| 3146 | - if ( ! empty( $widgets ) ) { | |
| 3147 | - return true; | |
| 3148 | - } | |
| 3149 | - } | |
| 3150 | - | |
| 3151 | - return false; | |
| 3152 | - } | |
| 3153 | - | |
| 3154 | - /** | |
| 3155 | - * Resolve the display label for an active filter group (taxonomy heading). | |
| 3156 | - * | |
| 3157 | - * @param string $taxonomy Resolved taxonomy slug (e.g. product_cat, pa_color). | |
| 3158 | - * @param string $raw_key Original URL key (e.g. product_cat, filter_color). | |
| 3159 | - * | |
| 3160 | - * @return string | |
| 3161 | - */ | |
| 3162 | - private static function get_active_filter_group_label( $taxonomy, $raw_key ) { | |
| 3163 | - if ( 's' === $raw_key || 'search' === $raw_key ) { | |
| 3164 | - return esc_html__( 'Search', 'shopbuilder' ); | |
| 3165 | - } | |
| 3166 | - if ( 'rating_filter' === $raw_key ) { | |
| 3167 | - return esc_html__( 'Ratings', 'shopbuilder' ); | |
| 3168 | - } | |
| 3169 | - if ( 'sale_filter' === $raw_key ) { | |
| 3170 | - return esc_html__( 'Sale Filter', 'shopbuilder' ); | |
| 3171 | - } | |
| 3172 | - | |
| 3173 | - if ( 0 === strpos( $taxonomy, 'pa_' ) && function_exists( 'wc_attribute_label' ) ) { | |
| 3174 | - return wc_attribute_label( $taxonomy ); | |
| 3175 | - } | |
| 3176 | - | |
| 3177 | - if ( taxonomy_exists( $taxonomy ) ) { | |
| 3178 | - $tax_obj = get_taxonomy( $taxonomy ); | |
| 3179 | - if ( $tax_obj && ! empty( $tax_obj->labels->name ) ) { | |
| 3180 | - return $tax_obj->labels->name; | |
| 3181 | - } | |
| 3182 | - } | |
| 3183 | - | |
| 3184 | - return ucwords( str_replace( [ '_', '-' ], ' ', $raw_key ) ); | |
| 3185 | - } | |
| 3186 | - | |
| 3187 | - /** | |
| 3188 | - * Resolve a term slug to its display name; fall back to a humanised slug. | |
| 3189 | - * | |
| 3190 | - * @param string $taxonomy Resolved taxonomy slug. | |
| 3191 | - * @param string $slug Raw slug from query string. | |
| 3192 | - * @param string $raw_key Original URL key. | |
| 3193 | - * | |
| 3194 | - * @return string | |
| 3195 | - */ | |
| 3196 | - private static function get_active_filter_term_label( $taxonomy, $slug, $raw_key ) { | |
| 3197 | - if ( 's' === $raw_key || 'search' === $raw_key || 'rating_filter' === $raw_key ) { | |
| 3198 | - return rawurldecode( $slug ); | |
| 3199 | - } | |
| 3200 | - | |
| 3201 | - if ( taxonomy_exists( $taxonomy ) ) { | |
| 3202 | - $term = get_term_by( 'slug', $slug, $taxonomy ); | |
| 3203 | - if ( $term && ! is_wp_error( $term ) ) { | |
| 3204 | - return $term->name; | |
| 3205 | - } | |
| 3206 | - } | |
| 3207 | - | |
| 3208 | - return ucwords( str_replace( [ '-', '_' ], ' ', rawurldecode( $slug ) ) ); | |
| 3209 | - } | |
| 3210 | - | |
| 3211 | - /** | |
| 3212 | 2510 | * Check if product has applied filter. |
| 3213 | 2511 | * |
| 3214 | 2512 | * @param string $page Page name. |
| 3215 | 2513 | * |
| @@ -3230,15 +2528,8 @@ | ||
| 3230 | 2528 | $ajax[] = ! isset( $data['settings']['active_filter'] ); |
| 3231 | 2529 | |
| 3232 | 2530 | } |
| 3233 | 2531 | |
| 3234 | - // Also account for the free, non-AJAX "Product Filters" widget so that | |
| 3235 | - // the active filter chips wrapper renders for it on initial page load. | |
| 3236 | - foreach ( $elmap->get_widget_data( 'rtsb-product-filters', [], $id ) as $data ) { | |
| 3237 | - $ajax[] = true; | |
| 3238 | - unset( $data ); | |
| 3239 | - } | |
| 3240 | - | |
| 3241 | 2532 | return ! empty( $ajax[0] ); |
| 3242 | 2533 | } |
| 3243 | 2534 | |
| 3244 | 2535 | /** |
| @@ -3252,14 +2543,14 @@ | ||
| 3252 | 2543 | if ( ! is_admin() ) { |
| 3253 | 2544 | return []; |
| 3254 | 2545 | } |
| 3255 | 2546 | |
| 3256 | - $cache_key = 'rtsb_product_categories_' . md5( serialize( $search_query ) ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_serialize | |
| 2547 | + $cache_key = 'rtsb_product_categories_' . md5( serialize( $search_query ) ); | |
| 3257 | 2548 | |
| 3258 | 2549 | if ( isset( self::$cache[ $cache_key ] ) ) { |
| 3259 | 2550 | return self::$cache[ $cache_key ]; |
| 3260 | 2551 | } |
| 3261 | - $results = wp_cache_get( $cache_key, Cache::group() ); | |
| 2552 | + $results = wp_cache_get( $cache_key, 'shopbuilder' ); | |
| 3262 | 2553 | if ( ! $results ) { |
| 3263 | 2554 | global $wpdb; |
| 3264 | 2555 | $sql = "SELECT t.term_id, t.name |
| 3265 | 2556 | FROM {$wpdb->terms} t |
| @@ -3274,9 +2565,9 @@ | ||
| 3274 | 2565 | } |
| 3275 | 2566 | |
| 3276 | 2567 | $results = $wpdb->get_results( $prepared_sql ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.PreparedSQL.NotPrepared |
| 3277 | 2568 | // Cache the results in the object cache for future use. |
| 3278 | - wp_cache_set( $cache_key, $results, Cache::group(), 12 * HOUR_IN_SECONDS ); | |
| 2569 | + wp_cache_set( $cache_key, $results, 'shopbuilder' ); // Adjust the expiration time as needed. | |
| 3279 | 2570 | Cache::set_data_cache_key( $cache_key ); |
| 3280 | 2571 | } |
| 3281 | 2572 | |
| 3282 | 2573 | $cats = []; |
| @@ -3308,14 +2599,14 @@ | ||
| 3308 | 2599 | if ( ! is_admin() ) { |
| 3309 | 2600 | return []; |
| 3310 | 2601 | } |
| 3311 | 2602 | |
| 3312 | - $cache_key = 'rtsb_product_tags_' . md5( serialize( $search_query ) ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_serialize | |
| 2603 | + $cache_key = 'rtsb_product_tags_' . md5( serialize( $search_query ) ); | |
| 3313 | 2604 | |
| 3314 | 2605 | if ( isset( self::$cache[ $cache_key ] ) ) { |
| 3315 | 2606 | return self::$cache[ $cache_key ]; |
| 3316 | 2607 | } |
| 3317 | - $results = wp_cache_get( $cache_key, Cache::group() ); | |
| 2608 | + $results = wp_cache_get( $cache_key, 'shopbuilder' ); | |
| 3318 | 2609 | if ( ! $results ) { |
| 3319 | 2610 | global $wpdb; |
| 3320 | 2611 | $sql = "SELECT t.term_id, t.name |
| 3321 | 2612 | FROM {$wpdb->terms} t |
| @@ -3330,9 +2621,9 @@ | ||
| 3330 | 2621 | } |
| 3331 | 2622 | |
| 3332 | 2623 | $results = $wpdb->get_results( $prepared_sql ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.PreparedSQL.NotPrepared |
| 3333 | 2624 | // Cache the results in the object cache for future use. |
| 3334 | - wp_cache_set( $cache_key, $results, Cache::group(), 12 * HOUR_IN_SECONDS ); | |
| 2625 | + wp_cache_set( $cache_key, $results, 'shopbuilder' ); // Adjust the expiration time as needed. | |
| 3335 | 2626 | Cache::set_data_cache_key( $cache_key ); |
| 3336 | 2627 | } |
| 3337 | 2628 | |
| 3338 | 2629 | $cats = []; |
| @@ -3412,9 +2703,8 @@ | ||
| 3412 | 2703 | /** |
| 3413 | 2704 | * Get Post Types. |
| 3414 | 2705 | * |
| 3415 | 2706 | * @param string $search_query Search query. |
| 3416 | - * @param array $args Arguments. | |
| 3417 | 2707 | * |
| 3418 | 2708 | * @return array |
| 3419 | 2709 | */ |
| 3420 | 2710 | public static function get_post_types( $search_query = null, $args = [] ) { |
| @@ -3425,8 +2715,9 @@ | ||
| 3425 | 2715 | 'post_type' => 'any', |
| 3426 | 2716 | 'posts_per_page' => 20, |
| 3427 | 2717 | 'orderby' => 'ID', |
| 3428 | 2718 | 'order' => 'DESC', |
| 2719 | + // 'suppress_filters' => false, // WPML Support, Remove Others Languages. | |
| 3429 | 2720 | ] |
| 3430 | 2721 | ); |
| 3431 | 2722 | |
| 3432 | 2723 | if ( 'archive' !== $args['post_type'] ) { |
| @@ -3484,9 +2775,9 @@ | ||
| 3484 | 2775 | public static function renderView( $viewName, $args = [], $return = false ) { |
| 3485 | 2776 | $viewName = str_replace( '.', '/', $viewName ); |
| 3486 | 2777 | |
| 3487 | 2778 | if ( ! empty( $args ) && is_array( $args ) ) { |
| 3488 | - extract( $args ); // phpcs:ignore WordPress.PHP.DontExtract.extract_extract | |
| 2779 | + extract( $args ); | |
| 3489 | 2780 | } |
| 3490 | 2781 | |
| 3491 | 2782 | $view_file = rtsb()->plugin_path() . '/resources/' . $viewName . '.php'; |
| 3492 | 2783 | |
| @@ -3508,9 +2799,9 @@ | ||
| 3508 | 2799 | |
| 3509 | 2800 | /** |
| 3510 | 2801 | * Best selling product query. |
| 3511 | 2802 | * |
| 3512 | - * @param int $minimum_sale Minimum sale. | |
| 2803 | + * @param int $minimum_sale Minimum sale/ | |
| 3513 | 2804 | * @param int $limit Total limit. |
| 3514 | 2805 | * |
| 3515 | 2806 | * @return array|mixed |
| 3516 | 2807 | */ |
| @@ -3603,9 +2894,12 @@ | ||
| 3603 | 2894 | |
| 3604 | 2895 | /** |
| 3605 | 2896 | * Checks if a feature is disabled for guest users based on the provided option. |
| 3606 | 2897 | * |
| 3607 | - * @return void | |
| 2898 | + * @param string $option The option to retrieve from the item. | |
| 2899 | + * @param mixed $default The default value if the option is not found. | |
| 2900 | + * | |
| 2901 | + * @return bool | |
| 3608 | 2902 | */ |
| 3609 | 2903 | public static function woocommerce_output_all_notices() { |
| 3610 | 2904 | if ( function_exists( 'wc_print_notices' ) ) : |
| 3611 | 2905 | echo '<div class="rtsb-notice">'; |
| @@ -3724,8 +3018,9 @@ | ||
| 3724 | 3018 | /** |
| 3725 | 3019 | * Generates HTML markup for displaying an endpoint icon. |
| 3726 | 3020 | * |
| 3727 | 3021 | * @param array $data The endpoint data containing icon information. |
| 3022 | + * @param string $endpoint The endpoint identifier. | |
| 3728 | 3023 | * @param boolean $wrapper Whether to wrap the icon in a span element. |
| 3729 | 3024 | * |
| 3730 | 3025 | * @return string |
| 3731 | 3026 | */ |
| @@ -3808,18 +3103,12 @@ | ||
| 3808 | 3103 | |
| 3809 | 3104 | /** |
| 3810 | 3105 | * Social Share Platforms. |
| 3811 | 3106 | * |
| 3812 | - * @param string $section_id Section ID. | |
| 3813 | - * @param string $block_id Block ID. | |
| 3814 | - * @param string $option_key Option key. | |
| 3815 | - * @param string $compare_key Compare key. | |
| 3816 | - * @param string $compare_value Compare value. | |
| 3817 | - * @param array $values Values. | |
| 3818 | - * | |
| 3819 | - * @return void | |
| 3107 | + * @return mixed|null | |
| 3820 | 3108 | */ |
| 3821 | 3109 | public static function set_repeater_options( $section_id, $block_id, $option_key, $compare_key, $compare_value, $values ) { |
| 3110 | + // $options = self::get_options( $section_id, $block_id ); | |
| 3822 | 3111 | $modules = DataModel::source()->get_option( $section_id, [], false ); |
| 3823 | 3112 | if ( empty( $modules[ $block_id ] ) ) { |
| 3824 | 3113 | return; |
| 3825 | 3114 | } |
| @@ -3865,14 +3154,14 @@ | ||
| 3865 | 3154 | * |
| 3866 | 3155 | * @param array $options CSS options to apply (e.g. padding, margin). |
| 3867 | 3156 | * @param string $cache_key Cache key for the CSS. |
| 3868 | 3157 | * @param array $css_properties An array of CSS properties with selectors and properties. |
| 3158 | + * @param string $style_handle The handle for the inline styles. | |
| 3869 | 3159 | * |
| 3870 | 3160 | * @return void |
| 3871 | 3161 | */ |
| 3872 | - public static function dynamic_styles( $options, $cache_key, $css_properties ) { | |
| 3873 | - $cached_css = wp_cache_get( $cache_key, Cache::group() ); | |
| 3874 | - $style_handle = self::optimized_handle( 'rtsb-frontend' ); | |
| 3162 | + public static function dynamic_styles( $options, $cache_key, $css_properties, $style_handle = 'rtsb-frontend' ) { | |
| 3163 | + $cached_css = wp_cache_get( $cache_key, 'shopbuilder' ); | |
| 3875 | 3164 | |
| 3876 | 3165 | if ( false !== $cached_css ) { |
| 3877 | 3166 | wp_add_inline_style( $style_handle, $cached_css ); |
| 3878 | 3167 | return; |
| @@ -3907,9 +3196,9 @@ | ||
| 3907 | 3196 | } |
| 3908 | 3197 | |
| 3909 | 3198 | $dynamic_css = implode( ' ', $css_rules ); |
| 3910 | 3199 | |
| 3911 | - wp_cache_set( $cache_key, $dynamic_css, Cache::group(), 12 * HOUR_IN_SECONDS ); | |
| 3200 | + wp_cache_set( $cache_key, $dynamic_css, 'shopbuilder', 12 * HOUR_IN_SECONDS ); | |
| 3912 | 3201 | Cache::set_data_cache_key( $cache_key ); |
| 3913 | 3202 | |
| 3914 | 3203 | if ( ! empty( $dynamic_css ) ) { |
| 3915 | 3204 | wp_add_inline_style( $style_handle, $dynamic_css ); |
| @@ -3919,11 +3208,8 @@ | ||
| 3919 | 3208 | /** |
| 3920 | 3209 | * Pro version notice. |
| 3921 | 3210 | * |
| 3922 | 3211 | * @param string $ver Pro Version. |
| 3923 | - * @param string $tab Tab. | |
| 3924 | - * @param string $name Name. | |
| 3925 | - * @param bool $enable_free_Link Enable free link. | |
| 3926 | 3212 | * |
| 3927 | 3213 | * @return array[] |
| 3928 | 3214 | */ |
| 3929 | 3215 | public static function pro_version_notice( $ver, $tab = 'billing_fields', $name = 'ShopBuilder', $enable_free_Link = true ) { |
| @@ -3972,9 +3258,9 @@ | ||
| 3972 | 3258 | if ( isset( self::$cache[ $cache_key ] ) ) { |
| 3973 | 3259 | return self::$cache[ $cache_key ]; |
| 3974 | 3260 | } |
| 3975 | 3261 | |
| 3976 | - $cached_result = wp_cache_get( $cache_key, Cache::group() ); | |
| 3262 | + $cached_result = wp_cache_get( $cache_key, 'shopbuilder' ); | |
| 3977 | 3263 | |
| 3978 | 3264 | if ( false !== $cached_result ) { |
| 3979 | 3265 | self::$cache[ $cache_key ] = $cached_result; |
| 3980 | 3266 | |
| @@ -3983,575 +3269,10 @@ | ||
| 3983 | 3269 | |
| 3984 | 3270 | $gallery_ids = $product->get_gallery_image_ids(); |
| 3985 | 3271 | self::$cache[ $cache_key ] = $gallery_ids; |
| 3986 | 3272 | |
| 3987 | - wp_cache_set( $cache_key, $gallery_ids, Cache::group(), 12 * HOUR_IN_SECONDS ); | |
| 3273 | + wp_cache_set( $cache_key, $gallery_ids, 'shopbuilder', 12 * HOUR_IN_SECONDS ); | |
| 3988 | 3274 | Cache::set_data_cache_key( $cache_key ); |
| 3989 | 3275 | |
| 3990 | 3276 | return $gallery_ids; |
| 3991 | - } | |
| 3992 | - | |
| 3993 | - /** | |
| 3994 | - * Check if optimization setting is turned on in the database. | |
| 3995 | - * | |
| 3996 | - * This only checks the user's setting value, without validating | |
| 3997 | - * whether the cache directory is writable. | |
| 3998 | - * | |
| 3999 | - * @return bool | |
| 4000 | - */ | |
| 4001 | - public static function is_optimization_setting_on() { | |
| 4002 | - $has_pro = rtsb()->has_pro(); | |
| 4003 | - $pro_ver = defined( 'RTSBPRO_VERSION' ) ? RTSBPRO_VERSION : 0; | |
| 4004 | - | |
| 4005 | - if ( $has_pro && version_compare( $pro_ver, '2.0.0', '<' ) ) { | |
| 4006 | - return false; | |
| 4007 | - } | |
| 4008 | - | |
| 4009 | - $generalList = GeneralList::instance()->get_data(); | |
| 4010 | - | |
| 4011 | - return 'on' === ( $generalList['optimization']['enable_optimization'] ?? '' ); | |
| 4012 | - } | |
| 4013 | - | |
| 4014 | - /** | |
| 4015 | - * Check if optimization is enabled and the cache directory is writable. | |
| 4016 | - * | |
| 4017 | - * @return bool | |
| 4018 | - */ | |
| 4019 | - public static function is_optimization_enabled() { | |
| 4020 | - // A bundle could not be built during this request, fall back to the | |
| 4021 | - // unbundled assets rather than emitting handles with an empty source. | |
| 4022 | - if ( self::$optimization_unavailable ) { | |
| 4023 | - return false; | |
| 4024 | - } | |
| 4025 | - | |
| 4026 | - if ( ! self::is_optimization_setting_on() ) { | |
| 4027 | - return false; | |
| 4028 | - } | |
| 4029 | - | |
| 4030 | - $upload = wp_upload_dir(); | |
| 4031 | - $cache_dir = trailingslashit( $upload['basedir'] ) . 'shopbuilder_uploads/cache/'; | |
| 4032 | - | |
| 4033 | - if ( ! wp_is_writable( $cache_dir ) ) { | |
| 4034 | - return false; | |
| 4035 | - } | |
| 4036 | - | |
| 4037 | - return true; | |
| 4038 | - } | |
| 4039 | - | |
| 4040 | - /** | |
| 4041 | - * Get the optimized handle. | |
| 4042 | - * | |
| 4043 | - * @param string $handle Base handle used for script/style IDs. | |
| 4044 | - * | |
| 4045 | - * @return string | |
| 4046 | - */ | |
| 4047 | - public static function optimized_handle( $handle ) { | |
| 4048 | - $use_optimization = self::is_optimization_enabled(); | |
| 4049 | - | |
| 4050 | - if ( $use_optimization ) { | |
| 4051 | - $handle = self::is_contextual_loading() ? self::get_optimized_handle_by_context() : 'rtsb-bundled'; | |
| 4052 | - } | |
| 4053 | - | |
| 4054 | - return $handle; | |
| 4055 | - } | |
| 4056 | - | |
| 4057 | - /** | |
| 4058 | - * Get the optimized handle by context. | |
| 4059 | - * | |
| 4060 | - * @return string | |
| 4061 | - */ | |
| 4062 | - public static function get_optimized_handle_by_context() { | |
| 4063 | - $context = self::detect_context(); | |
| 4064 | - | |
| 4065 | - if ( 'account' === $context ) { | |
| 4066 | - return 'rtsb-bundled-global'; | |
| 4067 | - } | |
| 4068 | - | |
| 4069 | - return "rtsb-bundled-$context"; | |
| 4070 | - } | |
| 4071 | - | |
| 4072 | - /** | |
| 4073 | - * Check if Elementor page. | |
| 4074 | - * | |
| 4075 | - * @param int $post_id Post ID. | |
| 4076 | - * | |
| 4077 | - * @return bool | |
| 4078 | - */ | |
| 4079 | - public static function is_elementor_page( $post_id = null ) { | |
| 4080 | - if ( ! defined( 'ELEMENTOR_VERSION' ) ) { | |
| 4081 | - return false; | |
| 4082 | - } | |
| 4083 | - | |
| 4084 | - $post_id = $post_id ?: get_the_ID(); | |
| 4085 | - | |
| 4086 | - if ( ! $post_id ) { | |
| 4087 | - return true; | |
| 4088 | - } | |
| 4089 | - | |
| 4090 | - return Plugin::$instance->documents->get( $post_id )->is_built_with_elementor(); | |
| 4091 | - } | |
| 4092 | - | |
| 4093 | - /** | |
| 4094 | - * Check if shop or archive. | |
| 4095 | - * | |
| 4096 | - * @return bool | |
| 4097 | - */ | |
| 4098 | - public static function is_shop_or_archive() { | |
| 4099 | - return is_shop() || is_product_category() || is_product_tag() || is_post_type_archive( 'product' ) || BuilderFns::is_archive() || BuilderFns::is_shop() || is_tax( 'product_brand' ); | |
| 4100 | - } | |
| 4101 | - | |
| 4102 | - /** | |
| 4103 | - * Detect context. | |
| 4104 | - * | |
| 4105 | - * @return string | |
| 4106 | - */ | |
| 4107 | - public static function detect_context() { | |
| 4108 | - switch ( true ) { | |
| 4109 | - case is_product() || BuilderFns::is_product(): | |
| 4110 | - $context = 'product'; | |
| 4111 | - break; | |
| 4112 | - | |
| 4113 | - case is_cart() || BuilderFns::is_cart(): | |
| 4114 | - $context = 'cart'; | |
| 4115 | - break; | |
| 4116 | - | |
| 4117 | - case is_checkout() || BuilderFns::is_checkout(): | |
| 4118 | - $context = 'checkout'; | |
| 4119 | - break; | |
| 4120 | - | |
| 4121 | - case self::is_shop_or_archive(): | |
| 4122 | - $context = 'shop'; | |
| 4123 | - break; | |
| 4124 | - | |
| 4125 | - default: | |
| 4126 | - $context = 'global'; | |
| 4127 | - break; | |
| 4128 | - } | |
| 4129 | - | |
| 4130 | - return apply_filters( 'rtsb/optimizer/context_detect', $context ); | |
| 4131 | - } | |
| 4132 | - | |
| 4133 | - /** | |
| 4134 | - * Enqueue optimized assets. | |
| 4135 | - * | |
| 4136 | - * @return void | |
| 4137 | - */ | |
| 4138 | - public static function enqueue_optimized_assets() { | |
| 4139 | - $asset_registry = AssetRegistry::instance(); | |
| 4140 | - $bundled_assets = $asset_registry->get_bundled_assets(); | |
| 4141 | - $context = self::detect_context(); | |
| 4142 | - $contextual_loading = self::is_contextual_loading(); | |
| 4143 | - $theme_handle = self::find_theme_stylesheet_handle(); | |
| 4144 | - | |
| 4145 | - if ( $contextual_loading ) { | |
| 4146 | - // Enqueue JS. | |
| 4147 | - if ( ! empty( $bundled_assets['js'] ) ) { | |
| 4148 | - $js_context = isset( $bundled_assets['js'][ $context ] ) ? $context : 'global'; | |
| 4149 | - | |
| 4150 | - if ( $js_context ) { | |
| 4151 | - wp_enqueue_script( $bundled_assets['js'][ $js_context ]['handle'] ); | |
| 4152 | - } | |
| 4153 | - } | |
| 4154 | - | |
| 4155 | - // Enqueue CSS. | |
| 4156 | - if ( ! empty( $bundled_assets['css'] ) ) { | |
| 4157 | - $css_context = isset( $bundled_assets['css'][ $context ] ) ? $context : 'global'; | |
| 4158 | - | |
| 4159 | - if ( $css_context ) { | |
| 4160 | - $handle = $bundled_assets['css'][ $css_context ]['handle']; | |
| 4161 | - | |
| 4162 | - wp_enqueue_style( $handle ); | |
| 4163 | - | |
| 4164 | - if ( ! empty( $theme_handle ) ) { | |
| 4165 | - self::set_theme_dependency( $theme_handle, $handle ); | |
| 4166 | - } | |
| 4167 | - } | |
| 4168 | - } | |
| 4169 | - } else { | |
| 4170 | - // Enqueue JS. | |
| 4171 | - if ( ! empty( $bundled_assets['js'] ) ) { | |
| 4172 | - wp_enqueue_script( $bundled_assets['js']['handle'] ); | |
| 4173 | - } | |
| 4174 | - | |
| 4175 | - // Enqueue CSS. | |
| 4176 | - if ( ! empty( $bundled_assets['css'] ) ) { | |
| 4177 | - $handle = $bundled_assets['css']['handle']; | |
| 4178 | - | |
| 4179 | - wp_enqueue_style( $handle ); | |
| 4180 | - | |
| 4181 | - if ( ! empty( $theme_handle ) ) { | |
| 4182 | - self::set_theme_dependency( $theme_handle, $handle ); | |
| 4183 | - } | |
| 4184 | - } | |
| 4185 | - } | |
| 4186 | - } | |
| 4187 | - | |
| 4188 | - /** | |
| 4189 | - * Find theme stylesheet handle. | |
| 4190 | - * | |
| 4191 | - * @return string|false | |
| 4192 | - */ | |
| 4193 | - private static function find_theme_stylesheet_handle() { | |
| 4194 | - static $cached_handle = null; | |
| 4195 | - | |
| 4196 | - if ( null !== $cached_handle ) { | |
| 4197 | - return $cached_handle; | |
| 4198 | - } | |
| 4199 | - | |
| 4200 | - global $wp_styles; | |
| 4201 | - | |
| 4202 | - if ( ! $wp_styles instanceof WP_Styles ) { | |
| 4203 | - return false; | |
| 4204 | - } | |
| 4205 | - | |
| 4206 | - $stylesheet_uri = get_stylesheet_uri(); | |
| 4207 | - $theme_directory_uri = get_stylesheet_directory_uri(); | |
| 4208 | - | |
| 4209 | - $hash = md5( $stylesheet_uri ); | |
| 4210 | - $transient_key = 'rtsb_theme_css_handle_' . $hash; | |
| 4211 | - | |
| 4212 | - $transient = get_transient( $transient_key ); | |
| 4213 | - | |
| 4214 | - if ( false !== $transient ) { | |
| 4215 | - $cached_handle = $transient; | |
| 4216 | - | |
| 4217 | - return $transient; | |
| 4218 | - } | |
| 4219 | - | |
| 4220 | - foreach ( $wp_styles->registered as $handle => $style ) { | |
| 4221 | - $src = $style->src; | |
| 4222 | - | |
| 4223 | - if ( | |
| 4224 | - ( $src === $stylesheet_uri || strpos( $src, $theme_directory_uri ) !== false ) && | |
| 4225 | - strpos( $src, 'style.css' ) !== false | |
| 4226 | - ) { | |
| 4227 | - set_transient( $transient_key, $handle, DAY_IN_SECONDS ); | |
| 4228 | - $cached_handle = $handle; | |
| 4229 | - | |
| 4230 | - return $handle; | |
| 4231 | - } | |
| 4232 | - } | |
| 4233 | - | |
| 4234 | - $filtered_handle = apply_filters( 'rtsb/optimizer/theme_stylesheet_handle', false ); | |
| 4235 | - | |
| 4236 | - if ( is_string( $filtered_handle ) && ! empty( $filtered_handle ) ) { | |
| 4237 | - set_transient( $transient_key, $filtered_handle, DAY_IN_SECONDS ); | |
| 4238 | - $cached_handle = $filtered_handle; | |
| 4239 | - | |
| 4240 | - return $filtered_handle; | |
| 4241 | - } | |
| 4242 | - | |
| 4243 | - set_transient( $transient_key, false, DAY_IN_SECONDS ); | |
| 4244 | - $cached_handle = false; | |
| 4245 | - | |
| 4246 | - return false; | |
| 4247 | - } | |
| 4248 | - | |
| 4249 | - /** | |
| 4250 | - * Set theme dependency. | |
| 4251 | - * | |
| 4252 | - * @param string $theme_handle Theme handle. | |
| 4253 | - * @param string $our_handle Our handle. | |
| 4254 | - * | |
| 4255 | - * @return void | |
| 4256 | - */ | |
| 4257 | - private static function set_theme_dependency( $theme_handle, $our_handle ) { | |
| 4258 | - global $wp_styles; | |
| 4259 | - | |
| 4260 | - if ( ! isset( $wp_styles->registered[ $theme_handle ] ) ) { | |
| 4261 | - return; | |
| 4262 | - } | |
| 4263 | - | |
| 4264 | - $theme_style = $wp_styles->registered[ $theme_handle ]; | |
| 4265 | - | |
| 4266 | - // Add our handle as a dependency if it's not already there. | |
| 4267 | - if ( ! in_array( $our_handle, $theme_style->deps, true ) ) { | |
| 4268 | - $theme_style->deps[] = $our_handle; | |
| 4269 | - } | |
| 4270 | - } | |
| 4271 | - | |
| 4272 | - /** | |
| 4273 | - * Check if Elementor scripts should be loaded. | |
| 4274 | - * | |
| 4275 | - * @return bool | |
| 4276 | - */ | |
| 4277 | - public static function should_load_elementor_scripts() { | |
| 4278 | - $data = GeneralList::instance()->get_data()['optimization'] ?? []; | |
| 4279 | - | |
| 4280 | - $enable_optimization = $data['enable_optimization'] ?? 'on'; | |
| 4281 | - $load_elementor_scripts = $data['load_elementor_scripts'] ?? 'on'; | |
| 4282 | - | |
| 4283 | - if ( 'on' !== $enable_optimization ) { | |
| 4284 | - return true; | |
| 4285 | - } | |
| 4286 | - | |
| 4287 | - return 'on' === $load_elementor_scripts; | |
| 4288 | - } | |
| 4289 | - | |
| 4290 | - /** | |
| 4291 | - * Locate asset. | |
| 4292 | - * | |
| 4293 | - * @param string $relative_path Relative path. | |
| 4294 | - * | |
| 4295 | - * @return string|null | |
| 4296 | - */ | |
| 4297 | - public static function locate_asset( $relative_path ) { | |
| 4298 | - $free_context = rtsb(); | |
| 4299 | - $pro_context = function_exists( 'rtsbpro' ) && rtsb()->has_pro() ? rtsbpro() : null; | |
| 4300 | - | |
| 4301 | - $paths = []; | |
| 4302 | - | |
| 4303 | - if ( $pro_context ) { | |
| 4304 | - $paths[] = $pro_context->get_assets_path( $relative_path ); | |
| 4305 | - } | |
| 4306 | - | |
| 4307 | - $paths[] = $free_context->get_assets_path( $relative_path ); | |
| 4308 | - | |
| 4309 | - foreach ( $paths as $path ) { | |
| 4310 | - if ( file_exists( $path ) ) { | |
| 4311 | - return $path; | |
| 4312 | - } | |
| 4313 | - } | |
| 4314 | - | |
| 4315 | - return null; | |
| 4316 | - } | |
| 4317 | - | |
| 4318 | - /** | |
| 4319 | - * Enqueue module assets. | |
| 4320 | - * | |
| 4321 | - * @param string $handle Asset handle. | |
| 4322 | - * @param string $module_name Module name. | |
| 4323 | - * @param array $options Options array: ['type' => 'css|js|both', 'deps' => [], 'context' => null]. | |
| 4324 | - * | |
| 4325 | - * @return string | |
| 4326 | - */ | |
| 4327 | - public static function enqueue_module_assets( $handle, $module_name, $options = [] ) { | |
| 4328 | - $use_optimization = self::is_optimization_enabled(); | |
| 4329 | - $handle = self::optimized_handle( $handle ); | |
| 4330 | - | |
| 4331 | - if ( $use_optimization ) { | |
| 4332 | - return $handle; | |
| 4333 | - } | |
| 4334 | - | |
| 4335 | - $defaults = [ | |
| 4336 | - 'type' => 'both', | |
| 4337 | - 'deps' => [ 'jquery', 'rtsb-public' ], | |
| 4338 | - 'context' => null, | |
| 4339 | - 'version' => RTSB_VERSION, | |
| 4340 | - ]; | |
| 4341 | - | |
| 4342 | - $config = array_merge( $defaults, $options ); | |
| 4343 | - $rtl_suffix = is_rtl() ? '-rtl' : ''; | |
| 4344 | - $rtl_dir = is_rtl() ? trailingslashit( 'rtl' ) : trailingslashit( 'css' ); | |
| 4345 | - $context = $config['context'] ?: rtsb(); | |
| 4346 | - $load_css = in_array( $config['type'], [ 'css', 'both' ], true ); | |
| 4347 | - $load_js = in_array( $config['type'], [ 'js', 'both' ], true ); | |
| 4348 | - | |
| 4349 | - // Register CSS if enabled. | |
| 4350 | - if ( $load_css ) { | |
| 4351 | - wp_register_style( | |
| 4352 | - $handle, | |
| 4353 | - $context->get_assets_uri( $rtl_dir . 'modules/' . $module_name . $rtl_suffix . '.css' ), | |
| 4354 | - [], | |
| 4355 | - $config['version'] | |
| 4356 | - ); | |
| 4357 | - } | |
| 4358 | - | |
| 4359 | - // Register JS if enabled. | |
| 4360 | - if ( $load_js ) { | |
| 4361 | - wp_register_script( | |
| 4362 | - $handle, | |
| 4363 | - $context->get_assets_uri( 'js/modules/' . $module_name . '.js' ), | |
| 4364 | - $config['deps'], | |
| 4365 | - $config['version'], | |
| 4366 | - true | |
| 4367 | - ); | |
| 4368 | - } | |
| 4369 | - | |
| 4370 | - if ( $load_css ) { | |
| 4371 | - wp_enqueue_style( $handle ); | |
| 4372 | - | |
| 4373 | - $theme_handle = self::find_theme_stylesheet_handle(); | |
| 4374 | - | |
| 4375 | - if ( ! empty( $theme_handle ) ) { | |
| 4376 | - self::set_theme_dependency( $theme_handle, $handle ); | |
| 4377 | - } | |
| 4378 | - } | |
| 4379 | - | |
| 4380 | - if ( $load_js ) { | |
| 4381 | - wp_enqueue_script( $handle ); | |
| 4382 | - } | |
| 4383 | - | |
| 4384 | - return $handle; | |
| 4385 | - } | |
| 4386 | - | |
| 4387 | - /** | |
| 4388 | - * Check if contextual loading is enabled. | |
| 4389 | - * | |
| 4390 | - * @return bool | |
| 4391 | - */ | |
| 4392 | - public static function is_contextual_loading() { | |
| 4393 | - $data = GeneralList::instance()->get_data()['optimization'] ?? []; | |
| 4394 | - | |
| 4395 | - return ! empty( $data['context_asset_loading'] ) && 'on' === $data['context_asset_loading']; | |
| 4396 | - } | |
| 4397 | - | |
| 4398 | - /** | |
| 4399 | - * Get Modules list with cache support. | |
| 4400 | - * | |
| 4401 | - * @return array | |
| 4402 | - */ | |
| 4403 | - public static function get_modules_list() { | |
| 4404 | - static $cached_modules = null; | |
| 4405 | - | |
| 4406 | - if ( null !== $cached_modules ) { | |
| 4407 | - return $cached_modules; | |
| 4408 | - } | |
| 4409 | - | |
| 4410 | - $cache_key = 'rtsb_module_list'; | |
| 4411 | - $cache_group = Cache::group(); | |
| 4412 | - | |
| 4413 | - $cached = wp_cache_get( $cache_key, $cache_group ); | |
| 4414 | - | |
| 4415 | - if ( false !== $cached ) { | |
| 4416 | - $cached_modules = $cached; | |
| 4417 | - | |
| 4418 | - return $cached; | |
| 4419 | - } | |
| 4420 | - | |
| 4421 | - $modules = ModuleList::instance()->get_data(); | |
| 4422 | - | |
| 4423 | - wp_cache_set( $cache_key, $modules, $cache_group, 12 * HOUR_IN_SECONDS ); | |
| 4424 | - Cache::set_data_cache_key( $cache_key ); | |
| 4425 | - | |
| 4426 | - $cached_modules = $modules; | |
| 4427 | - | |
| 4428 | - return $modules; | |
| 4429 | - } | |
| 4430 | - | |
| 4431 | - /** | |
| 4432 | - * Get Elementor widgets list with cache support. | |
| 4433 | - * | |
| 4434 | - * @return array | |
| 4435 | - */ | |
| 4436 | - public static function get_widgets_list() { | |
| 4437 | - static $cached_widgets = null; | |
| 4438 | - | |
| 4439 | - if ( null !== $cached_widgets ) { | |
| 4440 | - return $cached_widgets; | |
| 4441 | - } | |
| 4442 | - | |
| 4443 | - $cache_key = 'rtsb_elementor_widget_list'; | |
| 4444 | - $cache_group = Cache::group(); | |
| 4445 | - | |
| 4446 | - $cached = wp_cache_get( $cache_key, $cache_group ); | |
| 4447 | - | |
| 4448 | - if ( false !== $cached ) { | |
| 4449 | - $cached_widgets = $cached; | |
| 4450 | - | |
| 4451 | - return $cached; | |
| 4452 | - } | |
| 4453 | - | |
| 4454 | - $widgets = ElementList::instance()->get_list(); | |
| 4455 | - | |
| 4456 | - wp_cache_set( $cache_key, $widgets, $cache_group, 12 * HOUR_IN_SECONDS ); | |
| 4457 | - Cache::set_data_cache_key( $cache_key ); | |
| 4458 | - | |
| 4459 | - $cached_widgets = $widgets; | |
| 4460 | - | |
| 4461 | - return $widgets; | |
| 4462 | - } | |
| 4463 | - | |
| 4464 | - /** | |
| 4465 | - * Convert the given price to the active currency. | |
| 4466 | - * | |
| 4467 | - * @param float $price The original price. | |
| 4468 | - * @param Object||null $product Product. | |
| 4469 | - * | |
| 4470 | - * @return float | |
| 4471 | - */ | |
| 4472 | - public static function get_currency_base_price( $price, $product = null ) { | |
| 4473 | - return apply_filters( 'rtsb/convert/currency/price', $price, $product ); | |
| 4474 | - } | |
| 4475 | - /** | |
| 4476 | - * Generate a signed URL with a payload. | |
| 4477 | - * | |
| 4478 | - * @param array $payload Associative data to encode. | |
| 4479 | - * @param string $base_url Base URL to append ?key=... (e.g. wc_get_checkout_url()). | |
| 4480 | - * @param string $key Key name to use in the URL. | |
| 4481 | - * @return string Signed URL with key parameter. | |
| 4482 | - */ | |
| 4483 | - public static function generate_signed_url( array $payload, string $base_url, $key = 'key' ) { | |
| 4484 | - if ( empty( $key ) ) { | |
| 4485 | - $key = 'key'; | |
| 4486 | - } | |
| 4487 | - // Convert payload to JSON. | |
| 4488 | - $data = wp_json_encode( $payload ); | |
| 4489 | - // Create signature. | |
| 4490 | - $signature = wp_hash( $data ); | |
| 4491 | - // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode | |
| 4492 | - $encode_key = base64_encode( $data . '::' . $signature ); | |
| 4493 | - // Return full URL with key param. | |
| 4494 | - return add_query_arg( [ $key => rawurlencode( $encode_key ) ], $base_url ); | |
| 4495 | - } | |
| 4496 | - | |
| 4497 | - /** | |
| 4498 | - * Decode and verify a signed URL key. | |
| 4499 | - * | |
| 4500 | - * @param string $key Encoded key from URL. | |
| 4501 | - * @return array|false Decoded payload array on success, false on failure. | |
| 4502 | - */ | |
| 4503 | - public static function decode_signed_key( string $key ) { | |
| 4504 | - if ( empty( $key ) ) { | |
| 4505 | - return false; | |
| 4506 | - } | |
| 4507 | - $key = rawurldecode( wp_unslash( $key ) ); | |
| 4508 | - // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_decode | |
| 4509 | - $raw = base64_decode( sanitize_text_field( $key ) ); | |
| 4510 | - if ( ! $raw ) { | |
| 4511 | - return false; | |
| 4512 | - } | |
| 4513 | - $parts = explode( '::', $raw, 2 ); | |
| 4514 | - if ( count( $parts ) !== 2 ) { | |
| 4515 | - return false; | |
| 4516 | - } | |
| 4517 | - list( $data_json, $signature ) = $parts; | |
| 4518 | - // Validate signature. | |
| 4519 | - if ( ! hash_equals( wp_hash( $data_json ), $signature ) ) { | |
| 4520 | - return false; | |
| 4521 | - } | |
| 4522 | - $payload = json_decode( $data_json, true ); | |
| 4523 | - return is_array( $payload ) ? $payload : false; | |
| 4524 | - } | |
| 4525 | - | |
| 4526 | - /** | |
| 4527 | - * Get Loco Translate MO file path for a plugin. | |
| 4528 | - * | |
| 4529 | - * @param string $textdomain Plugin textdomain. | |
| 4530 | - * @return void|false | |
| 4531 | - */ | |
| 4532 | - public static function load_loco_textdomain( $textdomain ) { | |
| 4533 | - if ( ! function_exists( 'loco_plugin_version' ) ) { | |
| 4534 | - return false; | |
| 4535 | - } | |
| 4536 | - $lang = WP_LANG_DIR; | |
| 4537 | - $path = $lang . '/plugins/' . $textdomain . '-' . get_locale() . '.mo'; | |
| 4538 | - if ( ! file_exists( $path ) && defined( 'LOCO_LANG_DIR' ) ) { | |
| 4539 | - $lang = LOCO_LANG_DIR; | |
| 4540 | - $path = $lang . '/plugins/' . $textdomain . '-' . get_locale() . '.mo'; | |
| 4541 | - } | |
| 4542 | - if ( ! file_exists( $path ) ) { | |
| 4543 | - if ( 'shopbuilder' === $textdomain ) { | |
| 4544 | - $plugin_root = dirname( RTSB_FILE ); | |
| 4545 | - } elseif ( 'shopbuilder-pro' === $textdomain ) { | |
| 4546 | - $plugin_root = dirname( RTSBPRO_FILE ); | |
| 4547 | - } else { | |
| 4548 | - return false; | |
| 4549 | - } | |
| 4550 | - $path = $plugin_root . '/languages/' . $textdomain . '-' . get_locale() . '.mo'; | |
| 4551 | - } | |
| 4552 | - if ( ! file_exists( $path ) ) { | |
| 4553 | - return false; | |
| 4554 | - } | |
| 4555 | - load_textdomain( $textdomain, $path ); | |
| 4556 | 3277 | } |
| 4557 | 3278 | } |