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\ImageFactoryNeos 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.