Skip to content
This repository has been archived by the owner on Mar 1, 2023. It is now read-only.

Commit

Permalink
[BUGFIX] Fix variables not passed to field layout view in TYPO3 8.6
Browse files Browse the repository at this point in the history
Fluid variables were not passed correctly to the layout standalone view
of a field.

This commit fixes this issue, as well as a refactor for the older
versions behaviour to make the code more readable.
  • Loading branch information
romm committed Sep 5, 2017
1 parent 0be97eb commit cc1cfef
Showing 1 changed file with 82 additions and 69 deletions.
151 changes: 82 additions & 69 deletions Classes/ViewHelpers/FieldViewHelper.php
Expand Up @@ -68,11 +68,6 @@ class FieldViewHelper extends AbstractViewHelper
*/
protected $slotService;

/**
* @var array
*/
protected $originalArguments = [];

/**
* @inheritdoc
*/
Expand All @@ -88,8 +83,6 @@ public function initializeArguments()
*/
public function render()
{
$viewHelperVariableContainer = $this->renderingContext->getViewHelperVariableContainer();

/*
* First, we check if this view helper is called from within the
* `FormViewHelper`, because it would not make sense anywhere else.
Expand All @@ -116,21 +109,11 @@ public function render()
*/
$this->renderChildren();

/*
* We need to store original arguments declared for the current view
* context, because we may override them during the rendering of this
* view helper.
*/
$this->storeOriginalArguments();

/*
* We merge the arguments with the ones registered with the
* `OptionViewHelper`.
*/
$templateArguments = $this->arguments['arguments'] ?: [];
ArrayUtility::mergeRecursiveWithOverrule($templateArguments, $this->fieldService->getFieldOptions());
if (version_compare(VersionNumberUtility::getCurrentTypo3Version(), '8.0.0', '<')) {
$restoreCallback = $this->storeViewDataLegacy();
}

$currentView = $viewHelperVariableContainer->getView();
$templateArguments = $this->getTemplateArguments();

$result = $this->renderLayoutView($templateArguments);

Expand All @@ -140,14 +123,16 @@ public function render()
$this->fieldService->removeCurrentField();
$this->slotService->resetState();

$viewHelperVariableContainer->setView($currentView);
$this->restoreOriginalArguments($templateArguments);
if (version_compare(VersionNumberUtility::getCurrentTypo3Version(), '8.0.0', '<')) {
/** @noinspection PhpUndefinedVariableInspection */
$restoreCallback($templateArguments);
}

return $result;
}

/**
* Will render the associated Fluid view for this field (configured with the
* Will return the associated Fluid view for this field (configured with the
* `layout` argument).
*
* @param array $templateArguments
Expand All @@ -168,30 +153,84 @@ protected function renderLayoutView(array $templateArguments)

$view = $this->fieldService->getView($layout);

$layoutPaths = $this->getPaths('layout');
$partialPaths = $this->getPaths('partial');

if (version_compare(VersionNumberUtility::getCurrentTypo3Version(), '8.0.0', '<')) {
$view->setRenderingContext($this->renderingContext);
} else {
$renderingContext = $view->getRenderingContext();

// Removing all variables previously added to the provider.
$provider = $renderingContext->getVariableProvider();

foreach ($provider->getAllIdentifiers() as $key) {
$provider->remove($key);
}

/*
* Updating the view dependencies: the variable container as well as
* the controller context must be injected in the view.
*/
$renderingContext->setViewHelperVariableContainer($this->viewHelperVariableContainer);

$view->setControllerContext($this->controllerContext);

$variableProvider = $this->getVariableProvider();
$this->viewHelperVariableContainer->setView($view);
}

$view->setLayoutRootPaths($this->getPaths('layout'));
$view->setPartialRootPaths($this->getPaths('partial'));
$view->assignMultiple($templateArguments);

return $view->render();
}

/**
* Temporary solution for TYPO3 6.2 to 7.6 that will store the current view
* variables, to be able to restore them later.
*
* A callback function is returned; it will be called once the field layout
* view was processed, and will restore all the view data.
*
* @return \Closure
*
* @deprecated Will be deleted when TYPO3 7.6 is not supported anymore.
*/
protected function storeViewDataLegacy()
{
$originalArguments = [];

$variableProvider = $this->getVariableProvider();

foreach (self::$reservedVariablesNames as $key) {
if ($variableProvider->exists($key)) {
$originalArguments[$key] = $variableProvider->get($key);
}
}

$viewHelperVariableContainer = $this->renderingContext->getViewHelperVariableContainer();
$currentView = $viewHelperVariableContainer->getView();

return function (array $templateArguments) use ($originalArguments, $variableProvider, $viewHelperVariableContainer, $currentView) {
$viewHelperVariableContainer->setView($currentView);

/*
* Cleaning up the variables in the provider: the original
* values are restored to make the provider like it was before
* the field rendering started.
*/
foreach ($variableProvider->getAllIdentifiers() as $identifier) {
if (array_key_exists($identifier, $templateArguments)) {
$variableProvider->remove($identifier);
}
}

foreach ($templateArguments as $key => $value) {
foreach ($originalArguments as $key => $value) {
if ($variableProvider->exists($key)) {
$variableProvider->remove($key);
}

$variableProvider->add($key, $value);
}
}

$view->setLayoutRootPaths($layoutPaths);
$view->setPartialRootPaths($partialPaths);
$view->assignMultiple($templateArguments);

return $view->render();
};
}

/**
Expand Down Expand Up @@ -257,43 +296,17 @@ protected function getLayout(View $viewConfiguration)
}

/**
* Stores some arguments which may already have been initialized, and could
* be overridden in the local scope.
*/
protected function storeOriginalArguments()
{
$this->originalArguments = [];
$variableProvider = $this->getVariableProvider();

foreach (self::$reservedVariablesNames as $key) {
if ($variableProvider->exists($key)) {
$this->originalArguments[$key] = $variableProvider->get($key);
}
}
}

/**
* Will restore original arguments in the template variable container.
* Merging the arguments with the ones registered with the
* `OptionViewHelper`.
*
* @param array $templateArguments
* @return array
*/
protected function restoreOriginalArguments(array $templateArguments)
protected function getTemplateArguments()
{
$variableProvider = $this->getVariableProvider();

foreach ($variableProvider->getAllIdentifiers() as $identifier) {
if (array_key_exists($identifier, $templateArguments)) {
$variableProvider->remove($identifier);
}
}

foreach ($this->originalArguments as $key => $value) {
if ($variableProvider->exists($key)) {
$variableProvider->remove($key);
}
$templateArguments = $this->arguments['arguments'] ?: [];
ArrayUtility::mergeRecursiveWithOverrule($templateArguments, $this->fieldService->getFieldOptions());

$variableProvider->add($key, $value);
}
return $templateArguments;
}

/**
Expand Down

0 comments on commit cc1cfef

Please sign in to comment.