diff --git a/src/DataObject/DataObjectDocument.php b/src/DataObject/DataObjectDocument.php index ebc8254..6d43004 100644 --- a/src/DataObject/DataObjectDocument.php +++ b/src/DataObject/DataObjectDocument.php @@ -121,8 +121,19 @@ public function shouldIndex(): bool $dataObject = $this->getDataObject(); // If an anonymous user can't view it - $isPublic = Member::actAs(null, function () use ($dataObject) { - return $dataObject->canView(); + $isPublic = Member::actAs(null, static function () use ($dataObject) { + // Need to make sure that the version of the DataObject that we access is always the LIVE version + return Versioned::withVersionedMode(static function () use ($dataObject): bool { + Versioned::set_stage(Versioned::LIVE); + + $liveDataObject = DataObject::get($dataObject->ClassName)->byID($dataObject->ID); + + if (!$liveDataObject || !$liveDataObject->exists()) { + return false; + } + + return $liveDataObject->canView(); + }); }); if (!$isPublic) { diff --git a/tests/DataObject/DataObjectDocumentTest.php b/tests/DataObject/DataObjectDocumentTest.php index 350c3df..a297f88 100644 --- a/tests/DataObject/DataObjectDocumentTest.php +++ b/tests/DataObject/DataObjectDocumentTest.php @@ -2,6 +2,7 @@ namespace SilverStripe\SearchService\Tests\DataObject; +use Page; use SilverStripe\ORM\DataObject; use SilverStripe\ORM\FieldType\DBDatetime; use SilverStripe\ORM\RelationList; @@ -22,7 +23,14 @@ class DataObjectDocumentTest extends SearchServiceTest { - protected static $fixture_file = '../fixtures.yml'; // phpcs:ignore + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.PropertyTypeHint.MissingNativeTypeHint + * @var array + */ + protected static $fixture_file = [ + '../fixtures.yml', + '../pages.yml', + ]; /** * @phpcsSuppress SlevomatCodingStandard.TypeHints.PropertyTypeHint.MissingNativeTypeHint @@ -64,6 +72,22 @@ public function testShouldIndex(): void $docTwo = DataObjectDocument::create($dataObjectTwo); $docThree = DataObjectDocument::create($dataObjectThree); + // Add all three documents to our indexes, as this isn't the functionality we're testing here + $config->set( + 'getIndexesForDocument', + [ + $docOne->getIdentifier() => [ + 'index' => 'data', + ], + $docTwo->getIdentifier() => [ + 'index' => 'data', + ], + $docThree->getIdentifier() => [ + 'index' => 'data', + ], + ] + ); + // All should be unavailable to index initially $this->assertFalse($docOne->shouldIndex()); $this->assertFalse($docTwo->shouldIndex()); @@ -81,12 +105,6 @@ public function testShouldIndex(): void $docOne = DataObjectDocument::create($dataObjectOne); $docTwo = DataObjectDocument::create($dataObjectTwo); - $config->set('getIndexesForDocument', [ - $docOne->getIdentifier() => [ - 'index' => 'data', - ], - ]); - // Document one should be indexable (as it's published and has ShowInSearch: 1) $this->assertTrue($docOne->shouldIndex()); // Document two should NOT be indexable (it's published but has ShowInSearch: 0) @@ -95,6 +113,68 @@ public function testShouldIndex(): void $this->assertFalse($docThree->shouldIndex()); } + public function testShouldIndexChild(): void + { + $config = $this->mockConfig(); + + $parent = $this->objFromFixture(Page::class, 'page1'); + // Make sure our Parent is published before we fetch our child pages + $parent->publishRecursive(); + + $childOne = $this->objFromFixture(Page::class, 'page2'); + $childTwo = $this->objFromFixture(Page::class, 'page3'); + $childThree = $this->objFromFixture(Page::class, 'page5'); + + // Publish childOne and childThree + $childOne->publishRecursive(); + $childThree->publishRecursive(); + // Need to re-fetch childOne and childThree so that our Versioned state is up-to-date with what we just + // published + $childOne = $this->objFromFixture(Page::class, 'page2'); + $childThree = $this->objFromFixture(Page::class, 'page5'); + + // $docOne has a published page + $docOne = DataObjectDocument::create($childOne); + // $docTwo has an unpublished page + $docTwo = DataObjectDocument::create($childTwo); + // $docThree has a published page + $docThree = DataObjectDocument::create($childThree); + + // Add both documents to our indexes, as this isn't the functionality we're testing here + $config->set( + 'getIndexesForDocument', + [ + $docOne->getIdentifier() => [ + 'index' => 'data', + ], + $docTwo->getIdentifier() => [ + 'index' => 'data', + ], + $docThree->getIdentifier() => [ + 'index' => 'data', + ], + ] + ); + + // Our parent page has been published, and so has our child page, so this should be indexable + $this->assertTrue($docOne->shouldIndex()); + // Our parent page has been published, but the child has not + $this->assertFalse($docTwo->shouldIndex()); + // Our parent page is not published, even though the child is + $this->assertFalse($docThree->shouldIndex()); + + // Now trigger a change on our parent page (so that the draft and live versions no longer match) + $parent->Title = 'Parent Page Changed'; + $parent->write(); + + // Need to re-fetch childOne so that we re-fetch the Parent when we request canView() + $childOne = $this->objFromFixture(Page::class, 'page2'); + // Recreate the Document with our new child page + $docOne = DataObjectDocument::create($childOne); + // Check that our child page is still indexable, even after our parent page was given a different draft version + $this->assertTrue($docOne->shouldIndex()); + } + public function testMarkIndexed(): void { $dataobject = new DataObjectFake(['ShowInSearch' => true]); diff --git a/tests/pages.yml b/tests/pages.yml new file mode 100644 index 0000000..96423ea --- /dev/null +++ b/tests/pages.yml @@ -0,0 +1,19 @@ +Page: + page1: + Title: Parent Page + ShowInSearch: 1 + page2: + Title: Child Page 1 + Parent: =>Page.page1 + ShowInSearch: 1 + page3: + Title: Child Page 2 + Parent: =>Page.page1 + ShowInSearch: 1 + page4: + Title: Parent Page 2 + ShowInSearch: 1 + page5: + Title: Child Page 3 + Parent: =>Page.page4 + ShowInSearch: 1