From 2c1b7182775311719ec25e8dda1a83b85f38b9e5 Mon Sep 17 00:00:00 2001 From: Wybe Date: Thu, 27 Aug 2026 16:40:56 +0200 Subject: [PATCH 1/2] fix: limit children query to published posts --- src/PostData.php | 1 + tests/TestCase.php | 1 + tests/src/PostDataTest.php | 50 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+) diff --git a/src/PostData.php b/src/PostData.php index 2c4d0d7..31005b8 100644 --- a/src/PostData.php +++ b/src/PostData.php @@ -289,6 +289,7 @@ public function children(array $args = []): Collection $args = wp_parse_args($args, [ 'post_parent' => $this->id, 'post_type' => $this->postType, + 'post_status' => 'publish', 'order' => 'ASC', 'orderby' => 'menu_order', ]); diff --git a/tests/TestCase.php b/tests/TestCase.php index 2edd5f5..eec1a49 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -34,6 +34,7 @@ protected function tearDown(): void protected function getPackageProviders($app) { return [ + 'Spatie\LaravelData\LaravelDataServiceProvider', 'Yard\Data\Providers\DataServiceProvider', ]; } diff --git a/tests/src/PostDataTest.php b/tests/src/PostDataTest.php index fdb9cb6..7864051 100644 --- a/tests/src/PostDataTest.php +++ b/tests/src/PostDataTest.php @@ -59,3 +59,53 @@ expect($this->postData->url())->toBe(''); }); + +it('only queries published children', function () { + \WP_Mock::userFunction('is_post_type_hierarchical', [ + 'args' => ['post'], + 'return' => true, + ]); + + \WP_Mock::userFunction('wp_parse_args', [ + 'return' => fn (array $args, array $defaults): array => array_merge($defaults, $args), + ]); + + $queried = []; + + \WP_Mock::userFunction('get_children', [ + 'return' => function (array $args) use (&$queried): array { + $queried = $args; + + return []; + }, + ]); + + $this->postData->children(); + + expect($queried['post_status'])->toBe('publish'); +}); + +it('lets callers override the child post status', function () { + \WP_Mock::userFunction('is_post_type_hierarchical', [ + 'args' => ['post'], + 'return' => true, + ]); + + \WP_Mock::userFunction('wp_parse_args', [ + 'return' => fn (array $args, array $defaults): array => array_merge($defaults, $args), + ]); + + $queried = []; + + \WP_Mock::userFunction('get_children', [ + 'return' => function (array $args) use (&$queried): array { + $queried = $args; + + return []; + }, + ]); + + $this->postData->children(['post_status' => 'any']); + + expect($queried['post_status'])->toBe('any'); +}); From 3a3a67cacaa68e08c3d6de173256b8ad8db887f0 Mon Sep 17 00:00:00 2001 From: Wybe Date: Thu, 27 Aug 2026 16:40:57 +0200 Subject: [PATCH 2/2] fix: treat an unpublished parent as no parent --- src/PostData.php | 2 +- tests/src/PostDataTest.php | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/PostData.php b/src/PostData.php index 31005b8..799e267 100644 --- a/src/PostData.php +++ b/src/PostData.php @@ -309,7 +309,7 @@ public function parent(): ?static return null; } $parent = get_post_parent($this->id); - if (null === $parent) { + if (null === $parent || 'publish' !== $parent->post_status) { return null; } diff --git a/tests/src/PostDataTest.php b/tests/src/PostDataTest.php index 7864051..9f491f2 100644 --- a/tests/src/PostDataTest.php +++ b/tests/src/PostDataTest.php @@ -109,3 +109,18 @@ expect($queried['post_status'])->toBe('any'); }); + +it('has no parent when the parent is not published', function () { + \WP_Mock::userFunction('is_post_type_hierarchical', [ + 'args' => ['post'], + 'return' => true, + ]); + + \WP_Mock::userFunction('get_post_parent', [ + 'args' => [1], + 'return' => (object) ['ID' => 2, 'post_status' => 'draft'], + ]); + + expect($this->postData->parent())->toBeNull(); + expect($this->postData->isChild())->toBeFalse(); +});