99 lines
3.5 KiB
PHP
99 lines
3.5 KiB
PHP
<?php
|
|
namespace FluidTYPO3\Vhs\ViewHelpers\Variable;
|
|
|
|
/*
|
|
* This file is part of the FluidTYPO3/Vhs project under GPLv2 or later.
|
|
*
|
|
* For the full copyright and license information, please read the
|
|
* LICENSE.md file that was distributed with this source code.
|
|
*/
|
|
|
|
use TYPO3\CMS\Extbase\Reflection\ObjectAccess;
|
|
use TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper;
|
|
|
|
/**
|
|
* ### Variable: Set
|
|
*
|
|
* Sets a single variable in the TemplateVariableContainer
|
|
* scope. The variable then becomes accessible as {var}.
|
|
*
|
|
* Combines well with `v:variable.get` to set shorter variable
|
|
* names referencing dynamic variables, such as:
|
|
*
|
|
* <v:variable.set name="myObject" value="{v:variable.get(name: 'arrayVariable.{offset}')}" />
|
|
* <!-- If {index} == 4 then {myObject} is now == {arrayVariable.4} -->
|
|
* {myObject.name} <!-- corresponds to {arrayVariable.4.name} -->
|
|
*
|
|
* Note that `{arrayVariable.{offset}.name}` is not possible
|
|
* due to the way Fluid parses nodes; the above piece of
|
|
* code would try reading `arrayVariable.{offset}.name`
|
|
* as a variable actually called "arrayVariable.{offset}.name"
|
|
* rather than the correct `arrayVariable[offset][name]`.
|
|
*
|
|
* In many ways this ViewHelper works like `f:alias`
|
|
* with one exception: in `f:alias` the variable only
|
|
* becomes accessible in the tag content, whereas `v:variable.set`
|
|
* inserts the variable in the template and leaves it there
|
|
* (it "leaks" the variable).
|
|
*
|
|
* If $name contains a dot, VHS will attempt to load the object
|
|
* stored under the named used as the first segment part and
|
|
* set the value at the remaining path. E.g.
|
|
* `{value -> v:variable.set(name: 'object.property.subProperty')}`
|
|
* would attempt to load `{object}` first, then set
|
|
* `property.subProperty` on that object/array using
|
|
* ObjectAccess::setPropertyPath(). If `{object}` is not
|
|
* an object or an array, the variable will not be set. Please
|
|
* note: Extbase does not currently support setting variables
|
|
* deeper than two levels, meaning a `name` of fx `foo.bar.baz`
|
|
* will be ignored. To set values deeper than two levels you
|
|
* must first extract the second-level object then set the
|
|
* value on that object.
|
|
*
|
|
* Using as `{value -> v:variable.set(name: 'myVar')}` makes `{myVar}` contain
|
|
* `{value}`.
|
|
*
|
|
* @author Claus Due <claus@namelesscoder.net>
|
|
* @package Vhs
|
|
* @subpackage ViewHelpers\Var
|
|
*/
|
|
class SetViewHelper extends AbstractViewHelper {
|
|
|
|
/**
|
|
* Set (override) the variable in $name.
|
|
*
|
|
* @param string $name
|
|
* @param mixed $value
|
|
* @return void
|
|
*/
|
|
public function render($name, $value = NULL) {
|
|
if (NULL === $value) {
|
|
$value = $this->renderChildren();
|
|
}
|
|
if (FALSE === strpos($name, '.')) {
|
|
if (TRUE === $this->templateVariableContainer->exists($name)) {
|
|
$this->templateVariableContainer->remove($name);
|
|
}
|
|
$this->templateVariableContainer->add($name, $value);
|
|
} elseif (1 === substr_count($name, '.')) {
|
|
$parts = explode('.', $name);
|
|
$objectName = array_shift($parts);
|
|
$path = implode('.', $parts);
|
|
if (FALSE === $this->templateVariableContainer->exists($objectName)) {
|
|
return NULL;
|
|
}
|
|
$object = $this->templateVariableContainer->get($objectName);
|
|
try {
|
|
ObjectAccess::setProperty($object, $path, $value);
|
|
// Note: re-insert the variable to ensure unreferenced values like arrays also get updated
|
|
$this->templateVariableContainer->remove($objectName);
|
|
$this->templateVariableContainer->add($objectName, $object);
|
|
} catch (\Exception $error) {
|
|
return NULL;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
}
|