Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[Bug] Preview fails with ContentNotFoundException when page uses snippet_selection #8476

@james2001

Description

@james2001

Description

When previewing a page that contains a snippet_selection property, the preview fails with a ContentNotFoundException. This happens because ContentResolver re-aggregates snippets using the parent's stage (draft in preview mode), but snippets only have live dimension content available.

Sulu Version

  • Sulu 3.0.1
  • Symfony 7.2

Steps to Reproduce

  1. Create a snippet template (e.g., beer.xml)
  2. Create a page template with a snippet_selection property:
<property name="beers" type="snippet_selection">
    <params>
        <param name="types" value="beer"/>
    </params>
</property>
  1. Create and publish a snippet
  2. Create a page, select the published snippet in the snippet_selection field
  3. Observe the preview panel - it shows an error

Expected Behavior

The preview should display the page with the resolved snippet content.

Actual Behavior

Preview fails with:

ContentNotFoundException: Could not load content with id "019b6573-9aa4-7188-899a-f0d2c31084f7" and attributes: {"locale":"en","stage":"draft"}

Root Cause Analysis

The issue is in ContentResolver.php at lines 75-80:

if ($resource instanceof ContentRichEntityInterface) {
    $childContent = $this->contentAggregator->aggregate($resource, [
        'locale' => $locale,
        'stage' => $stage,  // BUG: Uses parent's stage (draft in preview)
    ]);

Flow:

  1. SnippetResourceLoader correctly loads snippets with STAGE_LIVE
  2. It returns Snippet entities (which implement ContentRichEntityInterface)
  3. ContentResolver sees these are ContentRichEntityInterface instances
  4. It re-aggregates them using the parent's stage (draft in preview mode)
  5. ContentAggregator can't find dimension content with stage=draft for the snippet
  6. ContentNotFoundException is thrown

Why snippets don't have draft content:
Snippets are typically only published (live), not kept in draft state like pages being edited. When a user selects a snippet in a page, they expect to see the published version.

Suggested Fix

Snippets should always be resolved with STAGE_LIVE, regardless of the parent's stage. Possible solutions:

Option 1: Check resource type in ContentResolver

if ($resource instanceof ContentRichEntityInterface) {
    $childStage = $resource instanceof SnippetInterface 
        ? DimensionContentInterface::STAGE_LIVE 
        : $stage;
    
    $childContent = $this->contentAggregator->aggregate($resource, [
        'locale' => $locale,
        'stage' => $childStage,
    ]);

Option 2: Have SnippetResourceLoader return resolved DimensionContent

Instead of returning the Snippet entity, return the already-aggregated DimensionContent with STAGE_LIVE. This bypasses the ContentRichEntityInterface check.

Workaround

We implemented a custom SnippetResourceLoader that fully resolves snippets with STAGE_LIVE and returns the resolved data structure, bypassing the re-aggregation:

class PreviewSafeSnippetResourceLoader implements ResourceLoaderInterface
{
    public function load(array $ids, ?string $locale, array $params = []): array
    {
        // Load snippets with STAGE_LIVE
        $snippets = $this->snippetRepository->findBy([
            'uuids' => $ids,
            'locale' => $locale,
            'stage' => DimensionContentInterface::STAGE_LIVE,
        ], [], [SnippetRepositoryInterface::GROUP_SELECT_SNIPPET_WEBSITE => true]);

        $contentResolver = $this->container->get('sulu_content.content_resolver');

        $mappedResult = [];
        foreach ($snippets as $snippet) {
            $dimensionContent = $this->contentAggregator->aggregate($snippet, [
                'locale' => $locale,
                'stage' => DimensionContentInterface::STAGE_LIVE,
            ]);
            
            // Return fully resolved data instead of entity
            $mappedResult[$snippet->getId()] = $contentResolver->resolve($dimensionContent);
        }

        return $mappedResult;
    }
}

Related

This may be related to similar issues with referenced content in preview mode.

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions