Commit 5b145511 authored by Ralf Zimmermann's avatar Ralf Zimmermann Committed by Christian Kuhn
Browse files

[BUGFIX] EXT:form - parse finisher values only if string

Parse finisher option values only if the referenced formelement value
is a string.

Resolves: #79412
Releases: master
Change-Id: Ie379a396473c31907d52c8aa096168fed803510b
Reviewed-on: https://review.typo3.org/51381

Tested-by: default avatarTYPO3com <no-reply@typo3.com>
Reviewed-by: default avatarDaniel Lorenz <daniel.lorenz@extco.de>
Tested-by: default avatarDaniel Lorenz <daniel.lorenz@extco.de>
Reviewed-by: Björn Jacob's avatarBjoern Jacob <bjoern.jacob@tritum.de>
Tested-by: Björn Jacob's avatarBjoern Jacob <bjoern.jacob@tritum.de>
Reviewed-by: Jan Helke's avatarJan Helke <typo3@helke.de>
Reviewed-by: Christian Kuhn's avatarChristian Kuhn <lolli@schwarzbu.ch>
Tested-by: Christian Kuhn's avatarChristian Kuhn <lolli@schwarzbu.ch>
parent 2e872f48
......@@ -161,34 +161,23 @@ abstract class AbstractFinisher implements FinisherInterface
}
$formRuntime = $this->finisherContext->getFormRuntime();
$optionToCompare = $optionValue;
// You can encapsulate a option value with {}.
// This enables you to access every getable property from the
// TYPO3\CMS\Form\Domain\Runtime.
//
// For example: {formState.formValues.<elemenIdentifier>}
// This is equal to "$formRuntime->getFormState()->getFormValues()[<elemenIdentifier>]"
// or {<elemenIdentifier>}
//
// Both examples are equal to "$formRuntime->getFormState()->getFormValues()[<elemenIdentifier>]"
// If the value is not a string nothing will be replaced.
$optionValue = preg_replace_callback('/{([^}]+)}/', function ($match) use ($formRuntime) {
return ObjectAccess::getPropertyPath($formRuntime, $match[1]);
}, $optionValue);
if ($optionToCompare === $optionValue) {
// This is just a shortcut for a {formState.formValues.<elementIdentifier>} notation.
// If one of the finisher option values is equal
// to a identifier from the form definition then
// the value of the submitted form element is used
// insteed.
// Lets say you have a textfield in your form with the
// identifier "Text1". If you put "Text1"
// in the email finisher option "subject" then the submited value
// from the "Text1" element is used as the email subject.
$formValues = $this->finisherContext->getFormValues();
if (!is_bool($optionValue) && array_key_exists($optionValue, $formValues)) {
$optionValue = $formRuntime[$optionValue];
$value = ObjectAccess::getPropertyPath($formRuntime, $match[1]);
if (!is_string($value)) {
$value = '{' . $match[1] . '}';
}
}
return $value;
}, $optionValue);
if (isset($this->options['translation']['translationFile'])) {
$optionValue = TranslationService::getInstance()->translateFinisherOption(
......
<?php
namespace TYPO3\CMS\Form\Tests\Unit\Domain\Finishers;
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
use Prophecy\Argument;
use TYPO3\CMS\Form\Domain\Finishers\AbstractFinisher;
use TYPO3\CMS\Form\Domain\Finishers\FinisherContext;
use TYPO3\CMS\Form\Domain\Runtime\FormRuntime;
/**
* Test case
*/
class AbstractFinisherTest extends \TYPO3\CMS\Components\TestingFramework\Core\UnitTestCase
{
/**
* @test
*/
public function parseOptionReturnsNullIfOptionNameIsTranslation()
{
$mockAbstractFinisher = $this->getAccessibleMockForAbstractClass(
AbstractFinisher::class,
[],
'',
false
);
$this->assertNull($mockAbstractFinisher->_call('parseOption', 'translation'));
}
/**
* @test
*/
public function parseOptionReturnsNullIfOptionNameNotExistsWithinOptions()
{
$mockAbstractFinisher = $this->getAccessibleMockForAbstractClass(
AbstractFinisher::class,
[],
'',
false
);
$mockAbstractFinisher->_set('options', []);
$this->assertNull($mockAbstractFinisher->_call('parseOption', 'foo'));
}
/**
* @test
*/
public function parseOptionReturnsNullIfOptionNameNotExistsWithinDefaultOptions()
{
$mockAbstractFinisher = $this->getAccessibleMockForAbstractClass(
AbstractFinisher::class,
[],
'',
false
);
$mockAbstractFinisher->_set('options', []);
$this->assertNull($mockAbstractFinisher->_call('parseOption', 'foo'));
}
/**
* @test
*/
public function parseOptionReturnsArrayOptionValuesAsArray()
{
$mockAbstractFinisher = $this->getAccessibleMockForAbstractClass(
AbstractFinisher::class,
[],
'',
false
);
$mockAbstractFinisher->_set('options', [
'foo' => ['bar', 'foobar']
]);
$expected = ['bar', 'foobar'];
$this->assertSame($expected, $mockAbstractFinisher->_call('parseOption', 'foo'));
}
/**
* @test
*/
public function parseOptionReturnsValueFromFormRuntimeIfOptionNameReferenceAFormElementIdentifierWhoseValueIsAString()
{
$expected = 'element-value';
$elementIdentifier = 'element-identifier-1';
$mockAbstractFinisher = $this->getAccessibleMockForAbstractClass(
AbstractFinisher::class,
[],
'',
false
);
$mockAbstractFinisher->_set('options', [
'subject' => '{' . $elementIdentifier . '}'
]);
$finisherContextProphecy = $this->prophesize(FinisherContext::class);
$formRuntimeProphecy = $this->prophesize(FormRuntime::class);
$formRuntimeProphecy->offsetExists(Argument::exact($elementIdentifier))->willReturn(true);
$formRuntimeProphecy->offsetGet(Argument::exact($elementIdentifier))->willReturn($expected);
$finisherContextProphecy->getFormRuntime(Argument::cetera())
->willReturn($formRuntimeProphecy->reveal());
$mockAbstractFinisher->_set('finisherContext', $finisherContextProphecy->reveal());
$this->assertSame($expected, $mockAbstractFinisher->_call('parseOption', 'subject'));
}
/**
* @test
*/
public function parseOptionReturnsNoReplacedValueFromFormRuntimeIfOptionNameReferenceAFormElementIdentifierWhoseValueIsNotAString()
{
$elementIdentifier = 'element-identifier-1';
$expected = '{' . $elementIdentifier . '}';
$mockAbstractFinisher = $this->getAccessibleMockForAbstractClass(
AbstractFinisher::class,
[],
'',
false
);
$mockAbstractFinisher->_set('options', [
'subject' => '{' . $elementIdentifier . '}'
]);
$finisherContextProphecy = $this->prophesize(FinisherContext::class);
$formRuntimeProphecy = $this->prophesize(FormRuntime::class);
$formRuntimeProphecy->offsetExists(Argument::exact($elementIdentifier))->willReturn(true);
$formElementValue = new \DateTime;
$formRuntimeProphecy->offsetGet(Argument::exact($elementIdentifier))->willReturn($formElementValue);
$finisherContextProphecy->getFormRuntime(Argument::cetera())
->willReturn($formRuntimeProphecy->reveal());
$mockAbstractFinisher->_set('finisherContext', $finisherContextProphecy->reveal());
$this->assertSame($expected, $mockAbstractFinisher->_call('parseOption', 'subject'));
}
/**
* @test
*/
public function parseOptionReturnsNoReplacedValueFromFormRuntimeIfOptionNameReferenceANonExistingFormElement()
{
$elementIdentifier = 'element-identifier-1';
$mockAbstractFinisher = $this->getAccessibleMockForAbstractClass(
AbstractFinisher::class,
[],
'',
false
);
$mockAbstractFinisher->_set('options', [
'subject' => '{' . $elementIdentifier . '}'
]);
$finisherContextProphecy = $this->prophesize(FinisherContext::class);
$formRuntimeProphecy = $this->prophesize(FormRuntime::class);
$formRuntimeProphecy->offsetExists(Argument::cetera())->willReturn(true);
$formRuntimeProphecy->offsetGet(Argument::cetera())->willReturn(false);
$finisherContextProphecy->getFormRuntime(Argument::cetera())
->willReturn($formRuntimeProphecy->reveal());
$mockAbstractFinisher->_set('finisherContext', $finisherContextProphecy->reveal());
$expected = '{' . $elementIdentifier . '}';
$this->assertSame($expected, $mockAbstractFinisher->_call('parseOption', 'subject'));
}
/**
* @test
*/
public function parseOptionReturnsDefaultOptionValueIfOptionNameNotExistsWithinOptionsButWithinDefaultOptions()
{
$expected = 'defaultValue';
$mockAbstractFinisher = $this->getAccessibleMockForAbstractClass(
AbstractFinisher::class,
[],
'',
false
);
$mockAbstractFinisher->_set('options', []);
$mockAbstractFinisher->_set('defaultOptions', [
'subject' => $expected
]);
$finisherContextProphecy = $this->prophesize(FinisherContext::class);
$formRuntimeProphecy = $this->prophesize(FormRuntime::class);
$formRuntimeProphecy->offsetExists(Argument::cetera())->willReturn(true);
$formRuntimeProphecy->offsetGet(Argument::cetera())->willReturn(false);
$finisherContextProphecy->getFormRuntime(Argument::cetera())
->willReturn($formRuntimeProphecy->reveal());
$mockAbstractFinisher->_set('finisherContext', $finisherContextProphecy->reveal());
$this->assertSame($expected, $mockAbstractFinisher->_call('parseOption', 'subject'));
}
/**
* @test
*/
public function parseOptionReturnsDefaultOptionValueIfOptionValueIsAFormElementReferenceAndTheFormElementValueIsEmpty()
{
$elementIdentifier = 'element-identifier-1';
$expected = 'defaultValue';
$mockAbstractFinisher = $this->getAccessibleMockForAbstractClass(
AbstractFinisher::class,
[],
'',
false
);
$mockAbstractFinisher->_set('options', [
'subject' => '{' . $elementIdentifier . '}'
]);
$mockAbstractFinisher->_set('defaultOptions', [
'subject' => $expected
]);
$finisherContextProphecy = $this->prophesize(FinisherContext::class);
$formRuntimeProphecy = $this->prophesize(FormRuntime::class);
$formRuntimeProphecy->offsetExists(Argument::exact($elementIdentifier))->willReturn(true);
$formRuntimeProphecy->offsetGet(Argument::exact($elementIdentifier))->willReturn('');
$finisherContextProphecy->getFormRuntime(Argument::cetera())
->willReturn($formRuntimeProphecy->reveal());
$mockAbstractFinisher->_set('finisherContext', $finisherContextProphecy->reveal());
$this->assertSame($expected, $mockAbstractFinisher->_call('parseOption', 'subject'));
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment