Skip to content

Commit

Permalink
BUGFIX: (9.0) Predict nodes that will be deleted through discard
Browse files Browse the repository at this point in the history
Using the `PendingChangesProjection` from Neos.Neos, which after
neos/neos-development-collection#4393 will track all
nodes that have been newly created within the workspace that contains the
change set that is being discarded.
  • Loading branch information
grebaldi committed Jul 8, 2023
1 parent eb3182f commit f692333
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 15 deletions.
51 changes: 49 additions & 2 deletions Classes/ContentRepository/Service/WorkspaceService.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

use Neos\ContentRepository\Core\ContentRepository;
use Neos\ContentRepository\Core\Factory\ContentRepositoryId;
use Neos\ContentRepository\Core\Projection\ContentGraph\ContentSubgraphIdentity;
use Neos\ContentRepository\Core\Feature\WorkspacePublication\Command\DiscardIndividualNodesFromWorkspace;
use Neos\ContentRepository\Core\Projection\ContentGraph\Node;
use Neos\ContentRepository\Core\Projection\Workspace\Workspace;
use Neos\Neos\FrontendRouting\NodeAddress;
Expand All @@ -24,8 +24,8 @@
use Neos\Flow\Annotations as Flow;
use Neos\Neos\Domain\Service\UserService as DomainUserService;
use Neos\Neos\PendingChangesProjection\ChangeFinder;
use Neos\Neos\PendingChangesProjection\ChangeProjection;
use Neos\Neos\Service\UserService;
use Neos\Neos\Ui\Domain\Model\Feedback\Operations\RemoveNode;

/**
* @Flow\Scope("singleton")
Expand Down Expand Up @@ -156,6 +156,53 @@ public function getAllowedTargetWorkspaces(ContentRepository $contentRepository)
return $workspacesArray;
}

public function predictRemoveNodeFeedbackFromDiscardIndividualNodesFromWorkspaceCommand(
DiscardIndividualNodesFromWorkspace $command,
ContentRepository $contentRepository
): array {
$workspace = $contentRepository->getWorkspaceFinder()->findOneByName($command->workspaceName);
if (is_null($workspace)) {
return Nodes::createEmpty();
}

$changeFinder = $contentRepository->projectionState(ChangeFinder::class);
$changes = $changeFinder->findByContentStreamId($workspace->currentContentStreamId);

$handledNodes = [];
$result = [];
foreach ($changes as $change) {
if ($change->created) {
foreach ($command->nodesToDiscard as $nodeToDiscard) {
if (in_array($nodeToDiscard, $handledNodes)) {
continue;
}

if (
$nodeToDiscard->contentStreamId->equals($change->contentStreamId)
&& $nodeToDiscard->nodeAggregateId->equals($change->nodeAggregateId)
&& $nodeToDiscard->dimensionSpacePoint->equals($change->originDimensionSpacePoint)
) {
$subgraph = $contentRepository->getContentGraph()
->getSubgraph(
$nodeToDiscard->contentStreamId,
$nodeToDiscard->dimensionSpacePoint,
VisibilityConstraints::withoutRestrictions()
);

$childNode = $subgraph->findNodeById($nodeToDiscard->nodeAggregateId);
$parentNode = $subgraph->findParentNode($nodeToDiscard->nodeAggregateId);
if ($parentNode) {
$result[] = new RemoveNode($childNode, $parentNode);
$handledNodes[] = $nodeToDiscard;
}
}
}
}
}

return $result;
}

private function getClosestDocumentNode(Node $node): ?Node
{
$subgraph = $this->contentRepositoryRegistry->subgraphForNode($node);
Expand Down
21 changes: 15 additions & 6 deletions Classes/Controller/BackendServiceController.php
Original file line number Diff line number Diff line change
Expand Up @@ -294,18 +294,27 @@ public function discardAction(array $nodeContextPaths): void
$nodeAddress->dimensionSpacePoint
);
}
$contentRepository->handle(
DiscardIndividualNodesFromWorkspace::create(
$workspaceName,
NodeIdsToPublishOrDiscard::create(...$nodeIdentifiersToDiscard)
)
)->block();

$command = DiscardIndividualNodesFromWorkspace::create(
$workspaceName,
NodeIdsToPublishOrDiscard::create(...$nodeIdentifiersToDiscard)
);
$removeNodeFeedback = $this->workspaceService
->predictRemoveNodeFeedbackFromDiscardIndividualNodesFromWorkspaceCommand(
$command,
$contentRepository
);

$contentRepository->handle($command)->block();

$success = new Success();
$success->setMessage(sprintf('Discarded %d node(s).', count($nodeContextPaths)));

$updateWorkspaceInfo = new UpdateWorkspaceInfo($contentRepositoryId, $workspaceName);
$this->feedbackCollection->add($success);
foreach ($removeNodeFeedback as $removeNode) {
$this->feedbackCollection->add($removeNode);
}
$this->feedbackCollection->add($updateWorkspaceInfo);
} catch (\Exception $e) {
$error = new Error();
Expand Down
20 changes: 16 additions & 4 deletions Classes/Domain/Model/Feedback/Operations/RemoveNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use Neos\ContentRepositoryRegistry\ContentRepositoryRegistry;
use Neos\Flow\Annotations as Flow;
use Neos\Neos\FrontendRouting\NodeAddressFactory;
use Neos\Neos\FrontendRouting\NodeAddress;
use Neos\ContentRepository\Core\Projection\ContentGraph\Node;
use Neos\Flow\Mvc\Controller\ControllerContext;
use Neos\Neos\Ui\Domain\Model\AbstractFeedback;
Expand All @@ -25,6 +26,10 @@ class RemoveNode extends AbstractFeedback

protected Node $parentNode;

private NodeAddress $nodeAddress;

private NodeAddress $parentNodeAddress;

/**
* @Flow\Inject
* @var ContentRepositoryRegistry
Expand All @@ -37,6 +42,15 @@ public function __construct(Node $node, Node $parentNode)
$this->parentNode = $parentNode;
}

protected function initializeObject(): void
{
$contentRepository = $this->contentRepositoryRegistry->get($this->node->subgraphIdentity->contentRepositoryId);
$nodeAddressFactory = NodeAddressFactory::create($contentRepository);

$this->nodeAddress = $nodeAddressFactory->createFromNode($this->node);
$this->parentNodeAddress = $nodeAddressFactory->createFromNode($this->parentNode);
}

public function getNode(): Node
{
return $this->node;
Expand Down Expand Up @@ -87,11 +101,9 @@ public function isSimilarTo(FeedbackInterface $feedback)
*/
public function serializePayload(ControllerContext $controllerContext)
{
$contentRepository = $this->contentRepositoryRegistry->get($this->node->subgraphIdentity->contentRepositoryId);
$nodeAddressFactory = NodeAddressFactory::create($contentRepository);
return [
'contextPath' => $nodeAddressFactory->createFromNode($this->node)->serializeForUri(),
'parentContextPath' => $nodeAddressFactory->createFromNode($this->parentNode)->serializeForUri()
'contextPath' => $this->nodeAddress->serializeForUri(),
'parentContextPath' => $this->parentNodeAddress->serializeForUri()
];
}
}
14 changes: 12 additions & 2 deletions Tests/IntegrationTests/TestDistribution/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
"vendor-dir": "Packages/Libraries",
"bin-dir": "bin",
"allow-plugins": {
"neos/composer-plugin": true
"neos/composer-plugin": true,
"cweagans/composer-patches": true
}
},
"require": {
Expand All @@ -20,7 +21,16 @@
"neos/neos-ui-compiled": "9.0.x-dev as 9.0",

"neos/test-site": "@dev",
"neos/test-nodetypes": "@dev"
"neos/test-nodetypes": "@dev",

"cweagans/composer-patches": "^1.7.3"
},
"extra": {
"patches": {
"neos/neos-development-collection": {
"!!!FEATURE: (Neos.Neos) Track created nodes in PendingChangesProjection": "https://github.com/neos/neos-development-collection/pull/4393.patch"
}
}
},
"repositories": {
"distribution": {
Expand Down
2 changes: 1 addition & 1 deletion packages/neos-ui-sagas/src/UI/ContentTree/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ export function * watchCurrentDocument({globalRegistry, configuration}) {
}

const state = yield select();
const childrenAreFullyLoaded = $get(['cr', 'nodes', 'byContextPath', contextPath, 'children'], state)
const childrenAreFullyLoaded = ($get(['cr', 'nodes', 'byContextPath', contextPath, 'children'], state) || [])
.filter(childEnvelope => nodeTypesRegistry.hasRole(childEnvelope.nodeType, 'content') || nodeTypesRegistry.hasRole(childEnvelope.nodeType, 'contentCollection'))
.every(
childEnvelope => Boolean($get(['cr', 'nodes', 'byContextPath', $get('contextPath', childEnvelope)], state))
Expand Down

0 comments on commit f692333

Please sign in to comment.