/
githubmirror
/
symfony
Обзор
Документация
Войти
/
githubmirror
/
symfony
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
8.2
src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolver/UploadedFileValueResolverTest.php
537 строк
18 KB
Eyüp Can Akman
[HttpKernel] Set propertyPath on MapUploadedFile validation violations
07 мар 2026, 21:13
07 мар 2026, 21:13
a3e9a6f
Код
Авторство
О чём код?
<?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests\Controller\ArgumentResolver; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Component\HttpFoundation\File\UploadedFile; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Attribute\MapUploadedFile; use Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestPayloadValueResolver; use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata; use Symfony\Component\HttpKernel\Event\ControllerArgumentsEvent; use Symfony\Component\HttpKernel\Exception\HttpException; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\Serializer\Serializer; use Symfony\Component\Validator\Constraints as Assert; use Symfony\Component\Validator\Exception\ValidationFailedException; use Symfony\Component\Validator\ValidatorBuilder; class UploadedFileValueResolverTest extends TestCase { private const FIXTURES_BASE_PATH = __DIR__.'/../../Fixtures/Controller/ArgumentResolver/UploadedFile'; #[DataProvider('provideContext')] public function testDefaults(RequestPayloadValueResolver $resolver, Request $request) { $attribute = new MapUploadedFile(); $argument = new ArgumentMetadata( 'foo', UploadedFile::class, false, false, null, false, [$attribute::class => $attribute] ); $event = new ControllerArgumentsEvent( $this->createStub(HttpKernelInterface::class), static function () {}, $resolver->resolve($request, $argument), $request, HttpKernelInterface::MAIN_REQUEST ); $resolver->onKernelControllerArguments($event); /** @var UploadedFile $data */ $data = $event->getArguments()[0]; $this->assertInstanceOf(UploadedFile::class, $data); $this->assertSame('file-small.txt', $data->getFilename()); $this->assertSame(36, $data->getSize()); } #[DataProvider('provideContext')] public function testEmpty(RequestPayloadValueResolver $resolver, Request $request) { $attribute = new MapUploadedFile(); $argument = new ArgumentMetadata( 'qux', UploadedFile::class, false, false, null, false, [$attribute::class => $attribute] ); $event = new ControllerArgumentsEvent( $this->createStub(HttpKernelInterface::class), static function () {}, $resolver->resolve($request, $argument), $request, HttpKernelInterface::MAIN_REQUEST ); $this->expectException(HttpException::class); $resolver->onKernelControllerArguments($event); } public function testEmptyArrayUploadedFileArgument() { $resolver = new RequestPayloadValueResolver( new Serializer(), (new ValidatorBuilder())->getValidator() ); $request = Request::create( '/', 'POST', files: [ 'qux' => [], ], server: ['HTTP_CONTENT_TYPE' => 'multipart/form-data'] ); $attribute = new MapUploadedFile(); $argument = new ArgumentMetadata( 'qux', UploadedFile::class, false, false, null, false, [$attribute::class => $attribute] ); $event = new ControllerArgumentsEvent( $this->createStub(HttpKernelInterface::class), static function () {}, $resolver->resolve($request, $argument), $request, HttpKernelInterface::MAIN_REQUEST ); $this->expectException(HttpException::class); $resolver->onKernelControllerArguments($event); } #[DataProvider('provideContext')] public function testEmptyArrayArgument(RequestPayloadValueResolver $resolver, Request $request) { $attribute = new MapUploadedFile(); $argument = new ArgumentMetadata( 'qux', 'array', false, false, null, false, [$attribute::class => $attribute] ); $event = new ControllerArgumentsEvent( $this->createStub(HttpKernelInterface::class), static function () {}, $resolver->resolve($request, $argument), $request, HttpKernelInterface::MAIN_REQUEST ); $resolver->onKernelControllerArguments($event); $data = $event->getArguments()[0]; $this->assertSame([], $data); } #[DataProvider('provideContext')] public function testCustomName(RequestPayloadValueResolver $resolver, Request $request) { $attribute = new MapUploadedFile(name: 'bar'); $argument = new ArgumentMetadata( 'foo', UploadedFile::class, false, false, null, false, [$attribute::class => $attribute] ); $event = new ControllerArgumentsEvent( $this->createStub(HttpKernelInterface::class), static function () {}, $resolver->resolve($request, $argument), $request, HttpKernelInterface::MAIN_REQUEST ); $resolver->onKernelControllerArguments($event); /** @var UploadedFile $data */ $data = $event->getArguments()[0]; $this->assertInstanceOf(UploadedFile::class, $data); $this->assertSame('file-big.txt', $data->getFilename()); $this->assertSame(71, $data->getSize()); } #[DataProvider('provideContext')] public function testConstraintsWithoutViolation(RequestPayloadValueResolver $resolver, Request $request) { $attribute = new MapUploadedFile(constraints: new Assert\File(maxSize: 100)); $argument = new ArgumentMetadata( 'bar', UploadedFile::class, false, false, null, false, [$attribute::class => $attribute] ); $event = new ControllerArgumentsEvent( $this->createStub(HttpKernelInterface::class), static function () {}, $resolver->resolve($request, $argument), $request, HttpKernelInterface::MAIN_REQUEST ); $resolver->onKernelControllerArguments($event); /** @var UploadedFile $data */ $data = $event->getArguments()[0]; $this->assertInstanceOf(UploadedFile::class, $data); $this->assertSame('file-big.txt', $data->getFilename()); $this->assertSame(71, $data->getSize()); } #[DataProvider('provideContext')] public function testConstraintsWithViolation(RequestPayloadValueResolver $resolver, Request $request) { $attribute = new MapUploadedFile(constraints: new Assert\File(maxSize: 50)); $argument = new ArgumentMetadata( 'bar', UploadedFile::class, false, false, null, false, [$attribute::class => $attribute] ); $event = new ControllerArgumentsEvent( $this->createStub(HttpKernelInterface::class), static function () {}, $resolver->resolve($request, $argument), $request, HttpKernelInterface::MAIN_REQUEST ); $this->expectException(HttpException::class); $this->expectExceptionMessageMatches('/^The file is too large/'); $resolver->onKernelControllerArguments($event); } #[DataProvider('provideContext')] public function testConstraintsViolationHasArgumentNameAsPropertyPath(RequestPayloadValueResolver $resolver, Request $request) { $attribute = new MapUploadedFile(constraints: new Assert\File(maxSize: 50)); $argument = new ArgumentMetadata( 'bar', UploadedFile::class, false, false, null, false, [$attribute::class => $attribute] ); $event = new ControllerArgumentsEvent( $this->createStub(HttpKernelInterface::class), static function () {}, $resolver->resolve($request, $argument), $request, HttpKernelInterface::MAIN_REQUEST ); try { $resolver->onKernelControllerArguments($event); $this->fail(\sprintf('Expected "%s" to be thrown.', HttpException::class)); } catch (HttpException $e) { $validationFailedException = $e->getPrevious(); $this->assertInstanceOf(ValidationFailedException::class, $validationFailedException); $this->assertSame('bar', $validationFailedException->getViolations()[0]->getPropertyPath()); } } #[DataProvider('provideContext')] public function testMultipleFilesArray(RequestPayloadValueResolver $resolver, Request $request) { $attribute = new MapUploadedFile(); $argument = new ArgumentMetadata( 'baz', UploadedFile::class, false, false, null, false, [$attribute::class => $attribute] ); $event = new ControllerArgumentsEvent( $this->createStub(HttpKernelInterface::class), static function () {}, $resolver->resolve($request, $argument), $request, HttpKernelInterface::MAIN_REQUEST ); $resolver->onKernelControllerArguments($event); /** @var UploadedFile[] $data */ $data = $event->getArguments()[0]; $this->assertCount(2, $data); $this->assertSame('file-small.txt', $data[0]->getFilename()); $this->assertSame(36, $data[0]->getSize()); $this->assertSame('file-big.txt', $data[1]->getFilename()); $this->assertSame(71, $data[1]->getSize()); } #[DataProvider('provideContext')] public function testMultipleFilesArrayConstraints(RequestPayloadValueResolver $resolver, Request $request) { $attribute = new MapUploadedFile(constraints: new Assert\File(maxSize: 50)); $argument = new ArgumentMetadata( 'baz', UploadedFile::class, false, false, null, false, [$attribute::class => $attribute] ); $event = new ControllerArgumentsEvent( $this->createStub(HttpKernelInterface::class), static function () {}, $resolver->resolve($request, $argument), $request, HttpKernelInterface::MAIN_REQUEST ); $this->expectException(HttpException::class); $this->expectExceptionMessageMatches('/^The file is too large/'); $resolver->onKernelControllerArguments($event); } #[DataProvider('provideContext')] public function testSingleFileVariadic(RequestPayloadValueResolver $resolver, Request $request) { $attribute = new MapUploadedFile(); $argument = new ArgumentMetadata( 'foo', UploadedFile::class, true, false, null, false, [$attribute::class => $attribute] ); $event = new ControllerArgumentsEvent( $this->createStub(HttpKernelInterface::class), static function () {}, $resolver->resolve($request, $argument), $request, HttpKernelInterface::MAIN_REQUEST ); $resolver->onKernelControllerArguments($event); /** @var UploadedFile[] $data */ $data = $event->getArguments(); $this->assertCount(1, $data); $this->assertSame('file-small.txt', $data[0]->getFilename()); $this->assertSame(36, $data[0]->getSize()); } #[DataProvider('provideContext')] public function testMultipleFilesVariadic(RequestPayloadValueResolver $resolver, Request $request) { $attribute = new MapUploadedFile(); $argument = new ArgumentMetadata( 'baz', UploadedFile::class, true, false, null, false, [$attribute::class => $attribute] ); $event = new ControllerArgumentsEvent( $this->createStub(HttpKernelInterface::class), static function () {}, $resolver->resolve($request, $argument), $request, HttpKernelInterface::MAIN_REQUEST ); $resolver->onKernelControllerArguments($event); /** @var UploadedFile[] $data */ $data = $event->getArguments(); $this->assertCount(2, $data); $this->assertSame('file-small.txt', $data[0]->getFilename()); $this->assertSame(36, $data[0]->getSize()); $this->assertSame('file-big.txt', $data[1]->getFilename()); $this->assertSame(71, $data[1]->getSize()); } #[DataProvider('provideContext')] public function testMultipleFilesVariadicConstraints(RequestPayloadValueResolver $resolver, Request $request) { $attribute = new MapUploadedFile(constraints: new Assert\File(maxSize: 50)); $argument = new ArgumentMetadata( 'baz', UploadedFile::class, true, false, null, false, [$attribute::class => $attribute] ); $event = new ControllerArgumentsEvent( $this->createStub(HttpKernelInterface::class), static function () {}, $resolver->resolve($request, $argument), $request, HttpKernelInterface::MAIN_REQUEST ); $this->expectException(HttpException::class); $this->expectExceptionMessageMatches('/^The file is too large/'); $resolver->onKernelControllerArguments($event); } #[DataProvider('provideContext')] public function testShouldAllowEmptyWhenNullable(RequestPayloadValueResolver $resolver, Request $request) { $attribute = new MapUploadedFile(); $argument = new ArgumentMetadata( 'qux', UploadedFile::class, false, false, null, true, [$attribute::class => $attribute] ); /** @var HttpKernelInterface&MockObject $httpKernel */ $httpKernel = $this->createStub(HttpKernelInterface::class); $event = new ControllerArgumentsEvent( $httpKernel, static function () {}, $resolver->resolve($request, $argument), $request, HttpKernelInterface::MAIN_REQUEST ); $resolver->onKernelControllerArguments($event); $data = $event->getArguments()[0]; $this->assertNull($data); } #[DataProvider('provideContext')] public function testShouldAllowEmptyWhenNullableArray(RequestPayloadValueResolver $resolver, Request $request) { $attribute = new MapUploadedFile(); $argument = new ArgumentMetadata( 'qux', 'array', false, false, null, true, [$attribute::class => $attribute] ); /** @var HttpKernelInterface&MockObject $httpKernel */ $httpKernel = $this->createStub(HttpKernelInterface::class); $event = new ControllerArgumentsEvent( $httpKernel, static function () {}, $resolver->resolve($request, $argument), $request, HttpKernelInterface::MAIN_REQUEST ); $resolver->onKernelControllerArguments($event); $data = $event->getArguments()[0]; $this->assertNull($data); } #[DataProvider('provideContext')] public function testShouldAllowEmptyWhenHasDefaultValue(RequestPayloadValueResolver $resolver, Request $request) { $attribute = new MapUploadedFile(); $argument = new ArgumentMetadata( 'qux', UploadedFile::class, false, true, 'default-value', false, [$attribute::class => $attribute] ); /** @var HttpKernelInterface&MockObject $httpKernel */ $httpKernel = $this->createStub(HttpKernelInterface::class); $event = new ControllerArgumentsEvent( $httpKernel, static function () {}, $resolver->resolve($request, $argument), $request, HttpKernelInterface::MAIN_REQUEST ); $resolver->onKernelControllerArguments($event); $data = $event->getArguments()[0]; $this->assertSame('default-value', $data); } public static function provideContext(): iterable { $resolver = new RequestPayloadValueResolver( new Serializer(), (new ValidatorBuilder())->getValidator() ); $small = new UploadedFile( self::FIXTURES_BASE_PATH.'/file-small.txt', 'file-small.txt', 'text/plain', null, true ); $big = new UploadedFile( self::FIXTURES_BASE_PATH.'/file-big.txt', 'file-big.txt', 'text/plain', null, true ); $request = Request::create( '/', 'POST', files: [ 'foo' => $small, 'bar' => $big, 'baz' => [$small, $big], ], server: ['HTTP_CONTENT_TYPE' => 'multipart/form-data'] ); yield 'standard' => [$resolver, $request]; } }