Plugin Directory

Changeset 3449426


Ignore:
Timestamp:
01/29/2026 09:56:56 AM (6 weeks ago)
Author:
codeandcore
Message:

Search functionality now integrated directly into the main WordPress search box

Location:
slug-search-and-admin-columns
Files:
25 added
6 edited

Legend:

Unmodified
Added
Removed
  • slug-search-and-admin-columns/trunk/admin/templates/settings-page.php

    r3425226 r3449426  
    128128
    129129        <!-- Search -->
    130         <div class="ssac-section-card">
    131             <div class="ssac-section-card-header">
    132                 <h2><?php esc_html_e('Search Settings', 'slug-search-and-admin-columns'); ?></h2>
    133                 <p class="description">
    134                     <?php esc_html_e('Choose how to search for posts.', 'slug-search-and-admin-columns'); ?>
    135                 </p>
    136             </div>
    137 
    138             <div class="ssac-field-row-parent">
    139                 <div class="ssac-field-row">
    140                     <div class="ssac-field-label">
    141                         <?php esc_html_e('Search Mode', 'slug-search-and-admin-columns'); ?>
    142                         <span class="ssac-help-icon" data-tooltip="<?php esc_attr_e('Exact matches the whole slug; Partial searches anywhere within the slug (useful for fragments).', 'slug-search-and-admin-columns'); ?>">
    143                                 <span class="dashicons dashicons-editor-help"></span>
    144                             </span>
    145                     </div>
    146                     <div class="ssac-field-control ssac-radio-group">
    147                         <label>
    148                             <input type="radio" name="ssac_settings[search_mode]" value="exact" <?php checked($ssac_settings['search_mode'], 'exact'); ?> />
    149                             <span><?php esc_html_e('Exact Match', 'slug-search-and-admin-columns'); ?></span>
    150                         </label>
    151                         <label>
    152                             <input type="radio" name="ssac_settings[search_mode]" value="partial" <?php checked($ssac_settings['search_mode'], 'partial'); ?> />
    153                             <span><?php esc_html_e('Partial Match', 'slug-search-and-admin-columns'); ?></span>
    154                         </label>
    155                     </div>
    156                 </div>
    157                 <div class="ssac-field-row">
    158                     <div class="ssac-field-label">
    159                         <?php esc_html_e('Case Sensitive?', 'slug-search-and-admin-columns'); ?>
    160                         <span class="ssac-help-icon" data-tooltip="<?php esc_attr_e('Treat uppercase and lowercase as different.', 'slug-search-and-admin-columns'); ?>">
    161                                 <span class="dashicons dashicons-editor-help"></span>
    162                             </span>
    163                     </div>
    164                     <div class="ssac-field-control">
    165                         <label>
    166                             <input type="checkbox" name="ssac_settings[case_sensitive]" value="1" <?php checked($ssac_settings['case_sensitive']); ?> />
    167                             <?php esc_html_e('Treat uppercase and lowercase as different.', 'slug-search-and-admin-columns'); ?>
    168                         </label>
    169                     </div>
    170                 </div>
    171             </div>
    172         </div>
    173 
    174130        <!-- Capability -->
    175131        <div class="ssac-section-card">
  • slug-search-and-admin-columns/trunk/includes/class-ssac-search.php

    r3425226 r3449426  
    2222
    2323    /**
    24      * Partial slug search term
    25      *
    26      * @var string|null
    27      */
    28     private static $partial_slug = null;
    29 
    30     /**
    31      * Active WP_Query instance
    32      *
    33      * @var WP_Query|null
    34      */
    35     private static $active_query = null;
    36 
    37 
    38     /**
    3924     * Initialize the search functionality
    4025     *
    41      * Hooks into WordPress actions to add search field and handle search queries
     26     * Hooks into WordPress actions to integrate slug search into global WP admin search
    4227     *
    4328     * @return void
     
    4530    public static function init()
    4631    {
    47         add_action('restrict_manage_posts', [__CLASS__, 'add_slug_search_field']);
    48         add_action('pre_get_posts', [__CLASS__, 'handle_slug_search']);
     32        add_filter('posts_search', [__CLASS__, 'include_slug_in_search'], 10, 2);
    4933    }
    5034
    5135
    5236    /**
    53      * Add slug search field to admin post list filters
     37     * Include post slug in global WordPress admin search
    5438     *
    55      * Displays a search input field in the post list table filters area
     39     * Modifies the search query to search ONLY in post slugs when users use the
     40     * standard WordPress admin search box
    5641     *
    57      * Security Note: This method does not use nonce verification because it handles
    58      * standard WordPress admin list table filters (like search, category, etc.).
    59      * Per WordPress core conventions, list table filters do not require nonces as they:
    60      * 1. Are only accessible to logged-in users with appropriate capabilities
    61      * 2. Are read-only GET parameters that don't modify data
    62      * 3. Follow the same pattern as WordPress' native filters
     42     * Security Note: This method sanitizes the search term from WordPress core.
     43     * The $search parameter comes from WordPress's native search handling which
     44     * already sanitizes the input. This filter only modifies the WHERE clause
     45     * for read-only query purposes.
    6346     *
    64      * @return void
     47     * @param string   $search The WHERE clause of the search query
     48     * @param WP_Query $query  The WP_Query instance
     49     * @return string Modified WHERE clause for slug-only search
    6550     */
    66     public static function add_slug_search_field()
    67     {
    68         global $typenow;
    69 
    70         $settings = SSAC_Settings::get_settings();
    71 
    72         // Only show on enabled post types
    73         if (!in_array($typenow, $settings['post_types'], true)) {
    74             return;
    75         }
    76 
    77         // Check user capability - only users with the required capability can see this field
    78         if (!current_user_can($settings['capability'])) {
    79             return;
    80         }
    81 
    82         // Lint-safe: Search filters in admin list tables use GET without nonces per WordPress core convention.
    83         // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- core WP convention
    84         $ssac_slug_input = '';
    85 
    86         // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- core WP convention
    87         if (isset($_GET['ssac_slug'])) {
    88             // phpcs:ignore WordPress.Security.NonceVerification.Recommended
    89             $ssac_slug_input = sanitize_text_field(wp_unslash($_GET['ssac_slug']));
    90         }
    91 
    92         // Output search field
    93         printf(
    94             '<input type="text" name="ssac_slug" placeholder="%s" value="%s" />',
    95             esc_attr__('Search by slug…', 'slug-search-and-admin-columns'),
    96             esc_attr($ssac_slug_input)
    97         );
    98     }
    99 
    100 
    101     /**
    102      * Handle slug search query modification
    103      *
    104      * Modifies the main query to search by post slug based on user input
    105      *
    106      * Security Note: This method does not use nonce verification for the following reasons:
    107      * 1. It hooks into 'pre_get_posts' which filters read-only query parameters
    108      * 2. All data is sanitized with sanitize_text_field() and wp_unslash()
    109      * 3. User capability is strictly checked with current_user_can()
    110      * 4. This follows WordPress core conventions for list table filters
    111      * 5. No data is modified based on $_GET input - only query parameters are altered
    112      *
    113      * See WordPress Developer Handbook: List Tables and Security
    114      * https://developer.wordpress.org/plugins/security/nonces/
    115      *
    116      * @param WP_Query $query The WordPress query object
    117      * @return void
    118      */
    119     public static function handle_slug_search($query)
     51    public static function include_slug_in_search($search, $query)
    12052    {
    12153        // Only run in admin on main query
    12254        if (!is_admin() || !$query->is_main_query()) {
    123             return;
     55            return $search;
    12456        }
    12557
     
    13062        // Only run on enabled post types
    13163        if (!in_array($ptype, $settings['post_types'])) {
    132             return;
     64            return $search;
    13365        }
    13466
    135         // Check user capability - critical security check
    136         // Only users with the required capability can filter by slug
     67        // Check user capability
    13768        if (!current_user_can($settings['capability'])) {
    138             return;
     69            return $search;
    13970        }
    14071
    141         // phpcs:ignore WordPress.Security.NonceVerification.Recommended
    142         // Reason: WP Admin List Table filters (search, dropdowns, custom GET params)
    143         // do not use nonces in core and are safe when sanitized and capability-checked.
    144         $ssac_slug = '';
    145 
    146         // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- core WP convention
    147         if (isset($_GET['ssac_slug'])) {
    148             // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- core WP convention
    149             $ssac_slug = sanitize_text_field(wp_unslash($_GET['ssac_slug']));
     72        // Only modify if there's a search term
     73        $search_term = $query->get('s');
     74        if (empty($search_term)) {
     75            return $search;
    15076        }
    15177
    152         // Exit if no search term
    153         if (empty($ssac_slug)) {
    154             return;
     78        // Check if search term matches slug pattern (lowercase, hyphens, numbers only)
     79        if (!preg_match('/^[a-z0-9\-]+$/', $search_term)) {
     80            return $search;
    15581        }
    15682
    157         $mode = $settings['search_mode'];
     83        global $wpdb;
    15884
    159         // Handle exact match
    160         if ($mode === 'exact') {
    161             $query->set('name', $ssac_slug);
    162         } else {
    163             // Handle partial match
    164             self::$partial_slug = $ssac_slug;
    165             self::$active_query = $query;
    166             add_filter('posts_where', [__CLASS__, 'posts_where_partial']);
    167             add_filter('posts_request', [__CLASS__, 'remove_partial_filter']);
    168         }
     85        // Replace the entire search with slug-only search
     86        // This searches ONLY the post_name (slug) field
     87        $search = $wpdb->prepare("AND ({$wpdb->posts}.post_name LIKE %s)", '%' . $search_term . '%');
     88
     89        return $search;
    16990    }
    17091
    17192
    172     /**
    173      * Modify WHERE clause for partial slug search
    174      *
    175      * Adds LIKE condition to search for partial slug matches
    176      *
    177      * @param string $where The WHERE clause of the query
    178      * @return string Modified WHERE clause
    179      */
    180     public static function posts_where_partial($where)
    181     {
    182         global $wpdb;
    183 
    184         // Add partial match condition if we have an active search
    185         if (self::$partial_slug && self::$active_query && self::$active_query->is_main_query()) {
    186             $where .= $wpdb->prepare(" AND {$wpdb->posts}.post_name LIKE %s", '%' . self::$partial_slug . '%');
    187         }
    188 
    189         return $where;
    190     }
    191 
    192 
    193     /**
    194      * Remove partial search filter after query is built
    195      *
    196      * Cleans up filters and resets static properties after the query is complete
    197      *
    198      * @param string $request The complete SQL query
    199      * @return string Unmodified SQL query
    200      */
    201     public static function remove_partial_filter($request)
    202     {
    203         // Remove filters
    204         remove_filter('posts_where', [__CLASS__, 'posts_where_partial']);
    205         remove_filter('posts_request', [__CLASS__, 'remove_partial_filter']);
    206 
    207         // Reset static properties
    208         self::$partial_slug = null;
    209         self::$active_query = null;
    210 
    211         return $request;
    212     }
    213 
    21493}
    215 
  • slug-search-and-admin-columns/trunk/includes/class-ssac-settings.php

    r3425226 r3449426  
    3939        'label_id' => 'ID',
    4040        'label_slug' => 'Slug',
    41         'search_mode' => 'partial',
    42         'case_sensitive' => 0,
    4341        'capability' => 'edit_posts',
    4442    ];
     
    158156        $output['enable_id'] = !empty($input['enable_id']) ? 1 : 0;
    159157        $output['enable_slug'] = !empty($input['enable_slug']) ? 1 : 0;
    160         $output['case_sensitive'] = !empty($input['case_sensitive']) ? 1 : 0;
    161158
    162159        // Sanitize text labels
     
    164161        $output['label_slug'] = isset($input['label_slug']) ? sanitize_text_field($input['label_slug']) : self::$defaults['label_slug'];
    165162
    166         // Sanitize search mode
    167         $output['search_mode'] = in_array($input['search_mode'], ['exact', 'partial']) ? $input['search_mode'] : 'partial';
    168 
    169163        // Sanitize capability
    170164        $caps = ['manage_options', 'edit_others_posts', 'edit_posts', 'read'];
  • slug-search-and-admin-columns/trunk/readme.txt

    r3426055 r3449426  
    66Tested up to: 6.9
    77Requires PHP: 7.4
    8 Stable tag: 1.0.1
     8Stable tag: 2.0.0
    99License: GPLv2 or later
    1010License URI: https://www.gnu.org/licenses/gpl-2.0.html
     
    2020* **Slug Search** - Search posts, pages, and custom post types by their slug (URL path)
    2121* **Sortable Columns** - Add ID and Slug columns to admin post lists with sorting capability
    22 * **Flexible Search Modes** - Choose between exact match or partial match search
     22* **Integrated Search** - Works directly with the default WordPress search box
     23* **Smart Detection** - Automatically detects slug searches without configuration
    2324* **Post Type Control** - Enable features for specific post types only
    2425* **User Permissions** - Control which user roles can see the columns and search
     
    1011022. Select which post types to enable (Posts, Pages, Custom Post Types)
    1021033. Enable ID and/or Slug columns as needed
    103 4. Choose search mode (Exact or Partial match)
    104 5. Set user capability level for column visibility
    105 6. Customize column labels if desired
    106 7. Click **Save Changes**
    107 
    108 That's it! The search field and columns will now appear in your admin post lists.
     104
     1054. Set user capability level for column visibility
     1065. Customize column labels if desired
     1076. Click **Save Changes**
     108
     109That's it! You can now search by slug directly in the main WordPress search bar, and columns will appear in your admin post lists.
    109110
    110111== Frequently Asked Questions ==
     
    120121= Will this slow down my admin panel? =
    121122
    122 No. The plugin is lightweight and only runs in the WordPress admin area. It uses native WordPress queries and is optimized for performance. For very large sites, using "Exact" search mode is recommended for faster results.
     123No. The plugin is lightweight and only runs in the WordPress admin area. It uses native WordPress queries and is optimized for performance.
    123124
    124125= Can I customize the column labels? =
     
    126127Yes! You can customize the labels for both the ID and Slug columns from the settings page to match your workflow or language preferences.
    127128
    128 = What's the difference between Exact and Partial search? =
    129 
    130 * **Exact Match**: Finds posts where the slug exactly matches your search term (faster)
    131 * **Partial Match**: Finds posts where the slug contains your search term anywhere (more flexible)
     129
    132130
    133131= Does it work with Gutenberg and Classic Editor? =
     
    157155== Screenshots ==
    158156
    159 1. **Slug Search Field** - Search by slug input field in the post list table filters
     1571. **Integrated Search** - Search by slug directly using the default WordPress search box
    1601582. **ID and Slug Columns** - Sortable ID and Slug columns in the admin post list
    1611593. **Settings Page** - Comprehensive settings panel with post type selection
    1621604. **Column Customization** - Enable/disable columns and customize labels
    163 5. **Search Modes** - Choose between exact and partial match search
    1641616. **User Permissions** - Control which user roles can access features
    165162
    166163== Changelog ==
     164
     165= 2.0.0 - 2026-01-29 =
     166* Major Update: Search functionality now integrated directly into the main WordPress search box.
     167* Improvement: Removed separate "Slug Search" input field for a cleaner UI.
     168* Improvement: Removed "Search Mode" settings; plugin now automatically handles fuzzy/partial matching for slug-like queries.
     169* Enhancement: Streamlined codebase for better performance.
    167170
    168171= 1.0.1 - 2025-12-23 =
     
    186189== Upgrade Notice ==
    187190
     191= 2.0.0 =
     192Major update: Search is now integrated into the main WordPress search bar. Separate search field has been removed.
     193
    188194= 1.0.1 =
    189195Critical update: Fixes fatal error on activation and potential conflicts with other plugins. Upgrade immediately.
  • slug-search-and-admin-columns/trunk/slug-search-and-admin-columns.php

    r3426055 r3449426  
    33 * Plugin Name: Slug Search and Admin Columns
    44 * Description: Adds slug search and ID/slug columns to WP admin. Settings included.
    5  * Version: 1.0.1
     5 * Version: 2.0.0
    66 * Author: Code and Core
    77 * Author URI: https://codeandcore.com
Note: See TracChangeset for help on using the changeset viewer.