Skip to content

Commit

Permalink
Merge pull request #3769 from neos/feature/conflict-resolution-03/reb…
Browse files Browse the repository at this point in the history
…ase-during-publish

FEATURE: Integrate conflict resolution with publish/discard dialog workflow
  • Loading branch information
mhsdesign authored Oct 29, 2024
2 parents aff0cd7 + 68fdde5 commit 147a733
Show file tree
Hide file tree
Showing 27 changed files with 871 additions and 357 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,37 +12,43 @@

declare(strict_types=1);

namespace Neos\Neos\Ui\Application;
namespace Neos\Neos\Ui\Application\PublishChangesInDocument;

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\WorkspaceName;
use Neos\Flow\Annotations as Flow;

/**
* The application layer level command DTO to communicate publication of all changes recorded for a given document
* The application layer level command DTO to communicate publication of
* all changes recorded for a given document
*
* @internal for communication within the Neos UI only
*/
#[Flow\Proxy(false)]
final readonly class PublishChangesInDocument
final readonly class PublishChangesInDocumentCommand
{
public function __construct(
public ContentRepositoryId $contentRepositoryId,
public WorkspaceName $workspaceName,
public NodeAggregateId $documentId,
public ?DimensionSpacePoint $preferredDimensionSpacePoint,
) {
}

/**
* @param array<string,string> $values
* @param array{contentRepositoryId:string,workspaceName:string,documentId:string,preferredDimensionSpacePoint?:array<string,string[]>} $values
*/
public static function fromArray(array $values): self
{
return new self(
ContentRepositoryId::fromString($values['contentRepositoryId']),
WorkspaceName::fromString($values['workspaceName']),
NodeAggregateId::fromString($values['documentId']),
isset($values['preferredDimensionSpacePoint']) && !empty($values['preferredDimensionSpacePoint'])
? DimensionSpacePoint::fromLegacyDimensionArray($values['preferredDimensionSpacePoint'])
: null,
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<?php

/*
* This file is part of the Neos.Neos package.
*
* (c) Contributors of the Neos Project - www.neos.io
*
* This package is Open Source Software. For the full copyright and license
* information, please view the LICENSE file which was distributed with this
* source code.
*/

declare(strict_types=1);

namespace Neos\Neos\Ui\Application\PublishChangesInDocument;

use Neos\ContentRepository\Core\Feature\WorkspaceRebase\Exception\WorkspaceRebaseFailed;
use Neos\ContentRepository\Core\SharedModel\Exception\NodeAggregateCurrentlyDoesNotExist;
use Neos\ContentRepository\Core\SharedModel\Exception\NodeAggregateDoesCurrentlyNotCoverDimensionSpacePoint;
use Neos\ContentRepositoryRegistry\ContentRepositoryRegistry;
use Neos\Flow\Annotations as Flow;
use Neos\Neos\Domain\NodeLabel\NodeLabelGeneratorInterface;
use Neos\Neos\Domain\Service\WorkspacePublishingService;
use Neos\Neos\Ui\Application\Shared\ConflictsOccurred;
use Neos\Neos\Ui\Application\Shared\PublishSucceeded;
use Neos\Neos\Ui\Controller\TranslationTrait;
use Neos\Neos\Ui\Infrastructure\ContentRepository\ConflictsFactory;

/**
* The application layer level command handler to perform publication of
* all changes recorded for a given document
*
* @internal for communication within the Neos UI only
*/
#[Flow\Scope("singleton")]
final class PublishChangesInDocumentCommandHandler
{
use TranslationTrait;

#[Flow\Inject]
protected ContentRepositoryRegistry $contentRepositoryRegistry;

#[Flow\Inject]
protected WorkspacePublishingService $workspacePublishingService;

#[Flow\Inject]
protected NodeLabelGeneratorInterface $nodeLabelGenerator;

/**
* @throws NodeAggregateCurrentlyDoesNotExist
*/
public function handle(
PublishChangesInDocumentCommand $command
): PublishSucceeded|ConflictsOccurred {
try {
$publishingResult = $this->workspacePublishingService->publishChangesInDocument(
$command->contentRepositoryId,
$command->workspaceName,
$command->documentId
);

$workspace = $this->contentRepositoryRegistry->get($command->contentRepositoryId)->findWorkspaceByName(
$command->workspaceName
);

return new PublishSucceeded(
numberOfAffectedChanges: $publishingResult->numberOfPublishedChanges,
baseWorkspaceName: $workspace?->baseWorkspaceName?->value
);
} catch (NodeAggregateCurrentlyDoesNotExist $e) {
throw new \RuntimeException(
$this->getLabel('NodeNotPublishedMissingParentNode'),
1705053430,
$e
);
} catch (NodeAggregateDoesCurrentlyNotCoverDimensionSpacePoint $e) {
throw new \RuntimeException(
$this->getLabel('NodeNotPublishedParentNodeNotInCurrentDimension'),
1705053432,
$e
);
} catch (WorkspaceRebaseFailed $e) {
$conflictsFactory = new ConflictsFactory(
contentRepository: $this->contentRepositoryRegistry
->get($command->contentRepositoryId),
nodeLabelGenerator: $this->nodeLabelGenerator,
workspaceName: $command->workspaceName,
preferredDimensionSpacePoint: $command->preferredDimensionSpacePoint
);

return new ConflictsOccurred(
conflicts: $conflictsFactory->fromWorkspaceRebaseFailed($e)
);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,37 +12,43 @@

declare(strict_types=1);

namespace Neos\Neos\Ui\Application;
namespace Neos\Neos\Ui\Application\PublishChangesInSite;

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\WorkspaceName;
use Neos\Flow\Annotations as Flow;

/**
* The application layer level command DTO to communicate publication of all changes recorded for a given site
* The application layer level command DTO to communicate publication of
* all changes recorded for a given site
*
* @internal for communication within the Neos UI only
*/
#[Flow\Proxy(false)]
final readonly class PublishChangesInSite
final readonly class PublishChangesInSiteCommand
{
public function __construct(
public ContentRepositoryId $contentRepositoryId,
public WorkspaceName $workspaceName,
public NodeAggregateId $siteId,
public ?DimensionSpacePoint $preferredDimensionSpacePoint,
) {
}

/**
* @param array<string,string> $values
* @param array{contentRepositoryId:string,workspaceName:string,siteId:string,preferredDimensionSpacePoint?:array<string,string[]>} $values
*/
public static function fromArray(array $values): self
{
return new self(
ContentRepositoryId::fromString($values['contentRepositoryId']),
WorkspaceName::fromString($values['workspaceName']),
NodeAggregateId::fromString($values['siteId']),
isset($values['preferredDimensionSpacePoint']) && !empty($values['preferredDimensionSpacePoint'])
? DimensionSpacePoint::fromLegacyDimensionArray($values['preferredDimensionSpacePoint'])
: null,
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<?php

/*
* This file is part of the Neos.Neos.Ui package.
*
* (c) Contributors of the Neos Project - www.neos.io
*
* This package is Open Source Software. For the full copyright and license
* information, please view the LICENSE file which was distributed with this
* source code.
*/

declare(strict_types=1);

namespace Neos\Neos\Ui\Application\PublishChangesInSite;

use Neos\ContentRepository\Core\Feature\WorkspaceRebase\Exception\WorkspaceRebaseFailed;
use Neos\ContentRepositoryRegistry\ContentRepositoryRegistry;
use Neos\Flow\Annotations as Flow;
use Neos\Neos\Domain\NodeLabel\NodeLabelGeneratorInterface;
use Neos\Neos\Domain\Service\WorkspacePublishingService;
use Neos\Neos\Ui\Application\Shared\ConflictsOccurred;
use Neos\Neos\Ui\Application\Shared\PublishSucceeded;
use Neos\Neos\Ui\Infrastructure\ContentRepository\ConflictsFactory;

/**
* The application layer level command handler to perform publication of
* all changes recorded for a given site
*
* @internal for communication within the Neos UI only
*/
#[Flow\Scope("singleton")]
final class PublishChangesInSiteCommandHandler
{
#[Flow\Inject]
protected ContentRepositoryRegistry $contentRepositoryRegistry;

#[Flow\Inject]
protected WorkspacePublishingService $workspacePublishingService;

#[Flow\Inject]
protected NodeLabelGeneratorInterface $nodeLabelGenerator;

public function handle(
PublishChangesInSiteCommand $command
): PublishSucceeded|ConflictsOccurred {
try {
$publishingResult = $this->workspacePublishingService->publishChangesInSite(
$command->contentRepositoryId,
$command->workspaceName,
$command->siteId
);

$workspace = $this->contentRepositoryRegistry->get($command->contentRepositoryId)->findWorkspaceByName(
$command->workspaceName
);

return new PublishSucceeded(
numberOfAffectedChanges: $publishingResult->numberOfPublishedChanges,
baseWorkspaceName: $workspace?->baseWorkspaceName?->value
);
} catch (WorkspaceRebaseFailed $e) {
$conflictsFactory = new ConflictsFactory(
contentRepository: $this->contentRepositoryRegistry
->get($command->contentRepositoryId),
nodeLabelGenerator: $this->nodeLabelGenerator,
workspaceName: $command->workspaceName,
preferredDimensionSpacePoint: $command->preferredDimensionSpacePoint
);

return new ConflictsOccurred(
conflicts: $conflictsFactory->fromWorkspaceRebaseFailed($e)
);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@

declare(strict_types=1);

namespace Neos\Neos\Ui\Application\SyncWorkspace;
namespace Neos\Neos\Ui\Application\Shared;

use Neos\ContentRepository\Core\SharedModel\Node\NodeAggregateId;
use Neos\Flow\Annotations as Flow;

/**
Expand All @@ -25,6 +26,7 @@
final readonly class Conflict implements \JsonSerializable
{
public function __construct(
public string $key,
public ?IconLabel $affectedSite,
public ?IconLabel $affectedDocument,
public ?IconLabel $affectedNode,
Expand Down
42 changes: 42 additions & 0 deletions Classes/Application/Shared/Conflicts.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

/*
* This file is part of the Neos.Neos.Ui package.
*
* (c) Contributors of the Neos Project - www.neos.io
*
* This package is Open Source Software. For the full copyright and license
* information, please view the LICENSE file which was distributed with this
* source code.
*/

declare(strict_types=1);

namespace Neos\Neos\Ui\Application\Shared;

use Neos\Flow\Annotations as Flow;

/**
* @internal for communication within the Neos UI only
*/
#[Flow\Proxy(false)]
final readonly class Conflicts implements \JsonSerializable, \Countable
{
/** @var Conflict[] */
private array $items;

public function __construct(Conflict ...$items)
{
$this->items = array_values($items);
}

public function jsonSerialize(): mixed
{
return $this->items;
}

public function count(): int
{
return count($this->items);
}
}
34 changes: 34 additions & 0 deletions Classes/Application/Shared/ConflictsOccurred.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

/*
* This file is part of the Neos.Neos.Ui package.
*
* (c) Contributors of the Neos Project - www.neos.io
*
* This package is Open Source Software. For the full copyright and license
* information, please view the LICENSE file which was distributed with this
* source code.
*/

declare(strict_types=1);

namespace Neos\Neos\Ui\Application\Shared;

use Neos\Flow\Annotations as Flow;

/**
* @internal for communication within the Neos UI only
*/
#[Flow\Proxy(false)]
final readonly class ConflictsOccurred implements \JsonSerializable
{
public function __construct(
public readonly Conflicts $conflicts
) {
}

public function jsonSerialize(): mixed
{
return get_object_vars($this);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

declare(strict_types=1);

namespace Neos\Neos\Ui\Application\SyncWorkspace;
namespace Neos\Neos\Ui\Application\Shared;

use Neos\Flow\Annotations as Flow;

Expand Down
Loading

0 comments on commit 147a733

Please sign in to comment.