PageRenderTime 52ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/src/Symfony/Component/Form/Tests/AbstractRequestHandlerTest.php

http://github.com/symfony/symfony
PHP | 417 lines | 281 code | 80 blank | 56 comment | 6 complexity | 2032164879590d6ffe98898da76eaf6a MD5 | raw file
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Component\Form\Tests;
  11. use PHPUnit\Framework\TestCase;
  12. use Symfony\Component\EventDispatcher\EventDispatcher;
  13. use Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper;
  14. use Symfony\Component\Form\Form;
  15. use Symfony\Component\Form\FormBuilder;
  16. use Symfony\Component\Form\FormError;
  17. use Symfony\Component\Form\FormFactory;
  18. use Symfony\Component\Form\Forms;
  19. use Symfony\Component\Form\RequestHandlerInterface;
  20. /**
  21. * @author Bernhard Schussek <bschussek@gmail.com>
  22. */
  23. abstract class AbstractRequestHandlerTest extends TestCase
  24. {
  25. /**
  26. * @var RequestHandlerInterface
  27. */
  28. protected $requestHandler;
  29. /**
  30. * @var FormFactory
  31. */
  32. protected $factory;
  33. protected $request;
  34. protected $serverParams;
  35. protected function setUp(): void
  36. {
  37. $this->serverParams = $this->getMockBuilder('Symfony\Component\Form\Util\ServerParams')->setMethods(['getNormalizedIniPostMaxSize', 'getContentLength'])->getMock();
  38. $this->requestHandler = $this->getRequestHandler();
  39. $this->factory = Forms::createFormFactoryBuilder()->getFormFactory();
  40. $this->request = null;
  41. }
  42. public function methodExceptGetProvider()
  43. {
  44. return [
  45. ['POST'],
  46. ['PUT'],
  47. ['DELETE'],
  48. ['PATCH'],
  49. ];
  50. }
  51. public function methodProvider()
  52. {
  53. return array_merge([
  54. ['GET'],
  55. ], $this->methodExceptGetProvider());
  56. }
  57. /**
  58. * @dataProvider methodProvider
  59. */
  60. public function testSubmitIfNameInRequest($method)
  61. {
  62. $form = $this->createForm('param1', $method);
  63. $this->setRequestData($method, [
  64. 'param1' => 'DATA',
  65. ]);
  66. $this->requestHandler->handleRequest($form, $this->request);
  67. $this->assertTrue($form->isSubmitted());
  68. $this->assertSame('DATA', $form->getData());
  69. }
  70. /**
  71. * @dataProvider methodProvider
  72. */
  73. public function testDoNotSubmitIfWrongRequestMethod($method)
  74. {
  75. $form = $this->createForm('param1', $method);
  76. $otherMethod = 'POST' === $method ? 'PUT' : 'POST';
  77. $this->setRequestData($otherMethod, [
  78. 'param1' => 'DATA',
  79. ]);
  80. $this->requestHandler->handleRequest($form, $this->request);
  81. $this->assertFalse($form->isSubmitted());
  82. }
  83. /**
  84. * @dataProvider methodExceptGetProvider
  85. */
  86. public function testDoNoSubmitSimpleFormIfNameNotInRequestAndNotGetRequest($method)
  87. {
  88. $form = $this->createForm('param1', $method, false);
  89. $this->setRequestData($method, [
  90. 'paramx' => [],
  91. ]);
  92. $this->requestHandler->handleRequest($form, $this->request);
  93. $this->assertFalse($form->isSubmitted());
  94. }
  95. /**
  96. * @dataProvider methodExceptGetProvider
  97. */
  98. public function testDoNotSubmitCompoundFormIfNameNotInRequestAndNotGetRequest($method)
  99. {
  100. $form = $this->createForm('param1', $method, true);
  101. $this->setRequestData($method, [
  102. 'paramx' => [],
  103. ]);
  104. $this->requestHandler->handleRequest($form, $this->request);
  105. $this->assertFalse($form->isSubmitted());
  106. }
  107. public function testDoNotSubmitIfNameNotInRequestAndGetRequest()
  108. {
  109. $form = $this->createForm('param1', 'GET');
  110. $this->setRequestData('GET', [
  111. 'paramx' => [],
  112. ]);
  113. $this->requestHandler->handleRequest($form, $this->request);
  114. $this->assertFalse($form->isSubmitted());
  115. }
  116. /**
  117. * @dataProvider methodProvider
  118. */
  119. public function testSubmitFormWithEmptyNameIfAtLeastOneFieldInRequest($method)
  120. {
  121. $form = $this->createForm('', $method, true);
  122. $form->add($this->createForm('param1'));
  123. $form->add($this->createForm('param2'));
  124. $this->setRequestData($method, $requestData = [
  125. 'param1' => 'submitted value',
  126. 'paramx' => 'submitted value',
  127. ]);
  128. $this->requestHandler->handleRequest($form, $this->request);
  129. $this->assertTrue($form->isSubmitted());
  130. $this->assertTrue($form->get('param1')->isSubmitted());
  131. $this->assertSame('submitted value', $form->get('param1')->getData());
  132. if ('PATCH' === $method) {
  133. $this->assertFalse($form->get('param2')->isSubmitted());
  134. } else {
  135. $this->assertTrue($form->get('param2')->isSubmitted());
  136. }
  137. $this->assertNull($form->get('param2')->getData());
  138. }
  139. /**
  140. * @dataProvider methodProvider
  141. */
  142. public function testDoNotSubmitFormWithEmptyNameIfNoFieldInRequest($method)
  143. {
  144. $form = $this->createForm('', $method, true);
  145. $form->add($this->createForm('param1'));
  146. $form->add($this->createForm('param2'));
  147. $this->setRequestData($method, [
  148. 'paramx' => 'submitted value',
  149. ]);
  150. $this->requestHandler->handleRequest($form, $this->request);
  151. $this->assertFalse($form->isSubmitted());
  152. }
  153. /**
  154. * @dataProvider methodExceptGetProvider
  155. */
  156. public function testMergeParamsAndFiles($method)
  157. {
  158. $form = $this->createForm('param1', $method, true);
  159. $form->add($this->createForm('field1'));
  160. $form->add($this->createBuilder('field2', false, ['allow_file_upload' => true])->getForm());
  161. $file = $this->getUploadedFile();
  162. $this->setRequestData($method, [
  163. 'param1' => [
  164. 'field1' => 'DATA',
  165. ],
  166. ], [
  167. 'param1' => [
  168. 'field2' => $file,
  169. ],
  170. ]);
  171. $this->requestHandler->handleRequest($form, $this->request);
  172. $this->assertTrue($form->isSubmitted());
  173. $this->assertSame('DATA', $form->get('field1')->getData());
  174. $this->assertSame($file, $form->get('field2')->getData());
  175. }
  176. /**
  177. * @dataProvider methodExceptGetProvider
  178. */
  179. public function testParamTakesPrecedenceOverFile($method)
  180. {
  181. $form = $this->createForm('param1', $method);
  182. $file = $this->getUploadedFile();
  183. $this->setRequestData($method, [
  184. 'param1' => 'DATA',
  185. ], [
  186. 'param1' => $file,
  187. ]);
  188. $this->requestHandler->handleRequest($form, $this->request);
  189. $this->assertTrue($form->isSubmitted());
  190. $this->assertSame('DATA', $form->getData());
  191. }
  192. /**
  193. * @dataProvider methodExceptGetProvider
  194. */
  195. public function testSubmitFileIfNoParam($method)
  196. {
  197. $form = $this->createBuilder('param1', false, ['allow_file_upload' => true])
  198. ->setMethod($method)
  199. ->getForm();
  200. $file = $this->getUploadedFile();
  201. $this->setRequestData($method, [
  202. 'param1' => null,
  203. ], [
  204. 'param1' => $file,
  205. ]);
  206. $this->requestHandler->handleRequest($form, $this->request);
  207. $this->assertTrue($form->isSubmitted());
  208. $this->assertSame($file, $form->getData());
  209. }
  210. /**
  211. * @dataProvider methodExceptGetProvider
  212. */
  213. public function testSubmitMultipleFiles($method)
  214. {
  215. $form = $this->createBuilder('param1', false, ['allow_file_upload' => true])
  216. ->setMethod($method)
  217. ->getForm();
  218. $file = $this->getUploadedFile();
  219. $this->setRequestData($method, [
  220. 'param1' => null,
  221. ], [
  222. 'param2' => $this->getUploadedFile('2'),
  223. 'param1' => $file,
  224. 'param3' => $this->getUploadedFile('3'),
  225. ]);
  226. $this->requestHandler->handleRequest($form, $this->request);
  227. $this->assertTrue($form->isSubmitted());
  228. $this->assertSame($file, $form->getData());
  229. }
  230. /**
  231. * @dataProvider methodExceptGetProvider
  232. */
  233. public function testSubmitFileWithNamelessForm($method)
  234. {
  235. $form = $this->createForm('', $method, true);
  236. $fileForm = $this->createBuilder('document', false, ['allow_file_upload' => true])->getForm();
  237. $form->add($fileForm);
  238. $file = $this->getUploadedFile();
  239. $this->setRequestData($method, [
  240. 'document' => null,
  241. ], [
  242. 'document' => $file,
  243. ]);
  244. $this->requestHandler->handleRequest($form, $this->request);
  245. $this->assertTrue($form->isSubmitted());
  246. $this->assertSame($file, $fileForm->getData());
  247. }
  248. /**
  249. * @dataProvider getPostMaxSizeFixtures
  250. */
  251. public function testAddFormErrorIfPostMaxSizeExceeded($contentLength, $iniMax, $shouldFail, array $errorParams = [])
  252. {
  253. $this->serverParams->expects($this->once())
  254. ->method('getContentLength')
  255. ->willReturn($contentLength);
  256. $this->serverParams->expects($this->any())
  257. ->method('getNormalizedIniPostMaxSize')
  258. ->willReturn($iniMax);
  259. $options = ['post_max_size_message' => 'Max {{ max }}!'];
  260. $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextType', null, $options);
  261. $this->setRequestData('POST', [], []);
  262. $this->requestHandler->handleRequest($form, $this->request);
  263. if ($shouldFail) {
  264. $error = new FormError($options['post_max_size_message'], null, $errorParams);
  265. $error->setOrigin($form);
  266. $this->assertEquals([$error], iterator_to_array($form->getErrors()));
  267. $this->assertTrue($form->isSubmitted());
  268. } else {
  269. $this->assertCount(0, $form->getErrors());
  270. $this->assertFalse($form->isSubmitted());
  271. }
  272. }
  273. public function getPostMaxSizeFixtures()
  274. {
  275. return [
  276. [pow(1024, 3) + 1, '1G', true, ['{{ max }}' => '1G']],
  277. [pow(1024, 3), '1G', false],
  278. [pow(1024, 2) + 1, '1M', true, ['{{ max }}' => '1M']],
  279. [pow(1024, 2), '1M', false],
  280. [1024 + 1, '1K', true, ['{{ max }}' => '1K']],
  281. [1024, '1K', false],
  282. [null, '1K', false],
  283. [1024, '', false],
  284. [1024, '0', false],
  285. ];
  286. }
  287. public function testUploadedFilesAreAccepted()
  288. {
  289. $this->assertTrue($this->requestHandler->isFileUpload($this->getUploadedFile()));
  290. }
  291. public function testInvalidFilesAreRejected()
  292. {
  293. $this->assertFalse($this->requestHandler->isFileUpload($this->getInvalidFile()));
  294. }
  295. /**
  296. * @dataProvider uploadFileErrorCodes
  297. */
  298. public function testFailedFileUploadIsTurnedIntoFormError($errorCode, $expectedErrorCode)
  299. {
  300. $this->assertSame($expectedErrorCode, $this->requestHandler->getUploadFileError($this->getFailedUploadedFile($errorCode)));
  301. }
  302. public function uploadFileErrorCodes()
  303. {
  304. return [
  305. 'no error' => [UPLOAD_ERR_OK, null],
  306. 'upload_max_filesize ini directive' => [UPLOAD_ERR_INI_SIZE, UPLOAD_ERR_INI_SIZE],
  307. 'MAX_FILE_SIZE from form' => [UPLOAD_ERR_FORM_SIZE, UPLOAD_ERR_FORM_SIZE],
  308. 'partially uploaded' => [UPLOAD_ERR_PARTIAL, UPLOAD_ERR_PARTIAL],
  309. 'no file upload' => [UPLOAD_ERR_NO_FILE, UPLOAD_ERR_NO_FILE],
  310. 'missing temporary directory' => [UPLOAD_ERR_NO_TMP_DIR, UPLOAD_ERR_NO_TMP_DIR],
  311. 'write failure' => [UPLOAD_ERR_CANT_WRITE, UPLOAD_ERR_CANT_WRITE],
  312. 'stopped by extension' => [UPLOAD_ERR_EXTENSION, UPLOAD_ERR_EXTENSION],
  313. ];
  314. }
  315. abstract protected function setRequestData($method, $data, $files = []);
  316. abstract protected function getRequestHandler();
  317. abstract protected function getUploadedFile($suffix = '');
  318. abstract protected function getInvalidFile();
  319. abstract protected function getFailedUploadedFile($errorCode);
  320. protected function createForm($name, $method = null, $compound = false)
  321. {
  322. $config = $this->createBuilder($name, $compound);
  323. if (null !== $method) {
  324. $config->setMethod($method);
  325. }
  326. return new Form($config);
  327. }
  328. protected function createBuilder($name, $compound = false, array $options = [])
  329. {
  330. $builder = new FormBuilder($name, null, new EventDispatcher(), $this->getMockBuilder('Symfony\Component\Form\FormFactoryInterface')->getMock(), $options);
  331. $builder->setCompound($compound);
  332. if ($compound) {
  333. $builder->setDataMapper(new PropertyPathMapper());
  334. }
  335. return $builder;
  336. }
  337. }