Skip to content

Instantly share code, notes, and snippets.

@kjbenk
Last active November 26, 2019 09:27
Show Gist options
  • Save kjbenk/cc48186565bfbabaee09a2ab30421a41 to your computer and use it in GitHub Desktop.
Save kjbenk/cc48186565bfbabaee09a2ab30421a41 to your computer and use it in GitHub Desktop.
WordPress: Taxonomy Top Level URL
<?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