diff --git a/src/Symfony/Bridge/Doctrine/composer.json b/src/Symfony/Bridge/Doctrine/composer.json index 4ab0ae1120..10d2e61606 100644 --- a/src/Symfony/Bridge/Doctrine/composer.json +++ b/src/Symfony/Bridge/Doctrine/composer.json @@ -27,7 +27,7 @@ "symfony/stopwatch": "~3.4|~4.0", "symfony/config": "^4.2", "symfony/dependency-injection": "~3.4|~4.0", - "symfony/form": "~4.3", + "symfony/form": "^4.3.5", "symfony/http-kernel": "~3.4|~4.0", "symfony/messenger": "~4.3", "symfony/property-access": "~3.4|~4.0", diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerResolverTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerResolverTest.php index d73f576568..2290e34e5f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerResolverTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerResolverTest.php @@ -20,9 +20,9 @@ use Symfony\Component\DependencyInjection\Container; use Symfony\Component\DependencyInjection\ContainerAwareInterface; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\Tests\Controller\ContainerControllerResolverTest; +use Symfony\Component\HttpKernel\Test\Controller\ContainerControllerResolverTestCase; -class ControllerResolverTest extends ContainerControllerResolverTest +class ControllerResolverTest extends ContainerControllerResolverTestCase { public function testGetControllerOnContainerAware() { diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json index 2c198d2ca7..a4bdaa3bc3 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -23,7 +23,7 @@ "symfony/debug": "~4.0", "symfony/dependency-injection": "^4.3", "symfony/http-foundation": "^4.3", - "symfony/http-kernel": "^4.3.4", + "symfony/http-kernel": "^4.3.5", "symfony/polyfill-mbstring": "~1.0", "symfony/filesystem": "~3.4|~4.0", "symfony/finder": "~3.4|~4.0", diff --git a/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php b/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php index 0f7c8d712f..0c0b271191 100644 --- a/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php +++ b/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php @@ -145,18 +145,20 @@ class TwigExtension extends Extension } } - unset( - $config['form'], - $config['globals'], - $config['extensions'] - ); - if (isset($config['autoescape_service']) && isset($config['autoescape_service_method'])) { $config['autoescape'] = [new Reference($config['autoescape_service']), $config['autoescape_service_method']]; } - unset($config['autoescape_service'], $config['autoescape_service_method']); - $container->getDefinition('twig')->replaceArgument(1, $config); + $container->getDefinition('twig')->replaceArgument(1, array_intersect_key($config, [ + 'debug' => true, + 'charset' => true, + 'base_template_class' => true, + 'strict_variables' => true, + 'autoescape' => true, + 'cache' => true, + 'auto_reload' => true, + 'optimizations' => true, + ])); $container->registerForAutoconfiguration(\Twig_ExtensionInterface::class)->addTag('twig.extension'); $container->registerForAutoconfiguration(\Twig_LoaderInterface::class)->addTag('twig.loader'); diff --git a/src/Symfony/Component/Form/Test/FormPerformanceTestCase.php b/src/Symfony/Component/Form/Test/FormPerformanceTestCase.php index e11ce03357..859129ac56 100644 --- a/src/Symfony/Component/Form/Test/FormPerformanceTestCase.php +++ b/src/Symfony/Component/Form/Test/FormPerformanceTestCase.php @@ -11,8 +11,6 @@ namespace Symfony\Component\Form\Test; -use Symfony\Component\Form\Tests\VersionAwareTest; - /** * Base class for performance tests. * diff --git a/src/Symfony/Component/Form/Tests/VersionAwareTest.php b/src/Symfony/Component/Form/Test/VersionAwareTest.php similarity index 92% rename from src/Symfony/Component/Form/Tests/VersionAwareTest.php rename to src/Symfony/Component/Form/Test/VersionAwareTest.php index 2b8489a6a2..62d12c433d 100644 --- a/src/Symfony/Component/Form/Tests/VersionAwareTest.php +++ b/src/Symfony/Component/Form/Test/VersionAwareTest.php @@ -9,8 +9,11 @@ * file that was distributed with this source code. */ -namespace Symfony\Component\Form\Tests; +namespace Symfony\Component\Form\Test; +/** + * @internal + */ trait VersionAwareTest { protected static $supportedFeatureSetVersion = 304; diff --git a/src/Symfony/Component/Form/Tests/AbstractLayoutTest.php b/src/Symfony/Component/Form/Tests/AbstractLayoutTest.php index 438c25b259..cdc4dba018 100644 --- a/src/Symfony/Component/Form/Tests/AbstractLayoutTest.php +++ b/src/Symfony/Component/Form/Tests/AbstractLayoutTest.php @@ -17,6 +17,7 @@ use Symfony\Component\Form\Extension\Csrf\CsrfExtension; use Symfony\Component\Form\FormError; use Symfony\Component\Form\FormView; use Symfony\Component\Form\Test\FormIntegrationTestCase; +use Symfony\Component\Form\Test\VersionAwareTest; abstract class AbstractLayoutTest extends FormIntegrationTestCase { diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/BaseTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/BaseTypeTest.php index 20618bba39..f30da62729 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/BaseTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/BaseTypeTest.php @@ -12,7 +12,7 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; use Symfony\Component\Form\Test\TypeTestCase; -use Symfony\Component\Form\Tests\VersionAwareTest; +use Symfony\Component\Form\Test\VersionAwareTest; /** * @author Bernhard Schussek diff --git a/src/Symfony/Component/HttpFoundation/Tests/JsonResponseTest.php b/src/Symfony/Component/HttpFoundation/Tests/JsonResponseTest.php index 3d981cd329..aa8441799b 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/JsonResponseTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/JsonResponseTest.php @@ -43,7 +43,7 @@ class JsonResponseTest extends TestCase $this->assertSame('0', $response->getContent()); $response = new JsonResponse(0.1); - $this->assertEquals('0.1', $response->getContent()); + $this->assertEquals(0.1, $response->getContent()); $this->assertIsString($response->getContent()); $response = new JsonResponse(true); @@ -132,7 +132,7 @@ class JsonResponseTest extends TestCase $response = JsonResponse::create(0.1); $this->assertInstanceOf('Symfony\Component\HttpFoundation\JsonResponse', $response); - $this->assertEquals('0.1', $response->getContent()); + $this->assertEquals(0.1, $response->getContent()); $this->assertIsString($response->getContent()); $response = JsonResponse::create(true); diff --git a/src/Symfony/Component/HttpKernel/Test/Controller/ContainerControllerResolverTestCase.php b/src/Symfony/Component/HttpKernel/Test/Controller/ContainerControllerResolverTestCase.php new file mode 100644 index 0000000000..eae8f60b9b --- /dev/null +++ b/src/Symfony/Component/HttpKernel/Test/Controller/ContainerControllerResolverTestCase.php @@ -0,0 +1,263 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Test\Controller; + +use Psr\Container\ContainerInterface; +use Psr\Log\LoggerInterface; +use Symfony\Component\Debug\ErrorHandler; +use Symfony\Component\DependencyInjection\Container; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\Controller\ContainerControllerResolver; + +/** + * @internal + */ +class ContainerControllerResolverTestCase extends ControllerResolverTestCase +{ + public function testGetControllerServiceWithSingleColon() + { + $service = new ControllerTestService('foo'); + + $container = $this->createMockContainer(); + $container->expects($this->once()) + ->method('has') + ->with('foo') + ->willReturn(true); + $container->expects($this->once()) + ->method('get') + ->with('foo') + ->willReturn($service) + ; + + $resolver = $this->createControllerResolver(null, $container); + $request = Request::create('/'); + $request->attributes->set('_controller', 'foo:action'); + + $controller = $resolver->getController($request); + + $this->assertSame($service, $controller[0]); + $this->assertSame('action', $controller[1]); + } + + public function testGetControllerService() + { + $service = new ControllerTestService('foo'); + + $container = $this->createMockContainer(); + $container->expects($this->once()) + ->method('has') + ->with('foo') + ->willReturn(true); + $container->expects($this->once()) + ->method('get') + ->with('foo') + ->willReturn($service) + ; + + $resolver = $this->createControllerResolver(null, $container); + $request = Request::create('/'); + $request->attributes->set('_controller', 'foo::action'); + + $controller = $resolver->getController($request); + + $this->assertSame($service, $controller[0]); + $this->assertSame('action', $controller[1]); + } + + public function testGetControllerInvokableService() + { + $service = new InvokableControllerService('bar'); + + $container = $this->createMockContainer(); + $container->expects($this->once()) + ->method('has') + ->with('foo') + ->willReturn(true) + ; + $container->expects($this->once()) + ->method('get') + ->with('foo') + ->willReturn($service) + ; + + $resolver = $this->createControllerResolver(null, $container); + $request = Request::create('/'); + $request->attributes->set('_controller', 'foo'); + + $controller = $resolver->getController($request); + + $this->assertSame($service, $controller); + } + + public function testGetControllerInvokableServiceWithClassNameAsName() + { + $service = new InvokableControllerService('bar'); + + $container = $this->createMockContainer(); + $container->expects($this->once()) + ->method('has') + ->with(InvokableControllerService::class) + ->willReturn(true) + ; + $container->expects($this->once()) + ->method('get') + ->with(InvokableControllerService::class) + ->willReturn($service) + ; + + $resolver = $this->createControllerResolver(null, $container); + $request = Request::create('/'); + $request->attributes->set('_controller', InvokableControllerService::class); + + $controller = $resolver->getController($request); + + $this->assertSame($service, $controller); + } + + /** + * @dataProvider getControllers + */ + public function testInstantiateControllerWhenControllerStartsWithABackslash($controller) + { + $service = new ControllerTestService('foo'); + $class = ControllerTestService::class; + + $container = $this->createMockContainer(); + $container->expects($this->once())->method('has')->with($class)->willReturn(true); + $container->expects($this->once())->method('get')->with($class)->willReturn($service); + + $resolver = $this->createControllerResolver(null, $container); + $request = Request::create('/'); + $request->attributes->set('_controller', $controller); + + $controller = $resolver->getController($request); + + $this->assertInstanceOf(ControllerTestService::class, $controller[0]); + $this->assertSame('action', $controller[1]); + } + + public function getControllers() + { + return [ + ['\\'.ControllerTestService::class.'::action'], + ['\\'.ControllerTestService::class.':action'], + ]; + } + + public function testExceptionWhenUsingRemovedControllerServiceWithClassNameAsName() + { + $this->expectException('InvalidArgumentException'); + $this->expectExceptionMessage('Controller "Symfony\Component\HttpKernel\Test\Controller\ControllerTestService" cannot be fetched from the container because it is private. Did you forget to tag the service with "controller.service_arguments"?'); + $container = $this->getMockBuilder(Container::class)->getMock(); + $container->expects($this->once()) + ->method('has') + ->with(ControllerTestService::class) + ->willReturn(false) + ; + + $container->expects($this->atLeastOnce()) + ->method('getRemovedIds') + ->with() + ->willReturn([ControllerTestService::class => true]) + ; + + $resolver = $this->createControllerResolver(null, $container); + $request = Request::create('/'); + $request->attributes->set('_controller', [ControllerTestService::class, 'action']); + + $resolver->getController($request); + } + + public function testExceptionWhenUsingRemovedControllerService() + { + $this->expectException('InvalidArgumentException'); + $this->expectExceptionMessage('Controller "app.my_controller" cannot be fetched from the container because it is private. Did you forget to tag the service with "controller.service_arguments"?'); + $container = $this->getMockBuilder(Container::class)->getMock(); + $container->expects($this->once()) + ->method('has') + ->with('app.my_controller') + ->willReturn(false) + ; + + $container->expects($this->atLeastOnce()) + ->method('getRemovedIds') + ->with() + ->willReturn(['app.my_controller' => true]) + ; + + $resolver = $this->createControllerResolver(null, $container); + + $request = Request::create('/'); + $request->attributes->set('_controller', 'app.my_controller'); + $resolver->getController($request); + } + + public function getUndefinedControllers() + { + $tests = parent::getUndefinedControllers(); + $tests[0] = ['foo', \InvalidArgumentException::class, 'Controller "foo" does neither exist as service nor as class']; + $tests[1] = ['oof::bar', \InvalidArgumentException::class, 'Controller "oof" does neither exist as service nor as class']; + $tests[2] = [['oof', 'bar'], \InvalidArgumentException::class, 'Controller "oof" does neither exist as service nor as class']; + $tests[] = [ + [ControllerTestService::class, 'action'], + \InvalidArgumentException::class, + 'Controller "Symfony\Component\HttpKernel\Test\Controller\ControllerTestService" has required constructor arguments and does not exist in the container. Did you forget to define such a service?', + ]; + $tests[] = [ + ControllerTestService::class.'::action', + \InvalidArgumentException::class, 'Controller "Symfony\Component\HttpKernel\Test\Controller\ControllerTestService" has required constructor arguments and does not exist in the container. Did you forget to define such a service?', + ]; + $tests[] = [ + InvokableControllerService::class, + \InvalidArgumentException::class, + 'Controller "Symfony\Component\HttpKernel\Test\Controller\InvokableControllerService" has required constructor arguments and does not exist in the container. Did you forget to define such a service?', + ]; + + return $tests; + } + + protected function createControllerResolver(LoggerInterface $logger = null, ContainerInterface $container = null) + { + if (!$container) { + $container = $this->createMockContainer(); + } + + return new ContainerControllerResolver($container, $logger); + } + + protected function createMockContainer() + { + return $this->getMockBuilder(ContainerInterface::class)->getMock(); + } +} + +class InvokableControllerService +{ + public function __construct($bar) // mandatory argument to prevent automatic instantiation + { + } + + public function __invoke() + { + } +} + +class ControllerTestService +{ + public function __construct($foo) + { + } + + public function action() + { + } +} diff --git a/src/Symfony/Component/HttpKernel/Test/Controller/ControllerResolverTestCase.php b/src/Symfony/Component/HttpKernel/Test/Controller/ControllerResolverTestCase.php new file mode 100644 index 0000000000..5d03a62060 --- /dev/null +++ b/src/Symfony/Component/HttpKernel/Test/Controller/ControllerResolverTestCase.php @@ -0,0 +1,292 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Test\Controller; + +use PHPUnit\Framework\TestCase; +use Psr\Log\LoggerInterface; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\Controller\ControllerResolver; +use Symfony\Component\HttpKernel\Test\Fixtures\Controller\NullableController; +use Symfony\Component\HttpKernel\Test\Fixtures\Controller\VariadicController; + +/** + * @internal + */ +class ControllerResolverTestCase extends TestCase +{ + public function testGetControllerWithoutControllerParameter() + { + $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock(); + $logger->expects($this->once())->method('warning')->with('Unable to look for the controller as the "_controller" parameter is missing.'); + $resolver = $this->createControllerResolver($logger); + + $request = Request::create('/'); + $this->assertFalse($resolver->getController($request), '->getController() returns false when the request has no _controller attribute'); + } + + public function testGetControllerWithLambda() + { + $resolver = $this->createControllerResolver(); + + $request = Request::create('/'); + $request->attributes->set('_controller', $lambda = function () {}); + $controller = $resolver->getController($request); + $this->assertSame($lambda, $controller); + } + + public function testGetControllerWithObjectAndInvokeMethod() + { + $resolver = $this->createControllerResolver(); + $object = new InvokableController(); + + $request = Request::create('/'); + $request->attributes->set('_controller', $object); + $controller = $resolver->getController($request); + $this->assertSame($object, $controller); + } + + public function testGetControllerWithObjectAndMethod() + { + $resolver = $this->createControllerResolver(); + $object = new ControllerTest(); + + $request = Request::create('/'); + $request->attributes->set('_controller', [$object, 'publicAction']); + $controller = $resolver->getController($request); + $this->assertSame([$object, 'publicAction'], $controller); + } + + public function testGetControllerWithClassAndMethodAsArray() + { + $resolver = $this->createControllerResolver(); + + $request = Request::create('/'); + $request->attributes->set('_controller', [ControllerTest::class, 'publicAction']); + $controller = $resolver->getController($request); + $this->assertInstanceOf(ControllerTest::class, $controller[0]); + $this->assertSame('publicAction', $controller[1]); + } + + public function testGetControllerWithClassAndMethodAsString() + { + $resolver = $this->createControllerResolver(); + + $request = Request::create('/'); + $request->attributes->set('_controller', ControllerTest::class.'::publicAction'); + $controller = $resolver->getController($request); + $this->assertInstanceOf(ControllerTest::class, $controller[0]); + $this->assertSame('publicAction', $controller[1]); + } + + public function testGetControllerWithInvokableClass() + { + $resolver = $this->createControllerResolver(); + + $request = Request::create('/'); + $request->attributes->set('_controller', InvokableController::class); + $controller = $resolver->getController($request); + $this->assertInstanceOf(InvokableController::class, $controller); + } + + public function testGetControllerOnObjectWithoutInvokeMethod() + { + $this->expectException('InvalidArgumentException'); + $resolver = $this->createControllerResolver(); + + $request = Request::create('/'); + $request->attributes->set('_controller', new \stdClass()); + $resolver->getController($request); + } + + public function testGetControllerWithFunction() + { + $resolver = $this->createControllerResolver(); + + $request = Request::create('/'); + $request->attributes->set('_controller', 'Symfony\Component\HttpKernel\Test\Controller\some_controller_function'); + $controller = $resolver->getController($request); + $this->assertSame('Symfony\Component\HttpKernel\Test\Controller\some_controller_function', $controller); + } + + public function testGetControllerWithClosure() + { + $resolver = $this->createControllerResolver(); + + $closure = function () { + return 'test'; + }; + + $request = Request::create('/'); + $request->attributes->set('_controller', $closure); + $controller = $resolver->getController($request); + $this->assertInstanceOf(\Closure::class, $controller); + $this->assertSame('test', $controller()); + } + + /** + * @dataProvider getStaticControllers + */ + public function testGetControllerWithStaticController($staticController, $returnValue) + { + $resolver = $this->createControllerResolver(); + + $request = Request::create('/'); + $request->attributes->set('_controller', $staticController); + $controller = $resolver->getController($request); + $this->assertSame($staticController, $controller); + $this->assertSame($returnValue, $controller()); + } + + public function getStaticControllers() + { + return [ + [TestAbstractController::class.'::staticAction', 'foo'], + [[TestAbstractController::class, 'staticAction'], 'foo'], + [PrivateConstructorController::class.'::staticAction', 'bar'], + [[PrivateConstructorController::class, 'staticAction'], 'bar'], + ]; + } + + /** + * @dataProvider getUndefinedControllers + */ + public function testGetControllerWithUndefinedController($controller, $exceptionName = null, $exceptionMessage = null) + { + $resolver = $this->createControllerResolver(); + $this->expectException($exceptionName); + $this->expectExceptionMessage($exceptionMessage); + + $request = Request::create('/'); + $request->attributes->set('_controller', $controller); + $resolver->getController($request); + } + + public function getUndefinedControllers() + { + $controller = new ControllerTest(); + + return [ + ['foo', \Error::class, 'Class \'foo\' not found'], + ['oof::bar', \Error::class, 'Class \'oof\' not found'], + [['oof', 'bar'], \Error::class, 'Class \'oof\' not found'], + ['Symfony\Component\HttpKernel\Test\Controller\ControllerTest::staticsAction', \InvalidArgumentException::class, 'The controller for URI "/" is not callable. Expected method "staticsAction" on class "Symfony\Component\HttpKernel\Test\Controller\ControllerTest", did you mean "staticAction"?'], + ['Symfony\Component\HttpKernel\Test\Controller\ControllerTest::privateAction', \InvalidArgumentException::class, 'The controller for URI "/" is not callable. Method "privateAction" on class "Symfony\Component\HttpKernel\Test\Controller\ControllerTest" should be public and non-abstract'], + ['Symfony\Component\HttpKernel\Test\Controller\ControllerTest::protectedAction', \InvalidArgumentException::class, 'The controller for URI "/" is not callable. Method "protectedAction" on class "Symfony\Component\HttpKernel\Test\Controller\ControllerTest" should be public and non-abstract'], + ['Symfony\Component\HttpKernel\Test\Controller\ControllerTest::undefinedAction', \InvalidArgumentException::class, 'The controller for URI "/" is not callable. Expected method "undefinedAction" on class "Symfony\Component\HttpKernel\Test\Controller\ControllerTest". Available methods: "publicAction", "staticAction"'], + ['Symfony\Component\HttpKernel\Test\Controller\ControllerTest', \InvalidArgumentException::class, 'The controller for URI "/" is not callable. Controller class "Symfony\Component\HttpKernel\Test\Controller\ControllerTest" cannot be called without a method name. You need to implement "__invoke" or use one of the available methods: "publicAction", "staticAction".'], + [[$controller, 'staticsAction'], \InvalidArgumentException::class, 'The controller for URI "/" is not callable. Expected method "staticsAction" on class "Symfony\Component\HttpKernel\Test\Controller\ControllerTest", did you mean "staticAction"?'], + [[$controller, 'privateAction'], \InvalidArgumentException::class, 'The controller for URI "/" is not callable. Method "privateAction" on class "Symfony\Component\HttpKernel\Test\Controller\ControllerTest" should be public and non-abstract'], + [[$controller, 'protectedAction'], \InvalidArgumentException::class, 'The controller for URI "/" is not callable. Method "protectedAction" on class "Symfony\Component\HttpKernel\Test\Controller\ControllerTest" should be public and non-abstract'], + [[$controller, 'undefinedAction'], \InvalidArgumentException::class, 'The controller for URI "/" is not callable. Expected method "undefinedAction" on class "Symfony\Component\HttpKernel\Test\Controller\ControllerTest". Available methods: "publicAction", "staticAction"'], + [$controller, \InvalidArgumentException::class, 'The controller for URI "/" is not callable. Controller class "Symfony\Component\HttpKernel\Test\Controller\ControllerTest" cannot be called without a method name. You need to implement "__invoke" or use one of the available methods: "publicAction", "staticAction".'], + [['a' => 'foo', 'b' => 'bar'], \InvalidArgumentException::class, 'The controller for URI "/" is not callable. Invalid array callable, expected [controller, method].'], + ]; + } + + public function testCreateControllerCanReturnAnyCallable() + { + $mock = $this->getMockBuilder('Symfony\Component\HttpKernel\Controller\ControllerResolver')->setMethods(['createController'])->getMock(); + $mock->expects($this->once())->method('createController')->willReturn('Symfony\Component\HttpKernel\Test\Controller\some_controller_function'); + + $request = Request::create('/'); + $request->attributes->set('_controller', 'foobar'); + $mock->getController($request); + } + + protected function createControllerResolver(LoggerInterface $logger = null) + { + return new ControllerResolver($logger); + } + + public function __invoke($foo, $bar = null) + { + } + + public function controllerMethod1($foo) + { + } + + protected function controllerMethod2($foo, $bar = null) + { + } + + protected function controllerMethod3($foo, $bar, $foobar) + { + } + + protected static function controllerMethod4() + { + } + + protected function controllerMethod5(Request $request) + { + } +} + +function some_controller_function($foo, $foobar) +{ +} + +class ControllerTest +{ + public function __construct() + { + } + + public function __toString() + { + return ''; + } + + public function publicAction() + { + } + + private function privateAction() + { + } + + protected function protectedAction() + { + } + + public static function staticAction() + { + } +} + +class InvokableController +{ + public function __invoke($foo, $bar = null) + { + } +} + +abstract class TestAbstractController +{ + public static function staticAction() + { + return 'foo'; + } +} + +class PrivateConstructorController +{ + private function __construct() + { + } + + public static function staticAction() + { + return 'bar'; + } +} diff --git a/src/Symfony/Component/HttpKernel/Tests/Fixtures/Controller/NullableController.php b/src/Symfony/Component/HttpKernel/Test/Fixtures/Controller/NullableController.php similarity index 81% rename from src/Symfony/Component/HttpKernel/Tests/Fixtures/Controller/NullableController.php rename to src/Symfony/Component/HttpKernel/Test/Fixtures/Controller/NullableController.php index 9db4df7b4c..8cf95f2f54 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Fixtures/Controller/NullableController.php +++ b/src/Symfony/Component/HttpKernel/Test/Fixtures/Controller/NullableController.php @@ -9,8 +9,11 @@ * file that was distributed with this source code. */ -namespace Symfony\Component\HttpKernel\Tests\Fixtures\Controller; +namespace Symfony\Component\HttpKernel\Test\Fixtures\Controller; +/** + * @internal + */ class NullableController { public function action(?string $foo, ?\stdClass $bar, ?string $baz = 'value', $mandatory) diff --git a/src/Symfony/Component/HttpKernel/Tests/Fixtures/Controller/VariadicController.php b/src/Symfony/Component/HttpKernel/Test/Fixtures/Controller/VariadicController.php similarity index 78% rename from src/Symfony/Component/HttpKernel/Tests/Fixtures/Controller/VariadicController.php rename to src/Symfony/Component/HttpKernel/Test/Fixtures/Controller/VariadicController.php index c39812453b..0201f50759 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Fixtures/Controller/VariadicController.php +++ b/src/Symfony/Component/HttpKernel/Test/Fixtures/Controller/VariadicController.php @@ -9,8 +9,11 @@ * file that was distributed with this source code. */ -namespace Symfony\Component\HttpKernel\Tests\Fixtures\Controller; +namespace Symfony\Component\HttpKernel\Test\Fixtures\Controller; +/** + * @internal + */ class VariadicController { public function action($foo, ...$bar) diff --git a/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolverTest.php b/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolverTest.php index 8ee9108b1b..c44d7c6ec7 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolverTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolverTest.php @@ -20,10 +20,10 @@ use Symfony\Component\HttpKernel\Controller\ArgumentResolver; use Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestAttributeValueResolver; use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface; use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactory; +use Symfony\Component\HttpKernel\Test\Fixtures\Controller\NullableController; +use Symfony\Component\HttpKernel\Test\Fixtures\Controller\VariadicController; use Symfony\Component\HttpKernel\Tests\Fixtures\Controller\ExtendingRequest; use Symfony\Component\HttpKernel\Tests\Fixtures\Controller\ExtendingSession; -use Symfony\Component\HttpKernel\Tests\Fixtures\Controller\NullableController; -use Symfony\Component\HttpKernel\Tests\Fixtures\Controller\VariadicController; class ArgumentResolverTest extends TestCase { diff --git a/src/Symfony/Component/HttpKernel/Tests/Controller/ContainerControllerResolverTest.php b/src/Symfony/Component/HttpKernel/Tests/Controller/ContainerControllerResolverTest.php index 956adb9613..2396ffd87d 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Controller/ContainerControllerResolverTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Controller/ContainerControllerResolverTest.php @@ -11,249 +11,8 @@ namespace Symfony\Component\HttpKernel\Tests\Controller; -use Psr\Container\ContainerInterface; -use Psr\Log\LoggerInterface; -use Symfony\Component\DependencyInjection\Container; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\Controller\ContainerControllerResolver; +use Symfony\Component\HttpKernel\Test\Controller\ContainerControllerResolverTestCase; -class ContainerControllerResolverTest extends ControllerResolverTest +class ContainerControllerResolverTest extends ContainerControllerResolverTestCase { - public function testGetControllerServiceWithSingleColon() - { - $service = new ControllerTestService('foo'); - - $container = $this->createMockContainer(); - $container->expects($this->once()) - ->method('has') - ->with('foo') - ->willReturn(true); - $container->expects($this->once()) - ->method('get') - ->with('foo') - ->willReturn($service) - ; - - $resolver = $this->createControllerResolver(null, $container); - $request = Request::create('/'); - $request->attributes->set('_controller', 'foo:action'); - - $controller = $resolver->getController($request); - - $this->assertSame($service, $controller[0]); - $this->assertSame('action', $controller[1]); - } - - public function testGetControllerService() - { - $service = new ControllerTestService('foo'); - - $container = $this->createMockContainer(); - $container->expects($this->once()) - ->method('has') - ->with('foo') - ->willReturn(true); - $container->expects($this->once()) - ->method('get') - ->with('foo') - ->willReturn($service) - ; - - $resolver = $this->createControllerResolver(null, $container); - $request = Request::create('/'); - $request->attributes->set('_controller', 'foo::action'); - - $controller = $resolver->getController($request); - - $this->assertSame($service, $controller[0]); - $this->assertSame('action', $controller[1]); - } - - public function testGetControllerInvokableService() - { - $service = new InvokableControllerService('bar'); - - $container = $this->createMockContainer(); - $container->expects($this->once()) - ->method('has') - ->with('foo') - ->willReturn(true) - ; - $container->expects($this->once()) - ->method('get') - ->with('foo') - ->willReturn($service) - ; - - $resolver = $this->createControllerResolver(null, $container); - $request = Request::create('/'); - $request->attributes->set('_controller', 'foo'); - - $controller = $resolver->getController($request); - - $this->assertSame($service, $controller); - } - - public function testGetControllerInvokableServiceWithClassNameAsName() - { - $service = new InvokableControllerService('bar'); - - $container = $this->createMockContainer(); - $container->expects($this->once()) - ->method('has') - ->with(InvokableControllerService::class) - ->willReturn(true) - ; - $container->expects($this->once()) - ->method('get') - ->with(InvokableControllerService::class) - ->willReturn($service) - ; - - $resolver = $this->createControllerResolver(null, $container); - $request = Request::create('/'); - $request->attributes->set('_controller', InvokableControllerService::class); - - $controller = $resolver->getController($request); - - $this->assertSame($service, $controller); - } - - /** - * @dataProvider getControllers - */ - public function testInstantiateControllerWhenControllerStartsWithABackslash($controller) - { - $service = new ControllerTestService('foo'); - $class = ControllerTestService::class; - - $container = $this->createMockContainer(); - $container->expects($this->once())->method('has')->with($class)->willReturn(true); - $container->expects($this->once())->method('get')->with($class)->willReturn($service); - - $resolver = $this->createControllerResolver(null, $container); - $request = Request::create('/'); - $request->attributes->set('_controller', $controller); - - $controller = $resolver->getController($request); - - $this->assertInstanceOf(ControllerTestService::class, $controller[0]); - $this->assertSame('action', $controller[1]); - } - - public function getControllers() - { - return [ - ['\\'.ControllerTestService::class.'::action'], - ['\\'.ControllerTestService::class.':action'], - ]; - } - - public function testExceptionWhenUsingRemovedControllerServiceWithClassNameAsName() - { - $this->expectException('InvalidArgumentException'); - $this->expectExceptionMessage('Controller "Symfony\Component\HttpKernel\Tests\Controller\ControllerTestService" cannot be fetched from the container because it is private. Did you forget to tag the service with "controller.service_arguments"?'); - $container = $this->getMockBuilder(Container::class)->getMock(); - $container->expects($this->once()) - ->method('has') - ->with(ControllerTestService::class) - ->willReturn(false) - ; - - $container->expects($this->atLeastOnce()) - ->method('getRemovedIds') - ->with() - ->willReturn([ControllerTestService::class => true]) - ; - - $resolver = $this->createControllerResolver(null, $container); - $request = Request::create('/'); - $request->attributes->set('_controller', [ControllerTestService::class, 'action']); - - $resolver->getController($request); - } - - public function testExceptionWhenUsingRemovedControllerService() - { - $this->expectException('InvalidArgumentException'); - $this->expectExceptionMessage('Controller "app.my_controller" cannot be fetched from the container because it is private. Did you forget to tag the service with "controller.service_arguments"?'); - $container = $this->getMockBuilder(Container::class)->getMock(); - $container->expects($this->once()) - ->method('has') - ->with('app.my_controller') - ->willReturn(false) - ; - - $container->expects($this->atLeastOnce()) - ->method('getRemovedIds') - ->with() - ->willReturn(['app.my_controller' => true]) - ; - - $resolver = $this->createControllerResolver(null, $container); - - $request = Request::create('/'); - $request->attributes->set('_controller', 'app.my_controller'); - $resolver->getController($request); - } - - public function getUndefinedControllers() - { - $tests = parent::getUndefinedControllers(); - $tests[0] = ['foo', \InvalidArgumentException::class, 'Controller "foo" does neither exist as service nor as class']; - $tests[1] = ['oof::bar', \InvalidArgumentException::class, 'Controller "oof" does neither exist as service nor as class']; - $tests[2] = [['oof', 'bar'], \InvalidArgumentException::class, 'Controller "oof" does neither exist as service nor as class']; - $tests[] = [ - [ControllerTestService::class, 'action'], - \InvalidArgumentException::class, - 'Controller "Symfony\Component\HttpKernel\Tests\Controller\ControllerTestService" has required constructor arguments and does not exist in the container. Did you forget to define such a service?', - ]; - $tests[] = [ - ControllerTestService::class.'::action', - \InvalidArgumentException::class, 'Controller "Symfony\Component\HttpKernel\Tests\Controller\ControllerTestService" has required constructor arguments and does not exist in the container. Did you forget to define such a service?', - ]; - $tests[] = [ - InvokableControllerService::class, - \InvalidArgumentException::class, - 'Controller "Symfony\Component\HttpKernel\Tests\Controller\InvokableControllerService" has required constructor arguments and does not exist in the container. Did you forget to define such a service?', - ]; - - return $tests; - } - - protected function createControllerResolver(LoggerInterface $logger = null, ContainerInterface $container = null) - { - if (!$container) { - $container = $this->createMockContainer(); - } - - return new ContainerControllerResolver($container, $logger); - } - - protected function createMockContainer() - { - return $this->getMockBuilder(ContainerInterface::class)->getMock(); - } -} - -class InvokableControllerService -{ - public function __construct($bar) // mandatory argument to prevent automatic instantiation - { - } - - public function __invoke() - { - } -} - -class ControllerTestService -{ - public function __construct($foo) - { - } - - public function action() - { - } } diff --git a/src/Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.php b/src/Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.php index 77ce524fc6..90dc626008 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.php @@ -11,243 +11,8 @@ namespace Symfony\Component\HttpKernel\Tests\Controller; -use PHPUnit\Framework\TestCase; -use Psr\Log\LoggerInterface; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\Controller\ControllerResolver; +use Symfony\Component\HttpKernel\Test\Controller\ControllerResolverTestCase; -class ControllerResolverTest extends TestCase -{ - public function testGetControllerWithoutControllerParameter() - { - $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock(); - $logger->expects($this->once())->method('warning')->with('Unable to look for the controller as the "_controller" parameter is missing.'); - $resolver = $this->createControllerResolver($logger); - - $request = Request::create('/'); - $this->assertFalse($resolver->getController($request), '->getController() returns false when the request has no _controller attribute'); - } - - public function testGetControllerWithLambda() - { - $resolver = $this->createControllerResolver(); - - $request = Request::create('/'); - $request->attributes->set('_controller', $lambda = function () {}); - $controller = $resolver->getController($request); - $this->assertSame($lambda, $controller); - } - - public function testGetControllerWithObjectAndInvokeMethod() - { - $resolver = $this->createControllerResolver(); - $object = new InvokableController(); - - $request = Request::create('/'); - $request->attributes->set('_controller', $object); - $controller = $resolver->getController($request); - $this->assertSame($object, $controller); - } - - public function testGetControllerWithObjectAndMethod() - { - $resolver = $this->createControllerResolver(); - $object = new ControllerTest(); - - $request = Request::create('/'); - $request->attributes->set('_controller', [$object, 'publicAction']); - $controller = $resolver->getController($request); - $this->assertSame([$object, 'publicAction'], $controller); - } - - public function testGetControllerWithClassAndMethodAsArray() - { - $resolver = $this->createControllerResolver(); - - $request = Request::create('/'); - $request->attributes->set('_controller', [ControllerTest::class, 'publicAction']); - $controller = $resolver->getController($request); - $this->assertInstanceOf(ControllerTest::class, $controller[0]); - $this->assertSame('publicAction', $controller[1]); - } - - public function testGetControllerWithClassAndMethodAsString() - { - $resolver = $this->createControllerResolver(); - - $request = Request::create('/'); - $request->attributes->set('_controller', ControllerTest::class.'::publicAction'); - $controller = $resolver->getController($request); - $this->assertInstanceOf(ControllerTest::class, $controller[0]); - $this->assertSame('publicAction', $controller[1]); - } - - public function testGetControllerWithInvokableClass() - { - $resolver = $this->createControllerResolver(); - - $request = Request::create('/'); - $request->attributes->set('_controller', InvokableController::class); - $controller = $resolver->getController($request); - $this->assertInstanceOf(InvokableController::class, $controller); - } - - public function testGetControllerOnObjectWithoutInvokeMethod() - { - $this->expectException('InvalidArgumentException'); - $resolver = $this->createControllerResolver(); - - $request = Request::create('/'); - $request->attributes->set('_controller', new \stdClass()); - $resolver->getController($request); - } - - public function testGetControllerWithFunction() - { - $resolver = $this->createControllerResolver(); - - $request = Request::create('/'); - $request->attributes->set('_controller', 'Symfony\Component\HttpKernel\Tests\Controller\some_controller_function'); - $controller = $resolver->getController($request); - $this->assertSame('Symfony\Component\HttpKernel\Tests\Controller\some_controller_function', $controller); - } - - public function testGetControllerWithClosure() - { - $resolver = $this->createControllerResolver(); - - $closure = function () { - return 'test'; - }; - - $request = Request::create('/'); - $request->attributes->set('_controller', $closure); - $controller = $resolver->getController($request); - $this->assertInstanceOf(\Closure::class, $controller); - $this->assertSame('test', $controller()); - } - - /** - * @dataProvider getStaticControllers - */ - public function testGetControllerWithStaticController($staticController, $returnValue) - { - $resolver = $this->createControllerResolver(); - - $request = Request::create('/'); - $request->attributes->set('_controller', $staticController); - $controller = $resolver->getController($request); - $this->assertSame($staticController, $controller); - $this->assertSame($returnValue, $controller()); - } - - public function getStaticControllers() - { - return [ - [TestAbstractController::class.'::staticAction', 'foo'], - [[TestAbstractController::class, 'staticAction'], 'foo'], - [PrivateConstructorController::class.'::staticAction', 'bar'], - [[PrivateConstructorController::class, 'staticAction'], 'bar'], - ]; - } - - /** - * @dataProvider getUndefinedControllers - */ - public function testGetControllerWithUndefinedController($controller, $exceptionName = null, $exceptionMessage = null) - { - $resolver = $this->createControllerResolver(); - $this->expectException($exceptionName); - $this->expectExceptionMessage($exceptionMessage); - - $request = Request::create('/'); - $request->attributes->set('_controller', $controller); - $resolver->getController($request); - } - - public function getUndefinedControllers() - { - $controller = new ControllerTest(); - - return [ - ['foo', \Error::class, 'Class \'foo\' not found'], - ['oof::bar', \Error::class, 'Class \'oof\' not found'], - [['oof', 'bar'], \Error::class, 'Class \'oof\' not found'], - ['Symfony\Component\HttpKernel\Tests\Controller\ControllerTest::staticsAction', \InvalidArgumentException::class, 'The controller for URI "/" is not callable. Expected method "staticsAction" on class "Symfony\Component\HttpKernel\Tests\Controller\ControllerTest", did you mean "staticAction"?'], - ['Symfony\Component\HttpKernel\Tests\Controller\ControllerTest::privateAction', \InvalidArgumentException::class, 'The controller for URI "/" is not callable. Method "privateAction" on class "Symfony\Component\HttpKernel\Tests\Controller\ControllerTest" should be public and non-abstract'], - ['Symfony\Component\HttpKernel\Tests\Controller\ControllerTest::protectedAction', \InvalidArgumentException::class, 'The controller for URI "/" is not callable. Method "protectedAction" on class "Symfony\Component\HttpKernel\Tests\Controller\ControllerTest" should be public and non-abstract'], - ['Symfony\Component\HttpKernel\Tests\Controller\ControllerTest::undefinedAction', \InvalidArgumentException::class, 'The controller for URI "/" is not callable. Expected method "undefinedAction" on class "Symfony\Component\HttpKernel\Tests\Controller\ControllerTest". Available methods: "publicAction", "staticAction"'], - ['Symfony\Component\HttpKernel\Tests\Controller\ControllerTest', \InvalidArgumentException::class, 'The controller for URI "/" is not callable. Controller class "Symfony\Component\HttpKernel\Tests\Controller\ControllerTest" cannot be called without a method name. You need to implement "__invoke" or use one of the available methods: "publicAction", "staticAction".'], - [[$controller, 'staticsAction'], \InvalidArgumentException::class, 'The controller for URI "/" is not callable. Expected method "staticsAction" on class "Symfony\Component\HttpKernel\Tests\Controller\ControllerTest", did you mean "staticAction"?'], - [[$controller, 'privateAction'], \InvalidArgumentException::class, 'The controller for URI "/" is not callable. Method "privateAction" on class "Symfony\Component\HttpKernel\Tests\Controller\ControllerTest" should be public and non-abstract'], - [[$controller, 'protectedAction'], \InvalidArgumentException::class, 'The controller for URI "/" is not callable. Method "protectedAction" on class "Symfony\Component\HttpKernel\Tests\Controller\ControllerTest" should be public and non-abstract'], - [[$controller, 'undefinedAction'], \InvalidArgumentException::class, 'The controller for URI "/" is not callable. Expected method "undefinedAction" on class "Symfony\Component\HttpKernel\Tests\Controller\ControllerTest". Available methods: "publicAction", "staticAction"'], - [$controller, \InvalidArgumentException::class, 'The controller for URI "/" is not callable. Controller class "Symfony\Component\HttpKernel\Tests\Controller\ControllerTest" cannot be called without a method name. You need to implement "__invoke" or use one of the available methods: "publicAction", "staticAction".'], - [['a' => 'foo', 'b' => 'bar'], \InvalidArgumentException::class, 'The controller for URI "/" is not callable. Invalid array callable, expected [controller, method].'], - ]; - } - - protected function createControllerResolver(LoggerInterface $logger = null) - { - return new ControllerResolver($logger); - } -} - -function some_controller_function($foo, $foobar) +class ControllerResolverTest extends ControllerResolverTestCase { } - -class ControllerTest -{ - public function __construct() - { - } - - public function __toString() - { - return ''; - } - - public function publicAction() - { - } - - private function privateAction() - { - } - - protected function protectedAction() - { - } - - public static function staticAction() - { - } -} - -class InvokableController -{ - public function __invoke($foo, $bar = null) - { - } -} - -abstract class TestAbstractController -{ - public static function staticAction() - { - return 'foo'; - } -} - -class PrivateConstructorController -{ - private function __construct() - { - } - - public static function staticAction() - { - return 'bar'; - } -} diff --git a/src/Symfony/Component/HttpKernel/Tests/ControllerMetadata/ArgumentMetadataFactoryTest.php b/src/Symfony/Component/HttpKernel/Tests/ControllerMetadata/ArgumentMetadataFactoryTest.php index f77b6759af..d319b6fb1d 100644 --- a/src/Symfony/Component/HttpKernel/Tests/ControllerMetadata/ArgumentMetadataFactoryTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/ControllerMetadata/ArgumentMetadataFactoryTest.php @@ -15,9 +15,9 @@ use Fake\ImportedAndFake; use PHPUnit\Framework\TestCase; use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata; use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactory; +use Symfony\Component\HttpKernel\Test\Fixtures\Controller\NullableController; +use Symfony\Component\HttpKernel\Test\Fixtures\Controller\VariadicController; use Symfony\Component\HttpKernel\Tests\Fixtures\Controller\BasicTypesController; -use Symfony\Component\HttpKernel\Tests\Fixtures\Controller\NullableController; -use Symfony\Component\HttpKernel\Tests\Fixtures\Controller\VariadicController; class ArgumentMetadataFactoryTest extends TestCase {