Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FEATURE: Extract workspace metadata and user-assignment to Neos #3838

Open
wants to merge 10 commits into
base: 9.0
Choose a base branch
from
4 changes: 0 additions & 4 deletions Classes/Application/ReloadNodes/ReloadNodesQueryHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
use Neos\Flow\Annotations as Flow;
use Neos\Flow\Mvc\ActionRequest;
use Neos\Neos\Domain\Service\NodeTypeNameFactory;
use Neos\Neos\Domain\Workspace\WorkspaceProvider;
use Neos\Neos\FrontendRouting\NodeAddressFactory;
use Neos\Neos\Ui\Fusion\Helper\NodeInfoHelper;

Expand All @@ -36,9 +35,6 @@
#[Flow\Scope("singleton")]
final class ReloadNodesQueryHandler
{
#[Flow\Inject]
protected WorkspaceProvider $workspaceProvider;

#[Flow\Inject]
protected ContentRepositoryRegistry $contentRepositoryRegistry;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
use Neos\ContentRepositoryRegistry\ContentRepositoryRegistry;
use Neos\Flow\Annotations as Flow;
use Neos\Neos\Domain\NodeLabel\NodeLabelGeneratorInterface;
use Neos\Neos\Domain\Workspace\WorkspaceProvider;
use Neos\Neos\Domain\Service\WorkspacePublishingService;

/**
* The application layer level command handler to for rebasing the workspace
Expand All @@ -32,20 +32,19 @@ final class SyncWorkspaceCommandHandler
protected ContentRepositoryRegistry $contentRepositoryRegistry;

#[Flow\Inject]
protected WorkspaceProvider $workspaceProvider;
protected WorkspacePublishingService $workspacePublishingService;

#[Flow\Inject]
protected NodeLabelGeneratorInterface $nodeLabelGenerator;

public function handle(SyncWorkspaceCommand $command): void
{
try {
$workspace = $this->workspaceProvider->provideForWorkspaceName(
$this->workspacePublishingService->rebaseWorkspace(
$command->contentRepositoryId,
$command->workspaceName
$command->workspaceName,
$command->rebaseErrorHandlingStrategy
);

$workspace->rebase($command->rebaseErrorHandlingStrategy);
} catch (WorkspaceRebaseFailed $e) {
$conflictsBuilder = Conflicts::builder(
contentRepository: $this->contentRepositoryRegistry
Expand Down
74 changes: 9 additions & 65 deletions Classes/ContentRepository/Service/WorkspaceService.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,18 @@
* source code.
*/

use Neos\ContentRepository\Core\ContentRepository;
use Neos\ContentRepository\Core\SharedModel\ContentRepository\ContentRepositoryId;
use Neos\ContentRepository\Core\Projection\ContentGraph\Filter\FindClosestNodeFilter;
use Neos\ContentRepository\Core\Projection\ContentGraph\Node;
use Neos\Neos\Domain\Service\NodeTypeNameFactory;
use Neos\Neos\FrontendRouting\NodeAddress;
use Neos\Neos\FrontendRouting\NodeAddressFactory;
use Neos\ContentRepository\Core\Projection\ContentGraph\VisibilityConstraints;
use Neos\ContentRepository\Core\SharedModel\ContentRepository\ContentRepositoryId;
use Neos\ContentRepository\Core\SharedModel\Workspace\WorkspaceName;
use Neos\ContentRepositoryRegistry\ContentRepositoryRegistry;
use Neos\Flow\Annotations as Flow;
use Neos\Neos\Domain\Service\UserService as DomainUserService;
use Neos\Neos\Domain\Service\NodeTypeNameFactory;
use Neos\Neos\Domain\Service\WorkspacePublishingService;
use Neos\Neos\FrontendRouting\NodeAddress;
use Neos\Neos\FrontendRouting\NodeAddressFactory;
use Neos\Neos\PendingChangesProjection\Change;
use Neos\Neos\PendingChangesProjection\ChangeFinder;
use Neos\Neos\Service\UserService;
use Neos\Neos\Utility\NodeTypeWithFallbackProvider;

/**
Expand All @@ -44,17 +41,8 @@ class WorkspaceService
#[Flow\Inject]
protected ContentRepositoryRegistry $contentRepositoryRegistry;

/**
* @Flow\Inject
* @var UserService
*/
protected $userService;

/**
* @Flow\Inject
* @var DomainUserService
*/
protected $domainUserService;
#[Flow\Inject]
protected WorkspacePublishingService $workspacePublishingService;

/**
* Get all publishable node context paths for a workspace
Expand All @@ -64,15 +52,10 @@ class WorkspaceService
public function getPublishableNodeInfo(WorkspaceName $workspaceName, ContentRepositoryId $contentRepositoryId): array
{
$contentRepository = $this->contentRepositoryRegistry->get($contentRepositoryId);
$workspace = $contentRepository->getWorkspaceFinder()->findOneByName($workspaceName);
if (is_null($workspace) || $workspace->baseWorkspaceName === null) {
return [];
}
$changeFinder = $contentRepository->projectionState(ChangeFinder::class);
$changes = $changeFinder->findByContentStreamId($workspace->currentContentStreamId);
$pendingChanges = $this->workspacePublishingService->pendingWorkspaceChanges($contentRepositoryId, $workspaceName);
/** @var array{contextPath:string,documentContextPath:string,typeOfChange:int}[] $unpublishedNodes */
$unpublishedNodes = [];
foreach ($changes as $change) {
foreach ($pendingChanges as $change) {
if ($change->removalAttachmentPoint) {
$nodeAddress = new NodeAddress(
$change->contentStreamId,
Expand Down Expand Up @@ -106,7 +89,6 @@ public function getPublishableNodeInfo(WorkspaceName $workspaceName, ContentRepo
if ($node instanceof Node) {
$documentNode = $subgraph->findClosestNode($node->aggregateId, FindClosestNodeFilter::create(nodeTypes: NodeTypeNameFactory::NAME_DOCUMENT));
if ($documentNode instanceof Node) {
$contentRepository = $this->contentRepositoryRegistry->get($documentNode->contentRepositoryId);
$nodeAddressFactory = NodeAddressFactory::create($contentRepository);
$unpublishedNodes[] = [
'contextPath' => $nodeAddressFactory->createFromNode($node)->serializeForUri(),
Expand All @@ -124,44 +106,6 @@ public function getPublishableNodeInfo(WorkspaceName $workspaceName, ContentRepo
}));
}

/**
* Get allowed target workspaces for current user
*
* @return array<string,array<string,mixed>>
*/
public function getAllowedTargetWorkspaces(ContentRepository $contentRepository): array
{
$user = $this->domainUserService->getCurrentUser();

$workspacesArray = [];
foreach ($contentRepository->getWorkspaceFinder()->findAll() as $workspace) {
// FIXME: This check should be implemented through a specialized Workspace Privilege or something similar
// Skip workspace not owned by current user
if ($workspace->workspaceOwner !== null && $workspace->workspaceOwner !== $user) {
continue;
}
// Skip own personal workspace
if ($workspace->workspaceName->value === $this->userService->getPersonalWorkspaceName()) {
continue;
}

if ($workspace->isPersonalWorkspace()) {
// Skip other personal workspaces
continue;
}

$workspaceArray = [
'name' => $workspace->workspaceName->jsonSerialize(),
'title' => $workspace->workspaceTitle->jsonSerialize(),
'description' => $workspace->workspaceDescription->jsonSerialize(),
'readonly' => !$this->domainUserService->currentUserCanPublishToWorkspace($workspace)
];
$workspacesArray[$workspace->workspaceName->jsonSerialize()] = $workspaceArray;
}

return $workspacesArray;
}

private function getTypeOfChange(Change $change): int
{
$result = 0;
Expand Down
23 changes: 9 additions & 14 deletions Classes/Controller/BackendController.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,10 @@
use Neos\Flow\Annotations as Flow;
use Neos\Flow\Mvc\Controller\ActionController;
use Neos\Flow\Persistence\PersistenceManagerInterface;
use Neos\Flow\Security\Context;
use Neos\Neos\Domain\Repository\DomainRepository;
use Neos\Neos\Domain\Repository\SiteRepository;
use Neos\Neos\Domain\Service\NodeTypeNameFactory;
use Neos\Neos\Domain\Service\WorkspaceNameBuilder;
use Neos\Neos\Domain\Service\WorkspaceService;
use Neos\Neos\FrontendRouting\NodeAddressFactory;
use Neos\Neos\FrontendRouting\NodeUriBuilderFactory;
use Neos\Neos\FrontendRouting\SiteDetection\SiteDetectionResult;
Expand Down Expand Up @@ -78,12 +77,6 @@ class BackendController extends ActionController
*/
protected $contentRepositoryRegistry;

/**
* @Flow\Inject
* @var Context
*/
protected $securityContext;

/**
* @Flow\Inject
* @var ConfigurationProviderInterface
Expand Down Expand Up @@ -126,6 +119,12 @@ class BackendController extends ActionController
*/
protected $nodeUriBuilderFactory;

/**
* @Flow\Inject
* @var WorkspaceService
*/
protected $workspaceService;

/**
* Displays the backend interface
*
Expand All @@ -138,23 +137,19 @@ public function indexAction(string $node = null)
$contentRepository = $this->contentRepositoryRegistry->get($siteDetectionResult->contentRepositoryId);

$nodeAddress = $node !== null ? NodeAddressFactory::create($contentRepository)->createFromUriString($node) : null;
unset($node);
$user = $this->userService->getBackendUser();

if ($user === null) {
$this->redirectToUri($this->uriBuilder->uriFor('index', [], 'Login', 'Neos.Neos'));
}

$currentAccount = $this->securityContext->getAccount();
assert($currentAccount !== null);
$workspaceName = WorkspaceNameBuilder::fromAccountIdentifier($currentAccount->getAccountIdentifier());

try {
$contentGraph = $contentRepository->getContentGraph($workspaceName);
$workspace = $this->workspaceService->getPersonalWorkspaceForUser($siteDetectionResult->contentRepositoryId, $user->getId());
} catch (WorkspaceDoesNotExist) {
// todo will cause infinite loop: https://github.com/neos/neos-development-collection/issues/4401
$this->redirectToUri($this->uriBuilder->uriFor('index', [], 'Login', 'Neos.Neos'));
}
$contentGraph = $contentRepository->getContentGraph($workspace->workspaceName);

$backendControllerInternals = $this->contentRepositoryRegistry->buildService(
$siteDetectionResult->contentRepositoryId,
Expand Down
Loading
Loading