'}`
'#([\\{,])([\'])(\\d+|[a-z_]\\w*)\\2(?=\\:)#i',
// --ibid. From `foo['bar']` to `foo.bar`
'#([\\w\\)\\]])\\[([\'"])([a-z_]\\w*)\\2\\]#i',
// Replace `true` with `!0`
'#(?<=return |[=:,\\(\\[])true\\b#',
// Replace `false` with `!1`
'#(?<=return |[=:,\\(\\[])false\\b#',
// Clean up ...
'#\\s*(\\/\\*|\\*\\/)\\s*#',
), array(
'$1',
'$1$2',
'}',
'$1$3',
'$1.$3',
'!0',
'!1',
'$1'
), $input );
}
/**
* Minify CSS
*
* @see https://gist.github.com/tovic/d7b310dea3b33e4732c0
*
* @param string
*
* @return string
*/
public static function minifyCSS( $input ) {
if ( trim( $input ) === "" ) {
return $input;
}
// Force white-space(s) in `calc()`
if ( strpos( $input, 'calc(' ) !== false ) {
$input = preg_replace_callback( '#(?<=[\\s:])calc\\(\\s*(.*?)\\s*\\)#', function ( $matches ) {
return 'calc(' . preg_replace( '#\\s+#', "\x1a", $matches[1] ) . ')';
}, $input );
}
return preg_replace( array(
// Remove comment(s)
'#("(?:[^"\\\\]++|\\\\.)*+"|\'(?:[^\'\\\\]++|\\\\.)*+\')|\\/\\*(?!\\!)(?>.*?\\*\\/)|^\\s*|\\s*$#s',
// Remove unused white-space(s)
'#("(?:[^"\\\\]++|\\\\.)*+"|\'(?:[^\'\\\\]++|\\\\.)*+\'|\\/\\*(?>.*?\\*\\/))|\\s*+;\\s*+(})\\s*+|\\s*+([*$~^|]?+=|[{};,>~+]|\\s*+-(?![0-9\\.])|!important\\b)\\s*+|([[(:])\\s++|\\s++([])])|\\s++(:)\\s*+(?!(?>[^{}"\']++|"(?:[^"\\\\]++|\\\\.)*+"|\'(?:[^\'\\\\]++|\\\\.)*+\')*+{)|^\\s++|\\s++\\z|(\\s)\\s+#si',
// Replace `0(cm|em|ex|in|mm|pc|pt|px|vh|vw|%)` with `0`
'#(?<=[\\s:])(0)(cm|em|ex|in|mm|pc|pt|px|vh|vw|%)#si',
// Replace `:0 0 0 0` with `:0`
'#:(0\\s+0|0\\s+0\\s+0\\s+0)(?=[;\\}]|\\!important)#i',
// Replace `background-position:0` with `background-position:0 0`
'#(background-position):0(?=[;\\}])#si',
// Replace `0.6` with `.6`, but only when preceded by a white-space or `=`, `:`, `,`, `(`, `-`
'#(?<=[\\s=:,\\(\\-]|&\\#32;)0+\\.(\\d+)#s',
// Minify string value
'#(\\/\\*(?>.*?\\*\\/))|(?.*?\\*\\/))|(\\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 = '';
}
$html .= '
';
break;
case 'option-label':
$html .= '' . $label . '' . __( 'Pro', 'ajax-search-for-woocommerce' ) . '
';
break;
}
return $html;
}
/**
* Calc score for searched.
*
* @param string $phrase Search phrase (user input).
* @param string $haystack eg. product title, SKU, attribute name etc.
* @param array $args Args that can wide or narrow comparison scope or change the score weight.
*
* @return float
*/
public static function calcScore( string $phrase, string $haystack, array $args = array() ) : float {
$score = 0;
if ( empty( $phrase ) || empty( $haystack ) ) {
return $score;
}
// Don't apply score for a search phrase with a single character
if ( strlen( $phrase ) <= 1 ) {
return $score;
}
$default = array(
'check_similarity' => true,
'check_position' => true,
'score_containing' => 50,
);
$args = array_merge( $default, $args );
$phrase = self::normalizePhrase( $phrase );
$haystack = self::normalizePhrase( $haystack );
/* -------------------------------------- *
* Bonus for comparing the entire phrase *
* -------------------------------------- */
$score += self::allocateScore( self::stringComparisonResult( $phrase, $haystack, $args ) );
/* ------------------------------------ *
* Bonus for comparing individual words *
* ------------------------------------ */
$words = explode( ' ', $phrase );
if ( count( $words ) > 1 ) {
$args['check_similarity'] = false;
foreach ( $words as $word ) {
$score += self::allocateScore( self::stringComparisonResult( $word, $haystack, $args ) ) / 3;
}
}
return $score;
}
/**
* Removes multiple whitespaces,
* strips whitespace (or other characters) from the beginning and end of a string
* and makes a string lowercase.
*
* @param string $phrase The phrase to normalize.
*
* @return string
*/
public static function normalizePhrase( string $phrase ) : string {
return mb_strtolower( trim( preg_replace( array('/\\s{2,}/', '/[\\t\\n]/'), ' ', $phrase ) ) );
}
/**
* Compare two strings and set data necessary to calculate score.
*
* @param string $haystack The string to search in.
* @param string $needle The string need to be found.
* @param array $args Args that can wide or narrow comparison scope or change the score weight.
*
* @return array
*/
public static function stringComparisonResult( string $needle = '', string $haystack = '', array $args = array() ) : array {
$results = array(
'exact_match' => false,
'partial_exact_match' => false,
'containing' => false,
'containing_pos' => 0,
'text_similarity' => 0,
);
$default = array(
'check_similarity' => true,
'check_position' => true,
'score_containing' => 50,
);
$args = array_merge( $default, $args );
$pos = strpos( $haystack, $needle );
if ( $pos !== false ) {
$results['containing'] = true;
if ( $haystack === $needle ) {
$results['exact_match'] = true;
} elseif ( strpos( $haystack, ' ' ) !== false ) {
$needleRegex = self::escPhraseForRegex( $needle );
if ( preg_match( '/\\b' . $needleRegex . '\\b/i', $haystack ) ) {
$results['partial_exact_match'] = true;
}
if ( $args['check_position'] ) {
$results['containing_pos'] = self::stringPosition( $pos, $haystack );
}
}
}
if ( $args['check_similarity'] && strlen( $needle ) > 1 ) {
$m = similar_text( $needle, $haystack, $percent );
$results['text_similarity'] = $percent;
}
return $results;
}
/**
* Allocate score. Take resutls of the comarison and calculate the final score.
*
* @param array $comparison Data after comparing two string.
* @param array $args Values and weights that are required to calculate score.
*
* @return float
*/
public static function allocateScore( array $comparison, array $args = array() ) : float {
$score = 0;
$default = [
'containing_score' => 50,
'exact_match_multiplier' => 5,
'partial_exact_match_multiplier' => 2,
'text_similarity_divisor' => 3,
'containing_position_divisor' => 2,
];
$args = apply_filters( 'dgwt/wcas/score_weights', array_merge( $default, $args ) );
if ( $comparison['text_similarity'] > 0 ) {
$score = $comparison['text_similarity'] / $args['text_similarity_divisor'];
}
// Add score based on substring position.
if ( $comparison['containing'] ) {
$score += $args['containing_score'];
// Bonus for contained substring.
// Bonus for exact match of the phrase to the text.
if ( $comparison['exact_match'] ) {
$score += $args['containing_score'] * $args['exact_match_multiplier'];
}
// Bonus for exact match of the phrase to the part of text.
if ( $comparison['partial_exact_match'] ) {
$score += $args['containing_score'] * $args['partial_exact_match_multiplier'];
}
// Bonus for substring position.
if ( $comparison['containing_pos'] > 0 ) {
$score += $comparison['containing_pos'] / $args['containing_position_divisor'];
}
}
return $score;
}
/**
* Check position of the substring relative to the whole string.
*
* @param int $position The result of the substr function.
* @param string $haystack The string to search in.
*
* @return float
*/
public static function stringPosition( int $position, string $haystack ) : float {
return 100 - $position * 100 / strlen( $haystack );
}
/**
* 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() {
$noResults = DGWT_WCAS()->settings->getOption( 'search_no_results_text', __( 'No results', 'ajax-search-for-woocommerce' ) );
$noResults = json_encode( Helpers::ksesNoResults( $noResults ), JSON_UNESCAPED_SLASHES );
$showMore = esc_html( DGWT_WCAS()->settings->getOption( 'search_see_all_results_text', __( 'See all products...', 'ajax-search-for-woocommerce' ) ) );
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' => $noResults,
'no_results_default' => __( 'No results', 'ajax-search-for-woocommerce' ),
'show_more' => $showMore,
'show_more_details' => $showMore,
'search_placeholder' => DGWT_WCAS()->settings->getOption( 'search_placeholder', __( 'Search for products...', 'ajax-search-for-woocommerce' ) ),
'submit' => DGWT_WCAS()->settings->getOption( 'search_submit_text', '' ),
'search_hist' => __( 'Your search history', 'ajax-search-for-woocommerce' ),
'search_hist_clear' => __( 'Clear', 'ajax-search-for-woocommerce' ),
) );
}
/**
* 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