Skip to content

Commit

Permalink
Set workflow place only on draft dimension (#144)
Browse files Browse the repository at this point in the history
  • Loading branch information
niklasnatter authored May 20, 2020
1 parent 1ffad73 commit 4511dcb
Show file tree
Hide file tree
Showing 9 changed files with 146 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,38 @@ public function map(
*/
private function setWorkflowData(WorkflowInterface $object, array $data): void
{
$this->setInitialPlaceToDraftDimension($object, $data);
$this->setPublishedToLiveDimension($object, $data);
}

/**
* @param mixed[] $data
*/
private function setInitialPlaceToDraftDimension(WorkflowInterface $object, array $data): void
{
// we want to set the initial place only to the draft dimension, the live dimension should not have a place
// after the place was set by this mapper initially, the place should only be changed by the ContentWorkflow
// see: https://github.com/sulu/SuluContentBundle/issues/92

if (!$object instanceof DimensionContentInterface
|| DimensionInterface::STAGE_DRAFT !== $object->getDimension()->getStage()) {
return;
}

if (!$object->getWorkflowPlace()) {
// TODO: get public workflow registry and set initial place based on $object::getWorkflowName()
$object->setWorkflowPlace(WorkflowInterface::WORKFLOW_PLACE_UNPUBLISHED);
}
}

/**
* @param mixed[] $data
*/
private function setPublishedToLiveDimension(WorkflowInterface $object, array $data): void
{
// the published property of the draft dimension should only be changed by a ContentWorkflow subscriber
// therefore we only want to copy the published property from the draft to the live dimension

if (!$object instanceof DimensionContentInterface
|| DimensionInterface::STAGE_LIVE !== $object->getDimension()->getStage()) {
return;
Expand All @@ -54,7 +86,7 @@ private function setWorkflowData(WorkflowInterface $object, array $data): void
$published = $data['published'] ?? null;

if (!$published) {
return;
throw new \RuntimeException('Expected "published" to be set in the data array.');
}

$object->setWorkflowPublished(new \DateTimeImmutable($published));
Expand Down
2 changes: 1 addition & 1 deletion Content/Application/ContentWorkflow/ContentWorkflow.php
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ public function __construct(
$this->dimensionContentRepository = $dimensionContentRepository;
$this->contentMerger = $contentMerger;
$this->eventDispatcher = $eventDispatcher ?: new EventDispatcher();
// TODO get workflow from outside
// TODO: get public workflow registry from outside
$this->workflowRegistry = $workflowRegistry ?: new Registry();
$this->workflowRegistry->addWorkflow(
$this->getWorkflow(),
Expand Down
4 changes: 2 additions & 2 deletions Content/Domain/Model/WorkflowInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ interface WorkflowInterface

public static function getWorkflowName(): string;

public function getWorkflowPlace(): string;
public function getWorkflowPlace(): ?string;

public function setWorkflowPlace(string $workflowPlace): void;
public function setWorkflowPlace(?string $workflowPlace): void;

public function getWorkflowPublished(): ?\DateTimeImmutable;

Expand Down
8 changes: 4 additions & 4 deletions Content/Domain/Model/WorkflowTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@
trait WorkflowTrait
{
/**
* @var string
* @var string|null
*/
protected $workflowPlace = WorkflowInterface::WORKFLOW_PLACE_UNPUBLISHED;
protected $workflowPlace;

/**
* @var \DateTimeImmutable|null
Expand All @@ -30,12 +30,12 @@ public static function getWorkflowName(): string
return WorkflowInterface::WORKFLOW_DEFAULT_NAME;
}

public function getWorkflowPlace(): string
public function getWorkflowPlace(): ?string
{
return $this->workflowPlace;
}

public function setWorkflowPlace(string $workflowPlace): void
public function setWorkflowPlace(?string $workflowPlace): void
{
$this->workflowPlace = $workflowPlace;
}
Expand Down
2 changes: 1 addition & 1 deletion Content/Infrastructure/Doctrine/MetadataLoader.php
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ public function loadClassMetadata(LoadClassMetadataEventArgs $event): void
}

if ($reflection->implementsInterface(WorkflowInterface::class)) {
$this->addField($metadata, 'workflowPlace', 'string', ['length' => 32, 'nullable' => false, 'default' => WorkflowInterface::WORKFLOW_PLACE_UNPUBLISHED]);
$this->addField($metadata, 'workflowPlace', 'string', ['length' => 32, 'nullable' => true]);
$this->addField($metadata, 'workflowPublished', 'datetime_immutable', ['nullable' => true]);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public function testMapLocalizedNoWorkflow(): void
$workflowMapper->map($data, $dimensionContent->reveal(), $localizedDimensionContent->reveal());
}

public function testMapUnlocalizedWorkflow(): void
public function testMapUnlocalizedDraft(): void
{
$workflowMapper = $this->createWorkflowDataMapperInstance();

Expand All @@ -71,15 +71,17 @@ public function testMapUnlocalizedWorkflow(): void
$dimensionContent = $this->prophesize(DimensionContentInterface::class);
$dimensionContent->willImplement(WorkflowInterface::class);
$dimension = $this->prophesize(DimensionInterface::class);
$dimension->getStage()->willReturn(DimensionInterface::STAGE_LIVE);
$dimension->getStage()->willReturn(DimensionInterface::STAGE_DRAFT);
$dimensionContent->getDimension()->willReturn($dimension->reveal());
$dimensionContent->getWorkflowPlace()->willReturn(null);

$dimensionContent->setWorkflowPublished(Argument::cetera())->shouldBeCalled();
$dimensionContent->setWorkflowPlace(WorkflowInterface::WORKFLOW_PLACE_UNPUBLISHED)->shouldBeCalled();
$dimensionContent->setWorkflowPublished(Argument::cetera())->shouldNotBeCalled();

$workflowMapper->map($data, $dimensionContent->reveal());
}

public function testMapLocalizedWorkflow(): void
public function testMapUnlocalizedDraftPlaceAlreadySet(): void
{
$workflowMapper = $this->createWorkflowDataMapperInstance();

Expand All @@ -89,20 +91,58 @@ public function testMapLocalizedWorkflow(): void

$dimensionContent = $this->prophesize(DimensionContentInterface::class);
$dimensionContent->willImplement(WorkflowInterface::class);
$dimension = $this->prophesize(DimensionInterface::class);
$dimension->getStage()->willReturn(DimensionInterface::STAGE_DRAFT);
$dimensionContent->getDimension()->willReturn($dimension->reveal());
$dimensionContent->getWorkflowPlace()->willReturn(WorkflowInterface::WORKFLOW_PLACE_UNPUBLISHED);

$localizedDimensionContent = $this->prophesize(DimensionContentInterface::class);
$localizedDimensionContent->willImplement(WorkflowInterface::class);
$dimensionContent->setWorkflowPlace(Argument::cetera())->shouldNotBeCalled();
$dimensionContent->setWorkflowPublished(Argument::cetera())->shouldNotBeCalled();

$workflowMapper->map($data, $dimensionContent->reveal());
}

public function testMapUnlocalizedLive(): void
{
$workflowMapper = $this->createWorkflowDataMapperInstance();

$data = [
'published' => (new \DateTime())->format('c'),
];

$dimensionContent = $this->prophesize(DimensionContentInterface::class);
$dimensionContent->willImplement(WorkflowInterface::class);
$dimension = $this->prophesize(DimensionInterface::class);
$dimension->getStage()->willReturn(DimensionInterface::STAGE_LIVE);
$localizedDimensionContent->getDimension()->willReturn($dimension->reveal());
$dimensionContent->getDimension()->willReturn($dimension->reveal());

$dimensionContent->setWorkflowPublished(Argument::any())->shouldNotBeCalled();
$localizedDimensionContent->setWorkflowPublished(Argument::cetera())->shouldBeCalled();
$dimensionContent->setWorkflowPlace(Argument::cetera())->shouldNotBeCalled();
$dimensionContent->setWorkflowPublished(Argument::type(\DateTimeInterface::class))->shouldBeCalled();

$workflowMapper->map($data, $dimensionContent->reveal(), $localizedDimensionContent->reveal());
$workflowMapper->map($data, $dimensionContent->reveal());
}

public function testMapUnlocalizedLivePublishedNotSet(): void
{
$workflowMapper = $this->createWorkflowDataMapperInstance();

$data = [];

$dimensionContent = $this->prophesize(DimensionContentInterface::class);
$dimensionContent->willImplement(WorkflowInterface::class);
$dimension = $this->prophesize(DimensionInterface::class);
$dimension->getStage()->willReturn(DimensionInterface::STAGE_LIVE);
$dimensionContent->getDimension()->willReturn($dimension->reveal());

$dimensionContent->setWorkflowPlace(Argument::cetera())->shouldNotBeCalled();
$dimensionContent->setWorkflowPublished(Argument::cetera())->shouldNotBeCalled();

$this->expectException(\RuntimeException::class);

$workflowMapper->map($data, $dimensionContent->reveal());
}

public function testMapUnlocalizedDraftWorkflow(): void
public function testMapLocalizedDraft(): void
{
$workflowMapper = $this->createWorkflowDataMapperInstance();

Expand All @@ -112,16 +152,24 @@ public function testMapUnlocalizedDraftWorkflow(): void

$dimensionContent = $this->prophesize(DimensionContentInterface::class);
$dimensionContent->willImplement(WorkflowInterface::class);

$localizedDimensionContent = $this->prophesize(DimensionContentInterface::class);
$localizedDimensionContent->willImplement(WorkflowInterface::class);
$dimension = $this->prophesize(DimensionInterface::class);
$dimension->getStage()->willReturn(DimensionInterface::STAGE_DRAFT);
$dimensionContent->getDimension()->willReturn($dimension->reveal());
$localizedDimensionContent->getDimension()->willReturn($dimension->reveal());
$localizedDimensionContent->getWorkflowPlace()->willReturn(null);

$dimensionContent->setWorkflowPublished(Argument::any())->shouldNotBeCalled();
$dimensionContent->setWorkflowPlace(Argument::cetera())->shouldNotBeCalled();
$dimensionContent->setWorkflowPublished(Argument::cetera())->shouldNotBeCalled();

$workflowMapper->map($data, $dimensionContent->reveal());
$localizedDimensionContent->setWorkflowPlace(WorkflowInterface::WORKFLOW_PLACE_UNPUBLISHED)->shouldBeCalled();
$localizedDimensionContent->setWorkflowPublished(Argument::cetera())->shouldNotBeCalled();

$workflowMapper->map($data, $dimensionContent->reveal(), $localizedDimensionContent->reveal());
}

public function testMapLocalizedDraftWorkflow(): void
public function testMapLocalizedDraftPlaceAlreadySet(): void
{
$workflowMapper = $this->createWorkflowDataMapperInstance();

Expand All @@ -137,44 +185,66 @@ public function testMapLocalizedDraftWorkflow(): void
$dimension = $this->prophesize(DimensionInterface::class);
$dimension->getStage()->willReturn(DimensionInterface::STAGE_DRAFT);
$localizedDimensionContent->getDimension()->willReturn($dimension->reveal());
$localizedDimensionContent->getWorkflowPlace()->willReturn(WorkflowInterface::WORKFLOW_PLACE_UNPUBLISHED);

$dimensionContent->setWorkflowPlace(Argument::cetera())->shouldNotBeCalled();
$dimensionContent->setWorkflowPublished(Argument::cetera())->shouldNotBeCalled();

$dimensionContent->setWorkflowPublished(Argument::any())->shouldNotBeCalled();
$localizedDimensionContent->setWorkflowPublished(Argument::any())->shouldNotBeCalled();
$localizedDimensionContent->setWorkflowPlace(Argument::cetera())->shouldNotBeCalled();
$localizedDimensionContent->setWorkflowPublished(Argument::cetera())->shouldNotBeCalled();

$workflowMapper->map($data, $dimensionContent->reveal(), $localizedDimensionContent->reveal());
}

public function testMapPublishedNotExists(): void
public function testMapLocalizedLive(): void
{
$workflowMapper = $this->createWorkflowDataMapperInstance();

$data = [];
$data = [
'published' => (new \DateTime())->format('c'),
];

$dimensionContent = $this->prophesize(DimensionContentInterface::class);
$dimensionContent->willImplement(WorkflowInterface::class);

$localizedDimensionContent = $this->prophesize(DimensionContentInterface::class);
$localizedDimensionContent->willImplement(WorkflowInterface::class);
$dimension = $this->prophesize(DimensionInterface::class);
$dimension->getStage()->willReturn(DimensionInterface::STAGE_LIVE);
$dimensionContent->getDimension()->willReturn($dimension->reveal());
$localizedDimensionContent->getDimension()->willReturn($dimension->reveal());

$dimensionContent->setWorkflowPublished(Argument::any())->shouldNotBeCalled();
$dimensionContent->setWorkflowPlace(Argument::cetera())->shouldNotBeCalled();
$dimensionContent->setWorkflowPublished(Argument::cetera())->shouldNotBeCalled();

$workflowMapper->map($data, $dimensionContent->reveal());
$localizedDimensionContent->setWorkflowPlace(Argument::cetera())->shouldNotBeCalled();
$localizedDimensionContent->setWorkflowPublished(Argument::type(\DateTimeInterface::class))->shouldBeCalled();

$workflowMapper->map($data, $dimensionContent->reveal(), $localizedDimensionContent->reveal());
}

public function testMapPublishedNull(): void
public function testMapLocalizedLivePublishedNotSet(): void
{
$workflowMapper = $this->createWorkflowDataMapperInstance();

$data = [];

$dimensionContent = $this->prophesize(DimensionContentInterface::class);
$dimensionContent->willImplement(WorkflowInterface::class);

$localizedDimensionContent = $this->prophesize(DimensionContentInterface::class);
$localizedDimensionContent->willImplement(WorkflowInterface::class);
$dimension = $this->prophesize(DimensionInterface::class);
$dimension->getStage()->willReturn(DimensionInterface::STAGE_LIVE);
$dimensionContent->getDimension()->willReturn($dimension->reveal());
$localizedDimensionContent->getDimension()->willReturn($dimension->reveal());

$dimensionContent->setWorkflowPublished(Argument::any())->shouldNotBeCalled();
$dimensionContent->setWorkflowPlace(Argument::cetera())->shouldNotBeCalled();
$dimensionContent->setWorkflowPublished(Argument::cetera())->shouldNotBeCalled();

$workflowMapper->map($data, $dimensionContent->reveal());
$localizedDimensionContent->setWorkflowPlace(Argument::cetera())->shouldNotBeCalled();
$localizedDimensionContent->setWorkflowPublished(Argument::cetera())->shouldNotBeCalled();

$this->expectException(\RuntimeException::class);

$workflowMapper->map($data, $dimensionContent->reveal(), $localizedDimensionContent->reveal());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,10 @@ public function getContentRichEntity(): ContentRichEntityInterface
$object->setTemplateKey('template-key');
$object->setTemplateData(['someTemplate' => 'data']);

$published = new \DateTimeImmutable('2020-02-02T12:30:00+00:00');
$object->setWorkflowPlace(WorkflowInterface::WORKFLOW_PLACE_DRAFT);
$object->setWorkflowPublished($published);

$contentNormalizer = $this->createContentNormalizerInstance();

$this->assertSame([
Expand All @@ -181,7 +185,7 @@ public function getContentRichEntity(): ContentRichEntityInterface
'excerptTitle' => 'Excerpt Title',
'id' => 5,
'locale' => 'de',
'published' => null,
'published' => '2020-02-02T12:30:00+00:00',
'publishedState' => false,
'seoCanonicalUrl' => 'https://caninical.localhost/',
'seoDescription' => 'Seo Description',
Expand All @@ -193,7 +197,7 @@ public function getContentRichEntity(): ContentRichEntityInterface
'someTemplate' => 'data',
'stage' => 'live',
'template' => 'template-key',
'workflowPlace' => 'unpublished',
'workflowPlace' => 'draft',
], $contentNormalizer->normalize($object));
}
}
2 changes: 1 addition & 1 deletion Tests/Unit/Content/Domain/Model/WorkflowTraitTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ protected function getWorkflowInstance(): WorkflowInterface
public function testGetWorkflowPlace(): void
{
$workflow = $this->getWorkflowInstance();
$this->assertSame('unpublished', $workflow->getWorkflowPlace());
$this->assertNull($workflow->getWorkflowPlace());
}

public function testSetWorkflowPlaceReview(): void
Expand Down
4 changes: 2 additions & 2 deletions Tests/Unit/Mocks/WorkflowMockWrapperTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@ public static function getWorkflowName(): string
return 'mock-workflow-name';
}

public function getWorkflowPlace(): string
public function getWorkflowPlace(): ?string
{
return $this->instance->getWorkflowPlace();
}

public function setWorkflowPlace(string $workflowPlace): void
public function setWorkflowPlace(?string $workflowPlace): void
{
$this->instance->setWorkflowPlace($workflowPlace);
}
Expand Down

0 comments on commit 4511dcb

Please sign in to comment.