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