From e16274f006d6083ed5146a53738299f0a8a45f4f Mon Sep 17 00:00:00 2001 From: Lucas Carvalho Date: Wed, 31 Dec 2025 16:53:59 -0300 Subject: [PATCH 1/3] Enhancement: Refactor `locate_template` to support customizable template paths. This update introduces a new filter, `locate_template_paths`, allowing developers to modify the array of template paths used in the `locate_template` function. The existing logic has been streamlined to iterate over these paths, improving flexibility and maintainability. Additionally, a new unit test has been added to verify the functionality of the filter, ensuring that templates can be located from custom directories. --- src/wp-includes/template.php | 37 ++++++++++++++++++------ tests/phpunit/tests/template.php | 48 ++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 9 deletions(-) diff --git a/src/wp-includes/template.php b/src/wp-includes/template.php index 81b35fadf4883..7f07589f41047 100644 --- a/src/wp-includes/template.php +++ b/src/wp-includes/template.php @@ -728,20 +728,39 @@ function locate_template( $template_names, $load = false, $load_once = true, $ar $is_child_theme = is_child_theme(); + $template_paths = array( + $wp_stylesheet_path, + $is_child_theme ? $wp_template_path : null, + ABSPATH . WPINC . '/theme-compat/', + ); + + $template_paths = array_filter( $template_paths ); + + /** + * Filters the template paths. + * + * @param array $template_paths The template paths. + * @return array The filtered template paths. + */ + $template_paths = apply_filters( 'locate_template_paths', $template_paths ); + $located = ''; foreach ( (array) $template_names as $template_name ) { if ( ! $template_name ) { continue; } - if ( file_exists( $wp_stylesheet_path . '/' . $template_name ) ) { - $located = $wp_stylesheet_path . '/' . $template_name; - break; - } elseif ( $is_child_theme && file_exists( $wp_template_path . '/' . $template_name ) ) { - $located = $wp_template_path . '/' . $template_name; - break; - } elseif ( file_exists( ABSPATH . WPINC . '/theme-compat/' . $template_name ) ) { - $located = ABSPATH . WPINC . '/theme-compat/' . $template_name; - break; + + foreach ( $template_paths as $template_path ) { + if ( ! is_string( $template_path ) || '' === $template_path ) { + continue; + } + + $file = rtrim( $template_path, '/' ) . '/' . $template_name; + + if ( file_exists( $file ) ) { + $located = $file; + break 2; + } } } diff --git a/tests/phpunit/tests/template.php b/tests/phpunit/tests/template.php index a965665360b05..0f8d0b4102cde 100644 --- a/tests/phpunit/tests/template.php +++ b/tests/phpunit/tests/template.php @@ -555,6 +555,54 @@ public function test_locate_template_uses_current_theme() { $this->assertSame( $new_theme->get_stylesheet_directory() . '/index.php', locate_template( $template_names ), 'Incorrect index template found in theme after switch.' ); } + /** + * Tests that the `locate_template_paths` filter allows modifying template paths. + * + * @group themes + * @covers ::locate_template + */ + public function test_locate_template_paths_filter() { + // Create a temporary directory. + $temp_file = wp_tempnam(); + unlink( $temp_file ); + + $temp_dir = $temp_file . '-templates'; + wp_mkdir_p( $temp_dir ); + + // Create a test template file. + $template_name = 'test-custom-template.php'; + $template_path = trailingslashit( $temp_dir ) . $template_name; + + file_put_contents( $template_path, "assertSame( + $template_path, + $located, + 'Template should be located in the directory added via locate_template_paths filter.' + ); + + remove_filter( 'locate_template_paths', $filter_callback ); + + $located_after_removal = locate_template( array( $template_name ) ); + $this->assertSame( + '', + $located_after_removal, + 'Template should not be located once the filter is removed.' + ); + + // Cleanup. + unlink( $template_path ); + rmdir( $temp_dir ); + } + /** * Tests that wp_start_template_enhancement_output_buffer() does not start a buffer in a block theme when no filters are present. * From 8b5a49ab1f869fc090a4c0ee28756f86b4ec1b8d Mon Sep 17 00:00:00 2001 From: Lucas Carvalho Date: Wed, 31 Dec 2025 17:48:20 -0300 Subject: [PATCH 2/3] Fix: Adjust formatting of the filter callback in template tests. --- tests/phpunit/tests/template.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/phpunit/tests/template.php b/tests/phpunit/tests/template.php index 0f8d0b4102cde..aa308c729f681 100644 --- a/tests/phpunit/tests/template.php +++ b/tests/phpunit/tests/template.php @@ -575,7 +575,7 @@ public function test_locate_template_paths_filter() { file_put_contents( $template_path, " Date: Fri, 2 Jan 2026 10:14:09 -0300 Subject: [PATCH 3/3] Update src/wp-includes/template.php Co-authored-by: Mukesh Panchal --- src/wp-includes/template.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/wp-includes/template.php b/src/wp-includes/template.php index 7f07589f41047..9d42fb238c951 100644 --- a/src/wp-includes/template.php +++ b/src/wp-includes/template.php @@ -740,7 +740,6 @@ function locate_template( $template_names, $load = false, $load_once = true, $ar * Filters the template paths. * * @param array $template_paths The template paths. - * @return array The filtered template paths. */ $template_paths = apply_filters( 'locate_template_paths', $template_paths );