\s\\{\\}\\];,])#si', '#(\\/\\*(?>.*?\\*\\/))|(\\burl\\()([\'"])([^\\s]+?)\\3(\\))#si', // Minify HEX color code '#(?<=[\\s=:,\\(]\\#)([a-f0-6]+)\\1([a-f0-6]+)\\2([a-f0-6]+)\\3#i', // Replace `(border|outline):none` with `(border|outline):0` '#(?<=[\\{;])(border|outline):none(?=[;\\}\\!])#', // Remove empty selector(s) '#(\\/\\*(?>.*?\\*\\/))|(^|[\\{\\}])(?:[^\\s\\{\\}]+)\\{\\}#s', '#\\x1A#', ), array( '$1', '$1$2$3$4$5$6$7', '$1', ':0', '$1:0 0', '.$1', '$1$3', '$1$2$4$5', '$1$2$3', '$1:0', '$1$2', ' ' ), $input ); } /** * Compare WooCommerce function * * @param $version * @param $op * * @return bool */ public static function compareWcVersion( $version, $op ) { if ( function_exists( 'WC' ) && version_compare( WC()->version, $version, $op ) ) { return true; } return false; } /** * Check if is settings page * @return bool */ public static function isSettingsPage() { if ( is_admin() && !empty($_GET['page']) && $_GET['page'] === 'dgwt_wcas_settings' ) { return true; } return false; } /** * Check if is debug page * @return bool */ public static function isDebugPage() { if ( is_admin() && !empty($_GET['page']) && $_GET['page'] === 'dgwt_wcas_debug' ) { return true; } return false; } /** * Check if is Freemius checkout page * @return bool */ public static function isCheckoutPage() { if ( is_admin() && !empty($_GET['page']) && $_GET['page'] === 'dgwt_wcas_settings-pricing' ) { return true; } return false; } /** * Get settings URL * * @return string */ public static function getSettingsUrl() { return admin_url( 'admin.php?page=dgwt_wcas_settings' ); } /** * Get total products * * @return int */ public static function getTotalProducts() { global $wpdb ; $sql = "SELECT COUNT(ID) FROM {$wpdb->posts} WHERE post_type = 'product' AND post_status = 'publish'"; $total = $wpdb->get_var( $sql ); return absint( $total ); } /** * Get all products IDs * @return array */ public static function getProductsForIndex() { global $wpdb ; $sql = "SELECT ID FROM {$wpdb->posts} WHERE post_type = 'product' AND post_status = 'publish' ORDER BY ID ASC"; $ids = $wpdb->get_col( $sql ); if ( !is_array( $ids ) || empty($ids[0]) || !is_numeric( $ids[0] ) ) { $ids = array(); } return $ids; } /** * Get readable format of memory * * @param int $bytes * * @return string */ public static function getReadableMemorySize( $bytes ) { $unit = array( 'b', 'kb', 'mb', 'gb', 'tb', 'pb' ); return @round( $bytes / pow( 1024, $i = floor( log( $bytes, 1024 ) ) ), 2 ) . ' ' . $unit[$i]; } /** * Get pro icon/label * * @param string $label * @param string $type * @param string $headerSubtitle * * @return string */ public static function getSettingsProLabel( $label, $type = 'header', $headerSubtitle = '' ) { $html = ''; switch ( $type ) { case 'header': if ( !empty($headerSubtitle) ) { $label = '' . $label . '' . $headerSubtitle . ''; } $html .= '
' . $label . '' . __( 'Pro', 'ajax-search-for-woocommerce' ) . '
'; break; case 'option-label': $html .= '
' . $label . '' . __( 'Pro', 'ajax-search-for-woocommerce' ) . '
'; break; } return $html; } /** * Calc score for searched * * @param string $searched * @param string $string eg. product title * @param array $args * * @return int */ public static function calcScore( $searched, $string, $args = array() ) { $score = 0; if ( empty($searched) || empty($string) ) { return $score; } $default = array( 'check_similarity' => true, 'check_position' => true, 'score_containing' => 50, ); $args = array_merge( $default, $args ); $searched = mb_strtolower( $searched ); $string = mb_strtolower( $string ); if ( $args['check_similarity'] ) { $m = similar_text( $searched, $string, $percent ); $score = ($score + $percent) / 3; } $pos = strpos( $string, $searched ); // Add score based on substring position if ( $pos !== false ) { $score += $args['score_containing']; // Bonus for contained substring // Bonus for substring position if ( $args['check_position'] ) { $posBonus = (100 - $pos * 100 / strlen( $string )) / 2; $score += $posBonus; } // Bonus for exact match if ( $string === $searched ) { $score += $args['score_containing'] * 5; } } return $score; } /** * Sorting by score * * @param $a * @param $b * * @return int */ public static function cmpSimilarity( $a, $b ) { $scoreA = 0; $scoreB = 0; if ( is_object( $a ) ) { $scoreA = $a->score; $scoreB = $b->score; } if ( is_array( $a ) ) { $scoreA = $a['score']; $scoreB = $b['score']; } if ( $scoreA == $scoreB ) { return 0; } return ( $scoreA < $scoreB ? 1 : -1 ); } /** * Sorting by search resutls groups priority * * @param $a * @param $b * * @return int */ public static function sortAjaxResutlsGroups( $a, $b ) { if ( $a['order'] == $b['order'] ) { return 0; } return ( $a['order'] < $b['order'] ? -1 : 1 ); } /** * Sort from the longest to the shortest * * @param $a * @param $b * * @return int */ public static function sortFromLongest( $a, $b ) { $la = mb_strlen( $a ); $lb = mb_strlen( $b ); if ( $la == $lb ) { return strcmp( $b, $a ); } return $lb - $la; } /** * Get taxonomy parents * * @param int $term_id * @param string $taxonomy * * @return string */ public static function getTermBreadcrumbs( $termID, $taxonomy, $visited = array(), $lang = '', $exclude = array() ) { $chain = ''; $separator = ' > '; if ( Multilingual::isMultilingual() ) { $parent = Multilingual::getTerm( $termID, $taxonomy, $lang ); } else { $parent = get_term( $termID, $taxonomy ); } if ( empty($parent) || !isset( $parent->name ) ) { return ''; } $name = $parent->name; if ( $parent->parent && $parent->parent != $parent->term_id && !in_array( $parent->parent, $visited ) ) { $visited[] = $parent->parent; $chain .= self::getTermBreadcrumbs( $parent->parent, $taxonomy, $visited, $lang ); } if ( !in_array( $parent->term_id, $exclude ) ) { $chain .= $name . $separator; } return $chain; } /** * Get taxonomies of products attributes * * @return array * */ public static function getAttributesTaxonomies() { $taxonomies = array(); $attributeTaxonomies = wc_get_attribute_taxonomies(); if ( !empty($attributeTaxonomies) ) { foreach ( $attributeTaxonomies as $taxonomy ) { $taxonomies[] = 'pa_' . $taxonomy->attribute_name; } } return apply_filters( 'dgwt/wcas/attribute_taxonomies', $taxonomies ); } /** * */ public static function canInstallPremium() { } /** * Get indexer demo HTML * * @return string */ public static function indexerDemoHtml() { $html = ''; ob_start(); include DGWT_WCAS_DIR . 'partials/admin/indexer-header-demo.php'; $html .= ob_get_clean(); return $html; } /** * Get features HTML * * @return string */ public static function featuresHtml() { $html = ''; ob_start(); include DGWT_WCAS_DIR . 'partials/admin/features.php'; $html .= ob_get_clean(); return $html; } /** * Get searchable custom fields keys * * @return array */ public static function getSearchableCustomFields() { global $wpdb ; $customFields = array(); $excludedMetaKeys = array( '_sku', '_wp_old_date', '_tax_status', '_stock_status', '_product_version', '_smooth_slider_style', 'auctioninc_calc_method', 'auctioninc_pack_method', '_thumbnail_id', '_product_image_gallery', 'pdf_download', 'slide_template', 'cad_iframe', 'downloads', 'edrawings_file', '3d_pdf_download', '3d_pdf_render', '_original_id' ); $excludedMetaKeys = apply_filters( 'dgwt/wcas/indexer/excluded_meta_keys', $excludedMetaKeys ); $sql = "SELECT DISTINCT meta_key\n FROM {$wpdb->postmeta} as pm\n INNER JOIN {$wpdb->posts} as p ON p.ID = pm.post_id\n WHERE p.post_type = 'product'\n AND pm.meta_value NOT LIKE 'field_%'\n AND pm.meta_value NOT LIKE 'a:%'\n AND pm.meta_value NOT LIKE '%\\%\\%%'\n AND pm.meta_value NOT LIKE '_oembed_%'\n AND pm.meta_value NOT REGEXP '^1[0-9]{9}'\n AND pm.meta_value NOT IN ('1','0','-1','no','yes','[]', '')\n "; $metaKeys = $wpdb->get_col( $sql ); if ( !empty($metaKeys) ) { foreach ( $metaKeys as $metaKey ) { if ( !in_array( $metaKey, $excludedMetaKeys ) && self::keyIsValid( $metaKey ) ) { $label = $metaKey; //@TODO Recognize labels based on meta key or public known as Yoast SEO etc. $customFields[] = array( 'label' => $label, 'key' => $label, ); } } } $customFields = array_reverse( $customFields ); return apply_filters( 'dgwt/wcas/indexer/searchable_custom_fields', $customFields ); } /** * Check if key is valid * * @param $key * * @return bool */ public static function keyIsValid( $key ) { return !preg_match( '/[^\\p{L}\\p{N}\\:\\.\\_\\s\\-]+/u', $key ); } /** * Check if table exist * * @return bool */ public static function isTableExists( $tableName ) { global $wpdb ; $exist = false; $wpdb->hide_errors(); if ( empty($tableName) ) { return false; } $sql = $wpdb->prepare( "SHOW TABLES LIKE %s", $wpdb->prefix . 'dgwt_wcas_%' ); $result = $wpdb->get_col( $sql ); if ( is_array( $result ) && in_array( $tableName, $result ) ) { $exist = true; } return $exist; } /** * Check if the engine can search in variable products * * @return bool */ public static function canSearchInVariableProducts() { global $wpdb ; $allow = false; $el = $wpdb->get_var( "SELECT ID FROM {$wpdb->posts} WHERE post_type = 'product_variation' LIMIT 1" ); if ( !empty($el) && is_numeric( $el ) ) { $allow = true; } if ( DGWT_WCAS()->settings->getOption( 'search_in_product_content' ) !== 'on' ) { $allow = false; } return apply_filters( 'dgwt/wcas/search_in_variable_products', $allow ); } /** * Allow to remove method for an hook when, it's a class method used and class don't have variable, but you know the class name * * @link https://github.com/herewithme/wp-filters-extras * @return bool */ public static function removeFiltersForAnonymousClass( $hook_name = '', $class_name = '', $method_name = '', $priority = 0 ) { global $wp_filter ; // Take only filters on right hook name and priority if ( !isset( $wp_filter[$hook_name][$priority] ) || !is_array( $wp_filter[$hook_name][$priority] ) ) { return false; } // Loop on filters registered foreach ( (array) $wp_filter[$hook_name][$priority] as $unique_id => $filter_array ) { // Test if filter is an array ! (always for class/method) if ( isset( $filter_array['function'] ) && is_array( $filter_array['function'] ) ) { // Test if object is a class, class and method is equal to param ! if ( is_object( $filter_array['function'][0] ) && get_class( $filter_array['function'][0] ) && get_class( $filter_array['function'][0] ) == $class_name && $filter_array['function'][1] == $method_name ) { // Test for WordPress >= 4.7 WP_Hook class (https://make.wordpress.org/core/2016/09/08/wp_hook-next-generation-actions-and-filters/) if ( is_a( $wp_filter[$hook_name], 'WP_Hook' ) ) { unset( $wp_filter[$hook_name]->callbacks[$priority][$unique_id] ); } else { unset( $wp_filter[$hook_name][$priority][$unique_id] ); } } } } return false; } /** * Create tooltip * * @param string $id * @param string $content * @param string $template * @param string $placement * @param string $class * * @return string */ public static function createTooltip( $id, $content = '', $template = '', $placement = 'right', $class = '' ) { if ( !empty($template) ) { $file = DGWT_WCAS_DIR . 'partials/admin/tooltips/' . $template . '.php'; if ( file_exists( $file ) ) { ob_start(); require $file; $content = ob_get_contents(); ob_end_clean(); } } $id = 'js-dgwt-wcas-tooltip-id' . sanitize_key( $id ); $html = '
'; $html .= ''; return $html; } /** * Create HTML override option tooltip * * @param string $id * @param string $content * @param string $template * @param string $placement * * @return string */ public static function getOverrideOptionText( $theme ) { $linkToShortcodesDoc = 'https://fibosearch.com/documentation/get-started/how-to-add-fibosearch-to-your-website/#add-fibosearch-with-a-shortcode'; $content = '

' . sprintf( __( 'This option is overridden by the seamless integration with the %s theme. If you want to change the value of this option, disable the integration in
WooCommerce -> FiboSearch -> Starting (tab).', 'ajax-search-for-woocommerce' ), $theme ) . '

'; $content .= '

' . sprintf( __( 'Furthermore, you can override this option for a specific search bar via shortcode params. Learn more about shortcodes parameters.', 'ajax-search-for-woocommerce' ), $linkToShortcodesDoc ) . '

'; return $content; } /** * Create HTML question mark with tooltip * * @param string $id * @param string $content * @param string $template * @param string $placement * * @return string */ public static function createQuestionMark( $id, $content = '', $template = '', $placement = 'right' ) { return self::createTooltip( $id, $content, $template, $placement, 'dashicons dashicons-editor-help dgwt-wcas-questio-mark' ); } /** * Create HTML option override tooltip * * @param string $id * @param string $content * @param string $template * @param string $placement * * @return string */ public static function createOverrideTooltip( $id, $content = '', $template = '', $placement = 'right' ) { return self::createTooltip( $id, $content, $template, $placement, 'dashicons dashicons-lock dgwt-wcas-override-tooltip' ); } /** * Get list of 24 hours */ public static function getHours() { $hours = array(); $cycle12 = ( get_option( 'time_format' ) === 'H:i' ? false : true ); for ( $i = 0 ; $i < 24 ; $i++ ) { $label = ( $cycle12 ? $i . ':00 am' : $i . ':00' ); if ( $cycle12 && $i === 0 ) { $label = 12 . ':00 am'; } if ( $cycle12 && $i > 11 ) { if ( $i === 12 ) { $label = 12 . ':00 pm'; } else { $label = $i - 12 . ':00 pm'; } } $hours[$i] = $label; } return $hours; } /** * Get local date including timezone * * @param $timestamp * @param string $format * * @return string * @throws \Exception */ public static function localDate( $timestamp, $format = '' ) { if ( empty($timestamp) ) { return ''; } if ( empty($format) ) { $format = get_option( 'date_format' ) . ' ' . get_option( 'time_format' ); } $date = new \WC_DateTime( "@{$timestamp}" ); $date->setTimezone( new \DateTimeZone( wc_timezone_string() ) ); return $date->date_i18n( $format ); } /** * Get labels * * @return array */ public static function getLabels() { return apply_filters( 'dgwt/wcas/labels', array( 'post' => __( 'Post' ), 'page' => __( 'Page' ), 'vendor' => __( 'Vendor', 'ajax-search-for-woocommerce' ), 'product_plu' => __( 'Products', 'woocommerce' ), 'post_plu' => __( 'Posts' ), 'page_plu' => __( 'Pages' ), 'vendor_plu' => __( 'Vendors', 'ajax-search-for-woocommerce' ), 'sku_label' => __( 'SKU', 'woocommerce' ) . ':', 'sale_badge' => __( 'Sale', 'woocommerce' ), 'vendor_sold_by' => __( 'Sold by:', 'ajax-search-for-woocommerce' ), 'featured_badge' => __( 'Featured', 'woocommerce' ), 'in' => _x( 'in', 'in categories fe. in Books > Crime stories', 'ajax-search-for-woocommerce' ), 'read_more' => __( 'continue reading', 'ajax-search-for-woocommerce' ), 'no_results' => DGWT_WCAS()->settings->getOption( 'search_no_results_text', __( 'No results', 'ajax-search-for-woocommerce' ) ), 'show_more' => DGWT_WCAS()->settings->getOption( 'search_see_all_results_text', __( 'See all products...', 'ajax-search-for-woocommerce' ) ), 'show_more_details' => DGWT_WCAS()->settings->getOption( 'search_see_all_results_text', __( 'See all products...', 'ajax-search-for-woocommerce' ) ), 'search_placeholder' => DGWT_WCAS()->settings->getOption( 'search_placeholder', __( 'Search for products...', 'ajax-search-for-woocommerce' ) ), 'submit' => DGWT_WCAS()->settings->getOption( 'search_submit_text', '' ), ) ); } /** * Get labels * * @param string $key * * @return string */ public static function getLabel( $key ) { $label = ''; $labels = self::getLabels(); if ( array_key_exists( $key, $labels ) ) { $label = $labels[$key]; } return $label; } /** * Remove all HTML tags including