mirror of
https://github.com/maximebf/php-debugbar.git
synced 2025-07-25 02:31:25 +02:00
Draft: Support twig namespaces (#479)
* Add Twig 1, 2 and 3 as required dependency - Latest safe Twig 1 version - Latest safe Twig 2 version - Latest safe Twig 3 version * Add ext-json as a requirement * Add namespacedTwigProfileCollector * Deprecated old class * Update docs for PHP/Twig * Remove incompatibility * Update namespace * Update composer.json Co-authored-by: Barry vd. Heuvel <barryvdh@gmail.com>
This commit is contained in:
@@ -22,7 +22,8 @@
|
||||
"symfony/var-dumper": "^2.6|^3|^4|^5"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^7.5.20 || ^9.4.2"
|
||||
"phpunit/phpunit": "^7.5.20 || ^9.4.2",
|
||||
"twig/twig": "^1.38|^2.7|^3.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
@@ -90,22 +90,48 @@ Display log messages and sent mail using `DebugBar\Bridge\SwiftMailer\SwiftLogCo
|
||||
|
||||
http://twig.sensiolabs.org/
|
||||
|
||||
### Version 1 and 2
|
||||
|
||||
This collector uses the class `Twig_Extension_Profiler` to collect info about rendered
|
||||
templates, blocks and macros.
|
||||
You need to inject the root `Twig_Profiler_Profile` into the collector:
|
||||
|
||||
$loader = new Twig_Loader_Filesystem('.');
|
||||
$env = new Twig_Environment($loader);
|
||||
$profile = new Twig_Profiler_Profile();
|
||||
$env->addExtension(new Twig_Extension_Profiler($profile));
|
||||
$debugbar->addCollector(new DebugBar\Bridge\TwigProfileCollector($profile));
|
||||
```php
|
||||
$loader = new Twig_Loader_Filesystem('.');
|
||||
$env = new Twig_Environment($loader);
|
||||
$profile = new Twig_Profiler_Profile();
|
||||
$env->addExtension(new Twig_Extension_Profiler($profile));
|
||||
$debugbar->addCollector(new DebugBar\Bridge\TwigProfileCollector($profile));
|
||||
```
|
||||
|
||||
You can optionally use `DebugBar\Bridge\Twig\TimeableTwigExtensionProfiler` in place of
|
||||
`Twig_Extension_Profiler` so render operation can be measured.
|
||||
|
||||
$loader = new Twig_Loader_Filesystem('.');
|
||||
$env = new Twig_Environment($loader);
|
||||
$profile = new Twig_Profiler_Profile();
|
||||
$env->addExtension(new DebugBar\Bridge\Twig\TimeableTwigExtensionProfiler($profile, $debugbar['time']));
|
||||
$debugbar->addCollector(new DebugBar\Bridge\TwigProfileCollector($profile));
|
||||
```php
|
||||
$loader = new Twig_Loader_Filesystem('.');
|
||||
$env = new Twig_Environment($loader);
|
||||
$profile = new Twig_Profiler_Profile();
|
||||
$env->addExtension(new DebugBar\Bridge\Twig\TimeableTwigExtensionProfiler($profile, $debugbar['time']));
|
||||
$debugbar->addCollector(new DebugBar\Bridge\TwigProfileCollector($profile));
|
||||
```
|
||||
|
||||
### Version 2 and 3
|
||||
|
||||
This collector uses the class `Twig\Extension\ProfilerExtension` to collect info about rendered
|
||||
templates, blocks and macros.
|
||||
You need to inject the root `Twig\Profiler\Profile` into the collector:
|
||||
|
||||
```php
|
||||
use DebugBar\Bridge\NamespacedTwigProfileCollector;
|
||||
use Twig\Environment;
|
||||
use Twig\Extension\ProfilerExtension;
|
||||
use Twig\Loader\FilesystemLoader;
|
||||
use Twig\Profiler\Profile;
|
||||
|
||||
$loader = new FilesystemLoader('.');
|
||||
$env = new Environment($loader);
|
||||
$profile = new Profile();
|
||||
$env->addExtension(new ProfilerExtension($profile));
|
||||
$debugbar->addCollector(new NamespacedTwigProfileCollector($profile));
|
||||
```
|
||||
|
||||
|
204
src/DebugBar/Bridge/NamespacedTwigProfileCollector.php
Normal file
204
src/DebugBar/Bridge/NamespacedTwigProfileCollector.php
Normal file
@@ -0,0 +1,204 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DebugBar\Bridge;
|
||||
|
||||
use DebugBar\DataCollector\AssetProvider;
|
||||
use DebugBar\DataCollector\DataCollector;
|
||||
use DebugBar\DataCollector\Renderable;
|
||||
use Twig\Environment;
|
||||
use Twig\Loader\LoaderInterface;
|
||||
use Twig\Profiler\Dumper\HtmlDumper;
|
||||
use Twig\Profiler\Profile;
|
||||
|
||||
/**
|
||||
* Collects data about rendered templates
|
||||
*
|
||||
* http://twig.sensiolabs.org/
|
||||
*
|
||||
* A \Twig\Profiler\Profile should be added to your \Twig\Environment
|
||||
* The root-Twig\Profiler\Profile-object should then be injected into this collector
|
||||
*
|
||||
* you can optionally provide the \Twig\Environment or the \Twig\Loader to also create
|
||||
* debug-links.
|
||||
*
|
||||
* @see \Twig\Extension\ProfilerExtension, \Twig\Profiler\Profile
|
||||
*
|
||||
* <code>
|
||||
* $env = new \Twig\Environment($loader); // Or from a PSR11-container
|
||||
* $profile = new \Twig\Profiler\Profile();
|
||||
* $env->addExtension(new \Twig\Extension\ProfilerExtension($profile));
|
||||
* $debugbar->addCollector(new ModernTwigProfileCollector($profile, $env));
|
||||
* // or: $debugbar->addCollector(new ModernTwigProfileCollector($profile, $loader));
|
||||
* </code>
|
||||
*/
|
||||
class NamespacedTwigProfileCollector extends DataCollector implements Renderable, AssetProvider
|
||||
{
|
||||
/**
|
||||
* @var Profile
|
||||
*/
|
||||
private $profile;
|
||||
|
||||
/**
|
||||
* @var LoaderInterface|Environment|null
|
||||
*/
|
||||
private $loader;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $templateCount;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $blockCount;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $macroCount;
|
||||
/**
|
||||
* @var array[] {
|
||||
* @var string $name
|
||||
* @var int $render_time
|
||||
* @var string $render_time_str
|
||||
* @var string $memory_str
|
||||
* @var string $xdebug_link
|
||||
* }
|
||||
*/
|
||||
private $templates;
|
||||
|
||||
/**
|
||||
* TwigProfileCollector constructor.
|
||||
*
|
||||
* @param Profile $profile
|
||||
* @param LoaderInterface|Environment $loaderOrEnv
|
||||
*/
|
||||
public function __construct(Profile $profile, $loaderOrEnv = null)
|
||||
{
|
||||
$this->profile = $profile;
|
||||
if ($loaderOrEnv instanceof Environment) {
|
||||
$loaderOrEnv = $loaderOrEnv->getLoader();
|
||||
}
|
||||
$this->loader = $loaderOrEnv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a hash where keys are control names and their values
|
||||
* an array of options as defined in {@see \DebugBar\JavascriptRenderer::addControl()}
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getWidgets()
|
||||
{
|
||||
return [
|
||||
'twig' => [
|
||||
'icon' => 'leaf',
|
||||
'widget' => 'PhpDebugBar.Widgets.TemplatesWidget',
|
||||
'map' => 'twig',
|
||||
'default' => json_encode(['templates' => []]),
|
||||
],
|
||||
'twig:badge' => [
|
||||
'map' => 'twig.badge',
|
||||
'default' => 0,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getAssets()
|
||||
{
|
||||
return [
|
||||
'css' => 'widgets/templates/widget.css',
|
||||
'js' => 'widgets/templates/widget.js',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the DebugBar when data needs to be collected
|
||||
*
|
||||
* @return array Collected data
|
||||
*/
|
||||
public function collect()
|
||||
{
|
||||
$this->templateCount = $this->blockCount = $this->macroCount = 0;
|
||||
$this->templates = [];
|
||||
$this->computeData($this->profile);
|
||||
|
||||
return [
|
||||
'nb_templates' => $this->templateCount,
|
||||
'nb_blocks' => $this->blockCount,
|
||||
'nb_macros' => $this->macroCount,
|
||||
'templates' => $this->templates,
|
||||
'accumulated_render_time' => $this->profile->getDuration(),
|
||||
'accumulated_render_time_str' => $this->getDataFormatter()->formatDuration($this->profile->getDuration()),
|
||||
'memory_usage_str' => $this->getDataFormatter()->formatBytes($this->profile->getMemoryUsage()),
|
||||
'callgraph' => $this->getHtmlCallGraph(),
|
||||
'badge' => implode(
|
||||
'/',
|
||||
[
|
||||
$this->templateCount,
|
||||
$this->blockCount,
|
||||
$this->macroCount,
|
||||
]
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the unique name of the collector
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'twig';
|
||||
}
|
||||
|
||||
public function getHtmlCallGraph()
|
||||
{
|
||||
$dumper = new HtmlDumper();
|
||||
return $dumper->dump($this->profile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an Xdebug Link to a file
|
||||
*
|
||||
* @return array {
|
||||
* @var string url
|
||||
* @var bool ajax
|
||||
* }
|
||||
*/
|
||||
public function getXdebugLink($template, $line = 1)
|
||||
{
|
||||
if (is_null($this->loader)) {
|
||||
return null;
|
||||
}
|
||||
$file = $this->loader->getSourceContext($template)->getPath();
|
||||
|
||||
return parent::getXdebugLink($file, $line);
|
||||
}
|
||||
|
||||
private function computeData(Profile $profile)
|
||||
{
|
||||
$this->templateCount += ($profile->isTemplate() ? 1 : 0);
|
||||
$this->blockCount += ($profile->isBlock() ? 1 : 0);
|
||||
$this->macroCount += ($profile->isMacro() ? 1 : 0);
|
||||
if ($profile->isTemplate()) {
|
||||
$this->templates[] = [
|
||||
'name' => $profile->getName(),
|
||||
'render_time' => $profile->getDuration(),
|
||||
'render_time_str' => $this->getDataFormatter()->formatDuration($profile->getDuration()),
|
||||
'memory_str' => $this->getDataFormatter()->formatBytes($profile->getMemoryUsage()),
|
||||
'xdebug_link' => $this->getXdebugLink($profile->getTemplate()),
|
||||
];
|
||||
}
|
||||
foreach ($profile as $p) {
|
||||
$this->computeData($p);
|
||||
}
|
||||
}
|
||||
}
|
@@ -57,4 +57,4 @@ class TimeableTwigExtensionProfiler extends \Twig_Extension_Profiler
|
||||
$this->timeDataCollector->stopMeasure($profile->getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -34,6 +34,8 @@ use DebugBar\DataCollector\Renderable;
|
||||
* $debugbar->addCollector(new TwigProfileCollector($profile, $env));
|
||||
* // or: $debugbar->addCollector(new TwigProfileCollector($profile, $loader));
|
||||
* </code>
|
||||
*
|
||||
* @deprecated Use `\Debugbar\Bridge\NamespacedTwigProfileCollector` instead for Twig 2.x and 3.x
|
||||
*/
|
||||
class TwigProfileCollector extends DataCollector implements Renderable, AssetProvider
|
||||
{
|
||||
|
Reference in New Issue
Block a user