diff --git a/src/wp-includes/class-wp.php b/src/wp-includes/class-wp.php index 6791c98cbc..238e2e6660 100644 --- a/src/wp-includes/class-wp.php +++ b/src/wp-includes/class-wp.php @@ -331,12 +331,12 @@ class WP { if ( $t->query_var && isset( $this->query_vars[$t->query_var] ) ) $this->query_vars[$t->query_var] = str_replace( ' ', '+', $this->query_vars[$t->query_var] ); - // Don't allow non-public taxonomies to be queried from the front-end. + // Don't allow non-publicly queryable taxonomies to be queried from the front-end. if ( ! is_admin() ) { - foreach ( get_taxonomies( array( 'public' => false ), 'objects' ) as $taxonomy => $t ) { + foreach ( get_taxonomies( array( 'publicly_queryable' => false ), 'objects' ) as $taxonomy => $t ) { /* * Disallow when set to the 'taxonomy' query var. - * Non-public taxonomies cannot register custom query vars. See register_taxonomy(). + * Non-publicly queryable taxonomies cannot register custom query vars. See register_taxonomy(). */ if ( isset( $this->query_vars['taxonomy'] ) && $taxonomy === $this->query_vars['taxonomy'] ) { unset( $this->query_vars['taxonomy'], $this->query_vars['term'] ); diff --git a/src/wp-includes/taxonomy.php b/src/wp-includes/taxonomy.php index 4d672564ef..0164b0f803 100644 --- a/src/wp-includes/taxonomy.php +++ b/src/wp-includes/taxonomy.php @@ -288,7 +288,12 @@ function is_taxonomy_hierarchical($taxonomy) { * taxonomies. See accepted values in get_taxonomy_labels(). * Default empty array. * @type string $description A short descriptive summary of what the taxonomy is for. Default empty. - * @type bool $public Whether the taxonomy is publicly queryable. Default true. + * @type bool $public Whether a taxonomy is intended for use publicly either via + * the admin interface or by front-end users. The default settings + * of `$publicly_queryable`, `$show_ui`, and `$show_in_nav_menus` + * are inherited from `$public`. + * @type bool $publicly_queryable Whether the taxonomy is publicly queryable. + * If not set, the default is inherited from `$public` * @type bool $hierarchical Whether the taxonomy is hierarchical. Default false. * @type bool $show_ui Whether to generate and allow a UI for managing terms in this taxonomy in * the admin. If not set, the default is inherited from `$public` @@ -362,6 +367,7 @@ function register_taxonomy( $taxonomy, $object_type, $args = array() ) { 'labels' => array(), 'description' => '', 'public' => true, + 'publicly_queryable' => null, 'hierarchical' => false, 'show_ui' => null, 'show_in_menu' => null, @@ -383,8 +389,13 @@ function register_taxonomy( $taxonomy, $object_type, $args = array() ) { return new WP_Error( 'taxonomy_length_invalid', __( 'Taxonomy names must be between 1 and 32 characters in length.' ) ); } - // Non-public taxonomies should not register query vars, except in the admin. - if ( false !== $args['query_var'] && ( is_admin() || false !== $args['public'] ) && ! empty( $wp ) ) { + // If not set, default to the setting for public. + if ( null === $args['publicly_queryable'] ) { + $args['publicly_queryable'] = $args['public']; + } + + // Non-publicly queryable taxonomies should not register query vars, except in the admin. + if ( false !== $args['query_var'] && ( is_admin() || false !== $args['publicly_queryable'] ) && ! empty( $wp ) ) { if ( true === $args['query_var'] ) $args['query_var'] = $taxonomy; else diff --git a/tests/phpunit/includes/utils.php b/tests/phpunit/includes/utils.php index 17b5630b7d..f0282da4aa 100644 --- a/tests/phpunit/includes/utils.php +++ b/tests/phpunit/includes/utils.php @@ -362,7 +362,7 @@ function _cleanup_query_vars() { unset( $GLOBALS[$v] ); foreach ( get_taxonomies( array() , 'objects' ) as $t ) { - if ( $t->public && ! empty( $t->query_var ) ) + if ( $t->publicly_queryable && ! empty( $t->query_var ) ) $GLOBALS['wp']->add_query_var( $t->query_var ); } diff --git a/tests/phpunit/tests/taxonomy.php b/tests/phpunit/tests/taxonomy.php index e4185fce29..4179bf4875 100644 --- a/tests/phpunit/tests/taxonomy.php +++ b/tests/phpunit/tests/taxonomy.php @@ -446,9 +446,9 @@ class Tests_Taxonomy extends WP_UnitTestCase { /** * @ticket 21949 */ - public function test_nonpublic_taxonomy_should_not_be_queryable_using_taxname_query_var() { + public function test_nonpublicly_queryable_taxonomy_should_not_be_queryable_using_taxname_query_var() { register_taxonomy( 'wptests_tax', 'post', array( - 'public' => false, + 'publicly_queryable' => false, ) ); $t = self::factory()->term->create_and_get( array( @@ -466,11 +466,11 @@ class Tests_Taxonomy extends WP_UnitTestCase { /** * @ticket 21949 */ - public function test_it_should_be_possible_to_register_a_query_var_that_matches_the_name_of_a_nonpublic_taxonomy() { + public function test_it_should_be_possible_to_register_a_query_var_that_matches_the_name_of_a_nonpublicly_queryable_taxonomy() { global $wp; register_taxonomy( 'wptests_tax', 'post', array( - 'public' => false, + 'publicly_queryable' => false, ) ); $t = $this->factory->term->create_and_get( array( 'taxonomy' => 'wptests_tax', @@ -501,9 +501,9 @@ class Tests_Taxonomy extends WP_UnitTestCase { /** * @ticket 21949 */ - public function test_nonpublic_taxonomy_should_not_be_queryable_using_taxonomy_and_term_vars() { + public function test_nonpublicly_queryable_taxonomy_should_not_be_queryable_using_taxonomy_and_term_vars() { register_taxonomy( 'wptests_tax', 'post', array( - 'public' => false, + 'publicly_queryable' => false, ) ); $t = self::factory()->term->create_and_get( array( @@ -518,6 +518,73 @@ class Tests_Taxonomy extends WP_UnitTestCase { $this->assertFalse( is_tax( 'wptests_tax' ) ); } + /** + * @ticket 34491 + */ + public function test_public_taxonomy_should_be_publicly_queryable() { + register_taxonomy( 'wptests_tax', 'post', array( + 'public' => true, + ) ); + + $this->assertContains( 'wptests_tax', get_taxonomies( array( 'publicly_queryable' => true ) ) ); + + $t = self::factory()->term->create_and_get( array( + 'taxonomy' => 'wptests_tax', + ) ); + + $p = self::factory()->post->create(); + wp_set_object_terms( $p, $t->slug, 'wptests_tax' ); + + $this->go_to( '/?wptests_tax=' . $t->slug ); + + $this->assertTrue( is_tax( 'wptests_tax' ) ); + } + + /** + * @ticket 34491 + */ + public function test_private_taxonomy_should_not_be_publicly_queryable() { + register_taxonomy( 'wptests_tax', 'post', array( + 'public' => false, + ) ); + + $this->assertContains( 'wptests_tax', get_taxonomies( array( 'publicly_queryable' => false ) ) ); + + $t = self::factory()->term->create_and_get( array( + 'taxonomy' => 'wptests_tax', + ) ); + + $p = self::factory()->post->create(); + wp_set_object_terms( $p, $t->slug, 'wptests_tax' ); + + $this->go_to( '/?wptests_tax=' . $t->slug ); + + $this->assertFalse( is_tax( 'wptests_tax' ) ); + } + + /** + * @ticket 34491 + */ + public function test_private_taxonomy_should_be_overridden_by_publicly_queryable() { + register_taxonomy( 'wptests_tax', 'post', array( + 'public' => false, + 'publicly_queryable' => true, + ) ); + + $this->assertContains( 'wptests_tax', get_taxonomies( array( 'publicly_queryable' => true ) ) ); + + $t = self::factory()->term->create_and_get( array( + 'taxonomy' => 'wptests_tax', + ) ); + + $p = self::factory()->post->create(); + wp_set_object_terms( $p, $t->slug, 'wptests_tax' ); + + $this->go_to( '/?wptests_tax=' . $t->slug ); + + $this->assertTrue( is_tax( 'wptests_tax' ) ); + } + /** * @ticket 35089 */