With PR #2374 Neos got the ability to render status messages for the status codes 403, 404 and 410 using Fusion.
The matcher receives the context values exception
, renderingOptions
, statusCode
,
statusMessage
and referenceCode
and will by default render the previous template.
By extending the error
case you can add custom 404 rendering like in the example below.
#
# Extend error matcher to render the document with uriPathSegment `notfound`
# for exceptions with 4xx status code
#
error {
@context.notfoundDocument = ${q(site).children('[instanceof Neos.Neos:Document]').filter('[uriPathSegment="notfound"]').get(0)}
4xx {
@position = 'start'
condition = ${statusCode >= 400 && statusCode < 500 && notfoundDocument}
renderer = Neos.Fusion:Renderer {
@context.node = ${notfoundDocument}
renderPath = '/root'
}
}
}
But the to have fully correct rendering of the error, especially when content dimensions are involved, the node
is not enough (hum 007 theme along). Add site
and documentNode
, too. And you must adjust the context to have the correct dimensions, since contrary to what you might expect, the site
will have default dimensions in it’s context in the error case.
To fetch the dimensions, you can do something like this (https://gist.github.com/kdambekalns/d9a7f8f09f1c69179816f42d82c68c8c):
// Reads the dimensions country and language from the request path and
// returns a DataStructure with dimensions and targetDimensions for use
// with the Eel context() operation.
prototype(Acme.Com:ExtractDimensions) < prototype(Neos.Fusion:Value) {
trimmedPath = ${String.trim(request.httpRequest.uri.path, '/')}
pathParts = ${String.split(this.trimmedPath, '/', 2)}
@context{
dimensionParts = ${String.split(this.pathParts[0], '_')}
defaultPresets = Neos.Fusion:DataStructure {
country = ${Configuration.setting('Neos.ContentRepository.contentDimensions.country.defaultPreset')}
language = ${Configuration.setting('Neos.ContentRepository.contentDimensions.language.defaultPreset')}
}
}
value = Neos.Fusion:Case {
dimensionsFound {
condition = ${Array.length(dimensionParts) == 2 && Configuration.setting('Neos.ContentRepository.contentDimensions.country.presets.' + dimensionParts[0] + '.values') && Configuration.setting('Neos.ContentRepository.contentDimensions.language.presets.' + dimensionParts[1] + '.values')}
renderer = Neos.Fusion:DataStructure {
dimensions = Neos.Fusion:DataStructure {
country = ${Configuration.setting('Neos.ContentRepository.contentDimensions.country.presets.' + dimensionParts[0] + '.values')}
language = ${Configuration.setting('Neos.ContentRepository.contentDimensions.language.presets.' + dimensionParts[1] + '.values')}
}
targetDimensions = Neos.Fusion:DataStructure {
country = ${dimensionParts[0]}
language = ${dimensionParts[1]}
}
}
}
noDimensionsFound {
condition = true
renderer = Neos.Fusion:DataStructure {
dimensions = Neos.Fusion:DataStructure {
country = ${Configuration.setting('Neos.ContentRepository.contentDimensions.country.presets.' + defaultPresets.country + '.values')}
language = ${Configuration.setting('Neos.ContentRepository.contentDimensions.language.presets.' + defaultPresets.language + '.values')}
}
targetDimensions = Neos.Fusion:DataStructure {
country = ${defaultPresets.country}
language = ${defaultPresets.language}
}
}
}
}
}
And then use it like this:
error {
4xx {
dimensions = Acme.Com:ExtractDimensions
@context.notfoundDocument = ${q(site).context({'dimensions': this.dimensions.dimensions, 'targetDimensions': this.dimensions.targetDimensions}).children('[instanceof Neos.Neos:Document]').filter('[uriPathSegment="404"]').get(0)}
@position = 'start'
condition = ${statusCode >= 400 && statusCode < 500 && notfoundDocument}
renderer = Neos.Fusion:Renderer {
@context {
site = ${notfoundDocument.context.currentSiteNode}
node = ${notfoundDocument}
documentNode = ${notfoundDocument}
}
renderPath = '/root'
}
}
}