Last active
November 26, 2019 09:27
-
-
Save kjbenk/cc48186565bfbabaee09a2ab30421a41 to your computer and use it in GitHub Desktop.
WordPress: Taxonomy Top Level URL
This file contains hidden or 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 | |
/** | |
* The class used to make certain taxonomies have a top level URL. | |
*/ | |
/** | |
* The Taxonomy_Top_Level_URL class. | |
*/ | |
class Taxonomy_Top_Level_URL { | |
/** | |
* Existing instance. | |
* | |
* @var array | |
*/ | |
protected static $instance; | |
/** | |
* The array holding all of the taxonomies that need top level URLs. | |
* | |
* @var array | |
*/ | |
private $_taxonomies = []; | |
/** | |
* Get class instance. | |
* | |
* @return object | |
*/ | |
public static function instance() { | |
if ( ! isset( static::$instance ) ) { | |
static::$instance = new static(); | |
static::$instance->setup(); | |
} | |
return static::$instance; | |
} | |
/** | |
* Setup the singleton. | |
*/ | |
public function setup() { | |
// Add the new top level rewrite rules. | |
add_filter( 'rewrite_rules_array', array( $this, 'rewrite_rules_array' ), 10, 1 ); | |
// Setup the taxonomy URL link. | |
add_filter( 'term_link', array( $this, 'custom_term_permalink' ), 10, 3 ); | |
// Flush rewrite rules whenever any term in the taxonomies is saved. | |
add_filter( 'created_term', array( $this, 'term_flush_rewrite_rules' ), 10, 3 ); | |
add_filter( 'edited_term', array( $this, 'term_flush_rewrite_rules' ), 10, 3 ); | |
add_filter( 'delete_term', array( $this, 'term_flush_rewrite_rules' ), 10, 3 ); | |
} | |
/** | |
* Adding assorted rewrite rules. | |
* | |
* @param array $rules The current rules. | |
* @return array $rules The new rules. | |
*/ | |
public function rewrite_rules_array( $rules ) { | |
// Move all terms to the top level if in our taxonomy. | |
$taxonomies = $this->get_taxonomies(); | |
$all_term_names = []; | |
if ( ! empty( $taxonomies ) ) { | |
foreach ( $taxonomies as $taxonomy ) { | |
$term_names = []; | |
if ( taxonomy_exists( $taxonomy ) ) { | |
$terms = get_terms( | |
$taxonomy, | |
[ | |
'hide_empty' => false, | |
] | |
); | |
// Get all term slugs. | |
$term_slugs = []; | |
foreach ( $terms as $term ) { | |
$term_slugs[] = $this->get_term_slug( $term ); | |
} | |
$term_names = array_map( 'preg_quote', $term_slugs ); | |
// Remove any terms that have already been added. | |
foreach ( $term_names as $key => $term_name ) { | |
if ( in_array( $term_name, $all_term_names, true ) ) { | |
unset( $term_names[ $key ] ); | |
} | |
} | |
// Add the new terms to the all terms array. | |
$all_term_names = array_merge( $all_term_names, $term_names ); | |
if ( ! empty( $term_names ) ) { | |
$rules = array_merge( $this->rewrite_term_rules( $term_names, $taxonomy, $rules ), $rules ); | |
} | |
} | |
} | |
} | |
return $rules; | |
} | |
/** | |
* Create the rules necessary to move a taxonomy term to a top level URL | |
* | |
* @param array $term_names The term names to add to the top level. | |
* @param string $taxonomy The taxonomy of the terms. | |
* @param array $rules The current rules. | |
* @return array $rules The new rules. | |
*/ | |
public function rewrite_term_rules( $term_names, $taxonomy, $rules ) { | |
$term_regex = implode( '|', $term_names ); | |
$taxonomy_name = $taxonomy; | |
if ( 'category' === $taxonomy ) { | |
$taxonomy_name = 'category_name'; | |
} | |
$new_term_rules = [ | |
'^(' . $term_regex . ')/?$' => 'index.php?' . $taxonomy_name . '=$matches[1]', | |
'(' . $term_regex . ')/page/?([0-9]{1,})/?' => 'index.php?' . $taxonomy_name . '=$matches[1]&paged=$matches[2]', | |
'(' . $term_regex . ')/feed/(feed|rdf|rss|rss2|atom|json)/?$' => 'index.php?' . $taxonomy_name . '=$matches[1]&feed=$matches[2]', | |
'(' . $term_regex . ')/(feed|rdf|rss|rss2|atom|json)/?$' => 'index.php?' . $taxonomy_name . '=$matches[1]&feed=$matches[2]', | |
'(' . $term_regex . ')/(feed|rdf|rss|rss2|atom|json)/(article|gallery)/?$' => 'index.php?' . $taxonomy_name . '=$matches[1]&feed=$matches[2]&post_type=$matches[3]', | |
]; | |
// Append the new rules to the beginning of the array so that they are matched first. | |
$rules = $new_term_rules + $rules; | |
return $rules; | |
} | |
/** | |
* Update all terms for a specfic taxonomy to the top level URL. | |
* | |
* @param string $termlink The current term link. | |
* @param WP_Term $term The current term. | |
* @param string $taxonomy The term taxonomy. | |
* @return string $termlink The new term link. | |
*/ | |
public function custom_term_permalink( $termlink, $term, $taxonomy ) { | |
if ( in_array( $taxonomy, $this->get_taxonomies(), true ) ) { | |
return trailingslashit( '/' . $this->get_term_slug( $term ) ); | |
} | |
return $termlink; | |
} | |
/** | |
* Flush rewrite rules when a term is created, edited or deleted. | |
* | |
* @param int $term_id Term ID. | |
* @param int $tt_id Term taxonomy ID. | |
* @param string $taxonomy Taxonomy slug. | |
*/ | |
public function term_flush_rewrite_rules( $term_id, $tt_id, $taxonomy ) { | |
if ( in_array( $taxonomy, $this->get_taxonomies(), true ) ) { | |
flush_rewrite_rules( false ); | |
} | |
} | |
/** | |
* Get the term slug to use in the URL. | |
* | |
* @param \WP_Term $term The term object. | |
* @return string $term_slug The term slug. | |
*/ | |
public function get_term_slug( \WP_Term $term ) { | |
$term_slug = $term->slug; | |
// Sub-categories should have their parent category slug prepended to the URL. | |
if ( 'category' === $term->taxonomy && 0 !== $term->parent ) { | |
$parent_term = get_term( $term->parent ); | |
if ( $parent_term instanceof \WP_Term ) { | |
$term_slug = $parent_term->slug . '/' . $term_slug; | |
} | |
} | |
return $term_slug; | |
} | |
/** | |
* Get the taxonomies. | |
* | |
* @return array $taxonomies The taxonomies. | |
*/ | |
public function get_taxonomies() { | |
return $this->_taxonomies; | |
} | |
/** | |
* Set the taxonomies. | |
* | |
* @param array $new_taxonomies The new taxonomies. | |
*/ | |
public function set_taxonomies( $new_taxonomies ) { | |
$this->_taxonomies = $new_taxonomies; | |
} | |
} | |
/** | |
* Get the singleton instance. | |
* | |
* @return Taxonomy_Top_Level_URL | |
*/ | |
function taxonomy_top_level_url() { | |
$instance = Taxonomy_Top_Level_URL::instance(); | |
// Add the taxonomies here. | |
$instance->set_taxonomies( [ | |
// 'category', | |
] ); | |
return $instance; | |
} | |
add_action( 'after_setup_theme', 'taxonomy_top_level_url' ); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment