1<?php 2 3/* 4 * This file is part of the Symfony package. 5 * 6 * (c) Fabien Potencier <fabien@symfony.com> 7 * 8 * For the full copyright and license information, please view the LICENSE 9 * file that was distributed with this source code. 10 */ 11 12namespace Symfony\Component\HttpKernel\Debug; 13 14use Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcher as BaseTraceableEventDispatcher; 15use Symfony\Component\HttpKernel\KernelEvents; 16use Symfony\Component\EventDispatcher\Event; 17 18/** 19 * Collects some data about event listeners. 20 * 21 * This event dispatcher delegates the dispatching to another one. 22 * 23 * @author Fabien Potencier <fabien@symfony.com> 24 */ 25class TraceableEventDispatcher extends BaseTraceableEventDispatcher 26{ 27 /** 28 * {@inheritdoc} 29 */ 30 protected function preDispatch($eventName, Event $event) 31 { 32 switch ($eventName) { 33 case KernelEvents::REQUEST: 34 $this->stopwatch->openSection(); 35 break; 36 case KernelEvents::VIEW: 37 case KernelEvents::RESPONSE: 38 // stop only if a controller has been executed 39 if ($this->stopwatch->isStarted('controller')) { 40 $this->stopwatch->stop('controller'); 41 } 42 break; 43 case KernelEvents::TERMINATE: 44 $token = $event->getResponse()->headers->get('X-Debug-Token'); 45 // There is a very special case when using built-in AppCache class as kernel wrapper, in the case 46 // of an ESI request leading to a `stale` response [B] inside a `fresh` cached response [A]. 47 // In this case, `$token` contains the [B] debug token, but the open `stopwatch` section ID 48 // is equal to the [A] debug token. Trying to reopen section with the [B] token throws an exception 49 // which must be caught. 50 try { 51 $this->stopwatch->openSection($token); 52 } catch (\LogicException $e) { 53 } 54 break; 55 } 56 } 57 58 /** 59 * {@inheritdoc} 60 */ 61 protected function postDispatch($eventName, Event $event) 62 { 63 switch ($eventName) { 64 case KernelEvents::CONTROLLER_ARGUMENTS: 65 $this->stopwatch->start('controller', 'section'); 66 break; 67 case KernelEvents::RESPONSE: 68 $token = $event->getResponse()->headers->get('X-Debug-Token'); 69 $this->stopwatch->stopSection($token); 70 break; 71 case KernelEvents::TERMINATE: 72 // In the special case described in the `preDispatch` method above, the `$token` section 73 // does not exist, then closing it throws an exception which must be caught. 74 $token = $event->getResponse()->headers->get('X-Debug-Token'); 75 try { 76 $this->stopwatch->stopSection($token); 77 } catch (\LogicException $e) { 78 } 79 break; 80 } 81 } 82} 83