Chris@0
|
1 <?php
|
Chris@0
|
2
|
Chris@0
|
3 /*
|
Chris@0
|
4 * This file is part of the Symfony package.
|
Chris@0
|
5 *
|
Chris@0
|
6 * (c) Fabien Potencier <fabien@symfony.com>
|
Chris@0
|
7 *
|
Chris@0
|
8 * For the full copyright and license information, please view the LICENSE
|
Chris@0
|
9 * file that was distributed with this source code.
|
Chris@0
|
10 */
|
Chris@0
|
11
|
Chris@0
|
12 namespace Symfony\Component\HttpKernel\DataCollector;
|
Chris@0
|
13
|
Chris@17
|
14 use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
Chris@14
|
15 use Symfony\Component\HttpFoundation\Cookie;
|
Chris@0
|
16 use Symfony\Component\HttpFoundation\ParameterBag;
|
Chris@0
|
17 use Symfony\Component\HttpFoundation\Request;
|
Chris@0
|
18 use Symfony\Component\HttpFoundation\Response;
|
Chris@17
|
19 use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
|
Chris@0
|
20 use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
|
Chris@0
|
21 use Symfony\Component\HttpKernel\KernelEvents;
|
Chris@0
|
22
|
Chris@0
|
23 /**
|
Chris@0
|
24 * @author Fabien Potencier <fabien@symfony.com>
|
Chris@0
|
25 */
|
Chris@14
|
26 class RequestDataCollector extends DataCollector implements EventSubscriberInterface, LateDataCollectorInterface
|
Chris@0
|
27 {
|
Chris@0
|
28 protected $controllers;
|
Chris@0
|
29
|
Chris@0
|
30 public function __construct()
|
Chris@0
|
31 {
|
Chris@0
|
32 $this->controllers = new \SplObjectStorage();
|
Chris@0
|
33 }
|
Chris@0
|
34
|
Chris@0
|
35 /**
|
Chris@0
|
36 * {@inheritdoc}
|
Chris@0
|
37 */
|
Chris@0
|
38 public function collect(Request $request, Response $response, \Exception $exception = null)
|
Chris@0
|
39 {
|
Chris@0
|
40 // attributes are serialized and as they can be anything, they need to be converted to strings.
|
Chris@17
|
41 $attributes = [];
|
Chris@0
|
42 $route = '';
|
Chris@0
|
43 foreach ($request->attributes->all() as $key => $value) {
|
Chris@0
|
44 if ('_route' === $key) {
|
Chris@17
|
45 $route = \is_object($value) ? $value->getPath() : $value;
|
Chris@0
|
46 $attributes[$key] = $route;
|
Chris@0
|
47 } else {
|
Chris@0
|
48 $attributes[$key] = $value;
|
Chris@0
|
49 }
|
Chris@0
|
50 }
|
Chris@0
|
51
|
Chris@0
|
52 $content = null;
|
Chris@0
|
53 try {
|
Chris@0
|
54 $content = $request->getContent();
|
Chris@0
|
55 } catch (\LogicException $e) {
|
Chris@0
|
56 // the user already got the request content as a resource
|
Chris@0
|
57 $content = false;
|
Chris@0
|
58 }
|
Chris@0
|
59
|
Chris@17
|
60 $sessionMetadata = [];
|
Chris@17
|
61 $sessionAttributes = [];
|
Chris@0
|
62 $session = null;
|
Chris@17
|
63 $flashes = [];
|
Chris@0
|
64 if ($request->hasSession()) {
|
Chris@0
|
65 $session = $request->getSession();
|
Chris@0
|
66 if ($session->isStarted()) {
|
Chris@0
|
67 $sessionMetadata['Created'] = date(DATE_RFC822, $session->getMetadataBag()->getCreated());
|
Chris@0
|
68 $sessionMetadata['Last used'] = date(DATE_RFC822, $session->getMetadataBag()->getLastUsed());
|
Chris@0
|
69 $sessionMetadata['Lifetime'] = $session->getMetadataBag()->getLifetime();
|
Chris@0
|
70 $sessionAttributes = $session->all();
|
Chris@0
|
71 $flashes = $session->getFlashBag()->peekAll();
|
Chris@0
|
72 }
|
Chris@0
|
73 }
|
Chris@0
|
74
|
Chris@0
|
75 $statusCode = $response->getStatusCode();
|
Chris@0
|
76
|
Chris@17
|
77 $responseCookies = [];
|
Chris@14
|
78 foreach ($response->headers->getCookies() as $cookie) {
|
Chris@14
|
79 $responseCookies[$cookie->getName()] = $cookie;
|
Chris@14
|
80 }
|
Chris@14
|
81
|
Chris@17
|
82 $this->data = [
|
Chris@0
|
83 'method' => $request->getMethod(),
|
Chris@0
|
84 'format' => $request->getRequestFormat(),
|
Chris@0
|
85 'content' => $content,
|
Chris@0
|
86 'content_type' => $response->headers->get('Content-Type', 'text/html'),
|
Chris@0
|
87 'status_text' => isset(Response::$statusTexts[$statusCode]) ? Response::$statusTexts[$statusCode] : '',
|
Chris@0
|
88 'status_code' => $statusCode,
|
Chris@0
|
89 'request_query' => $request->query->all(),
|
Chris@0
|
90 'request_request' => $request->request->all(),
|
Chris@0
|
91 'request_headers' => $request->headers->all(),
|
Chris@0
|
92 'request_server' => $request->server->all(),
|
Chris@0
|
93 'request_cookies' => $request->cookies->all(),
|
Chris@0
|
94 'request_attributes' => $attributes,
|
Chris@0
|
95 'route' => $route,
|
Chris@14
|
96 'response_headers' => $response->headers->all(),
|
Chris@14
|
97 'response_cookies' => $responseCookies,
|
Chris@0
|
98 'session_metadata' => $sessionMetadata,
|
Chris@0
|
99 'session_attributes' => $sessionAttributes,
|
Chris@0
|
100 'flashes' => $flashes,
|
Chris@0
|
101 'path_info' => $request->getPathInfo(),
|
Chris@0
|
102 'controller' => 'n/a',
|
Chris@0
|
103 'locale' => $request->getLocale(),
|
Chris@17
|
104 ];
|
Chris@0
|
105
|
Chris@0
|
106 if (isset($this->data['request_headers']['php-auth-pw'])) {
|
Chris@0
|
107 $this->data['request_headers']['php-auth-pw'] = '******';
|
Chris@0
|
108 }
|
Chris@0
|
109
|
Chris@0
|
110 if (isset($this->data['request_server']['PHP_AUTH_PW'])) {
|
Chris@0
|
111 $this->data['request_server']['PHP_AUTH_PW'] = '******';
|
Chris@0
|
112 }
|
Chris@0
|
113
|
Chris@0
|
114 if (isset($this->data['request_request']['_password'])) {
|
Chris@0
|
115 $this->data['request_request']['_password'] = '******';
|
Chris@0
|
116 }
|
Chris@0
|
117
|
Chris@0
|
118 foreach ($this->data as $key => $value) {
|
Chris@17
|
119 if (!\is_array($value)) {
|
Chris@0
|
120 continue;
|
Chris@0
|
121 }
|
Chris@0
|
122 if ('request_headers' === $key || 'response_headers' === $key) {
|
Chris@14
|
123 $this->data[$key] = array_map(function ($v) { return isset($v[0]) && !isset($v[1]) ? $v[0] : $v; }, $value);
|
Chris@0
|
124 }
|
Chris@0
|
125 }
|
Chris@0
|
126
|
Chris@0
|
127 if (isset($this->controllers[$request])) {
|
Chris@0
|
128 $this->data['controller'] = $this->parseController($this->controllers[$request]);
|
Chris@0
|
129 unset($this->controllers[$request]);
|
Chris@0
|
130 }
|
Chris@0
|
131
|
Chris@14
|
132 if ($request->attributes->has('_redirected') && $redirectCookie = $request->cookies->get('sf_redirect')) {
|
Chris@14
|
133 $this->data['redirect'] = json_decode($redirectCookie, true);
|
Chris@0
|
134
|
Chris@14
|
135 $response->headers->clearCookie('sf_redirect');
|
Chris@14
|
136 }
|
Chris@14
|
137
|
Chris@14
|
138 if ($response->isRedirect()) {
|
Chris@14
|
139 $response->headers->setCookie(new Cookie(
|
Chris@14
|
140 'sf_redirect',
|
Chris@17
|
141 json_encode([
|
Chris@0
|
142 'token' => $response->headers->get('x-debug-token'),
|
Chris@0
|
143 'route' => $request->attributes->get('_route', 'n/a'),
|
Chris@0
|
144 'method' => $request->getMethod(),
|
Chris@0
|
145 'controller' => $this->parseController($request->attributes->get('_controller')),
|
Chris@0
|
146 'status_code' => $statusCode,
|
Chris@0
|
147 'status_text' => Response::$statusTexts[(int) $statusCode],
|
Chris@17
|
148 ])
|
Chris@14
|
149 ));
|
Chris@0
|
150 }
|
Chris@14
|
151
|
Chris@17
|
152 $this->data['identifier'] = $this->data['route'] ?: (\is_array($this->data['controller']) ? $this->data['controller']['class'].'::'.$this->data['controller']['method'].'()' : $this->data['controller']);
|
Chris@14
|
153 }
|
Chris@14
|
154
|
Chris@14
|
155 public function lateCollect()
|
Chris@14
|
156 {
|
Chris@14
|
157 $this->data = $this->cloneVar($this->data);
|
Chris@14
|
158 }
|
Chris@14
|
159
|
Chris@14
|
160 public function reset()
|
Chris@14
|
161 {
|
Chris@17
|
162 $this->data = [];
|
Chris@14
|
163 $this->controllers = new \SplObjectStorage();
|
Chris@0
|
164 }
|
Chris@0
|
165
|
Chris@0
|
166 public function getMethod()
|
Chris@0
|
167 {
|
Chris@0
|
168 return $this->data['method'];
|
Chris@0
|
169 }
|
Chris@0
|
170
|
Chris@0
|
171 public function getPathInfo()
|
Chris@0
|
172 {
|
Chris@0
|
173 return $this->data['path_info'];
|
Chris@0
|
174 }
|
Chris@0
|
175
|
Chris@0
|
176 public function getRequestRequest()
|
Chris@0
|
177 {
|
Chris@14
|
178 return new ParameterBag($this->data['request_request']->getValue());
|
Chris@0
|
179 }
|
Chris@0
|
180
|
Chris@0
|
181 public function getRequestQuery()
|
Chris@0
|
182 {
|
Chris@14
|
183 return new ParameterBag($this->data['request_query']->getValue());
|
Chris@0
|
184 }
|
Chris@0
|
185
|
Chris@0
|
186 public function getRequestHeaders()
|
Chris@0
|
187 {
|
Chris@14
|
188 return new ParameterBag($this->data['request_headers']->getValue());
|
Chris@0
|
189 }
|
Chris@0
|
190
|
Chris@0
|
191 public function getRequestServer($raw = false)
|
Chris@0
|
192 {
|
Chris@14
|
193 return new ParameterBag($this->data['request_server']->getValue($raw));
|
Chris@0
|
194 }
|
Chris@0
|
195
|
Chris@0
|
196 public function getRequestCookies($raw = false)
|
Chris@0
|
197 {
|
Chris@14
|
198 return new ParameterBag($this->data['request_cookies']->getValue($raw));
|
Chris@0
|
199 }
|
Chris@0
|
200
|
Chris@0
|
201 public function getRequestAttributes()
|
Chris@0
|
202 {
|
Chris@14
|
203 return new ParameterBag($this->data['request_attributes']->getValue());
|
Chris@0
|
204 }
|
Chris@0
|
205
|
Chris@0
|
206 public function getResponseHeaders()
|
Chris@0
|
207 {
|
Chris@14
|
208 return new ParameterBag($this->data['response_headers']->getValue());
|
Chris@14
|
209 }
|
Chris@14
|
210
|
Chris@14
|
211 public function getResponseCookies()
|
Chris@14
|
212 {
|
Chris@14
|
213 return new ParameterBag($this->data['response_cookies']->getValue());
|
Chris@0
|
214 }
|
Chris@0
|
215
|
Chris@0
|
216 public function getSessionMetadata()
|
Chris@0
|
217 {
|
Chris@14
|
218 return $this->data['session_metadata']->getValue();
|
Chris@0
|
219 }
|
Chris@0
|
220
|
Chris@0
|
221 public function getSessionAttributes()
|
Chris@0
|
222 {
|
Chris@14
|
223 return $this->data['session_attributes']->getValue();
|
Chris@0
|
224 }
|
Chris@0
|
225
|
Chris@0
|
226 public function getFlashes()
|
Chris@0
|
227 {
|
Chris@14
|
228 return $this->data['flashes']->getValue();
|
Chris@0
|
229 }
|
Chris@0
|
230
|
Chris@0
|
231 public function getContent()
|
Chris@0
|
232 {
|
Chris@0
|
233 return $this->data['content'];
|
Chris@0
|
234 }
|
Chris@0
|
235
|
Chris@0
|
236 public function getContentType()
|
Chris@0
|
237 {
|
Chris@0
|
238 return $this->data['content_type'];
|
Chris@0
|
239 }
|
Chris@0
|
240
|
Chris@0
|
241 public function getStatusText()
|
Chris@0
|
242 {
|
Chris@0
|
243 return $this->data['status_text'];
|
Chris@0
|
244 }
|
Chris@0
|
245
|
Chris@0
|
246 public function getStatusCode()
|
Chris@0
|
247 {
|
Chris@0
|
248 return $this->data['status_code'];
|
Chris@0
|
249 }
|
Chris@0
|
250
|
Chris@0
|
251 public function getFormat()
|
Chris@0
|
252 {
|
Chris@0
|
253 return $this->data['format'];
|
Chris@0
|
254 }
|
Chris@0
|
255
|
Chris@0
|
256 public function getLocale()
|
Chris@0
|
257 {
|
Chris@0
|
258 return $this->data['locale'];
|
Chris@0
|
259 }
|
Chris@0
|
260
|
Chris@0
|
261 /**
|
Chris@0
|
262 * Gets the route name.
|
Chris@0
|
263 *
|
Chris@0
|
264 * The _route request attributes is automatically set by the Router Matcher.
|
Chris@0
|
265 *
|
Chris@0
|
266 * @return string The route
|
Chris@0
|
267 */
|
Chris@0
|
268 public function getRoute()
|
Chris@0
|
269 {
|
Chris@0
|
270 return $this->data['route'];
|
Chris@0
|
271 }
|
Chris@0
|
272
|
Chris@0
|
273 public function getIdentifier()
|
Chris@0
|
274 {
|
Chris@14
|
275 return $this->data['identifier'];
|
Chris@0
|
276 }
|
Chris@0
|
277
|
Chris@0
|
278 /**
|
Chris@0
|
279 * Gets the route parameters.
|
Chris@0
|
280 *
|
Chris@0
|
281 * The _route_params request attributes is automatically set by the RouterListener.
|
Chris@0
|
282 *
|
Chris@0
|
283 * @return array The parameters
|
Chris@0
|
284 */
|
Chris@0
|
285 public function getRouteParams()
|
Chris@0
|
286 {
|
Chris@17
|
287 return isset($this->data['request_attributes']['_route_params']) ? $this->data['request_attributes']['_route_params']->getValue() : [];
|
Chris@0
|
288 }
|
Chris@0
|
289
|
Chris@0
|
290 /**
|
Chris@0
|
291 * Gets the parsed controller.
|
Chris@0
|
292 *
|
Chris@0
|
293 * @return array|string The controller as a string or array of data
|
Chris@0
|
294 * with keys 'class', 'method', 'file' and 'line'
|
Chris@0
|
295 */
|
Chris@0
|
296 public function getController()
|
Chris@0
|
297 {
|
Chris@0
|
298 return $this->data['controller'];
|
Chris@0
|
299 }
|
Chris@0
|
300
|
Chris@0
|
301 /**
|
Chris@0
|
302 * Gets the previous request attributes.
|
Chris@0
|
303 *
|
Chris@0
|
304 * @return array|bool A legacy array of data from the previous redirection response
|
Chris@0
|
305 * or false otherwise
|
Chris@0
|
306 */
|
Chris@0
|
307 public function getRedirect()
|
Chris@0
|
308 {
|
Chris@0
|
309 return isset($this->data['redirect']) ? $this->data['redirect'] : false;
|
Chris@0
|
310 }
|
Chris@0
|
311
|
Chris@0
|
312 public function onKernelController(FilterControllerEvent $event)
|
Chris@0
|
313 {
|
Chris@0
|
314 $this->controllers[$event->getRequest()] = $event->getController();
|
Chris@0
|
315 }
|
Chris@0
|
316
|
Chris@0
|
317 public function onKernelResponse(FilterResponseEvent $event)
|
Chris@0
|
318 {
|
Chris@14
|
319 if (!$event->isMasterRequest()) {
|
Chris@0
|
320 return;
|
Chris@0
|
321 }
|
Chris@0
|
322
|
Chris@14
|
323 if ($event->getRequest()->cookies->has('sf_redirect')) {
|
Chris@0
|
324 $event->getRequest()->attributes->set('_redirected', true);
|
Chris@0
|
325 }
|
Chris@0
|
326 }
|
Chris@0
|
327
|
Chris@0
|
328 public static function getSubscribedEvents()
|
Chris@0
|
329 {
|
Chris@17
|
330 return [
|
Chris@0
|
331 KernelEvents::CONTROLLER => 'onKernelController',
|
Chris@0
|
332 KernelEvents::RESPONSE => 'onKernelResponse',
|
Chris@17
|
333 ];
|
Chris@0
|
334 }
|
Chris@0
|
335
|
Chris@0
|
336 /**
|
Chris@0
|
337 * {@inheritdoc}
|
Chris@0
|
338 */
|
Chris@0
|
339 public function getName()
|
Chris@0
|
340 {
|
Chris@0
|
341 return 'request';
|
Chris@0
|
342 }
|
Chris@0
|
343
|
Chris@0
|
344 /**
|
Chris@0
|
345 * Parse a controller.
|
Chris@0
|
346 *
|
Chris@0
|
347 * @param mixed $controller The controller to parse
|
Chris@0
|
348 *
|
Chris@0
|
349 * @return array|string An array of controller data or a simple string
|
Chris@0
|
350 */
|
Chris@0
|
351 protected function parseController($controller)
|
Chris@0
|
352 {
|
Chris@17
|
353 if (\is_string($controller) && false !== strpos($controller, '::')) {
|
Chris@0
|
354 $controller = explode('::', $controller);
|
Chris@0
|
355 }
|
Chris@0
|
356
|
Chris@17
|
357 if (\is_array($controller)) {
|
Chris@0
|
358 try {
|
Chris@0
|
359 $r = new \ReflectionMethod($controller[0], $controller[1]);
|
Chris@0
|
360
|
Chris@17
|
361 return [
|
Chris@17
|
362 'class' => \is_object($controller[0]) ? \get_class($controller[0]) : $controller[0],
|
Chris@0
|
363 'method' => $controller[1],
|
Chris@0
|
364 'file' => $r->getFileName(),
|
Chris@0
|
365 'line' => $r->getStartLine(),
|
Chris@17
|
366 ];
|
Chris@0
|
367 } catch (\ReflectionException $e) {
|
Chris@17
|
368 if (\is_callable($controller)) {
|
Chris@0
|
369 // using __call or __callStatic
|
Chris@17
|
370 return [
|
Chris@17
|
371 'class' => \is_object($controller[0]) ? \get_class($controller[0]) : $controller[0],
|
Chris@0
|
372 'method' => $controller[1],
|
Chris@0
|
373 'file' => 'n/a',
|
Chris@0
|
374 'line' => 'n/a',
|
Chris@17
|
375 ];
|
Chris@0
|
376 }
|
Chris@0
|
377 }
|
Chris@0
|
378 }
|
Chris@0
|
379
|
Chris@0
|
380 if ($controller instanceof \Closure) {
|
Chris@0
|
381 $r = new \ReflectionFunction($controller);
|
Chris@0
|
382
|
Chris@17
|
383 $controller = [
|
Chris@0
|
384 'class' => $r->getName(),
|
Chris@0
|
385 'method' => null,
|
Chris@0
|
386 'file' => $r->getFileName(),
|
Chris@0
|
387 'line' => $r->getStartLine(),
|
Chris@17
|
388 ];
|
Chris@17
|
389
|
Chris@17
|
390 if (false !== strpos($r->name, '{closure}')) {
|
Chris@17
|
391 return $controller;
|
Chris@17
|
392 }
|
Chris@17
|
393 $controller['method'] = $r->name;
|
Chris@17
|
394
|
Chris@17
|
395 if ($class = $r->getClosureScopeClass()) {
|
Chris@17
|
396 $controller['class'] = $class->name;
|
Chris@17
|
397 } else {
|
Chris@17
|
398 return $r->name;
|
Chris@17
|
399 }
|
Chris@17
|
400
|
Chris@17
|
401 return $controller;
|
Chris@0
|
402 }
|
Chris@0
|
403
|
Chris@17
|
404 if (\is_object($controller)) {
|
Chris@0
|
405 $r = new \ReflectionClass($controller);
|
Chris@0
|
406
|
Chris@17
|
407 return [
|
Chris@0
|
408 'class' => $r->getName(),
|
Chris@0
|
409 'method' => null,
|
Chris@0
|
410 'file' => $r->getFileName(),
|
Chris@0
|
411 'line' => $r->getStartLine(),
|
Chris@17
|
412 ];
|
Chris@0
|
413 }
|
Chris@0
|
414
|
Chris@17
|
415 return \is_string($controller) ? $controller : 'n/a';
|
Chris@0
|
416 }
|
Chris@0
|
417 }
|