Skip to content

Commit

Permalink
WIP: Adjust to use new NodeAddress
Browse files Browse the repository at this point in the history
  • Loading branch information
mhsdesign committed May 13, 2024
1 parent bb353d6 commit 8a2748f
Show file tree
Hide file tree
Showing 13 changed files with 283 additions and 241 deletions.
68 changes: 36 additions & 32 deletions Neos.Neos/Classes/Controller/Frontend/NodeController.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@

namespace Neos\Neos\Controller\Frontend;

use Neos\ContentRepository\Core\ContentRepository;
use Neos\ContentRepository\Core\Projection\ContentGraph\ContentGraphWithRuntimeCaches\ContentSubgraphWithRuntimeCaches;
use Neos\ContentRepository\Core\Projection\ContentGraph\ContentGraphWithRuntimeCaches\InMemoryCache;
use Neos\ContentRepository\Core\Projection\ContentGraph\ContentSubgraphInterface;
Expand All @@ -25,6 +24,7 @@
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\NodeAddress;
use Neos\ContentRepositoryRegistry\ContentRepositoryRegistry;
use Neos\Flow\Annotations as Flow;
use Neos\Flow\Mvc\Controller\ActionController;
Expand All @@ -39,10 +39,10 @@
use Neos\Neos\Domain\Service\RenderingModeService;
use Neos\Neos\FrontendRouting\Exception\InvalidShortcutException;
use Neos\Neos\FrontendRouting\Exception\NodeNotFoundException;
use Neos\Neos\FrontendRouting\NodeAddress;
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 +106,9 @@ class NodeController extends ActionController
#[Flow\InjectConfiguration(path: "frontend.shortcutRedirectHttpStatusCode", package: "Neos.Neos")]
protected int $shortcutRedirectHttpStatusCode;

#[Flow\Inject]
protected NodeUriBuilderFactory $nodeUriBuilderFactory;

/**
* @param string $node
* @throws NodeNotFoundException
Expand All @@ -130,21 +133,15 @@ public function previewAction(string $node): void
$siteDetectionResult = SiteDetectionResult::fromRequest($this->request->getHttpRequest());
$contentRepository = $this->contentRepositoryRegistry->get($siteDetectionResult->contentRepositoryId);

$nodeAddress = NodeAddressFactory::create($contentRepository)->createFromUriString($node);
// todo temporary legacy
$nodeAddress = NodeAddressFactory::create($contentRepository)->createFromUriString($node)->toNewAddress($contentRepository->id);

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

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

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

$nodeInstance = $subgraph->findNodeById($nodeAddress->nodeAggregateId);
$nodeInstance = $subgraph->findNodeById($nodeAddress->aggregateId);

if (is_null($nodeInstance)) {
throw new NodeNotFoundException(
Expand All @@ -153,12 +150,19 @@ public function previewAction(string $node): void
);
}

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

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

if (
$this->getNodeType($nodeInstance)->isOfType(NodeTypeNameFactory::NAME_SHORTCUT)
&& !$renderingMode->isEdit
&& $nodeAddress->workspaceName->isLive() // shortcuts are only resolvable for the live workspace
) {
$this->handleShortcutNode($nodeAddress, $contentRepository);
$this->handleShortcutNode($nodeAddress);
}

$this->view->setOption('renderingModeName', $renderingMode->name);
Expand Down Expand Up @@ -192,33 +196,33 @@ public function previewAction(string $node): void
*/
public function showAction(string $node): void
{
$siteDetectionResult = SiteDetectionResult::fromRequest($this->request->getHttpRequest());
$contentRepository = $this->contentRepositoryRegistry->get($siteDetectionResult->contentRepositoryId);
$nodeAddress = NodeAddress::fromJsonString($node);
unset($node);

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

$contentRepository = $this->contentRepositoryRegistry->get($nodeAddress->contentRepositoryId);
$subgraph = $contentRepository->getContentGraph($nodeAddress->workspaceName)->getSubgraph(
$nodeAddress->dimensionSpacePoint,
VisibilityConstraints::frontend()
);

$nodeInstance = $subgraph->findNodeById($nodeAddress->nodeAggregateId);
$nodeInstance = $subgraph->findNodeById($nodeAddress->aggregateId);
if ($nodeInstance === null) {
throw new NodeNotFoundException(sprintf('The cached node address for this uri could not be resolved. Possibly you have to flush the "Flow_Mvc_Routing_Route" cache. %s', $nodeAddress), 1707300738);
throw new NodeNotFoundException(sprintf('The cached node address for this uri could not be resolved. Possibly you have to flush the "Flow_Mvc_Routing_Route" cache. %s', $nodeAddress->toJson()), 1707300738);
}

$site = $subgraph->findClosestNode($nodeAddress->nodeAggregateId, FindClosestNodeFilter::create(nodeTypes: NodeTypeNameFactory::NAME_SITE));
$site = $subgraph->findClosestNode($nodeAddress->aggregateId, FindClosestNodeFilter::create(nodeTypes: NodeTypeNameFactory::NAME_SITE));
if ($site === null) {
throw new NodeNotFoundException(sprintf('The site node of %s could not be resolved.', $nodeAddress), 1707300861);
throw new NodeNotFoundException(sprintf('The site node of %s could not be resolved.', $nodeAddress->toJson()), 1707300861);
}

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

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

$this->view->setOption('renderingModeName', RenderingMode::FRONTEND);
Expand Down Expand Up @@ -266,31 +270,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(NodeAddress $nodeAddress): void
{
try {
$resolvedTarget = $this->nodeShortcutResolver->resolveShortcutTarget($nodeAddress, $contentRepository);
$resolvedTarget = $this->nodeShortcutResolver->resolveShortcutTarget($nodeAddress);
} 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',
$nodeAddress->toJson(),
$e->getMessage()
), 1430218730, $e);
}
if ($resolvedTarget instanceof NodeAddress) {
if ($resolvedTarget === $nodeAddress) {
if ($nodeAddress->equals($resolvedTarget)) {
return;
}
try {
$resolvedUri = NodeUriBuilder::fromRequest($this->request)->uriFor($nodeAddress);
$resolvedUri = $this->nodeUriBuilderFactory->forRequest($this->request->getHttpRequest())
->uriFor(NodeUriSpecification::create($nodeAddress));
} 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',
$nodeAddress->toJson(),
$e->getMessage()
), 1599670695, $e);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

use Neos\ContentRepository\Core\ContentRepository;
use Neos\ContentRepository\Core\DimensionSpace\DimensionSpacePoint;
use Neos\ContentRepository\Core\SharedModel\Node\NodeAddress;
use Neos\ContentRepository\Core\SharedModel\Workspace\WorkspaceName;
use Neos\ContentRepositoryRegistry\ContentRepositoryRegistry;
use Neos\Flow\Annotations as Flow;
Expand Down Expand Up @@ -240,12 +241,13 @@ private function matchUriPath(
$uriPath,
$dimensionSpacePoint->hash
);
$nodeAddress = NodeAddressFactory::create($contentRepository)->createFromContentStreamIdAndDimensionSpacePointAndNodeAggregateId(
$documentUriPathFinder->getLiveContentStreamId(),
$nodeAddress = NodeAddress::create(
$contentRepository->id,
WorkspaceName::forLive(),
$dimensionSpacePoint,
$nodeInfo->getNodeAggregateId(),
);
return new MatchResult($nodeAddress->serializeForUri(), $nodeInfo->getRouteTags());
return new MatchResult($nodeAddress->toJson(), $nodeInfo->getRouteTags());
}

/**
Expand All @@ -261,7 +263,6 @@ public function resolveWithParameters(array &$routeValues, RouteParameters $para
$currentRequestSiteDetectionResult = SiteDetectionResult::fromRouteParameters($parameters);

$nodeAddress = $routeValues[$this->name];
// TODO: for cross-CR links: NodeAddressInContentRepository as a new value object
if (!$nodeAddress instanceof NodeAddress) {
return false;
}
Expand All @@ -284,23 +285,19 @@ public function resolveWithParameters(array &$routeValues, RouteParameters $para
* To disallow showing a node actually disabled/hidden itself has to be ensured in matching a request path,
* not in building one.
*
* @param NodeAddress $nodeAddress
* @param SiteDetectionResult $currentRequestSiteDetectionResult
* @return ResolveResult
* @throws InvalidShortcutException
* @throws NodeNotFoundException
*/
private function resolveNodeAddress(
NodeAddress $nodeAddress,
SiteDetectionResult $currentRequestSiteDetectionResult
): ResolveResult {
// TODO: SOMEHOW FIND OTHER CONTENT REPOSITORY HERE FOR CROSS-CR LINKS!!
$contentRepository = $this->contentRepositoryRegistry->get(
$currentRequestSiteDetectionResult->contentRepositoryId
$nodeAddress->contentRepositoryId
);
$documentUriPathFinder = $contentRepository->projectionState(DocumentUriPathFinder::class);
$nodeInfo = $documentUriPathFinder->getByIdAndDimensionSpacePointHash(
$nodeAddress->nodeAggregateId,
$nodeAddress->aggregateId,
$nodeAddress->dimensionSpacePoint->hash
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@
* Marker interface which can be used to replace the currently used FrontendNodeRoutePartHandler,
* to e.g. use the one with localization support.
*
* TODO CORE MIGRATION
*
* **See {@see EventSourcedFrontendNodeRoutePartHandler} documentation for a
* detailed explanation of the Frontend Routing process.**
*/
Expand Down
14 changes: 14 additions & 0 deletions Neos.Neos/Classes/FrontendRouting/NodeAddress.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
namespace Neos\Neos\FrontendRouting;

use Neos\ContentRepository\Core\DimensionSpace\DimensionSpacePoint;
use Neos\ContentRepository\Core\SharedModel\ContentRepository\ContentRepositoryId;
use Neos\ContentRepository\Core\SharedModel\Node\NodeAggregateId;
use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamId;
use Neos\ContentRepository\Core\SharedModel\Workspace\WorkspaceName;
Expand Down Expand Up @@ -49,6 +50,19 @@ public function __construct(
) {
}

/**
* @deprecated
*/
public function toNewAddress(ContentRepositoryId $contentRepositoryId): \Neos\ContentRepository\Core\SharedModel\Node\NodeAddress
{
return \Neos\ContentRepository\Core\SharedModel\Node\NodeAddress::create(
$contentRepositoryId,
$this->workspaceName,
$this->dimensionSpacePoint,
$this->nodeAggregateId
);
}

public function withNodeAggregateId(NodeAggregateId $nodeAggregateId): self
{
return new self(
Expand Down
25 changes: 11 additions & 14 deletions Neos.Neos/Classes/FrontendRouting/NodeShortcutResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
use GuzzleHttp\Psr7\Uri;
use Neos\ContentRepository\Core\ContentRepository;
use Neos\ContentRepository\Core\SharedModel\Node\NodeAggregateId;
use Neos\ContentRepository\Core\SharedModel\Node\NodeAddress;
use Neos\ContentRepositoryRegistry\ContentRepositoryRegistry;
use Neos\Flow\Annotations as Flow;
use Neos\Flow\ResourceManagement\ResourceManager;
use Neos\Media\Domain\Model\AssetInterface;
Expand All @@ -36,38 +38,33 @@
*/
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 NodeAddress|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(NodeAddress $nodeAddress)
{
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);
throw new \RuntimeException(sprintf('Cannot resolve shortcut target for node-address %s in workspace %s because the DocumentUriPathProjection only handles the live workspace.', $nodeAddress->aggregateId->value, $nodeAddress->workspaceName->value), 1707208650);
}
$contentRepository = $this->contentRepositoryRegistry->get($nodeAddress->contentRepositoryId);
$documentUriPathFinder = $contentRepository->projectionState(DocumentUriPathFinder::class);
$documentNodeInfo = $documentUriPathFinder->getByIdAndDimensionSpacePointHash(
$nodeAddress->nodeAggregateId,
$nodeAddress->aggregateId,
$nodeAddress->dimensionSpacePoint->hash
);
$resolvedTarget = $this->resolveNode($documentNodeInfo, $contentRepository);
Expand All @@ -77,7 +74,7 @@ public function resolveShortcutTarget(NodeAddress $nodeAddress, ContentRepositor
if ($resolvedTarget === $documentNodeInfo) {
return $nodeAddress;
}
return $nodeAddress->withNodeAggregateId($documentNodeInfo->getNodeAggregateId());
return $nodeAddress->withAggregateId($documentNodeInfo->getNodeAggregateId());
}

/**
Expand Down
7 changes: 5 additions & 2 deletions Neos.Neos/Classes/Fusion/Cache/CacheTag.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Neos\ContentRepository\Core\SharedModel\ContentRepository\ContentRepositoryId;
use Neos\ContentRepository\Core\SharedModel\Node\NodeAggregateId;
use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamId;
use Neos\ContentRepository\Core\SharedModel\Workspace\WorkspaceName;
use Neos\Flow\Annotations as Flow;

/**
Expand Down Expand Up @@ -107,12 +108,14 @@ final public static function forNodeTypeName(

final public static function forDynamicNodeAggregate(
ContentRepositoryId $contentRepositoryId,
ContentStreamId $contentStreamId,
WorkspaceName|ContentStreamId $workspaceName,
NodeAggregateId $nodeAggregateId,
): self {
return new self(
'DynamicNodeTag_'
. self::getHashForContentStreamIdAndContentRepositoryId($contentStreamId, $contentRepositoryId)
// todo discuss if we should use the $workspaceName, and do we even flush this?
// https://github.com/neos/neos-development-collection/pull/4940/files#r1531217463
// . self::getHashForContentStreamIdAndContentRepositoryId($workspaceName, $contentRepositoryId)
. '_' . $nodeAggregateId->value
);
}
Expand Down
Loading

0 comments on commit 8a2748f

Please sign in to comment.