first commit

This commit is contained in:
Sampanna Rimal
2024-08-27 17:48:06 +05:45
commit 53c0140f58
10839 changed files with 1125847 additions and 0 deletions

View File

@@ -0,0 +1,75 @@
<?php
/*
* This file is part of the DebugBar package.
*
* (c) 2013 Maxime Bouroumeau-Fuseau
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace DebugBar\Bridge;
use CacheCache\Cache;
use CacheCache\LoggingBackend;
use Monolog\Logger;
/**
* Collects CacheCache operations
*
* http://maximebf.github.io/CacheCache/
*
* Example:
* <code>
* $debugbar->addCollector(new CacheCacheCollector(CacheManager::get('default')));
* // or
* $debugbar->addCollector(new CacheCacheCollector());
* $debugbar['cache']->addCache(CacheManager::get('default'));
* </code>
*/
class CacheCacheCollector extends MonologCollector
{
protected $logger;
/**
* CacheCacheCollector constructor.
* @param Cache|null $cache
* @param Logger|null $logger
* @param bool $level
* @param bool $bubble
*/
public function __construct(Cache $cache = null, Logger $logger = null, $level = Logger::DEBUG, $bubble = true)
{
parent::__construct(null, $level, $bubble);
if ($logger === null) {
$logger = new Logger('Cache');
}
$this->logger = $logger;
if ($cache !== null) {
$this->addCache($cache);
}
}
/**
* @param Cache $cache
*/
public function addCache(Cache $cache)
{
$backend = $cache->getBackend();
if (!($backend instanceof LoggingBackend)) {
$backend = new LoggingBackend($backend, $this->logger);
}
$cache->setBackend($backend);
$this->addLogger($backend->getLogger());
}
/**
* @return string
*/
public function getName()
{
return 'cache';
}
}

View File

@@ -0,0 +1,115 @@
<?php
/*
* This file is part of the DebugBar package.
*
* (c) 2013 Maxime Bouroumeau-Fuseau
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace DebugBar\Bridge;
use DebugBar\DataCollector\AssetProvider;
use DebugBar\DataCollector\DataCollector;
use DebugBar\DataCollector\Renderable;
use DebugBar\DebugBarException;
use Doctrine\DBAL\Logging\DebugStack;
use Doctrine\ORM\EntityManager;
/**
* Collects Doctrine queries
*
* http://doctrine-project.org
*
* Uses the DebugStack logger to collects data about queries
*
* <code>
* $debugStack = new Doctrine\DBAL\Logging\DebugStack();
* $entityManager->getConnection()->getConfiguration()->setSQLLogger($debugStack);
* $debugbar->addCollector(new DoctrineCollector($debugStack));
* </code>
*/
class DoctrineCollector extends DataCollector implements Renderable, AssetProvider
{
protected $debugStack;
/**
* DoctrineCollector constructor.
* @param $debugStackOrEntityManager
* @throws DebugBarException
*/
public function __construct($debugStackOrEntityManager)
{
if ($debugStackOrEntityManager instanceof EntityManager) {
$debugStackOrEntityManager = $debugStackOrEntityManager->getConnection()->getConfiguration()->getSQLLogger();
}
if (!($debugStackOrEntityManager instanceof DebugStack)) {
throw new DebugBarException("'DoctrineCollector' requires an 'EntityManager' or 'DebugStack' object");
}
$this->debugStack = $debugStackOrEntityManager;
}
/**
* @return array
*/
public function collect()
{
$queries = array();
$totalExecTime = 0;
foreach ($this->debugStack->queries as $q) {
$queries[] = array(
'sql' => $q['sql'],
'params' => (object) $q['params'],
'duration' => $q['executionMS'],
'duration_str' => $this->formatDuration($q['executionMS'])
);
$totalExecTime += $q['executionMS'];
}
return array(
'nb_statements' => count($queries),
'accumulated_duration' => $totalExecTime,
'accumulated_duration_str' => $this->formatDuration($totalExecTime),
'statements' => $queries
);
}
/**
* @return string
*/
public function getName()
{
return 'doctrine';
}
/**
* @return array
*/
public function getWidgets()
{
return array(
"database" => array(
"icon" => "arrow-right",
"widget" => "PhpDebugBar.Widgets.SQLQueriesWidget",
"map" => "doctrine",
"default" => "[]"
),
"database:badge" => array(
"map" => "doctrine.nb_statements",
"default" => 0
)
);
}
/**
* @return array
*/
public function getAssets()
{
return array(
'css' => 'widgets/sqlqueries/widget.css',
'js' => 'widgets/sqlqueries/widget.js'
);
}
}

View File

@@ -0,0 +1,118 @@
<?php
/*
* This file is part of the DebugBar package.
*
* (c) 2013 Maxime Bouroumeau-Fuseau
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace DebugBar\Bridge;
use DebugBar\DataCollector\DataCollectorInterface;
use DebugBar\DataCollector\MessagesAggregateInterface;
use DebugBar\DataCollector\Renderable;
use Monolog\Handler\AbstractProcessingHandler;
use Monolog\Logger;
/**
* A monolog handler as well as a data collector
*
* https://github.com/Seldaek/monolog
*
* <code>
* $debugbar->addCollector(new MonologCollector($logger));
* </code>
*/
class MonologCollector extends AbstractProcessingHandler implements DataCollectorInterface, Renderable, MessagesAggregateInterface
{
protected $name;
protected $records = array();
/**
* @param Logger $logger
* @param int $level
* @param boolean $bubble
* @param string $name
*/
public function __construct(Logger $logger = null, $level = Logger::DEBUG, $bubble = true, $name = 'monolog')
{
parent::__construct($level, $bubble);
$this->name = $name;
if ($logger !== null) {
$this->addLogger($logger);
}
}
/**
* Adds logger which messages you want to log
*
* @param Logger $logger
*/
public function addLogger(Logger $logger)
{
$logger->pushHandler($this);
}
/**
* @param array|\Monolog\LogRecord $record
*/
protected function write($record): void
{
$this->records[] = array(
'message' => $record['formatted'],
'is_string' => true,
'label' => strtolower($record['level_name']),
'time' => $record['datetime']->format('U')
);
}
/**
* @return array
*/
public function getMessages()
{
return $this->records;
}
/**
* @return array
*/
public function collect()
{
return array(
'count' => count($this->records),
'records' => $this->records
);
}
/**
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* @return array
*/
public function getWidgets()
{
$name = $this->getName();
return array(
$name => array(
"icon" => "suitcase",
"widget" => "PhpDebugBar.Widgets.MessagesWidget",
"map" => "$name.records",
"default" => "[]"
),
"$name:badge" => array(
"map" => "$name.count",
"default" => "null"
)
);
}
}

View File

@@ -0,0 +1,213 @@
<?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;
$this->setLoaderOrEnv($loaderOrEnv);
}
/**
* @param LoaderInterface|Environment $loaderOrEnv
*/
public function setLoaderOrEnv($loaderOrEnv)
{
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);
}
}
}

View File

@@ -0,0 +1,307 @@
<?php
/*
* This file is part of the DebugBar package.
*
* (c) 2013 Maxime Bouroumeau-Fuseau
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace DebugBar\Bridge;
use DebugBar\DataCollector\AssetProvider;
use DebugBar\DataCollector\DataCollector;
use DebugBar\DataCollector\Renderable;
use Monolog\Handler\TestHandler;
use Monolog\Logger;
use Propel\Runtime\Connection\ConnectionInterface;
use Propel\Runtime\Connection\ProfilerConnectionWrapper;
use Propel\Runtime\Propel;
use Psr\Log\LogLevel;
use Psr\Log\LoggerInterface;
/**
* A Propel logger which acts as a data collector
*
* http://propelorm.org/
*
* Will log queries and display them using the SQLQueries widget.
*
* Example:
* <code>
* $debugbar->addCollector(new \DebugBar\Bridge\Propel2Collector(\Propel\Runtime\Propel::getServiceContainer()->getReadConnection()));
* </code>
*/
class Propel2Collector extends DataCollector implements Renderable, AssetProvider
{
/**
* @var null|TestHandler
*/
protected $handler = null;
/**
* @var null|Logger
*/
protected $logger = null;
/**
* @var array
*/
protected $config = array();
/**
* @var array
*/
protected $errors = array();
/**
* @var int
*/
protected $queryCount = 0;
/**
* @param ConnectionInterface $connection Propel connection
*/
public function __construct(
ConnectionInterface $connection,
array $logMethods = array(
'beginTransaction',
'commit',
'rollBack',
'forceRollBack',
'exec',
'query',
'execute'
)
) {
if ($connection instanceof ProfilerConnectionWrapper) {
$connection->setLogMethods($logMethods);
$this->config = $connection->getProfiler()->getConfiguration();
$this->handler = new TestHandler();
if ($connection->getLogger() instanceof Logger) {
$this->logger = $connection->getLogger();
$this->logger->pushHandler($this->handler);
} else {
$this->errors[] = 'Supported only monolog logger';
}
} else {
$this->errors[] = 'You need set ProfilerConnectionWrapper';
}
}
/**
* @return TestHandler|null
*/
public function getHandler()
{
return $this->handler;
}
/**
* @return array
*/
public function getConfig()
{
return $this->config;
}
/**
* @return Logger|null
*/
public function getLogger()
{
return $this->logger;
}
/**
* @return LoggerInterface
*/
protected function getDefaultLogger()
{
return Propel::getServiceContainer()->getLogger();
}
/**
* @return int
*/
protected function getQueryCount()
{
return $this->queryCount;
}
/**
* @param array $records
* @param array $config
* @return array
*/
protected function getStatements($records, $config)
{
$statements = array();
foreach ($records as $record) {
$duration = null;
$memory = null;
$isSuccess = ( LogLevel::INFO === strtolower($record['level_name']) );
$detailsCount = count($config['details']);
$parameters = explode($config['outerGlue'], $record['message'], $detailsCount + 1);
if (count($parameters) === ($detailsCount + 1)) {
$parameters = array_map('trim', $parameters);
$_details = array();
foreach (array_splice($parameters, 0, $detailsCount) as $string) {
list($key, $value) = array_map('trim', explode($config['innerGlue'], $string, 2));
$_details[$key] = $value;
}
$details = array();
foreach ($config['details'] as $key => $detail) {
if (isset($_details[$detail['name']])) {
$value = $_details[$detail['name']];
if ('time' === $key) {
if (substr_count($value, 'ms')) {
$value = (float)$value / 1000;
} else {
$value = (float)$value;
}
} else {
$suffixes = array('B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB');
$suffix = substr($value, -2);
$i = array_search($suffix, $suffixes, true);
$i = (false === $i) ? 0 : $i;
$value = ((float)$value) * pow(1024, $i);
}
$details[$key] = $value;
}
}
if (isset($details['time'])) {
$duration = $details['time'];
}
if (isset($details['memDelta'])) {
$memory = $details['memDelta'];
}
$message = end($parameters);
if ($isSuccess) {
$this->queryCount++;
}
} else {
$message = $record['message'];
}
$statement = array(
'sql' => $message,
'is_success' => $isSuccess,
'duration' => $duration,
'duration_str' => $this->getDataFormatter()->formatDuration($duration),
'memory' => $memory,
'memory_str' => $this->getDataFormatter()->formatBytes($memory),
);
if (false === $isSuccess) {
$statement['sql'] = '';
$statement['error_code'] = $record['level'];
$statement['error_message'] = $message;
}
$statements[] = $statement;
}
return $statements;
}
/**
* @return array
*/
public function collect()
{
if (count($this->errors)) {
return array(
'statements' => array_map(function ($message) {
return array('sql' => '', 'is_success' => false, 'error_code' => 500, 'error_message' => $message);
}, $this->errors),
'nb_statements' => 0,
'nb_failed_statements' => count($this->errors),
);
}
if ($this->getHandler() === null) {
return array();
}
$statements = $this->getStatements($this->getHandler()->getRecords(), $this->getConfig());
$failedStatement = count(array_filter($statements, function ($statement) {
return false === $statement['is_success'];
}));
$accumulatedDuration = array_reduce($statements, function ($accumulatedDuration, $statement) {
$time = isset($statement['duration']) ? $statement['duration'] : 0;
return $accumulatedDuration += $time;
});
$memoryUsage = array_reduce($statements, function ($memoryUsage, $statement) {
$time = isset($statement['memory']) ? $statement['memory'] : 0;
return $memoryUsage += $time;
});
return array(
'nb_statements' => $this->getQueryCount(),
'nb_failed_statements' => $failedStatement,
'accumulated_duration' => $accumulatedDuration,
'accumulated_duration_str' => $this->getDataFormatter()->formatDuration($accumulatedDuration),
'memory_usage' => $memoryUsage,
'memory_usage_str' => $this->getDataFormatter()->formatBytes($memoryUsage),
'statements' => $statements
);
}
/**
* @return string
*/
public function getName()
{
$additionalName = '';
if ($this->getLogger() !== $this->getDefaultLogger()) {
$additionalName = ' ('.$this->getLogger()->getName().')';
}
return 'propel2'.$additionalName;
}
/**
* @return array
*/
public function getWidgets()
{
return array(
$this->getName() => array(
'icon' => 'bolt',
'widget' => 'PhpDebugBar.Widgets.SQLQueriesWidget',
'map' => $this->getName(),
'default' => '[]'
),
$this->getName().':badge' => array(
'map' => $this->getName().'.nb_statements',
'default' => 0
),
);
}
/**
* @return array
*/
public function getAssets()
{
return array(
'css' => 'widgets/sqlqueries/widget.css',
'js' => 'widgets/sqlqueries/widget.js'
);
}
}

View File

@@ -0,0 +1,253 @@
<?php
/*
* This file is part of the DebugBar package.
*
* (c) 2013 Maxime Bouroumeau-Fuseau
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace DebugBar\Bridge;
use BasicLogger;
use DebugBar\DataCollector\AssetProvider;
use DebugBar\DataCollector\DataCollector;
use DebugBar\DataCollector\Renderable;
use Propel;
use PropelConfiguration;
use PropelPDO;
use Psr\Log\LogLevel;
use Psr\Log\LoggerInterface;
/**
* A Propel logger which acts as a data collector
*
* http://propelorm.org/
*
* Will log queries and display them using the SQLQueries widget.
* You can provide a LoggerInterface object to forward non-query related message to.
*
* Example:
* <code>
* $debugbar->addCollector(new PropelCollector($debugbar['messages']));
* PropelCollector::enablePropelProfiling();
* </code>
*/
class PropelCollector extends DataCollector implements BasicLogger, Renderable, AssetProvider
{
protected $logger;
protected $statements = array();
protected $accumulatedTime = 0;
protected $peakMemory = 0;
/**
* Sets the needed configuration option in propel to enable query logging
*
* @param PropelConfiguration $config Apply profiling on a specific config
*/
public static function enablePropelProfiling(PropelConfiguration $config = null)
{
if ($config === null) {
$config = Propel::getConfiguration(PropelConfiguration::TYPE_OBJECT);
}
$config->setParameter('debugpdo.logging.details.method.enabled', true);
$config->setParameter('debugpdo.logging.details.time.enabled', true);
$config->setParameter('debugpdo.logging.details.mem.enabled', true);
$allMethods = array(
'PropelPDO::__construct', // logs connection opening
'PropelPDO::__destruct', // logs connection close
'PropelPDO::exec', // logs a query
'PropelPDO::query', // logs a query
'PropelPDO::beginTransaction', // logs a transaction begin
'PropelPDO::commit', // logs a transaction commit
'PropelPDO::rollBack', // logs a transaction rollBack (watch out for the capital 'B')
'DebugPDOStatement::execute', // logs a query from a prepared statement
);
$config->setParameter('debugpdo.logging.methods', $allMethods, false);
}
/**
* @param LoggerInterface $logger A logger to forward non-query log lines to
* @param PropelPDO $conn Bound this collector to a connection only
*/
public function __construct(LoggerInterface $logger = null, PropelPDO $conn = null)
{
if ($conn) {
$conn->setLogger($this);
} else {
Propel::setLogger($this);
}
$this->logger = $logger;
$this->logQueriesToLogger = false;
}
public function setLogQueriesToLogger($enable = true)
{
$this->logQueriesToLogger = $enable;
return $this;
}
public function isLogQueriesToLogger()
{
return $this->logQueriesToLogger;
}
public function emergency($m)
{
$this->log($m, Propel::LOG_EMERG);
}
public function alert($m)
{
$this->log($m, Propel::LOG_ALERT);
}
public function crit($m)
{
$this->log($m, Propel::LOG_CRIT);
}
public function err($m)
{
$this->log($m, Propel::LOG_ERR);
}
public function warning($m)
{
$this->log($m, Propel::LOG_WARNING);
}
public function notice($m)
{
$this->log($m, Propel::LOG_NOTICE);
}
public function info($m)
{
$this->log($m, Propel::LOG_INFO);
}
public function debug($m)
{
$this->log($m, Propel::LOG_DEBUG);
}
public function log($message, $severity = null)
{
if (strpos($message, 'DebugPDOStatement::execute') !== false) {
list($sql, $duration_str) = $this->parseAndLogSqlQuery($message);
if (!$this->logQueriesToLogger) {
return;
}
$message = "$sql ($duration_str)";
}
if ($this->logger !== null) {
$this->logger->log($this->convertLogLevel($severity), $message);
}
}
/**
* Converts Propel log levels to PSR log levels
*
* @param int $level
* @return string
*/
protected function convertLogLevel($level)
{
$map = array(
Propel::LOG_EMERG => LogLevel::EMERGENCY,
Propel::LOG_ALERT => LogLevel::ALERT,
Propel::LOG_CRIT => LogLevel::CRITICAL,
Propel::LOG_ERR => LogLevel::ERROR,
Propel::LOG_WARNING => LogLevel::WARNING,
Propel::LOG_NOTICE => LogLevel::NOTICE,
Propel::LOG_DEBUG => LogLevel::DEBUG
);
return $map[$level];
}
/**
* Parse a log line to extract query information
*
* @param string $message
*/
protected function parseAndLogSqlQuery($message)
{
$parts = explode('|', $message, 4);
$sql = trim($parts[3]);
$duration = 0;
if (preg_match('/([0-9]+\.[0-9]+)/', $parts[1], $matches)) {
$duration = (float) $matches[1];
}
$memory = 0;
if (preg_match('/([0-9]+\.[0-9]+) ([A-Z]{1,2})/', $parts[2], $matches)) {
$memory = (float) $matches[1];
if ($matches[2] == 'KB') {
$memory *= 1024;
} elseif ($matches[2] == 'MB') {
$memory *= 1024 * 1024;
}
}
$this->statements[] = array(
'sql' => $sql,
'is_success' => true,
'duration' => $duration,
'duration_str' => $this->formatDuration($duration),
'memory' => $memory,
'memory_str' => $this->formatBytes($memory)
);
$this->accumulatedTime += $duration;
$this->peakMemory = max($this->peakMemory, $memory);
return array($sql, $this->formatDuration($duration));
}
public function collect()
{
return array(
'nb_statements' => count($this->statements),
'nb_failed_statements' => 0,
'accumulated_duration' => $this->accumulatedTime,
'accumulated_duration_str' => $this->formatDuration($this->accumulatedTime),
'peak_memory_usage' => $this->peakMemory,
'peak_memory_usage_str' => $this->formatBytes($this->peakMemory),
'statements' => $this->statements
);
}
public function getName()
{
return 'propel';
}
public function getWidgets()
{
return array(
"propel" => array(
"icon" => "bolt",
"widget" => "PhpDebugBar.Widgets.SQLQueriesWidget",
"map" => "propel",
"default" => "[]"
),
"propel:badge" => array(
"map" => "propel.nb_statements",
"default" => 0
)
);
}
public function getAssets()
{
return array(
'css' => 'widgets/sqlqueries/widget.css',
'js' => 'widgets/sqlqueries/widget.js'
);
}
}

View File

@@ -0,0 +1,66 @@
<?php
/*
* This file is part of the DebugBar package.
*
* (c) 2013 Maxime Bouroumeau-Fuseau
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace DebugBar\Bridge;
use DebugBar\DataCollector\MessagesCollector;
use Psr\Log\LogLevel;
use Slim\Log;
use Slim\Slim;
/**
* Collects messages from a Slim logger
*
* http://slimframework.com
*/
class SlimCollector extends MessagesCollector
{
protected $slim;
protected $originalLogWriter;
public function __construct(Slim $slim)
{
$this->slim = $slim;
if ($log = $slim->getLog()) {
$this->originalLogWriter = $log->getWriter();
$log->setWriter($this);
$log->setEnabled(true);
}
}
public function write($message, $level)
{
if ($this->originalLogWriter) {
$this->originalLogWriter->write($message, $level);
}
$this->addMessage($message, $this->getLevelName($level));
}
protected function getLevelName($level)
{
$map = array(
Log::EMERGENCY => LogLevel::EMERGENCY,
Log::ALERT => LogLevel::ALERT,
Log::CRITICAL => LogLevel::CRITICAL,
Log::ERROR => LogLevel::ERROR,
Log::WARN => LogLevel::WARNING,
Log::NOTICE => LogLevel::NOTICE,
Log::INFO => LogLevel::INFO,
Log::DEBUG => LogLevel::DEBUG
);
return $map[$level];
}
public function getName()
{
return 'slim';
}
}

View File

@@ -0,0 +1,53 @@
<?php
/*
* This file is part of the DebugBar package.
*
* (c) 2013 Maxime Bouroumeau-Fuseau
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace DebugBar\Bridge\SwiftMailer;
use DebugBar\DataCollector\MessagesCollector;
use Swift_Mailer;
use Swift_Plugins_Logger;
use Swift_Plugins_LoggerPlugin;
/**
* Collects log messages
*
* http://swiftmailer.org/
*/
class SwiftLogCollector extends MessagesCollector implements Swift_Plugins_Logger
{
public function __construct(Swift_Mailer $mailer)
{
$mailer->registerPlugin(new Swift_Plugins_LoggerPlugin($this));
}
public function add($entry)
{
$this->addMessage($entry);
}
public function dump()
{
$dump = '';
foreach ($this->messages as $message) {
if (!$message['is_string']) {
continue;
}
$dump .= $message['message'] . PHP_EOL;
}
return $dump;
}
public function getName()
{
return 'swiftmailer_logs';
}
}

View File

@@ -0,0 +1,103 @@
<?php
/*
* This file is part of the DebugBar package.
*
* (c) 2013 Maxime Bouroumeau-Fuseau
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace DebugBar\Bridge\SwiftMailer;
use DebugBar\DataCollector\AssetProvider;
use DebugBar\DataCollector\DataCollector;
use DebugBar\DataCollector\Renderable;
use Swift_Mailer;
use Swift_Plugins_MessageLogger;
/**
* Collects data about sent mails
*
* http://swiftmailer.org/
*/
class SwiftMailCollector extends DataCollector implements Renderable, AssetProvider
{
protected $messagesLogger;
/** @var bool */
private $showBody = false;
public function __construct(Swift_Mailer $mailer)
{
$this->messagesLogger = new Swift_Plugins_MessageLogger();
$mailer->registerPlugin($this->messagesLogger);
}
public function showMessageBody($show = true)
{
$this->showBody = $show;
}
public function collect()
{
$mails = array();
foreach ($this->messagesLogger->getMessages() as $msg) {
$html = $this->showBody ? $msg->getBody() : null;
$mails[] = array(
'to' => $this->formatTo($msg->getTo()),
'subject' => $msg->getSubject(),
'headers' => $msg->getHeaders()->toString(),
'body' => $html,
'html' => $html,
);
}
return array(
'count' => count($mails),
'mails' => $mails
);
}
protected function formatTo($to)
{
if (!$to) {
return '';
}
$f = array();
foreach ($to as $k => $v) {
$f[] = (empty($v) ? '' : "$v ") . "<$k>";
}
return implode(', ', $f);
}
public function getName()
{
return 'swiftmailer_mails';
}
public function getWidgets()
{
return array(
'emails' => array(
'icon' => 'inbox',
'widget' => 'PhpDebugBar.Widgets.MailsWidget',
'map' => 'swiftmailer_mails.mails',
'default' => '[]',
'title' => 'Mails'
),
'emails:badge' => array(
'map' => 'swiftmailer_mails.count',
'default' => 'null'
)
);
}
public function getAssets()
{
return array(
'css' => 'widgets/mails/widget.css',
'js' => 'widgets/mails/widget.js'
);
}
}

View File

@@ -0,0 +1,110 @@
<?php
namespace DebugBar\Bridge\Symfony;
use DebugBar\DataCollector\AssetProvider;
use DebugBar\DataCollector\DataCollector;
use DebugBar\DataCollector\Renderable;
use Symfony\Component\Mime\Part\AbstractPart;
/**
* Collects data about sent mail events
*
* https://github.com/symfony/mailer
*/
class SymfonyMailCollector extends DataCollector implements Renderable, AssetProvider
{
/** @var array */
private $messages = array();
/** @var bool */
private $showDetailed = false;
/** @var bool */
private $showBody = false;
/** @param \Symfony\Component\Mailer\SentMessage $message */
public function addSymfonyMessage($message)
{
$this->messages[] = $message->getOriginalMessage();
}
/**
* @deprecated use showMessageBody()
*/
public function showMessageDetail()
{
$this->showMessageBody(true);
}
public function showMessageBody($show = true)
{
$this->showBody = $show;
}
public function collect()
{
$mails = array();
foreach ($this->messages as $message) {
/* @var \Symfony\Component\Mime\Message $message */
$mail = [
'to' => array_map(function ($address) {
/* @var \Symfony\Component\Mime\Address $address */
return $address->toString();
}, $message->getTo()),
'subject' => $message->getSubject(),
'headers' => $message->getHeaders()->toString(),
'body' => null,
'html' => null,
];
if ($this->showBody) {
$body = $message->getBody();
if ($body instanceof AbstractPart) {
$mail['html'] = $message->getHtmlBody();
$mail['body'] = $message->getTextBody();
} else {
$mail['body'] = $body->bodyToString();
}
}
$mails[] = $mail;
}
return array(
'count' => count($mails),
'mails' => $mails,
);
}
public function getName()
{
return 'symfonymailer_mails';
}
public function getWidgets()
{
return array(
'emails' => array(
'icon' => 'inbox',
'widget' => 'PhpDebugBar.Widgets.MailsWidget',
'map' => 'symfonymailer_mails.mails',
'default' => '[]',
'title' => 'Mails'
),
'emails:badge' => array(
'map' => 'symfonymailer_mails.count',
'default' => 'null'
)
);
}
public function getAssets()
{
return array(
'css' => 'widgets/mails/widget.css',
'js' => 'widgets/mails/widget.js'
);
}
}

View File

@@ -0,0 +1,94 @@
<?php
namespace DebugBar\Bridge\Twig;
use Twig\Environment;
use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;
/**
* Debug messages to debugbar in your Twig templates.
*
* @package DebugBar\Bridge\Twig
*/
class DebugTwigExtension extends AbstractExtension
{
/**
* @var \DebugBar\DataCollector\MessagesCollector|null
*/
protected $messagesCollector;
/**
* @var string
*/
protected $functionName;
/**
*
* @param \DebugBar\DataCollector\MessagesCollector|null $app
* @param string $functionName
*/
public function __construct($messagesCollector, $functionName = 'debug')
{
$this->messagesCollector = $messagesCollector;
$this->functionName = $functionName;
}
/**
* {@inheritDoc}
*/
public function getName()
{
return static::class;
}
/**
* {@inheritDoc}
*/
public function getFunctions()
{
return [
new TwigFunction(
$this->functionName,
[$this, 'debug'],
['needs_context' => true, 'needs_environment' => true]
),
];
}
/**
* Based on Twig_Extension_Debug / twig_var_dump
*
* @param Environment $env
* @param $context
*/
public function debug(Environment $env, $context)
{
if (!$env->isDebug() || !$this->messagesCollector) {
return;
}
$count = func_num_args();
if (2 === $count) {
$data = [];
foreach ($context as $key => $value) {
if (is_object($value)) {
if (method_exists($value, 'toArray')) {
$data[$key] = $value->toArray();
} else {
$data[$key] = "Object (" . get_class($value) . ")";
}
} else {
$data[$key] = $value;
}
}
$this->messagesCollector->addMessage($data, 'debug');
} else {
for ($i = 2; $i < $count; $i++) {
$this->messagesCollector->addMessage(func_get_arg($i), 'debug');
}
}
return;
}
}

View File

@@ -0,0 +1,99 @@
<?php
namespace DebugBar\Bridge\Twig;
use DebugBar\DataFormatter\HasDataFormatter;
use Twig\Environment;
use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;
/**
* Dump variables using debugbar DataFormatter
*
* @package DebugBar\Bridge\Twig
*/
class DumpTwigExtension extends AbstractExtension
{
use HasDataFormatter;
/**
* @var string
*/
protected $functionName;
/**
* Create a new auth extension.
*
* @param string $functionName
*/
public function __construct($functionName = 'dump')
{
$this->functionName = $functionName;
}
/**
* {@inheritDoc}
*/
public function getName()
{
return static::class;
}
/**
* {@inheritDoc}
*/
public function getFunctions()
{
return [
new TwigFunction(
$this->functionName,
[$this, 'dump'],
['is_safe' => ['html'], 'needs_context' => true, 'needs_environment' => true]
),
];
}
/**
* Based on Twig_Extension_Debug / twig_var_dump
*
* @param Environment $env
* @param $context
*
* @return string
*/
public function dump(Environment $env, $context)
{
if (!$env->isDebug()) {
return;
}
$output = '';
$count = func_num_args();
if (2 === $count) {
$data = [];
foreach ($context as $key => $value) {
if (is_object($value)) {
if (method_exists($value, 'toArray')) {
$data[$key] = $value->toArray();
} else {
$data[$key] = "Object (" . get_class($value) . ")";
}
} else {
$data[$key] = $value;
}
}
$output .= $this->formatVar($data);
} else {
for ($i = 2; $i < $count; $i++) {
$output .= $this->formatVar(func_get_arg($i));
}
}
if ($this->isHtmlVarDumperUsed()) {
return $output;
}
return '<pre>' . $output . '</pre>';
}
}

View File

@@ -0,0 +1,77 @@
<?php
namespace DebugBar\Bridge\Twig;
use Twig\Extension\AbstractExtension;
/**
* Access debugbar timeline measure in your Twig templates.
* Based on Symfony\Bridge\Twig\Extension\StopwatchExtension
*
* @package DebugBar\Bridge\Twig
*/
class MeasureTwigExtension extends AbstractExtension
{
/**
* @var \DebugBar\DataCollector\TimeDataCollector|null
*/
protected $timeCollector;
/**
* @var string
*/
protected $tagName;
/**
* Create a new auth extension.
*
* @param \DebugBar\DataCollector\TimeDataCollector|null $debugbar
* @param string $tagName
*/
public function __construct($timeCollector, $tagName = 'measure')
{
$this->timeCollector = $timeCollector;
$this->tagName = $tagName;
}
/**
* {@inheritDoc}
*/
public function getName()
{
return static::class;
}
/**
* @return \Twig\TokenParser\TokenParserInterface[]
*/
public function getTokenParsers()
{
return [
/*
* {% measure foo %}
* Some stuff which will be recorded on the timeline
* {% endmeasure %}
*/
new MeasureTwigTokenParser(!is_null($this->timeCollector), $this->tagName, $this->getName()),
];
}
public function startMeasure(...$arg)
{
if (!$this->timeCollector) {
return;
}
$this->timeCollector->startMeasure(...$arg);
}
public function stopMeasure(...$arg)
{
if (!$this->timeCollector) {
return;
}
$this->timeCollector->stopMeasure(...$arg);
}
}

View File

@@ -0,0 +1,50 @@
<?php
namespace DebugBar\Bridge\Twig;
use DebugBar\Bridge\Twig\MeasureTwigExtension;
use Twig\Compiler;
use Twig\Node\Expression\AssignNameExpression;
use Twig\Node\Node;
/**
* Represents a measure node.
* Based on Symfony\Bridge\Twig\Node\StopwatchNode
*/
class MeasureTwigNode extends Node
{
/**
* @var string
*/
protected $extName;
public function __construct(
Node $name,
$body,
AssignNameExpression $var,
$lineno = 0,
$tag = null,
$extName = null
) {
parent::__construct(['body' => $body, 'name' => $name, 'var' => $var], [], $lineno, $tag);
$this->extName = $extName ?: MeasureTwigExtension::class;
}
public function compile(Compiler $compiler)
{
$compiler
->addDebugInfo($this)
->write('')
->subcompile($this->getNode('var'))
->raw(' = ')
->subcompile($this->getNode('name'))
->write(";\n")
->write("\$this->env->getExtension('".$this->extName."')->startMeasure(")
->subcompile($this->getNode('var'))
->raw(");\n")
->subcompile($this->getNode('body'))
->write("\$this->env->getExtension('".$this->extName."')->stopMeasure(")
->subcompile($this->getNode('var'))
->raw(");\n");
}
}

View File

@@ -0,0 +1,78 @@
<?php
namespace DebugBar\Bridge\Twig;
use Twig\Node\Expression\AssignNameExpression;
use Twig\Token;
use Twig\TokenParser\AbstractTokenParser;
/**
* Token Parser for the measure tag.
* Based on Symfony\Bridge\Twig\TokenParser\StopwatchTokenParser;
*/
class MeasureTwigTokenParser extends AbstractTokenParser
{
/**
* @var string
*/
private $extName;
/**
* @var string
*/
private $tagName;
/**
* @var bool
*/
private $enabled;
/**
*
* @param string $tagName
*/
public function __construct($enabled, $tagName, $extName = null)
{
$this->enabled = $enabled;
$this->tagName = $tagName;
$this->extName = $extName;
}
public function parse(Token $token)
{
$lineno = $token->getLine();
$stream = $this->parser->getStream();
// {% measure 'bar' %}
$name = $this->parser->getExpressionParser()->parseExpression();
$stream->expect(Token::BLOCK_END_TYPE);
// {% endmeasure %}
$body = $this->parser->subparse([$this, 'decideMeasureEnd'], true);
$stream->expect(Token::BLOCK_END_TYPE);
if ($this->enabled) {
return new MeasureTwigNode(
$name,
$body,
new AssignNameExpression($this->parser->getVarName(), $token->getLine()),
$lineno,
$this->getTag(),
$this->extName
);
}
return $body;
}
public function getTag()
{
return $this->tagName;
}
public function decideMeasureEnd(Token $token)
{
return $token->test('end'.$this->getTag());
}
}

View File

@@ -0,0 +1,61 @@
<?php
/*
* This file is part of the DebugBar package.
*
* (c) 2017 Tim Riemenschneider
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace DebugBar\Bridge\Twig;
use DebugBar\DataCollector\TimeDataCollector;
use Twig\Extension\ProfilerExtension;
use Twig\Profiler\Profile;
/**
* Class TimeableTwigExtensionProfiler
*
* Extends ProfilerExtension to add rendering times to the TimeDataCollector
*
* @package DebugBar\Bridge\Twig
*/
class TimeableTwigExtensionProfiler extends ProfilerExtension
{
/**
* @var \DebugBar\DataCollector\TimeDataCollector
*/
private $timeDataCollector;
/**
* @param \DebugBar\DataCollector\TimeDataCollector $timeDataCollector
*/
public function setTimeDataCollector(TimeDataCollector $timeDataCollector)
{
$this->timeDataCollector = $timeDataCollector;
}
public function __construct(Profile $profile, TimeDataCollector $timeDataCollector = null)
{
parent::__construct($profile);
$this->timeDataCollector = $timeDataCollector;
}
public function enter(Profile $profile)
{
if ($this->timeDataCollector && $profile->isTemplate()) {
$this->timeDataCollector->startMeasure($profile->getName(), 'template ' . $profile->getName());
}
parent::enter($profile);
}
public function leave(Profile $profile)
{
parent::leave($profile);
if ($this->timeDataCollector && $profile->isTemplate()) {
$this->timeDataCollector->stopMeasure($profile->getName());
}
}
}

View File

@@ -0,0 +1,419 @@
<?php
/*
* This file is part of the DebugBar package.
*
* (c) 2013 Maxime Bouroumeau-Fuseau
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace DebugBar\Bridge\Twig;
use DebugBar\DataCollector\TimeDataCollector;
use Twig_CompilerInterface;
use Twig_Environment;
use Twig_ExtensionInterface;
use Twig_LexerInterface;
use Twig_LoaderInterface;
use Twig_NodeInterface;
use Twig_NodeVisitorInterface;
use Twig_ParserInterface;
use Twig_TokenParserInterface;
use Twig_TokenStream;
/**
* Wrapped a Twig Environment to provide profiling features
*
* @deprecated
*/
class TraceableTwigEnvironment extends Twig_Environment
{
protected $twig;
protected $renderedTemplates = array();
protected $timeDataCollector;
/**
* @param Twig_Environment $twig
* @param TimeDataCollector $timeDataCollector
*/
public function __construct(Twig_Environment $twig, TimeDataCollector $timeDataCollector = null)
{
$this->twig = $twig;
$this->timeDataCollector = $timeDataCollector;
}
public function __call($name, $arguments)
{
return call_user_func_array(array($this->twig, $name), $arguments);
}
public function getRenderedTemplates()
{
return $this->renderedTemplates;
}
public function addRenderedTemplate(array $info)
{
$this->renderedTemplates[] = $info;
}
public function getTimeDataCollector()
{
return $this->timeDataCollector;
}
public function getBaseTemplateClass()
{
return $this->twig->getBaseTemplateClass();
}
public function setBaseTemplateClass($class)
{
$this->twig->setBaseTemplateClass($class);
}
public function enableDebug()
{
$this->twig->enableDebug();
}
public function disableDebug()
{
$this->twig->disableDebug();
}
public function isDebug()
{
return $this->twig->isDebug();
}
public function enableAutoReload()
{
$this->twig->enableAutoReload();
}
public function disableAutoReload()
{
$this->twig->disableAutoReload();
}
public function isAutoReload()
{
return $this->twig->isAutoReload();
}
public function enableStrictVariables()
{
$this->twig->enableStrictVariables();
}
public function disableStrictVariables()
{
$this->twig->disableStrictVariables();
}
public function isStrictVariables()
{
return $this->twig->isStrictVariables();
}
public function getCache($original = true)
{
return $this->twig->getCache($original);
}
public function setCache($cache)
{
$this->twig->setCache($cache);
}
public function getCacheFilename($name)
{
return $this->twig->getCacheFilename($name);
}
public function getTemplateClass($name, $index = null)
{
return $this->twig->getTemplateClass($name, $index);
}
public function getTemplateClassPrefix()
{
return $this->twig->getTemplateClassPrefix();
}
public function render($name, array $context = array())
{
return $this->loadTemplate($name)->render($context);
}
public function display($name, array $context = array())
{
$this->loadTemplate($name)->display($context);
}
public function loadTemplate($name, $index = null)
{
$cls = $this->twig->getTemplateClass($name, $index);
if (isset($this->twig->loadedTemplates[$cls])) {
return $this->twig->loadedTemplates[$cls];
}
if (!class_exists($cls, false)) {
if (false === $cache = $this->getCacheFilename($name)) {
eval('?>'.$this->compileSource($this->getLoader()->getSource($name), $name));
} else {
if (!is_file($cache) || ($this->isAutoReload() && !$this->isTemplateFresh($name, filemtime($cache)))) {
$this->writeCacheFile($cache, $this->compileSource($this->getLoader()->getSource($name), $name));
}
require_once $cache;
}
}
if (!$this->twig->runtimeInitialized) {
$this->initRuntime();
}
return $this->twig->loadedTemplates[$cls] = new TraceableTwigTemplate($this, new $cls($this));
}
public function isTemplateFresh($name, $time)
{
return $this->twig->isTemplateFresh($name, $time);
}
public function resolveTemplate($names)
{
return $this->twig->resolveTemplate($names);
}
public function clearTemplateCache()
{
$this->twig->clearTemplateCache();
}
public function clearCacheFiles()
{
$this->twig->clearCacheFiles();
}
public function getLexer()
{
return $this->twig->getLexer();
}
public function setLexer(Twig_LexerInterface $lexer)
{
$this->twig->setLexer($lexer);
}
public function tokenize($source, $name = null)
{
return $this->twig->tokenize($source, $name);
}
public function getParser()
{
return $this->twig->getParser();
}
public function setParser(Twig_ParserInterface $parser)
{
$this->twig->setParser($parser);
}
public function parse(Twig_TokenStream $tokens)
{
return $this->twig->parse($tokens);
}
public function getCompiler()
{
return $this->twig->getCompiler();
}
public function setCompiler(Twig_CompilerInterface $compiler)
{
$this->twig->setCompiler($compiler);
}
public function compile(Twig_NodeInterface $node)
{
return $this->twig->compile($node);
}
public function compileSource($source, $name = null)
{
return $this->twig->compileSource($source, $name);
}
public function setLoader(Twig_LoaderInterface $loader)
{
$this->twig->setLoader($loader);
}
public function getLoader()
{
return $this->twig->getLoader();
}
public function setCharset($charset)
{
$this->twig->setCharset($charset);
}
public function getCharset()
{
return $this->twig->getCharset();
}
public function initRuntime()
{
$this->twig->initRuntime();
}
public function hasExtension($name)
{
return $this->twig->hasExtension($name);
}
public function getExtension($name)
{
return $this->twig->getExtension($name);
}
public function addExtension(Twig_ExtensionInterface $extension)
{
$this->twig->addExtension($extension);
}
public function removeExtension($name)
{
$this->twig->removeExtension($name);
}
public function setExtensions(array $extensions)
{
$this->twig->setExtensions($extensions);
}
public function getExtensions()
{
return $this->twig->getExtensions();
}
public function addTokenParser(Twig_TokenParserInterface $parser)
{
$this->twig->addTokenParser($parser);
}
public function getTokenParsers()
{
return $this->twig->getTokenParsers();
}
public function getTags()
{
return $this->twig->getTags();
}
public function addNodeVisitor(Twig_NodeVisitorInterface $visitor)
{
$this->twig->addNodeVisitor($visitor);
}
public function getNodeVisitors()
{
return $this->twig->getNodeVisitors();
}
public function addFilter($name, $filter = null)
{
$this->twig->addFilter($name, $filter);
}
public function getFilter($name)
{
return $this->twig->getFilter($name);
}
public function registerUndefinedFilterCallback($callable)
{
$this->twig->registerUndefinedFilterCallback($callable);
}
public function getFilters()
{
return $this->twig->getFilters();
}
public function addTest($name, $test = null)
{
$this->twig->addTest($name, $test);
}
public function getTests()
{
return $this->twig->getTests();
}
public function getTest($name)
{
return $this->twig->getTest($name);
}
public function addFunction($name, $function = null)
{
$this->twig->addFunction($name, $function);
}
public function getFunction($name)
{
return $this->twig->getFunction($name);
}
public function registerUndefinedFunctionCallback($callable)
{
$this->twig->registerUndefinedFunctionCallback($callable);
}
public function getFunctions()
{
return $this->twig->getFunctions();
}
public function addGlobal($name, $value)
{
$this->twig->addGlobal($name, $value);
}
public function getGlobals()
{
return $this->twig->getGlobals();
}
public function mergeGlobals(array $context)
{
return $this->twig->mergeGlobals($context);
}
public function getUnaryOperators()
{
return $this->twig->getUnaryOperators();
}
public function getBinaryOperators()
{
return $this->twig->getBinaryOperators();
}
public function computeAlternatives($name, $items)
{
return $this->twig->computeAlternatives($name, $items);
}
}

View File

@@ -0,0 +1,138 @@
<?php
/*
* This file is part of the DebugBar package.
*
* (c) 2013 Maxime Bouroumeau-Fuseau
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace DebugBar\Bridge\Twig;
use Twig_Template;
use Twig_TemplateInterface;
/**
* Wraps a Twig_Template to add profiling features
*
* @deprecated
*/
class TraceableTwigTemplate extends Twig_Template implements Twig_TemplateInterface
{
protected $template;
/**
* @param TraceableTwigEnvironment $env
* @param Twig_Template $template
*/
public function __construct(TraceableTwigEnvironment $env, Twig_Template $template)
{
$this->env = $env;
$this->template = $template;
}
public function __call($name, $arguments)
{
return call_user_func_array(array($this->template, $name), $arguments);
}
public function doDisplay(array $context, array $blocks = array())
{
return $this->template->doDisplay($context, $blocks);
}
public function getTemplateName()
{
return $this->template->getTemplateName();
}
public function getEnvironment()
{
return $this->template->getEnvironment();
}
public function getParent(array $context)
{
return $this->template->getParent($context);
}
public function isTraitable()
{
return $this->template->isTraitable();
}
public function displayParentBlock($name, array $context, array $blocks = array())
{
$this->template->displayParentBlock($name, $context, $blocks);
}
public function displayBlock($name, array $context, array $blocks = array(), $useBlocks = true)
{
$this->template->displayBlock($name, $context, $blocks, $useBlocks);
}
public function renderParentBlock($name, array $context, array $blocks = array())
{
return $this->template->renderParentBlock($name, $context, $blocks);
}
public function renderBlock($name, array $context, array $blocks = array(), $useBlocks = true)
{
return $this->template->renderBlock($name, $context, $blocks, $useBlocks);
}
public function hasBlock($name)
{
return $this->template->hasBlock($name);
}
public function getBlockNames()
{
return $this->template->getBlockNames();
}
public function getBlocks()
{
return $this->template->getBlocks();
}
public function display(array $context, array $blocks = array())
{
$start = microtime(true);
$this->template->display($context, $blocks);
$end = microtime(true);
if ($timeDataCollector = $this->env->getTimeDataCollector()) {
$name = sprintf("twig.render(%s)", $this->template->getTemplateName());
$timeDataCollector->addMeasure($name, $start, $end);
}
$this->env->addRenderedTemplate(array(
'name' => $this->template->getTemplateName(),
'render_time' => $end - $start
));
}
public function render(array $context)
{
$level = ob_get_level();
ob_start();
try {
$this->display($context);
} catch (Exception $e) {
while (ob_get_level() > $level) {
ob_end_clean();
}
throw $e;
}
return ob_get_clean();
}
public static function clearCache()
{
Twig_Template::clearCache();
}
}

View File

@@ -0,0 +1,89 @@
<?php
/*
* This file is part of the DebugBar package.
*
* (c) 2013 Maxime Bouroumeau-Fuseau
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace DebugBar\Bridge\Twig;
use DebugBar\DataCollector\AssetProvider;
use DebugBar\DataCollector\DataCollector;
use DebugBar\DataCollector\Renderable;
/**
* Collects data about rendered templates
*
* http://twig.sensiolabs.org/
*
* Your Twig_Environment object needs to be wrapped in a
* TraceableTwigEnvironment object
*
* <code>
* $env = new TraceableTwigEnvironment(new Twig_Environment($loader));
* $debugbar->addCollector(new TwigCollector($env));
* </code>
*
* @deprecated use DebugBar\Bridge\TwigProfileCollector instead
*/
class TwigCollector extends DataCollector implements Renderable, AssetProvider
{
public function __construct(TraceableTwigEnvironment $twig)
{
$this->twig = $twig;
}
public function collect()
{
$templates = array();
$accuRenderTime = 0;
foreach ($this->twig->getRenderedTemplates() as $tpl) {
$accuRenderTime += $tpl['render_time'];
$templates[] = array(
'name' => $tpl['name'],
'render_time' => $tpl['render_time'],
'render_time_str' => $this->formatDuration($tpl['render_time'])
);
}
return array(
'nb_templates' => count($templates),
'templates' => $templates,
'accumulated_render_time' => $accuRenderTime,
'accumulated_render_time_str' => $this->formatDuration($accuRenderTime)
);
}
public function getName()
{
return 'twig';
}
public function getWidgets()
{
return array(
'twig' => array(
'icon' => 'leaf',
'widget' => 'PhpDebugBar.Widgets.TemplatesWidget',
'map' => 'twig',
'default' => json_encode(array('templates' => array())),
),
'twig:badge' => array(
'map' => 'twig.nb_templates',
'default' => 0
)
);
}
public function getAssets()
{
return array(
'css' => 'widgets/templates/widget.css',
'js' => 'widgets/templates/widget.js'
);
}
}

View File

@@ -0,0 +1,199 @@
<?php
/*
* This file is part of the DebugBar package.
*
* (c) 2017 Tim Riemenschneider
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace DebugBar\Bridge;
use DebugBar\DataCollector\AssetProvider;
use DebugBar\DataCollector\DataCollector;
use DebugBar\DataCollector\Renderable;
/**
* Collects data about rendered templates
*
* http://twig.sensiolabs.org/
*
* A Twig_Extension_Profiler 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_Profiler, \Twig_Profiler_Profile
*
* <code>
* $env = new Twig_Environment($loader); // Or from a PSR11-container
* $profile = new Twig_Profiler_Profile();
* $env->addExtension(new Twig_Extension_Profile($profile));
* $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
{
/**
* @var \Twig_Profiler_Profile
*/
private $profile;
/**
* @var \Twig_LoaderInterface
*/
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 \Twig_Profiler_Profile $profile
* @param \Twig_LoaderInterface|\Twig_Environment $loaderOrEnv
*/
public function __construct(\Twig_Profiler_Profile $profile, $loaderOrEnv = null)
{
$this->profile = $profile;
if ($loaderOrEnv instanceof \Twig_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 array(
'twig' => array(
'icon' => 'leaf',
'widget' => 'PhpDebugBar.Widgets.TemplatesWidget',
'map' => 'twig',
'default' => json_encode(array('templates' => array())),
),
'twig:badge' => array(
'map' => 'twig.badge',
'default' => 0,
),
);
}
/**
* @return array
*/
public function getAssets()
{
return array(
'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 = array();
$this->computeData($this->profile);
return array(
'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(
'/',
array(
$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 \Twig_Profiler_Dumper_Html();
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(\Twig_Profiler_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[] = array(
'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);
}
}
}