Hint: If you used the Kickstarter to create your component, an empty factory has already been created alongside the PresentationObject.
In this tutorial, we're going to write a PresentationObject factory for the image component we've created in "PresentationObjects and Components". Let's assume that we have a Vendor.Site:Content.Image
node type with the properties image__src
, image__alt
and image__title
that we want to integrate with our Image component.
PresentationObject factories are co-located with their respective PresentationObjects. It's recommended to create factory methods with a speaking name prefixed with for*
or from*
to describe their use-case. When your code base grows, the factory will act like an index showing you all the different places in which the respective component is used.
EXAMPLE: PresentationObject Factory
<?php declare(strict_types=1);
namespace Vendor\Site\Presentation\Image;
use Neos\Flow\Annotations as Flow;
/**
* @Flow\Scope("singleton")
*/
final class ImageFactory extends AbstractComponentPresentationObjectFactory
{
/**
* @param TraversableNodeInterface $node
* @return ImageInterface
*/
public function forImageNode(TraversableNodeInterface $node): ImageInterface
{
// Optional: Use assertions to ensure the incoming node type
assert($node->getNodeType()->isOfType('Vendor.Site:Content.Image'));
return new Image(
$node->getProperty('image__src')
? $this->uriService->getAssetUri($node->getProperty('image__src'))
: $this->uriService->getDummyImageUri()
$node->getProperty('image__alt') ?? '',
$node->getProperty('image__title')
);
}
}
Each factory that extends AbstractComponentPresentationObjectFactory
automatically implements the Neos\Eel\ProtectedContextAwareInterface
and can be used as an Eel helper. To make our factory available in Fusion, we need to register it in the Settings:
EXAMPLE: Settings.PresentationHelpers.yaml
Neos:
Fusion:
defaultContext:
Vendor.Site.Image: Vendor\Site\Presentation\Image\ImageFactory
Neos uses the Neos.Neos:ContentCase
to map nodes to rendering prototypes. For our Vendor.Site:Content.Image
node, the entry point is going to be a Fusion prototype of the same name.
From here, we just need to extend Neos.Neos:ContentComponent
and provide our PresentationObject component Vendor.Site:Component.Image
as the renderer. As the presentationObject
we pass the result of the forImageNode
-method of our newly registered ImageFactory
.
EXAMPLE: Resources/Private/Fusion/Integration/Content/Image.fusion
prototype(Vendor.Site:Content.Image) < prototype(Neos.Neos:ContentComponent) {
renderer = Vendor.Site:Component.Image {
presentationObject = ${Vendor.Site.Image.forImageNode(node)}
}
}
That's it! Our image component is now fully integrated and can be edited in the Neos Backend.