Created
May 2, 2015 05:35
-
-
Save mcaskill/d3ada21f9ff0800a6970 to your computer and use it in GitHub Desktop.
WordPress : Sort post titles in alphabetical order, disregarding initial definite and indefinite articles
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* File: Sort posts in alphabetical order, ignoring initial articles. | |
* | |
* This condition is achieved using the `post_fields` and `posts_orderby` | |
* filters. The implementer must provide their own list of definite and | |
* indefinite articles for the hooks to ignore. | |
* | |
* To enable natural language sorting, pass the following Query parameter: | |
* `"ignore_initial_articles" => true` | |
* | |
* @link https://css-tricks.com/ignoring-the-in-wordpress-queries/ | |
*/ | |
namespace McAskill\WordPress\IgnoreInitialArticles; | |
/** | |
* Retrieve definite and indefinite articles used when sorting titles. | |
* | |
* Based on {@see WP_Query::get_search_stopwords()}. | |
* | |
* @return array Initial articles. | |
*/ | |
function get_initial_articles() | |
{ | |
static::$articles = null; | |
if ( is_array( $articles ) ) { | |
return $articles; | |
} | |
/** | |
* translators: This is a comma-separated list of very common initial words that | |
* should be excluded from sorting and filing processes, like "a", "an", and "the". | |
* These are usually called "articles". You should not simply translate these | |
* individual words into your language. Instead, look for and provide commonly | |
* accepted articles in your language. | |
* | |
* @link http://www.loc.gov/marc/bibliographic/bdapndxf.html | |
*/ | |
$words = explode( ',', _x( 'a,an,the', 'Comma-separated list of initial articles in your language' ) ); | |
$articles = []; | |
foreach ( $words as $word ) { | |
$word = trim( $word, "\r\n\t " ); | |
if ( $word ) { | |
$articles[] = $word; | |
} | |
} | |
/** | |
* Filter articles used when parsing search terms. | |
* | |
* @param array $articles articles. | |
*/ | |
$articles = apply_filters( 'wp_initial_articles', $articles ); | |
return $articles; | |
} | |
/** | |
* Filter: Create a virtual table column named "title2" at the time | |
* of the query. Populate the table column with the titles of the | |
* queried posts. If the title has a matching initial article, | |
* it will be removed. | |
* | |
* The list of English stopwords is the approximate search engines list, | |
* and is translatable. | |
* | |
* @used-by Filter: "posts_fields" | |
* | |
* @param string $fields The SELECT clause of the query. | |
* @param WP_Query &$wp_query The WP_Query instance (passed by reference). | |
* | |
* @return string $fields | |
*/ | |
function create_temp_column( $fields, $wp_query ) | |
{ | |
if ( $wp_query->get( 'ignore_initial_articles', false ) ) { | |
global $wpdb; | |
$matches = get_initial_articles(); | |
if ( count( $matches ) ) { | |
$matches = implode( '|', $matches ); | |
$has_article = " CASE | |
WHEN $wpdb->posts.post_title regexp( '^($matches)[[:space:]]' ) | |
THEN trim( substr( $wpdb->posts.post_title from 4 ) ) | |
ELSE $wpdb->posts.post_title | |
END AS title2"; | |
if ( $has_article ) { | |
$fields .= ( preg_match( '/^(\s+)?,/', $has_article ) ? $has_article : ", $has_article" ); | |
} | |
} | |
} | |
return $fields; | |
} | |
/** | |
* Filter: Create a new custom "orderby". It orders the posts by | |
* the virtual table column "title2" using the ASC order. | |
* | |
* @used-by Filter: "posts_orderby" | |
* | |
* @param string $orderby The ORDER BY clause of the query. | |
* @param WP_Query &$wp_query The WP_Query instance (passed by reference). | |
* | |
* @return string $orderby | |
*/ | |
function sort_by_temp_column( $orderby, $wp_query ) | |
{ | |
if ( $wp_query->get( 'ignore_initial_articles', false ) ) { | |
$custom_orderby = ' UPPER( title2 ) ASC'; | |
if ( $custom_orderby ) { | |
$orderby = $custom_orderby; | |
} | |
} | |
return $orderby; | |
} | |
add_filter( 'posts_fields', __NAMESPACE__ . '\\create_temp_column' ); | |
add_filter( 'posts_orderby', __NAMESPACE__ . '\\sort_by_temp_column' ); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment