1<?php
2
3declare(strict_types=1);
4
5/*
6 * This file is part of the TYPO3 CMS project.
7 *
8 * It is free software; you can redistribute it and/or modify it under
9 * the terms of the GNU General Public License, either version 2
10 * of the License, or any later version.
11 *
12 * For the full copyright and license information, please read the
13 * LICENSE.txt file that was distributed with this source code.
14 *
15 * The TYPO3 project - inspiring people to share!
16 */
17
18namespace TYPO3\CMS\Form\Domain\Finishers;
19
20use TYPO3\CMS\Core\Utility\GeneralUtility;
21use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
22use TYPO3\CMS\Fluid\View\StandaloneView;
23use TYPO3\CMS\Form\Domain\Finishers\Exception\FinisherException;
24use TYPO3\CMS\Form\Domain\Runtime\FormRuntime;
25use TYPO3\CMS\Form\ViewHelpers\RenderRenderableViewHelper;
26use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
27
28/**
29 * A finisher that outputs a given text
30 *
31 * Options:
32 *
33 * - message: A hard-coded message to be rendered
34 * - contentElementUid: A content element uid to be rendered
35 *
36 * Usage:
37 * //...
38 * $confirmationFinisher = $this->objectManager->get(ConfirmationFinisher::class);
39 * $confirmationFinisher->setOptions(
40 *   [
41 *     'message' => 'foo',
42 *   ]
43 * );
44 * $formDefinition->addFinisher($confirmationFinisher);
45 * // ...
46 *
47 * Scope: frontend
48 */
49class ConfirmationFinisher extends AbstractFinisher
50{
51
52    /**
53     * @var array
54     */
55    protected $defaultOptions = [
56        'message' => 'The form has been submitted.',
57        'contentElementUid' => 0,
58        'typoscriptObjectPath' => 'lib.tx_form.contentElementRendering'
59    ];
60
61    /**
62     * @var array
63     */
64    protected $typoScriptSetup = [];
65
66    /**
67     * @var ConfigurationManagerInterface
68     */
69    protected $configurationManager;
70
71    /**
72     * @var ContentObjectRenderer
73     */
74    protected $contentObjectRenderer;
75
76    /**
77     * @param \TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface $configurationManager
78     */
79    public function injectConfigurationManager(ConfigurationManagerInterface $configurationManager)
80    {
81        $this->configurationManager = $configurationManager;
82        $this->typoScriptSetup = $this->configurationManager->getConfiguration(ConfigurationManagerInterface::CONFIGURATION_TYPE_FULL_TYPOSCRIPT);
83    }
84
85    /**
86     * @param ContentObjectRenderer $contentObjectRenderer
87     */
88    public function injectContentObjectRenderer(ContentObjectRenderer $contentObjectRenderer)
89    {
90        $this->contentObjectRenderer = $contentObjectRenderer;
91    }
92
93    /**
94     * Executes this finisher
95     *
96     * @see AbstractFinisher::execute()
97     * @return string
98     *
99     * @throws FinisherException
100     */
101    protected function executeInternal()
102    {
103        $contentElementUid = $this->parseOption('contentElementUid');
104        $typoscriptObjectPath = $this->parseOption('typoscriptObjectPath');
105        $typoscriptObjectPath = is_string($typoscriptObjectPath) ? $typoscriptObjectPath : '';
106        if (!empty($contentElementUid)) {
107            $pathSegments = GeneralUtility::trimExplode('.', $typoscriptObjectPath);
108            $lastSegment = array_pop($pathSegments);
109            $setup = $this->typoScriptSetup;
110            foreach ($pathSegments as $segment) {
111                if (!array_key_exists($segment . '.', $setup)) {
112                    throw new FinisherException(
113                        sprintf('TypoScript object path "%s" does not exist', $typoscriptObjectPath),
114                        1489238980
115                    );
116                }
117                $setup = $setup[$segment . '.'];
118            }
119            $this->contentObjectRenderer->start([$contentElementUid], '');
120            $this->contentObjectRenderer->setCurrentVal((string)$contentElementUid);
121            $message = $this->contentObjectRenderer->cObjGetSingle($setup[$lastSegment], $setup[$lastSegment . '.'], $lastSegment);
122        } else {
123            $message = $this->parseOption('message');
124        }
125
126        $standaloneView = $this->initializeStandaloneView(
127            $this->finisherContext->getFormRuntime()
128        );
129
130        $standaloneView->assignMultiple([
131            'message' => $message,
132            'isPreparedMessage' => !empty($contentElementUid),
133        ]);
134
135        return $standaloneView->render();
136    }
137
138    /**
139     * @param FormRuntime $formRuntime
140     * @return StandaloneView
141     * @throws FinisherException
142     */
143    protected function initializeStandaloneView(FormRuntime $formRuntime): StandaloneView
144    {
145        $standaloneView = $this->objectManager->get(StandaloneView::class);
146
147        if (!isset($this->options['templateName'])) {
148            throw new FinisherException(
149                'The option "templateName" must be set for the ConfirmationFinisher.',
150                1521573955
151            );
152        }
153
154        $standaloneView->setTemplate($this->options['templateName']);
155        $standaloneView->getTemplatePaths()->fillFromConfigurationArray($this->options);
156
157        if (isset($this->options['variables']) && is_array($this->options['variables'])) {
158            $standaloneView->assignMultiple($this->options['variables']);
159        }
160
161        $standaloneView->assign('form', $formRuntime);
162        $standaloneView->assign('finisherVariableProvider', $this->finisherContext->getFinisherVariableProvider());
163
164        $standaloneView->getRenderingContext()
165            ->getViewHelperVariableContainer()
166            ->addOrUpdate(RenderRenderableViewHelper::class, 'formRuntime', $formRuntime);
167
168        return $standaloneView;
169    }
170}
171