Find this useful? Enter your email to receive occasional updates for securing PHP code.
Signing you up...
Thank you for signing up!
PHP Decode
<?php namespace Barryvdh\Debugbar; use Barryvdh\Debugbar\DataCollector\CacheCollector; u..
Decoded Output download
<?php
namespace Barryvdh\Debugbar;
use Barryvdh\Debugbar\DataCollector\CacheCollector;
use Barryvdh\Debugbar\DataCollector\EventCollector;
use Barryvdh\Debugbar\DataCollector\FilesCollector;
use Barryvdh\Debugbar\DataCollector\GateCollector;
use Barryvdh\Debugbar\DataCollector\LaravelCollector;
use Barryvdh\Debugbar\DataCollector\LivewireCollector;
use Barryvdh\Debugbar\DataCollector\LogsCollector;
use Barryvdh\Debugbar\DataCollector\MultiAuthCollector;
use Barryvdh\Debugbar\DataCollector\QueryCollector;
use Barryvdh\Debugbar\DataCollector\SessionCollector;
use Barryvdh\Debugbar\DataCollector\RequestCollector;
use Barryvdh\Debugbar\DataCollector\RouteCollector;
use Barryvdh\Debugbar\DataCollector\ViewCollector;
use Barryvdh\Debugbar\DataFormatter\QueryFormatter;
use Barryvdh\Debugbar\Storage\SocketStorage;
use Barryvdh\Debugbar\Storage\FilesystemStorage;
use Barryvdh\Debugbar\Support\Clockwork\ClockworkCollector;
use DebugBar\Bridge\MonologCollector;
use DebugBar\Bridge\Symfony\SymfonyMailCollector;
use DebugBar\DataCollector\ConfigCollector;
use DebugBar\DataCollector\DataCollectorInterface;
use DebugBar\DataCollector\ExceptionsCollector;
use DebugBar\DataCollector\MemoryCollector;
use DebugBar\DataCollector\MessagesCollector;
use DebugBar\DataCollector\ObjectCountCollector;
use DebugBar\DataCollector\PhpInfoCollector;
use DebugBar\DataCollector\RequestDataCollector;
use DebugBar\DataCollector\TimeDataCollector;
use DebugBar\DebugBar;
use DebugBar\Storage\PdoStorage;
use DebugBar\Storage\RedisStorage;
use Exception;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Mail\Events\MessageSent;
use Illuminate\Session\SessionManager;
use Illuminate\Support\Str;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Mailer\Envelope;
use Symfony\Component\Mailer\SentMessage;
use Symfony\Component\Mailer\Transport\AbstractTransport;
use Symfony\Component\Mime\RawMessage;
use Throwable;
/**
* Debug bar subclass which adds all without Request and with LaravelCollector.
* Rest is added in Service Provider
*
* @method void emergency(...$message)
* @method void alert(...$message)
* @method void critical(...$message)
* @method void error(...$message)
* @method void warning(...$message)
* @method void notice(...$message)
* @method void info(...$message)
* @method void debug(...$message)
* @method void log(...$message)
*/
class LaravelDebugbar extends DebugBar
{
/**
* The Laravel application instance.
*
* @var \Illuminate\Foundation\Application
*/
protected $app;
/**
* Normalized Laravel Version
*
* @var string
*/
protected $version;
/**
* True when booted.
*
* @var bool
*/
protected $booted = false;
/**
* True when enabled, false disabled on null for still unknown
*
* @var bool
*/
protected $enabled = null;
/**
* True when this is a Lumen application
*
* @var bool
*/
protected $is_lumen = false;
protected ?string $editorTemplateLink = null;
protected array $remoteServerReplacements = [];
/**
* @param Application $app
*/
public function __construct($app = null)
{
if (!$app) {
$app = app(); //Fallback when $app is not given
}
$this->app = $app;
$this->version = $app->version();
$this->is_lumen = Str::contains($this->version, 'Lumen');
if ($this->is_lumen) {
$this->version = Str::betweenFirst($app->version(), '(', ')');
}
}
/**
* Enable the Debugbar and boot, if not already booted.
*/
public function enable()
{
$this->enabled = true;
if (!$this->booted) {
$this->boot();
}
}
/**
* Boot the debugbar (add collectors, renderer and listener)
*/
public function boot()
{
if ($this->booted) {
return;
}
/** @var Application $app */
$app = $this->app;
/** @var \Illuminate\Config\Repository $config */
$config = $app['config'];
/** @var \Illuminate\Events\Dispatcher|null $events */
$events = isset($app['events']) ? $app['events'] : null;
$this->editorTemplateLink = $config->get('debugbar.editor') ?: null;
$this->remoteServerReplacements = $this->getRemoteServerReplacements();
// Set custom error handler
if ($config->get('debugbar.error_handler', false)) {
set_error_handler([$this, 'handleError']);
}
$this->selectStorage($this);
if ($this->shouldCollect('phpinfo', true)) {
$this->addCollector(new PhpInfoCollector());
}
if ($this->shouldCollect('messages', true)) {
$this->addCollector(new MessagesCollector());
if ($config->get('debugbar.options.messages.trace', true)) {
$this['messages']->collectFileTrace(true);
}
}
if ($this->shouldCollect('time', true)) {
$startTime = $app['request']->server('REQUEST_TIME_FLOAT');
$this->addCollector(new TimeDataCollector($startTime));
if ($config->get('debugbar.options.time.memory_usage')) {
$this['time']->showMemoryUsage();
}
if (! $this->isLumen() && $startTime) {
$app->booted(
function () use ($startTime) {
$this->addMeasure('Booting', $startTime, microtime(true), [], 'time');
}
);
}
$this->startMeasure('application', 'Application', 'time');
}
if ($this->shouldCollect('memory', true)) {
$this->addCollector(new MemoryCollector());
$this['memory']->setPrecision($config->get('debugbar.options.memory.precision', 0));
if (function_exists('memory_reset_peak_usage') && $config->get('debugbar.options.memory.reset_peak')) {
memory_reset_peak_usage();
}
if ($config->get('debugbar.options.memory.with_baseline')) {
$this['memory']->resetMemoryBaseline();
}
}
if ($this->shouldCollect('exceptions', true)) {
try {
$this->addCollector(new ExceptionsCollector());
$this['exceptions']->setChainExceptions(
$config->get('debugbar.options.exceptions.chain', true)
);
} catch (Exception $e) {
}
}
if ($this->shouldCollect('laravel', false)) {
$this->addCollector(new LaravelCollector($app));
}
if ($this->shouldCollect('default_request', false)) {
$this->addCollector(new RequestDataCollector());
}
if ($this->shouldCollect('events', false) && $events) {
try {
$startTime = $app['request']->server('REQUEST_TIME_FLOAT');
$collectData = $config->get('debugbar.options.events.data', false);
$this->addCollector(new EventCollector($startTime, $collectData));
$events->subscribe($this['event']);
} catch (Exception $e) {
$this->addCollectorException('Cannot add EventCollector', $e);
}
}
if ($this->shouldCollect('views', true) && $events) {
try {
$collectData = $config->get('debugbar.options.views.data', true);
$excludePaths = $config->get('debugbar.options.views.exclude_paths', []);
$group = $config->get('debugbar.options.views.group', true);
$this->addCollector(new ViewCollector($collectData, $excludePaths, $group));
$events->listen(
'composing:*',
function ($event, $params) {
$this['views']->addView($params[0]);
}
);
} catch (Exception $e) {
$this->addCollectorException('Cannot add ViewCollector', $e);
}
}
if (!$this->isLumen() && $this->shouldCollect('route')) {
try {
$this->addCollector($app->make(RouteCollector::class));
} catch (Exception $e) {
$this->addCollectorException('Cannot add RouteCollector', $e);
}
}
if (!$this->isLumen() && $this->shouldCollect('log', true)) {
try {
if ($this->hasCollector('messages')) {
$logger = new MessagesCollector('log');
$this['messages']->aggregate($logger);
$app['log']->listen(
function (\Illuminate\Log\Events\MessageLogged $log) use ($logger) {
try {
$logMessage = (string) $log->message;
if (mb_check_encoding($logMessage, 'UTF-8')) {
$context = $log->context;
$logMessage .= (!empty($context) ? ' ' . json_encode($context, JSON_PRETTY_PRINT) : '');
} else {
$logMessage = "[INVALID UTF-8 DATA]";
}
} catch (Exception $e) {
$logMessage = "[Exception: " . $e->getMessage() . "]";
}
$logger->addMessage(
'[' . date('H:i:s') . '] ' . "LOG.{$log->level}: " . $logMessage,
$log->level,
false
);
}
);
} else {
$this->addCollector(new MonologCollector($this->getMonologLogger()));
}
} catch (Exception $e) {
$this->addCollectorException('Cannot add LogsCollector', $e);
}
}
if ($this->shouldCollect('db', true) && isset($app['db']) && $events) {
if ($this->hasCollector('time') && $config->get('debugbar.options.db.timeline', false)) {
$timeCollector = $this['time'];
} else {
$timeCollector = null;
}
$queryCollector = new QueryCollector($timeCollector);
$queryCollector->setDataFormatter(new QueryFormatter());
$queryCollector->setLimits($config->get('debugbar.options.db.soft_limit'), $config->get('debugbar.options.db.hard_limit'));
$queryCollector->setDurationBackground($config->get('debugbar.options.db.duration_background'));
if ($config->get('debugbar.options.db.with_params')) {
$queryCollector->setRenderSqlWithParams(true);
}
if ($dbBacktrace = $config->get('debugbar.options.db.backtrace')) {
$middleware = ! $this->is_lumen ? $app['router']->getMiddleware() : [];
$queryCollector->setFindSource($dbBacktrace, $middleware);
}
if ($excludePaths = $config->get('debugbar.options.db.backtrace_exclude_paths')) {
$queryCollector->mergeBacktraceExcludePaths($excludePaths);
}
if ($config->get('debugbar.options.db.explain.enabled')) {
$types = $config->get('debugbar.options.db.explain.types');
$queryCollector->setExplainSource(true, $types);
}
if ($config->get('debugbar.options.db.hints', true)) {
$queryCollector->setShowHints(true);
}
if ($config->get('debugbar.options.db.show_copy', false)) {
$queryCollector->setShowCopyButton(true);
}
$this->addCollector($queryCollector);
try {
$events->listen(
function (\Illuminate\Database\Events\QueryExecuted $query) {
if (!app(static::class)->shouldCollect('db', true)) {
return; // Issue 776 : We've turned off collecting after the listener was attached
}
//allow collecting only queries slower than a specified amount of milliseconds
$threshold = app('config')->get('debugbar.options.db.slow_threshold', false);
if (!$threshold || $query->time > $threshold) {
$this['queries']->addQuery($query);
}
}
);
} catch (Exception $e) {
$this->addCollectorException('Cannot listen to Queries', $e);
}
try {
$events->listen(
\Illuminate\Database\Events\TransactionBeginning::class,
function ($transaction) {
$this['queries']->collectTransactionEvent('Begin Transaction', $transaction->connection);
}
);
$events->listen(
\Illuminate\Database\Events\TransactionCommitted::class,
function ($transaction) {
$this['queries']->collectTransactionEvent('Commit Transaction', $transaction->connection);
}
);
$events->listen(
\Illuminate\Database\Events\TransactionRolledBack::class,
function ($transaction) {
$this['queries']->collectTransactionEvent('Rollback Transaction', $transaction->connection);
}
);
$events->listen(
'connection.*.beganTransaction',
function ($event, $params) {
$this['queries']->collectTransactionEvent('Begin Transaction', $params[0]);
}
);
$events->listen(
'connection.*.committed',
function ($event, $params) {
$this['queries']->collectTransactionEvent('Commit Transaction', $params[0]);
}
);
$events->listen(
'connection.*.rollingBack',
function ($event, $params) {
$this['queries']->collectTransactionEvent('Rollback Transaction', $params[0]);
}
);
$events->listen(
function (\Illuminate\Database\Events\ConnectionEstablished $event) {
$this['queries']->collectTransactionEvent('Connection Established', $event->connection);
if (app('config')->get('debugbar.options.db.memory_usage')) {
$event->connection->beforeExecuting(function () {
$this['queries']->startMemoryUsage();
});
}
}
);
} catch (Exception $e) {
$this->addCollectorException('Cannot listen transactions to Queries', $e);
}
}
if ($this->shouldCollect('models', true) && $events) {
try {
$this->addCollector(new ObjectCountCollector('models'));
$events->listen('eloquent.retrieved:*', function ($event, $models) {
foreach (array_filter($models) as $model) {
$this['models']->countClass($model);
}
});
} catch (Exception $e) {
$this->addCollectorException('Cannot add Models Collector', $e);
}
}
if ($this->shouldCollect('livewire', true) && $app->bound('livewire')) {
try {
$this->addCollector($app->make(LivewireCollector::class));
} catch (Exception $e) {
$this->addCollectorException('Cannot add Livewire Collector', $e);
}
}
if ($this->shouldCollect('mail', true) && class_exists('Illuminate\Mail\MailServiceProvider') && $events) {
try {
$mailCollector = new SymfonyMailCollector();
$this->addCollector($mailCollector);
$events->listen(function (MessageSent $event) use ($mailCollector) {
$mailCollector->addSymfonyMessage($event->sent->getSymfonySentMessage());
});
if ($config->get('debugbar.options.mail.show_body') || $config->get('debugbar.options.mail.full_log')) {
$mailCollector->showMessageBody();
}
if ($this->hasCollector('time') && $config->get('debugbar.options.mail.timeline')) {
$transport = $app['mailer']->getSymfonyTransport();
$app['mailer']->setSymfonyTransport(new class ($transport, $this) extends AbstractTransport{
private $originalTransport;
private $laravelDebugbar;
public function __construct($transport, $laravelDebugbar)
{
$this->originalTransport = $transport;
$this->laravelDebugbar = $laravelDebugbar;
}
public function send(RawMessage $message, Envelope $envelope = null): ?SentMessage
{
return $this->laravelDebugbar['time']->measure(
'mail: ' . Str::limit($message->getSubject(), 100),
function () use ($message, $envelope) {
return $this->originalTransport->send($message, $envelope);
},
'mail'
);
}
protected function doSend(SentMessage $message): void
{
}
public function __toString(): string
{
return $this->originalTransport->__toString();
}
});
}
} catch (Exception $e) {
$this->addCollectorException('Cannot add SymfonyMailCollector', $e);
}
}
if ($this->shouldCollect('logs', false)) {
try {
$file = $config->get('debugbar.options.logs.file');
$this->addCollector(new LogsCollector($file));
} catch (Exception $e) {
$this->addCollectorException('Cannot add LogsCollector', $e);
}
}
if ($this->shouldCollect('files', false)) {
$this->addCollector(new FilesCollector($app));
}
if ($this->shouldCollect('auth', false)) {
try {
$guards = $config->get('auth.guards', []);
$this->addCollector(new MultiAuthCollector($app['auth'], $guards));
$this['auth']->setShowName(
$config->get('debugbar.options.auth.show_name')
);
$this['auth']->setShowGuardsData(
$config->get('debugbar.options.auth.show_guards', true)
);
} catch (Exception $e) {
$this->addCollectorException('Cannot add AuthCollector', $e);
}
}
if ($this->shouldCollect('gate', false)) {
try {
$this->addCollector($app->make(GateCollector::class));
} catch (Exception $e) {
$this->addCollectorException('Cannot add GateCollector', $e);
}
}
if ($this->shouldCollect('cache', false) && $events) {
try {
$collectValues = $config->get('debugbar.options.cache.values', true);
$startTime = $app['request']->server('REQUEST_TIME_FLOAT');
$this->addCollector(new CacheCollector($startTime, $collectValues));
$events->subscribe($this['cache']);
} catch (Exception $e) {
$this->addCollectorException('Cannot add CacheCollector', $e);
}
}
if ($this->shouldCollect('jobs', false) && $events) {
try {
$this->addCollector(new ObjectCountCollector('jobs', 'briefcase'));
$events->listen(\Illuminate\Queue\Events\JobQueued::class, function ($event) {
$this['jobs']->countClass($event->job);
});
} catch (Exception $e) {
$this->addCollectorException('Cannot add Jobs Collector', $e);
}
}
$renderer = $this->getJavascriptRenderer();
$renderer->setIncludeVendors($config->get('debugbar.include_vendors', true));
$renderer->setBindAjaxHandlerToFetch($config->get('debugbar.capture_ajax', true));
$renderer->setBindAjaxHandlerToXHR($config->get('debugbar.capture_ajax', true));
$this->booted = true;
}
public function shouldCollect($name, $default = false)
{
return $this->app['config']->get('debugbar.collectors.' . $name, $default);
}
/**
* Adds a data collector
*
* @param DataCollectorInterface $collector
*
* @throws DebugBarException
* @return $this
*/
public function addCollector(DataCollectorInterface $collector)
{
parent::addCollector($collector);
if (method_exists($collector, 'useHtmlVarDumper')) {
$collector->useHtmlVarDumper();
}
if (method_exists($collector, 'setEditorLinkTemplate') && $this->editorTemplateLink) {
$collector->setEditorLinkTemplate($this->editorTemplateLink);
}
if (method_exists($collector, 'addXdebugReplacements') && $this->remoteServerReplacements) {
$collector->addXdebugReplacements($this->remoteServerReplacements);
}
return $this;
}
/**
* Handle silenced errors
*
* @param $level
* @param $message
* @param string $file
* @param int $line
* @param array $context
* @throws \ErrorException
*/
public function handleError($level, $message, $file = '', $line = 0, $context = [])
{
$exception = new \ErrorException($message, 0, $level, $file, $line);
if (error_reporting() & $level) {
throw $exception;
}
$this->addThrowable($exception);
if ($this->hasCollector('messages')) {
$file = $file ? ' on ' . $this['messages']->normalizeFilePath($file) . ":{$line}" : '';
$this['messages']->addMessage($message . $file, 'deprecation');
}
}
/**
* Starts a measure
*
* @param string $name Internal name, used to stop the measure
* @param string $label Public name
* @param string|null $collector
*/
public function startMeasure($name, $label = null, $collector = null)
{
if ($this->hasCollector('time')) {
/** @var \DebugBar\DataCollector\TimeDataCollector */
$time = $this->getCollector('time');
$time->startMeasure($name, $label, $collector);
}
}
/**
* Stops a measure
*
* @param string $name
*/
public function stopMeasure($name)
{
if ($this->hasCollector('time')) {
/** @var \DebugBar\DataCollector\TimeDataCollector $collector */
$collector = $this->getCollector('time');
try {
$collector->stopMeasure($name);
} catch (Exception $e) {
// $this->addThrowable($e);
}
}
}
/**
* Adds an exception to be profiled in the debug bar
*
* @param Exception $e
* @deprecated in favor of addThrowable
*/
public function addException(Exception $e)
{
return $this->addThrowable($e);
}
/**
* Adds an exception to be profiled in the debug bar
*
* @param Throwable $e
*/
public function addThrowable($e)
{
if ($this->hasCollector('exceptions')) {
/** @var \DebugBar\DataCollector\ExceptionsCollector $collector */
$collector = $this->getCollector('exceptions');
$collector->addThrowable($e);
}
}
/**
* Register collector exceptions
*
* @param string $message
* @param Exception $exception
*/
protected function addCollectorException(string $message, Exception $exception)
{
$this->addThrowable(
new Exception(
$message . ' on Laravel Debugbar: ' . $exception->getMessage(),
$exception->getCode(),
$exception
)
);
}
/**
* Returns a JavascriptRenderer for this instance
*
* @param string $baseUrl
* @param string $basePath
* @return JavascriptRenderer
*/
public function getJavascriptRenderer($baseUrl = null, $basePath = null)
{
if ($this->jsRenderer === null) {
$this->jsRenderer = new JavascriptRenderer($this, $baseUrl, $basePath);
}
return $this->jsRenderer;
}
/**
* Modify the response and inject the debugbar (or data in headers)
*
* @param \Symfony\Component\HttpFoundation\Request $request
* @param \Symfony\Component\HttpFoundation\Response $response
* @return \Symfony\Component\HttpFoundation\Response
*/
public function modifyResponse(Request $request, Response $response)
{
/** @var Application $app */
$app = $this->app;
if (!$this->isEnabled() || $this->isDebugbarRequest()) {
return $response;
}
// Show the Http Response Exception in the Debugbar, when available
if (isset($response->exception)) {
$this->addThrowable($response->exception);
}
if ($this->shouldCollect('config', false)) {
try {
$configCollector = new ConfigCollector();
$configCollector->setData($app['config']->all());
$this->addCollector($configCollector);
} catch (Exception $e) {
$this->addCollectorException('Cannot add ConfigCollector', $e);
}
}
$sessionHiddens = $app['config']->get('debugbar.options.session.hiddens', []);
if ($app->bound(SessionManager::class)) {
/** @var \Illuminate\Session\SessionManager $sessionManager */
$sessionManager = $app->make(SessionManager::class);
$httpDriver = new SymfonyHttpDriver($sessionManager, $response);
$this->setHttpDriver($httpDriver);
if ($this->shouldCollect('session') && ! $this->hasCollector('session')) {
try {
$this->addCollector(new SessionCollector($sessionManager, $sessionHiddens));
} catch (Exception $e) {
$this->addCollectorException('Cannot add SessionCollector', $e);
}
}
} else {
$sessionManager = null;
}
$requestHiddens = array_merge(
$app['config']->get('debugbar.options.symfony_request.hiddens', []),
array_map(fn ($key) => 'session_attributes.' . $key, $sessionHiddens)
);
if ($this->shouldCollect('symfony_request', true) && !$this->hasCollector('request')) {
try {
$reqId = $this->getCurrentRequestId();
$this->addCollector(new RequestCollector($request, $response, $sessionManager, $reqId, $requestHiddens));
} catch (Exception $e) {
$this->addCollectorException('Cannot add SymfonyRequestCollector', $e);
}
}
if ($app['config']->get('debugbar.clockwork') && ! $this->hasCollector('clockwork')) {
try {
$this->addCollector(new ClockworkCollector($request, $response, $sessionManager, $requestHiddens));
} catch (Exception $e) {
$this->addCollectorException('Cannot add ClockworkCollector', $e);
}
$this->addClockworkHeaders($response);
}
if ($response->isRedirection()) {
try {
$this->stackData();
} catch (Exception $e) {
$app['log']->error('Debugbar exception: ' . $e->getMessage());
}
} elseif (
$this->isJsonRequest($request) &&
$app['config']->get('debugbar.capture_ajax', true)
) {
try {
if ($this->hasCollector('views') && $response->headers->has('X-Inertia')) {
$content = $response->getContent();
if (is_string($content)) {
$content = json_decode($content, true);
}
if (is_array($content)) {
$this['views']->addInertiaAjaxView($content);
}
}
} catch (Exception $e) {
}
try {
$this->sendDataInHeaders(true);
if ($app['config']->get('debugbar.add_ajax_timing', false)) {
$this->addServerTimingHeaders($response);
}
} catch (Exception $e) {
$app['log']->error('Debugbar exception: ' . $e->getMessage());
}
} elseif (
!$app['config']->get('debugbar.inject', true) ||
($response->headers->has('Content-Type') &&
strpos($response->headers->get('Content-Type'), 'html') === false) ||
$request->getRequestFormat() !== 'html' ||
$response->getContent() === false ||
$this->isJsonRequest($request)
) {
try {
// Just collect + store data, don't inject it.
$this->collect();
} catch (Exception $e) {
$app['log']->error('Debugbar exception: ' . $e->getMessage());
}
} else {
try {
$this->injectDebugbar($response);
} catch (Exception $e) {
$app['log']->error('Debugbar exception: ' . $e->getMessage());
}
}
return $response;
}
/**
* Check if the Debugbar is enabled
* @return boolean
*/
public function isEnabled()
{
if ($this->enabled === null) {
/** @var \Illuminate\Config\Repository $config */
$config = $this->app['config'];
$configEnabled = value($config->get('debugbar.enabled'));
if ($configEnabled === null) {
$configEnabled = $config->get('app.debug');
}
$this->enabled = $configEnabled && !$this->app->runningInConsole() && !$this->app->environment('testing');
}
return $this->enabled;
}
/**
* Check if this is a request to the Debugbar OpenHandler
*
* @return bool
*/
protected function isDebugbarRequest()
{
return $this->app['request']->is($this->app['config']->get('debugbar.route_prefix') . '*');
}
/**
* @param \Symfony\Component\HttpFoundation\Request $request
* @return bool
*/
protected function isJsonRequest(Request $request)
{
// If XmlHttpRequest or Live, return true
if ($request->isXmlHttpRequest() || $request->headers->has('X-Livewire')) {
return true;
}
// Check if the request wants Json
$acceptable = $request->getAcceptableContentTypes();
return (isset($acceptable[0]) && $acceptable[0] == 'application/json');
}
/**
* Collects the data from the collectors
*
* @return array
*/
public function collect()
{
/** @var Request $request */
$request = $this->app['request'];
$this->data = [
'__meta' => [
'id' => $this->getCurrentRequestId(),
'datetime' => date('Y-m-d H:i:s'),
'utime' => microtime(true),
'method' => $request->getMethod(),
'uri' => $request->getRequestUri(),
'ip' => $request->getClientIp()
]
];
foreach ($this->collectors as $name => $collector) {
$this->data[$name] = $collector->collect();
}
// Remove all invalid (non UTF-8) characters
array_walk_recursive(
$this->data,
function (&$item) {
if (is_string($item) && !mb_check_encoding($item, 'UTF-8')) {
$item = mb_convert_encoding($item, 'UTF-8', 'UTF-8');
}
}
);
if ($this->storage !== null) {
$this->storage->save($this->getCurrentRequestId(), $this->data);
}
return $this->data;
}
/**
* Injects the web debug toolbar into the given Response.
*
* @param \Symfony\Component\HttpFoundation\Response $response A Response instance
* Based on https://github.com/symfony/WebProfilerBundle/blob/master/EventListener/WebDebugToolbarListener.php
*/
public function injectDebugbar(Response $response)
{
/** @var \Illuminate\Config\Repository $config */
$config = $this->app['config'];
$content = $response->getContent();
$renderer = $this->getJavascriptRenderer();
$autoShow = $config->get('debugbar.ajax_handler_auto_show', true);
$renderer->setAjaxHandlerAutoShow($autoShow);
$enableTab = $config->get('debugbar.ajax_handler_enable_tab', true);
$renderer->setAjaxHandlerEnableTab($enableTab);
if ($this->getStorage()) {
$openHandlerUrl = route('debugbar.openhandler');
$renderer->setOpenHandlerUrl($openHandlerUrl);
}
$head = $renderer->renderHead();
$widget = $renderer->render();
// Try to put the js/css directly before the </head>
$pos = stripos($content, '</head>');
if (false !== $pos) {
$content = substr($content, 0, $pos) . $head . substr($content, $pos);
} else {
// Append the head before the widget
$widget = $head . $widget;
}
// Try to put the widget at the end, directly before the </body>
$pos = strripos($content, '</body>');
if (false !== $pos) {
$content = substr($content, 0, $pos) . $widget . substr($content, $pos);
} else {
$content = $content . $widget;
}
$original = null;
if ($response instanceof \Illuminate\Http\Response && $response->getOriginalContent()) {
$original = $response->getOriginalContent();
}
// Update the new content and reset the content length
$response->setContent($content);
$response->headers->remove('Content-Length');
// Restore original response (e.g. the View or Ajax data)
if ($original) {
$response->original = $original;
}
}
/**
* Disable the Debugbar
*/
public function disable()
{
$this->enabled = false;
}
/**
* Adds a measure
*
* @param string $label
* @param float $start
* @param float $end
* @param array|null $params
* @param string|null $collector
*/
public function addMeasure($label, $start, $end, $params = [], $collector = null)
{
if ($this->hasCollector('time')) {
/** @var \DebugBar\DataCollector\TimeDataCollector */
$time = $this->getCollector('time');
$time->addMeasure($label, $start, $end, $params, $collector);
}
}
/**
* Utility function to measure the execution of a Closure
*
* @param string $label
* @param \Closure $closure
* @param string|null $collector
* @return mixed
*/
public function measure($label, \Closure $closure, $collector = null)
{
if ($this->hasCollector('time')) {
/** @var \DebugBar\DataCollector\TimeDataCollector */
$time = $this->getCollector('time');
$result = $time->measure($label, $closure, $collector);
} else {
$result = $closure();
}
return $result;
}
/**
* Collect data in a CLI request
*
* @return array
*/
public function collectConsole()
{
if (!$this->isEnabled()) {
return;
}
$this->data = [
'__meta' => [
'id' => $this->getCurrentRequestId(),
'datetime' => date('Y-m-d H:i:s'),
'utime' => microtime(true),
'method' => 'CLI',
'uri' => isset($_SERVER['argv']) ? implode(' ', $_SERVER['argv']) : null,
'ip' => isset($_SERVER['SSH_CLIENT']) ? $_SERVER['SSH_CLIENT'] : null
]
];
foreach ($this->collectors as $name => $collector) {
$this->data[$name] = $collector->collect();
}
// Remove all invalid (non UTF-8) characters
array_walk_recursive(
$this->data,
function (&$item) {
if (is_string($item) && !mb_check_encoding($item, 'UTF-8')) {
$item = mb_convert_encoding($item, 'UTF-8', 'UTF-8');
}
}
);
if ($this->storage !== null) {
$this->storage->save($this->getCurrentRequestId(), $this->data);
}
return $this->data;
}
/**
* Magic calls for adding messages
*
* @param string $method
* @param array $args
* @return mixed|void
*/
public function __call($method, $args)
{
$messageLevels = ['emergency', 'alert', 'critical', 'error', 'warning', 'notice', 'info', 'debug', 'log'];
if (in_array($method, $messageLevels)) {
foreach ($args as $arg) {
$this->addMessage($arg, $method);
}
}
}
/**
* Adds a message to the MessagesCollector
*
* A message can be anything from an object to a string
*
* @param mixed $message
* @param string $label
*/
public function addMessage($message, $label = 'info')
{
if ($this->hasCollector('messages')) {
/** @var \DebugBar\DataCollector\MessagesCollector $collector */
$collector = $this->getCollector('messages');
$collector->addMessage($message, $label);
}
}
/**
* Check the version of Laravel
*
* @param string $version
* @param string $operator (default: '>=')
* @return boolean
*/
protected function checkVersion($version, $operator = ">=")
{
return version_compare($this->version, $version, $operator);
}
protected function isLumen()
{
return $this->is_lumen;
}
/**
* @param DebugBar $debugbar
*/
protected function selectStorage(DebugBar $debugbar)
{
/** @var \Illuminate\Config\Repository $config */
$config = $this->app['config'];
if ($config->get('debugbar.storage.enabled')) {
$driver = $config->get('debugbar.storage.driver', 'file');
switch ($driver) {
case 'pdo':
$connection = $config->get('debugbar.storage.connection');
$table = $this->app['db']->getTablePrefix() . 'phpdebugbar';
$pdo = $this->app['db']->connection($connection)->getPdo();
$storage = new PdoStorage($pdo, $table);
break;
case 'redis':
$connection = $config->get('debugbar.storage.connection');
$client = $this->app['redis']->connection($connection);
if (is_a($client, 'Illuminate\Redis\Connections\Connection', false)) {
$client = $client->client();
}
$storage = new RedisStorage($client);
break;
case 'custom':
$class = $config->get('debugbar.storage.provider');
$storage = $this->app->make($class);
break;
case 'socket':
$hostname = $config->get('debugbar.storage.hostname', '127.0.0.1');
$port = $config->get('debugbar.storage.port', 2304);
$storage = new SocketStorage($hostname, $port);
break;
case 'file':
default:
$path = $config->get('debugbar.storage.path');
$storage = new FilesystemStorage($this->app['files'], $path);
break;
}
$debugbar->setStorage($storage);
}
}
protected function addClockworkHeaders(Response $response)
{
$prefix = $this->app['config']->get('debugbar.route_prefix');
$response->headers->set('X-Clockwork-Id', $this->getCurrentRequestId(), true);
$response->headers->set('X-Clockwork-Version', 9, true);
$response->headers->set('X-Clockwork-Path', $prefix . '/clockwork/', true);
}
/**
* Add Server-Timing headers for the TimeData collector
*
* @see https://www.w3.org/TR/server-timing/
* @param Response $response
*/
protected function addServerTimingHeaders(Response $response)
{
if ($this->hasCollector('time')) {
$collector = $this->getCollector('time');
$headers = [];
foreach ($collector->collect()['measures'] as $m) {
$headers[] = sprintf('app;desc="%s";dur=%F', str_replace(array("
", "
"), ' ', str_replace('"', "'", $m['label'])), $m['duration'] * 1000);
}
$response->headers->set('Server-Timing', $headers, false);
}
}
/**
* @return array
*/
private function getRemoteServerReplacements()
{
$localPath = $this->app['config']->get('debugbar.local_sites_path') ?: base_path();
$remotePaths = array_filter(explode(',', $this->app['config']->get('debugbar.remote_sites_path') ?: '')) ?: [base_path()];
return array_fill_keys($remotePaths, $localPath);
}
/**
* @return \Monolog\Logger
* @throws Exception
*/
private function getMonologLogger()
{
$logger = $this->app['log']->getLogger();
if (get_class($logger) !== 'Monolog\Logger') {
throw new Exception('Logger is not a Monolog\Logger instance');
}
return $logger;
}
}
?>
Did this file decode correctly?
Original Code
<?php
namespace Barryvdh\Debugbar;
use Barryvdh\Debugbar\DataCollector\CacheCollector;
use Barryvdh\Debugbar\DataCollector\EventCollector;
use Barryvdh\Debugbar\DataCollector\FilesCollector;
use Barryvdh\Debugbar\DataCollector\GateCollector;
use Barryvdh\Debugbar\DataCollector\LaravelCollector;
use Barryvdh\Debugbar\DataCollector\LivewireCollector;
use Barryvdh\Debugbar\DataCollector\LogsCollector;
use Barryvdh\Debugbar\DataCollector\MultiAuthCollector;
use Barryvdh\Debugbar\DataCollector\QueryCollector;
use Barryvdh\Debugbar\DataCollector\SessionCollector;
use Barryvdh\Debugbar\DataCollector\RequestCollector;
use Barryvdh\Debugbar\DataCollector\RouteCollector;
use Barryvdh\Debugbar\DataCollector\ViewCollector;
use Barryvdh\Debugbar\DataFormatter\QueryFormatter;
use Barryvdh\Debugbar\Storage\SocketStorage;
use Barryvdh\Debugbar\Storage\FilesystemStorage;
use Barryvdh\Debugbar\Support\Clockwork\ClockworkCollector;
use DebugBar\Bridge\MonologCollector;
use DebugBar\Bridge\Symfony\SymfonyMailCollector;
use DebugBar\DataCollector\ConfigCollector;
use DebugBar\DataCollector\DataCollectorInterface;
use DebugBar\DataCollector\ExceptionsCollector;
use DebugBar\DataCollector\MemoryCollector;
use DebugBar\DataCollector\MessagesCollector;
use DebugBar\DataCollector\ObjectCountCollector;
use DebugBar\DataCollector\PhpInfoCollector;
use DebugBar\DataCollector\RequestDataCollector;
use DebugBar\DataCollector\TimeDataCollector;
use DebugBar\DebugBar;
use DebugBar\Storage\PdoStorage;
use DebugBar\Storage\RedisStorage;
use Exception;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Mail\Events\MessageSent;
use Illuminate\Session\SessionManager;
use Illuminate\Support\Str;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Mailer\Envelope;
use Symfony\Component\Mailer\SentMessage;
use Symfony\Component\Mailer\Transport\AbstractTransport;
use Symfony\Component\Mime\RawMessage;
use Throwable;
/**
* Debug bar subclass which adds all without Request and with LaravelCollector.
* Rest is added in Service Provider
*
* @method void emergency(...$message)
* @method void alert(...$message)
* @method void critical(...$message)
* @method void error(...$message)
* @method void warning(...$message)
* @method void notice(...$message)
* @method void info(...$message)
* @method void debug(...$message)
* @method void log(...$message)
*/
class LaravelDebugbar extends DebugBar
{
/**
* The Laravel application instance.
*
* @var \Illuminate\Foundation\Application
*/
protected $app;
/**
* Normalized Laravel Version
*
* @var string
*/
protected $version;
/**
* True when booted.
*
* @var bool
*/
protected $booted = false;
/**
* True when enabled, false disabled on null for still unknown
*
* @var bool
*/
protected $enabled = null;
/**
* True when this is a Lumen application
*
* @var bool
*/
protected $is_lumen = false;
protected ?string $editorTemplateLink = null;
protected array $remoteServerReplacements = [];
/**
* @param Application $app
*/
public function __construct($app = null)
{
if (!$app) {
$app = app(); //Fallback when $app is not given
}
$this->app = $app;
$this->version = $app->version();
$this->is_lumen = Str::contains($this->version, 'Lumen');
if ($this->is_lumen) {
$this->version = Str::betweenFirst($app->version(), '(', ')');
}
}
/**
* Enable the Debugbar and boot, if not already booted.
*/
public function enable()
{
$this->enabled = true;
if (!$this->booted) {
$this->boot();
}
}
/**
* Boot the debugbar (add collectors, renderer and listener)
*/
public function boot()
{
if ($this->booted) {
return;
}
/** @var Application $app */
$app = $this->app;
/** @var \Illuminate\Config\Repository $config */
$config = $app['config'];
/** @var \Illuminate\Events\Dispatcher|null $events */
$events = isset($app['events']) ? $app['events'] : null;
$this->editorTemplateLink = $config->get('debugbar.editor') ?: null;
$this->remoteServerReplacements = $this->getRemoteServerReplacements();
// Set custom error handler
if ($config->get('debugbar.error_handler', false)) {
set_error_handler([$this, 'handleError']);
}
$this->selectStorage($this);
if ($this->shouldCollect('phpinfo', true)) {
$this->addCollector(new PhpInfoCollector());
}
if ($this->shouldCollect('messages', true)) {
$this->addCollector(new MessagesCollector());
if ($config->get('debugbar.options.messages.trace', true)) {
$this['messages']->collectFileTrace(true);
}
}
if ($this->shouldCollect('time', true)) {
$startTime = $app['request']->server('REQUEST_TIME_FLOAT');
$this->addCollector(new TimeDataCollector($startTime));
if ($config->get('debugbar.options.time.memory_usage')) {
$this['time']->showMemoryUsage();
}
if (! $this->isLumen() && $startTime) {
$app->booted(
function () use ($startTime) {
$this->addMeasure('Booting', $startTime, microtime(true), [], 'time');
}
);
}
$this->startMeasure('application', 'Application', 'time');
}
if ($this->shouldCollect('memory', true)) {
$this->addCollector(new MemoryCollector());
$this['memory']->setPrecision($config->get('debugbar.options.memory.precision', 0));
if (function_exists('memory_reset_peak_usage') && $config->get('debugbar.options.memory.reset_peak')) {
memory_reset_peak_usage();
}
if ($config->get('debugbar.options.memory.with_baseline')) {
$this['memory']->resetMemoryBaseline();
}
}
if ($this->shouldCollect('exceptions', true)) {
try {
$this->addCollector(new ExceptionsCollector());
$this['exceptions']->setChainExceptions(
$config->get('debugbar.options.exceptions.chain', true)
);
} catch (Exception $e) {
}
}
if ($this->shouldCollect('laravel', false)) {
$this->addCollector(new LaravelCollector($app));
}
if ($this->shouldCollect('default_request', false)) {
$this->addCollector(new RequestDataCollector());
}
if ($this->shouldCollect('events', false) && $events) {
try {
$startTime = $app['request']->server('REQUEST_TIME_FLOAT');
$collectData = $config->get('debugbar.options.events.data', false);
$this->addCollector(new EventCollector($startTime, $collectData));
$events->subscribe($this['event']);
} catch (Exception $e) {
$this->addCollectorException('Cannot add EventCollector', $e);
}
}
if ($this->shouldCollect('views', true) && $events) {
try {
$collectData = $config->get('debugbar.options.views.data', true);
$excludePaths = $config->get('debugbar.options.views.exclude_paths', []);
$group = $config->get('debugbar.options.views.group', true);
$this->addCollector(new ViewCollector($collectData, $excludePaths, $group));
$events->listen(
'composing:*',
function ($event, $params) {
$this['views']->addView($params[0]);
}
);
} catch (Exception $e) {
$this->addCollectorException('Cannot add ViewCollector', $e);
}
}
if (!$this->isLumen() && $this->shouldCollect('route')) {
try {
$this->addCollector($app->make(RouteCollector::class));
} catch (Exception $e) {
$this->addCollectorException('Cannot add RouteCollector', $e);
}
}
if (!$this->isLumen() && $this->shouldCollect('log', true)) {
try {
if ($this->hasCollector('messages')) {
$logger = new MessagesCollector('log');
$this['messages']->aggregate($logger);
$app['log']->listen(
function (\Illuminate\Log\Events\MessageLogged $log) use ($logger) {
try {
$logMessage = (string) $log->message;
if (mb_check_encoding($logMessage, 'UTF-8')) {
$context = $log->context;
$logMessage .= (!empty($context) ? ' ' . json_encode($context, JSON_PRETTY_PRINT) : '');
} else {
$logMessage = "[INVALID UTF-8 DATA]";
}
} catch (Exception $e) {
$logMessage = "[Exception: " . $e->getMessage() . "]";
}
$logger->addMessage(
'[' . date('H:i:s') . '] ' . "LOG.{$log->level}: " . $logMessage,
$log->level,
false
);
}
);
} else {
$this->addCollector(new MonologCollector($this->getMonologLogger()));
}
} catch (Exception $e) {
$this->addCollectorException('Cannot add LogsCollector', $e);
}
}
if ($this->shouldCollect('db', true) && isset($app['db']) && $events) {
if ($this->hasCollector('time') && $config->get('debugbar.options.db.timeline', false)) {
$timeCollector = $this['time'];
} else {
$timeCollector = null;
}
$queryCollector = new QueryCollector($timeCollector);
$queryCollector->setDataFormatter(new QueryFormatter());
$queryCollector->setLimits($config->get('debugbar.options.db.soft_limit'), $config->get('debugbar.options.db.hard_limit'));
$queryCollector->setDurationBackground($config->get('debugbar.options.db.duration_background'));
if ($config->get('debugbar.options.db.with_params')) {
$queryCollector->setRenderSqlWithParams(true);
}
if ($dbBacktrace = $config->get('debugbar.options.db.backtrace')) {
$middleware = ! $this->is_lumen ? $app['router']->getMiddleware() : [];
$queryCollector->setFindSource($dbBacktrace, $middleware);
}
if ($excludePaths = $config->get('debugbar.options.db.backtrace_exclude_paths')) {
$queryCollector->mergeBacktraceExcludePaths($excludePaths);
}
if ($config->get('debugbar.options.db.explain.enabled')) {
$types = $config->get('debugbar.options.db.explain.types');
$queryCollector->setExplainSource(true, $types);
}
if ($config->get('debugbar.options.db.hints', true)) {
$queryCollector->setShowHints(true);
}
if ($config->get('debugbar.options.db.show_copy', false)) {
$queryCollector->setShowCopyButton(true);
}
$this->addCollector($queryCollector);
try {
$events->listen(
function (\Illuminate\Database\Events\QueryExecuted $query) {
if (!app(static::class)->shouldCollect('db', true)) {
return; // Issue 776 : We've turned off collecting after the listener was attached
}
//allow collecting only queries slower than a specified amount of milliseconds
$threshold = app('config')->get('debugbar.options.db.slow_threshold', false);
if (!$threshold || $query->time > $threshold) {
$this['queries']->addQuery($query);
}
}
);
} catch (Exception $e) {
$this->addCollectorException('Cannot listen to Queries', $e);
}
try {
$events->listen(
\Illuminate\Database\Events\TransactionBeginning::class,
function ($transaction) {
$this['queries']->collectTransactionEvent('Begin Transaction', $transaction->connection);
}
);
$events->listen(
\Illuminate\Database\Events\TransactionCommitted::class,
function ($transaction) {
$this['queries']->collectTransactionEvent('Commit Transaction', $transaction->connection);
}
);
$events->listen(
\Illuminate\Database\Events\TransactionRolledBack::class,
function ($transaction) {
$this['queries']->collectTransactionEvent('Rollback Transaction', $transaction->connection);
}
);
$events->listen(
'connection.*.beganTransaction',
function ($event, $params) {
$this['queries']->collectTransactionEvent('Begin Transaction', $params[0]);
}
);
$events->listen(
'connection.*.committed',
function ($event, $params) {
$this['queries']->collectTransactionEvent('Commit Transaction', $params[0]);
}
);
$events->listen(
'connection.*.rollingBack',
function ($event, $params) {
$this['queries']->collectTransactionEvent('Rollback Transaction', $params[0]);
}
);
$events->listen(
function (\Illuminate\Database\Events\ConnectionEstablished $event) {
$this['queries']->collectTransactionEvent('Connection Established', $event->connection);
if (app('config')->get('debugbar.options.db.memory_usage')) {
$event->connection->beforeExecuting(function () {
$this['queries']->startMemoryUsage();
});
}
}
);
} catch (Exception $e) {
$this->addCollectorException('Cannot listen transactions to Queries', $e);
}
}
if ($this->shouldCollect('models', true) && $events) {
try {
$this->addCollector(new ObjectCountCollector('models'));
$events->listen('eloquent.retrieved:*', function ($event, $models) {
foreach (array_filter($models) as $model) {
$this['models']->countClass($model);
}
});
} catch (Exception $e) {
$this->addCollectorException('Cannot add Models Collector', $e);
}
}
if ($this->shouldCollect('livewire', true) && $app->bound('livewire')) {
try {
$this->addCollector($app->make(LivewireCollector::class));
} catch (Exception $e) {
$this->addCollectorException('Cannot add Livewire Collector', $e);
}
}
if ($this->shouldCollect('mail', true) && class_exists('Illuminate\Mail\MailServiceProvider') && $events) {
try {
$mailCollector = new SymfonyMailCollector();
$this->addCollector($mailCollector);
$events->listen(function (MessageSent $event) use ($mailCollector) {
$mailCollector->addSymfonyMessage($event->sent->getSymfonySentMessage());
});
if ($config->get('debugbar.options.mail.show_body') || $config->get('debugbar.options.mail.full_log')) {
$mailCollector->showMessageBody();
}
if ($this->hasCollector('time') && $config->get('debugbar.options.mail.timeline')) {
$transport = $app['mailer']->getSymfonyTransport();
$app['mailer']->setSymfonyTransport(new class ($transport, $this) extends AbstractTransport{
private $originalTransport;
private $laravelDebugbar;
public function __construct($transport, $laravelDebugbar)
{
$this->originalTransport = $transport;
$this->laravelDebugbar = $laravelDebugbar;
}
public function send(RawMessage $message, Envelope $envelope = null): ?SentMessage
{
return $this->laravelDebugbar['time']->measure(
'mail: ' . Str::limit($message->getSubject(), 100),
function () use ($message, $envelope) {
return $this->originalTransport->send($message, $envelope);
},
'mail'
);
}
protected function doSend(SentMessage $message): void
{
}
public function __toString(): string
{
return $this->originalTransport->__toString();
}
});
}
} catch (Exception $e) {
$this->addCollectorException('Cannot add SymfonyMailCollector', $e);
}
}
if ($this->shouldCollect('logs', false)) {
try {
$file = $config->get('debugbar.options.logs.file');
$this->addCollector(new LogsCollector($file));
} catch (Exception $e) {
$this->addCollectorException('Cannot add LogsCollector', $e);
}
}
if ($this->shouldCollect('files', false)) {
$this->addCollector(new FilesCollector($app));
}
if ($this->shouldCollect('auth', false)) {
try {
$guards = $config->get('auth.guards', []);
$this->addCollector(new MultiAuthCollector($app['auth'], $guards));
$this['auth']->setShowName(
$config->get('debugbar.options.auth.show_name')
);
$this['auth']->setShowGuardsData(
$config->get('debugbar.options.auth.show_guards', true)
);
} catch (Exception $e) {
$this->addCollectorException('Cannot add AuthCollector', $e);
}
}
if ($this->shouldCollect('gate', false)) {
try {
$this->addCollector($app->make(GateCollector::class));
} catch (Exception $e) {
$this->addCollectorException('Cannot add GateCollector', $e);
}
}
if ($this->shouldCollect('cache', false) && $events) {
try {
$collectValues = $config->get('debugbar.options.cache.values', true);
$startTime = $app['request']->server('REQUEST_TIME_FLOAT');
$this->addCollector(new CacheCollector($startTime, $collectValues));
$events->subscribe($this['cache']);
} catch (Exception $e) {
$this->addCollectorException('Cannot add CacheCollector', $e);
}
}
if ($this->shouldCollect('jobs', false) && $events) {
try {
$this->addCollector(new ObjectCountCollector('jobs', 'briefcase'));
$events->listen(\Illuminate\Queue\Events\JobQueued::class, function ($event) {
$this['jobs']->countClass($event->job);
});
} catch (Exception $e) {
$this->addCollectorException('Cannot add Jobs Collector', $e);
}
}
$renderer = $this->getJavascriptRenderer();
$renderer->setIncludeVendors($config->get('debugbar.include_vendors', true));
$renderer->setBindAjaxHandlerToFetch($config->get('debugbar.capture_ajax', true));
$renderer->setBindAjaxHandlerToXHR($config->get('debugbar.capture_ajax', true));
$this->booted = true;
}
public function shouldCollect($name, $default = false)
{
return $this->app['config']->get('debugbar.collectors.' . $name, $default);
}
/**
* Adds a data collector
*
* @param DataCollectorInterface $collector
*
* @throws DebugBarException
* @return $this
*/
public function addCollector(DataCollectorInterface $collector)
{
parent::addCollector($collector);
if (method_exists($collector, 'useHtmlVarDumper')) {
$collector->useHtmlVarDumper();
}
if (method_exists($collector, 'setEditorLinkTemplate') && $this->editorTemplateLink) {
$collector->setEditorLinkTemplate($this->editorTemplateLink);
}
if (method_exists($collector, 'addXdebugReplacements') && $this->remoteServerReplacements) {
$collector->addXdebugReplacements($this->remoteServerReplacements);
}
return $this;
}
/**
* Handle silenced errors
*
* @param $level
* @param $message
* @param string $file
* @param int $line
* @param array $context
* @throws \ErrorException
*/
public function handleError($level, $message, $file = '', $line = 0, $context = [])
{
$exception = new \ErrorException($message, 0, $level, $file, $line);
if (error_reporting() & $level) {
throw $exception;
}
$this->addThrowable($exception);
if ($this->hasCollector('messages')) {
$file = $file ? ' on ' . $this['messages']->normalizeFilePath($file) . ":{$line}" : '';
$this['messages']->addMessage($message . $file, 'deprecation');
}
}
/**
* Starts a measure
*
* @param string $name Internal name, used to stop the measure
* @param string $label Public name
* @param string|null $collector
*/
public function startMeasure($name, $label = null, $collector = null)
{
if ($this->hasCollector('time')) {
/** @var \DebugBar\DataCollector\TimeDataCollector */
$time = $this->getCollector('time');
$time->startMeasure($name, $label, $collector);
}
}
/**
* Stops a measure
*
* @param string $name
*/
public function stopMeasure($name)
{
if ($this->hasCollector('time')) {
/** @var \DebugBar\DataCollector\TimeDataCollector $collector */
$collector = $this->getCollector('time');
try {
$collector->stopMeasure($name);
} catch (Exception $e) {
// $this->addThrowable($e);
}
}
}
/**
* Adds an exception to be profiled in the debug bar
*
* @param Exception $e
* @deprecated in favor of addThrowable
*/
public function addException(Exception $e)
{
return $this->addThrowable($e);
}
/**
* Adds an exception to be profiled in the debug bar
*
* @param Throwable $e
*/
public function addThrowable($e)
{
if ($this->hasCollector('exceptions')) {
/** @var \DebugBar\DataCollector\ExceptionsCollector $collector */
$collector = $this->getCollector('exceptions');
$collector->addThrowable($e);
}
}
/**
* Register collector exceptions
*
* @param string $message
* @param Exception $exception
*/
protected function addCollectorException(string $message, Exception $exception)
{
$this->addThrowable(
new Exception(
$message . ' on Laravel Debugbar: ' . $exception->getMessage(),
$exception->getCode(),
$exception
)
);
}
/**
* Returns a JavascriptRenderer for this instance
*
* @param string $baseUrl
* @param string $basePath
* @return JavascriptRenderer
*/
public function getJavascriptRenderer($baseUrl = null, $basePath = null)
{
if ($this->jsRenderer === null) {
$this->jsRenderer = new JavascriptRenderer($this, $baseUrl, $basePath);
}
return $this->jsRenderer;
}
/**
* Modify the response and inject the debugbar (or data in headers)
*
* @param \Symfony\Component\HttpFoundation\Request $request
* @param \Symfony\Component\HttpFoundation\Response $response
* @return \Symfony\Component\HttpFoundation\Response
*/
public function modifyResponse(Request $request, Response $response)
{
/** @var Application $app */
$app = $this->app;
if (!$this->isEnabled() || $this->isDebugbarRequest()) {
return $response;
}
// Show the Http Response Exception in the Debugbar, when available
if (isset($response->exception)) {
$this->addThrowable($response->exception);
}
if ($this->shouldCollect('config', false)) {
try {
$configCollector = new ConfigCollector();
$configCollector->setData($app['config']->all());
$this->addCollector($configCollector);
} catch (Exception $e) {
$this->addCollectorException('Cannot add ConfigCollector', $e);
}
}
$sessionHiddens = $app['config']->get('debugbar.options.session.hiddens', []);
if ($app->bound(SessionManager::class)) {
/** @var \Illuminate\Session\SessionManager $sessionManager */
$sessionManager = $app->make(SessionManager::class);
$httpDriver = new SymfonyHttpDriver($sessionManager, $response);
$this->setHttpDriver($httpDriver);
if ($this->shouldCollect('session') && ! $this->hasCollector('session')) {
try {
$this->addCollector(new SessionCollector($sessionManager, $sessionHiddens));
} catch (Exception $e) {
$this->addCollectorException('Cannot add SessionCollector', $e);
}
}
} else {
$sessionManager = null;
}
$requestHiddens = array_merge(
$app['config']->get('debugbar.options.symfony_request.hiddens', []),
array_map(fn ($key) => 'session_attributes.' . $key, $sessionHiddens)
);
if ($this->shouldCollect('symfony_request', true) && !$this->hasCollector('request')) {
try {
$reqId = $this->getCurrentRequestId();
$this->addCollector(new RequestCollector($request, $response, $sessionManager, $reqId, $requestHiddens));
} catch (Exception $e) {
$this->addCollectorException('Cannot add SymfonyRequestCollector', $e);
}
}
if ($app['config']->get('debugbar.clockwork') && ! $this->hasCollector('clockwork')) {
try {
$this->addCollector(new ClockworkCollector($request, $response, $sessionManager, $requestHiddens));
} catch (Exception $e) {
$this->addCollectorException('Cannot add ClockworkCollector', $e);
}
$this->addClockworkHeaders($response);
}
if ($response->isRedirection()) {
try {
$this->stackData();
} catch (Exception $e) {
$app['log']->error('Debugbar exception: ' . $e->getMessage());
}
} elseif (
$this->isJsonRequest($request) &&
$app['config']->get('debugbar.capture_ajax', true)
) {
try {
if ($this->hasCollector('views') && $response->headers->has('X-Inertia')) {
$content = $response->getContent();
if (is_string($content)) {
$content = json_decode($content, true);
}
if (is_array($content)) {
$this['views']->addInertiaAjaxView($content);
}
}
} catch (Exception $e) {
}
try {
$this->sendDataInHeaders(true);
if ($app['config']->get('debugbar.add_ajax_timing', false)) {
$this->addServerTimingHeaders($response);
}
} catch (Exception $e) {
$app['log']->error('Debugbar exception: ' . $e->getMessage());
}
} elseif (
!$app['config']->get('debugbar.inject', true) ||
($response->headers->has('Content-Type') &&
strpos($response->headers->get('Content-Type'), 'html') === false) ||
$request->getRequestFormat() !== 'html' ||
$response->getContent() === false ||
$this->isJsonRequest($request)
) {
try {
// Just collect + store data, don't inject it.
$this->collect();
} catch (Exception $e) {
$app['log']->error('Debugbar exception: ' . $e->getMessage());
}
} else {
try {
$this->injectDebugbar($response);
} catch (Exception $e) {
$app['log']->error('Debugbar exception: ' . $e->getMessage());
}
}
return $response;
}
/**
* Check if the Debugbar is enabled
* @return boolean
*/
public function isEnabled()
{
if ($this->enabled === null) {
/** @var \Illuminate\Config\Repository $config */
$config = $this->app['config'];
$configEnabled = value($config->get('debugbar.enabled'));
if ($configEnabled === null) {
$configEnabled = $config->get('app.debug');
}
$this->enabled = $configEnabled && !$this->app->runningInConsole() && !$this->app->environment('testing');
}
return $this->enabled;
}
/**
* Check if this is a request to the Debugbar OpenHandler
*
* @return bool
*/
protected function isDebugbarRequest()
{
return $this->app['request']->is($this->app['config']->get('debugbar.route_prefix') . '*');
}
/**
* @param \Symfony\Component\HttpFoundation\Request $request
* @return bool
*/
protected function isJsonRequest(Request $request)
{
// If XmlHttpRequest or Live, return true
if ($request->isXmlHttpRequest() || $request->headers->has('X-Livewire')) {
return true;
}
// Check if the request wants Json
$acceptable = $request->getAcceptableContentTypes();
return (isset($acceptable[0]) && $acceptable[0] == 'application/json');
}
/**
* Collects the data from the collectors
*
* @return array
*/
public function collect()
{
/** @var Request $request */
$request = $this->app['request'];
$this->data = [
'__meta' => [
'id' => $this->getCurrentRequestId(),
'datetime' => date('Y-m-d H:i:s'),
'utime' => microtime(true),
'method' => $request->getMethod(),
'uri' => $request->getRequestUri(),
'ip' => $request->getClientIp()
]
];
foreach ($this->collectors as $name => $collector) {
$this->data[$name] = $collector->collect();
}
// Remove all invalid (non UTF-8) characters
array_walk_recursive(
$this->data,
function (&$item) {
if (is_string($item) && !mb_check_encoding($item, 'UTF-8')) {
$item = mb_convert_encoding($item, 'UTF-8', 'UTF-8');
}
}
);
if ($this->storage !== null) {
$this->storage->save($this->getCurrentRequestId(), $this->data);
}
return $this->data;
}
/**
* Injects the web debug toolbar into the given Response.
*
* @param \Symfony\Component\HttpFoundation\Response $response A Response instance
* Based on https://github.com/symfony/WebProfilerBundle/blob/master/EventListener/WebDebugToolbarListener.php
*/
public function injectDebugbar(Response $response)
{
/** @var \Illuminate\Config\Repository $config */
$config = $this->app['config'];
$content = $response->getContent();
$renderer = $this->getJavascriptRenderer();
$autoShow = $config->get('debugbar.ajax_handler_auto_show', true);
$renderer->setAjaxHandlerAutoShow($autoShow);
$enableTab = $config->get('debugbar.ajax_handler_enable_tab', true);
$renderer->setAjaxHandlerEnableTab($enableTab);
if ($this->getStorage()) {
$openHandlerUrl = route('debugbar.openhandler');
$renderer->setOpenHandlerUrl($openHandlerUrl);
}
$head = $renderer->renderHead();
$widget = $renderer->render();
// Try to put the js/css directly before the </head>
$pos = stripos($content, '</head>');
if (false !== $pos) {
$content = substr($content, 0, $pos) . $head . substr($content, $pos);
} else {
// Append the head before the widget
$widget = $head . $widget;
}
// Try to put the widget at the end, directly before the </body>
$pos = strripos($content, '</body>');
if (false !== $pos) {
$content = substr($content, 0, $pos) . $widget . substr($content, $pos);
} else {
$content = $content . $widget;
}
$original = null;
if ($response instanceof \Illuminate\Http\Response && $response->getOriginalContent()) {
$original = $response->getOriginalContent();
}
// Update the new content and reset the content length
$response->setContent($content);
$response->headers->remove('Content-Length');
// Restore original response (e.g. the View or Ajax data)
if ($original) {
$response->original = $original;
}
}
/**
* Disable the Debugbar
*/
public function disable()
{
$this->enabled = false;
}
/**
* Adds a measure
*
* @param string $label
* @param float $start
* @param float $end
* @param array|null $params
* @param string|null $collector
*/
public function addMeasure($label, $start, $end, $params = [], $collector = null)
{
if ($this->hasCollector('time')) {
/** @var \DebugBar\DataCollector\TimeDataCollector */
$time = $this->getCollector('time');
$time->addMeasure($label, $start, $end, $params, $collector);
}
}
/**
* Utility function to measure the execution of a Closure
*
* @param string $label
* @param \Closure $closure
* @param string|null $collector
* @return mixed
*/
public function measure($label, \Closure $closure, $collector = null)
{
if ($this->hasCollector('time')) {
/** @var \DebugBar\DataCollector\TimeDataCollector */
$time = $this->getCollector('time');
$result = $time->measure($label, $closure, $collector);
} else {
$result = $closure();
}
return $result;
}
/**
* Collect data in a CLI request
*
* @return array
*/
public function collectConsole()
{
if (!$this->isEnabled()) {
return;
}
$this->data = [
'__meta' => [
'id' => $this->getCurrentRequestId(),
'datetime' => date('Y-m-d H:i:s'),
'utime' => microtime(true),
'method' => 'CLI',
'uri' => isset($_SERVER['argv']) ? implode(' ', $_SERVER['argv']) : null,
'ip' => isset($_SERVER['SSH_CLIENT']) ? $_SERVER['SSH_CLIENT'] : null
]
];
foreach ($this->collectors as $name => $collector) {
$this->data[$name] = $collector->collect();
}
// Remove all invalid (non UTF-8) characters
array_walk_recursive(
$this->data,
function (&$item) {
if (is_string($item) && !mb_check_encoding($item, 'UTF-8')) {
$item = mb_convert_encoding($item, 'UTF-8', 'UTF-8');
}
}
);
if ($this->storage !== null) {
$this->storage->save($this->getCurrentRequestId(), $this->data);
}
return $this->data;
}
/**
* Magic calls for adding messages
*
* @param string $method
* @param array $args
* @return mixed|void
*/
public function __call($method, $args)
{
$messageLevels = ['emergency', 'alert', 'critical', 'error', 'warning', 'notice', 'info', 'debug', 'log'];
if (in_array($method, $messageLevels)) {
foreach ($args as $arg) {
$this->addMessage($arg, $method);
}
}
}
/**
* Adds a message to the MessagesCollector
*
* A message can be anything from an object to a string
*
* @param mixed $message
* @param string $label
*/
public function addMessage($message, $label = 'info')
{
if ($this->hasCollector('messages')) {
/** @var \DebugBar\DataCollector\MessagesCollector $collector */
$collector = $this->getCollector('messages');
$collector->addMessage($message, $label);
}
}
/**
* Check the version of Laravel
*
* @param string $version
* @param string $operator (default: '>=')
* @return boolean
*/
protected function checkVersion($version, $operator = ">=")
{
return version_compare($this->version, $version, $operator);
}
protected function isLumen()
{
return $this->is_lumen;
}
/**
* @param DebugBar $debugbar
*/
protected function selectStorage(DebugBar $debugbar)
{
/** @var \Illuminate\Config\Repository $config */
$config = $this->app['config'];
if ($config->get('debugbar.storage.enabled')) {
$driver = $config->get('debugbar.storage.driver', 'file');
switch ($driver) {
case 'pdo':
$connection = $config->get('debugbar.storage.connection');
$table = $this->app['db']->getTablePrefix() . 'phpdebugbar';
$pdo = $this->app['db']->connection($connection)->getPdo();
$storage = new PdoStorage($pdo, $table);
break;
case 'redis':
$connection = $config->get('debugbar.storage.connection');
$client = $this->app['redis']->connection($connection);
if (is_a($client, 'Illuminate\Redis\Connections\Connection', false)) {
$client = $client->client();
}
$storage = new RedisStorage($client);
break;
case 'custom':
$class = $config->get('debugbar.storage.provider');
$storage = $this->app->make($class);
break;
case 'socket':
$hostname = $config->get('debugbar.storage.hostname', '127.0.0.1');
$port = $config->get('debugbar.storage.port', 2304);
$storage = new SocketStorage($hostname, $port);
break;
case 'file':
default:
$path = $config->get('debugbar.storage.path');
$storage = new FilesystemStorage($this->app['files'], $path);
break;
}
$debugbar->setStorage($storage);
}
}
protected function addClockworkHeaders(Response $response)
{
$prefix = $this->app['config']->get('debugbar.route_prefix');
$response->headers->set('X-Clockwork-Id', $this->getCurrentRequestId(), true);
$response->headers->set('X-Clockwork-Version', 9, true);
$response->headers->set('X-Clockwork-Path', $prefix . '/clockwork/', true);
}
/**
* Add Server-Timing headers for the TimeData collector
*
* @see https://www.w3.org/TR/server-timing/
* @param Response $response
*/
protected function addServerTimingHeaders(Response $response)
{
if ($this->hasCollector('time')) {
$collector = $this->getCollector('time');
$headers = [];
foreach ($collector->collect()['measures'] as $m) {
$headers[] = sprintf('app;desc="%s";dur=%F', str_replace(array("\n", "\r"), ' ', str_replace('"', "'", $m['label'])), $m['duration'] * 1000);
}
$response->headers->set('Server-Timing', $headers, false);
}
}
/**
* @return array
*/
private function getRemoteServerReplacements()
{
$localPath = $this->app['config']->get('debugbar.local_sites_path') ?: base_path();
$remotePaths = array_filter(explode(',', $this->app['config']->get('debugbar.remote_sites_path') ?: '')) ?: [base_path()];
return array_fill_keys($remotePaths, $localPath);
}
/**
* @return \Monolog\Logger
* @throws Exception
*/
private function getMonologLogger()
{
$logger = $this->app['log']->getLogger();
if (get_class($logger) !== 'Monolog\Logger') {
throw new Exception('Logger is not a Monolog\Logger instance');
}
return $logger;
}
}
Function Calls
None |
Stats
MD5 | fea89f8199406f63739c095b98598531 |
Eval Count | 0 |
Decode Time | 108 ms |