Skip to content

Commit

Permalink
WIP: Migrate showAction to NodeIdentity
Browse files Browse the repository at this point in the history
  • Loading branch information
mhsdesign committed Feb 16, 2024
1 parent 99cb0c3 commit 60705ce
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 52 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,20 @@ public static function fromJsonString(string $jsonString): self
return self::fromArray(\json_decode($jsonString, true, JSON_THROW_ON_ERROR));
}

public function withNodeAggregateId(NodeAggregateId $nodeAggregateId): self
{
return new self($this->contentRepositoryId, $this->workspaceName, $this->dimensionSpacePoint, $nodeAggregateId);
}

public function equals(self $other): bool
{
return $this->contentRepositoryId->equals($other->contentRepositoryId)
&& $this->workspaceName->equals($other->workspaceName)
&& $this->dimensionSpacePoint->equals($other->dimensionSpacePoint)
&& $this->nodeAggregateId->equals($other->nodeAggregateId);

}

public function toJson(): string
{
return json_encode($this, JSON_THROW_ON_ERROR);
Expand Down
5 changes: 2 additions & 3 deletions Neos.ContentRepositoryRegistry/Classes/NodeSerializer.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public function __construct(
) {
}

public function findNodeByIdentity(NodeIdentity $identity): Node
public function findNodeByIdentity(NodeIdentity $identity, VisibilityConstraints $visibilityConstraints): Node
{
$contentRepository = $this->contentRepositoryRegistry->get($identity->contentRepositoryId);
$workspace = $contentRepository->getWorkspaceFinder()->findOneByName($identity->workspaceName);
Expand All @@ -32,8 +32,7 @@ public function findNodeByIdentity(NodeIdentity $identity): Node
$subgraph = $contentRepository->getContentGraph()->getSubgraph(
$workspace->currentContentStreamId,
$identity->dimensionSpacePoint,
// todo policy? Or what to prevent from accidentally showing unwanted nodes.
VisibilityConstraints::withoutRestrictions()
$visibilityConstraints
);
$node = $subgraph->findNodeById($identity->nodeAggregateId);
if (!$node) {
Expand Down
62 changes: 31 additions & 31 deletions Neos.Neos/Classes/Controller/Frontend/NodeController.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@
use Neos\ContentRepository\Core\Projection\ContentGraph\Subtree;
use Neos\ContentRepository\Core\Projection\ContentGraph\VisibilityConstraints;
use Neos\ContentRepository\Core\SharedModel\Node\NodeAggregateId;
use Neos\ContentRepository\Core\SharedModel\Node\NodeIdentity;
use Neos\ContentRepositoryRegistry\ContentRepositoryRegistry;
use Neos\ContentRepositoryRegistry\NodeSerializer;
use Neos\Flow\Annotations as Flow;
use Neos\Flow\Mvc\Controller\ActionController;
use Neos\Flow\Mvc\Exception\NoMatchingRouteException;
Expand All @@ -43,6 +45,8 @@
use Neos\Neos\FrontendRouting\NodeAddressFactory;
use Neos\Neos\FrontendRouting\NodeShortcutResolver;
use Neos\Neos\FrontendRouting\NodeUriBuilder;
use Neos\Neos\FrontendRouting\NodeUriBuilderFactory;
use Neos\Neos\FrontendRouting\NodeUriSpecification;
use Neos\Neos\FrontendRouting\SiteDetection\SiteDetectionResult;
use Neos\Neos\Utility\NodeTypeWithFallbackProvider;
use Neos\Neos\View\FusionView;
Expand Down Expand Up @@ -106,6 +110,12 @@ class NodeController extends ActionController
#[Flow\InjectConfiguration(path: "frontend.shortcutRedirectHttpStatusCode", package: "Neos.Neos")]
protected int $shortcutRedirectHttpStatusCode;

#[Flow\Inject]
protected NodeUriBuilderFactory $nodeUriBuilderFactory;

#[Flow\Inject]
protected NodeSerializer $nodeSerializer;

/**
* @param string $node
* @throws NodeNotFoundException
Expand Down Expand Up @@ -193,41 +203,31 @@ public function previewAction(string $node): void
*/
public function showAction(string $node): void
{
$siteDetectionResult = SiteDetectionResult::fromRequest($this->request->getHttpRequest());
$contentRepository = $this->contentRepositoryRegistry->get($siteDetectionResult->contentRepositoryId);
$nodeIdentity = NodeIdentity::fromJsonString($node);
unset($node);

$nodeAddress = NodeAddressFactory::create($contentRepository)->createFromUriString($node);
if (!$nodeAddress->isInLiveWorkspace()) {
if (!$nodeIdentity->workspaceName->isLive()) {
throw new NodeNotFoundException('The requested node isn\'t accessible to the current user', 1430218623);
}

$subgraph = $contentRepository->getContentGraph()->getSubgraph(
$nodeAddress->contentStreamId,
$nodeAddress->dimensionSpacePoint,
VisibilityConstraints::frontend()
);
$node = $this->nodeSerializer->findNodeByIdentity($nodeIdentity, VisibilityConstraints::frontend());
$subgraph = $this->contentRepositoryRegistry->subgraphForNode($node);

$site = $subgraph->findClosestNode($nodeAddress->nodeAggregateId, FindClosestNodeFilter::create(nodeTypes: NodeTypeNameFactory::NAME_SITE));
$site = $subgraph->findClosestNode($node->nodeAggregateId, FindClosestNodeFilter::create(nodeTypes: NodeTypeNameFactory::NAME_SITE));
if ($site === null) {
throw new NodeNotFoundException("TODO: SITE NOT FOUND; should not happen (for address " . $nodeAddress);
throw new NodeNotFoundException("TODO: SITE NOT FOUND; should not happen (for address " . $nodeIdentity->toJson());
}

$this->fillCacheWithContentNodes($nodeAddress->nodeAggregateId, $subgraph);

$nodeInstance = $subgraph->findNodeById($nodeAddress->nodeAggregateId);
$this->fillCacheWithContentNodes($node->nodeAggregateId, $subgraph);

if ($nodeInstance === null) {
throw new NodeNotFoundException('The requested node does not exist', 1596191460);
}

if ($this->getNodeType($nodeInstance)->isOfType(NodeTypeNameFactory::NAME_SHORTCUT)) {
$this->handleShortcutNode($nodeAddress, $contentRepository);
if ($this->getNodeType($node)->isOfType(NodeTypeNameFactory::NAME_SHORTCUT)) {
$this->handleShortcutNode($nodeIdentity);
}

$this->view->setOption('renderingModeName', RenderingMode::FRONTEND);

$this->view->assignMultiple([
'value' => $nodeInstance,
'value' => $node,
'site' => $site,
]);
}
Expand Down Expand Up @@ -269,31 +269,31 @@ protected function overrideViewVariablesFromInternalArguments()
/**
* Handles redirects to shortcut targets of nodes in the live workspace.
*
* @param NodeAddress $nodeAddress
* @throws NodeNotFoundException
* @throws \Neos\Flow\Mvc\Exception\StopActionException
*/
protected function handleShortcutNode(NodeAddress $nodeAddress, ContentRepository $contentRepository): void
protected function handleShortcutNode(NodeIdentity $nodeIdentity): void
{
try {
$resolvedTarget = $this->nodeShortcutResolver->resolveShortcutTarget($nodeAddress, $contentRepository);
$resolvedTarget = $this->nodeShortcutResolver->resolveShortcutTarget($nodeIdentity);
} catch (InvalidShortcutException $e) {
throw new NodeNotFoundException(sprintf(
'The shortcut node target of node "%s" could not be resolved: %s',
$nodeAddress,
'The shortcut node target of node %s could not be resolved: %s',
$nodeIdentity->toJson(),
$e->getMessage()
), 1430218730, $e);
}
if ($resolvedTarget instanceof NodeAddress) {
if ($resolvedTarget === $nodeAddress) {
if ($resolvedTarget instanceof NodeIdentity) {
if ($nodeIdentity->equals($resolvedTarget)) {
return;
}
try {
$resolvedUri = NodeUriBuilder::fromRequest($this->request)->uriFor($nodeAddress);
$resolvedUri = $this->nodeUriBuilderFactory->forRequest($this->request->getHttpRequest())
->uriFor(NodeUriSpecification::create($nodeIdentity));
} catch (NoMatchingRouteException $e) {
throw new NodeNotFoundException(sprintf(
'The shortcut node target of node "%s" could not be resolved: %s',
$nodeAddress,
'The shortcut node target of node %s could not be resolved: %s',
$nodeIdentity->toJson(),
$e->getMessage()
), 1599670695, $e);
}
Expand Down
32 changes: 14 additions & 18 deletions Neos.Neos/Classes/FrontendRouting/NodeShortcutResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
use GuzzleHttp\Psr7\Uri;
use Neos\ContentRepository\Core\ContentRepository;
use Neos\ContentRepository\Core\SharedModel\Node\NodeAggregateId;
use Neos\Neos\FrontendRouting\NodeAddress;
use Neos\ContentRepository\Core\SharedModel\Node\NodeIdentity;
use Neos\ContentRepositoryRegistry\ContentRepositoryRegistry;
use Neos\Neos\FrontendRouting\Exception\InvalidShortcutException;
use Neos\Neos\FrontendRouting\Exception\NodeNotFoundException;
use Neos\Neos\FrontendRouting\Projection\DocumentNodeInfo;
Expand All @@ -38,48 +39,43 @@
*/
class NodeShortcutResolver
{
private AssetRepository $assetRepository;

private ResourceManager $resourceManager;

public function __construct(
AssetRepository $assetRepository,
ResourceManager $resourceManager
private readonly AssetRepository $assetRepository,
private readonly ResourceManager $resourceManager,
private readonly ContentRepositoryRegistry $contentRepositoryRegistry
) {
$this->assetRepository = $assetRepository;
$this->resourceManager = $resourceManager;
}

/**
* "adapter" for {@see resolveNode} when working with NodeAddresses.
* Note: The ContentStreamId is not required for this service,
* because it is only covering the live workspace
*
* @param NodeAddress $nodeAddress
* @return NodeAddress|UriInterface NodeAddress is returned if we want to link to another node
* @return NodeIdentity|UriInterface NodeIdentity is returned if we want to link to another node
* (i.e. node is NOT a shortcut node; or target is a node);
* or UriInterface for links to fixed URLs (Asset URLs or external URLs)
* @throws \Neos\Neos\FrontendRouting\Exception\InvalidShortcutException
* @throws NodeNotFoundException
*/
public function resolveShortcutTarget(NodeAddress $nodeAddress, ContentRepository $contentRepository)
public function resolveShortcutTarget(NodeIdentity $nodeIdentity)
{
if (!$nodeAddress->workspaceName->isLive()) {
throw new \RuntimeException(sprintf('Cannot resolve shortcut target for node-address %s in workspace %s because the DocumentUriPathProjection only handles the live workspace.', $nodeAddress->nodeAggregateId->value, $nodeAddress->workspaceName->value), 1707208650);
if (!$nodeIdentity->workspaceName->isLive()) {
throw new \RuntimeException(sprintf('Cannot resolve shortcut target for node-address %s in workspace %s because the DocumentUriPathProjection only handles the live workspace.', $nodeIdentity->nodeAggregateId->value, $nodeIdentity->workspaceName->value), 1707208650);
}
$contentRepository = $this->contentRepositoryRegistry->get($nodeIdentity->contentRepositoryId);
$documentUriPathFinder = $contentRepository->projectionState(DocumentUriPathFinder::class);
$documentNodeInfo = $documentUriPathFinder->getByIdAndDimensionSpacePointHash(
$nodeAddress->nodeAggregateId,
$nodeAddress->dimensionSpacePoint->hash
$nodeIdentity->nodeAggregateId,
$nodeIdentity->dimensionSpacePoint->hash
);
$resolvedTarget = $this->resolveNode($documentNodeInfo, $contentRepository);
if ($resolvedTarget instanceof UriInterface) {
return $resolvedTarget;
}
if ($resolvedTarget === $documentNodeInfo) {
return $nodeAddress;
return $nodeIdentity;
}
return $nodeAddress->withNodeAggregateId($documentNodeInfo->getNodeAggregateId());
return $nodeIdentity->withNodeAggregateId($documentNodeInfo->getNodeAggregateId());
}

/**
Expand Down

0 comments on commit 60705ce

Please sign in to comment.