Skip to content

Commit

Permalink
Merge pull request #4856 from mhsdesign/feature/fusionRuntimRenderHtt…
Browse files Browse the repository at this point in the history
…pResponse

!!! FEATURE: Render `ResponseInterface` directly in Fusion Views
  • Loading branch information
mhsdesign committed Apr 24, 2024
2 parents c49653b + 2cf100f commit 7a74b72
Show file tree
Hide file tree
Showing 35 changed files with 847 additions and 340 deletions.
2 changes: 1 addition & 1 deletion Neos.Fusion/Classes/Core/Cache/FusionContextSerializer.php
Expand Up @@ -9,7 +9,7 @@
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;

/**
* Serializer for Fusion's [at]cache.context values
* Serializer for Fusion's \@cache.context values
*
* Uses the Flows's property mapper as implementation.
* It relies on a converter being available from the context value type to string and reverse.
Expand Down
33 changes: 24 additions & 9 deletions Neos.Fusion/Classes/Core/FusionGlobals.php
Expand Up @@ -5,21 +5,31 @@
namespace Neos\Fusion\Core;

/**
* Fusion allows to add variable to the context either via
* \@context.foo = "bar" or by leveraging the php api {@see Runtime::pushContext()}.
* Fusion differentiates between dynamic context variables and fixed Fusion globals.
*
* Those approaches are highly dynamic and don't guarantee the existence of variables,
* Context variables are allowed to be set via Fusion's \@context.foo = "bar"
* or by leveraging the php api {@see Runtime::pushContext()}.
*
* Context variables are highly dynamic and don't guarantee the existence of a specific variables,
* as they have to be explicitly preserved in uncached \@cache segments,
* or might accidentally be popped from the stack.
*
* The Fusion runtime is instantiated with a set of global variables which contain the EEL helper definitions
* or functions like FlowQuery. Also, variables like "request" are made available via it.
* The Fusion globals are immutable and part of the runtime's constructor.
* A fixed set of global variables which might contain the EEL helper definitions
* or functions like FlowQuery can be passed this way.
*
* Additionally, also special variables like "request" are made available.
*
* The "${request}" special case: To make the request available in uncached segments, it would need to be serialized,
* but we don't allow this currently and despite that, it would be absurd to cache a random request.
* The speciality with "request" and similar is that they should be always available but never cached.
* Regular context variables must be serialized to be available in uncached segments,
* but the current request must not be serialized into the cache as it contains user specific information.
* This is avoided by always exposing the current action request via the global variable.
*
* Overriding Fusion globals is disallowed via \@context and {@see Runtime::pushContext()}.
*
* Fusion globals are case-sensitive, though it's not recommend to leverage this behaviour.
*
* @internal The globals will be set inside the FusionView as declared
*/
final readonly class FusionGlobals
{
Expand All @@ -45,8 +55,13 @@ public static function fromArray(array $variables): self
}

/**
* You can access the current request like via this getter:
* `$runtime->fusionGlobals->get('request')`
* Access the possible current request or other globals:
*
* $actionRequest = $this->runtime->fusionGlobals->get('request');
* if (!$actionRequest instanceof ActionRequest) {
* // fallback or error
* }
*
*/
public function get(string $name): mixed
{
Expand Down
@@ -0,0 +1,9 @@
<?php

declare(strict_types=1);

namespace Neos\Fusion\Core;

final class IllegalEntryFusionPathValueException extends \Neos\Fusion\Exception
{
}
127 changes: 127 additions & 0 deletions Neos.Fusion/Classes/Core/LegacyFusionControllerContext.php
@@ -0,0 +1,127 @@
<?php

declare(strict_types=1);

namespace Neos\Fusion\Core;

use Neos\Flow\Annotations as Flow;
use Neos\Flow\Mvc\ActionRequest;
use Neos\Flow\Mvc\ActionResponse;
use Neos\Flow\Mvc\Controller\ControllerContext;
use Neos\Flow\Mvc\FlashMessage\FlashMessageContainer;
use Neos\Flow\Mvc\FlashMessage\FlashMessageService;
use Neos\Flow\Mvc\Routing\UriBuilder;

/**
* Legacy stub to replace the original {@see ControllerContext} inside Fusion {@see Runtime::getControllerContext()}.
*
* The concept of the controller context inside Fusion has been deprecated.
*
* You should definitely not pass this object along further, which will also most likely not work as it doesn't
* satisfy the constraint of `instanceof ControllerContext`!
*
* To migrate the use case of fetching the active request, please look into {@see FusionGlobals::get()} instead.
* By convention, an {@see ActionRequest} will be available as `request`:
*
* $actionRequest = $this->runtime->fusionGlobals->get('request');
* if (!$actionRequest instanceof ActionRequest) {
* // fallback or error
* }
*
* To get an {@see UriBuilder} proceed with:
*
* $uriBuilder = new UriBuilder();
* $uriBuilder->setRequest($actionRequest);
*
* WARNING regarding {@see Runtime::getControllerContext()}:
* Invoking this backwards-compatible layer is possibly unsafe, if the rendering was not started
* in {@see self::renderResponse()} or no `request` global is available. This will raise an exception.
*
* @deprecated with Neos 9.0 can be removed with 10
* @internal
*/
final class LegacyFusionControllerContext
{
/**
* @Flow\Inject
* @var FlashMessageService
*/
protected $flashMessageService;

public function __construct(
private readonly ActionRequest $request,
private readonly ActionResponse $legacyActionResponseForCurrentRendering
) {
}

/**
* To migrate the use case of fetching the active request, please look into {@see FusionGlobals::get()} instead.
* By convention, an {@see ActionRequest} will be available as `request`:
*
* $actionRequest = $this->runtime->fusionGlobals->get('request');
* if (!$actionRequest instanceof ActionRequest) {
* // fallback or error
* }
*
* @deprecated with Neos 9.0 can be removed with 10
*/
public function getRequest(): ActionRequest
{
return $this->request;
}

/**
* To migrate the use case of getting the UriBuilder please use this instead:
*
* $actionRequest = $this->runtime->fusionGlobals->get('request');
* if (!$actionRequest instanceof ActionRequest) {
* // fallback or error
* }
* $uriBuilder = new UriBuilder();
* $uriBuilder->setRequest($actionRequest);
*
* @deprecated with Neos 9.0 can be removed with 10
*/
public function getUriBuilder(): UriBuilder
{
$uriBuilder = new UriBuilder();
$uriBuilder->setRequest($this->request);
return $uriBuilder;
}

/**
* To migrate this use case please use {@see FlashMessageService::getFlashMessageContainerForRequest()} in
* combination with fetching the active request as described here {@see getRequest} instead.
*
* @deprecated with Neos 9.0 can be removed with 10
*/
public function getFlashMessageContainer(): FlashMessageContainer
{
return $this->flashMessageService->getFlashMessageContainerForRequest($this->request);
}

/**
* PURELY INTERNAL with partially undefined behaviour!!!
*
* Gives access to the legacy mutable action response simulation {@see Runtime::withSimulatedLegacyControllerContext()}
*
* Initially it was possible to mutate the current response of the active MVC controller through this getter.
*
* While *HIGHLY* internal behaviour and *ONLY* to be used by Neos.Fusion.Form or Neos.Neos:Plugin
* this legacy layer is in place to still allow this functionality.
*
* @deprecated with Neos 9.0 can be removed with 10
* @internal THIS SHOULD NEVER BE CALLED ON USER-LAND
*/
public function getResponse(): ActionResponse
{
// expose action response to be possibly mutated in neos forms or fusion plugins.
// this behaviour is highly internal and deprecated!
return $this->legacyActionResponseForCurrentRendering;
}

/**
* The method {@see ControllerContext::getArguments()} was removed without replacement.
*/
// public function getArguments(): Arguments;
}

0 comments on commit 7a74b72

Please sign in to comment.