diff --git a/src/Symfony/Bundle/FrameworkBundle/Controller/InternalController.php b/src/Symfony/Bundle/FrameworkBundle/Controller/InternalController.php index 641deb7683..ce674b190c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Controller/InternalController.php +++ b/src/Symfony/Bundle/FrameworkBundle/Controller/InternalController.php @@ -31,6 +31,35 @@ class InternalController extends ContainerAware */ public function indexAction($path, $controller) { + // safeguard + if (!is_string($controller)) { + throw new \RuntimeException('A Controller must be a string.'); + } + + // check that the controller looks like a controller + if (false === strpos($controller, '::')) { + $count = substr_count($controller, ':'); + if (2 == $count) { + // the convention already enforces the Controller suffix + } elseif (1 == $count) { + // controller in the service:method notation + list($service, $method) = explode(':', $controller, 2); + $class = get_class($this->container->get($service)); + + if (!preg_match('/Controller$/', $class)) { + throw new \RuntimeException('A Controller class name must end with Controller.'); + } + } else { + throw new \LogicException('Unable to parse the Controller name.'); + } + } else { + list($class, $method) = explode('::', $controller, 2); + + if (!preg_match('/Controller$/', $class)) { + throw new \RuntimeException('A Controller class name must end with Controller.'); + } + } + $request = $this->container->get('request'); $attributes = $request->attributes; diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/InternalControllerTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/InternalControllerTest.php new file mode 100644 index 0000000000..2b35ff1424 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/InternalControllerTest.php @@ -0,0 +1,52 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Tests\Controller; + +use Symfony\Bundle\FrameworkBundle\Controller\InternalController; +use Symfony\Bundle\FrameworkBundle\Tests\TestCase; +use Symfony\Component\HttpFoundation\Request; + +class InternalControllerTest extends TestCase +{ + /** + * @expectedException \RuntimeException + * @expectedExceptionMessage A Controller class name must end with Controller. + */ + public function testWithAClassMethodController() + { + $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface'); + + $controller = new InternalController(); + $controller->setContainer($container); + + $controller->indexAction('/', 'Symfony\Component\HttpFoundation\Request::getPathInfo'); + } + + /** + * @expectedException \RuntimeException + * @expectedExceptionMessage A Controller class name must end with Controller. + */ + public function testWithAServiceController() + { + $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface'); + $container + ->expects($this->once()) + ->method('get') + ->will($this->returnValue(new Request())) + ; + + $controller = new InternalController(); + $controller->setContainer($container); + + $controller->indexAction('/', 'service:method'); + } +}