diff --git a/src/wp-includes/class-wp-query.php b/src/wp-includes/class-wp-query.php index de1f05363b2f8..892ae504eb3b9 100644 --- a/src/wp-includes/class-wp-query.php +++ b/src/wp-includes/class-wp-query.php @@ -962,7 +962,11 @@ public function parse_query( $query = '' ) { $this->is_tag = true; break; default: - $this->is_tax = true; + if ( ! empty( $tax_query['terms'] ) ) { + $this->is_tax = true; + } else { + $this->is_tax_without_term = true; + } } } } @@ -4250,6 +4254,44 @@ public function is_tag( $tag = '' ) { return false; } + /** + * Determines whether the query is for an existing custom taxonomy root archive page. + * + * If the $taxonomy parameter is specified, this function will additionally + * check if the query is for that specific $taxonomy. + * + * @since 6.8.0 + * + * @global WP_Taxonomy[] $wp_taxonomies Registered taxonomies. + * + * @param string|string[] $taxonomy Optional. Taxonomy slug or slugs to check against. + * Default empty. + * @return bool Whether the query is for an existing custom taxonomy root archive page. + * True for custom taxonomy root archive pages, false for built-in taxonomies + * (category and tag archives). + */ + public function is_tax_without_term( $taxonomy = '' ) { + global $wp_taxonomies; + + if ( ! $this->is_tax_without_term ) { + return false; + } + + if ( empty( $taxonomy ) ) { + return true; + } + + $queried_object = $this->get_queried_object(); + $tax_array = array_intersect( array_keys( $wp_taxonomies ), (array) $taxonomy ); + + // Check that the taxonomy matches. + if ( ! ( isset( $queried_object->name ) && count( $tax_array ) && in_array( $queried_object->name, $tax_array, true ) ) ) { + return false; + } + + return true; + } + /** * Determines whether the query is for an existing custom taxonomy archive page. * diff --git a/src/wp-includes/general-template.php b/src/wp-includes/general-template.php index 32ed7972ad9e7..70c83ceaa198d 100644 --- a/src/wp-includes/general-template.php +++ b/src/wp-includes/general-template.php @@ -1758,9 +1758,15 @@ function get_the_archive_title() { } elseif ( is_post_type_archive() ) { $title = post_type_archive_title( '', false ); $prefix = _x( 'Archives:', 'post type archive title prefix' ); + } elseif ( is_tax_without_term() ) { + $queried_object = get_queried_object(); + if ( $queried_object ) { + $title = $queried_object->labels->singular_name; + $prefix = _x( 'Archives:', 'taxonomy archive title prefix' ); + } } elseif ( is_tax() ) { $queried_object = get_queried_object(); - if ( $queried_object instanceof WP_Term ) { + if ( $queried_object ) { $tax = get_taxonomy( $queried_object->taxonomy ); $title = single_term_title( '', false ); $prefix = sprintf( @@ -1768,9 +1774,6 @@ function get_the_archive_title() { _x( '%s:', 'taxonomy term archive title prefix' ), $tax->labels->singular_name ); - } elseif ( $queried_object instanceof WP_Taxonomy ) { - $title = $queried_object->labels->singular_name; - $prefix = _x( 'Archives:', 'taxonomy archive title prefix' ); } } diff --git a/src/wp-includes/query.php b/src/wp-includes/query.php index 94c6453b6637b..ef6dc7d63ae54 100644 --- a/src/wp-includes/query.php +++ b/src/wp-includes/query.php @@ -308,6 +308,37 @@ function is_tag( $tag = '' ) { return $wp_query->is_tag( $tag ); } +/** + * Determines whether the query is for an existing custom taxonomy root archive page. + * + * If the $taxonomy parameter is specified, this function will additionally + * check if the query is for that specific $taxonomy. + * + * For more information on this and similar theme functions, check out + * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ + * Conditional Tags} article in the Theme Developer Handbook. + * + * @since 6.8.0 + * + * @global WP_Query $wp_query WordPress Query object. + * + * @param string|string[] $taxonomy Optional. Taxonomy slug or slugs to check against. + * Default empty. + * @return bool Whether the query is for an existing custom taxonomy root archive page. + * True for custom taxonomy root archive pages, false for built-in taxonomies + * (category and tag archives). + */ +function is_tax_without_term( $taxonomy = '' ) { + global $wp_query; + + if ( ! isset( $wp_query ) ) { + _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1.0' ); + return false; + } + + return $wp_query->is_tax_without_term( $taxonomy ); +} + /** * Determines whether the query is for an existing custom taxonomy archive page. * diff --git a/src/wp-includes/template-loader.php b/src/wp-includes/template-loader.php index 0fd08545cc67d..9a31a94fb949f 100644 --- a/src/wp-includes/template-loader.php +++ b/src/wp-includes/template-loader.php @@ -62,6 +62,7 @@ 'is_home' => 'get_home_template', 'is_privacy_policy' => 'get_privacy_policy_template', 'is_post_type_archive' => 'get_post_type_archive_template', + 'is_tax_without_term' => 'get_root_taxonomy_template', 'is_tax' => 'get_taxonomy_template', 'is_attachment' => 'get_attachment_template', 'is_single' => 'get_single_template', diff --git a/src/wp-includes/template.php b/src/wp-includes/template.php index 8a0a156b47f0e..1f6e51586ae02 100644 --- a/src/wp-includes/template.php +++ b/src/wp-includes/template.php @@ -317,6 +317,45 @@ function get_tag_template() { return get_query_template( 'tag', $templates ); } +/** + * Retrieves path of custom taxonomy root template in current or parent template. + * + * The hierarchy for this template looks like: + * + * 1. root-taxonomy-{taxonomy_slug}.php + * 2. taxonomy-{taxonomy_slug}.php + * 3. root-taxonomy.php + * 4. taxonomy.php + * + * An example of this is: + * + * 1. root-taxonomy-location.php + * 2. taxonomy-location.php + * 3. root-taxonomy.php + * 4. taxonomy.php + * + * The template hierarchy and template path are filterable via the {@see '$type_template_hierarchy'} + * and {@see '$type_template'} dynamic hooks, where `$type` is 'taxonomy'. + * + * @since 6.8.0 + * + * @see get_query_template() + * + * @return string Full path to custom taxonomy term template file. + */ +function get_root_taxonomy_template() { + $tax = get_queried_object(); + + $templates = array(); + + $templates[] = "root-taxonomy-$taxonomy.php"; + $templates[] = "taxonomy-$taxonomy.php"; + $templates[] = 'root-taxonomy.php'; + $templates[] = 'taxonomy.php'; + + return get_query_template( 'taxonomy', $templates ); +} + /** * Retrieves path of custom taxonomy term template in current or parent template. * @@ -344,12 +383,11 @@ function get_tag_template() { * @return string Full path to custom taxonomy term template file. */ function get_taxonomy_template() { - $term_or_tax = get_queried_object(); + $term = get_queried_object(); $templates = array(); - if ( $term_or_tax instanceof WP_Term && ! empty( $term_or_tax->slug ) ) { - $term = $term_or_tax; + if ( ! empty( $term->slug ) ) { $taxonomy = $term->taxonomy; $slug_decoded = urldecode( $term->slug ); @@ -359,9 +397,6 @@ function get_taxonomy_template() { $templates[] = "taxonomy-$taxonomy-{$term->slug}.php"; $templates[] = "taxonomy-$taxonomy.php"; - } elseif ( $term_or_tax instanceof WP_Taxonomy ) { - $taxonomy = $term_or_tax->name; - $templates[] = "taxonomy-$taxonomy.php"; } $templates[] = 'taxonomy.php';