added a Twig panel to the WebProfiler
This commit is contained in:
parent
ef0c9679cb
commit
daad64fa54
@ -1,10 +1,4 @@
|
||||
{
|
||||
"repositories": [
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://github.com/fabpot/Twig"
|
||||
}
|
||||
],
|
||||
"name": "symfony/symfony",
|
||||
"type": "library",
|
||||
"description": "The Symfony PHP framework",
|
||||
@ -24,7 +18,7 @@
|
||||
"require": {
|
||||
"php": ">=5.3.9",
|
||||
"doctrine/common": "~2.3",
|
||||
"twig/twig": "dev-profiler as 1.17.x-dev",
|
||||
"twig/twig": "~1.18",
|
||||
"psr/log": "~1.0"
|
||||
},
|
||||
"replace": {
|
||||
|
143
src/Symfony/Bridge/Twig/DataCollector/TwigDataCollector.php
Normal file
143
src/Symfony/Bridge/Twig/DataCollector/TwigDataCollector.php
Normal file
@ -0,0 +1,143 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Bridge\Twig\DataCollector;
|
||||
|
||||
use Symfony\Component\HttpKernel\DataCollector\DataCollector;
|
||||
use Symfony\Component\HttpKernel\DataCollector\LateDataCollectorInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
/**
|
||||
* TwigDataCollector.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class TwigDataCollector extends DataCollector implements LateDataCollectorInterface
|
||||
{
|
||||
private $profile;
|
||||
private $computed;
|
||||
|
||||
public function __construct(\Twig_Profiler_Profile $profile)
|
||||
{
|
||||
$this->profile = $profile;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function collect(Request $request, Response $response, \Exception $exception = null)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function lateCollect()
|
||||
{
|
||||
$this->data['profile'] = serialize($this->profile);
|
||||
}
|
||||
|
||||
public function getTime()
|
||||
{
|
||||
return $this->getProfile()->getDuration() * 1000;
|
||||
}
|
||||
|
||||
public function getTemplateCount()
|
||||
{
|
||||
return $this->getComputedData('template_count');
|
||||
}
|
||||
|
||||
public function getTemplates()
|
||||
{
|
||||
return $this->getComputedData('templates');
|
||||
}
|
||||
|
||||
public function getBlockCount()
|
||||
{
|
||||
return $this->getComputedData('block_count');
|
||||
}
|
||||
|
||||
public function getMacroCount()
|
||||
{
|
||||
return $this->getComputedData('macro_count');
|
||||
}
|
||||
|
||||
public function getHtmlCallGraph()
|
||||
{
|
||||
$dumper = new \Twig_Profiler_Dumper_Html();
|
||||
|
||||
return new \Twig_Markup($dumper->dump($this->getProfile()), 'UTF-8');
|
||||
}
|
||||
|
||||
public function getProfile()
|
||||
{
|
||||
if (null === $this->profile) {
|
||||
$this->profile = unserialize($this->data['profile']);
|
||||
}
|
||||
|
||||
return $this->profile;
|
||||
}
|
||||
|
||||
private function getComputedData($index)
|
||||
{
|
||||
if (null === $this->computed) {
|
||||
$this->computed = $this->computeData($this->getProfile());
|
||||
}
|
||||
|
||||
return $this->computed['index'];
|
||||
}
|
||||
|
||||
private function computeData(\Twig_Profiler_Profile $profile)
|
||||
{
|
||||
$data = array(
|
||||
'template_count' => 0,
|
||||
'block_count' => 0,
|
||||
'macro_count' => 0,
|
||||
);
|
||||
|
||||
$templates = array();
|
||||
foreach ($profile as $p) {
|
||||
$d = $this->computeData($p);
|
||||
|
||||
$data['template_count'] += ($p->isTemplate() ? 1 : 0) + $d['template_count'];
|
||||
$data['block_count'] += ($p->isBlock() ? 1 : 0) + $d['block_count'];
|
||||
$data['macro_count'] += ($p->isMacro() ? 1 : 0) + $d['macro_count'];
|
||||
|
||||
if ($p->isTemplate()) {
|
||||
if (!isset($templates[$p->getTemplate()])) {
|
||||
$templates[$p->getTemplate()] = 1;
|
||||
} else {
|
||||
$templates[$p->getTemplate()]++;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($d['templates'] as $template => $count) {
|
||||
if (!isset($templates[$template])) {
|
||||
$templates[$template] = $count;
|
||||
} else {
|
||||
$templates[$template] += $count;
|
||||
}
|
||||
}
|
||||
}
|
||||
$data['templates'] = $templates;
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'twig';
|
||||
}
|
||||
}
|
@ -21,7 +21,7 @@ class ProfilerExtension extends \Twig_Extension_Profiler
|
||||
private $stopwatch;
|
||||
private $events;
|
||||
|
||||
public function __construct(\Twig_Profiler_Profile $profile, Stopwatch $stopwatch)
|
||||
public function __construct(\Twig_Profiler_Profile $profile, Stopwatch $stopwatch = null)
|
||||
{
|
||||
parent::__construct($profile);
|
||||
|
||||
@ -31,7 +31,7 @@ class ProfilerExtension extends \Twig_Extension_Profiler
|
||||
|
||||
public function enter(\Twig_Profiler_Profile $profile)
|
||||
{
|
||||
if ($profile->isTemplate()) {
|
||||
if ($this->stopwatch && $profile->isTemplate()) {
|
||||
$this->events[$profile] = $this->stopwatch->start($profile->getName(), 'template');
|
||||
}
|
||||
|
||||
@ -42,7 +42,7 @@ class ProfilerExtension extends \Twig_Extension_Profiler
|
||||
{
|
||||
parent::leave($profile);
|
||||
|
||||
if ($profile->isTemplate()) {
|
||||
if ($this->stopwatch && $profile->isTemplate()) {
|
||||
$this->events[$profile]->stop();
|
||||
unset($this->events[$profile]);
|
||||
}
|
||||
|
@ -18,7 +18,7 @@
|
||||
"require": {
|
||||
"php": ">=5.3.9",
|
||||
"symfony/security-csrf": "~2.6|~3.0.0",
|
||||
"twig/twig": "~1.17"
|
||||
"twig/twig": "~1.18"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/finder": "~2.3|~3.0.0",
|
||||
|
@ -63,8 +63,9 @@ class ExtensionPass implements CompilerPassInterface
|
||||
$container->getDefinition('twig.extension.code')->replaceArgument(0, $container->getParameter('templating.helper.code.file_link_format'));
|
||||
}
|
||||
|
||||
if ($container->getParameter('kernel.debug') && $container->has('debug.stopwatch')) {
|
||||
if ($container->getParameter('kernel.debug')) {
|
||||
$container->getDefinition('twig.extension.profiler')->addTag('twig.extension');
|
||||
$container->getDefinition('twig.extension.debug')->addTag('twig.extension');
|
||||
}
|
||||
|
||||
if ($container->has('templating')) {
|
||||
|
@ -101,10 +101,6 @@ class TwigExtension extends Extension
|
||||
$config['extensions']
|
||||
);
|
||||
|
||||
if ($container->getParameter('kernel.debug')) {
|
||||
$loader->load('debug.xml');
|
||||
}
|
||||
|
||||
if (isset($config['autoescape_service']) && isset($config['autoescape_service_method'])) {
|
||||
$config['autoescape'] = array(new Reference($config['autoescape_service']), $config['autoescape_service_method']);
|
||||
}
|
||||
|
@ -1,16 +0,0 @@
|
||||
<?xml version="1.0" ?>
|
||||
|
||||
<container xmlns="http://symfony.com/schema/dic/services"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
|
||||
|
||||
<parameters>
|
||||
<parameter key="debug.templating.engine.twig.class">Symfony\Bundle\TwigBundle\Debug\TimedTwigEngine</parameter>
|
||||
</parameters>
|
||||
|
||||
<services>
|
||||
<service id="twig.extension.debug" class="Twig_Extension_Debug" public="false">
|
||||
<tag name="twig.extension" />
|
||||
</service>
|
||||
</services>
|
||||
</container>
|
@ -72,11 +72,16 @@
|
||||
|
||||
<service id="twig.extension.profiler" class="Symfony\Bridge\Twig\Extension\ProfilerExtension" public="false">
|
||||
<argument type="service" id="twig.profile" />
|
||||
<argument type="service" id="debug.stopwatch" on-invalid="ignore" />
|
||||
<argument type="service" id="debug.stopwatch" on-invalid="null" />
|
||||
</service>
|
||||
|
||||
<service id="twig.profile" class="Twig_Profiler_Profile" />
|
||||
|
||||
<service id="data_collector.twig" class="Symfony\Bridge\Twig\DataCollector\TwigDataCollector" public="false">
|
||||
<tag name="data_collector" template="@WebProfiler/Collector/twig.html.twig" id="twig" priority="255" />
|
||||
<argument type="service" id="twig.profile" />
|
||||
</service>
|
||||
|
||||
<service id="twig.extension.trans" class="%twig.extension.trans.class%" public="false">
|
||||
<argument type="service" id="translator" />
|
||||
</service>
|
||||
@ -128,6 +133,8 @@
|
||||
<argument type="service" id="twig.form.renderer" />
|
||||
</service>
|
||||
|
||||
<service id="twig.extension.debug" class="Twig_Extension_Debug" public="false" />
|
||||
|
||||
<service id="twig.form.engine" class="%twig.form.engine.class%" public="false">
|
||||
<argument>%twig.form.resources%</argument>
|
||||
</service>
|
||||
|
@ -0,0 +1,85 @@
|
||||
{% extends '@WebProfiler/Profiler/layout.html.twig' %}
|
||||
|
||||
{% block toolbar %}
|
||||
{% set time = collector.templatecount ? '%0.0f ms'|format(collector.time) : 'n/a' %}
|
||||
{% set icon %}
|
||||
<img height="28" alt="Twig" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAcCAYAAACOGPReAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAbElEQVRIx2NgGAXUBowMDAwMaWlp/6ll4KxZsxhZYJy0tDRqGMjAwMDAwEQL77OgCxSXlJBsSG9PDwqfJi6lj/fRvTJ4XYocUTBXE4q8oRtRRBnKwsw8RFw6fA0lKkd1dnYOIpfCCthRMIIAAI0IFu9Hxh7ZAAAAAElFTkSuQmCC" />
|
||||
<span class="sf-toolbar-status">{{ time }}</span>
|
||||
{% endset %}
|
||||
{% set text %}
|
||||
<div class="sf-toolbar-info-piece">
|
||||
<b>Render Time</b>
|
||||
<span>{{ time }}</span>
|
||||
</div>
|
||||
<div class="sf-toolbar-info-piece">
|
||||
<b>Template Calls</b>
|
||||
<span>{{ collector.templatecount }}</span>
|
||||
</div>
|
||||
<div class="sf-toolbar-info-piece">
|
||||
<b>Block Calls</b>
|
||||
<span>{{ collector.blockcount }}</span>
|
||||
</div>
|
||||
<div class="sf-toolbar-info-piece">
|
||||
<b>Macro Calls</b>
|
||||
<span>{{ collector.macrocount }}</span>
|
||||
</div>
|
||||
{% endset %}
|
||||
{% include '@WebProfiler/Profiler/toolbar_item.html.twig' with { 'link': profiler_url } %}
|
||||
{% endblock %}
|
||||
|
||||
{% block menu %}
|
||||
<span class="label">
|
||||
<span class="icon"><img alt="Twig" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAgCAYAAAABtRhCAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAbklEQVRIx2NgGAVDHTDCGGlpaf9pZcmsWbPg9rAgS6SlpdHCMhQ+E72DlAWbYHFJCcUG9/b0YBWnuw9HLaRPosEV4cPHh9iyBczXxGaZ0WxBfBwwM4/mw1ELRy0c4MK7s7NzCPsQvYU1CkYBNgAAV5UW+fU+ZL4AAAAASUVORK5CYII="></span>
|
||||
<strong>Twig</strong>
|
||||
<span class="count">
|
||||
<span>{{ collector.templatecount }}</span>
|
||||
<span>{{ '%0.0f ms'|format(collector.time) }}</span>
|
||||
</span>
|
||||
</span>
|
||||
{% endblock %}
|
||||
|
||||
{% block panel %}
|
||||
{% if collector.templatecount %}
|
||||
<h2>Twig Stats</h2>
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th>Total Render Time<br /><small>including sub-requests rendering time</small></th>
|
||||
<td><pre>{{ '%0.0f ms'|format(collector.time) }}</pre></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="col" style="width: 30%">Template Calls</th>
|
||||
<td scope="col" style="width: 60%"><pre>{{ collector.templatecount }}</pre></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Block Calls</th>
|
||||
<td><pre>{{ collector.blockcount }}</pre></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Macro Calls</th>
|
||||
<td><pre>{{ collector.macrocount }}</pre></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h2>Rendered Templates</h2>
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th scope="col">Template Name</th>
|
||||
<th scope="col">Render Count</th>
|
||||
</tr>
|
||||
{% for template, count in collector.templates %}
|
||||
<tr>
|
||||
<td><code>{{ template }}</code></td>
|
||||
<td><pre>{{ count }}</pre></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
|
||||
<h2>Rendering Call Graph</h2>
|
||||
|
||||
{{ collector.htmlcallgraph }}
|
||||
{% else %}
|
||||
<p><em>No Twig templates were rendered for this request.</em></p>
|
||||
{% endif %}
|
||||
{% endblock %}
|
@ -19,7 +19,7 @@
|
||||
"php": ">=5.3.9",
|
||||
"symfony/http-kernel": "~2.4|~3.0.0",
|
||||
"symfony/routing": "~2.2|~3.0.0",
|
||||
"symfony/twig-bridge": "~2.2|~3.0.0"
|
||||
"symfony/twig-bridge": "~2.7|~3.0.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/config": "~2.2|~3.0.0",
|
||||
|
Reference in New Issue
Block a user