Neos 5.0 »Jabberwock« and Flow 6.0 released

Finally, a new major release of Neos and Flow! We can't wait to tell you all about it.

Neos 5.0 and Flow 6.0 come with an updated Neos UI 5.0, an all-new Redirect Handler 3.0, PSR-7 and way more.
 

– Written by


The Jabberwock

Sunrise in Saxon Switzerland taken by Fabian Tschök

Foundation for the future

Neos 5.0 and Flow 6.0 aka »Jabberwock« improves the stability, performance, compatibility and sets the foundation for the future. It is packed with many features under the surface. So, let's get started!

PSR-7 compatibility, for instance, is a very important low-level Flow Framework improvement, that will make it much easier to connect Neos and Flow to other PHP applications with less effort and more flexibility. We have been working on the implementation for quite a while and it's finally ready

Handling redirects is a very important task on a daily bases for Neos CMS editors and integrators that can be quite challenging sometimes. We got a lot of feedback from the community lately and transferred all that information into a major upgrade release for the Redirect Handler Feature - you gonna love it!

To keep the codebase clean and to avoid legacy code maintenance, we have removed the old Ember-JS Neos UI to be able to focus 100% on the React UI from now on. And it's never been that easy to use Fusion instead of Fluid for the Flow MVC Framework. 

Read more about the release:

For a full list of changes, improvements, and features, please check the release notes.

As always, be sure to read the Important notes for developers before you update.

The message of »Jabberwock«

“The Anglo-Saxon word ‘wocer’ or ‘wocor’ signifies ‘offspring’ or ‘fruit’. Taking ‘jabber’ in its ordinary acceptation of ‘excited and voluble discussion’” – Lewis Carroll

In our humble opinion this perfectly matches our team values and the open source spirit in general.

Neos UI 5.0

Highlights

Together with Neos 5.0 the Neos UI will be versioned and released together with Neos itself and therefore get the same versioning.

Neos 5.0 is compatible only with Neos UI 5.0.x. Neos 4.x will continue to get bugfix releases in the form of Neos UI 4.0.x releases. 

All of the new UI features since the release of Neos 5.0 will only be available in Neos 5.1. Such stricter versioning scheme would allow us to be more coordinated across the whole team and also have more stable releases.

Since the release of Neos 4.3 LTS, the user interface of Neos has two new major features:

Neos Backend showing inline properties validation

Validation of Inline Properties

Validation of inline properties:

now it's possible to have inline content validated against the same rules as properties that are edited through the inspector. For example, you can restrict the length of some headline that is edited inline.

Neos Backend showing RichTextEditor inspector editor

RichTextEditor inspector editor

RichTextEditor inspector editor:

now it is possible to have rich text editing not only inline but also in the inspector. Useful if you need to allow editors to be able to edit email finishers and similar things.

The UI has seen more visual polish:

  • Neos backend is finally responsive and the Neos logo is now visible in the backend!
  • Edit preview mode toggle has been greatly simplified and takes up less space
  • It is now possible to switch to inaccessible dimension combinations

Improvements for the powerful extensibility of the the Neos UI:

  • Integration of CKEditor5 v12. (Please be aware that some CKE plugins might need slight adjustments)
  • Link input options and inline UI buttons are now extendable
  • It's now possible to disable caching of data sources

Besides these new features, we have a countless number of bug fixes and maintenance tasks, over 180 commits in total! You may explore the full list of changes on Github: https://github.com/neos/neos-ui/compare/3.3.0...5.0

Other changes in Neos 5.0

The Ember-JS based content module is gone

Just a few notes on the removal of old Ember-JS fragments:

  • There are traces of emberjs still in the core
  • They will be removed in the next minor/bugfix versions
  • Be aware of that every third-party code that relies on Ember-JS should be considered broken

Setup can now be uninstalled

Until Neos 4.3 LTS the neos/setup package can't be uninstalled because neos/neos depends on it. With Neos 5.0 you can now uninstall the Neos setup.

Reason for this hard dependency are the Step-implementations that break the proxy building if the corresponding base classes can't be found.

Breaking: If root composer.json was modified (composer require neos/neos-setup)

Disable and deprecate plugin and content prototype generators

The prototype generator classes are deprecated and removed from the nodeType configuration. This helps to make the fusion-code more explicit and the connection between nodeType and fusion prototype much simpler. The previously assigned base types were not recommended anymore and thus usually are overwritten.

A very welcome effect is that the error message for missing node rendering prototypes will be more clear and not saying that a template file is missing.

In addition this removes the documentPrototypeGenerator.

Note: Neos.Fusion:Template is not considered best practice anymore in favor of fusion-afx.

Upgrade instructions:

To upgrade you have to make sure that content and plugin nodetypes have a matching fusion prototype that looks like the following examples:

prototype(Vendor.Site:ContentExample) < prototype(Neos.Fusion:Template) {
    templatePath = "resource://Vendor.Site/Private/Templates/NodeTypes/EContentExamplexample.html" 
    /* for all properties needed for rendering */
    title = ${q(node).property('title')}
}

prototype(Vendor.Site:PluginExample) < prototype(Neos.Neos:Plugin) {
        package = "Vendor.Site"
        subpackage = ""
        controller = "Example"
        action = "index"
}

Neos Redirect Handler 3.0

The release notes include changes for the following packages:

  • Neos.RedirectHandler 3.0.0
  • Neos.RedirectHandler.NeosAdapter 4.0.0
  • Neos.RedirectHandler.DatabaseStorage 4.0.0
  • Neos.RedirectHandler.Ui 2.0.0

Add context to redirects

Each redirect can now have a comment detailing why it’s there. When adding or modifying a redirect the current user will be stored as creator to know who to ask if a redirect causes confusion. The redirects that Neos optionally generates when moving or renaming pages are also marked to make them easy to find.

Prepare redirects in advance

Instead of setting up a redirect just in time when it’s needed, it’s now possible to define a start- and end date which will automatically enable or disable the redirect.

Manage many redirects easily

The redirects module has been completely rewritten to allow searching, sorting and filtering all redirects easily and almost instantly.

Import & export

It’s now also possible to import and export redirects as CSV via the redirect backend module including all additional meta fields mentioned above. The import will show a detailed log of what changes were made. Developers can access the redirects more easily with new import and export service classes to generate custom output for web servers or other systems. Because the rendering for these actions is now based on Fusion, it’s even possible to extend them with custom export formats or interactions.

Customisation

The selectable status codes for a project can now be configured to match a projects requirements.

Some filter options for the redirects list can be preconfigured to directly show the desired redirects when the module is opened.

List of redirects in the new Neos redirect management ui

Neos Redirect Handler 3.0 Backend Module


Flow 6.0

Main changes

PSR-7 Compatibility

Flow Routing is now completely PSR-7 compatible.

This replaces the HTTP stack of Flow with PSR-7.

Many areas of Flow are affected by this, most notably and breaking:

  • All HTTP is now fully PSR-7
  • Response in MVC controllers is no longer an HTTP response and has very different methods.
  • CLI and MVC use different dispatchers now
  • ActionRequest::getParentRequest() will return null at the top instead of an HttpRequest, you can still get the HttpRequest via ActionRequest::getHttpRequest()
  • ActionRequest::fromHttpRequest(ServerRequestInterface $httpRequest) introduced
  • ActionRequest::createSubRequest() introduced
  • ActionRequest can no longer be created via new
  • \Neos\Flow\Mvc\ActionRequestFactory introduced to correctly merge arguments from the HTTP request
  • Neos.Http.Factories introduced, implementing PSR-17 HTTP factories, use those to create and fake HTTP requests
  • The HTTP process was split into more components to have easier extension points in between. So you can interject between the creation of the top level ActionRequest (after which security is available) and the actual dispatching to a controller

More detailed information on the PSR-7 topic:

 

Allow mapping whole request body to a single action argument

This allows to annotate a method action with the new @Flow\MapRequestBody("$foo")
Annotation, which will lead to the full parsed request body being mapped into the action argument $foo. Previously this was not possible and the request body had to be wrapped with an object with a single foo property.

This is useful for APIs that want to receive specific payloads that are defined on third parties or want to accept a list of models as an argument.

POST /api/v1/foo [{ "name": "foo1" }, { "name": "foo2" }]
/**
 * @param array<Foo> $foos
 * @Flow\MapRequestBody("$foos")
 */
public function fooAction(array $foos)

 

Configurable FlashMessage containers

Introduces a new setting Neos.Flow.mvc.flashMessages.containers that allows to configure separate FlashMessage containers.

It also changes the default behavior to persist FlashMessages in a session Cookie rather than in a server-side session.

This is a breaking change because it changes the API slightly by removing the @api annotation from the FlashMessageContainer. This is required because that object is no longer stored in the
session by default. Instead of interacting with the FlashMessageContainer directly, the addFlashMessage() method must be used now.

The FlashMessageContainer can still be fetched from the ControllerContext but this will internally now use the FlashMessageService to restore the container from the configured storage implementation.

Background:

This patch changes the default behavior to store FlashMessages in a (HTTP) session cookie. This should not have any effect to the PHP code and FlashMessages can still be obtained with the
<f:flashMessages /> Fluid ViewHelper. However, the FlashMessages can now also be read from JavaScript allowing the redirected action to be cached!

Furthermore it's now possible to use different cookies for different parts of the website so that FlashMessages don't interact. This is useful for example for FlashMessages in the Neos Backend
and/or within plugins.

Using Fusion as MVC view

We improved the possibility to use Fusion as a "View" within the Flow MVC framework. No worries, the Fluid implementation is still 100% supported. Fusion is the second option you have available for more flexibility within the Flow Framework. 

Views.yaml

First you have to set the corresponding view configuration for your controller: 

-
  requestFilter: 'isPackage("Acme.Package") && isController("List")'
  viewObjectName: 'Neos\Fusion\View\FusionView'
  options:
    fusionPathPatterns:
      - 'resource://Neos.Fusion/Private/Fusion'
      - 'resource://Acme.Package/Private/Fusion'

View.yaml

Controller

/**
 * @Flow\Scope("singleton")
 */
class ListController extends ActionController
{
    /**
     * @var FusionView
     */
    protected $view;
    
    public function indexAction()
    {
    	$this->view->assign('foo' => 'bar');
    }
}

Controller.php

Fusion

Flow will use the Root.fusion file within the configured fusionPathPattters setting. By default, the corresponding Fusion path is mapped automatically via naming convention Package.Key.Controller.action.

prototype(Acme.Package:List.Index) < prototype(Neos.Fusion:Component) {
	renderer = afx`
		<span>{foo}</span>
	`
}

Acme.Package.ListController.index = Acme.Package:List.Index {
	foo = 'This will be displayed'
}

Root .fusion

Others

Enable `subdivideHashPathSegment` and `relativeSymlinks` by default

The old defaults for these settings worked but caused trouble once projects got bigger over time:

  • subdivideHashPathSegment: false caused having too many symlinks in a single folder for many filesystems
  • relativeSymlinks: false did not allow to put the Web/_Resources directory into the shared folder for faster deployments

ATTENTION: This alters the default behavior and the published resources will get a url with nested paths. That is why this is considered a breaking change.

NOTE: After updating you have to empty the Web/_Resources/Persistent folder and run ./flow resource:publish. This is usually all done automatically from the deployment tool you are using.

If you do not want this behavior you can disable the subdivision via configuration for your project with the following configuration.

Neos:
  Flow:
    resource:
      targets:
        localWebDirectoryPersistentResourcesTarget:
          targetOptions:
            subdivideHashPathSegment: false
            relativeSymlinks: false

You probably want to redirect requests to the old urls in your web server configuration, the following regex search/replace patterns may be used for that:

  • searchPattern: ^_Resources\/Persistent\/([a-f0-9]{1})([a-f0-9]{1})([a-f0-9]{1})([a-f0-9]{1})([a-f0-9]{36})\/(.+)$
  • replacePattern: _Resources/Persistent/$1/$2/$3/$4/$1$2$3$4$5/$6

nginx redirect rule:

# redirect resource urls without subdivideHashPathSegments
rewrite "^/_Resources\/Persistent\/([a-f0-9]{1})([a-f0-9]{1})([a-f0-9]{1})([a-f0-9]{1})([a-f0-9]{36})\/(.+)$" /_Resources/Persistent/$1/$2/$3/$4/$1$2$3$4$5/$6 permanent;

Furthermore, we

  • raised PHP minimum dependency to PHP 7.2
  • updated PHPUnit from 7 to 8
  • removed the deprecated Legacy logger. The PSR-3 Logger is default since version 4.0 and now the only one available.

PSALM

We are now also using PSALM static code analytics to automatically test our code (https://github.com/vimeo/psalm).


Important notes for developers

Please be aware of some changes coming with this release before you update. Especially when parts of Neos or Flow (or any other core package) have been extended that weren't marked as public API.

In principle, we try to avoid introducing global breaking changes into a minor release. Please note the following changes that have been made in packages shipped with this version:

Neos

  1. Ember-JS
    Every third-party code that relies on Ember-JS should be considered broken
  2. Neos Setup can be uninstalled
    This is breaking if root composer.json was modified (e.g. composer require neos/neos-setup)
  3. PHP minimum version raised to 7.2
  4. PHP Unit updated from version 7 to 8
  5. Deprecated Legacy logger is removed
    The PSR-3 Logger is default since version 4.0 and now the only one available

Flow

We introduced ActionResponse for clean PSR-7. This is the continuation of a clear separation between MVC and HTTP stacks. The introduced ActionResponse offers a very limited interface to work with on the MVC level.


Documentation and Support

Upgrading

The detailed upgrading process for Neos 5.0 is explained in the upgrade instructions.

Changelogs

See the Neos 5.0 changelogs and Flow 6.0 changelogs for all changes and details.

Support for Neos 5.0 and Flow 6.0 LTS

As shown in our release roadmap, Neos 5.0 and Flow 6.0 will get bug fixes until April 2021 and security fixes until April 2022.


Thank you!

Special thanks for this release go to the release managers Daniel Lienert and Karsten Dambekalns. Thank you also to their fellow team Minions members, all other core team members and the community for your valuable contributions and sponsorships.

Additionally, we also want to thank all companies enabling us to do all this. Especially 1&1 for mainly sponsoring the new Neos Redirect Handler 3.0 and webexcess for contributing the package originally as a Neos core package!