‪TYPO3CMS  9.5
ActionControllerArgumentTest.php
Go to the documentation of this file.
1 <?php
2 declare(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 
28 use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase;
29 
33 class ‪ActionControllerArgumentTest extends FunctionalTestCase
34 {
35  private const ‪ENCRYPTION_KEY = '4408d27a916d51e624b69af3554f516dbab61037a9f7b9fd6f81b4d3bedeccb6';
36 
40  protected ‪$objectManager;
41 
46 
47  private ‪$pluginName;
48  private ‪$extensionName;
50 
51  protected function ‪setUp(): void
52  {
53  parent::setUp();
54 
55  $this->pluginName = 'Pi1';
56  $this->extensionName = 'Extbase\\Tests\\Functional\\Mvc\\Controller\\Fixture';
57  $this->pluginNamespacePrefix = strtolower('tx_' . $this->extensionName . '_' . $this->pluginName);
58  $this->objectManager = GeneralUtility::makeInstance(ObjectManager::class);
59  $this->objectContainer = $this->objectManager->get(Container::class);
60  ‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'] = ‪self::ENCRYPTION_KEY;
61  }
62 
63  protected function ‪tearDown(): void
64  {
65  unset($this->objectManager, $this->objectContainer);
66  unset($this->extensionName, $this->pluginName, $this->pluginNamespacePrefix);
67  unset(‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey']);
68  parent::tearDown();
69  }
70 
72  {
73  return [
74  // regular models
75  'preset model' => [
76  'inputPresetModel',
77  ['preset' => (new ‪Fixture\Domain\Model\Model())->setValue('preset')],
78  'validateModel',
79  [
80  'form/model/value' => 'preset',
81  'validationResults/model' => [[]],
82  ],
83  ],
84  'preset DTO' => [
85  'inputPresetDto',
86  ['preset' => (new ‪Fixture\Domain\Model\ModelDto())->setValue('preset')],
87  'validateDto',
88  [
89  'form/dto/value' => 'preset',
90  'validationResults/dto' => [[]],
91  ],
92  ],
93  ];
94  }
95 
105  public function ‪validationErrorReturnsToForwardedPreviousAction(string $forwardTargetAction, array $forwardTargetArguments, string $validateAction, array $expectations)
106  {
107  // trigger action to forward to some `input*` action
108  $controller = $this->‪buildController();
109  $controller->declareForwardTargetAction($forwardTargetAction);
110  $controller->declareForwardTargetArguments($forwardTargetArguments);
111 
112  $inputRequest = $this->‪buildRequest('forward');
113  $inputResponse = $this->‪buildResponse();
114  $this->‪dispatch($controller, $inputRequest, $inputResponse);
115 
116  $inputDocument = $this->‪createDocument($inputResponse->getContent());
117  $parsedInputData = $this->‪parseDataFromResponseDocument($inputDocument);
118  self::assertNotEmpty($parsedInputData['form'] ?? null);
119  unset($inputRequest, $controller);
120 
121  // trigger `validate*` action with generated arguments from FormViewHelper (see template)
122  $controller = $this->‪buildController();
123  $validateRequest = $this->‪buildRequest($validateAction, $parsedInputData['form']);
124  $validateResponse = $this->‪buildResponse();
125 
126  // dispatch request to `validate*` action
127  $this->‪dispatch($controller, $validateRequest, $validateResponse);
128 
129  $validateDocument = $this->‪createDocument($validateResponse->getContent());
130  $parsedValidateData = $this->‪parseDataFromResponseDocument($validateDocument);
131  foreach ($expectations ?? [] as $bodyPath => $bodyValue) {
132  self::assertSame($bodyValue, ‪ArrayUtility::getValueByPath($parsedValidateData, $bodyPath));
133  }
134  }
135 
136  private function ‪dispatch(‪ArgumentTestController $controller, ‪RequestInterface $request, ‪ResponseInterface $response): void
137  {
138  while (!$request->‪isDispatched()) {
139  try {
140  $controller->‪processRequest($request, $response);
141  } catch (‪StopActionException $exception) {
142  // simulate Dispatcher::resolveController() using a new controller instance
143  $controller = $this->‪buildController();
144  }
145  }
146  }
147 
155  private function ‪parseDataFromResponseDocument(\DOMDocument $document): array
156  {
157  $results = [];
158  $xpath = new \DOMXPath($document);
159 
160  $elements = $xpath->query('//div[@id="validationResults"]');
161  if ($elements->count() !== 0) {
162  $results['validationResults'] = json_decode(
163  trim($elements->item(0)->textContent),
164  true
165  );
166  }
167 
168  $elements = $xpath->query('//input[@type="text" or @type="hidden"]');
169  foreach ($elements as $element) {
170  if (!$element instanceof \DOMElement) {
171  continue;
172  }
173  $results['form'][$element->getAttribute('name')] = $element->getAttribute('value');
174  }
175  if (!empty($results['form'])) {
176  $results['form'] = $this->‪inflateFormValues($results['form']);
177  }
178  return $results;
179  }
180 
188  private function ‪inflateFormValues(array $formValues): array
189  {
190  $inflatedFormValues = [];
191  $normalizedFormPaths = array_map(
192  function (string $formName) {
193  $formName = substr($formName, strlen($this->pluginNamespacePrefix));
194  $formName = str_replace('][', '/', trim($formName, '[]'));
195  return $formName;
196  },
197  array_keys($formValues)
198  );
199  $normalizedFormValues = array_combine($normalizedFormPaths, $formValues);
200  foreach ($normalizedFormValues as $formPath => $formValue) {
201  $inflatedFormValues = ‪ArrayUtility::setValueByPath($inflatedFormValues, $formPath, $formValue, '/');
202  }
203  return $inflatedFormValues;
204  }
205 
206  private function ‪createDocument(string $content): \DOMDocument
207  {
208  $document = new \DOMDocument();
209  $document->loadHTML(
210  $content,
211  LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD
212  | LIBXML_NOBLANKS | LIBXML_NOERROR | LIBXML_NONET | LIBXML_NOWARNING
213  );
214  $document->preserveWhiteSpace = false;
215  return $document;
216  }
217 
218  private function ‪buildRequest(string $actionName, array $arguments = null): ‪Request
219  {
220  $request = $this->objectManager->get(Request::class);
221  $request->‪setPluginName($this->pluginName);
222  $request->setControllerExtensionName($this->extensionName);
223  $request->setControllerName('ArgumentTest');
224  $request->setMethod('GET');
225  $request->setFormat('html');
226  $request->setControllerActionName($actionName);
227  if ($arguments !== null) {
228  $request->setArguments($arguments);
229  }
230  return $request;
231  }
232 
233  private function ‪buildResponse(): ‪Response
234  {
235  return $this->objectManager->get(Response::class);
236  }
237 
239  {
240  return $this->objectManager->get(ArgumentTestController::class);
241  }
242 }
‪TYPO3\CMS\Extbase\Mvc\Controller\ActionController\processRequest
‪processRequest(\TYPO3\CMS\Extbase\Mvc\RequestInterface $request, \TYPO3\CMS\Extbase\Mvc\ResponseInterface $response)
Definition: ActionController.php:127
‪TYPO3\CMS\Extbase\Mvc\Exception\StopActionException
Definition: StopActionException.php:26
‪TYPO3\CMS\Extbase\Mvc\RequestInterface\isDispatched
‪bool isDispatched()
‪TYPO3\CMS\Extbase\Tests\Functional\Mvc\Controller\ActionControllerArgumentTest\tearDown
‪tearDown()
Definition: ActionControllerArgumentTest.php:61
‪TYPO3\CMS\Extbase\Object\Container\Container
Definition: Container.php:30
‪TYPO3\CMS\Extbase\Tests\Functional\Mvc\Controller
Definition: ActionControllerArgumentTest.php:3
‪TYPO3\CMS\Extbase\Mvc\ResponseInterface
Definition: ResponseInterface.php:21
‪TYPO3\CMS\Extbase\Tests\Functional\Mvc\Controller\ActionControllerArgumentTest
Definition: ActionControllerArgumentTest.php:34
‪TYPO3\CMS\Extbase\Tests\Functional\Mvc\Controller\ActionControllerArgumentTest\buildRequest
‪buildRequest(string $actionName, array $arguments=null)
Definition: ActionControllerArgumentTest.php:216
‪TYPO3\CMS\Extbase\Tests\Functional\Mvc\Controller\ActionControllerArgumentTest\ENCRYPTION_KEY
‪const ENCRYPTION_KEY
Definition: ActionControllerArgumentTest.php:35
‪TYPO3\CMS\Extbase\Tests\Functional\Mvc\Controller\ActionControllerArgumentTest\$pluginName
‪$pluginName
Definition: ActionControllerArgumentTest.php:45
‪TYPO3\CMS\Extbase\Tests\Functional\Mvc\Controller\ActionControllerArgumentTest\dispatch
‪dispatch(ArgumentTestController $controller, RequestInterface $request, ResponseInterface $response)
Definition: ActionControllerArgumentTest.php:134
‪TYPO3\CMS\Core\Utility\ArrayUtility\getValueByPath
‪static mixed getValueByPath(array $array, $path, $delimiter='/')
Definition: ArrayUtility.php:179
‪TYPO3\CMS\Extbase\Tests\Functional\Mvc\Controller\ActionControllerArgumentTest\createDocument
‪createDocument(string $content)
Definition: ActionControllerArgumentTest.php:204
‪TYPO3\CMS\Extbase\Tests\Functional\Mvc\Controller\Fixture\Controller\ArgumentTestController
Definition: ArgumentTestController.php:29
‪TYPO3\CMS\Extbase\Mvc\Web\Response
Definition: Response.php:25
‪TYPO3\CMS\Extbase\Tests\Functional\Mvc\Controller\ActionControllerArgumentTest\validationErrorReturnsToForwardedPreviousActionDataProvider
‪validationErrorReturnsToForwardedPreviousActionDataProvider()
Definition: ActionControllerArgumentTest.php:69
‪TYPO3\CMS\Extbase\Tests\Functional\Mvc\Controller\Fixture\Domain\Model\Model
Definition: Model.php:24
‪TYPO3\CMS\Extbase\Mvc\Web\Request
Definition: Request.php:21
‪TYPO3\CMS\Extbase\Tests\Functional\Mvc\Controller\ActionControllerArgumentTest\buildResponse
‪buildResponse()
Definition: ActionControllerArgumentTest.php:231
‪TYPO3\CMS\Extbase\Tests\Functional\Mvc\Controller\ActionControllerArgumentTest\validationErrorReturnsToForwardedPreviousAction
‪validationErrorReturnsToForwardedPreviousAction(string $forwardTargetAction, array $forwardTargetArguments, string $validateAction, array $expectations)
Definition: ActionControllerArgumentTest.php:103
‪TYPO3\CMS\Core\Utility\ArrayUtility\setValueByPath
‪static array setValueByPath(array $array, $path, $value, $delimiter='/')
Definition: ArrayUtility.php:271
‪TYPO3\CMS\Extbase\Tests\Functional\Mvc\Controller\ActionControllerArgumentTest\$objectManager
‪ObjectManager $objectManager
Definition: ActionControllerArgumentTest.php:39
‪TYPO3\CMS\Extbase\Tests\Functional\Mvc\Controller\ActionControllerArgumentTest\inflateFormValues
‪array inflateFormValues(array $formValues)
Definition: ActionControllerArgumentTest.php:186
‪TYPO3\CMS\Extbase\Mvc\RequestInterface
Definition: RequestInterface.php:21
‪TYPO3\CMS\Extbase\Tests\Functional\Mvc\Controller\ActionControllerArgumentTest\$extensionName
‪$extensionName
Definition: ActionControllerArgumentTest.php:46
‪TYPO3\CMS\Core\Utility\ArrayUtility
Definition: ArrayUtility.php:23
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Extbase\Tests\Functional\Mvc\Controller\ActionControllerArgumentTest\setUp
‪setUp()
Definition: ActionControllerArgumentTest.php:49
‪TYPO3\CMS\Extbase\Tests\Functional\Mvc\Controller\Fixture\Domain\Model\ModelDto
Definition: ModelDto.php:22
‪TYPO3\CMS\Extbase\Mvc\Request\setPluginName
‪setPluginName($pluginName=null)
Definition: Request.php:170
‪TYPO3\CMS\Extbase\Tests\Functional\Mvc\Controller\ActionControllerArgumentTest\$pluginNamespacePrefix
‪$pluginNamespacePrefix
Definition: ActionControllerArgumentTest.php:47
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:45
‪TYPO3\CMS\Extbase\Tests\Functional\Mvc\Controller\ActionControllerArgumentTest\parseDataFromResponseDocument
‪array parseDataFromResponseDocument(\DOMDocument $document)
Definition: ActionControllerArgumentTest.php:153
‪TYPO3\CMS\Extbase\Tests\Functional\Mvc\Controller\ActionControllerArgumentTest\buildController
‪buildController()
Definition: ActionControllerArgumentTest.php:236
‪TYPO3\CMS\Extbase\Object\ObjectManager
Definition: ObjectManager.php:25
‪TYPO3\CMS\Extbase\Tests\Functional\Mvc\Controller\ActionControllerArgumentTest\$objectContainer
‪Container $objectContainer
Definition: ActionControllerArgumentTest.php:43