Accessing and exposing rendered nodes

Hello together,

currently I’m working on exposing a JSON object holding the rendered content of the nodes to an API. So far I’ve created a new package with a hook on the event afterNodePublishing where I can access my document.

class Package extends BasePackage
{

    /**
     * @param Bootstrap $bootstrap The current bootstrap
     */
    public function boot(Bootstrap $bootstrap)
    {
        $dispatcher = $bootstrap->getSignalSlotDispatcher();
        $dispatcher->connect(Workspace::class, 'afterNodePublishing', Publisher::class, 'createExportJSON');
    }

}

I can access the node’s properties per FlowQuery within my function createExportJSON, but I’ve yet to figure out how to access the whole rendered node.

public function createExportJSON (NodeInterface $node): void
    {

        $query = new FlowQuery([$node]);
        $title = $query->property('headline');

    }

What I get here is the headline of my document as a simple string, but what I need is the whole HTML which is provided by Fusion. So basically the HTML within the afx here:

renderer = afx`
	    <h2 class="inf-no-margin">
            <span class="inf-headline inf-headline--large--thin inf-block inf-no-margin">{props.headline}</span>
        </h2>
    `

How can I achieve this?

hi and welcome !

you want to render 1 node component out of band. And fusion can do that :wink:

you would need to use the Neos.Neos:FusionView

assign the node:
$view->assign(‘value’, $node)

and set the fusionPath to /<Neos.Neos:ContentCase>

and render it :wink:


if you need more help i will show you code snippets ^^

1 Like

Hi Marc,

Thanks for your fast response!

Unfortunately I’m running into this error when trying to execute the render function of FusionView and I don’t really know how to provide the ControllerContext in this case:

Neos\Neos\Domain\Service\FusionService_Original::createRuntime(): Argument #2 ($controllerContext) must be of type Neos\Flow\Mvc\Controller\ControllerContext, null given

class JsonExportHelper extends FusionView
{

    /**
     * @param $node
     *
     * @return string
     */
    public function getRenderedContent($node) {

        $this->assign('value', $node);
        $this->setFusionPath('/<Neos.Neos:ContentCase>');
        $this->render();

        return '';

    }

}

Some code snippets would be of great help, thank you! :smiley:

this happens because youre using the $view not in a controller. (see the fusion tests have the same “problem”)

normally the ActionController would call $this->view->setControllerContext($controllerContext); and inject this way the required $controllerContext.

you need to create some dummy controller context somehow and assign it to the view.

also you dont need to extend the FusionView but you can just use it by initializing it:

$fusionView = new FusionView();
$fusionView->assign('value', $node);
....
1 Like

i guess youre asking yourself now where do i get the ControllerContext?

its use in fusion is for the global request object: ${request} or when using Neos.Neos:ConvertUris for example.

there are some options as far as i know:

1

either you create an actual fake controller context:

2

or you create it from the eviroment:

3

or you just put in a dummy by extending Neos\Flow\Mvc\Controller\ControllerContext and overriding the contructor to empty, basically a mock. (which doenst work at all and will throw when its called)

1 Like

Probably you can also use GitHub - punktDe/outofbandrendering: Supplies an EelHelper to do out of band rendering of fusion objects.
instead.
Just call the service or helper from PHP.

1 Like

Thanks for your suggestion Sebastian! Unfortunately it’s not viable for me since we don’t meet the php version requirements.

Nevertheless it’s an interesting resource to look into about that topic.

@Marc First of all thank you very much for taking your time and the helpful insight! :slightly_smiling_face:

I managed to get an output that at least seems to carry the HTML, but there’s a lot of neos stuff in there which I haven’t figured out how to get rid of yet. :confused:

 /**
     * @return string|ResponseInterface
     * @throws UnresolvedDependenciesException
     */
    protected function renderContent(NodeInterface $node)
    {

        $view = new FusionView();

        /** @var ServerRequestFactoryInterface $httpRequestFactory */
        $http_request_factory = $this->object_manager->get(ServerRequestFactoryInterface::class);
        $http_request = $http_request_factory->createServerRequest('GET', 'http://localhost/');
        $request = ActionRequest::fromHttpRequest($http_request);

        $uri_builder = new UriBuilder();
        $uri_builder->setRequest($request);

        $this->controller_context = new ControllerContext (
            $request,
            new ActionResponse(),
            new Arguments([]),
            $uri_builder
        );

        $view->setControllerContext($this->controller_context);
        $view->assign('value', $node);
        $view->setFusionPath('/<Neos.Neos:ContentCase>');

        return $view->render();

    }

The return value looks like this:

nice :clap:
the ‘neos stuff’ are the markers of the node components so they are clickable and editable in the neos ui.

they are not shown in live mode. So i assume
$node->getContext()->isInBackend() returns true?

your goal would be to make the node believe its in the live mode… there are dark ways muhahah … lemme check

Yes, it returns true so your assumption is correct :slightly_smiling_face: