├── .gitignore ├── DataCollector ├── AsseticDataCollector.php ├── ContainerDataCollector.php ├── RoutingDataCollector.php └── TwigDataCollector.php ├── DependencyInjection ├── Compiler │ └── TwigEngineCompilerPass.php ├── Configuration.php └── WebProfilerExtraExtension.php ├── LICENSE ├── README.md ├── Resources ├── config │ ├── assetic.xml │ ├── container.xml │ ├── routing.xml │ └── twig.xml ├── meta │ └── LICENCE ├── public │ └── images │ │ ├── assetic.png │ │ ├── container.png │ │ ├── routing.png │ │ └── twig.png └── views │ └── Collector │ ├── assetic.html.twig │ ├── container.html.twig │ ├── routing.html.twig │ └── twig.html.twig ├── TwigProfilerEngine.php ├── WebProfilerExtraBundle.php ├── composer.json └── screen.png /.gitignore: -------------------------------------------------------------------------------- 1 | vendor 2 | composer.lock 3 | -------------------------------------------------------------------------------- /DataCollector/AsseticDataCollector.php: -------------------------------------------------------------------------------- 1 | 5 | * 6 | * For the full copyright and license information, please view the LICENSE 7 | * file that was distributed with this source code. 8 | */ 9 | 10 | namespace Elao\WebProfilerExtraBundle\DataCollector; 11 | 12 | use Symfony\Component\DependencyInjection\Container; 13 | use Symfony\Component\HttpKernel\DataCollector\DataCollector; 14 | use Symfony\Component\HttpFoundation\Request; 15 | use Symfony\Component\HttpFoundation\Response; 16 | 17 | /** 18 | * AsseticDataCollector. 19 | * 20 | * @author Vincent Bouzeran 21 | */ 22 | class AsseticDataCollector extends DataCollector 23 | { 24 | protected $container; 25 | 26 | /** 27 | * Constructor for the Assetic Datacollector 28 | * 29 | * @param Container $container The service container 30 | * @param boolean $displayInWdt True if the shortcut should be displayed 31 | */ 32 | public function __construct(Container $container, $displayInWdt) 33 | { 34 | $this->container = $container; 35 | $this->data['display_in_wdt'] = $displayInWdt; 36 | } 37 | 38 | /** 39 | * Collect assets informations from Assetic Asset Manager 40 | * 41 | * @param Request $request The Request Object 42 | * @param Response $response The Response Object 43 | * @param \Exception $exception Exception 44 | */ 45 | public function collect(Request $request, Response $response, \Exception $exception = null) 46 | { 47 | $collections = array(); 48 | 49 | foreach ($this->getAssetManager()->getNames() as $name) { 50 | $collection = $this->getAssetManager()->get($name); 51 | $assets = array(); 52 | $filters = array(); 53 | 54 | foreach ($collection->all() as $asset) { 55 | $assets[] = $asset->getSourcePath(); 56 | } 57 | 58 | foreach ($collection->getFilters() as $filter) { 59 | $filters[] = get_class($filter); 60 | } 61 | 62 | $collections[$name] = array( 63 | 'target' => $collection->getTargetPath(), 64 | 'assets' => $assets, 65 | 'filters' => $filters 66 | ); 67 | } 68 | 69 | $this->data['collections'] = $collections; 70 | } 71 | 72 | /** 73 | * Resets this data collector to its initial state. 74 | */ 75 | public function reset() 76 | { 77 | $this->data = ['display_in_wdt' => $this->data['display_in_wdt']]; 78 | } 79 | 80 | /** 81 | * Get the Assetic Assetic manager 82 | * 83 | * @return LazyAssetManager 84 | */ 85 | protected function getAssetManager() 86 | { 87 | return $this->container->get('assetic.asset_manager'); 88 | } 89 | 90 | /** 91 | * Calculates the Collection Count 92 | * 93 | * @return integer The Amount of the Collection 94 | */ 95 | public function getCollectionCount() 96 | { 97 | return count($this->data['collections']); 98 | } 99 | 100 | /** 101 | * Returns the Collection 102 | * 103 | * @return array Returns the Collection 104 | */ 105 | public function getCollections() 106 | { 107 | return $this->data['collections']; 108 | } 109 | 110 | public function getDisplayInWdt() 111 | { 112 | return $this->data['display_in_wdt']; 113 | } 114 | 115 | /** 116 | * {@inheritdoc} 117 | */ 118 | public function getName() 119 | { 120 | return 'elao_assetic'; 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /DataCollector/ContainerDataCollector.php: -------------------------------------------------------------------------------- 1 | 5 | * 6 | * For the full copyright and license information, please view the LICENSE 7 | * file that was distributed with this source code. 8 | */ 9 | 10 | namespace Elao\WebProfilerExtraBundle\DataCollector; 11 | 12 | use Symfony\Component\HttpKernel\Kernel; 13 | use Symfony\Component\HttpKernel\DataCollector\DataCollector; 14 | use Symfony\Component\HttpFoundation\Request; 15 | use Symfony\Component\HttpFoundation\Response; 16 | use Symfony\Component\DependencyInjection\Alias; 17 | use Symfony\Component\DependencyInjection\Definition; 18 | use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; 19 | use Symfony\Component\DependencyInjection\ContainerBuilder; 20 | use Symfony\Component\Config\FileLocator; 21 | 22 | /** 23 | * ContainerDataCollector. 24 | * 25 | * @author Vincent Bouzeran 26 | */ 27 | class ContainerDataCollector extends DataCollector 28 | { 29 | /** 30 | * @var Kernel 31 | */ 32 | protected $kernel; 33 | 34 | /** 35 | * @var ContainerBuilder 36 | */ 37 | protected $containerBuilder; 38 | 39 | /** 40 | * Constructor for the Container Datacollector 41 | * 42 | * @param Kernel $kernel The Kernel 43 | * @param boolean $displayInWdt True if the shortcut should be displayed 44 | */ 45 | public function __construct(Kernel $kernel, $displayInWdt) 46 | { 47 | $this->kernel = $kernel; 48 | $this->data['display_in_wdt'] = $displayInWdt; 49 | } 50 | 51 | /** 52 | * Gets the Kernel 53 | * 54 | * @return object The Kernel Object 55 | */ 56 | public function getKernel() 57 | { 58 | return $this->kernel; 59 | } 60 | 61 | /** 62 | * Collect information about services and parameters from the cached dumped xml container 63 | * 64 | * @param Request $request The Request Object 65 | * @param Response $response The Response Object 66 | * @param \Exception $exception The Exception 67 | */ 68 | public function collect(Request $request, Response $response, \Exception $exception = null) 69 | { 70 | $parameters = array(); 71 | $services = array(); 72 | 73 | $this->loadContainerBuilder(); 74 | 75 | if ($this->containerBuilder !== false) { 76 | foreach ($this->containerBuilder->getParameterBag()->all() as $key => $value) { 77 | $service = substr($key, 0, strpos($key, '.')); 78 | if (!isset($parameters[$service])) { 79 | $parameters[$service] = array(); 80 | } 81 | $parameters[$service][$key] = $value; 82 | } 83 | 84 | $serviceIds = $this->containerBuilder->getServiceIds(); 85 | foreach ($serviceIds as $serviceId) { 86 | $definition = $this->resolveServiceDefinition($serviceId); 87 | 88 | if ($definition instanceof Definition && $definition->isPublic()) { 89 | $services[$serviceId] = array('class' => $definition->getClass()); 90 | } elseif ($definition instanceof Alias) { 91 | $services[$serviceId] = array('alias' => $definition); 92 | } else { 93 | continue; // We don't want private services 94 | } 95 | } 96 | 97 | ksort($services); 98 | ksort($parameters); 99 | } 100 | $this->data['parameters'] = $parameters; 101 | $this->data['services'] = $services; 102 | } 103 | 104 | /** 105 | * Resets this data collector to its initial state. 106 | */ 107 | public function reset() 108 | { 109 | $this->data = ['display_in_wdt' => $this->data['display_in_wdt']]; 110 | } 111 | 112 | /** 113 | * Returns the Parameters Information 114 | * 115 | * @return array Collection of Parameters 116 | */ 117 | public function getParameters() 118 | { 119 | return $this->data['parameters']; 120 | } 121 | 122 | /** 123 | * Returns the amount of Services 124 | * 125 | * @return integer Amount of Services 126 | */ 127 | public function getServiceCount() 128 | { 129 | return count($this->getServices()); 130 | } 131 | 132 | /** 133 | * Returns the Services Information 134 | * 135 | * @return array Collection of the Services 136 | */ 137 | public function getServices() 138 | { 139 | return $this->data['services']; 140 | } 141 | 142 | public function getDisplayInWdt() 143 | { 144 | return $this->data['display_in_wdt']; 145 | } 146 | 147 | /** 148 | * {@inheritdoc} 149 | */ 150 | public function getName() 151 | { 152 | return 'elao_container'; 153 | } 154 | 155 | /** 156 | * Loads the ContainerBuilder from the cache. 157 | * 158 | * @author Ryan Weaver 159 | * 160 | */ 161 | private function loadContainerBuilder() 162 | { 163 | if ($this->containerBuilder !== null) { 164 | return; 165 | } 166 | $container = $this->kernel->getContainer(); 167 | if (!$this->getKernel()->isDebug() 168 | || !$container->hasParameter('debug.container.dump') 169 | || !file_exists($cachedFile = $container->getParameter('debug.container.dump')) 170 | ) { 171 | $this->containerBuilder = false; 172 | return; 173 | } 174 | 175 | $containerBuilder = new ContainerBuilder(); 176 | 177 | $loader = new XmlFileLoader($containerBuilder, new FileLocator()); 178 | $loader->load($cachedFile); 179 | 180 | $this->containerBuilder = $containerBuilder; 181 | } 182 | 183 | /** 184 | * Given an array of service IDs, this returns the array of corresponding 185 | * Definition and Alias objects that those ids represent. 186 | * 187 | * @param string $serviceId The service id to resolve 188 | * 189 | * @author Ryan Weaver 190 | * 191 | * @return \Symfony\Component\DependencyInjection\Definition|\Symfony\Component\DependencyInjection\Alias 192 | */ 193 | private function resolveServiceDefinition($serviceId) 194 | { 195 | if ($this->containerBuilder->hasDefinition($serviceId)) { 196 | return $this->containerBuilder->getDefinition($serviceId); 197 | } 198 | 199 | // Some service IDs don't have a Definition, they're simply an Alias 200 | if ($this->containerBuilder->hasAlias($serviceId)) { 201 | return $this->containerBuilder->getAlias($serviceId); 202 | } 203 | 204 | // the service has been injected in some special way, just return the service 205 | return $this->containerBuilder->get($serviceId); 206 | } 207 | } 208 | -------------------------------------------------------------------------------- /DataCollector/RoutingDataCollector.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Elao\WebProfilerExtraBundle\DataCollector; 13 | 14 | use Symfony\Component\HttpKernel\DataCollector\DataCollector; 15 | use Symfony\Component\HttpFoundation\Request; 16 | use Symfony\Component\HttpFoundation\Response; 17 | use Symfony\Component\Routing\RouterInterface; 18 | 19 | /** 20 | * RoutingDataCollector. 21 | * 22 | * @author Vincent Bouzeran 23 | */ 24 | class RoutingDataCollector extends DataCollector 25 | { 26 | protected $router; 27 | 28 | /** 29 | * Constructor for the Router Datacollector 30 | * 31 | * @param Router $router The Router Object 32 | * @param boolean $displayInWdt True if the shortcut should be displayed 33 | */ 34 | public function __construct(RouterInterface $router, $displayInWdt) 35 | { 36 | $this->router = $router; 37 | $this->data['display_in_wdt'] = $displayInWdt; 38 | } 39 | 40 | /** 41 | * Collects the Information on the Route 42 | * 43 | * @param Request $request The Request Object 44 | * @param Response $response The Response Object 45 | * @param \Exception $exception The Exception 46 | */ 47 | public function collect(Request $request, Response $response, \Exception $exception = null) 48 | { 49 | $collection = $this->router->getRouteCollection(); 50 | $_ressources = $collection->getResources(); 51 | $_routes = $collection->all(); 52 | 53 | $routes = array(); 54 | $ressources = array(); 55 | 56 | foreach ($_ressources as $ressource) { 57 | $ressources[] = array( 58 | 'type' => get_class($ressource), 59 | 'path' => $ressource->__toString() 60 | ); 61 | } 62 | 63 | foreach ($_routes as $routeName => $route) { 64 | $defaults = $route->getDefaults(); 65 | $requirements = $route->getRequirements(); 66 | 67 | $controller = isset($defaults['_controller']) ? $defaults['_controller'] : 'unknown'; 68 | $routes[$routeName] = array( 69 | 'name' => $routeName, 70 | 'pattern' => $route->getPath(), 71 | 'controller' => $controller, 72 | 'method' => isset($requirements['_method']) ? $requirements['_method'] : 'ANY', 73 | ); 74 | } 75 | ksort($routes); 76 | $this->data['matchRoute'] = $request->attributes->get('_route'); 77 | $this->data['routes'] = $routes; 78 | $this->data['ressources'] = $ressources; 79 | } 80 | 81 | /** 82 | * Resets this data collector to its initial state. 83 | */ 84 | public function reset() 85 | { 86 | $this->data = ['display_in_wdt' => $this->data['display_in_wdt']]; 87 | } 88 | 89 | /** 90 | * Returns the Amount of Routes 91 | * 92 | * @return integer Amount of Routes 93 | */ 94 | public function getRouteCount() 95 | { 96 | return count($this->data['routes']); 97 | } 98 | 99 | /** 100 | * Returns the Matched Routes Information 101 | * 102 | * @return array Matched Routes Collection 103 | */ 104 | public function getMatchRoute() 105 | { 106 | return $this->data['matchRoute']; 107 | } 108 | 109 | /** 110 | * Returns the Ressources Information 111 | * 112 | * @return array Ressources Information 113 | */ 114 | public function getRessources() 115 | { 116 | return $this->data['ressources']; 117 | } 118 | 119 | /** 120 | * Returns the Amount of Ressources 121 | * 122 | * @return integer Amount of Ressources 123 | */ 124 | public function getRessourceCount() 125 | { 126 | return count($this->data['ressources']); 127 | } 128 | 129 | /** 130 | * Returns all the Routes 131 | * 132 | * @return array Route Information 133 | */ 134 | public function getRoutes() 135 | { 136 | return $this->data['routes']; 137 | } 138 | 139 | /** 140 | * Returns the Time 141 | * 142 | * @return int Time 143 | */ 144 | public function getTime() 145 | { 146 | $time = 0; 147 | 148 | return $time; 149 | } 150 | 151 | public function getDisplayInWdt() 152 | { 153 | return $this->data['display_in_wdt']; 154 | } 155 | 156 | /** 157 | * {@inheritdoc} 158 | */ 159 | public function getName() 160 | { 161 | return 'elao_routing'; 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /DataCollector/TwigDataCollector.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace Elao\WebProfilerExtraBundle\DataCollector; 12 | 13 | use Symfony\Component\HttpKernel\DataCollector\DataCollector; 14 | use Symfony\Component\HttpFoundation\Request; 15 | use Symfony\Component\HttpFoundation\Response; 16 | use Symfony\Component\DependencyInjection\Container; 17 | 18 | /** 19 | * AsseticDataCollector. 20 | * 21 | * @author Vincent Bouzeran 22 | */ 23 | class TwigDataCollector extends DataCollector 24 | { 25 | private $container; 26 | 27 | /** 28 | * The Constructor for the Twig Datacollector 29 | * 30 | * @param Container $container The service container 31 | * @param boolean $displayInWdt True if the shortcut should be displayed 32 | */ 33 | public function __construct(Container $container, $displayInWdt) 34 | { 35 | $this->container = $container; 36 | $this->data['display_in_wdt'] = $displayInWdt; 37 | } 38 | 39 | /** 40 | * Collect information from Twig 41 | * 42 | * @param Request $request The Request Object 43 | * @param Response $response The Response Object 44 | * @param \Exception $exception The Exception 45 | */ 46 | public function collect(Request $request, Response $response, \Exception $exception = null) 47 | { 48 | $filters = array(); 49 | $tests = array(); 50 | $extensions = array(); 51 | $functions = array(); 52 | 53 | foreach ($this->getTwig()->getExtensions() as $extensionName => $extension) { 54 | $extensions[] = array( 55 | 'name' => $extensionName, 56 | 'class' => get_class($extension) 57 | ); 58 | foreach ($extension->getFilters() as $filterName => $filter) { 59 | if ($filter instanceof \Twig_FilterInterface) { 60 | $call = $filter->compile(); 61 | if (is_array($call) && is_callable($call)) { 62 | $call = 'Method '.$call[1].' of an object '.get_class($call[0]); 63 | } 64 | } else { 65 | $call = $filter->getName(); 66 | } 67 | 68 | $filters[] = array( 69 | 'name' => $filterName, 70 | 'extension' => $extensionName, 71 | 'call' => $call, 72 | ); 73 | } 74 | 75 | foreach ($extension->getTests() as $testName => $test) { 76 | if ($test instanceof \Twig_TestInterface) { 77 | $call = $test->compile(); 78 | } else { 79 | $call = $test->getName(); 80 | } 81 | 82 | $tests[] = array( 83 | 'name' => $testName, 84 | 'extension' => $extensionName, 85 | 'call' => $call, 86 | ); 87 | } 88 | 89 | foreach ($extension->getFunctions() as $functionName => $function) { 90 | if ($function instanceof \Twig_FunctionInterface) { 91 | $call = $function->compile(); 92 | } else { 93 | $call = $function->getName(); 94 | } 95 | 96 | $functions[] = array( 97 | 'name' => $functionName, 98 | 'extension' => $extensionName, 99 | 'call' => $call, 100 | ); 101 | } 102 | } 103 | 104 | $globals = array(); 105 | 106 | foreach ($this->getTwig()->getGlobals() as $globalName => $global) { 107 | $globals[] = array( 108 | 'name' => $globalName, 109 | 'value' => $this->getVarDump($global), 110 | ); 111 | } 112 | 113 | $this->data['globals'] = $globals; 114 | $this->data['extensions'] = $extensions; 115 | $this->data['tests'] = $tests; 116 | $this->data['filters'] = $filters; 117 | $this->data['functions'] = $functions; 118 | } 119 | 120 | /** 121 | * Resets this data collector to its initial state. 122 | */ 123 | public function reset() 124 | { 125 | $this->data = ['display_in_wdt' => $this->data['display_in_wdt']]; 126 | } 127 | 128 | /** 129 | * Get Twig Environment 130 | * 131 | * @return \Twig_Environment 132 | */ 133 | protected function getTwig() 134 | { 135 | return $this->container->get('twig'); 136 | } 137 | 138 | /** 139 | * Collects data on the twig templates rendered 140 | * 141 | * @param mixed $templateName The template name 142 | * @param array $parameters The array of parameters passed to the template 143 | * @param array $templatePath The template path 144 | */ 145 | public function collectTemplateData($templateName, $parameters, $templatePath = null) 146 | { 147 | $collectedParameters = array(); 148 | foreach ($parameters as $name => $value) { 149 | $collectedParameters[$name] = array( 150 | 'type' => in_array(gettype($value), array('object', 'resource')) ? get_class($value) : gettype($value), 151 | 'value' => in_array(gettype($value), array('object', 'resource', 'array')) ? null : $value, 152 | ); 153 | } 154 | 155 | $this->data['templates'][] = array( 156 | 'name' => $templateName, 157 | 'path' => $templatePath, 158 | 'parameters' => $collectedParameters 159 | ); 160 | } 161 | 162 | /** 163 | * Returns the amount of Templates 164 | * 165 | * @return int Amount of templates 166 | */ 167 | public function getCountTemplates() 168 | { 169 | return count($this->getTemplates()); 170 | } 171 | 172 | /** 173 | * Returns the Twig templates information 174 | * 175 | * @return array Template information 176 | */ 177 | public function getTemplates() 178 | { 179 | return isset($this->data['templates']) ? $this->data['templates'] : array(); 180 | } 181 | 182 | /** 183 | * Returns the amount of Extensions 184 | * 185 | * @return integer Amount of Extensions 186 | */ 187 | public function getCountExtensions() 188 | { 189 | return count($this->getExtensions()); 190 | } 191 | 192 | /** 193 | * Returns the Twig Globals Information 194 | * 195 | * @return array Globals Information 196 | */ 197 | public function getGlobals() 198 | { 199 | return $this->data['globals']; 200 | } 201 | 202 | /** 203 | * Returns the Twig Extensions Information 204 | * 205 | * @return array Extension Information 206 | */ 207 | public function getExtensions() 208 | { 209 | return $this->data['extensions']; 210 | } 211 | 212 | /** 213 | * Returns the amount of Filters 214 | * 215 | * @return integer Amount of Filters 216 | */ 217 | public function getCountFilters() 218 | { 219 | return count($this->getFilters()); 220 | } 221 | 222 | /** 223 | * Returns the Filter Information 224 | * 225 | * @return array Filter Information 226 | */ 227 | public function getFilters() 228 | { 229 | return $this->data['filters']; 230 | } 231 | 232 | /** 233 | * Returns the amount of Twig Tests 234 | * 235 | * @return integer Amount of Tests 236 | */ 237 | public function getCountTests() 238 | { 239 | return count($this->getTests()); 240 | } 241 | 242 | /** 243 | * Returns the Tests Information 244 | * 245 | * @return array Tests Information 246 | */ 247 | public function getTests() 248 | { 249 | return $this->data['tests']; 250 | } 251 | 252 | /** 253 | * Returns the amount of Twig Functions 254 | * 255 | * @return integer Amount of Functions 256 | */ 257 | public function getCountFunctions() 258 | { 259 | return count($this->getFunctions()); 260 | } 261 | 262 | /** 263 | * Returns Twig Functions Information 264 | * 265 | * @return array Function Information 266 | */ 267 | public function getFunctions() 268 | { 269 | return $this->data['functions']; 270 | } 271 | 272 | public function getDisplayInWdt() 273 | { 274 | return $this->data['display_in_wdt']; 275 | } 276 | 277 | /** 278 | * {@inheritdoc} 279 | */ 280 | public function getName() 281 | { 282 | return 'elao_twig'; 283 | } 284 | 285 | /** 286 | * Returns var_dump like of a variable but avoiding flood dumping 287 | * 288 | * @return string Formated var_dump 289 | */ 290 | protected function getVarDump($var) 291 | { 292 | $varType = gettype($var); 293 | switch ($varType) { 294 | case 'boolean': 295 | case 'integer': 296 | case 'double': 297 | case 'NULL': 298 | case 'ressource': 299 | return print_r($var, 1); 300 | case 'string': 301 | return (250 < strlen($var)) ? substr($var, 0, 250).'...' : $var; 302 | case 'object': 303 | return 'Object instance of ' . get_class($var); 304 | case 'array': 305 | $formated_array = array(); 306 | 307 | foreach ($var as $key => $value) { 308 | $formated_array[$key] = $this->getVarDump($value); 309 | } 310 | 311 | return print_r($formated_array, 1); 312 | } 313 | } 314 | } 315 | -------------------------------------------------------------------------------- /DependencyInjection/Compiler/TwigEngineCompilerPass.php: -------------------------------------------------------------------------------- 1 | hasParameter('web_profiler_extra.data_collector.twig.enabled') 15 | || !$container->getParameter('web_profiler_extra.data_collector.twig.enabled') 16 | ) { 17 | return; 18 | } 19 | 20 | $container->setDefinition( 21 | 'templating.engine.twig.decorated', 22 | $container->getDefinition('templating.engine.twig') 23 | ); 24 | 25 | $container->setDefinition( 26 | 'templating.engine.twig', 27 | new Definition( 28 | '%web_profiler_extra.templating.engine.twig.class%', 29 | array( 30 | new Reference('twig'), 31 | new Reference('templating.engine.twig.decorated'), 32 | new Reference('web_profiler_extra.data_collector.twig'), 33 | ) 34 | ) 35 | ); 36 | 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /DependencyInjection/Configuration.php: -------------------------------------------------------------------------------- 1 | 5 | * 6 | * For the full copyright and license information, please view the LICENSE 7 | * file that was distributed with this source code. 8 | */ 9 | 10 | namespace Elao\WebProfilerExtraBundle\DependencyInjection; 11 | 12 | use Symfony\Component\Config\Definition\Builder\TreeBuilder; 13 | use Symfony\Component\Config\Definition\ConfigurationInterface; 14 | 15 | /** 16 | * @author Grégoire Pineau 17 | */ 18 | class Configuration implements ConfigurationInterface 19 | { 20 | /** 21 | * {@inheritDoc} 22 | */ 23 | public function getConfigTreeBuilder() 24 | { 25 | $treeBuilder = new TreeBuilder('web_profiler_extra'); 26 | 27 | if (method_exists($treeBuilder, 'getRootNode')) { 28 | $rootNode = $treeBuilder->getRootNode(); 29 | } else { 30 | // BC layer for symfony/config 4.1 and older 31 | $rootNode = $treeBuilder->root('web_profiler_extra'); 32 | } 33 | 34 | $rootNode 35 | ->children() 36 | ->arrayNode('routing') 37 | ->addDefaultsIfNotSet() 38 | ->children() 39 | ->booleanNode('enabled')->defaultTrue()->end() 40 | ->booleanNode('display_in_wdt')->defaultTrue()->end() 41 | ->end() 42 | ->end() 43 | ->arrayNode('container') 44 | ->addDefaultsIfNotSet() 45 | ->children() 46 | ->booleanNode('enabled')->defaultTrue()->end() 47 | ->booleanNode('display_in_wdt')->defaultTrue()->end() 48 | ->end() 49 | ->end() 50 | ->arrayNode('assetic') 51 | ->addDefaultsIfNotSet() 52 | ->children() 53 | ->booleanNode('enabled')->defaultFalse()->end() 54 | ->booleanNode('display_in_wdt')->defaultFalse()->end() 55 | ->end() 56 | ->end() 57 | ->arrayNode('twig') 58 | ->addDefaultsIfNotSet() 59 | ->children() 60 | ->booleanNode('enabled')->defaultTrue()->end() 61 | ->booleanNode('display_in_wdt')->defaultTrue()->end() 62 | ->end() 63 | ->end() 64 | ->end() 65 | ; 66 | 67 | return $treeBuilder; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /DependencyInjection/WebProfilerExtraExtension.php: -------------------------------------------------------------------------------- 1 | 5 | * 6 | * For the full copyright and license information, please view the LICENSE 7 | * file that was distributed with this source code. 8 | */ 9 | 10 | namespace Elao\WebProfilerExtraBundle\DependencyInjection; 11 | 12 | use Symfony\Component\HttpKernel\DependencyInjection\Extension; 13 | use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; 14 | use Symfony\Component\DependencyInjection\ContainerBuilder; 15 | use Symfony\Component\Config\FileLocator; 16 | 17 | /** 18 | * ExtraProfilerExtension is an extension to add debug information to the web profiler: 19 | * assetic: Information about assetics assets 20 | * routing: Information about loaded routes 21 | * container: Information about the container configuration & sevices 22 | * twig: Information about Twig 23 | * 24 | * @author Vincent Bouzeran 25 | * @author Grégoire Pineau 26 | */ 27 | class WebProfilerExtraExtension extends Extension 28 | { 29 | private $resources = array( 30 | 'routing' => 'routing.xml', 31 | 'container' => 'container.xml', 32 | 'assetic' => 'assetic.xml', 33 | 'twig' => 'twig.xml', 34 | ); 35 | 36 | /** 37 | * {@inheritDoc} 38 | */ 39 | public function load(array $configs, ContainerBuilder $container) 40 | { 41 | $configuration = new Configuration(); 42 | $config = $this->processConfiguration($configuration, $configs); 43 | 44 | $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); 45 | foreach ($config as $resource => $item) { 46 | if ($item['enabled']) { 47 | $loader->load($this->resources[$resource]); 48 | $container->setParameter('web_profiler_extra.data_collector.'.$resource.'.display_in_wdt', $item['display_in_wdt']); 49 | } 50 | } 51 | 52 | $container->setParameter('web_profiler_extra.data_collector.twig.enabled', $config['twig']['enabled']); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2004-2011 ELAO 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is furnished 8 | to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Elao WebProfilerExtraBundle 2 | ============ 3 | 4 | [![Total Downloads](https://poser.pugx.org/elao/web-profiler-extra-bundle/d/total.png)](https://packagist.org/packages/elao/web-profiler-extra-bundle) 5 | 6 | 7 | 8 | ## What is this Symfony2 bundle for ? 9 | 10 | It adds in your WebProfiler extra sections : 11 | 12 | + **Routing** : Lists all the routes connected to your application 13 | + **Container** : Lists all the services available in your container 14 | + **Twig** : Lists Twig extensions, tests, filters and functions available for your application 15 | + **Assetic** 16 | 17 | ![WebProfilerExtraBundle](screen.png "WebProfilerExtraBundle Screenshot") 18 | 19 | 20 | ## Installation 21 | 22 | #### If you are working with Symfony >= 2.2 23 | 24 | Add this in your `composer.json` 25 | 26 | "require-dev": { 27 | [...] 28 | "elao/web-profiler-extra-bundle" : "~2.3@dev" 29 | }, 30 | 31 | And run `php composer.phar update elao/web-profiler-extra-bundle` 32 | 33 | If you are working with Symfony <= 2.1, prefer the 2.1 branch of this bundle `"elao/web-profiler-extra-bundle" : "dev-2.1"` 34 | 35 | 36 | #### Register the bundle in your AppKernel (`app/AppKernel.php`) 37 | 38 | Most of the time, we need this bundle to be only activated in the `dev` environment 39 | 40 | [...] 41 | if (in_array($this->getEnvironment(), array('dev', 'test'))) { 42 | [...] 43 | $bundles[] = new Elao\WebProfilerExtraBundle\WebProfilerExtraBundle(); 44 | } 45 | 46 | #### Activate the different collectors in `app/config/config_dev.yml` 47 | 48 | web_profiler_extra: 49 | routing: 50 | enabled: true 51 | display_in_wdt: true 52 | container: 53 | enabled: true 54 | display_in_wdt: true 55 | assetic: 56 | enabled: true 57 | display_in_wdt: true 58 | twig: 59 | enabled: true 60 | display_in_wdt: true 61 | 62 | If you don't use assetic then you need to disable the assetic collector 63 | 64 | web_profiler_extra: 65 | assetic: 66 | enabled: false 67 | display_in_wdt: false 68 | 69 | ## Install assets 70 | 71 | Install assets by running to have beautiful icons in your debug bar 72 | 73 | $ app/console assets:install web/ --symlink 74 | 75 | ## Screenshot 76 | 77 | ![Screenshot](screen.png) 78 | -------------------------------------------------------------------------------- /Resources/config/assetic.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | Elao\WebProfilerExtraBundle\DataCollector\AsseticDataCollector 9 | 10 | 11 | 12 | 13 | 14 | %web_profiler_extra.data_collector.assetic.display_in_wdt% 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /Resources/config/container.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | Elao\WebProfilerExtraBundle\DataCollector\ContainerDataCollector 9 | 10 | 11 | 12 | 13 | 14 | %web_profiler_extra.data_collector.container.display_in_wdt% 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /Resources/config/routing.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | Elao\WebProfilerExtraBundle\DataCollector\RoutingDataCollector 9 | 10 | 11 | 12 | 13 | 14 | %web_profiler_extra.data_collector.routing.display_in_wdt% 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /Resources/config/twig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | Elao\WebProfilerExtraBundle\DataCollector\TwigDataCollector 9 | Elao\WebProfilerExtraBundle\TwigProfilerEngine 10 | 11 | 12 | 13 | 14 | 15 | %web_profiler_extra.data_collector.twig.display_in_wdt% 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /Resources/meta/LICENCE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015 Elao - http://www.elao.com 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is furnished 8 | to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /Resources/public/images/assetic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Elao/WebProfilerExtraBundle/edbcd31a3e0b0940b0ed0301d467f2419280d679/Resources/public/images/assetic.png -------------------------------------------------------------------------------- /Resources/public/images/container.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Elao/WebProfilerExtraBundle/edbcd31a3e0b0940b0ed0301d467f2419280d679/Resources/public/images/container.png -------------------------------------------------------------------------------- /Resources/public/images/routing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Elao/WebProfilerExtraBundle/edbcd31a3e0b0940b0ed0301d467f2419280d679/Resources/public/images/routing.png -------------------------------------------------------------------------------- /Resources/public/images/twig.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Elao/WebProfilerExtraBundle/edbcd31a3e0b0940b0ed0301d467f2419280d679/Resources/public/images/twig.png -------------------------------------------------------------------------------- /Resources/views/Collector/assetic.html.twig: -------------------------------------------------------------------------------- 1 | {% extends '@WebProfiler/Profiler/layout.html.twig' %} 2 | 3 | {% block toolbar %} 4 | {% if collector.displayInWdt %} 5 | {% set icon %} 6 | Assetic 7 | Assetic 8 | {% endset %} 9 | {% set text %} 10 |
11 | Collections 12 | {{ collector.collections|length }} 13 |
14 | {% endset %} 15 | {% include '@WebProfiler/Profiler/toolbar_item.html.twig' with { 'link': profiler_url } %} 16 | {% endif %} 17 | {% endblock %} 18 | 19 | {% block menu %} 20 | 21 | 22 | 23 | 24 | Assetic 25 | 26 | {{ collector.collectionCount }} 27 | 28 | 29 | {% endblock %} 30 | 31 | {% block panel %} 32 |

Assetic

33 | {% if collector.collections|length %} 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | {% for i, collection in collector.collections %} 42 | 43 | 46 | 53 | 60 | 63 | 64 | {% endfor %} 65 |
CollectionSourcesFiltersTarget Url
44 | {{ i }} 45 | 47 |
    48 | {% for asset in collection.assets %} 49 |
  • {{ asset }}
  • 50 | {% endfor %} 51 |
52 |
54 |
    55 | {% for filter in collection.filters %} 56 |
  • {{ filter }}
  • 57 | {% endfor %} 58 |
59 |
61 | {{ collection.target }} 62 |
66 | {% else %} 67 |

68 | No assetic collection 69 |

70 | {% endif %} 71 | {% endblock %} 72 | -------------------------------------------------------------------------------- /Resources/views/Collector/container.html.twig: -------------------------------------------------------------------------------- 1 | {% extends '@WebProfiler/Profiler/layout.html.twig' %} 2 | 3 | 4 | {% block toolbar %} 5 | {% if collector.displayInWdt %} 6 | {% set serviceCount = collector.serviceCount %} 7 | {% set icon %} 8 | Container 9 | {{ serviceCount }} 10 | Services 11 | {% endset %} 12 | {% set text %} 13 |
14 | Services 15 | {{ serviceCount }} 16 |
17 |
18 | Parameter
namespaces
19 | {{ collector.parameters|length }} 20 |
21 | {% endset %} 22 | {% include '@WebProfiler/Profiler/toolbar_item.html.twig' with { 'link': profiler_url } %} 23 | {% endif %} 24 | {% endblock %} 25 | 26 | {% block menu %} 27 | 28 | 29 | 30 | 31 | Container 32 | 33 | {{ collector.serviceCount }} 34 | 35 | 36 | {% endblock %} 37 | 38 | {% block panel %} 39 | {% if collector.services is empty %} 40 |
41 | No debug container information 42 |
43 | {% else %} 44 | {% set profiler_markup_version = profiler_markup_version|default(1) %} 45 | 46 | {% if profiler_markup_version == 2 %} 47 |

Container metrics

48 |
49 |
50 | {{ collector.serviceCount }} 51 | Services 52 |
53 | 54 |
55 | {{ collector.parameters|length }} 56 | Parameters namespaces 57 |
58 |
59 | {% endif %} 60 | 61 |

Container Parameters

62 | 63 | {% for service, parameters in collector.parameters %} 64 | 65 | 66 | 67 | 68 | 69 | 70 | {% for key, value in parameters %} 71 | 72 | 73 | 76 | 77 | {% endfor %} 78 | 79 | {% endfor %} 80 |
{{ service|default('#') }}
{{ key }} 74 | {{ value | yaml_dump }} 75 |
81 | 82 |

Container Services:

83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | {% for service_id, service in collector.services %} 91 | 92 | 93 | 100 | 101 | {% endfor %} 102 |
NameClass Name
{{ service_id }} 94 | {% if service.class is defined %} 95 | {{ service.class }} 96 | {% elseif service.alias is defined %} 97 | alias to {{ service.alias }} 98 | {% endif %} 99 |
103 | {% endif %} 104 | {% endblock %} 105 | -------------------------------------------------------------------------------- /Resources/views/Collector/routing.html.twig: -------------------------------------------------------------------------------- 1 | {% extends '@WebProfiler/Profiler/layout.html.twig' %} 2 | 3 | {% block toolbar %} 4 | {% if collector.displayInWdt %} 5 | {% set icon %} 6 | Routing 7 | {{ collector.routecount }} 8 | Routes 9 | {% endset %} 10 | {% set text %} 11 |
12 | Routes 13 | {{ collector.routecount }} 14 |
15 |
16 | Resources 17 | {{ collector.ressourcecount }} 18 |
19 | {% endset %} 20 | {% include '@WebProfiler/Profiler/toolbar_item.html.twig' with { 'link': profiler_url } %} 21 | {% endif %} 22 | {% endblock %} 23 | 24 | {% block menu %} 25 | 26 | 27 | 28 | 29 | Routing 30 | 31 | {{ collector.routecount }} 32 | 33 | 34 | {% endblock %} 35 | 36 | {% block panel %} 37 | 38 |

Routes

39 | {% if not collector.routecount %} 40 | No route. 41 | {% else %} 42 | 43 | {% for route in collector.routes %} 44 | 45 | 48 | 51 | 55 | 56 | {% endfor %} 57 |
46 | {{ route.name }} 47 | 49 | {{ route.method }} 50 | 52 | {{ route.pattern }}
53 | {{ route.controller }} 54 |
58 | {% endif %} 59 | 60 |

Sources

61 | 62 | {% if not collector.ressourcecount %} 63 | No source. 64 | {% else %} 65 | 66 | {% for i, ressource in collector.ressources %} 67 | 68 | 71 | 74 | 75 | {% endfor %} 76 |
69 | {{ ressource.type }} 70 | 72 | {{ ressource.path }} 73 |
77 | {% endif %} 78 | 79 | {% endblock %} 80 | -------------------------------------------------------------------------------- /Resources/views/Collector/twig.html.twig: -------------------------------------------------------------------------------- 1 | {% extends '@WebProfiler/Profiler/layout.html.twig' %} 2 | 3 | {% block toolbar %} 4 | {% if collector.displayInWdt %} 5 | {% set icon %} 6 | Twig 7 | Twig 8 | {% endset %} 9 | {% set text %} 10 |
11 | Template{{ 1 == collector.templates|length ? ':' : 's'}} 12 | 13 | {% if 1 == collector.templates|length %} 14 | {% set template = collector.templates|first %} 15 | {% if template.path %} 16 | 17 | {{ template.name }} 18 | 19 | {% else %} 20 | {{ template.name }} 21 | {% endif %} 22 | {% else %} 23 | {{ collector.templates|length }} 24 | {% endif %} 25 | 26 |
27 |
28 | Globals 29 | {{ collector.globals|length }} 30 |
31 |
32 | Extensions 33 | {{ collector.extensions|length }} 34 |
35 |
36 | avail. Tests 37 | {{ collector.tests|length }} 38 |
39 |
40 | avail. Filters 41 | {{ collector.filters|length }} 42 |
43 |
44 | avail. Functions 45 | {{ collector.functions|length }} 46 |
47 | {% endset %} 48 | {% include '@WebProfiler/Profiler/toolbar_item.html.twig' with { 'link': profiler_url } %} 49 | {% endif %} 50 | {% endblock %} 51 | 52 | {% block menu %} 53 | 54 | 55 | 56 | 57 | Twig 58 | 59 | {{ collector.extensions|length }} 60 | 61 | 62 | {% endblock %} 63 | 64 | {% block panel %} 65 | {% set profiler_markup_version = profiler_markup_version|default(1) %} 66 | 67 | {% if profiler_markup_version == 2 %} 68 |

Twig metrics

69 |
70 |
71 | {{ collector.globals|length }} 72 | Globals 73 |
74 |
75 | {{ collector.extensions|length }} 76 | Extensions 77 |
78 |
79 | {{ collector.tests|length }} 80 | Tests 81 |
82 |
83 | {{ collector.filters|length }} 84 | Filters 85 |
86 |
87 | {{ collector.functions|length }} 88 | Functions 89 |
90 |
91 | {% endif %} 92 | 93 | {% if collector.templates|length %} 94 |

Twig Templates

95 | 96 | 97 | 98 | 99 | 100 | {% for template in collector.templates %} 101 | 102 | 111 | 132 | 133 | {% endfor %} 134 |
TemplateParameters
103 | {% if template.path %} 104 | 105 | {{ template.name }} 106 | 107 | {% else %} 108 | {{ template.name }} 109 | {% endif %} 110 | 112 | {% for parameter, metadata in template.parameters %} 113 | {% if metadata.type == 'boolean' %} 114 | {% set value = metadata.value ? 'true' : 'false' %} 115 | {% elseif metadata.type == 'string' %} 116 | {% set maxStrLength = 40 %} 117 | {% set value = metadata.value %} 118 | {% if value|length > maxStrLength %} 119 | {% set value = value|slice(0, maxStrLength) ~ '…' %} 120 | {% endif %} 121 | {% set value = '"' ~ value ~ '"' %} 122 | {% else %} 123 | {% set value = metadata.value %} 124 | {% endif %} 125 | 126 | {{ parameter }}: {{ metadata.type }} 127 | {{ value }} 128 | 129 | {% if not loop.last %}
{% endif %} 130 | {% endfor %} 131 |
135 | {% endif %} 136 | 137 | {% if collector.globals|length %} 138 |

Twig Globals

139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | {% for global in collector.globals %} 148 | 149 | 150 | 151 | 152 | {% endfor %} 153 | 154 |
NameValue
{{ global.name }}{{ global.value }}
155 | {% endif %} 156 | 157 | {% if collector.extensions|length %} 158 |

Twig Extensions

159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | {% for extension in collector.extensions %} 168 | 169 | 170 | 171 | 172 | {% endfor %} 173 | 174 |
ExtensionClass
{{ extension.name }}{{ extension.class }}
175 | {% endif %} 176 | 177 | {% if collector.tests|length %} 178 |

Twig Tests available

179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | {% for test in collector.tests %} 189 | 190 | 191 | 192 | 193 | 194 | {% endfor %} 195 | 196 |
TestCallExtension
{{ test.name }}{{ test.call }}{{ test.extension }}
197 | {% endif %} 198 | 199 | {% if collector.filters|length %} 200 |

Twig Filters available

201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | {% for filter in collector.filters %} 211 | 212 | 213 | 214 | 215 | 216 | {% endfor %} 217 | 218 |
FilterCallExtension
{{ filter.name }}{{ filter.call }}{{ filter.extension }}
219 | {% endif %} 220 | 221 | {% if collector.functions|length %} 222 |

Twig Functions available

223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | {% for function in collector.functions %} 233 | 234 | 235 | 236 | 237 | 238 | {% endfor %} 239 | 240 |
FunctionCallExtension
{{ function.name }}{{ function.call }}{{ function.extension }}
241 | {% endif %} 242 | {% endblock %} 243 | -------------------------------------------------------------------------------- /TwigProfilerEngine.php: -------------------------------------------------------------------------------- 1 | environment = $environment; 18 | $this->twigEngine = $twigEngine; 19 | $this->collector = $collector; 20 | } 21 | 22 | /** 23 | * {@inheritdoc} 24 | */ 25 | public function render($name, array $parameters = array()) 26 | { 27 | $templatePath = null; 28 | 29 | $loader = $this->environment->getLoader(); 30 | 31 | if ($loader instanceof \Twig_LoaderInterface) { 32 | $templatePath = $loader->getCacheKey($name); 33 | } 34 | $this->collector->collectTemplateData($name, $parameters, $templatePath); 35 | 36 | return $this->twigEngine->render($name, $parameters); 37 | } 38 | 39 | /** 40 | * {@inheritdoc} 41 | */ 42 | public function stream($name, array $parameters = array()) 43 | { 44 | $this->twigEngine->stream($name, $parameters); 45 | } 46 | 47 | /** 48 | * {@inheritdoc} 49 | */ 50 | public function exists($name) 51 | { 52 | return $this->twigEngine->exists($name); 53 | } 54 | 55 | /** 56 | * {@inheritdoc} 57 | */ 58 | public function supports($name) 59 | { 60 | return $this->twigEngine->supports($name); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /WebProfilerExtraBundle.php: -------------------------------------------------------------------------------- 1 | addCompilerPass(new TwigEngineCompilerPass()); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "elao/web-profiler-extra-bundle", 3 | "type": "symfony-bundle", 4 | "description": "Add routing, container, assetic & twig information inside the profiler", 5 | "keywords": ["elao", "profiler", "extra", "bundle"], 6 | "homepage": "http://github.com/Elao/WebProfilerExtraBundle", 7 | "license": "MIT", 8 | "authors": [ 9 | { 10 | "name": "Elao Team", 11 | "homepage": "http://www.elao.com" 12 | }, 13 | { 14 | "name": "Contributors", 15 | "homepage": "http://github.com/Elao/WebProfilerExtraBundle/contributors" 16 | } 17 | ], 18 | "require": { 19 | "symfony/framework-bundle": "~2.1|~3.0|~4.0", 20 | "symfony/templating": "~2.0|~3.0|~4.0", 21 | "symfony/twig-bundle": "~2.0|~3.0|~4.0", 22 | "twig/twig": "~1.12|~2.0" 23 | }, 24 | "autoload": { 25 | "psr-4": { 26 | "Elao\\WebProfilerExtraBundle\\": "." 27 | } 28 | }, 29 | "extra": { 30 | "branch-alias": { 31 | "dev-master": "2.3-dev" 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Elao/WebProfilerExtraBundle/edbcd31a3e0b0940b0ed0301d467f2419280d679/screen.png --------------------------------------------------------------------------------