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

TASK: Cleanup & fix workspace cli commands #4465

Merged
merged 9 commits into from
Sep 11, 2023

This file was deleted.

180 changes: 72 additions & 108 deletions Neos.Neos/Classes/Command/WorkspaceCommandController.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
use Neos\ContentRepository\Core\Feature\WorkspacePublication\Command\DiscardWorkspace;
use Neos\ContentRepository\Core\Feature\WorkspacePublication\Command\PublishWorkspace;
use Neos\ContentRepository\Core\Projection\Workspace\Workspace;
use Neos\ContentRepository\Core\Service\WorkspaceMaintenanceServiceFactory;
use Neos\ContentRepository\Core\SharedModel\Exception\WorkspaceDoesNotExist;
use Neos\ContentRepository\Core\SharedModel\User\UserId;
use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamId;
Expand All @@ -31,22 +32,18 @@
use Neos\ContentRepositoryRegistry\ContentRepositoryRegistry;
use Neos\Flow\Annotations as Flow;
use Neos\Flow\Cli\CommandController;
use Neos\Flow\Cli\Exception\StopCommandException;
use Neos\Flow\Persistence\PersistenceManagerInterface;
use Neos\Neos\Domain\Service\UserService;
use Symfony\Component\Serializer\Exception\ExceptionInterface;

/**
* The Workspace Command Controller
*
* @Flow\Scope("singleton")
*/
#[Flow\Scope('singleton')]
class WorkspaceCommandController extends CommandController
{
/**
* @Flow\Inject
* @var UserService
*/
protected $userService;
#[Flow\Inject]
protected UserService $userService;

#[Flow\Inject]
protected PersistenceManagerInterface $persistenceManager;
Expand All @@ -58,34 +55,23 @@ class WorkspaceCommandController extends CommandController
* Publish changes of a workspace
*
* This command publishes all modified, created or deleted nodes in the specified workspace to its base workspace.
* If a target workspace is specified, the content is published to that workspace instead.
*
* @param string $workspace Name of the workspace containing the changes to publish, for example "user-john"
* @param string $contentRepositoryIdentifier
* @param boolean $verbose If enabled, some information about individual nodes will be displayed
* @param boolean $dryRun If set, only displays which nodes would be published, no real changes are committed
* @return void
* @throws ExceptionInterface
*/
public function publishCommand(
$workspace,
string $contentRepositoryIdentifier = 'default',
$verbose = false,
$dryRun = false
) {
public function publishCommand(string $workspace, string $contentRepositoryIdentifier = 'default'): void
{
$contentRepositoryId = ContentRepositoryId::fromString($contentRepositoryIdentifier);
$contentRepository = $this->contentRepositoryRegistry->get($contentRepositoryId);

if (!$dryRun) {
$contentRepository->handle(new PublishWorkspace(
WorkspaceName::fromString($workspace),
))->block();
$contentRepository->handle(new PublishWorkspace(
WorkspaceName::fromString($workspace),
))->block();

$this->outputLine(
'Published all nodes in workspace %s to its base workspace',
[$workspace]
);
}
$this->outputLine(
'Published all nodes in workspace %s to its base workspace',
[$workspace]
);
}

/**
Expand All @@ -94,34 +80,33 @@ public function publishCommand(
* This command discards all modified, created or deleted nodes in the specified workspace.
*
* @param string $workspace Name of the workspace, for example "user-john"
* @param boolean $verbose If enabled, information about individual nodes will be displayed
* @param boolean $dryRun If set, only displays which nodes would be discarded, no real changes are committed
* @return void
* @param string $contentRepositoryIdentifier
* @throws StopCommandException
*/
public function discardCommand(
$workspace,
string $contentRepositoryIdentifier = 'default',
$verbose = false,
$dryRun = false
) {
public function discardCommand(string $workspace, string $contentRepositoryIdentifier = 'default'): void
{
$contentRepositoryId = ContentRepositoryId::fromString($contentRepositoryIdentifier);
$contentRepository = $this->contentRepositoryRegistry->get($contentRepositoryId);

if (!$dryRun) {
try {
$contentRepository->handle(
DiscardWorkspace::create(
WorkspaceName::fromString($workspace),
)
)->block();
} catch (WorkspaceDoesNotExist $exception) {
$this->outputLine('Workspace "%s" does not exist', [$workspace]);
$this->quit(1);
}
$this->outputLine('Discarded all nodes in workspace %s', [$workspace]);
try {
$contentRepository->handle(
DiscardWorkspace::create(
WorkspaceName::fromString($workspace),
)
)->block();
} catch (WorkspaceDoesNotExist $exception) {
$this->outputLine('Workspace "%s" does not exist', [$workspace]);
$this->quit(1);
}
$this->outputLine('Discarded all nodes in workspace %s', [$workspace]);
}

/**
* Create a new root workspace for a content repository.
*
* @param string $name
* @param string $contentRepositoryIdentifier
*/
public function createRootCommand(string $name, string $contentRepositoryIdentifier = 'default'): void
{
$contentRepositoryId = ContentRepositoryId::fromString($contentRepositoryIdentifier);
Expand All @@ -142,26 +127,28 @@ public function createRootCommand(string $name, string $contentRepositoryIdentif
*
* @param string $workspace Name of the workspace, for example "christmas-campaign"
* @param string $baseWorkspace Name of the base workspace. If none is specified, "live" is assumed.
* @param string $title Human friendly title of the workspace, for example "Christmas Campaign"
* @param string $description A description explaining the purpose of the new workspace
* @param string|null $title Human friendly title of the workspace, for example "Christmas Campaign"
* @param string|null $description A description explaining the purpose of the new workspace
* @param string $owner The identifier of a User to own the workspace
* @return void
* @param string $contentRepositoryIdentifier
* @throws StopCommandException
*/
public function createCommand(
$workspace,
$baseWorkspace = 'live',
$title = null,
$description = null,
$owner = '',
string $workspace,
string $baseWorkspace = 'live',
string $title = null,
string $description = null,
string $owner = '',
string $contentRepositoryIdentifier = 'default'
) {
): void {
$contentRepositoryId = ContentRepositoryId::fromString($contentRepositoryIdentifier);
$contentRepository = $this->contentRepositoryRegistry->get($contentRepositoryId);

if ($owner === '') {
$workspaceOwner = null;
$workspaceOwnerUserId = null;
} else {
$workspaceOwner = $this->userService->getCurrentUserIdentifier();
$workspaceOwnerUserId = UserId::fromString($owner);
$workspaceOwner = $this->userService->findByUserIdentifier($workspaceOwnerUserId);
if ($workspaceOwner === null) {
$this->outputLine('The user "%s" specified as owner does not exist', [$owner]);
$this->quit(3);
Expand All @@ -175,7 +162,7 @@ public function createCommand(
WorkspaceTitle::fromString($title ?: $workspace),
WorkspaceDescription::fromString($description ?: $workspace),
ContentStreamId::create(),
$workspaceOwner
$workspaceOwnerUserId
))->block();
} catch (WorkspaceAlreadyExists $workspaceAlreadyExists) {
$this->outputLine('Workspace "%s" already exists', [$workspace]);
Expand All @@ -185,7 +172,7 @@ public function createCommand(
$this->quit(2);
}

if ($workspaceOwner instanceof UserId) {
if ($workspaceOwnerUserId instanceof UserId) {
$this->outputLine(
'Created a new workspace "%s", based on workspace "%s", owned by "%s".',
[$workspace, $baseWorkspace, $owner]
Expand All @@ -206,10 +193,9 @@ public function createCommand(
*
* @param string $workspace Name of the workspace, for example "christmas-campaign"
* @param boolean $force Delete the workspace and all of its contents
* @return void
* @see neos.neos:workspace:discard
*/
public function deleteCommand($workspace, $force = false, string $contentRepositoryIdentifier = 'default')
public function deleteCommand(string $workspace, bool $force = false, string $contentRepositoryIdentifier = 'default'): void
{
throw new \BadMethodCallException(
'Workspace removal is not supported yet',
Expand Down Expand Up @@ -290,56 +276,32 @@ public function deleteCommand($workspace, $force = false, string $contentReposit
}

/**
* Rebase a workspace
*
* This command sets a new base workspace for the specified workspace. Note that doing so will put the possible
* changes contained in the workspace to be rebased into a different context and thus might lead to unintended
* results when being published.
*
* @param string $workspace Name of the workspace to rebase, for example "user-john"
* @param string $baseWorkspace Name of the new base workspace
* @return void
* Rebase all outdated content streams
*/
public function rebaseCommand($workspace, $baseWorkspace, string $contentRepositoryIdentifier = 'default')
public function rebaseOutdatedCommand(string $contentRepositoryIdentifier = 'default'): void
{
throw new \BadMethodCallException(
'Workspace rebasing is now a different concept ("real", git-like rebase <3),'
. ' changing the base workspace is not yet supported',
1651960852
$contentRepositoryId = ContentRepositoryId::fromString($contentRepositoryIdentifier);
$workspaceMaintenanceService = $this->contentRepositoryRegistry->buildService(
$contentRepositoryId,
new WorkspaceMaintenanceServiceFactory()
);
/*
$workspaceName = $workspace;
$workspace = $this->workspaceFinder->findOneByName(WorkspaceName::fromString($workspaceName));
if (!$workspace instanceof Workspace) {
$this->outputLine('Workspace "%s" does not exist', [$workspaceName]);
$this->quit(1);
}
$outdatedWorkspaces = $workspaceMaintenanceService->rebaseOutdatedWorkspaces();

if ($workspace->getName() === 'live') {
$this->outputLine('The workspace "live" cannot be rebased as it is the global base workspace.');
$this->quit(2);
}

$baseWorkspaceName = $baseWorkspace;
$baseWorkspace = $this->workspaceFinder->findOneByName($baseWorkspaceName);
if (!$baseWorkspace instanceof Workspace) {
$this->outputLine('The base workspace "%s" does not exist', [$baseWorkspaceName]);
$this->quit(2);
if (!count($outdatedWorkspaces)) {
$this->outputLine('There are no outdated workspaces.');
} else {
foreach ($outdatedWorkspaces as $outdatedWorkspace) {
$this->outputFormatted('Rebased workspace %s', [$outdatedWorkspace->workspaceName->value]);
}
}

$workspace->setBaseWorkspace($baseWorkspace);
$this->workspaceFinder->update($workspace);

$this->outputLine('Set "%s" as the new base workspace for "%s".', [$baseWorkspaceName, $workspaceName]);
*/
}

/**
* Display a list of existing workspaces
*
* @return void
* @throws StopCommandException
*/
public function listCommand(string $contentRepositoryIdentifier = 'default')
public function listCommand(string $contentRepositoryIdentifier = 'default'): void
{
$contentRepositoryId = ContentRepositoryId::fromString($contentRepositoryIdentifier);
$contentRepository = $this->contentRepositoryRegistry->get($contentRepositoryId);
Expand All @@ -352,16 +314,18 @@ public function listCommand(string $contentRepositoryIdentifier = 'default')
}

$tableRows = [];
$headerRow = ['Name', 'Base Workspace', 'Title', 'Owner', 'Description'];
$headerRow = ['Name', 'Base Workspace', 'Title', 'Owner', 'Description', 'Status', 'Content Stream'];

foreach ($workspaces as $workspace) {
/* @var Workspace $workspace */
$tableRows[] = [
$workspace->workspaceName,
$workspace->baseWorkspaceName ?: '',
$workspace->workspaceTitle,
$workspace->workspaceName->value,
$workspace->baseWorkspaceName?->value ?: '',
$workspace->workspaceTitle?->value,
$workspace->workspaceOwner ?: '',
$workspace->workspaceDescription
$workspace->workspaceDescription->value,
$workspace->status->value,
$workspace->currentContentStreamId->value,
];
}
$this->output->outputTable($tableRows, $headerRow);
Expand Down