/', '', $content ); return !empty( $content ) ? \trim( $content ) : $content; } /** * Retrieves the list of supported product types. * This function provides an array of product types that are supported in the context of the application. * * @return array List of supported product types. */ public static function supported_product_types() { $product_types = array( 'simple', 'variable', 'variation', 'grouped', 'external', 'composite', 'bundle', 'bundled', 'yith_bundle', 'yith-composite', 'subscription', 'variable-subscription', 'woosb', 'woosg', 'auction', 'course' ); return apply_filters( 'ctx_filter_product_types_for_product_query', $product_types ); } /** * Removes all shortcodes from the given content. * This function processes the content to remove WordPress shortcodes, and additional shortcode-like patterns. * It first processes registered shortcodes, then removes any remaining shortcode-like structures. * * @param string $content The content from which to remove shortcodes. * @return string The content with shortcodes removed. */ public static function remove_shortcodes( $content ) { if ( $content === '' ) { return ''; } // Process registered shortcodes. $content = \strip_shortcodes( \do_shortcode( $content ) ); // Custom function to strip invalid XML, if necessary. $content = self::strip_invalid_xml( $content ); // More specific regex to target shortcode-like patterns. $expression = '/\[\/*[č?a-zA-Z1-90_| -=\'"\{\}]*\/*\]/m'; $content = \preg_replace( $expression, '', $content ); return $content; } /** * Adds UTM parameters to a given URL. * This function appends UTM (Urchin Tracking Module) parameters to a URL for tracking purposes. * Only parameters that are not empty will be added to the URL. * * @param array $utm Associative array of UTM parameters. * @param string $url The URL to which UTM parameters will be added. * @return string The URL with UTM parameters appended. */ public static function add_utm_parameter( array $utm, $url ) { if ( !empty( $utm['utm_source'] ) && !empty( $utm['utm_medium'] ) && !empty( $utm['utm_campaign'] ) ) { $utm = \array_map( function( $value ) { return \str_replace( ' ', '+', $value ); }, $utm); $url = \add_query_arg( \array_filter( $utm ), $url ); } return $url; } /** * Checks if the current WooCommerce version meets or exceeds the specified version. * It requires WooCommerce to be installed and activated. * * @param string $version The WooCommerce version to compare against, default '3.0'. * @return bool True if the current version is greater than or equal to the specified version, false otherwise. */ public static function wc_version_check( $version = '3.0' ) { if ( !\function_exists( 'get_plugins') ) { require_once ABSPATH . 'wp-admin/includes/plugin.php'; } $plugins = \get_plugins(); $plugin_path = 'woocommerce/woocommerce.php'; if ( !isset( $plugins[$plugin_path] ) ) { return false; } return \version_compare( $plugins[$plugin_path]['Version'], $version, '>=' ); } /** * Generates a unique option name by appending a numerical suffix if necessary. * This function sanitizes the provided slug, checks against a list of disallowed * names, and ensures uniqueness in the WordPress options table. * * @param string $slug The base slug to use for the option name. * @param string $prefix A prefix to be added to the slug (optional). * @param int|null $option_id An existing option ID to exclude from the check (optional). * @return string The unique, sanitized option name. */ public static function unique_option_name( $slug, $prefix = '', $option_id = null ) { global $wpdb; // Sanitize and prepare slug. $slug = \sanitize_key( $slug ); $slug = \str_replace( ' ', '_', $slug ); if ( '_' === \substr( $slug, -1 ) ) { $slug = \substr( $slug, 0, -1 ); } /** @noinspection SpellCheckingInspection */ $slug = \preg_replace( '/[^A-Za-z0-9_]/', '', $slug ); // List of disallowed slugs. $disallowed = array( 'siteurl', 'home', 'blogname', 'blogdescription', 'users_can_register', 'admin_email' ); if ( $option_id && $option_id > 0 ) { $check_sql = "SELECT option_name FROM $wpdb->options WHERE option_name = %s AND option_id != %d LIMIT 1"; $name_check = $wpdb->get_var( $wpdb->prepare( $check_sql, $prefix . $slug, $option_id ) ); // phpcs:ignore } else { $check_sql = "SELECT option_name FROM $wpdb->options WHERE option_name = %s LIMIT 1"; $name_check = $wpdb->get_var( $wpdb->prepare( $check_sql, $prefix . $slug ) ); // phpcs:ignore } // slug found or slug in disallowed list if ( $name_check || \in_array( $slug, $disallowed, true ) ) { $suffix = 2; do { $alt_name = \_truncate_post_slug( $slug, 200 - ( \strlen( $suffix ) + 1 ) ) . "-$suffix"; if ( $option_id && $option_id > 0 ) { $name_check = $wpdb->get_var( $wpdb->prepare( $check_sql, $prefix . $alt_name, $option_id ) ); // phpcs:ignore } else { $name_check = $wpdb->get_var( $wpdb->prepare( $check_sql, $prefix . $alt_name ) ); // phpcs:ignore } ++$suffix; } while ( $name_check ); $slug = $alt_name; } return $slug; } /** * Retrieves a list of option names from the WordPress database that start with a given prefix. * This function performs a database query to find all options matching the specified prefix. * * @param string $prefix The prefix to search for in option names. * @return array|object|null Array of objects containing option names or null on failure. */ public static function get_options( $prefix ) { global $wpdb; // Ensure the prefix is sanitized to prevent SQL injection. $safe_prefix = \esc_sql( $prefix ); $sql = "SELECT option_name FROM $wpdb->options WHERE option_name LIKE %s"; $prepared_sql = $wpdb->prepare( $sql, $safe_prefix . '%' ); // Execute the query and handle potential errors. try { $results = $wpdb->get_results( $prepared_sql ); return $results; } catch ( \Exception $e ) { // Consider logging the error or handling it as per your application's needs. return null; } } /** * Extends wp_strip_all_tags to handle WP_Error objects. * This function returns an empty string if the input is a WP_Error object, * otherwise, it strips all HTML tags from the input. * * @param string|\WP_Error $string The input to be processed. Can be a string or WP_Error object. * @return string The processed string without HTML tags, or an empty string if input was a WP_Error. * @since 4.5.10 */ public static function strip_all_tags( $string ) { if ( $string instanceof \WP_Error ) { return ''; } return \wp_strip_all_tags( $string ); } /** * Remove non supported xml character * * @param string $value * @return string * @since 4.5.10 * @see https://stackoverflow.com/questions/3466035/how-to-skip-invalid-characters-in-xml-file-using-php */ public static function strip_invalid_xml( $value ) { $ret = ''; if ( empty( $value ) ) { return $ret; } if ( \is_int( $value ) || is_float( $value )) { $ret = $value; } else { $length = \strlen( $value ); for ( $i = 0; $i < $length; $i++ ) { $current = \ord( $value[ $i ] ); if ( ( 0x9 === $current ) || ( 0xA === $current ) || ( 0xD === $current ) || ( ( $current >= 0x20 ) && ( $current <= 0xD7FF ) ) || ( ( $current >= 0xE000 ) && ( $current <= 0xFFFD ) ) || ( ( $current >= 0x10000 ) && ( $current <= 0x10FFFF ) ) ) { $ret .= \chr( $current ); } else { $ret .= ''; } } } return $ret; } /** * Returns the parent product ID for a variation product, or the product ID itself if it's not a variation. * This function is useful when needing to identify the main product associated with a variation. * * @param \WC_Product $product The WooCommerce product object. * @return int The ID of the parent product for variations, or the product's own ID. */ public static function parent_product_id( $product ) { if ( !$product instanceof \WC_Product ) { // Optionally handle the error if $product is not a valid WC_Product object. return 0; } return $product->is_type( 'variation' ) ? $product->get_parent_id() : $product->get_id(); } /** * Get parent product id for Polylang Multi Language * * @param int $element_id product id for current language * * @return int parent product id for parent language */ public static function woo_feed_pll_get_original_post_id( $element_id ) { if ( function_exists( 'pll_get_post_translations' ) ) { $polylang_post = pll_get_post_translations( $element_id ); $defaultLanguage = pll_default_language(); if ( isset( $polylang_post[ $defaultLanguage ] ) ) { $parent_id = $polylang_post[ $defaultLanguage ]; } } return ! empty( $parent_id ) ? $parent_id : $element_id; } }