HEX
Server: Apache
System: Linux vps.teamads.com 4.18.0-553.126.1.el8_10.x86_64 #1 SMP Thu May 28 06:44:09 EDT 2026 x86_64
User: teamadsc (1024)
PHP: 8.1.34
Disabled: NONE
Upload Files
File: /home/teamadsc/public_html/wp-content/plugins/better-search/includes/main-functions.php
<?php
/**
 * Utlity functions used by Better Search
 *
 * @package Better_Search
 */

// If this file is called directly, then abort execution.
if ( ! defined( 'WPINC' ) ) {
	die( "Aren't you supposed to come here via WP-Admin?" );
}

/**
 * Gets the search results.
 *
 * @since   1.2
 *
 * @param   string     $search_query    Search term.
 * @param   int|string $limit           Maximum number of search results.
 * @return  string     Search results
 */
function get_bsearch_results( $search_query = '', $limit = '' ) {
	global $bsearch_error;

	if ( ! ( $limit ) ) {
		$limit = isset( $_GET['limit'] ) ? intval( $_GET['limit'] ) : bsearch_get_option( 'limit' ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
	}

	// Order by date or by score?
	$bydate = isset( $_GET['bydate'] ) ? intval( $_GET['bydate'] ) : 0; // phpcs:ignore WordPress.Security.NonceVerification.Recommended

	$topscore = 0;

	$matches  = get_bsearch_matches( $search_query, $bydate );   // Fetch the search results for the search term stored in $search_query.
	$searches = $matches[0];    // 0 index contains the search results always.

	if ( $searches ) {
		$topscore = max( wp_list_pluck( (array) $searches, 'score' ) );
		$numrows  = count( $searches );
	} else {
		$numrows = 1;
	}

	$match_range = get_bsearch_range( $numrows, $limit );
	$searches    = array_slice( $searches, $match_range[0], $match_range[1] - $match_range[0] + 1 );   // Extract the elements for the page from the complete results array.

	$output = '';

	/* Lets start printing the results */
	if ( '' != $search_query ) { //phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
		if ( $searches ) {
			$output .= get_bsearch_header( $search_query, $numrows, $limit );

			$search_query = preg_quote( $search_query, '/' );
			$keys         = explode( ' ', str_replace( array( "'", '"', '&quot;', '\+', '\-' ), '', $search_query ) );

			foreach ( $searches as $search ) {
				$score      = $search->score;
				$search     = get_post( $search->ID );
				$post_title = get_the_title( $search->ID );

				/* Highlight the search terms in the title */
				if ( bsearch_get_option( 'highlight' ) ) {
					$post_title = bsearch_highlight( $post_title, $keys );
				}

				$output .= '<article id="post-' . $search->ID . '" ';
				$output .= 'class="' . join( ' ', get_post_class( 'bsearch-post', $search->ID ) ) . '"';
				$output .= '>';

				$output .= '<header class="bsearch-entry-header">';

				$output .= sprintf( '<h2 class="bsearch-entry-title"><a href="%1$s" rel="bookmark">%2$s</a></h2>', esc_url( get_permalink( $search->ID ) ), $post_title );

				$output .= sprintf( '<p><span class="bsearch_score">%1$s</span> &nbsp;&nbsp;&nbsp;&nbsp; <span class="bsearch_date">%2$s</span></p>', get_bsearch_score( $search, $score, $topscore ), get_bsearch_date( $search, __( 'Posted on: ', 'better-search' ) ) );

				$output .= '</header>';

				$output .= '<div class="bsearch-entry-content">';

				if ( bsearch_get_option( 'include_thumb' ) ) {
					list( $thumb_width, $thumb_height ) = bsearch_get_thumb_size( 'thumbnail' );

					$output .= '<p class="bsearch_thumb_wrapper">';
					$output .= bsearch_get_the_post_thumbnail(
						array(
							'postid'       => $search,
							'thumb_height' => $thumb_height,
							'thumb_width'  => $thumb_width,
						)
					);
					$output .= '</p>';
				}

				$excerpt = get_bsearch_excerpt( $search->ID, bsearch_get_option( 'excerpt_length' ) );

				/* Highlight the search terms in the excerpt */
				if ( bsearch_get_option( 'highlight' ) ) {
					$excerpt = bsearch_highlight( $excerpt, $keys );
				}

				$output .= sprintf( '<p class="bsearch_excerpt">%1$s</p>', $excerpt );

				$output .= '</div>';
				$output .= '</article>';
			} //end of foreach loop

			$output .= get_bsearch_footer( $search_query, $numrows, $limit );

		} else {
			$output .= '<p>';
			$output .= __( 'No results.', 'better-search' );
			$output .= '</p>';
		}
	} else {
		$output .= '<p>';
		if ( '' !== $bsearch_error->get_error_message( 'bsearch_banned' ) && bsearch_get_option( 'banned_stop_search' ) ) {
			foreach ( $bsearch_error->get_error_messages() as $error ) {
				$output .= $error . '<br/>';
			}
		} else {
			$output .= __( 'Please type in your search terms. Use descriptive words since this search is intelligent.', 'better-search' );
		}
		$output .= '</p>';
	}

	if ( bsearch_get_option( 'show_credit' ) ) {
		$output .= bsearch_get_credit_link();
	}

	/**
	 * Filter formatted string with search results
	 *
	 * @since   1.2
	 *
	 * @param   string  $output         Formatted results
	 * @param   string  $search_query   Search query
	 * @param   int     $limit          Number of results per page
	 */
	return apply_filters( 'get_bsearch_results', $output, $search_query, $limit );
}


/**
 * Fetch the search query for Better Search.
 *
 * @since   2.0.0
 *
 * @param bool $escaped Whether the result is escaped. Default true.
 *                      Always escape this if you are going to display it.
 * @return  string  Better Search query
 */
function get_bsearch_query( $escaped = true ) {

	$search_query = trim(
		bsearch_clean_terms(
			get_search_query( $escaped )
		)
	);

	/**
	 * Filter search terms string
	 *
	 * @since   2.0.0
	 *
	 * @param   string  $search_query   Search query
	 */
	return apply_filters( 'get_bsearch_query', $search_query );

}


/**
 * Returns an array with the cleaned-up search string at the zero index and possibly a list of terms in the second.
 *
 * @since   1.2
 *
 * @param   mixed $search_query   The search term.
 * @return  array   Cleaned up search string
 */
function get_bsearch_terms( $search_query = '' ) {

	if ( empty( $search_query ) ) {
		$search_query = get_bsearch_query();
	}
	$s_array[0] = $search_query;

	$use_fulltext = bsearch_get_option( 'use_fulltext' );

	/**
		If use_fulltext is false OR if all the words are shorter than four chars, add the array of search terms.
		Currently this will disable match ranking and won't be quote-savvy.
		If we are using fulltext, turn it off unless there's a search word longer than three chars
		ideally we'd also check against stopwords here
	*/
	$search_words = explode( ' ', $search_query );

	if ( $use_fulltext ) {
		$use_fulltext_proxy = false;
		foreach ( $search_words as $search_word ) {
			if ( strlen( $search_word ) > 3 ) {
				$use_fulltext_proxy = true;
			}
		}
		$use_fulltext = $use_fulltext_proxy;
	}

	if ( ! $use_fulltext ) {
		// Strip out all the fancy characters that fulltext would use.
		$search_query = addslashes_gpc( $search_query );
		$search_query = preg_replace( '/, +/', ' ', $search_query );
		$search_query = str_replace( ',', ' ', $search_query );
		$search_query = str_replace( '"', ' ', $search_query );
		$search_query = trim( $search_query );
		$search_words = explode( ' ', $search_query );

		$s_array[0] = $search_query;    // Save original query at [0].
		$s_array[1] = $search_words;    // Save array of terms at [1].
	}

	/**
	 * Filter array holding the search query and terms
	 *
	 * @since   1.2
	 *
	 * @param   array   $s_array    Original query is at [0] and array of terms at [1]
	 */
	return apply_filters( 'get_bsearch_terms', $s_array );
}


/**
 * Get the matches for the search term.
 *
 * @since   1.2
 *
 * @param   string $search_query    Search terms array.
 * @param   bool   $bydate         Sort by date flag.
 * @return  array   Search results
 */
function get_bsearch_matches( $search_query, $bydate ) {
	global $wpdb, $bsearch_error;

	// if there are two items in $search_info, the string has been broken into separate terms that
	// are listed at $search_info[1]. The cleaned-up version of $search_query is still at the zero index.
	// This is when fulltext is disabled, and we search using LIKE.
	$search_info = get_bsearch_terms( $search_query );

	if ( '' !== $bsearch_error->get_error_message( 'bsearch_banned' ) && bsearch_get_option( 'banned_stop_search' ) ) {
		$matches[0]              = array();
		$matches['search_query'] = $search_query;

		return $matches;
	}

	// Get search transient.
	$search_query_transient = 'bs_' . preg_replace( '/[^A-Za-z0-9\-]/', '', str_replace( ' ', '', $search_query ) );

	/**
	 * Filter name of the search transient
	 *
	 * @since   2.1.0
	 *
	 * @param   string  $search_query_transient Transient name
	 * @param   array   $search_query   Search query
	 */
	$search_query_transient = apply_filters( 'bsearch_transient_name', $search_query_transient, $search_query );
	$search_query_transient = substr( $search_query_transient, 0, 40 ); // Name of the transient limited to 40 chars.

	$matches = get_transient( $search_query_transient );

	if ( $matches ) {

		if ( isset( $matches['search_query'] ) ) {

			if ( $matches['search_query'] == $search_query ) { //phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
				$results = $matches[0];

				/**
				 * Filter array holding the search results
				 *
				 * @since   1.2
				 *
				 * @param   object  $matches    Search results object
				 * @param   array   $search_info    Search query
				 */
				return apply_filters( 'get_bsearch_matches', $matches, $search_info );

			}
		}
	}

	$boolean_mode      = bsearch_get_option( 'boolean_mode' );
	$aggressive_search = bsearch_get_option( 'aggressive_search' );

	// If no transient is set.
	if ( ! isset( $results ) ) {
		$sql = bsearch_sql_prepare( $search_info, $boolean_mode, $bydate );

		$results = $wpdb->get_results( $sql ); //phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
	}

	// If no results are found then force BOOLEAN mode only if this isn't ON before.
	if ( ! $results && ! $boolean_mode && $aggressive_search ) {
		$sql = bsearch_sql_prepare( $search_info, 1, $bydate );

		$results = $wpdb->get_results( $sql ); //phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
	}

	// If no results are found then force LIKE mode.
	if ( ! $results && $aggressive_search ) {
		// Strip out all the fancy characters that fulltext would use.
		$search_query = addslashes_gpc( $search_query );
		$search_query = preg_replace( '/, +/', ' ', $search_query );
		$search_query = str_replace( ',', ' ', $search_query );
		$search_query = str_replace( '"', ' ', $search_query );
		$search_query = trim( $search_query );
		$search_words = explode( ' ', $search_query );

		$s_array[0] = $search_query;    // Save original query at [0].
		$s_array[1] = $search_words;    // Save array of terms at [1].

		$search_info = $s_array;

		$sql = bsearch_sql_prepare( $search_info, 0, $bydate );

		$results = $wpdb->get_results( $sql ); //phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
	}

	$matches[0]              = $results;
	$matches['search_query'] = $search_query;

	if ( bsearch_get_option( 'cache' ) ) {
		// Set search transient.
		set_transient( $search_query_transient, $matches, 7200 );
	}

	/**
	 * Described in better-search.php
	 */
	return apply_filters( 'get_bsearch_matches', $matches, $search_info );
}


/**
 * Returns an array with the first and last indices to be displayed on the page.
 *
 * @since   1.2
 *
 * @param   int $numrows    Total results.
 * @param   int $limit      Results per page.
 * @return  array   First and last indices to be displayed on the page
 */
function get_bsearch_range( $numrows, $limit ) {

	if ( ! ( $limit ) ) {
		$limit = isset( $_GET['limit'] ) ? intval( $_GET['limit'] ) : bsearch_get_option( 'limit' ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
	}
	$page = isset( $_GET['bpaged'] ) ? intval( wp_unslash( $_GET['bpaged'] ) ) : 0; // phpcs:ignore WordPress.Security.NonceVerification.Recommended

	$last = min( $page + $limit - 1, $numrows - 1 );

	$match_range = array( $page, $last );

	/**
	 * Filter array with the first and last indices to be displayed on the page.
	 *
	 * @since   1.3
	 *
	 * @param   array   $match_range    First and last indices to be displayed on the page
	 * @param   int     $numrows        Total results
	 * @param   int     $limit          Results per page
	 */
	return apply_filters( 'get_bsearch_range', $match_range, $numrows, $limit );
}