use Symfony\Component\HttpFoundation\ParameterBag;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
*/
class RequestDataCollector extends DataCollector implements EventSubscriberInterface
{
+ /** @var \SplObjectStorage */
protected $controllers;
public function __construct()
// attributes are serialized and as they can be anything, they need to be converted to strings.
$attributes = array();
+ $route = '';
foreach ($request->attributes->all() as $key => $value) {
- if ('_route' === $key && is_object($value)) {
- $attributes[$key] = $this->varToString($value->getPath());
- } elseif ('_route_params' === $key) {
- // we need to keep route params as an array (see getRouteParams())
- foreach ($value as $k => $v) {
- $value[$k] = $this->varToString($v);
- }
- $attributes[$key] = $value;
+ if ('_route' === $key) {
+ $route = is_object($value) ? $value->getPath() : $value;
+ $attributes[$key] = $route;
} else {
- $attributes[$key] = $this->varToString($value);
+ $attributes[$key] = $value;
}
}
$sessionMetadata = array();
$sessionAttributes = array();
+ $session = null;
$flashes = array();
if ($request->hasSession()) {
$session = $request->getSession();
$statusCode = $response->getStatusCode();
$this->data = array(
+ 'method' => $request->getMethod(),
'format' => $request->getRequestFormat(),
'content' => $content,
'content_type' => $response->headers->get('Content-Type', 'text/html'),
'request_server' => $request->server->all(),
'request_cookies' => $request->cookies->all(),
'request_attributes' => $attributes,
+ 'route' => $route,
'response_headers' => $responseHeaders,
'session_metadata' => $sessionMetadata,
'session_attributes' => $sessionAttributes,
$value = array_map(function ($v) { return isset($v[0]) && !isset($v[1]) ? $v[0] : $v; }, $value);
}
if ('request_server' !== $key && 'request_cookies' !== $key) {
- $this->data[$key] = $value;
+ $this->data[$key] = array_map(array($this, 'cloneVar'), $value);
}
}
if (isset($this->controllers[$request])) {
- $controller = $this->controllers[$request];
- if (is_array($controller)) {
- try {
- $r = new \ReflectionMethod($controller[0], $controller[1]);
- $this->data['controller'] = array(
- 'class' => is_object($controller[0]) ? get_class($controller[0]) : $controller[0],
- 'method' => $controller[1],
- 'file' => $r->getFileName(),
- 'line' => $r->getStartLine(),
- );
- } catch (\ReflectionException $e) {
- if (is_callable($controller)) {
- // using __call or __callStatic
- $this->data['controller'] = array(
- 'class' => is_object($controller[0]) ? get_class($controller[0]) : $controller[0],
- 'method' => $controller[1],
- 'file' => 'n/a',
- 'line' => 'n/a',
- );
- }
- }
- } elseif ($controller instanceof \Closure) {
- $r = new \ReflectionFunction($controller);
- $this->data['controller'] = array(
- 'class' => $r->getName(),
- 'method' => null,
- 'file' => $r->getFileName(),
- 'line' => $r->getStartLine(),
- );
- } elseif (is_object($controller)) {
- $r = new \ReflectionClass($controller);
- $this->data['controller'] = array(
- 'class' => $r->getName(),
- 'method' => null,
- 'file' => $r->getFileName(),
- 'line' => $r->getStartLine(),
- );
- } else {
- $this->data['controller'] = (string) $controller ?: 'n/a';
- }
+ $this->data['controller'] = $this->parseController($this->controllers[$request]);
unset($this->controllers[$request]);
}
+
+ if (null !== $session && $session->isStarted()) {
+ if ($request->attributes->has('_redirected')) {
+ $this->data['redirect'] = $session->remove('sf_redirect');
+ }
+
+ if ($response->isRedirect()) {
+ $session->set('sf_redirect', array(
+ 'token' => $response->headers->get('x-debug-token'),
+ 'route' => $request->attributes->get('_route', 'n/a'),
+ 'method' => $request->getMethod(),
+ 'controller' => $this->parseController($request->attributes->get('_controller')),
+ 'status_code' => $statusCode,
+ 'status_text' => Response::$statusTexts[(int) $statusCode],
+ ));
+ }
+ }
+ }
+
+ public function getMethod()
+ {
+ return $this->data['method'];
}
public function getPathInfo()
return new ParameterBag($this->data['request_headers']);
}
- public function getRequestServer()
+ public function getRequestServer($raw = false)
{
- return new ParameterBag($this->data['request_server']);
+ return new ParameterBag($raw ? $this->data['request_server'] : array_map(array($this, 'cloneVar'), $this->data['request_server']));
}
- public function getRequestCookies()
+ public function getRequestCookies($raw = false)
{
- return new ParameterBag($this->data['request_cookies']);
+ return new ParameterBag($raw ? $this->data['request_cookies'] : array_map(array($this, 'cloneVar'), $this->data['request_cookies']));
}
public function getRequestAttributes()
*/
public function getRoute()
{
- return isset($this->data['request_attributes']['_route']) ? $this->data['request_attributes']['_route'] : '';
+ return $this->data['route'];
+ }
+
+ public function getIdentifier()
+ {
+ return $this->data['route'] ?: (is_array($this->data['controller']) ? $this->data['controller']['class'].'::'.$this->data['controller']['method'].'()' : $this->data['controller']);
}
/**
*/
public function getRouteParams()
{
- return isset($this->data['request_attributes']['_route_params']) ? $this->data['request_attributes']['_route_params'] : array();
+ if (!isset($this->data['request_attributes']['_route_params'])) {
+ return array();
+ }
+
+ $data = $this->data['request_attributes']['_route_params'];
+ $rawData = $data->getRawData();
+ if (!isset($rawData[1])) {
+ return array();
+ }
+
+ $params = array();
+ foreach ($rawData[1] as $k => $v) {
+ $params[$k] = $data->seek($k);
+ }
+
+ return $params;
}
/**
- * Gets the controller.
+ * Gets the parsed controller.
*
- * @return string The controller as a string
+ * @return array|string The controller as a string or array of data
+ * with keys 'class', 'method', 'file' and 'line'
*/
public function getController()
{
return $this->data['controller'];
}
+ /**
+ * Gets the previous request attributes.
+ *
+ * @return array|bool A legacy array of data from the previous redirection response
+ * or false otherwise
+ */
+ public function getRedirect()
+ {
+ return isset($this->data['redirect']) ? $this->data['redirect'] : false;
+ }
+
public function onKernelController(FilterControllerEvent $event)
{
$this->controllers[$event->getRequest()] = $event->getController();
}
+ public function onKernelResponse(FilterResponseEvent $event)
+ {
+ if (!$event->isMasterRequest() || !$event->getRequest()->hasSession() || !$event->getRequest()->getSession()->isStarted()) {
+ return;
+ }
+
+ if ($event->getRequest()->getSession()->has('sf_redirect')) {
+ $event->getRequest()->attributes->set('_redirected', true);
+ }
+ }
+
public static function getSubscribedEvents()
{
- return array(KernelEvents::CONTROLLER => 'onKernelController');
+ return array(
+ KernelEvents::CONTROLLER => 'onKernelController',
+ KernelEvents::RESPONSE => 'onKernelResponse',
+ );
}
/**
{
return 'request';
}
+
+ /**
+ * Parse a controller.
+ *
+ * @param mixed $controller The controller to parse
+ *
+ * @return array|string An array of controller data or a simple string
+ */
+ protected function parseController($controller)
+ {
+ if (is_string($controller) && false !== strpos($controller, '::')) {
+ $controller = explode('::', $controller);
+ }
+
+ if (is_array($controller)) {
+ try {
+ $r = new \ReflectionMethod($controller[0], $controller[1]);
+
+ return array(
+ 'class' => is_object($controller[0]) ? get_class($controller[0]) : $controller[0],
+ 'method' => $controller[1],
+ 'file' => $r->getFileName(),
+ 'line' => $r->getStartLine(),
+ );
+ } catch (\ReflectionException $e) {
+ if (is_callable($controller)) {
+ // using __call or __callStatic
+ return array(
+ 'class' => is_object($controller[0]) ? get_class($controller[0]) : $controller[0],
+ 'method' => $controller[1],
+ 'file' => 'n/a',
+ 'line' => 'n/a',
+ );
+ }
+ }
+ }
+
+ if ($controller instanceof \Closure) {
+ $r = new \ReflectionFunction($controller);
+
+ return array(
+ 'class' => $r->getName(),
+ 'method' => null,
+ 'file' => $r->getFileName(),
+ 'line' => $r->getStartLine(),
+ );
+ }
+
+ if (is_object($controller)) {
+ $r = new \ReflectionClass($controller);
+
+ return array(
+ 'class' => $r->getName(),
+ 'method' => null,
+ 'file' => $r->getFileName(),
+ 'line' => $r->getStartLine(),
+ );
+ }
+
+ return is_string($controller) ? $controller : 'n/a';
+ }
}