Skip to content

Commit

Permalink
FEATURE: Add SiteNodeUtility::findSiteNodeBySite
Browse files Browse the repository at this point in the history
The rather hacky method `findCurrentSiteNode` was refactored and its usage adjusted.
  • Loading branch information
mhsdesign committed Oct 12, 2023
1 parent c2dbecb commit 4c53438
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 51 deletions.
15 changes: 14 additions & 1 deletion Neos.Neos/Classes/Domain/Repository/SiteRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,11 @@
use Neos\Flow\Persistence\QueryInterface;
use Neos\Flow\Persistence\QueryResultInterface;
use Neos\Flow\Persistence\Repository;
use Neos\Neos\Domain\Model\Site;
use Neos\Neos\Domain\Exception as NeosException;
use Neos\Neos\Domain\Model\Site;
use Neos\Neos\Domain\Model\SiteNodeName;
use Neos\Neos\Domain\Service\NodeTypeNameFactory;
use Neos\Neos\Domain\Service\SiteNodeUtility;
use Neos\Neos\Utility\NodeTypeWithFallbackProvider;

/**
Expand Down Expand Up @@ -104,6 +105,18 @@ public function findOneByNodeName(string|SiteNodeName $nodeName): ?Site
}

/**
* Finds a given site by site node.
*
* To find the correct site node by its descended child node leverage `findClosestNode`:
* ```php
* $siteNode = $subgraph->findClosestNode(
* $node->nodeAggregateId,
* FindClosestNodeFilter::create(nodeTypeConstraints: NodeTypeNameFactory::NAME_SITE)
* );
* ```
*
* To resolve the SiteNode by a Site use {@see SiteNodeUtility::findSiteNodeBySite()}
*
* @throws \Neos\Neos\Domain\Exception in case the passed $siteNode is not a real site node or no site matches this site node.
*/
public function findSiteBySiteNode(Node $siteNode): Site
Expand Down
90 changes: 54 additions & 36 deletions Neos.Neos/Classes/Domain/Service/SiteNodeUtility.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,64 +16,82 @@
namespace Neos\Neos\Domain\Service;

use Neos\ContentRepository\Core\DimensionSpace\DimensionSpacePoint;
use Neos\ContentRepository\Core\Factory\ContentRepositoryId;
use Neos\ContentRepository\Core\Projection\ContentGraph\Node;
use Neos\ContentRepository\Core\Projection\ContentGraph\VisibilityConstraints;
use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamId;
use Neos\ContentRepositoryRegistry\ContentRepositoryRegistry;
use Neos\Flow\Annotations as Flow;
use Neos\Neos\Domain\Model\Site;
use Neos\Neos\Domain\Repository\DomainRepository;
use Neos\Neos\Domain\Repository\SiteRepository;
use Neos\Neos\Utility\NodeTypeWithFallbackProvider;

/** @internal */
#[Flow\Scope('singleton')]
final class SiteNodeUtility
{
use NodeTypeWithFallbackProvider;

public function __construct(
private readonly ContentRepositoryRegistry $contentRepositoryRegistry,
private readonly DomainRepository $domainRepository,
private readonly SiteRepository $siteRepository
private readonly ContentRepositoryRegistry $contentRepositoryRegistry
) {
}

/** @internal */
public function findCurrentSiteNode(
ContentRepositoryId $contentRepositoryId,
/**
* Find the site node by the neos site entity.
*
* To find the site node for the live workspace in a 0 dimensional content repository use:
*
* ```php
* $contentRepository = $this->contentRepositoryRegistry->get($site->getConfiguration()->contentRepositoryId);
* $liveWorkspace = $contentRepository->getWorkspaceFinder()->findOneByName(WorkspaceName::forLive())
* ?? throw new \RuntimeException('Expected live workspace to exist.');
*
* $siteNode = $this->siteNodeUtility->findSiteNodeBySite(
* $site,
* $liveWorkspace->currentContentStreamId,
* DimensionSpacePoint::fromArray([]),
* VisibilityConstraints::frontend()
* );
* ```
*
* To resolve the Site by a node use {@see SiteRepository::findSiteBySiteNode()}
*/
public function findSiteNodeBySite(
Site $site,
ContentStreamId $contentStreamId,
DimensionSpacePoint $dimensionSpacePoint,
VisibilityConstraints $visibilityConstraints
): Node {
$domain = $this->domainRepository->findOneByActiveRequest();
$site = $domain
? $domain->getSite()
: $this->siteRepository->findDefault();
$contentRepository = $this->contentRepositoryRegistry->get($site->getConfiguration()->contentRepositoryId);

$subgraph = $contentRepository->getContentGraph()->getSubgraph(
$contentStreamId,
$dimensionSpacePoint,
$visibilityConstraints,
);

$rootNodeAggregate = $contentRepository->getContentGraph()->findRootNodeAggregateByType(
$contentStreamId,
NodeTypeNameFactory::forSites()
);
$rootNode = $rootNodeAggregate->getNodeByCoveredDimensionSpacePoint($dimensionSpacePoint);

if ($site instanceof Site) {
$contentRepository = $this->contentRepositoryRegistry->get($contentRepositoryId);
$subgraph = $contentRepository->getContentGraph()->getSubgraph(
$contentStreamId,
$dimensionSpacePoint,
$visibilityConstraints,
);
$siteNode = $subgraph->findChildNodeConnectedThroughEdgeName(
$rootNode->nodeAggregateId,
$site->getNodeName()->toNodeName()
);

if (!$siteNode) {
throw new \RuntimeException(sprintf(
'No site node found for site "%s"', $site->getNodeName()
), 1697140379);
}

$rootNodeAggregate = $contentRepository->getContentGraph()
->findRootNodeAggregateByType(
$contentStreamId,
NodeTypeNameFactory::forSites()
);
$sitesNode = $subgraph->findNodeById($rootNodeAggregate->nodeAggregateId);
if ($sitesNode) {
$siteNode = $subgraph->findChildNodeConnectedThroughEdgeName(
$sitesNode->nodeAggregateId,
$site->getNodeName()->toNodeName()
);
if ($siteNode instanceof Node) {
return $siteNode;
}
}
if (!$this->getNodeType($siteNode)->isOfType(NodeTypeNameFactory::NAME_SITE)) {
throw new \RuntimeException(sprintf(
'The site node "%s" (type: "%s") must be of type "%s"', $siteNode->nodeAggregateId->value, $siteNode->nodeTypeName->value, NodeTypeNameFactory::NAME_SITE
), 1697140367);
}

throw new \RuntimeException('No site node found for domain "' . $domain?->getHostname() . '" and site "' . $site?->getNodeName() . '"');
return $siteNode;
}
}
26 changes: 12 additions & 14 deletions Neos.Neos/Classes/View/FusionExceptionView.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,8 @@

namespace Neos\Neos\View;

use GuzzleHttp\Psr7\ServerRequest;
use Neos\ContentRepository\Core\Projection\ContentGraph\Node;
use Neos\ContentRepository\Core\Projection\ContentGraph\VisibilityConstraints;
use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamId;
use Neos\ContentRepository\Core\SharedModel\Workspace\WorkspaceName;
use Neos\ContentRepositoryRegistry\ContentRepositoryRegistry;
use Neos\Flow\Annotations as Flow;
Expand All @@ -36,10 +34,10 @@
use Neos\Fusion\Core\RuntimeFactory;
use Neos\Fusion\Exception\RuntimeException;
use Neos\Neos\Domain\Model\RenderingMode;
use Neos\Neos\Domain\Repository\DomainRepository;
use Neos\Neos\Domain\Repository\SiteRepository;
use Neos\Neos\Domain\Service\FusionService;
use Neos\Neos\Domain\Service\SiteNodeUtility;
use Neos\Neos\Domain\Service\RenderingModeService;
use Neos\Neos\FrontendRouting\SiteDetection\SiteDetectionResult;

class FusionExceptionView extends AbstractView
Expand Down Expand Up @@ -90,7 +88,7 @@ class FusionExceptionView extends AbstractView
protected ContentRepositoryRegistry $contentRepositoryRegistry;

#[Flow\Inject]
protected RenderingModeService $userInterfaceModeService;
protected DomainRepository $domainRepository;

/**
* @return string
Expand All @@ -117,14 +115,15 @@ public function render()
);
$dimensionSpacePoint = $fusionExceptionViewInternals->getArbitraryDimensionSpacePoint();

$contentStreamId = $contentRepository->getWorkspaceFinder()->findOneByName(WorkspaceName::forLive())
?->currentContentStreamId;
$liveWorkspace = $contentRepository->getWorkspaceFinder()->findOneByName(WorkspaceName::forLive());

$currentSiteNode = null;
if ($contentStreamId instanceof ContentStreamId) {
$currentSiteNode = $this->siteNodeUtility->findCurrentSiteNode(
$siteDetectionResult->contentRepositoryId,
$contentStreamId,
if ($liveWorkspace) {
$site = $this->siteRepository->findOneByNodeName($siteDetectionResult->siteNodeName);

$currentSiteNode = $this->siteNodeUtility->findSiteNodeBySite(
$site,
$liveWorkspace->currentContentStreamId,
$dimensionSpacePoint,
VisibilityConstraints::frontend()
);
Expand Down Expand Up @@ -163,13 +162,12 @@ public function render()

try {
$output = $fusionRuntime->render('error');
$output = $this->extractBodyFromOutput($output);
return $this->extractBodyFromOutput($output);
} catch (RuntimeException $exception) {
throw $exception->getPrevious() ?: $exception;
} finally {
$fusionRuntime->popContext();
}
$fusionRuntime->popContext();

return $output;
}

return '';
Expand Down

0 comments on commit 4c53438

Please sign in to comment.