| 220 | * Filter the SQL for the ORDER BY clause for search queries. |
| 221 | * Adds ORDER BY condition with spaces replaced with underscores in 'post_title'. |
| 222 | * Adds ORDER BY condition to order by title length. |
| 223 | * |
| 224 | * @param string $orderby The ORDER BY clause of the query. |
| 225 | * @param WP_Query $query The WP_Query instance (passed by reference). |
| 226 | * @return string Filtered order by clause |
| 227 | */ |
| 228 | function search_posts_orderby( $orderby, $query ) { |
| 229 | global $wpdb; |
| 230 | |
| 231 | if ( $query->is_main_query() && is_search() && !$query->get( 'exact' ) ) { |
| 232 | |
| 233 | $search_order_by_title = $query->get( 'search_orderby_title' ); |
| 234 | |
| 235 | // Check if search_orderby_title is set by WP_Query::parse_search |
| 236 | if ( is_array( $search_order_by_title ) && !empty( $search_order_by_title ) ) { |
| 237 | |
| 238 | // Get search orderby query. |
| 239 | $orderby = parse_search_order( $query->query_vars ); |
| 240 | |
| 241 | // Add order by title length. |
| 242 | $orderby .= " , CHAR_LENGTH( $wpdb->posts.post_title ) ASC, $wpdb->posts.post_title ASC"; |
| 243 | } |
| 244 | } |
| 245 | |
| 246 | return $orderby; |
| 247 | } |
| 248 | |
| 249 | /** |
| 250 | * Generate SQL for the ORDER BY condition based on passed search terms. |
| 251 | * Similar to WP_Query::parse_search_order. |
| 252 | * Adds ORDER BY condition with spaces replaced with underscores in 'post_title'. |
| 253 | * |
| 254 | * @global wpdb $wpdb WordPress database abstraction object. |
| 255 | * |
| 256 | * @param array $q Query variables. |
| 257 | * @return string ORDER BY clause. |
| 258 | */ |
| 259 | function parse_search_order( $q ) { |
| 260 | global $wpdb; |
| 261 | |
| 262 | if ( $q['search_terms_count'] > 1 ) { |
| 263 | $num_terms = count( $q['search_orderby_title'] ); |
| 264 | |
| 265 | // If the search terms contain negative queries, don't bother ordering by sentence matches. |
| 266 | $like = $_like = ''; |
| 267 | if ( ! preg_match( '/(?:\s|^)\-/', $q['s'] ) ) { |
| 268 | $like = '%' . $wpdb->esc_like( $q['s'] ) . '%'; |
| 269 | } |
| 270 | |
| 271 | $search_orderby = ''; |
| 272 | |
| 273 | // Sentence match in 'post_title'. |
| 274 | if ( $like ) { |
| 275 | $search_orderby .= $wpdb->prepare( "WHEN $wpdb->posts.post_title LIKE %s THEN 1 ", $like ); |
| 276 | $_like = str_replace( '-', '_', sanitize_title_with_dashes( $q['s'] ) ); |
| 277 | $_like = '%' . $wpdb->esc_like( $_like ) . '%'; |
| 278 | if ( $_like !== $like ) { |
| 279 | // Sentence match in 'post_title' with spaces replaced with underscores. |
| 280 | $search_orderby .= $wpdb->prepare( "WHEN $wpdb->posts.post_title LIKE %s THEN 2 ", $_like ); |
| 281 | } |
| 282 | } |
| 283 | |
| 284 | // Sanity limit, sort as sentence when more than 6 terms. |
| 285 | // (few searches are longer than 6 terms and most titles are not) |
| 286 | if ( $num_terms < 7 ) { |
| 287 | // all words in title |
| 288 | $search_orderby .= 'WHEN ' . implode( ' AND ', $q['search_orderby_title'] ) . ' THEN 3 '; |
| 289 | // any word in title, not needed when $num_terms == 1 |
| 290 | if ( $num_terms > 1 ) |
| 291 | $search_orderby .= 'WHEN ' . implode( ' OR ', $q['search_orderby_title'] ) . ' THEN 4 '; |
| 292 | } |
| 293 | |
| 294 | // Sentence match in 'post_content'. |
| 295 | if ( $like ) { |
| 296 | $search_orderby .= $wpdb->prepare( "WHEN $wpdb->posts.post_content LIKE %s THEN 5 ", $like ); |
| 297 | } |
| 298 | |
| 299 | if ( $search_orderby ) { |
| 300 | $search_orderby = '(CASE ' . $search_orderby . 'ELSE 6 END)'; |
| 301 | } |
| 302 | } else { |
| 303 | // Single word or sentence search. |
| 304 | $search_orderby = reset( $q['search_orderby_title'] ) . ' DESC'; |
| 305 | } |
| 306 | |
| 307 | return $search_orderby; |
| 308 | } |
| 309 | |
| 310 | /** |