2010-05-18 11:48:56 +01:00
|
|
|
<?php
|
|
|
|
|
2010-07-09 09:05:26 +01:00
|
|
|
namespace Symfony\Bundle\FrameworkBundle\Controller;
|
2010-05-18 11:48:56 +01:00
|
|
|
|
2010-08-20 22:09:55 +01:00
|
|
|
use Symfony\Component\HttpKernel\Log\LoggerInterface;
|
|
|
|
use Symfony\Component\HttpKernel\Controller\ControllerResolver as BaseControllerResolver;
|
|
|
|
use Symfony\Component\HttpKernel\HttpKernelInterface;
|
|
|
|
use Symfony\Component\HttpFoundation\Request;
|
|
|
|
use Symfony\Component\EventDispatcher\Event;
|
|
|
|
use Symfony\Component\DependencyInjection\ContainerInterface;
|
2010-08-10 14:03:31 +01:00
|
|
|
use Symfony\Bundle\FrameworkBundle\Controller\ControllerNameConverter;
|
2010-08-28 08:39:04 +01:00
|
|
|
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
|
2010-05-18 11:48:56 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* This file is part of the Symfony framework.
|
|
|
|
*
|
|
|
|
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
|
|
|
|
*
|
|
|
|
* This source file is subject to the MIT license that is bundled
|
|
|
|
* with this source code in the file LICENSE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
2010-07-22 18:57:45 +01:00
|
|
|
* ControllerResolver.
|
2010-05-18 11:48:56 +01:00
|
|
|
*
|
2010-08-09 14:21:59 +01:00
|
|
|
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
|
2010-05-18 11:48:56 +01:00
|
|
|
*/
|
2010-08-09 14:21:59 +01:00
|
|
|
class ControllerResolver extends BaseControllerResolver
|
2010-05-18 11:48:56 +01:00
|
|
|
{
|
|
|
|
protected $container;
|
2010-08-10 14:03:31 +01:00
|
|
|
protected $converter;
|
2010-06-23 20:42:41 +01:00
|
|
|
protected $esiSupport;
|
2010-05-18 11:48:56 +01:00
|
|
|
|
2010-08-09 14:21:59 +01:00
|
|
|
/**
|
|
|
|
* Constructor.
|
|
|
|
*
|
2010-08-10 14:03:31 +01:00
|
|
|
* @param ContainerInterface $container A ContainerInterface instance
|
|
|
|
* @param ControllerNameConverter $converter A ControllerNameConverter instance
|
|
|
|
* @param LoggerInterface $logger A LoggerInterface instance
|
2010-08-09 14:21:59 +01:00
|
|
|
*/
|
2010-08-10 14:03:31 +01:00
|
|
|
public function __construct(ContainerInterface $container, ControllerNameConverter $converter, LoggerInterface $logger = null)
|
2010-05-18 11:48:56 +01:00
|
|
|
{
|
|
|
|
$this->container = $container;
|
2010-08-10 14:03:31 +01:00
|
|
|
$this->converter = $converter;
|
2010-06-27 17:28:29 +01:00
|
|
|
$this->esiSupport = $container->has('esi') && $container->getEsiService()->hasSurrogateEsiCapability($container->getRequestService());
|
2010-08-09 14:21:59 +01:00
|
|
|
|
|
|
|
parent::__construct($logger);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns a callable for the given controller.
|
|
|
|
*
|
|
|
|
* @param string $controller A Controller string
|
|
|
|
*
|
|
|
|
* @return mixed A PHP callable
|
|
|
|
*/
|
|
|
|
protected function createController($controller)
|
|
|
|
{
|
|
|
|
if (false === strpos($controller, '::')) {
|
2010-09-23 07:41:24 +01:00
|
|
|
$count = substr_count($controller, ':');
|
|
|
|
if (2 == $count) {
|
|
|
|
// controller in the a:b:c notation then
|
|
|
|
$controller = $this->converter->fromShortNotation($controller);
|
|
|
|
} elseif (1 == $count) {
|
|
|
|
// controller in the service:method notation
|
|
|
|
list($service, $method) = explode(':', $controller);
|
|
|
|
|
|
|
|
return array($this->container->get($service), $method);
|
|
|
|
} else {
|
|
|
|
throw new \LogicException(sprintf('Unable to parse the controller name "%s".', $controller));
|
|
|
|
}
|
2010-08-09 14:21:59 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
list($class, $method) = explode('::', $controller);
|
|
|
|
|
|
|
|
if (!class_exists($class)) {
|
|
|
|
throw new \InvalidArgumentException(sprintf('Class "%s" does not exist.', $class));
|
|
|
|
}
|
|
|
|
|
2010-08-22 21:35:44 +01:00
|
|
|
$controller = new $class();
|
2010-08-28 08:39:04 +01:00
|
|
|
if ($controller instanceof ContainerAwareInterface) {
|
2010-08-22 21:35:44 +01:00
|
|
|
$controller->setContainer($this->container);
|
|
|
|
}
|
|
|
|
|
|
|
|
return array($controller, $method);
|
2010-05-18 11:48:56 +01:00
|
|
|
}
|
|
|
|
|
2010-08-14 19:36:09 +01:00
|
|
|
/**
|
|
|
|
* Forwards the request to another controller.
|
|
|
|
*
|
|
|
|
* @param string $controller The controller name (a string like BlogBundle:Post:index)
|
2010-08-30 08:15:54 +01:00
|
|
|
* @param array $attributes An array of request attributes
|
|
|
|
* @param array $query An array of request query parameters
|
2010-08-14 19:36:09 +01:00
|
|
|
*
|
|
|
|
* @return Response A Response instance
|
|
|
|
*/
|
2010-08-30 08:15:54 +01:00
|
|
|
public function forward($controller, array $attributes = array(), array $query = array())
|
2010-08-14 19:36:09 +01:00
|
|
|
{
|
2010-08-30 08:15:54 +01:00
|
|
|
$attributes['_controller'] = $controller;
|
|
|
|
$subRequest = $this->container->getRequestService()->duplicate($query, null, $attributes);
|
2010-08-14 19:36:09 +01:00
|
|
|
|
|
|
|
return $this->container->get('kernel')->handle($subRequest, HttpKernelInterface::SUB_REQUEST);
|
|
|
|
}
|
|
|
|
|
2010-05-18 11:48:56 +01:00
|
|
|
/**
|
|
|
|
* Renders a Controller and returns the Response content.
|
|
|
|
*
|
2010-06-23 20:42:41 +01:00
|
|
|
* Note that this method generates an esi:include tag only when both the standalone
|
2010-08-20 22:09:55 +01:00
|
|
|
* option is set to true and the request has ESI capability (@see Symfony\Component\HttpKernel\Cache\ESI).
|
2010-06-23 20:42:41 +01:00
|
|
|
*
|
2010-05-18 12:05:03 +01:00
|
|
|
* Available options:
|
|
|
|
*
|
2010-08-30 08:15:54 +01:00
|
|
|
* * attributes: An array of request attributes (only when the first argument is a controller)
|
|
|
|
* * query: An array of request query parameters (only when the first argument is a controller)
|
2010-05-18 12:05:03 +01:00
|
|
|
* * ignore_errors: true to return an empty string in case of an error
|
2010-08-30 08:15:54 +01:00
|
|
|
* * alt: an alternative controller to execute in case of an error (can be a controller, a URI, or an array with the controller, the attributes, and the query arguments)
|
2010-06-23 20:42:41 +01:00
|
|
|
* * standalone: whether to generate an esi:include tag or not when ESI is supported
|
|
|
|
* * comment: a comment to add when returning an esi:include tag
|
2010-05-18 12:05:03 +01:00
|
|
|
*
|
2010-05-18 11:48:56 +01:00
|
|
|
* @param string $controller A controller name to execute (a string like BlogBundle:Post:index), or a relative URI
|
|
|
|
* @param array $options An array of options
|
|
|
|
*
|
|
|
|
* @return string The Response content
|
|
|
|
*/
|
|
|
|
public function render($controller, array $options = array())
|
|
|
|
{
|
2010-05-18 12:05:03 +01:00
|
|
|
$options = array_merge(array(
|
2010-08-30 08:15:54 +01:00
|
|
|
'attributes' => array(),
|
2010-05-18 12:05:03 +01:00
|
|
|
'query' => array(),
|
2010-08-24 13:35:23 +01:00
|
|
|
'ignore_errors' => !$this->container->getParameter('kernel.debug'),
|
2010-05-18 12:05:03 +01:00
|
|
|
'alt' => array(),
|
2010-06-23 20:42:41 +01:00
|
|
|
'standalone' => false,
|
|
|
|
'comment' => '',
|
2010-05-18 12:05:03 +01:00
|
|
|
), $options);
|
|
|
|
|
|
|
|
if (!is_array($options['alt'])) {
|
|
|
|
$options['alt'] = array($options['alt']);
|
|
|
|
}
|
|
|
|
|
2010-06-23 20:42:41 +01:00
|
|
|
if ($this->esiSupport && $options['standalone']) {
|
2010-08-30 08:15:54 +01:00
|
|
|
$uri = $this->generateInternalUri($controller, $options['attributes'], $options['query']);
|
2010-06-23 20:42:41 +01:00
|
|
|
|
|
|
|
$alt = '';
|
|
|
|
if ($options['alt']) {
|
|
|
|
$alt = $this->generateInternalUri($options['alt'][0], isset($options['alt'][1]) ? $options['alt'][1] : array(), isset($options['alt'][2]) ? $options['alt'][2] : array());
|
|
|
|
}
|
|
|
|
|
|
|
|
return $this->container->getEsiService()->renderTag($uri, $alt, $options['ignore_errors'], $options['comment']);
|
|
|
|
}
|
|
|
|
|
2010-05-18 11:48:56 +01:00
|
|
|
$request = $this->container->getRequestService();
|
|
|
|
|
|
|
|
// controller or URI?
|
|
|
|
if (0 === strpos($controller, '/')) {
|
|
|
|
$subRequest = Request::create($controller, 'get', array(), $request->cookies->all(), array(), $request->server->all());
|
2010-08-27 08:08:11 +01:00
|
|
|
$subRequest->setSession($request->getSession());
|
2010-05-18 11:48:56 +01:00
|
|
|
} else {
|
2010-08-30 08:15:54 +01:00
|
|
|
$options['attributes']['_controller'] = $controller;
|
|
|
|
$options['attributes']['_format'] = $request->getRequestFormat();
|
|
|
|
$subRequest = $request->duplicate($options['query'], null, $options['attributes']);
|
2010-05-18 11:48:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
2010-08-14 17:29:27 +01:00
|
|
|
$response = $this->container->getKernelService()->handle($subRequest, HttpKernelInterface::SUB_REQUEST, true);
|
|
|
|
|
|
|
|
if (200 != $response->getStatusCode()) {
|
|
|
|
throw new \RuntimeException(sprintf('Error when rendering "%s" (Status code is %s).', $request->getUri(), $response->getStatusCode()));
|
|
|
|
}
|
|
|
|
|
|
|
|
return $response->getContent();
|
2010-05-18 11:48:56 +01:00
|
|
|
} catch (\Exception $e) {
|
|
|
|
if ($options['alt']) {
|
|
|
|
$alt = $options['alt'];
|
|
|
|
unset($options['alt']);
|
2010-08-30 08:15:54 +01:00
|
|
|
$options['attributes'] = isset($alt[1]) ? $alt[1] : array();
|
2010-05-18 11:48:56 +01:00
|
|
|
$options['query'] = isset($alt[2]) ? $alt[2] : array();
|
|
|
|
|
|
|
|
return $this->render($alt[0], $options);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!$options['ignore_errors']) {
|
|
|
|
throw $e;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-06-23 20:42:41 +01:00
|
|
|
/**
|
|
|
|
* Generates an internal URI for a given controller.
|
|
|
|
*
|
|
|
|
* This method uses the "_internal" route, which should be available.
|
|
|
|
*
|
|
|
|
* @param string $controller A controller name to execute (a string like BlogBundle:Post:index), or a relative URI
|
2010-08-30 08:15:54 +01:00
|
|
|
* @param array $attributes An array of request attributes
|
|
|
|
* @param array $query An array of request query parameters
|
2010-06-23 20:42:41 +01:00
|
|
|
*
|
|
|
|
* @return string An internal URI
|
|
|
|
*/
|
2010-08-30 08:15:54 +01:00
|
|
|
public function generateInternalUri($controller, array $attributes = array(), array $query = array())
|
2010-06-23 20:42:41 +01:00
|
|
|
{
|
|
|
|
if (0 === strpos($controller, '/')) {
|
|
|
|
return $controller;
|
|
|
|
}
|
|
|
|
|
|
|
|
$uri = $this->container->getRouterService()->generate('_internal', array(
|
|
|
|
'controller' => $controller,
|
2010-08-30 08:15:54 +01:00
|
|
|
'path' => $attributes ? http_build_query($attributes) : 'none',
|
2010-06-23 20:42:41 +01:00
|
|
|
'_format' => $this->container->getRequestService()->getRequestFormat(),
|
|
|
|
), true);
|
|
|
|
|
|
|
|
if ($query) {
|
|
|
|
$uri = $uri.'?'.http_build_query($query);
|
|
|
|
}
|
|
|
|
|
|
|
|
return $uri;
|
|
|
|
}
|
2010-05-18 11:48:56 +01:00
|
|
|
}
|