This is the package bundle you can install alongside a plain Neos to play around with the event-sourced CR.
✅ Done
⏩ Currently worked on
🚫 Will not be supported
Feature | Current CR | Event Sourced CR |
---|---|---|
Basics | ||
Create/ Edit / Delete Nodes | ✅ | ✅ |
Shortcut Handling | ✅ | ✅ |
Query Nodes | ✅ | ✅ |
Cut / Copy / Paste | ✅ | ✅ |
Move Nodes | ✅ | ✅ |
Hide Nodes | ✅ | ✅ |
History | (✅) | |
Basic Workspaces | ✅ | ✅ |
Workspace Module | ✅ | ✅ |
Nested Workspaces | ✅ | |
Undo / Redo | 🚫 | |
Setting Start / End time | ✅ | |
Resolving Referencing Nodes | 🚫 | ✅ |
Menu Rendering | ✅ | ✅ |
Dimension Menu Rendering | ✅ | ✅ |
Supporting "not in menu" | ✅ | ✅ |
Change node type | ✅ | ✅ |
Advanced | ||
Dimensions | ✅ | ✅ |
Dimension Fallback | ✅ | ✅ |
Multiple Sites | ✅ | ✅ |
Permissions / Policy | ✅ | |
Maintenance | ||
Export / Import | ✅ | ✅⏩ |
Node Migrations | ✅ | ✅ |
Structure Adjustments a.k.a. node:repair | ✅ | ✅ |
Integrity Checks | 🚫 | ✅ |
API | ||
Separate Read and Write API | 🚫 | ✅ |
More convenient write API | ||
Extensible Read API | (✅) custom Node | ✅ NodeAccessors |
FlowQuery is compatible | ✅ | ✅ |
Advanced test cases | 🚫 | ✅ |
Don't use ORM, but direct SQL queries | 🚫 | ✅ |
Asynchronous operations possible | 🚫 | ✅ |
performant node moving | 🚫 | ✅ |
performant node deletion | 🚫 | ✅ |
near-constant read performance | 🚫 | ✅ |
performant URL generation (routing) | 🚫 | ✅ |
MySQL support | ✅ | ✅ |
Postgres support | ✅ | ⏩ (much higher performance) |
usage without Neos/Flow | 🚫 | prepared |
extensible property serialization | 🚫 | ✅ through Symfony Serializer |
traverse node references in both directions | 🚫 | ✅ |
content merge conflict detection | 🚫 | ✅ |
content merge conflict resolution | 🚫 | ⏩ |
User Interface | ||
Ensure node deletion can be published in UI | ✅ | ✅ |
Support Dimension Constraints | ✅ | |
Publish Workspace | ✅ | ✅ |
Publish Current Page | ✅ | ✅ |
Discard all | ✅ | ✅ |
Discard Current Page | ✅ | ✅ |
Change node type in UI | ✅ | ✅ |
The Event Sourced Content Repository relies on a feature called (Recursive) Common Table Expressions (CTE) that require
Lateron, we will also support PostgreSQL. (We know it will work, but we did not create migrations or did testing yet).
The new code should be compatible with PHP 7.4
See https://github.com/neos/neos-development-distribution/tree/event-sourced
Linting is done via CodeSniffer and PHPStan. Both are integrated as composer scripts (see composer.json). To manually lint your branch before opening a PR, you can run
composer lint
from the folder the collection resides (probably Packages/CR
in a Neos distribution)
Linting can be added to commit hooks if desired.
In the collection folder (probably Packages/CR
in a Neos distribution),
add lines similar to the following to your .git/hooks/pre-commit
file (the example is for a DDEV environment):
#!/bin/sh
ddev exec "cd Packages/CR; composer lint"
By default, the Mysql Adapter is active right now, as Postgres is still in development.
To activate Postgres, right now, the following steps are needed in your distribution:
# Configuration/Objects.yaml
Neos\EventSourcedContentRepository\Domain\Projection\Content\ContentGraphInterface:
className: 'Neos\ContentGraph\PostgreSQLAdapter\Domain\Repository\ContentHypergraph'
if you want to run Postgres and MySQL side by side for the tests, you need the following config:
# Configuration/Settings.yaml
Neos:
EventSourcedContentRepository:
unstableInternalWillChangeLater:
testing:
projectorsToBeReset:
'Neos\ContentGraph\PostgreSQLAdapter\Domain\Projection\HypergraphProjector': true
activeContentGraphs:
'Postgres': 'Neos\ContentGraph\PostgreSQLAdapter\Domain\Repository\ContentHypergraph'
projection:
defaultProjectorsToBeBlocked:
'Neos\ContentGraph\PostgreSQLAdapter\Domain\Projection\HypergraphProjector': true
if you want to run Postgres without MySQL, you need the following config:
# Configuration/Settings.yaml
Neos:
EventSourcedContentRepository:
unstableInternalWillChangeLater:
testing:
projectorsToBeReset:
'Neos\ContentGraph\PostgreSQLAdapter\Domain\Projection\HypergraphProjector': true
'Neos\ContentGraph\DoctrineDbalAdapter\Domain\Projection\GraphProjector': false
activeContentGraphs:
'Postgres': 'Neos\ContentGraph\PostgreSQLAdapter\Domain\Repository\ContentHypergraph'
'DoctrineDBAL': false
projection:
defaultProjectorsToBeBlocked:
'Neos\ContentGraph\PostgreSQLAdapter\Domain\Projection\HypergraphProjector': true
'Neos\ContentGraph\DoctrineDbalAdapter\Domain\Projection\GraphProjector': false
This section should give an overview about the different involved packages, to ease understanding the different moving parts.
see https://github.com/neos/neos-development-collection/pull/2202 for the Pull Request.
Domain\Projection\Content
, the new NodeInterface
and TraversableNodeInterface
are defined.Domain\ValueObject
, corresponding value objects are defined.Neos\ContentRepository\Domain\Model\Node
implements the full new NodeInterface
and most of TraversableNodeInterface
. This is needed to ensure we can build FlowQuery implementations which can work with old and new API at once.TraversableNodeInterface
(TODO not yet all of them)see https://github.com/neos/neos-development-collection/pull/2202 for the Pull Request.
TraversableNodeInterface
in the core (e.g. FusionView)APIs to query the configured dimension space
Transition package implementing the event sourced CR core. In the longer run, will probably be merged into Neos.ContentRepository.
Domain\Context\*
implements Commands, Command Handlers, Events for Workspace, Content Stream, NodesDomain\Projection\*
implements projections for changes, workspace listing; and contains the definition for the main Content
Graph projection (ContentGraphInterface
and ContentSubgraphInterface
)implementation of the ContentGraphInterface
and ContentSubgraphInterface
using MySQL queries.
implementation of the ContentGraphInterface
and ContentSubgraphInterface
using PostgreSQL queries.
It turns out that there are numerous changes needed to the details of Neos.Neos - so this package hooks into various places in the Neos lifecycle to override certain Neos functionality.
We often completely override certain classes / behaviors from the Neos core completely; so that should make merging the changes back to the Neos.Neos package at some point a lot easier because we can then replace full classes instead of only individual pieces.
This package consists of the following bounded contexts, listed in their order during request processing:
This contains a CommandController and a service to generate events from reading NodeData
. It can be activated using the new CLI command.
We replace the default FrontendNodeRoutePartHandler
by providing an extra implementation of FrontendNodeRoutePartHandlerInterface
.
Activation: We replace the implementation of FrontendNodeRoutePartHandlerInterface
in Objects.yaml
.
Http
and Routing
namespaces are used for behaviours internal to the routing.This is a replacement for Frontend\NodeController
of Neos.Neos.
Activation: We trigger this controller by AOP (in NodeControllerAspect
): We call the new controller when processRequest()
is called for the Neos controller.
We replace certain Fusion implementations which are already re-implemented to work more efficiently with the ContentGraph API; and which implement linking (because this API also changed). This includes:
Menu / DimensionMenu
NodeUri, ConvertUris
ContentElementEditable / ContentElementWrapping
(because the ContentElementWrapping service has changed quite a lot)autoInclude
in Settings.yaml
, we load the Fusion file resource://Neos.EventSourcedNeosAdjustments/Private/Fusion/Root.fusion
. This Root.fusion
replaces the implementations for the aforementioned Fusion
objects, so things work as expected for integrators (without new namespaces).Eel NodeHelper
and WorkspaceHelper
Neos.EventSourcedNeosAdjustments.*
; so a separate name. These helpers are explicitely used in the Root.fusion
mentioned a few lines above.custom ExceptionHandler
because this also needs the replacement ContentElementWrappingService
.
Root.fusion
mentioned a few lines above.ViewHelperReplacementAspect
implements aliasing of ViewHelper classes; effectively returning the VHs in this namespace instead of the default ones.We implement a completely new ContentElementWrappingService
and ContentElementWrappingService
; mainly because they change quite a bit and their interfaces now require TraversableNodeInterface
instead of the legacy NodeInterface
.
The new services are used in the overridden ViewHelpers (see section Fluid above); and in overridden Fusion implementations (see section Fusion above).
A NodeAddress
is an external representation of a node (used in routing). TODO: Move to Neos.EventSourcedContentRepository.
BackendController
is an alternative implementation for Neos.Neos.Ui
BackendController
.
BackendControllerAspect
): We call the new controller when processRequest()
is called for the Neos backend controller.EditorContentStreamZookeeper
(TODO change name maybe?).
Package.php
.Fusion
(for backend)
resource://Neos.EventSourcedNeosAdjustments/Private/Fusion/Backend/Root.fusion
using Views.yaml
.NodeInfoHelper
, calling to a custom NodePropertyConverterService
Resources/Private/UiAdapter