use TYPO3\CMS\Core\Utility\ArrayUtility;
use TYPO3\CMS\Core\Utility\Exception\MissingArrayPathException;
use TYPO3\CMS\Extbase\Reflection\ObjectAccess;
+use TYPO3\CMS\Form\Domain\Finishers\Exception\FinisherException;
+use TYPO3\CMS\Form\Domain\Runtime\FormRuntime;
use TYPO3\CMS\Form\Service\TranslationService;
use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
return null;
}
- if (is_array($optionValue) || is_bool($optionValue)) {
- return $optionValue;
- }
-
- if ($optionValue instanceof \Closure) {
+ if (!is_string($optionValue) && !is_array($optionValue)) {
return $optionValue;
}
$formRuntime = $this->finisherContext->getFormRuntime();
+ $optionValue = $this->substituteRuntimeReferences($optionValue, $formRuntime);
- // You can encapsulate a option value with {}.
- // This enables you to access every getable property from the
- // TYPO3\CMS\Form\Domain\Runtime\FormRuntime.
- //
- // For example: {formState.formValues.<elemenIdentifier>}
- // or {<elemenIdentifier>}
- //
- // Both examples are equal to "$formRuntime->getFormState()->getFormValues()[<elemenIdentifier>]"
- // If the value is not a string nothing will be replaced.
- // There is a special option value '{__currentTimestamp}'.
- // This will be replaced with the current timestamp.
- $optionValue = preg_replace_callback('/{([^}]+)}/', function ($match) use ($formRuntime) {
- if ($match[1] === '__currentTimestamp') {
- $value = time();
- } else {
- // try to resolve the path '{...}' within the FormRuntime
- $value = ObjectAccess::getPropertyPath($formRuntime, $match[1]);
- if ($value === null) {
- // try to resolve the path '{...}' within the FinisherVariableProvider
- $value = ObjectAccess::getPropertyPath(
- $this->finisherContext->getFinisherVariableProvider(),
- $match[1]
- );
- }
- }
- if (!is_string($value) && !is_numeric($value)) {
- $value = '{' . $match[1] . '}';
+ if (is_string($optionValue)) {
+ $translationOptions = isset($this->options['translation']) && \is_array($this->options['translation'])
+ ? $this->options['translation']
+ : [];
+
+ $optionValue = $this->translateFinisherOption(
+ $optionValue,
+ $formRuntime,
+ $optionName,
+ $optionValue,
+ $translationOptions
+ );
+
+ $optionValue = $this->substituteRuntimeReferences($optionValue, $formRuntime);
+ }
+
+ if (empty($optionValue)) {
+ if ($defaultValue !== null) {
+ $optionValue = $defaultValue;
}
- return $value;
- }, $optionValue);
+ }
+ return $optionValue;
+ }
- $renderingOptions = isset($this->options['translation']) ?? \is_array($this->options['translation'])
- ? $this->options['translation']
- : [];
+ /**
+ * Wraps TranslationService::translateFinisherOption to recursively
+ * invoke all array items of resolved form state values or nested
+ * finisher option configuration settings.
+ *
+ * @param string|array $subject
+ * @param FormRuntime $formRuntime
+ * @param string $optionName
+ * @param string|array $optionValue
+ * @param array $translationOptions
+ * @return array|string
+ */
+ protected function translateFinisherOption(
+ $subject,
+ FormRuntime $formRuntime,
+ string $optionName,
+ $optionValue,
+ array $translationOptions
+ ) {
+ if (is_array($subject)) {
+ foreach ($subject as $key => $value) {
+ $subject[$key] = $this->translateFinisherOption(
+ $value,
+ $formRuntime,
+ $optionName . '.' . $value,
+ $value,
+ $translationOptions
+ );
+ }
+ return $subject;
+ }
- $optionValue = TranslationService::getInstance()->translateFinisherOption(
+ return TranslationService::getInstance()->translateFinisherOption(
$formRuntime,
$this->finisherIdentifier,
$optionName,
$optionValue,
- $renderingOptions
+ $translationOptions
);
+ }
- if (empty($optionValue)) {
- if ($defaultValue !== null) {
- $optionValue = $defaultValue;
- }
+ /**
+ * You can encapsulate a option value with {}.
+ * This enables you to access every getable property from the
+ * TYPO3\CMS\Form\Domain\Runtime\FormRuntime.
+ *
+ * For example: {formState.formValues.<elemenIdentifier>}
+ * or {<elemenIdentifier>}
+ *
+ * Both examples are equal to "$formRuntime->getFormState()->getFormValues()[<elemenIdentifier>]"
+ * There is a special option value '{__currentTimestamp}'.
+ * This will be replaced with the current timestamp.
+ *
+ * @param string|array $needle
+ * @param FormRuntime $formRuntime
+ * @return mixed
+ */
+ protected function substituteRuntimeReferences($needle, FormRuntime $formRuntime)
+ {
+ // neither array nor string, directly return
+ if (!is_array($needle) && !is_string($needle)) {
+ return $needle;
}
- return $optionValue;
+
+ // resolve (recursively) all array items
+ if (is_array($needle)) {
+ return array_map(
+ function ($item) use ($formRuntime) {
+ return $this->substituteRuntimeReferences($item, $formRuntime);
+ },
+ $needle
+ );
+ }
+
+ // substitute one(!) variable in string which either could result
+ // again in a string or an array representing multiple values
+ if (preg_match('/^{([^}]+)}$/', $needle, $matches)) {
+ return $this->resolveRuntimeReference(
+ $matches[1],
+ $formRuntime
+ );
+ }
+
+ // in case string contains more than just one variable or just a static
+ // value that does not need to be substituted at all, candidates are:
+ // * "prefix{variable}suffix
+ // * "{variable-1},{variable-2}"
+ // * "some static value"
+ // * mixed cases of the above
+ return preg_replace_callback(
+ '/{([^}]+)}/',
+ function ($matches) use ($formRuntime) {
+ $value = $this->resolveRuntimeReference(
+ $matches[1],
+ $formRuntime
+ );
+
+ // substitute each match by returning the resolved value
+ if (!is_array($value)) {
+ return $value;
+ }
+
+ // now the resolve value is an array that shall substitute
+ // a variable in a string that probably is not the only one
+ // or is wrapped with other static string content (see above)
+ // ... which is just not possible
+ throw new FinisherException(
+ 'Cannot convert array to string',
+ 1519239265
+ );
+ },
+ $needle
+ );
+ }
+
+ /**
+ * Resolving property by name from submitted form data.
+ *
+ * @param string $property
+ * @param FormRuntime $formRuntime
+ * @return int|string|array
+ */
+ protected function resolveRuntimeReference(string $property, FormRuntime $formRuntime)
+ {
+ if ($property === '__currentTimestamp') {
+ return time();
+ }
+ // try to resolve the path '{...}' within the FormRuntime
+ $value = ObjectAccess::getPropertyPath($formRuntime, $property);
+ if ($value === null) {
+ // try to resolve the path '{...}' within the FinisherVariableProvider
+ $value = ObjectAccess::getPropertyPath(
+ $this->finisherContext->getFinisherVariableProvider(),
+ $property
+ );
+ }
+ if ($value !== null) {
+ return $value;
+ }
+ // in case no value could be resolved
+ return '{' . $property . '}';
}
/**
*/
use Prophecy\Argument;
+use Prophecy\Prophecy\ObjectProphecy;
use TYPO3\CMS\Core\Utility\GeneralUtility;
-use TYPO3\CMS\Extbase\Object\ObjectManager;
use TYPO3\CMS\Form\Domain\Finishers\AbstractFinisher;
+use TYPO3\CMS\Form\Domain\Finishers\Exception\FinisherException;
use TYPO3\CMS\Form\Domain\Finishers\FinisherContext;
+use TYPO3\CMS\Form\Domain\Finishers\FinisherVariableProvider;
use TYPO3\CMS\Form\Domain\Runtime\FormRuntime;
-use TYPO3\CMS\Form\Service\TranslationService;
use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
/**
/**
* @test
*/
- public function parseOptionReturnsArrayOptionValuesAsArray(): void
+ public function parseOptionReturnsBoolOptionValuesAsBool(): void
{
$mockAbstractFinisher = $this->getAccessibleMockForAbstractClass(
AbstractFinisher::class,
);
$mockAbstractFinisher->_set('options', [
- 'foo' => ['bar', 'foobar']
+ 'foo1' => false,
]);
- $expected = ['bar', 'foobar'];
+ $expected = false;
- $this->assertSame($expected, $mockAbstractFinisher->_call('parseOption', 'foo'));
+ $this->assertSame($expected, $mockAbstractFinisher->_call('parseOption', 'foo1'));
}
/**
* @test
*/
- public function parseOptionReturnsBoolOptionValuesAsBool(): void
+ public function parseOptionReturnsDefaultOptionValueIfOptionNameNotExistsWithinOptionsButWithinDefaultOptions(): void
{
+ $expected = 'defaultValue';
+
$mockAbstractFinisher = $this->getAccessibleMockForAbstractClass(
AbstractFinisher::class,
[],
'',
- false
+ false,
+ false,
+ true,
+ [
+ 'translateFinisherOption'
+ ]
);
- $mockAbstractFinisher->_set('options', [
- 'foo1' => false,
+ $mockAbstractFinisher
+ ->expects($this->any())
+ ->method('translateFinisherOption')
+ ->willReturnArgument(0);
+
+ $mockAbstractFinisher->_set('options', []);
+ $mockAbstractFinisher->_set('defaultOptions', [
+ 'subject' => $expected
]);
- $expected = false;
+ $finisherContextProphecy = $this->prophesize(FinisherContext::class);
- $this->assertSame($expected, $mockAbstractFinisher->_call('parseOption', 'foo1'));
+ $formRuntimeProphecy = $this->prophesize(FormRuntime::class);
+ $formRuntimeProphecy->offsetExists(Argument::cetera())->willReturn(true);
+ $formRuntimeProphecy->offsetGet(Argument::cetera())->willReturn(null);
+
+ $finisherContextProphecy->getFormRuntime(Argument::cetera())
+ ->willReturn($formRuntimeProphecy->reveal());
+ $finisherContextProphecy->getFinisherVariableProvider(Argument::cetera())
+ ->willReturn(new FinisherVariableProvider);
+
+ $mockAbstractFinisher->_set('finisherContext', $finisherContextProphecy->reveal());
+
+ $this->assertSame($expected, $mockAbstractFinisher->_call('parseOption', 'subject'));
}
/**
* @test
*/
- public function parseOptionReturnsValueFromFormRuntimeIfOptionNameReferenceAFormElementIdentifierWhoseValueIsAString(): void
+ public function parseOptionReturnsDefaultOptionValueIfOptionValueIsAFormElementReferenceAndTheFormElementValueIsEmpty(): void
{
- $objectManagerProphecy = $this->prophesize(ObjectManager::class);
- GeneralUtility::setSingletonInstance(ObjectManager::class, $objectManagerProphecy->reveal());
-
- $mockTranslationService = $this->getAccessibleMock(TranslationService::class, [
- 'translateFinisherOption'
- ], [], '', false);
-
- $mockTranslationService
- ->expects($this->any())
- ->method('translateFinisherOption')
- ->willReturnArgument(3);
-
- $objectManagerProphecy
- ->get(TranslationService::class)
- ->willReturn($mockTranslationService);
-
- $expected = 'element-value';
$elementIdentifier = 'element-identifier-1';
+ $expected = 'defaultValue';
$mockAbstractFinisher = $this->getAccessibleMockForAbstractClass(
AbstractFinisher::class,
[],
'',
- false
+ false,
+ false,
+ true,
+ [
+ 'translateFinisherOption'
+ ]
);
+ $mockAbstractFinisher
+ ->expects($this->any())
+ ->method('translateFinisherOption')
+ ->willReturnArgument(0);
+
$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($expected);
+ $formRuntimeProphecy = $this->createFormRuntimeProphecy([
+ $elementIdentifier => ''
+ ]);
$finisherContextProphecy->getFormRuntime(Argument::cetera())
->willReturn($formRuntimeProphecy->reveal());
/**
* @test
*/
- public function parseOptionReturnsNoReplacedValueFromFormRuntimeIfOptionNameReferenceAFormElementIdentifierWhoseValueIsNotAString(): void
+ public function parseOptionResolvesFormElementReferenceFromTranslation(): void
{
- $objectManagerProphecy = $this->prophesize(ObjectManager::class);
- GeneralUtility::setSingletonInstance(ObjectManager::class, $objectManagerProphecy->reveal());
-
- $mockTranslationService = $this->getAccessibleMock(TranslationService::class, [
- 'translateFinisherOption'
- ], [], '', false);
-
- $mockTranslationService
- ->expects($this->any())
- ->method('translateFinisherOption')
- ->willReturnArgument(3);
-
- $objectManagerProphecy
- ->get(TranslationService::class)
- ->willReturn($mockTranslationService);
-
- $elementIdentifier = 'element-identifier-1';
- $expected = '{' . $elementIdentifier . '}';
-
$mockAbstractFinisher = $this->getAccessibleMockForAbstractClass(
AbstractFinisher::class,
[],
'',
- false
+ false,
+ false,
+ true,
+ [
+ 'translateFinisherOption'
+ ]
);
+ $elementIdentifier = 'element-identifier-1';
+ $elementValue = 'element-value-1';
+ $elementReferenceName = '{' . $elementIdentifier . '}';
+
+ $translationValue = 'subject: ' . $elementReferenceName;
+ $expected = 'subject: ' . $elementValue;
+
+ $mockAbstractFinisher
+ ->expects($this->any())
+ ->method('translateFinisherOption')
+ ->willReturn($translationValue);
+
$mockAbstractFinisher->_set('options', [
- 'subject' => '{' . $elementIdentifier . '}'
+ 'subject' => ''
]);
$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);
+ $formRuntimeProphecy = $this->createFormRuntimeProphecy([
+ $elementIdentifier => $elementValue
+ ]);
$finisherContextProphecy->getFormRuntime(Argument::cetera())
->willReturn($formRuntimeProphecy->reveal());
/**
* @test
*/
- public function parseOptionReturnsNoReplacedValueFromFormRuntimeIfOptionNameReferenceANonExistingFormElement(): void
+ public function substituteRuntimeReferencesReturnsArrayIfInputIsArray(): void
{
- $objectManagerProphecy = $this->prophesize(ObjectManager::class);
- GeneralUtility::setSingletonInstance(ObjectManager::class, $objectManagerProphecy->reveal());
-
- $mockTranslationService = $this->getAccessibleMock(TranslationService::class, [
- 'translateFinisherOption'
- ], [], '', false);
+ $mockAbstractFinisher = $this->getAccessibleMockForAbstractClass(
+ AbstractFinisher::class,
+ [],
+ '',
+ false
+ );
- $mockTranslationService
- ->expects($this->any())
- ->method('translateFinisherOption')
- ->willReturnArgument(3);
+ $formRuntimeProphecy = $this->prophesize(FormRuntime::class);
- $objectManagerProphecy
- ->get(TranslationService::class)
- ->willReturn($mockTranslationService);
+ $input = ['bar', 'foobar', ['x', 'y']];
+ $expected = ['bar', 'foobar', ['x', 'y']];
- $elementIdentifier = 'element-identifier-1';
+ $this->assertSame($expected, $mockAbstractFinisher->_call('substituteRuntimeReferences', $input, $formRuntimeProphecy->reveal()));
+ }
+ /**
+ * @test
+ */
+ public function substituteRuntimeReferencesReturnsStringIfInputIsString(): void
+ {
$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());
+ $input = 'foobar';
+ $expected = 'foobar';
- $expected = '{' . $elementIdentifier . '}';
- $this->assertSame($expected, $mockAbstractFinisher->_call('parseOption', 'subject'));
+ $this->assertSame($expected, $mockAbstractFinisher->_call('substituteRuntimeReferences', $input, $formRuntimeProphecy->reveal()));
}
/**
* @test
*/
- public function parseOptionReturnsDefaultOptionValueIfOptionNameNotExistsWithinOptionsButWithinDefaultOptions(): void
+ public function substituteRuntimeReferencesReturnsValueFromFormRuntimeIfInputReferenceAFormElementIdentifierWhoseValueIsAString(): void
{
- $objectManagerProphecy = $this->prophesize(ObjectManager::class);
- GeneralUtility::setSingletonInstance(ObjectManager::class, $objectManagerProphecy->reveal());
-
- $mockTranslationService = $this->getAccessibleMock(TranslationService::class, [
- 'translateFinisherOption'
- ], [], '', false);
+ $mockAbstractFinisher = $this->getAccessibleMockForAbstractClass(
+ AbstractFinisher::class,
+ [],
+ '',
+ false
+ );
- $mockTranslationService
- ->expects($this->any())
- ->method('translateFinisherOption')
- ->willReturnArgument(3);
+ $elementIdentifier = 'element-identifier-1';
+ $input = '{' . $elementIdentifier . '}';
+ $expected = 'element-value';
- $objectManagerProphecy
- ->get(TranslationService::class)
- ->willReturn($mockTranslationService);
+ $formRuntimeProphecy = $this->createFormRuntimeProphecy([
+ $elementIdentifier => $expected
+ ]);
- $expected = 'defaultValue';
+ $this->assertSame($expected, $mockAbstractFinisher->_call('substituteRuntimeReferences', $input, $formRuntimeProphecy->reveal()));
+ }
+ /**
+ * @test
+ */
+ public function substituteRuntimeReferencesReturnsValueFromFormRuntimeIfInputReferenceMultipleFormElementIdentifierWhoseValueIsAString(): void
+ {
$mockAbstractFinisher = $this->getAccessibleMockForAbstractClass(
AbstractFinisher::class,
[],
false
);
- $mockAbstractFinisher->_set('options', []);
- $mockAbstractFinisher->_set('defaultOptions', [
- 'subject' => $expected
- ]);
-
- $finisherContextProphecy = $this->prophesize(FinisherContext::class);
+ $elementIdentifier1 = 'element-identifier-1';
+ $elementValue1 = 'element-value-1';
+ $elementIdentifier2 = 'element-identifier-2';
+ $elementValue2 = 'element-value-2';
- $formRuntimeProphecy = $this->prophesize(FormRuntime::class);
- $formRuntimeProphecy->offsetExists(Argument::cetera())->willReturn(true);
- $formRuntimeProphecy->offsetGet(Argument::cetera())->willReturn(false);
+ $input = '{' . $elementIdentifier1 . '},{' . $elementIdentifier2 . '}';
+ $expected = $elementValue1 . ',' . $elementValue2;
- $finisherContextProphecy->getFormRuntime(Argument::cetera())
- ->willReturn($formRuntimeProphecy->reveal());
-
- $mockAbstractFinisher->_set('finisherContext', $finisherContextProphecy->reveal());
+ $formRuntimeProphecy = $this->createFormRuntimeProphecy([
+ $elementIdentifier1 => $elementValue1,
+ $elementIdentifier2 => $elementValue2
+ ]);
- $this->assertSame($expected, $mockAbstractFinisher->_call('parseOption', 'subject'));
+ $this->assertSame($expected, $mockAbstractFinisher->_call('substituteRuntimeReferences', $input, $formRuntimeProphecy->reveal()));
}
/**
* @test
*/
- public function parseOptionReturnsDefaultOptionValueIfOptionValueIsAFormElementReferenceAndTheFormElementValueIsEmpty(): void
+ public function substituteRuntimeReferencesReturnsValueFromFormRuntimeIfInputReferenceAFormElementIdentifierWhoseValueIsAnArray(): void
{
- $objectManagerProphecy = $this->prophesize(ObjectManager::class);
- GeneralUtility::setSingletonInstance(ObjectManager::class, $objectManagerProphecy->reveal());
-
- $mockTranslationService = $this->getAccessibleMock(TranslationService::class, [
- 'translateFinisherOption'
- ], [], '', false);
+ $mockAbstractFinisher = $this->getAccessibleMockForAbstractClass(
+ AbstractFinisher::class,
+ [],
+ '',
+ false
+ );
- $mockTranslationService
- ->expects($this->any())
- ->method('translateFinisherOption')
- ->willReturnArgument(3);
+ $elementIdentifier = 'element-identifier-1';
+ $input = '{' . $elementIdentifier . '}';
+ $expected = ['bar', 'foobar'];
- $objectManagerProphecy
- ->get(TranslationService::class)
- ->willReturn($mockTranslationService);
+ $formRuntimeProphecy = $this->createFormRuntimeProphecy([
+ $elementIdentifier => $expected
+ ]);
- $elementIdentifier = 'element-identifier-1';
- $expected = 'defaultValue';
+ $this->assertSame($expected, $mockAbstractFinisher->_call('substituteRuntimeReferences', $input, $formRuntimeProphecy->reveal()));
+ }
+ /**
+ * @test
+ */
+ public function substituteRuntimeReferencesReturnsValueFromFormRuntimeIfInputIsArrayAndSomeItemsReferenceAFormElementIdentifierWhoseValueIsAnArray(): void
+ {
$mockAbstractFinisher = $this->getAccessibleMockForAbstractClass(
AbstractFinisher::class,
[],
false
);
- $mockAbstractFinisher->_set('options', [
- 'subject' => '{' . $elementIdentifier . '}'
- ]);
- $mockAbstractFinisher->_set('defaultOptions', [
- 'subject' => $expected
+ $elementIdentifier1 = 'element-identifier-1';
+ $elementValue1 = ['klaus', 'fritz'];
+ $elementIdentifier2 = 'element-identifier-2';
+ $elementValue2 = ['stan', 'steve'];
+
+ $input = [
+ '{' . $elementIdentifier1 . '}',
+ 'static value',
+ 'norbert' => [
+ 'lisa',
+ '{' . $elementIdentifier1 . '}',
+ '{' . $elementIdentifier2 . '}',
+ ],
+ ];
+ $expected = [
+ ['klaus', 'fritz'],
+ 'static value',
+ 'norbert' => [
+ 'lisa',
+ ['klaus', 'fritz'],
+ ['stan', 'steve'],
+ ]
+ ];
+
+ $formRuntimeProphecy = $this->createFormRuntimeProphecy([
+ $elementIdentifier1 => $elementValue1,
+ $elementIdentifier2 => $elementValue2
]);
- $finisherContextProphecy = $this->prophesize(FinisherContext::class);
+ $this->assertSame($expected, $mockAbstractFinisher->_call('substituteRuntimeReferences', $input, $formRuntimeProphecy->reveal()));
+ }
- $formRuntimeProphecy = $this->prophesize(FormRuntime::class);
- $formRuntimeProphecy->offsetExists(Argument::exact($elementIdentifier))->willReturn(true);
- $formRuntimeProphecy->offsetGet(Argument::exact($elementIdentifier))->willReturn('');
+ /**
+ * @test
+ */
+ public function substituteRuntimeReferencesReturnsNoReplacedValueIfInputReferenceANonExistingFormElement(): void
+ {
+ $mockAbstractFinisher = $this->getAccessibleMockForAbstractClass(
+ AbstractFinisher::class,
+ [],
+ '',
+ false
+ );
- $finisherContextProphecy->getFormRuntime(Argument::cetera())
- ->willReturn($formRuntimeProphecy->reveal());
+ $elementIdentifier = 'element-identifier-1';
+ $input = '{' . $elementIdentifier . '}';
+ $expected = '{' . $elementIdentifier . '}';
+ $formRuntimeProphecy = $this->createFormRuntimeProphecy([
+ $elementIdentifier => $expected
+ ]);
+
+ $finisherContextProphecy = $this->prophesize(FinisherContext::class);
+ $finisherContextProphecy->getFinisherVariableProvider(Argument::cetera())->willReturn(new FinisherVariableProvider);
$mockAbstractFinisher->_set('finisherContext', $finisherContextProphecy->reveal());
- $this->assertSame($expected, $mockAbstractFinisher->_call('parseOption', 'subject'));
+ $this->assertSame($expected, $mockAbstractFinisher->_call('substituteRuntimeReferences', $input, $formRuntimeProphecy->reveal()));
}
/**
* @test
*/
- public function parseOptionReturnsTimestampIfOptionValueIsATimestampRequestTrigger(): void
+ public function substituteRuntimeReferencesReturnsTimestampIfInputIsATimestampRequestTrigger(): void
{
- $objectManagerProphecy = $this->prophesize(ObjectManager::class);
- GeneralUtility::setSingletonInstance(ObjectManager::class, $objectManagerProphecy->reveal());
+ $mockAbstractFinisher = $this->getAccessibleMockForAbstractClass(
+ AbstractFinisher::class,
+ [],
+ '',
+ false
+ );
- $mockTranslationService = $this->getAccessibleMock(TranslationService::class, [
- 'translateFinisherOption'
- ], [], '', false);
+ $input = '{__currentTimestamp}';
+ $expected = '#^([0-9]{10})$#';
- $mockTranslationService
- ->expects($this->any())
- ->method('translateFinisherOption')
- ->willReturnArgument(3);
+ $formRuntimeProphecy = $this->prophesize(FormRuntime::class);
- $objectManagerProphecy
- ->get(TranslationService::class)
- ->willReturn($mockTranslationService);
+ $this->assertEquals(1, preg_match($expected, (string)$mockAbstractFinisher->_call('substituteRuntimeReferences', $input, $formRuntimeProphecy->reveal())));
+ }
+ /**
+ * @test
+ */
+ public function substituteRuntimeReferencesThrowsExceptionOnMultipleVariablesResolvedAsArray(): void
+ {
$mockAbstractFinisher = $this->getAccessibleMockForAbstractClass(
AbstractFinisher::class,
[],
false
);
- $mockAbstractFinisher->_set('options', [
- 'crdate' => '{__currentTimestamp}'
+ $elementIdentifier = 'element-identifier-1';
+ $input = 'BEFORE {' . $elementIdentifier . '} AFTER';
+
+ $formRuntimeProphecy = $this->createFormRuntimeProphecy([
+ $elementIdentifier => ['value-1', 'value-2']
]);
$finisherContextProphecy = $this->prophesize(FinisherContext::class);
+ $finisherContextProphecy->getFinisherVariableProvider(Argument::cetera())->willReturn(new FinisherVariableProvider);
+ $mockAbstractFinisher->_set('finisherContext', $finisherContextProphecy->reveal());
- $formRuntimeProphecy = $this->prophesize(FormRuntime::class);
-
- $finisherContextProphecy->getFormRuntime(Argument::cetera())
- ->willReturn($formRuntimeProphecy->reveal());
+ $this->expectException(FinisherException::class);
+ $this->expectExceptionCode(1519239265);
- $mockAbstractFinisher->_set('finisherContext', $finisherContextProphecy->reveal());
+ $mockAbstractFinisher->_call(
+ 'substituteRuntimeReferences',
+ $input,
+ $formRuntimeProphecy->reveal()
+ );
+ }
- $expected = '#^([0-9]{10})$#';
- $this->assertEquals(1, preg_match($expected, $mockAbstractFinisher->_call('parseOption', 'crdate')));
+ /**
+ * @param array $values Key/Value pairs to be retrievable
+ * @return ObjectProphecy|FormRuntime
+ */
+ protected function createFormRuntimeProphecy(array $values)
+ {
+ /** @var ObjectProphecy|FormRuntime $formRuntimeProphecy */
+ $formRuntimeProphecy = $this->prophesize(FormRuntime::class);
+ foreach ($values as $key => $value) {
+ $formRuntimeProphecy->offsetExists(Argument::exact($key))->willReturn(true);
+ $formRuntimeProphecy->offsetGet(Argument::exact($key))->willReturn($value);
+ }
+ return $formRuntimeProphecy;
}
}