diff --git a/src/wp-includes/canonical.php b/src/wp-includes/canonical.php index 9404ed6ea5..5e8efb0bae 100644 --- a/src/wp-includes/canonical.php +++ b/src/wp-includes/canonical.php @@ -331,7 +331,9 @@ function redirect_canonical( $requested_url = null, $do_redirect = true ) { $term_count = 0; foreach ( $wp_query->tax_query->queried_terms as $tax_query ) { - $term_count += count( $tax_query['terms'] ); + if ( isset( $tax_query['terms'] ) && is_countable( $tax_query['terms'] ) ) { + $term_count += count( $tax_query['terms'] ); + } } $obj = $wp_query->get_queried_object(); diff --git a/tests/phpunit/tests/canonical.php b/tests/phpunit/tests/canonical.php index 63e5c4078b..6d16402112 100644 --- a/tests/phpunit/tests/canonical.php +++ b/tests/phpunit/tests/canonical.php @@ -375,4 +375,31 @@ class Tests_Canonical extends WP_Canonical_UnitTestCase { delete_option( 'page_on_front' ); } + + /** + * Ensure NOT EXISTS queries do not trigger not-countable or undefined array key errors. + * + * @ticket 55955 + */ + public function test_feed_canonical_with_not_exists_query() { + // Set a NOT EXISTS tax_query on the global query. + $global_query = $GLOBALS['wp_query']; + $GLOBALS['wp_query'] = new WP_Query( + array( + 'post_type' => 'post', + 'tax_query' => array( + array( + 'taxonomy' => 'post_format', + 'operator' => 'NOT EXISTS', + ), + ), + ) + ); + + $url = redirect_canonical( get_term_feed_link( self::$terms['/category/parent/'] ), false ); + // Restore original global. + $GLOBALS['wp_query'] = $global_query; + + $this->assertNull( $url ); + } }