Skip to content

Commit

Permalink
TASK: Refine fusion inline docs
Browse files Browse the repository at this point in the history
  • Loading branch information
mhsdesign committed Feb 25, 2024
1 parent bf8b9ef commit 17caac0
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 25 deletions.
2 changes: 1 addition & 1 deletion Neos.Fusion/Classes/Core/Cache/FusionContextSerializer.php
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
5 changes: 2 additions & 3 deletions Neos.Fusion/Classes/Core/RuntimeFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,16 +44,15 @@ public function create(array $fusionConfiguration, ControllerContext $controller
$defaultContextVariables = EelUtility::getDefaultContextVariables(
$this->defaultContextConfiguration ?? []
);
$runtime = new Runtime(
return new Runtime(
FusionConfiguration::fromArray($fusionConfiguration),
FusionGlobals::fromArray(
[
...$defaultContextVariables,
'request' => $controllerContext?->getRequest() ?? ActionRequest::fromHttpRequest(ServerRequest::fromGlobals()),
...$defaultContextVariables
]
)
);
return $runtime;
}

public function createFromConfiguration(
Expand Down
16 changes: 7 additions & 9 deletions Neos.Neos/Classes/Fusion/Cache/NeosFusionContextSerializer.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,16 @@
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;

/**
* Serializer for Fusion's [at]cache.context values
* Serializer for Fusion's \@cache.context values
*
* Implements special handing for serializing {@see Node} objects in fusions cache context:
*
* ```
* [at]cache {
* mode = 'uncached'
* context {
* 1 = 'node'
* }
* }
* ```
* \@cache {
* mode = 'uncached'
* context {
* 1 = 'node'
* }
* }
*
* The property mapper cannot be relied upon to serialize nodes, as this is willingly not implemented.
*
Expand Down
37 changes: 34 additions & 3 deletions Neos.Neos/Classes/View/FusionView.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
use Neos\ContentRepository\Core\Projection\ContentGraph\Node;
use Neos\ContentRepositoryRegistry\ContentRepositoryRegistry;
use Neos\Flow\Annotations as Flow;
use Neos\Flow\Mvc\ActionRequest;
use Neos\Flow\Mvc\Controller\ControllerContext;
use Neos\Flow\Mvc\View\AbstractView;
use Neos\Flow\Security\Context;
use Neos\Fusion\Core\FusionGlobals;
Expand Down Expand Up @@ -52,6 +54,12 @@ class FusionView extends AbstractView
#[Flow\Inject]
protected RenderingModeService $renderingModeService;

/**
* Via {@see assign} request using the "request" key,
* will be available also as Fusion global in the runtime.
*/
protected ?ActionRequest $assignedActionRequest = null;

/**
* Renders the view
*
Expand Down Expand Up @@ -196,10 +204,10 @@ protected function getFusionRuntime(Node $currentSiteNode)

$renderingMode = $this->renderingModeService->findByName($this->getOption('renderingModeName'));

$fusionGlobals = FusionGlobals::fromArray([
'request' => $this->controllerContext->getRequest(),
$fusionGlobals = FusionGlobals::fromArray(array_filter([
'request' => $this->assignedActionRequest,
'renderingMode' => $renderingMode
]);
]));
$this->fusionRuntime = $this->runtimeFactory->createFromConfiguration(
$fusionConfiguration,
$fusionGlobals
Expand All @@ -220,7 +228,30 @@ protected function getFusionRuntime(Node $currentSiteNode)
*/
public function assign($key, $value): AbstractView
{
if ($key === 'request') {
// the request cannot be used as "normal" fusion variable and must be treated as FusionGlobal
// to for example not cache it accidentally
// additionally we need it for special request based handling in the view
$this->assignedActionRequest = $value;
return $this;
}
$this->fusionRuntime = null;
return parent::assign($key, $value);
}

/**
* Legacy layer to set the request for this view if not set already.
*
* Please use {@see assign} with "request" instead
*
* $view->assign('request"', $this->request)
*
* @deprecated with Neos 9
*/
public function setControllerContext(ControllerContext $controllerContext)
{
if (!$this->assignedActionRequest) {
$this->assignedActionRequest = $controllerContext->getRequest();
}
}
}

0 comments on commit 17caac0

Please sign in to comment.