Skip to content

Commit

Permalink
Merge pull request #5307 from neos/feature/4448-site-import
Browse files Browse the repository at this point in the history
!!! FEATURE: High level Neos site import `site:importAll`
  • Loading branch information
mhsdesign authored Nov 12, 2024
2 parents 85b6a4d + 5696f36 commit 3a5b6c5
Show file tree
Hide file tree
Showing 58 changed files with 1,940 additions and 1,454 deletions.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
@contentrepository
Feature: As a user of the CR I want to export the event stream
Feature: As a user of the CR I want to export the event stream using the EventExportProcessor

Background:
Given using the following content dimensions:
Expand All @@ -12,9 +12,9 @@ Feature: As a user of the CR I want to export the event stream
And using identifier "default", I define a content repository
And I am in content repository "default"
And the command CreateRootWorkspace is executed with payload:
| Key | Value |
| workspaceName | "live" |
| newContentStreamId | "cs-identifier" |
| Key | Value |
| workspaceName | "live" |
| newContentStreamId | "cs-identifier" |
And I am in workspace "live"
And the command CreateRootNodeAggregateWithNode is executed with payload:
| Key | Value |
Expand All @@ -37,7 +37,7 @@ Feature: As a user of the CR I want to export the event stream
When the events are exported
Then I expect the following jsonl:
"""
{"identifier":"random-event-uuid","type":"RootNodeAggregateWithNodeWasCreated","payload":{"workspaceName":"live","contentStreamId":"cs-identifier","nodeAggregateId":"lady-eleonode-rootford","nodeTypeName":"Neos.ContentRepository:Root","coveredDimensionSpacePoints":[{"language":"de"},{"language":"gsw"},{"language":"fr"}],"nodeAggregateClassification":"root"},"metadata":{"commandClass":"Neos\\ContentRepository\\Core\\Feature\\RootNodeCreation\\Command\\CreateRootNodeAggregateWithNode","commandPayload":{"workspaceName":"live","nodeAggregateId":"lady-eleonode-rootford","nodeTypeName":"Neos.ContentRepository:Root","tetheredDescendantNodeAggregateIds":[]},"initiatingUserId":"system","initiatingTimestamp":"random-time"}}
{"identifier":"random-event-uuid","type":"NodeAggregateWithNodeWasCreated","payload":{"workspaceName":"live","contentStreamId":"cs-identifier","nodeAggregateId":"nody-mc-nodeface","nodeTypeName":"Neos.ContentRepository.Testing:Document","originDimensionSpacePoint":{"language":"de"},"succeedingSiblingsForCoverage":[{"dimensionSpacePoint":{"language":"de"},"nodeAggregateId":null},{"dimensionSpacePoint":{"language":"gsw"},"nodeAggregateId":null},{"dimensionSpacePoint":{"language":"fr"},"nodeAggregateId":null}],"parentNodeAggregateId":"lady-eleonode-rootford","nodeName":"child-document","initialPropertyValues":[],"nodeAggregateClassification":"regular","nodeReferences":[]},"metadata":{"initiatingTimestamp":"random-time"}}
{"identifier":"random-event-uuid","type":"RootNodeAggregateWithNodeWasCreated","payload":{"nodeAggregateId":"lady-eleonode-rootford","nodeTypeName":"Neos.ContentRepository:Root","coveredDimensionSpacePoints":[{"language":"de"},{"language":"gsw"},{"language":"fr"}],"nodeAggregateClassification":"root"},"metadata":{"commandClass":"Neos\\ContentRepository\\Core\\Feature\\RootNodeCreation\\Command\\CreateRootNodeAggregateWithNode","commandPayload":{"workspaceName":"live","nodeAggregateId":"lady-eleonode-rootford","nodeTypeName":"Neos.ContentRepository:Root","tetheredDescendantNodeAggregateIds":[]},"initiatingUserId":"system","initiatingTimestamp":"random-time"}}
{"identifier":"random-event-uuid","type":"NodeAggregateWithNodeWasCreated","payload":{"nodeAggregateId":"nody-mc-nodeface","nodeTypeName":"Neos.ContentRepository.Testing:Document","originDimensionSpacePoint":{"language":"de"},"succeedingSiblingsForCoverage":[{"dimensionSpacePoint":{"language":"de"},"nodeAggregateId":null},{"dimensionSpacePoint":{"language":"gsw"},"nodeAggregateId":null},{"dimensionSpacePoint":{"language":"fr"},"nodeAggregateId":null}],"parentNodeAggregateId":"lady-eleonode-rootford","nodeName":"child-document","initialPropertyValues":[],"nodeAggregateClassification":"regular","nodeReferences":[]},"metadata":{"initiatingTimestamp":"random-time"}}
"""
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
@contentrepository
Feature: As a user of the CR I want to export the event stream
Feature: As a user of the CR I want to import events using the EventStoreImportProcessor

Background:
Given using no content dimensions
Expand All @@ -11,56 +11,59 @@ Feature: As a user of the CR I want to export the event stream
"""
And using identifier "default", I define a content repository
And I am in content repository "default"
And the command CreateRootWorkspace is executed with payload:
| Key | Value |
| workspaceName | "live" |
| newContentStreamId | "cs-identifier" |
And I am in workspace "live"

Scenario: Import the event stream into a specific content stream
Then I expect exactly 0 events to be published on stream with prefix "ContentStream:cs-identifier"
Given using the following events.jsonl:
"""
{"identifier":"9f64c281-e5b0-48d9-900b-288a8faf92a9","type":"RootNodeAggregateWithNodeWasCreated","payload":{"workspaceName":"workspace-name","contentStreamId":"cs-imported-identifier","nodeAggregateId":"acme-site-sites","nodeTypeName":"Neos.Neos:Sites","coveredDimensionSpacePoints":[[]],"nodeAggregateClassification":"root"},"metadata":[]}
{"identifier":"1640ebbf-7ffe-4526-b0f4-7575cefabfab","type":"NodeAggregateWithNodeWasCreated","payload":{"workspaceName":"workspace-name","contentStreamId":"cs-imported-identifier","nodeAggregateId":"acme-site","nodeTypeName":"Vendor.Site:HomePage","originDimensionSpacePoint":[],"succeedingSiblingsForCoverage":[{"dimensionSpacePoint":[],"nodeAggregateId":null}],"parentNodeAggregateId":"acme-site-sites","nodeName":"acme-site","initialPropertyValues":{"title":{"value":"My Site","type":"string"},"uriPathSegment":{"value":"my-site","type":"string"}},"nodeAggregateClassification":"regular"},"metadata":[]}
"""
And I import the events.jsonl into "cs-identifier"
And I import the events.jsonl into workspace "live"
Then I expect exactly 3 events to be published on stream with prefix "ContentStream:cs-identifier"
And event at index 0 is of type "ContentStreamWasCreated" with payload:
| Key | Expected |
| contentStreamId | "cs-identifier" |
And event at index 1 is of type "RootNodeAggregateWithNodeWasCreated" with payload:
| Key | Expected |
| workspaceName | "workspace-name" |
| workspaceName | "live" |
| contentStreamId | "cs-identifier" |
| nodeAggregateId | "acme-site-sites" |
| nodeTypeName | "Neos.Neos:Sites" |
And event at index 2 is of type "NodeAggregateWithNodeWasCreated" with payload:
| Key | Expected |
| workspaceName | "workspace-name" |
| workspaceName | "live" |
| contentStreamId | "cs-identifier" |
| nodeAggregateId | "acme-site" |
| nodeTypeName | "Vendor.Site:HomePage" |

Scenario: Import the event stream
Then I expect exactly 0 events to be published on stream with prefix "ContentStream:cs-imported-identifier"
Given using the following events.jsonl:
"""
{"identifier":"9f64c281-e5b0-48d9-900b-288a8faf92a9","type":"RootNodeAggregateWithNodeWasCreated","payload":{"workspaceName":"workspace-name","contentStreamId":"cs-imported-identifier","nodeAggregateId":"acme-site-sites","nodeTypeName":"Neos.Neos:Sites","coveredDimensionSpacePoints":[[]],"nodeAggregateClassification":"root"},"metadata":[]}
{"identifier":"1640ebbf-7ffe-4526-b0f4-7575cefabfab","type":"NodeAggregateWithNodeWasCreated","payload":{"workspaceName":"workspace-name","contentStreamId":"cs-imported-identifier","nodeAggregateId":"acme-site","nodeTypeName":"Vendor.Site:HomePage","originDimensionSpacePoint":[],"succeedingSiblingsForCoverage":[{"dimensionSpacePoint":[],"nodeAggregateId":null}],"parentNodeAggregateId":"acme-site-sites","nodeName":"acme-site","initialPropertyValues":{"title":{"value":"My Site","type":"string"},"uriPathSegment":{"value":"my-site","type":"string"}},"nodeAggregateClassification":"regular"},"metadata":[]}
"""
And I import the events.jsonl
Then I expect exactly 3 events to be published on stream with prefix "ContentStream:cs-imported-identifier"
Then I expect exactly 3 events to be published on stream with prefix "ContentStream:cs-identifier"
And event at index 0 is of type "ContentStreamWasCreated" with payload:
| Key | Expected |
| contentStreamId | "cs-imported-identifier" |
| Key | Expected |
| contentStreamId | "cs-identifier" |
And event at index 1 is of type "RootNodeAggregateWithNodeWasCreated" with payload:
| Key | Expected |
| workspaceName | "workspace-name" |
| contentStreamId | "cs-imported-identifier" |
| nodeAggregateId | "acme-site-sites" |
| nodeTypeName | "Neos.Neos:Sites" |
| Key | Expected |
| workspaceName | "live" |
| contentStreamId | "cs-identifier" |
| nodeAggregateId | "acme-site-sites" |
| nodeTypeName | "Neos.Neos:Sites" |
And event at index 2 is of type "NodeAggregateWithNodeWasCreated" with payload:
| Key | Expected |
| workspaceName | "workspace-name" |
| contentStreamId | "cs-imported-identifier" |
| nodeAggregateId | "acme-site" |
| nodeTypeName | "Vendor.Site:HomePage" |
| Key | Expected |
| workspaceName | "live" |
| contentStreamId | "cs-identifier" |
| nodeAggregateId | "acme-site" |
| nodeTypeName | "Vendor.Site:HomePage" |

Scenario: Import faulty event stream with explicit "ContentStreamWasCreated" does not duplicate content-stream
see issue https://github.com/neos/neos-development-collection/issues/4298
Expand All @@ -73,7 +76,7 @@ Feature: As a user of the CR I want to export the event stream
"""
And I import the events.jsonl

And I expect a MigrationError with the message
And I expect a migration exception with the message
"""
Failed to read events. ContentStreamWasCreated is not expected in imported event stream.
"""
Expand Down
5 changes: 4 additions & 1 deletion Neos.ContentRepository.Export/src/Asset/AssetExporter.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

declare(strict_types=1);

namespace Neos\ContentRepository\Export\Asset;

use League\Flysystem\Filesystem;
Expand All @@ -14,7 +16,8 @@ public function __construct(
private readonly Filesystem $files,
private readonly AssetLoaderInterface $assetLoader,
private readonly ResourceLoaderInterface $resourceLoader,
) {}
) {
}

public function exportAsset(string $assetId): void
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,13 @@ public function __construct(

public static function fromRawEvent(Event $event): self
{
$payload = \json_decode($event->data->value, true, 512, JSON_THROW_ON_ERROR);
// unset content stream id as this is overwritten during import
unset($payload['contentStreamId'], $payload['workspaceName']);
return new self(
$event->id->value,
$event->type->value,
\json_decode($event->data->value, true, 512, JSON_THROW_ON_ERROR),
$payload,
$event->metadata?->value ?? [],
);
}
Expand Down
63 changes: 0 additions & 63 deletions Neos.ContentRepository.Export/src/ExportService.php

This file was deleted.

39 changes: 0 additions & 39 deletions Neos.ContentRepository.Export/src/ExportServiceFactory.php

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

declare(strict_types=1);

namespace Neos\ContentRepository\Export\Factory;

use Neos\ContentRepository\Core\Factory\ContentRepositoryServiceFactoryDependencies;
use Neos\ContentRepository\Core\Factory\ContentRepositoryServiceFactoryInterface;
use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamId;
use Neos\ContentRepository\Export\Processors\EventExportProcessor;

/**
* @implements ContentRepositoryServiceFactoryInterface<EventExportProcessor>
*/
final readonly class EventExportProcessorFactory implements ContentRepositoryServiceFactoryInterface
{
public function __construct(
private ContentStreamId $contentStreamId,
) {
}

public function build(ContentRepositoryServiceFactoryDependencies $serviceFactoryDependencies): EventExportProcessor
{
return new EventExportProcessor(
$this->contentStreamId,
$serviceFactoryDependencies->eventStore,
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

declare(strict_types=1);

namespace Neos\ContentRepository\Export\Factory;

use Neos\ContentRepository\Core\Factory\ContentRepositoryServiceFactoryDependencies;
use Neos\ContentRepository\Core\Factory\ContentRepositoryServiceFactoryInterface;
use Neos\ContentRepository\Core\SharedModel\Workspace\WorkspaceName;
use Neos\ContentRepository\Export\Processors\EventStoreImportProcessor;

/**
* @implements ContentRepositoryServiceFactoryInterface<EventStoreImportProcessor>
*/
final readonly class EventStoreImportProcessorFactory implements ContentRepositoryServiceFactoryInterface
{
public function __construct(
private WorkspaceName $targetWorkspaceName,
private bool $keepEventIds,
) {
}

public function build(ContentRepositoryServiceFactoryDependencies $serviceFactoryDependencies): EventStoreImportProcessor
{
return new EventStoreImportProcessor(
$this->targetWorkspaceName,
$this->keepEventIds,
$serviceFactoryDependencies->eventStore,
$serviceFactoryDependencies->eventNormalizer,
$serviceFactoryDependencies->contentRepository,
);
}
}
Loading

0 comments on commit 3a5b6c5

Please sign in to comment.