From c2fbd6cae189bb6f91fe89d1c38a343de6bd5779 Mon Sep 17 00:00:00 2001 From: Giuseppe Mazzapica Date: Thu, 15 Sep 2016 15:30:54 +0200 Subject: [PATCH 1/6] Update README with filtering documentation [ci skip] --- README.md | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/README.md b/README.md index ba3519b..a2a6c60 100644 --- a/README.md +++ b/README.md @@ -99,6 +99,39 @@ array( And if you compare this array with the [visual overview of template hierarchy](https://developer.wordpress.org/files/2014/10/template-hierarchy.png) you can see that is an accurate representation of the template hierarchy for a category query. +### Filter the Hierarchy + +Hierarchy provides a filter, `brain-hierarchy.branches` that allows to filter the branches that will +be used to when "resolving" a query. + +The filter passes the array of branches, where each item is a **class name** of an object implementing +`BranchInterface`. The array can be modified, but Hierarchy ensures that after the filter all the items +are still an array of the same type. + +Considering that changing the branch will break core compatibility (it is possible to obtain a +completely different template hierarchy compared to the one core uses) I suggest to use this feature +only if you are sure what you are going to do. + +It is also possible to avoid any filtering by instantiating `Hierachy` class with the `Hierachy::NOT_FILTERABLE` + flag. + +```php +$hierarchy = new Hierachy(Hierachy::NOT_FILTERABLE); +``` + +Note that this will prevent `Hierachy` to fire the core `{$type}_template_hierachy` filter (introduced in WP 4.7). + +This hook gives the ability to filter a specific "branch" of the template hierarchy. +See ["Make WordPress" blog post](https://make.wordpress.org/core/2016/09/09/new-functions-hooks-and-behaviour-for-theme-developers-in-wordpress-4-7/) +for more details. + +Let me just cite from there: + +> It’s important to remember that the consistency of the template hierarchy in WordPress is what +makes standardised theme structures possible. +It’s highly recommended that you do not remove templates from the candidate hierarchy using these +new filters, unless you’re absolutely certain of what you’re doing. + # Template Resolution From c1a8beffe53d3f9c2d01591bc8a94526515bd69b Mon Sep 17 00:00:00 2001 From: Giuseppe Mazzapica Date: Thu, 15 Sep 2016 15:33:53 +0200 Subject: [PATCH 2/6] Add missing link in README TOC [ci skip] --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index a2a6c60..239afba 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ Hierarchy - [What / Why?](#what--why) - [Template Hierarchy Representation](#template-hierarchy-representation) + - [Filter the Hierachy](#filter-the-hierarchy) - [Template Resolution](#templates-resolution) - [Template Resolution Example](#templates-resolution-example) - [Introducing `QueryTemplate`](#introducing-querytemplate) From bcdd745529a43fc68ae774ba9f68155e5742b95b Mon Sep 17 00:00:00 2001 From: Giuseppe Mazzapica Date: Mon, 11 Jun 2018 20:22:09 +0200 Subject: [PATCH 3/6] Add support for CPT post templates See #15 --- src/Branch/BranchPage.php | 28 ++- src/Branch/BranchSingle.php | 18 ++ src/PostTemplates.php | 75 +++++++ tests/src/Functional/HierarchyTest.php | 9 +- tests/src/Functional/QueryTemplateTest.php | 18 +- tests/src/Unit/Branch/BranchPageTest.php | 59 +++--- tests/src/Unit/Branch/BranchSingleTest.php | 39 +++- tests/src/Unit/PostTemplatesTest.php | 230 +++++++++++++++++++++ 8 files changed, 436 insertions(+), 40 deletions(-) create mode 100644 src/PostTemplates.php create mode 100644 tests/src/Unit/PostTemplatesTest.php diff --git a/src/Branch/BranchPage.php b/src/Branch/BranchPage.php index 0390e00..075ccbd 100644 --- a/src/Branch/BranchPage.php +++ b/src/Branch/BranchPage.php @@ -10,12 +10,28 @@ namespace Brain\Hierarchy\Branch; +use Brain\Hierarchy\PostTemplates; + /** * @author Giuseppe Mazzapica * @license http://opensource.org/licenses/MIT MIT */ final class BranchPage implements BranchInterface { + + /** + * @var \Brain\Hierarchy\PostTemplates + */ + private $postTemplates; + + /** + * @param \Brain\Hierarchy\PostTemplates|null $postTemplates + */ + public function __construct(PostTemplates $postTemplates = null) + { + $this->postTemplates = $postTemplates ?: new PostTemplates(); + } + /** * {@inheritdoc} */ @@ -53,15 +69,9 @@ public function leaves(\WP_Query $query) $post->ID and $leaves[] = "page-{$post->ID}"; $leaves[] = 'page'; - $template = ($post->ID && $post->post_type === 'page') - ? filter_var(get_page_template_slug($post), FILTER_SANITIZE_URL) - : false; - - if (!empty($template) && validate_file($template) === 0) { - $dir = dirname($template); - $filename = pathinfo($template, PATHINFO_FILENAME); - $name = $dir === '.' ? $filename : "{$dir}/{$filename}"; - array_unshift($leaves, $name); + if ($post->post_type === 'page') { + $template = $this->postTemplates->findFor($post); + $template and array_unshift($leaves, $template); } return $leaves; diff --git a/src/Branch/BranchSingle.php b/src/Branch/BranchSingle.php index 81217ca..a3eceae 100644 --- a/src/Branch/BranchSingle.php +++ b/src/Branch/BranchSingle.php @@ -10,12 +10,27 @@ namespace Brain\Hierarchy\Branch; +use Brain\Hierarchy\PostTemplates; + /** * @author Giuseppe Mazzapica * @license http://opensource.org/licenses/MIT MIT */ final class BranchSingle implements BranchInterface { + /** + * @var \Brain\Hierarchy\PostTemplates + */ + private $postTemplates; + + /** + * @param \Brain\Hierarchy\PostTemplates|null $postTemplates + */ + public function __construct(PostTemplates $postTemplates = null) + { + $this->postTemplates = $postTemplates ?: new PostTemplates(); + } + /** * {@inheritdoc} */ @@ -54,6 +69,9 @@ public function leaves(\WP_Query $query) array_unshift($leaves, "single-{$post->post_type}-{$decoded}"); } + $template = $this->postTemplates->findFor($post); + $template and array_unshift($leaves, $template); + return $leaves; } } diff --git a/src/PostTemplates.php b/src/PostTemplates.php new file mode 100644 index 0000000..4e6d4fe --- /dev/null +++ b/src/PostTemplates.php @@ -0,0 +1,75 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Brain\Hierarchy; + +/** + * @author Giuseppe Mazzapica + * @license http://opensource.org/licenses/MIT MIT + */ +class PostTemplates +{ + + /** + * @var array[] + */ + private $templates = []; + + /** + * @param \WP_Post $post + * @return string + */ + public function findFor(\WP_Post $post) + { + if (!$post->ID || !$post->post_type) { + return ''; + } + + $stored = filter_var(get_page_template_slug($post), FILTER_SANITIZE_URL); + if (!$stored || validate_file($stored) !== 0) { + return ''; + } + + $stored = wp_normalize_path($stored); + $templates = $this->templatesForType($post->post_type); + + foreach ($templates as $template) { + if ($template === $stored) { + $dir = dirname($template); + $filename = pathinfo($template, PATHINFO_FILENAME); + + return $dir === '.' ? $filename : "{$dir}/{$filename}"; + } + } + + return ''; + } + + /** + * @param string $postType + * @return string[] + */ + private function templatesForType($postType) + { + if (array_key_exists($postType, $this->templates)) { + return $this->templates[$postType]; + } + + $this->templates[$postType] = []; + $templates = (array)wp_get_theme()->get_page_templates(null, $postType); + foreach ($templates as $template => $header) { + if ($template && is_string($template)) { + $this->templates[$postType][] = wp_normalize_path($template); + } + } + + return $this->templates[$postType]; + } +} diff --git a/tests/src/Functional/HierarchyTest.php b/tests/src/Functional/HierarchyTest.php index 910e22f..9dd243d 100644 --- a/tests/src/Functional/HierarchyTest.php +++ b/tests/src/Functional/HierarchyTest.php @@ -12,6 +12,7 @@ use Brain\Hierarchy\Hierarchy; use Brain\Hierarchy\Tests\TestCase; +use Brain\Monkey\Functions; use Brain\Monkey\WP\Filters; /** @@ -29,6 +30,8 @@ public function testGetHierarchy() $post->post_name = '%E3%81%B2%E3%82%89'; $post->post_type = 'book'; + Functions::when('get_page_template_slug')->justReturn(false); + $query = new \WP_Query( ['is_single' => true, 'is_singular' => true], $post, @@ -75,6 +78,8 @@ public function testGetHierarchyFiltered() return $leaves; }); + Functions::when('get_page_template_slug')->justReturn(false); + $post = \Mockery::mock('WP_Post'); $post->ID = 1; $post->post_name = '%E3%81%B2%E3%82%89'; @@ -116,6 +121,8 @@ public function testGetHierarchyNotAppliesFiltersIfNotFiltered() return $leaves; }); + Functions::when('get_page_template_slug')->justReturn(false); + $post = \Mockery::mock('WP_Post'); $post->ID = 1; $post->post_name = '%E3%81%B2%E3%82%89'; @@ -148,4 +155,4 @@ public function testGetHierarchyNotAppliesFiltersIfNotFiltered() $this->assertSame($expected, $actual); } -} \ No newline at end of file +} diff --git a/tests/src/Functional/QueryTemplateTest.php b/tests/src/Functional/QueryTemplateTest.php index 28a5445..9e33c22 100644 --- a/tests/src/Functional/QueryTemplateTest.php +++ b/tests/src/Functional/QueryTemplateTest.php @@ -32,8 +32,22 @@ public function testLoadPageCustom() $post->post_name = 'a-page'; $post->post_type = 'page'; - Functions::expect('get_page_template_slug')->with($post)->andReturn('page-templates/page-custom.php'); - Functions::expect('validate_file')->with('page-templates/page-custom.php')->andReturn(0); + $theme = Mockery::mock('\WP_Theme'); + $theme + ->shouldReceive('get_page_templates') + ->andReturn(['page-templates/page-custom.php' => 'Custom']); + + Functions::expect('wp_get_theme')->andReturn($theme); + + Functions::expect('get_page_template_slug') + ->with($post) + ->andReturn('page-templates/page-custom.php'); + Functions::expect('validate_file') + ->with('page-templates/page-custom.php') + ->andReturn(0); + Functions::expect('wp_normalize_path') + ->with('page-templates/page-custom.php') + ->andReturn('page-templates/page-custom.php'); $wpQuery = new \WP_Query(['is_page' => true], $post, ['pagename' => 'a-page']); diff --git a/tests/src/Unit/Branch/BranchPageTest.php b/tests/src/Unit/Branch/BranchPageTest.php index 2bfd130..09101c7 100644 --- a/tests/src/Unit/Branch/BranchPageTest.php +++ b/tests/src/Unit/Branch/BranchPageTest.php @@ -10,6 +10,7 @@ namespace Brain\Hierarchy\Tests\Unit\Branch; +use Brain\Hierarchy\PostTemplates; use Brain\Monkey\Functions; use Brain\Hierarchy\Branch\BranchPage; use Brain\Hierarchy\Tests\TestCase; @@ -57,10 +58,16 @@ public function testLeavesPage() $post->post_name = 'foo'; $post->post_type = 'page'; + $postTemplates = Mockery::mock(PostTemplates::class); + $postTemplates + ->shouldReceive('findFor') + ->once() + ->with($post) + ->andReturn(''); + $query = new \WP_Query([], $post, ['pagename' => '']); - Functions::expect('get_page_template_slug')->with($post)->andReturn(''); - $branch = new BranchPage(); + $branch = new BranchPage($postTemplates); assertSame(['page-foo', 'page-1', 'page'], $branch->leaves($query)); } @@ -71,10 +78,16 @@ public function testLeavesPagePagename() $post->post_name = 'foo'; $post->post_type = 'page'; + $postTemplates = Mockery::mock(PostTemplates::class); + $postTemplates + ->shouldReceive('findFor') + ->once() + ->with($post) + ->andReturn(''); + $query = new \WP_Query([], $post, ['pagename' => 'bar']); - Functions::expect('get_page_template_slug')->with($post)->andReturn(''); - $branch = new BranchPage(); + $branch = new BranchPage($postTemplates); assertSame(['page-bar', 'page-1', 'page'], $branch->leaves($query)); } @@ -86,11 +99,16 @@ public function testLeavesPagePagenameTemplate() $post->post_name = 'foo'; $post->post_type = 'page'; + $postTemplates = Mockery::mock(PostTemplates::class); + $postTemplates + ->shouldReceive('findFor') + ->once() + ->with($post) + ->andReturn('page-meh'); + $query = new \WP_Query([], $post, ['pagename' => 'bar']); - Functions::expect('get_page_template_slug')->with($post)->andReturn('page-meh.php'); - Functions::expect('validate_file')->with('page-meh.php')->andReturn(0); - $branch = new BranchPage(); + $branch = new BranchPage($postTemplates); assertSame(['page-meh', 'page-bar', 'page-1', 'page'], $branch->leaves($query)); } @@ -103,29 +121,18 @@ public function testLeavesPagePagenameTemplateFolder() $post->post_type = 'page'; $query = new \WP_Query([], $post, ['pagename' => 'bar']); - Functions::expect('get_page_template_slug')->with($post)->andReturn('page-templates/page-meh.php'); - Functions::expect('validate_file')->with('page-templates/page-meh.php')->andReturn(0); - $branch = new BranchPage(); + $postTemplates = Mockery::mock(PostTemplates::class); + $postTemplates + ->shouldReceive('findFor') + ->once() + ->with($post) + ->andReturn('page-templates/page-meh'); + + $branch = new BranchPage($postTemplates); $expected = ['page-templates/page-meh', 'page-bar', 'page-1', 'page']; assertSame($expected, $branch->leaves($query)); } - - public function testLeavesPagePagenameTemplateNoValidate() - { - $post = Mockery::mock('\WP_Post'); - $post->ID = 1; - $post->post_name = 'foo'; - $post->post_type = 'page'; - - $query = new \WP_Query([], $post, ['pagename' => 'bar']); - Functions::expect('get_page_template_slug')->with($post)->andReturn('page-meh.php'); - Functions::expect('validate_file')->with('page-meh.php')->andReturn(1); - - $branch = new BranchPage(); - - assertSame(['page-bar', 'page-1', 'page'], $branch->leaves($query)); - } } diff --git a/tests/src/Unit/Branch/BranchSingleTest.php b/tests/src/Unit/Branch/BranchSingleTest.php index 568d25d..f3cb56e 100644 --- a/tests/src/Unit/Branch/BranchSingleTest.php +++ b/tests/src/Unit/Branch/BranchSingleTest.php @@ -11,6 +11,7 @@ namespace Brain\Hierarchy\Tests\Unit\Branch; use Brain\Hierarchy\Branch\BranchSingle; +use Brain\Hierarchy\PostTemplates; use Brain\Hierarchy\Tests\TestCase; use Mockery; @@ -33,7 +34,7 @@ public function testLeavesNoPost() assertSame(['single'], $branch->leaves($query)); } - public function testLeaves() + public function testLeavesNoTemplate() { $post = Mockery::mock('\WP_Post'); $post->ID = 123; @@ -41,9 +42,43 @@ public function testLeaves() $post->post_type = 'my_cpt'; $query = new \WP_Query([], $post); - $branch = new BranchSingle(); + $postTemplates = Mockery::mock(PostTemplates::class); + $postTemplates + ->shouldReceive('findFor') + ->once() + ->with($post) + ->andReturn(''); + + $branch = new BranchSingle($postTemplates); + + $expected = [ + 'single-my_cpt-one_two_three', + 'single-my_cpt', + 'single' + ]; + + assertSame($expected, $branch->leaves($query)); + } + + public function testLeavesPostTemplate() + { + $post = Mockery::mock('\WP_Post'); + $post->ID = 123; + $post->post_name = 'one_two_three'; + $post->post_type = 'my_cpt'; + $query = new \WP_Query([], $post); + + $postTemplates = Mockery::mock(PostTemplates::class); + $postTemplates + ->shouldReceive('findFor') + ->once() + ->with($post) + ->andReturn('templates/foo'); + + $branch = new BranchSingle($postTemplates); $expected = [ + 'templates/foo', 'single-my_cpt-one_two_three', 'single-my_cpt', 'single' diff --git a/tests/src/Unit/PostTemplatesTest.php b/tests/src/Unit/PostTemplatesTest.php new file mode 100644 index 0000000..1718552 --- /dev/null +++ b/tests/src/Unit/PostTemplatesTest.php @@ -0,0 +1,230 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Brain\Hierarchy\Tests\Unit; + + +use Brain\Hierarchy\PostTemplates; +use Brain\Hierarchy\Tests\TestCase; +use Brain\Monkey\Functions; + +/** + * @author Giuseppe Mazzapica + * @license http://opensource.org/licenses/MIT MIT + */ +class PostTemplatesTest extends TestCase +{ + + public function testEmptyPostReturnEmptyString() + { + $postTemplates = new PostTemplates(); + + $post = \Mockery::mock(\WP_Post::class); + $post->ID = ''; + $post->post_type = ''; + + static::assertSame('', $postTemplates->findFor($post)); + } + + public function testPostWithoutTemplateReturnEmptyString() + { + $postTemplates = new PostTemplates(); + + $post = \Mockery::mock(\WP_Post::class); + $post->ID = 123; + $post->post_type = 'event'; + + Functions::expect('get_page_template_slug') + ->once() + ->with($post) + ->andReturn(false); + + static::assertSame('', $postTemplates->findFor($post)); + } + + public function testPostWithUnexistentTemplateReturnEmptyString() + { + $postTemplates = new PostTemplates(); + + $post = \Mockery::mock(\WP_Post::class); + $post->ID = 123; + $post->post_type = 'event'; + + Functions::expect('get_page_template_slug') + ->once() + ->with($post) + ->andReturn('foo.php'); + + Functions::expect('wp_normalize_path') + ->once() + ->with('foo.php') + ->andReturn('foo.php'); + + Functions::expect('wp_normalize_path') + ->once() + ->with('bar.php') + ->andReturn('bar.php'); + + Functions::expect('validate_file') + ->once() + ->with('foo.php') + ->andReturn(0); + + $theme = \Mockery::mock(\WP_Theme::class); + $theme->shouldReceive('get_page_templates') + ->once() + ->with(null, 'event') + ->andReturn(['bar.php' => 'Bar']); + + Functions::expect('wp_get_theme') + ->once() + ->andReturn($theme); + + static::assertSame('', $postTemplates->findFor($post)); + } + + public function testPostWithValidTemplateReturnItsName() + { + $postTemplates = new PostTemplates(); + + $post = \Mockery::mock(\WP_Post::class); + $post->ID = 123; + $post->post_type = 'event'; + + Functions::expect('get_page_template_slug') + ->once() + ->with($post) + ->andReturn('foo.php'); + + Functions::expect('wp_normalize_path') + ->atLeast() + ->once() + ->with('foo.php') + ->andReturn('foo.php'); + + Functions::expect('wp_normalize_path') + ->atLeast() + ->once() + ->with('bar.php') + ->andReturn('bar.php'); + + Functions::expect('validate_file') + ->atLeast() + ->once() + ->with('foo.php') + ->andReturn(0); + + $theme = \Mockery::mock(\WP_Theme::class); + $theme->shouldReceive('get_page_templates') + ->once() + ->with(null, 'event') + ->andReturn(['foo.php' => 'Foo', 'bar.php' => 'Bar']); + + Functions::expect('wp_get_theme') + ->once() + ->andReturn($theme); + + static::assertSame('foo', $postTemplates->findFor($post)); + } + + public function testPostWithValidTemplateReturnItsNameAndDir() + { + $postTemplates = new PostTemplates(); + + $post = \Mockery::mock(\WP_Post::class); + $post->ID = 123; + $post->post_type = 'event'; + + Functions::expect('get_page_template_slug') + ->once() + ->with($post) + ->andReturn('path/foo.php'); + + Functions::expect('wp_normalize_path') + ->atLeast() + ->once() + ->with('path/foo.php') + ->andReturn('path/foo.php'); + + Functions::expect('wp_normalize_path') + ->atLeast() + ->once() + ->with('bar.php') + ->andReturn('bar.php'); + + Functions::expect('validate_file') + ->atLeast() + ->once() + ->with('path/foo.php') + ->andReturn(0); + + $theme = \Mockery::mock(\WP_Theme::class); + $theme->shouldReceive('get_page_templates') + ->once() + ->with(null, 'event') + ->andReturn(['path/foo.php' => 'Foo', 'bar.php' => 'Bar']); + + Functions::expect('wp_get_theme') + ->once() + ->andReturn($theme); + + static::assertSame('path/foo', $postTemplates->findFor($post)); + } + + public function testTemplatesAreReadOnceFromTheme() + { + $postTemplates = new PostTemplates(); + + $post = \Mockery::mock(\WP_Post::class); + $post->ID = 123; + $post->post_type = 'event'; + + Functions::expect('get_page_template_slug') + ->atLeast() + ->once() + ->with($post) + ->andReturn('path/foo.php'); + + Functions::expect('wp_normalize_path') + ->atLeast() + ->once() + ->with('path/foo.php') + ->andReturn('path/foo.php'); + + Functions::expect('wp_normalize_path') + ->atLeast() + ->once() + ->with('bar.php') + ->andReturn('bar.php'); + + Functions::expect('validate_file') + ->atLeast() + ->once() + ->with('path/foo.php') + ->andReturn(0); + + $theme = \Mockery::mock(\WP_Theme::class); + $theme->shouldReceive('get_page_templates') + ->once() + ->with(null, 'event') + ->andReturn(['path/foo.php' => 'Foo', 'bar.php' => 'Bar']); + + Functions::expect('wp_get_theme') + ->once() + ->andReturn($theme); + + $postTemplates->findFor($post); + $postTemplates->findFor($post); + $postTemplates->findFor($post); + $postTemplates->findFor($post); + + static::assertSame('path/foo', $postTemplates->findFor($post)); + } +} From 5eabd7c6083e782654b439530bd737d713598ae6 Mon Sep 17 00:00:00 2001 From: Giuseppe Mazzapica Date: Mon, 11 Jun 2018 20:25:16 +0200 Subject: [PATCH 4/6] Add tests for 7.1 and 7.2 --- .travis.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 13e4851..b75e31c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,8 @@ php: - 5.5 - 5.6 - 7.0 + - 7.1 + - 7.2 - hhvm matrix: @@ -18,4 +20,4 @@ script: - php vendor/bin/phpunit -c phpunit.xml.dist after_success: - - bash <(curl -s https://codecov.io/bash) \ No newline at end of file + - bash <(curl -s https://codecov.io/bash) From 3634a94819a7496b3c041214bd07d594d6015127 Mon Sep 17 00:00:00 2001 From: Giuseppe Mazzapica Date: Fri, 28 Sep 2018 18:21:45 +0200 Subject: [PATCH 5/6] Tpate page template is took into account even when no pagename See #16 --- src/Branch/BranchPage.php | 27 +++++++++++----------- tests/src/Functional/QueryTemplateTest.php | 3 +++ tests/src/Unit/Branch/BranchPageTest.php | 27 ++++++++++++++++++++++ 3 files changed, 44 insertions(+), 13 deletions(-) diff --git a/src/Branch/BranchPage.php b/src/Branch/BranchPage.php index 075ccbd..2bafe8a 100644 --- a/src/Branch/BranchPage.php +++ b/src/Branch/BranchPage.php @@ -55,25 +55,26 @@ public function leaves(\WP_Query $query) { /** @var \WP_Post $post */ $post = $query->get_queried_object(); - $post instanceof \WP_Post or $post = new \WP_Post((object) ['ID' => 0]); - $pagename = $query->get('pagename'); - if (empty($post->post_name) && empty($pagename)) { - return ['page']; - } + $template = $this->postTemplates->findFor($post); + $pagename = $query->get('pagename'); + (!$pagename && $post->ID) and $pagename = $post->post_name; - $name = $pagename ? $pagename : $post->post_name; + $leaves = $template ? [$template] : []; + $baseLeaves = $post->ID ? ["page-{$post->ID}", 'page'] : ['page']; - $leaves = ["page-{$name}"]; - $post->ID and $leaves[] = "page-{$post->ID}"; - $leaves[] = 'page'; + if (!$pagename) { + return array_merge($leaves, $baseLeaves); + } - if ($post->post_type === 'page') { - $template = $this->postTemplates->findFor($post); - $template and array_unshift($leaves, $template); + $pagenameDecoded = urldecode($pagename); + if ($pagenameDecoded !== $pagename) { + $leaves[] = "page-{$pagenameDecoded}"; } - return $leaves; + $leaves[] = "page-{$pagename}"; + + return array_merge($leaves, $baseLeaves); } } diff --git a/tests/src/Functional/QueryTemplateTest.php b/tests/src/Functional/QueryTemplateTest.php index 9e33c22..91bd46e 100644 --- a/tests/src/Functional/QueryTemplateTest.php +++ b/tests/src/Functional/QueryTemplateTest.php @@ -62,6 +62,9 @@ public function testLoadPageSingular() $post = Mockery::mock('\WP_Post'); $post->ID = 1; $post->post_type = 'page'; + $post->post_name = 'foo'; + + Functions::expect('get_page_template_slug')->with($post)->andReturn(''); $wpQuery = new \WP_Query(['is_page' => true, 'is_singular' => true], $post); diff --git a/tests/src/Unit/Branch/BranchPageTest.php b/tests/src/Unit/Branch/BranchPageTest.php index 09101c7..2625a0a 100644 --- a/tests/src/Unit/Branch/BranchPageTest.php +++ b/tests/src/Unit/Branch/BranchPageTest.php @@ -22,6 +22,7 @@ */ final class BranchPageTest extends TestCase { + public function testLeavesNoPageNoPagename() { $post = Mockery::mock('\WP_Post'); @@ -135,4 +136,30 @@ public function testLeavesPagePagenameTemplateFolder() assertSame($expected, $branch->leaves($query)); } + + public function testPageNameReturnTemplateIfNoPagename() + { + Functions::when('sanitize_title')->alias('strtolower'); + + $post = Mockery::mock('\WP_Post'); + $post->ID = 1; + $post->post_name = ''; + $post->post_title = 'foo'; + $post->post_type = 'page'; + + $query = new \WP_Query(['is_preview' => true], $post, ['page_id' => 1, 'pagename' => '']); + + $postTemplates = Mockery::mock(PostTemplates::class); + $postTemplates + ->shouldReceive('findFor') + ->once() + ->with($post) + ->andReturn('page-foo'); + + $branch = new BranchPage($postTemplates); + + $expected = ['page-foo', 'page-1', 'page']; + + assertSame($expected, $branch->leaves($query)); + } } From a6c0251b4e56c36af2cee0171918e5a88614dae2 Mon Sep 17 00:00:00 2001 From: Stefan Lindberg Date: Fri, 28 Sep 2018 22:20:25 +0200 Subject: [PATCH 6/6] =?UTF-8?q?Fix=20templateForType=20not=20matching=20$s?= =?UTF-8?q?tored=20when=20using=20=C3=A5=C3=A4=C3=B6=20in=20template=20fil?= =?UTF-8?q?e=20name=20on=20custom=20post=20type?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/PostTemplates.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/PostTemplates.php b/src/PostTemplates.php index 4e6d4fe..2fe892c 100644 --- a/src/PostTemplates.php +++ b/src/PostTemplates.php @@ -66,7 +66,8 @@ private function templatesForType($postType) $templates = (array)wp_get_theme()->get_page_templates(null, $postType); foreach ($templates as $template => $header) { if ($template && is_string($template)) { - $this->templates[$postType][] = wp_normalize_path($template); + $sanitized = filter_var($template, FILTER_SANITIZE_URL); + $this->templates[$postType][] = wp_normalize_path($sanitized); } }