Skip to content

Commit 8fda5bc

Browse files
committed
Fix #157 regression: publishable pageDataProperty components blocked for anonymous users
ClassMetadata::getFieldValue() uses a raw array cast which bypasses Doctrine's lazy initialization — both traditional proxies and PHP 8.4+ native lazy ghost objects. Added initializeLazyObject() helper in PublishableStatusChecker that calls EntityManager::initializeObject() before reading the publishedAt field value, covering both lazy object types transparently. Added missing component_position resource reference to the draft fixture and a new fixture + two Behat scenarios covering published and draft publishable components in pageDataProperty positions for anonymous users.
1 parent 3012b4b commit 8fda5bc

3 files changed

Lines changed: 73 additions & 0 deletions

File tree

features/bootstrap/DoctrineContext.php

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -829,6 +829,53 @@ public function thereIsAPageDataWithDraftComponentInPageDataPropertyPosition(str
829829
$this->manager->persist($route);
830830

831831
$this->manager->flush();
832+
833+
$this->restContext->resources['component_position'] = $this->iriConverter->getIriFromResource($componentPosition);
834+
}
835+
836+
/**
837+
* @Given there is a PageData resource with a published component in a pageDataProperty position and the route path :path
838+
*/
839+
public function thereIsAPageDataWithPublishedComponentInPageDataPropertyPosition(string $path): void
840+
{
841+
$componentGroup = new ComponentGroup();
842+
$componentGroup->reference = 'test';
843+
$componentGroup->location = 'test';
844+
$this->timestampedHelper->persistTimestampedFields($componentGroup, true);
845+
$this->manager->persist($componentGroup);
846+
847+
$componentPosition = new ComponentPosition();
848+
$componentPosition->pageDataProperty = 'publishableComponent';
849+
$componentPosition->componentGroup = $componentGroup;
850+
$componentPosition->sortValue = 0;
851+
$this->timestampedHelper->persistTimestampedFields($componentPosition, true);
852+
$this->manager->persist($componentPosition);
853+
$this->restContext->resources['component_position'] = $this->iriConverter->getIriFromResource($componentPosition);
854+
855+
$page = new Page();
856+
$page->isTemplate = true;
857+
$page->reference = 'test page';
858+
$page->addComponentGroup($componentGroup);
859+
$this->timestampedHelper->persistTimestampedFields($page, true);
860+
$this->manager->persist($page);
861+
862+
$publishedComponent = new DummyPublishableComponent();
863+
$publishedComponent->setPublishedAt(new \DateTime());
864+
$this->manager->persist($publishedComponent);
865+
866+
$pageData = new PageDataWithComponent();
867+
$pageData->publishableComponent = $publishedComponent;
868+
$pageData->page = $page;
869+
$this->timestampedHelper->persistTimestampedFields($pageData, true);
870+
$this->manager->persist($pageData);
871+
872+
$route = new Route();
873+
$route->setPath($path)->setName($path)->setPageData($pageData);
874+
$this->timestampedHelper->persistTimestampedFields($route, true);
875+
$this->manager->persist($route);
876+
877+
$this->manager->flush();
878+
$this->manager->clear();
832879
}
833880

834881
/**

features/main/dynamic_page.feature

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,3 +82,17 @@ Feature: Dynamic pages
8282
Then the response status code should be 200
8383
And the JSON node "pageDataProperty" should be equal to "component"
8484
And the JSON node "component" should be null
85+
86+
Scenario: A published pageDataProperty component is returned for anonymous users
87+
Given there is a PageData resource with a published component in a pageDataProperty position and the route path "/page-data"
88+
And I add "path" header equal to "/page-data"
89+
When I send a "GET" request to the resource "component_position"
90+
Then the response status code should be 200
91+
And the JSON node "component" should match the regex "/\/component\/dummy_publishable_components\/[a-z0-9\-]+/"
92+
93+
Scenario: A draft pageDataProperty component is not returned for anonymous users
94+
Given there is a PageData resource with a draft component in a pageDataProperty position and the route path "/page-data"
95+
And I add "path" header equal to "/page-data"
96+
When I send a "GET" request to the resource "component_position"
97+
Then the response status code should be 200
98+
And the JSON node "component" should be null

src/Helper/Publishable/PublishableStatusChecker.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ public function isActivePublishedAt(object $object): bool
5454
throw new \InvalidArgumentException(\sprintf('Object of class %s does not implement publishable configuration.', $object::class));
5555
}
5656

57+
$this->initializeLazyObject($object);
58+
5759
$value = $this->getClassMetadata($object)->getFieldValue($object, $this->attributeReader->getConfiguration($object)->fieldName);
5860

5961
return null !== $value && new \DateTimeImmutable() >= $value;
@@ -65,9 +67,19 @@ public function hasPublicationDate(object $object): bool
6567
throw new \InvalidArgumentException(\sprintf('Object of class %s does not implement publishable configuration.', $object::class));
6668
}
6769

70+
$this->initializeLazyObject($object);
71+
6872
return null !== $this->getClassMetadata($object)->getFieldValue($object, $this->attributeReader->getConfiguration($object)->fieldName);
6973
}
7074

75+
private function initializeLazyObject(object $object): void
76+
{
77+
$em = $this->registry->getManagerForClass($this->getObjectClass($object));
78+
if ($em && $em->isUninitializedObject($object)) {
79+
$em->initializeObject($object);
80+
}
81+
}
82+
7183
public function isRequestForPublished(Request $request): bool
7284
{
7385
return $request->query->getBoolean('published', false);

0 commit comments

Comments
 (0)