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 | âś… | âś… |
- Flowpack.NodeTemplates is currently NOT supported because it works heavily with stateful Node objects. In principle, it can be possible to build an API-compatible version based on the ES CR, by providing a "Node" shim object.
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"
- create standalone package collection instead of branches
- command to import from NodeData to events
- make it work with Neos.ContentRepository.DimensionSpace package
- ensure Behavioral Tests run again
- Update CR for Neos 5
- Update EventSourcedNeosAdjustments for Neos 5
- Content Cache (#103)
- ensure Functional Tests run again
- figure out how/if to use event sourced Site/Domain (!possibly difficult!) -> fixed; won't use event sourced site/domain
- change RoutePart Handler when using event-sourced mode
- adjust NodeController when using event-sourced mode
- add switch to use event-sourced read model in Fusion rendering (!possibly difficult due to method signatures!)
- allow to open User Interface based on Event-Sourced read model
- implement Show/Hide of nodes (recursively)
- create Commands in response to UI interaction
- SetProperty command
- CreateNode
- MoveNode
- ShowNode
- DisableNode
- create feature list in this README, detailing what is supported and what not yet.
- support empty content dimension values in URL; e.g. "/de/..." for german, and "/..." for english
- absolute node referencing for ContentCollection (e.g. shared footer in Demo Site)
- fix Policy handling to configure permissions for various UI parts
- fix structure tree
- show correct workspace state after reload (top publish button)
- [?] fix inline linking
- fix node tree search
- [?] fix node tree filter
- Implement Node Repair
- (further TODOs here; this list is not complete yet)
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 neos/neos-development-collection#2202 for the Pull Request.
- in namespace
Domain\Projection\Content
, the newNodeInterface
andTraversableNodeInterface
are defined. - in namespace
Domain\ValueObject
, corresponding value objects are defined. - the old
Neos\ContentRepository\Domain\Model\Node
implements the full newNodeInterface
and most ofTraversableNodeInterface
. This is needed to ensure we can build FlowQuery implementations which can work with old and new API at once. - adjusted FlowQuery operations to
TraversableNodeInterface
(TODO not yet all of them)
see neos/neos-development-collection#2202 for the Pull Request.
- various detail improvements to use
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 mainContent
Graph projection (ContentGraphInterface
andContentSubgraphInterface
)
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
.
- internally, the
Http
andRouting
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)- Activation: using fusion
autoInclude
inSettings.yaml
, we load the Fusion fileresource://Neos.EventSourcedNeosAdjustments/Private/Fusion/Root.fusion
. ThisRoot.fusion
replaces the implementations for the aforementioned Fusion objects, so things work as expected for integrators (without new namespaces).
-
Eel
NodeHelper
andWorkspaceHelper
- Activation: These helpers are registered under the names
Neos.EventSourcedNeosAdjustments.*
; so a separate name. These helpers are explicitely used in theRoot.fusion
mentioned a few lines above.
- Activation: These helpers are registered under the names
-
custom
ExceptionHandler
because this also needs the replacementContentElementWrappingService
.- Activation: This helper is used as exception handlers in the
Root.fusion
mentioned a few lines above. - If people used these exception handlers themselves, they need to reconfigure them to the new implementations.
- Activation: This helper is used as exception handlers in the
- We replace Linking and Content Element Wrapping ViewHelpers, because Node Linking has changed and ContentElementWrapping has changed as well.
- Activation: Using AOP, the
ViewHelperReplacementAspect
implements aliasing of ViewHelper classes; effectively returning the VHs in this namespace instead of the default ones.
- Activation: Using AOP, the
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 forNeos.Neos.Ui
BackendController
.- Activation: We trigger this controller by AOP (in
BackendControllerAspect
): We call the new controller whenprocessRequest()
is called for the Neos backend controller.
- Activation: We trigger this controller by AOP (in
- We create Content Streams on backend login using the
EditorContentStreamZookeeper
(TODO change name maybe?).- Activation: We trigger this service by Signal/Slot in
Package.php
.
- Activation: We trigger this service by Signal/Slot in
Fusion
(for backend)- Activation: We load a custom
resource://Neos.EventSourcedNeosAdjustments/Private/Fusion/Backend/Root.fusion
usingViews.yaml
. - custom
NodeInfoHelper
, calling to a customNodePropertyConverterService
- Activation: We load a custom
- adjust the DimensionSwitcher JS component in
Resources/Private/UiAdapter
- TODO: this is not everything yet.