Plugin Directory

Changeset 3453117


Ignore:
Timestamp:
02/03/2026 05:26:51 PM (2 months ago)
Author:
bhimpfen
Message:

Release 1.1.0

Location:
better-wp-search/trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • better-wp-search/trunk/better-wp-search.php

    r1347902 r3453117  
    11<?php
    2 /*                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              /*
     2/**
    33 * Plugin Name:       Better WP Search
    4  * Plugin URI:        http://www.himpfen.com/better-wp-search/
    5  * Description:       Better WP Search improves the default WordPress search functionality.
    6  * Version:           1.0.0
     4 * Plugin URI:        https://www.himpfen.com/better-wp-search/
     5 * Description:       Improves default WordPress search by redirecting single-result searches and canonicalizing search URLs.
     6 * Version:           1.1.0
    77 * Author:            Brandon Himpfen
    8  * Author URI:        http://www.himpfen.com/
     8 * Author URI:        https://www.himpfen.com/
    99 * License:           GPL-2.0+
    10  * License URI:       http://www.gnu.org/licenses/gpl-2.0.txt
     10 * License URI:       https://www.gnu.org/licenses/gpl-2.0.txt
     11 * Text Domain:       better-wp-search
    1112 */
    1213
    13 // If there is only one search result, redirect to that post
    14 function bws_redirect_single_search() {
    15   if (is_search() && is_main_query()) {
    16       global $wp_query;
    17       if ($wp_query->post_count == 1 && $wp_query->max_num_pages == 1) {
    18           wp_redirect( get_permalink( $wp_query->posts['0']->ID ) );
    19           exit;
    20       }
    21   }
     14if ( ! defined( 'ABSPATH' ) ) {
     15    exit;
    2216}
    23 add_action('template_redirect', 'bws_redirect_single_search' );
    24 
    25 // Nice Search
    26 // Replaes /?s=query searches to /search/query and converts %20 to +
    27 // Originally created by Mark Jaquith
    28 // Plugin URI: https://wordpress.org/plugins/nice-search/
    29 function bws_nice_search() {
    30     global $wp_rewrite;
    31     if ( !isset( $wp_rewrite ) || !is_object( $wp_rewrite ) || !$wp_rewrite->using_permalinks() )
    32         return;
    33 
    34     $search_base = $wp_rewrite->search_base;
    35     if ( is_search() && !is_admin() && strpos( $_SERVER['REQUEST_URI'], "/{$search_base}/" ) === false ) {
    36         wp_redirect( home_url( "/{$search_base}/" . urlencode( get_query_var( 's' ) ) ) );
    37         exit();
     17
     18final class Better_WP_Search {
     19
     20    /** @var Better_WP_Search|null */
     21    private static $instance = null;
     22
     23    /**
     24     * Boot the plugin.
     25     *
     26     * @return Better_WP_Search
     27     */
     28    public static function instance() {
     29        if ( null === self::$instance ) {
     30            self::$instance = new self();
     31        }
     32        return self::$instance;
     33    }
     34
     35    private function __construct() {
     36        add_action( 'template_redirect', array( $this, 'maybe_redirect_single_result' ) );
     37        add_action( 'template_redirect', array( $this, 'maybe_redirect_pretty_search' ) );
     38    }
     39
     40    /**
     41     * Common guards: avoid redirects in contexts where they are undesirable.
     42     *
     43     * @return bool True if redirects are allowed for this request.
     44     */
     45    private function redirects_allowed() {
     46        if ( is_admin() ) {
     47            return false;
     48        }
     49
     50        if ( function_exists( 'wp_doing_ajax' ) && wp_doing_ajax() ) {
     51            return false;
     52        }
     53
     54        if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) {
     55            return false;
     56        }
     57
     58        if ( defined( 'WP_CLI' ) && WP_CLI ) {
     59            return false;
     60        }
     61
     62        if ( is_feed() || is_preview() ) {
     63            return false;
     64        }
     65
     66        /**
     67         * Filter whether Better WP Search is allowed to redirect on this request.
     68         *
     69         * @param bool $allowed
     70         */
     71        return (bool) apply_filters( 'bws_redirects_allowed', true );
     72    }
     73
     74    /**
     75     * If there is only one search result, redirect to that post.
     76     */
     77    public function maybe_redirect_single_result() {
     78        if ( ! $this->redirects_allowed() ) {
     79            return;
     80        }
     81
     82        if ( ! is_search() || ! is_main_query() ) {
     83            return;
     84        }
     85
     86        /**
     87         * Filter whether single-result redirects are enabled.
     88         *
     89         * @param bool $enabled
     90         */
     91        $enabled = (bool) apply_filters( 'bws_single_result_redirect_enabled', true );
     92        if ( ! $enabled ) {
     93            return;
     94        }
     95
     96        global $wp_query;
     97
     98        if ( ! isset( $wp_query ) || ! is_object( $wp_query ) ) {
     99            return;
     100        }
     101
     102        if ( (int) $wp_query->post_count !== 1 || (int) $wp_query->max_num_pages !== 1 ) {
     103            return;
     104        }
     105
     106        if ( empty( $wp_query->posts ) || ! isset( $wp_query->posts[0] ) || ! is_object( $wp_query->posts[0] ) ) {
     107            return;
     108        }
     109
     110        $post_id = (int) $wp_query->posts[0]->ID;
     111        if ( $post_id <= 0 ) {
     112            return;
     113        }
     114
     115        $url = get_permalink( $post_id );
     116        if ( ! $url ) {
     117            return;
     118        }
     119
     120        /**
     121         * Filter the destination URL for single-result redirects.
     122         *
     123         * @param string $url
     124         * @param int    $post_id
     125         */
     126        $url = (string) apply_filters( 'bws_single_result_redirect_url', $url, $post_id );
     127
     128        /**
     129         * Filter the HTTP status code used for single-result redirects.
     130         *
     131         * @param int $status Default 302.
     132         */
     133        $status = (int) apply_filters( 'bws_single_result_redirect_status', 302 );
     134
     135        wp_safe_redirect( esc_url_raw( $url ), $status );
     136        exit;
     137    }
     138
     139    /**
     140     * Canonicalize search URLs from /?s=query to /search/query when permalinks are enabled.
     141     *
     142     * Inspired by the historical "Nice Search" approach.
     143     */
     144    public function maybe_redirect_pretty_search() {
     145        if ( ! $this->redirects_allowed() ) {
     146            return;
     147        }
     148
     149        if ( ! is_search() || ! is_main_query() ) {
     150            return;
     151        }
     152
     153        /**
     154         * Filter whether pretty search redirects are enabled.
     155         *
     156         * @param bool $enabled
     157         */
     158        $enabled = (bool) apply_filters( 'bws_pretty_search_enabled', true );
     159        if ( ! $enabled ) {
     160            return;
     161        }
     162
     163        $search_term = get_query_var( 's' );
     164        if ( ! is_string( $search_term ) || '' === trim( $search_term ) ) {
     165            return;
     166        }
     167
     168        global $wp_rewrite;
     169        if ( ! isset( $wp_rewrite ) || ! is_object( $wp_rewrite ) || ! $wp_rewrite->using_permalinks() ) {
     170            return;
     171        }
     172
     173        $search_base = isset( $wp_rewrite->search_base ) && $wp_rewrite->search_base ? $wp_rewrite->search_base : 'search';
     174
     175        // If already on /search/... do nothing.
     176        $request_uri = isset( $_SERVER['REQUEST_URI'] ) ? (string) $_SERVER['REQUEST_URI'] : '';
     177        $path        = wp_parse_url( $request_uri, PHP_URL_PATH );
     178        $path        = is_string( $path ) ? $path : '';
     179
     180        // Normalize: ensure single leading slash and compare.
     181        $needle = '/' . trim( $search_base, '/' ) . '/';
     182        if ( false !== strpos( $path, $needle ) ) {
     183            return;
     184        }
     185
     186        $pretty = home_url( user_trailingslashit( $search_base . '/' . rawurlencode( $search_term ) ) );
     187
     188        /**
     189         * Filter the pretty search redirect URL.
     190         *
     191         * @param string $pretty
     192         * @param string $search_term
     193         * @param string $search_base
     194         */
     195        $pretty = (string) apply_filters( 'bws_pretty_search_url', $pretty, $search_term, $search_base );
     196
     197        /**
     198         * Filter the HTTP status code used for pretty search redirects.
     199         *
     200         * @param int $status Default 301.
     201         */
     202        $status = (int) apply_filters( 'bws_pretty_search_status', 301 );
     203
     204        wp_safe_redirect( esc_url_raw( $pretty ), $status );
     205        exit;
    38206    }
    39207}
    40208
    41 add_action( 'template_redirect', 'bws_nice_search' );
    42 
    43 // Hotfix for http://core.trac.wordpress.org/ticket/13961 for WP versions less than 3.5
    44 if ( version_compare( $wp_version, '3.5', '<=' ) ) {
    45     function bws_nice_search_urldecode_hotfix( $q ) {
    46         if ( $q->get( 's' ) && empty( $_GET['s'] ) && is_main_query() )
    47             $q->set( 's', urldecode( $q->get( 's' ) ) );
    48     }
    49     add_action( 'pre_get_posts', 'bws_nice_search_urldecode_hotfix' );
    50 }
     209Better_WP_Search::instance();
  • better-wp-search/trunk/readme.txt

    r2095343 r3453117  
    55Requires at least: 3.5.0
    66Tested up to: 5.2.1
    7 Stable tag: 5.2
     7Stable tag: 1.1.0
    88License: GPLv2 or later
    99License URI: http://www.gnu.org/licenses/gpl-2.0.html
     
    3535== Changelog ==
    3636
     37= 1.1.0 =
     38* Refactor to a class-based structure.
     39* Use wp_safe_redirect() and add safety guards.
     40* Add filters for enabling/disabling and customizing redirect URLs/status codes.
     41
    3742= 1.0.0 =
    3843* Initial commit of files.
Note: See TracChangeset for help on using the changeset viewer.