‪TYPO3CMS  11.5
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 
23 use Psr\Http\Message\ResponseInterface;
32 use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase;
33 
37 class ‪ActionControllerArgumentTest extends FunctionalTestCase
38 {
39  private string ‪$pluginName = 'Pi1';
40  private string ‪$extensionName = 'ActionControllerArgumentTest';
41  private ?string ‪$pluginNamespacePrefix = null;
42 
44  'typo3/sysext/extbase/Tests/Functional/Mvc/Controller/Fixture/Extension/action_controller_argument_test',
45  ];
46 
47  protected function ‪setUp(): void
48  {
49  parent::setUp();
50  $this->pluginNamespacePrefix = strtolower('tx_' . $this->extensionName . '_' . $this->pluginName);
51  ‪$GLOBALS['TYPO3_REQUEST'] = (new ‪ServerRequest())
52  ->withAttribute('applicationType', ‪SystemEnvironmentBuilder::REQUESTTYPE_BE);
53  }
54 
56  {
57  return [
58  // regular models
59  'preset model' => [
60  'inputPresetModel',
61  ['preset' => (new ‪Model())->setValue('preset')],
62  'validateModel',
63  [
64  'form/model/value' => 'preset',
65  'validationResults/model' => [[]],
66  ],
67  ],
68  'preset DTO' => [
69  'inputPresetDto',
70  ['preset' => (new ‪ModelDto())->setValue('preset')],
71  'validateDto',
72  [
73  'form/dto/value' => 'preset',
74  'validationResults/dto' => [[]],
75  ],
76  ],
77  ];
78  }
79 
89  public function ‪validationErrorReturnsToForwardedPreviousAction(string $forwardTargetAction, array $forwardTargetArguments, string $validateAction, array $expectations): void
90  {
91  // trigger action to forward to some `input*` action
92  $controller = $this->‪buildController();
93  $controller->declareForwardTargetAction($forwardTargetAction);
94  $controller->declareForwardTargetArguments($forwardTargetArguments);
95 
96  $inputRequest = $this->‪buildRequest('forward');
97  $inputResponse = $this->‪dispatch($controller, $inputRequest);
98 
99  $body = $inputResponse->getBody();
100  $body->rewind();
101  $inputDocument = $this->‪createDocument($body->getContents());
102  $parsedInputData = $this->‪parseDataFromResponseDocument($inputDocument);
103  self::assertNotEmpty($parsedInputData['form'] ?? null);
104  unset($inputRequest, $controller);
105 
106  // trigger `validate*` action with generated arguments from FormViewHelper (see template)
107  $controller = $this->‪buildController();
108  $validateRequest = $this->‪buildRequest($validateAction, $parsedInputData['form']);
109 
110  // dispatch request to `validate*` action
111  $validateResponse = $this->‪dispatch($controller, $validateRequest);
112  $body = $validateResponse->getBody();
113  $body->rewind();
114  $validateDocument = $this->‪createDocument($body->getContents());
115  $parsedValidateData = $this->‪parseDataFromResponseDocument($validateDocument);
116  foreach ($expectations ?? [] as $bodyPath => $bodyValue) {
117  self::assertSame($bodyValue, ‪ArrayUtility::getValueByPath($parsedValidateData, $bodyPath));
118  }
119  }
120 
121  private function ‪dispatch(‪ArgumentTestController $controller, ‪RequestInterface $request): ResponseInterface
122  {
123  while (!$request->isDispatched()) {
124  try {
125  $response = $controller->‪processRequest($request);
126  if ($response instanceof ‪ForwardResponse) {
128  $controller = $this->‪buildController();
129  return $controller->‪processRequest($request);
130  }
131  } catch (‪StopActionException $exception) {
132  // simulate Dispatcher::resolveController() using a new controller instance
133  $controller = $this->‪buildController();
134  }
135  }
136 
137  return $response;
138  }
139 
147  private function ‪parseDataFromResponseDocument(\DOMDocument $document): array
148  {
149  $results = [];
150  $xpath = new \DOMXPath($document);
151 
152  $elements = $xpath->query('//div[@id="validationResults"]');
153  if ($elements->count() !== 0) {
154  $results['validationResults'] = json_decode(
155  trim($elements->item(0)->textContent),
156  true
157  );
158  }
159 
160  $elements = $xpath->query('//input[@type="text" or @type="hidden"]');
161  foreach ($elements as $element) {
162  if (!$element instanceof \DOMElement) {
163  continue;
164  }
165  $results['form'][$element->getAttribute('name')] = $element->getAttribute('value');
166  }
167  if (!empty($results['form'])) {
168  $results['form'] = $this->‪inflateFormValues($results['form']);
169  }
170  return $results;
171  }
172 
180  private function ‪inflateFormValues(array $formValues): array
181  {
182  $inflatedFormValues = [];
183  $normalizedFormPaths = array_map(
184  function (string $formName) {
185  $formName = substr($formName, strlen($this->pluginNamespacePrefix));
186  $formName = str_replace('][', '/', trim($formName, '[]'));
187  return $formName;
188  },
189  array_keys($formValues)
190  );
191  $normalizedFormValues = array_combine($normalizedFormPaths, $formValues);
192  foreach ($normalizedFormValues as $formPath => $formValue) {
193  $inflatedFormValues = ‪ArrayUtility::setValueByPath($inflatedFormValues, $formPath, $formValue, '/');
194  }
195  return $inflatedFormValues;
196  }
197 
198  private function ‪createDocument(string $content): \DOMDocument
199  {
200  $document = new \DOMDocument();
201  $document->loadHTML(
202  $content,
203  LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD
204  | LIBXML_NOBLANKS | LIBXML_NOERROR | LIBXML_NONET | LIBXML_NOWARNING
205  );
206  $document->preserveWhiteSpace = false;
207  return $document;
208  }
209 
210  private function ‪buildRequest(string $actionName, array $arguments = null): ‪Request
211  {
212  $request = new ‪Request();
213  $request->setPluginName($this->pluginName);
214  $request->setControllerExtensionName($this->extensionName);
215  $request->setControllerName('ArgumentTest');
216  $request->setFormat('html');
217  $request->setControllerActionName($actionName);
218  if ($arguments !== null) {
219  $request->setArguments($arguments);
220  }
221  return $request;
222  }
223 
225  {
226  return $this->get(ArgumentTestController::class);
227  }
228 }
‪TYPO3\CMS\Extbase\Tests\Functional\Mvc\Controller\ActionControllerArgumentTest\$testExtensionsToLoad
‪$testExtensionsToLoad
Definition: ActionControllerArgumentTest.php:43
‪TYPO3\CMS\Extbase\Mvc\Exception\StopActionException
Definition: StopActionException.php:37
‪TYPO3\CMS\Extbase\Mvc\Dispatcher
Definition: Dispatcher.php:38
‪TYPO3\CMS\Extbase\Tests\Functional\Mvc\Controller
Definition: ActionControllerArgumentTest.php:18
‪TYPO3\CMS\Extbase\Tests\Functional\Mvc\Controller\ActionControllerArgumentTest
Definition: ActionControllerArgumentTest.php:38
‪TYPO3\CMS\Core\Core\SystemEnvironmentBuilder
Definition: SystemEnvironmentBuilder.php:41
‪TYPO3\CMS\Extbase\Tests\Functional\Mvc\Controller\ActionControllerArgumentTest\buildRequest
‪buildRequest(string $actionName, array $arguments=null)
Definition: ActionControllerArgumentTest.php:210
‪TYPO3\CMS\Extbase\Tests\Functional\Mvc\Controller\ActionControllerArgumentTest\$pluginName
‪string $pluginName
Definition: ActionControllerArgumentTest.php:39
‪TYPO3\CMS\Core\Core\SystemEnvironmentBuilder\REQUESTTYPE_BE
‪const REQUESTTYPE_BE
Definition: SystemEnvironmentBuilder.php:45
‪TYPO3\CMS\Extbase\Http\ForwardResponse
Definition: ForwardResponse.php:24
‪TYPO3\CMS\Extbase\Tests\Functional\Mvc\Controller\ActionControllerArgumentTest\$pluginNamespacePrefix
‪string $pluginNamespacePrefix
Definition: ActionControllerArgumentTest.php:41
‪ExtbaseTeam\ActionControllerArgumentTest\Domain\Model\ModelDto
Definition: ModelDto.php:24
‪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:198
‪TYPO3\CMS\Extbase\Mvc\Controller\ActionController\processRequest
‪ResponseInterface processRequest(RequestInterface $request)
Definition: ActionController.php:441
‪TYPO3\CMS\Extbase\Tests\Functional\Mvc\Controller\ActionControllerArgumentTest\validationErrorReturnsToForwardedPreviousActionDataProvider
‪validationErrorReturnsToForwardedPreviousActionDataProvider()
Definition: ActionControllerArgumentTest.php:55
‪TYPO3\CMS\Core\Http\ServerRequest
Definition: ServerRequest.php:37
‪TYPO3\CMS\Extbase\Mvc\Dispatcher\buildRequestFromCurrentRequestAndForwardResponse
‪static buildRequestFromCurrentRequestAndForwardResponse(Request $currentRequest, ForwardResponse $forwardResponse)
Definition: Dispatcher.php:147
‪ExtbaseTeam\ActionControllerArgumentTest\Domain\Model\Model
Definition: Model.php:26
‪TYPO3\CMS\Extbase\Tests\Functional\Mvc\Controller\ActionControllerArgumentTest\validationErrorReturnsToForwardedPreviousAction
‪validationErrorReturnsToForwardedPreviousAction(string $forwardTargetAction, array $forwardTargetArguments, string $validateAction, array $expectations)
Definition: ActionControllerArgumentTest.php:89
‪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\inflateFormValues
‪array inflateFormValues(array $formValues)
Definition: ActionControllerArgumentTest.php:180
‪TYPO3\CMS\Extbase\Mvc\RequestInterface
Definition: RequestInterface.php:27
‪TYPO3\CMS\Core\Utility\ArrayUtility
Definition: ArrayUtility.php:24
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Extbase\Tests\Functional\Mvc\Controller\ActionControllerArgumentTest\setUp
‪setUp()
Definition: ActionControllerArgumentTest.php:47
‪TYPO3\CMS\Extbase\Tests\Functional\Mvc\Controller\ActionControllerArgumentTest\$extensionName
‪string $extensionName
Definition: ActionControllerArgumentTest.php:40
‪ExtbaseTeam\ActionControllerArgumentTest\Controller\ArgumentTestController
Definition: ArgumentTestController.php:31
‪TYPO3\CMS\Extbase\Tests\Functional\Mvc\Controller\ActionControllerArgumentTest\parseDataFromResponseDocument
‪array parseDataFromResponseDocument(\DOMDocument $document)
Definition: ActionControllerArgumentTest.php:147
‪TYPO3\CMS\Extbase\Tests\Functional\Mvc\Controller\ActionControllerArgumentTest\buildController
‪buildController()
Definition: ActionControllerArgumentTest.php:224
‪TYPO3\CMS\Extbase\Mvc\Request
Definition: Request.php:39
‪TYPO3\CMS\Extbase\Tests\Functional\Mvc\Controller\ActionControllerArgumentTest\dispatch
‪dispatch(ArgumentTestController $controller, RequestInterface $request)
Definition: ActionControllerArgumentTest.php:121