vendor and env first commit
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace Barryvdh\Debugbar\Console;
|
||||
|
||||
use DebugBar\DebugBar;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
class ClearCommand extends Command
|
||||
{
|
||||
protected $name = 'debugbar:clear';
|
||||
protected $description = 'Clear the Debugbar Storage';
|
||||
protected $debugbar;
|
||||
|
||||
public function __construct(DebugBar $debugbar)
|
||||
{
|
||||
$this->debugbar = $debugbar;
|
||||
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
public function handle()
|
||||
{
|
||||
$this->debugbar->boot();
|
||||
|
||||
if ($storage = $this->debugbar->getStorage()) {
|
||||
try {
|
||||
$storage->clear();
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
// hide InvalidArgumentException if storage location does not exist
|
||||
if (strpos($e->getMessage(), 'does not exist') === false) {
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
$this->info('Debugbar Storage cleared!');
|
||||
} else {
|
||||
$this->error('No Debugbar Storage found..');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
namespace Barryvdh\Debugbar\Controllers;
|
||||
|
||||
use Illuminate\Http\Response;
|
||||
|
||||
class AssetController extends BaseController
|
||||
{
|
||||
/**
|
||||
* Return the javascript for the Debugbar
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function js()
|
||||
{
|
||||
$renderer = $this->debugbar->getJavascriptRenderer();
|
||||
|
||||
$content = $renderer->dumpAssetsToString('js');
|
||||
|
||||
$response = new Response(
|
||||
$content,
|
||||
200,
|
||||
[
|
||||
'Content-Type' => 'text/javascript',
|
||||
]
|
||||
);
|
||||
|
||||
return $this->cacheResponse($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the stylesheets for the Debugbar
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function css()
|
||||
{
|
||||
$renderer = $this->debugbar->getJavascriptRenderer();
|
||||
|
||||
$content = $renderer->dumpAssetsToString('css');
|
||||
|
||||
$response = new Response(
|
||||
$content,
|
||||
200,
|
||||
[
|
||||
'Content-Type' => 'text/css',
|
||||
]
|
||||
);
|
||||
|
||||
return $this->cacheResponse($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cache the response 1 year (31536000 sec)
|
||||
*/
|
||||
protected function cacheResponse(Response $response)
|
||||
{
|
||||
$response->setSharedMaxAge(31536000);
|
||||
$response->setMaxAge(31536000);
|
||||
$response->setExpires(new \DateTime('+1 year'));
|
||||
|
||||
return $response;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
namespace Barryvdh\Debugbar\Controllers;
|
||||
|
||||
use Barryvdh\Debugbar\LaravelDebugbar;
|
||||
use Illuminate\Routing\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Laravel\Telescope\Telescope;
|
||||
|
||||
// phpcs:ignoreFile
|
||||
if (class_exists('Illuminate\Routing\Controller')) {
|
||||
|
||||
class BaseController extends Controller
|
||||
{
|
||||
protected $debugbar;
|
||||
|
||||
public function __construct(Request $request, LaravelDebugbar $debugbar)
|
||||
{
|
||||
$this->debugbar = $debugbar;
|
||||
|
||||
if ($request->hasSession()) {
|
||||
$request->session()->reflash();
|
||||
}
|
||||
|
||||
$this->middleware(function ($request, $next) {
|
||||
if (class_exists(Telescope::class)) {
|
||||
Telescope::stopRecording();
|
||||
}
|
||||
return $next($request);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
class BaseController
|
||||
{
|
||||
protected $debugbar;
|
||||
|
||||
public function __construct(Request $request, LaravelDebugbar $debugbar)
|
||||
{
|
||||
$this->debugbar = $debugbar;
|
||||
|
||||
if ($request->hasSession()) {
|
||||
$request->session()->reflash();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace Barryvdh\Debugbar\Controllers;
|
||||
|
||||
use Illuminate\Http\Response;
|
||||
|
||||
class CacheController extends BaseController
|
||||
{
|
||||
/**
|
||||
* Forget a cache key
|
||||
*
|
||||
*/
|
||||
public function delete($key, $tags = '')
|
||||
{
|
||||
$cache = app('cache');
|
||||
|
||||
if (!empty($tags)) {
|
||||
$tags = json_decode($tags, true);
|
||||
$cache = $cache->tags($tags);
|
||||
} else {
|
||||
unset($tags);
|
||||
}
|
||||
|
||||
$success = $cache->forget($key);
|
||||
|
||||
return response()->json(compact('success'));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
|
||||
namespace Barryvdh\Debugbar\Controllers;
|
||||
|
||||
use Barryvdh\Debugbar\Support\Clockwork\Converter;
|
||||
use DebugBar\DebugBarException;
|
||||
use DebugBar\OpenHandler;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
|
||||
class OpenHandlerController extends BaseController
|
||||
{
|
||||
/**
|
||||
* Check if the storage is open for inspecting.
|
||||
*
|
||||
* @param Request $request
|
||||
* @return bool
|
||||
*/
|
||||
protected function isStorageOpen(Request $request)
|
||||
{
|
||||
$open = config('debugbar.storage.open');
|
||||
|
||||
if (is_callable($open)) {
|
||||
return call_user_func($open, [$request]);
|
||||
}
|
||||
|
||||
if (is_string($open) && class_exists($open)) {
|
||||
return method_exists($open, 'resolve') ? $open::resolve($request) : false;
|
||||
}
|
||||
|
||||
if (is_bool($open)) {
|
||||
return $open;
|
||||
}
|
||||
|
||||
// Allow localhost request when not explicitly allowed/disallowed
|
||||
if (in_array($request->ip(), ['127.0.0.1', '::1'], true)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function handle(Request $request)
|
||||
{
|
||||
if ($request->input('op') === 'get' || $this->isStorageOpen($request)) {
|
||||
$openHandler = new OpenHandler($this->debugbar);
|
||||
$data = $openHandler->handle($request->input(), false, false);
|
||||
} else {
|
||||
$data = [
|
||||
[
|
||||
'datetime' => date("Y-m-d H:i:s"),
|
||||
'id' => null,
|
||||
'ip' => $request->getClientIp(),
|
||||
'method' => 'ERROR',
|
||||
'uri' => '!! To enable public access to previous requests, set debugbar.storage.open to true in your config, or enable DEBUGBAR_OPEN_STORAGE if you did not publish the config. !!',
|
||||
'utime' => microtime(true),
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
return new Response(
|
||||
$data,
|
||||
200,
|
||||
[
|
||||
'Content-Type' => 'application/json'
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return Clockwork output
|
||||
*
|
||||
* @param $id
|
||||
* @return mixed
|
||||
* @throws \DebugBar\DebugBarException
|
||||
*/
|
||||
public function clockwork(Request $request, $id)
|
||||
{
|
||||
$request = [
|
||||
'op' => 'get',
|
||||
'id' => $id,
|
||||
];
|
||||
|
||||
$openHandler = new OpenHandler($this->debugbar);
|
||||
$data = $openHandler->handle($request, false, false);
|
||||
|
||||
// Convert to Clockwork
|
||||
$converter = new Converter();
|
||||
$output = $converter->convert(json_decode($data, true));
|
||||
|
||||
return response()->json($output);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace Barryvdh\Debugbar\Controllers;
|
||||
|
||||
use Barryvdh\Debugbar\Support\Clockwork\Converter;
|
||||
use DebugBar\OpenHandler;
|
||||
use Illuminate\Http\Response;
|
||||
use Laravel\Telescope\Contracts\EntriesRepository;
|
||||
use Laravel\Telescope\IncomingEntry;
|
||||
use Laravel\Telescope\Storage\EntryQueryOptions;
|
||||
use Laravel\Telescope\Telescope;
|
||||
|
||||
class TelescopeController extends BaseController
|
||||
{
|
||||
public function show(EntriesRepository $storage, $uuid)
|
||||
{
|
||||
|
||||
$entry = $storage->find($uuid);
|
||||
$result = $storage->get('request', (new EntryQueryOptions())->batchId($entry->batchId))->first();
|
||||
|
||||
return redirect(config('telescope.domain') . '/' . config('telescope.path') . '/requests/' . $result->id);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
<?php
|
||||
|
||||
namespace Barryvdh\Debugbar\DataCollector;
|
||||
|
||||
use DebugBar\DataCollector\TimeDataCollector;
|
||||
use Illuminate\Cache\Events\CacheEvent;
|
||||
use Illuminate\Cache\Events\CacheHit;
|
||||
use Illuminate\Cache\Events\CacheMissed;
|
||||
use Illuminate\Cache\Events\KeyForgotten;
|
||||
use Illuminate\Cache\Events\KeyWritten;
|
||||
use Illuminate\Events\Dispatcher;
|
||||
|
||||
class CacheCollector extends TimeDataCollector
|
||||
{
|
||||
/** @var bool */
|
||||
protected $collectValues;
|
||||
|
||||
/** @var array */
|
||||
protected $classMap = [
|
||||
CacheHit::class => 'hit',
|
||||
CacheMissed::class => 'missed',
|
||||
KeyWritten::class => 'written',
|
||||
KeyForgotten::class => 'forgotten',
|
||||
];
|
||||
|
||||
public function __construct($requestStartTime, $collectValues)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->collectValues = $collectValues;
|
||||
}
|
||||
|
||||
public function onCacheEvent(CacheEvent $event)
|
||||
{
|
||||
$class = get_class($event);
|
||||
$params = get_object_vars($event);
|
||||
|
||||
$label = $this->classMap[$class];
|
||||
|
||||
if (isset($params['value'])) {
|
||||
if ($this->collectValues) {
|
||||
$params['value'] = htmlspecialchars($this->getDataFormatter()->formatVar($event->value));
|
||||
} else {
|
||||
unset($params['value']);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!empty($params['key']) && in_array($label, ['hit', 'written'])) {
|
||||
$params['delete'] = route('debugbar.cache.delete', [
|
||||
'key' => urlencode($params['key']),
|
||||
'tags' => !empty($params['tags']) ? json_encode($params['tags']) : '',
|
||||
]);
|
||||
}
|
||||
|
||||
$time = microtime(true);
|
||||
$this->addMeasure($label . "\t" . $event->key, $time, $time, $params);
|
||||
}
|
||||
|
||||
|
||||
public function subscribe(Dispatcher $dispatcher)
|
||||
{
|
||||
foreach ($this->classMap as $eventClass => $type) {
|
||||
$dispatcher->listen($eventClass, [$this, 'onCacheEvent']);
|
||||
}
|
||||
}
|
||||
|
||||
public function collect()
|
||||
{
|
||||
$data = parent::collect();
|
||||
$data['nb_measures'] = count($data['measures']);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return 'cache';
|
||||
}
|
||||
|
||||
public function getWidgets()
|
||||
{
|
||||
return [
|
||||
'cache' => [
|
||||
'icon' => 'clipboard',
|
||||
'widget' => 'PhpDebugBar.Widgets.LaravelCacheWidget',
|
||||
'map' => 'cache',
|
||||
'default' => '{}',
|
||||
],
|
||||
'cache:badge' => [
|
||||
'map' => 'cache.nb_measures',
|
||||
'default' => 'null',
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
<?php
|
||||
|
||||
namespace Barryvdh\Debugbar\DataCollector;
|
||||
|
||||
use Barryvdh\Debugbar\DataFormatter\SimpleFormatter;
|
||||
use DebugBar\DataCollector\TimeDataCollector;
|
||||
use Illuminate\Contracts\Events\Dispatcher;
|
||||
use Illuminate\Support\Str;
|
||||
use Symfony\Component\VarDumper\Cloner\VarCloner;
|
||||
|
||||
class EventCollector extends TimeDataCollector
|
||||
{
|
||||
/** @var Dispatcher */
|
||||
protected $events;
|
||||
|
||||
/** @var integer */
|
||||
protected $previousTime;
|
||||
|
||||
/** @var bool */
|
||||
protected $collectValues;
|
||||
|
||||
public function __construct($requestStartTime = null, $collectValues = false)
|
||||
{
|
||||
parent::__construct($requestStartTime);
|
||||
$this->previousTime = microtime(true);
|
||||
$this->collectValues = $collectValues;
|
||||
$this->setDataFormatter(new SimpleFormatter());
|
||||
}
|
||||
|
||||
public function onWildcardEvent($name = null, $data = [])
|
||||
{
|
||||
$currentTime = microtime(true);
|
||||
|
||||
if (! $this->collectValues) {
|
||||
$this->addMeasure($name, $this->previousTime, $currentTime);
|
||||
$this->previousTime = $currentTime;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$params = $this->prepareParams($data);
|
||||
|
||||
// Find all listeners for the current event
|
||||
foreach ($this->events->getListeners($name) as $i => $listener) {
|
||||
// Check if it's an object + method name
|
||||
if (is_array($listener) && count($listener) > 1 && is_object($listener[0])) {
|
||||
list($class, $method) = $listener;
|
||||
|
||||
// Skip this class itself
|
||||
if ($class instanceof static) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Format the listener to readable format
|
||||
$listener = get_class($class) . '@' . $method;
|
||||
|
||||
// Handle closures
|
||||
} elseif ($listener instanceof \Closure) {
|
||||
$reflector = new \ReflectionFunction($listener);
|
||||
|
||||
// Skip our own listeners
|
||||
if ($reflector->getNamespaceName() == 'Barryvdh\Debugbar') {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Format the closure to a readable format
|
||||
$filename = ltrim(str_replace(base_path(), '', $reflector->getFileName()), '/');
|
||||
$lines = $reflector->getStartLine() . '-' . $reflector->getEndLine();
|
||||
$listener = $reflector->getName() . ' (' . $filename . ':' . $lines . ')';
|
||||
} else {
|
||||
// Not sure if this is possible, but to prevent edge cases
|
||||
$listener = $this->getDataFormatter()->formatVar($listener);
|
||||
}
|
||||
|
||||
$params['listeners.' . $i] = $listener;
|
||||
}
|
||||
$this->addMeasure($name, $this->previousTime, $currentTime, $params);
|
||||
$this->previousTime = $currentTime;
|
||||
}
|
||||
|
||||
public function subscribe(Dispatcher $events)
|
||||
{
|
||||
$this->events = $events;
|
||||
$events->listen('*', [$this, 'onWildcardEvent']);
|
||||
}
|
||||
|
||||
protected function prepareParams($params)
|
||||
{
|
||||
$data = [];
|
||||
foreach ($params as $key => $value) {
|
||||
if (is_object($value) && Str::is('Illuminate\*\Events\*', get_class($value))) {
|
||||
$value = $this->prepareParams(get_object_vars($value));
|
||||
}
|
||||
$data[$key] = htmlentities($this->getDataFormatter()->formatVar($value), ENT_QUOTES, 'UTF-8', false);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function collect()
|
||||
{
|
||||
$data = parent::collect();
|
||||
$data['nb_measures'] = count($data['measures']);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return 'event';
|
||||
}
|
||||
|
||||
public function getWidgets()
|
||||
{
|
||||
return [
|
||||
"events" => [
|
||||
"icon" => "tasks",
|
||||
"widget" => "PhpDebugBar.Widgets.TimelineWidget",
|
||||
"map" => "event",
|
||||
"default" => "{}",
|
||||
],
|
||||
'events:badge' => [
|
||||
'map' => 'event.nb_measures',
|
||||
'default' => 0,
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
<?php
|
||||
|
||||
namespace Barryvdh\Debugbar\DataCollector;
|
||||
|
||||
use DebugBar\DataCollector\DataCollector;
|
||||
use DebugBar\DataCollector\Renderable;
|
||||
use Illuminate\Container\Container;
|
||||
|
||||
class FilesCollector extends DataCollector implements Renderable
|
||||
{
|
||||
/** @var \Illuminate\Container\Container */
|
||||
protected $app;
|
||||
protected $basePath;
|
||||
|
||||
/**
|
||||
* @param \Illuminate\Container\Container $app
|
||||
*/
|
||||
public function __construct(Container $app = null)
|
||||
{
|
||||
$this->app = $app;
|
||||
$this->basePath = base_path();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function collect()
|
||||
{
|
||||
$files = $this->getIncludedFiles();
|
||||
$compiled = $this->getCompiledFiles();
|
||||
|
||||
$included = [];
|
||||
$alreadyCompiled = [];
|
||||
foreach ($files as $file) {
|
||||
// Skip the files from Debugbar, they are only loaded for Debugging and confuse the output.
|
||||
// Of course some files are stil always loaded (ServiceProvider, Facade etc)
|
||||
if (
|
||||
strpos($file, 'vendor/maximebf/debugbar/src') !== false || strpos(
|
||||
$file,
|
||||
'vendor/barryvdh/laravel-debugbar/src'
|
||||
) !== false
|
||||
) {
|
||||
continue;
|
||||
} elseif (!in_array($file, $compiled)) {
|
||||
$included[] = [
|
||||
'message' => "'" . $this->stripBasePath($file) . "',",
|
||||
// Use PHP syntax so we can copy-paste to compile config file.
|
||||
'is_string' => true,
|
||||
];
|
||||
} else {
|
||||
$alreadyCompiled[] = [
|
||||
'message' => "* '" . $this->stripBasePath($file) . "',",
|
||||
// Mark with *, so know they are compiled anyway.
|
||||
'is_string' => true,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// First the included files, then those that are going to be compiled.
|
||||
$messages = array_merge($included, $alreadyCompiled);
|
||||
|
||||
return [
|
||||
'messages' => $messages,
|
||||
'count' => count($included),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the files included on load.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getIncludedFiles()
|
||||
{
|
||||
return get_included_files();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the files that are going to be compiled, so they aren't as important.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getCompiledFiles()
|
||||
{
|
||||
if ($this->app && class_exists('Illuminate\Foundation\Console\OptimizeCommand')) {
|
||||
$reflector = new \ReflectionClass('Illuminate\Foundation\Console\OptimizeCommand');
|
||||
$path = dirname($reflector->getFileName()) . '/Optimize/config.php';
|
||||
|
||||
if (file_exists($path)) {
|
||||
$app = $this->app;
|
||||
$core = require $path;
|
||||
return array_merge($core, $app['config']['compile']);
|
||||
}
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the basePath from the paths, so they are relative to the base
|
||||
*
|
||||
* @param $path
|
||||
* @return string
|
||||
*/
|
||||
protected function stripBasePath($path)
|
||||
{
|
||||
return ltrim(str_replace($this->basePath, '', $path), '/');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getWidgets()
|
||||
{
|
||||
$name = $this->getName();
|
||||
return [
|
||||
"$name" => [
|
||||
"icon" => "files-o",
|
||||
"widget" => "PhpDebugBar.Widgets.MessagesWidget",
|
||||
"map" => "$name.messages",
|
||||
"default" => "{}"
|
||||
],
|
||||
"$name:badge" => [
|
||||
"map" => "$name.count",
|
||||
"default" => "null"
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'files';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
namespace Barryvdh\Debugbar\DataCollector;
|
||||
|
||||
use Barryvdh\Debugbar\DataFormatter\SimpleFormatter;
|
||||
use DebugBar\DataCollector\MessagesCollector;
|
||||
use Illuminate\Auth\Access\Response;
|
||||
use Illuminate\Contracts\Auth\Access\Gate;
|
||||
use Illuminate\Contracts\Auth\Authenticatable;
|
||||
use Symfony\Component\VarDumper\Cloner\VarCloner;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* Collector for Laravel's Auth provider
|
||||
*/
|
||||
class GateCollector extends MessagesCollector
|
||||
{
|
||||
/**
|
||||
* @param Gate $gate
|
||||
*/
|
||||
public function __construct(Gate $gate)
|
||||
{
|
||||
parent::__construct('gate');
|
||||
$this->setDataFormatter(new SimpleFormatter());
|
||||
$gate->after(function ($user, $ability, $result, $arguments = []) {
|
||||
$this->addCheck($user, $ability, $result, $arguments);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function customizeMessageHtml($messageHtml, $message)
|
||||
{
|
||||
$pos = strpos((string) $messageHtml, 'array:4');
|
||||
if ($pos !== false) {
|
||||
$messageHtml = substr_replace($messageHtml, $message['ability'], $pos, 7);
|
||||
}
|
||||
|
||||
return parent::customizeMessageHtml($messageHtml, $message);
|
||||
}
|
||||
|
||||
public function addCheck($user, $ability, $result, $arguments = [])
|
||||
{
|
||||
$userKey = 'user';
|
||||
$userId = null;
|
||||
|
||||
if ($user) {
|
||||
$userKey = Str::snake(class_basename($user));
|
||||
$userId = $user instanceof Authenticatable ? $user->getAuthIdentifier() : $user->getKey();
|
||||
}
|
||||
|
||||
$label = $result ? 'success' : 'error';
|
||||
|
||||
if ($result instanceof Response) {
|
||||
$label = $result->allowed() ? 'success' : 'error';
|
||||
}
|
||||
|
||||
$this->addMessage([
|
||||
'ability' => $ability,
|
||||
'result' => $result,
|
||||
$userKey => $userId,
|
||||
'arguments' => $this->getDataFormatter()->formatVar($arguments),
|
||||
], $label, false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
namespace Barryvdh\Debugbar\DataCollector;
|
||||
|
||||
use DebugBar\DataCollector\DataCollector;
|
||||
use DebugBar\DataCollector\DataCollectorInterface;
|
||||
use DebugBar\DataCollector\Renderable;
|
||||
use Illuminate\Contracts\Events\Dispatcher;
|
||||
|
||||
/**
|
||||
* @deprecated in favor of \DebugBar\DataCollector\ObjectCountCollector
|
||||
*/
|
||||
class JobsCollector extends DataCollector implements DataCollectorInterface, Renderable
|
||||
{
|
||||
public $jobs = [];
|
||||
public $count = 0;
|
||||
|
||||
/**
|
||||
* @param Dispatcher $events
|
||||
*/
|
||||
public function __construct(Dispatcher $events)
|
||||
{
|
||||
$events->listen(\Illuminate\Queue\Events\JobQueued::class, function ($event) {
|
||||
$class = get_class($event->job);
|
||||
$this->jobs[$class] = ($this->jobs[$class] ?? 0) + 1;
|
||||
$this->count++;
|
||||
});
|
||||
}
|
||||
|
||||
public function collect()
|
||||
{
|
||||
ksort($this->jobs, SORT_NUMERIC);
|
||||
|
||||
return ['data' => array_reverse($this->jobs), 'count' => $this->count];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'jobs';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getWidgets()
|
||||
{
|
||||
return [
|
||||
"jobs" => [
|
||||
"icon" => "briefcase",
|
||||
"widget" => "PhpDebugBar.Widgets.HtmlVariableListWidget",
|
||||
"map" => "jobs.data",
|
||||
"default" => "{}"
|
||||
],
|
||||
'jobs:badge' => [
|
||||
'map' => 'jobs.count',
|
||||
'default' => 0
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
namespace Barryvdh\Debugbar\DataCollector;
|
||||
|
||||
use DebugBar\DataCollector\DataCollector;
|
||||
use DebugBar\DataCollector\Renderable;
|
||||
use Illuminate\Foundation\Application;
|
||||
|
||||
class LaravelCollector extends DataCollector implements Renderable
|
||||
{
|
||||
/** @var \Illuminate\Foundation\Application $app */
|
||||
protected $app;
|
||||
|
||||
/**
|
||||
* @param Application $app
|
||||
*/
|
||||
public function __construct(Application $app = null)
|
||||
{
|
||||
$this->app = $app;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function collect()
|
||||
{
|
||||
// Fallback if not injected
|
||||
$app = $this->app ?: app();
|
||||
|
||||
return [
|
||||
"version" => $app::VERSION,
|
||||
"environment" => $app->environment(),
|
||||
"locale" => $app->getLocale(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'laravel';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getWidgets()
|
||||
{
|
||||
return [
|
||||
"version" => [
|
||||
"icon" => "github",
|
||||
"tooltip" => "Laravel Version",
|
||||
"map" => "laravel.version",
|
||||
"default" => ""
|
||||
],
|
||||
"environment" => [
|
||||
"icon" => "desktop",
|
||||
"tooltip" => "Environment",
|
||||
"map" => "laravel.environment",
|
||||
"default" => ""
|
||||
],
|
||||
"locale" => [
|
||||
"icon" => "flag",
|
||||
"tooltip" => "Current locale",
|
||||
"map" => "laravel.locale",
|
||||
"default" => "",
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
|
||||
namespace Barryvdh\Debugbar\DataCollector;
|
||||
|
||||
use DebugBar\DataCollector\DataCollector;
|
||||
use DebugBar\DataCollector\DataCollectorInterface;
|
||||
use DebugBar\DataCollector\Renderable;
|
||||
use Illuminate\Contracts\Events\Dispatcher;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Fluent;
|
||||
use Illuminate\Support\Str;
|
||||
use Livewire\Livewire;
|
||||
use Livewire\Component;
|
||||
|
||||
/**
|
||||
* Collector for Models.
|
||||
*/
|
||||
class LivewireCollector extends DataCollector implements DataCollectorInterface, Renderable
|
||||
{
|
||||
public $data = [];
|
||||
|
||||
public function __construct(Request $request)
|
||||
{
|
||||
// Listen to Livewire views
|
||||
Livewire::listen('view:render', function (View $view) use ($request) {
|
||||
/** @var \Livewire\Component $component */
|
||||
$component = $view->getData()['_instance'];
|
||||
|
||||
// Create a unique name for each component
|
||||
$key = $component->getName() . ' #' . $component->id;
|
||||
|
||||
$data = [
|
||||
'data' => $component->getPublicPropertiesDefinedBySubClass(),
|
||||
];
|
||||
|
||||
if ($request->request->get('id') == $component->id) {
|
||||
$data['oldData'] = $request->request->get('data');
|
||||
$data['actionQueue'] = $request->request->get('actionQueue');
|
||||
}
|
||||
|
||||
$data['name'] = $component->getName();
|
||||
$data['view'] = $view->name();
|
||||
$data['component'] = get_class($component);
|
||||
$data['id'] = $component->id;
|
||||
|
||||
$this->data[$key] = $this->formatVar($data);
|
||||
});
|
||||
|
||||
Livewire::listen('render', function (Component $component) use ($request) {
|
||||
// Create an unique name for each compoent
|
||||
$key = $component->getName() . ' #' . $component->getId();
|
||||
|
||||
$data = [
|
||||
'data' => $component->all(),
|
||||
];
|
||||
|
||||
if ($request->request->get('id') == $component->getId()) {
|
||||
$data['oldData'] = $request->request->get('data');
|
||||
$data['actionQueue'] = $request->request->get('actionQueue');
|
||||
}
|
||||
|
||||
$data['name'] = $component->getName();
|
||||
$data['component'] = get_class($component);
|
||||
$data['id'] = $component->getId();
|
||||
|
||||
$this->data[$key] = $this->formatVar($data);
|
||||
});
|
||||
}
|
||||
|
||||
public function collect()
|
||||
{
|
||||
return ['data' => $this->data, 'count' => count($this->data)];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'livewire';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getWidgets()
|
||||
{
|
||||
return [
|
||||
"livewire" => [
|
||||
"icon" => "bolt",
|
||||
"widget" => "PhpDebugBar.Widgets.VariableListWidget",
|
||||
"map" => "livewire.data",
|
||||
"default" => "{}"
|
||||
],
|
||||
'livewire:badge' => [
|
||||
'map' => 'livewire.count',
|
||||
'default' => 0
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
<?php
|
||||
|
||||
namespace Barryvdh\Debugbar\DataCollector;
|
||||
|
||||
use DebugBar\DataCollector\MessagesCollector;
|
||||
use Illuminate\Support\Arr;
|
||||
use Psr\Log\LogLevel;
|
||||
use ReflectionClass;
|
||||
|
||||
class LogsCollector extends MessagesCollector
|
||||
{
|
||||
protected $lines = 124;
|
||||
|
||||
public function __construct($path = null, $name = 'logs')
|
||||
{
|
||||
parent::__construct($name);
|
||||
|
||||
$paths = Arr::wrap($path ?: [
|
||||
storage_path('logs/laravel.log'),
|
||||
storage_path('logs/laravel-' . date('Y-m-d') . '.log'), // for daily driver
|
||||
]);
|
||||
|
||||
foreach ($paths as $path) {
|
||||
$this->getStorageLogs($path);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get logs apache in app/storage/logs
|
||||
* only 24 last of current day
|
||||
*
|
||||
* @param string $path
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getStorageLogs($path)
|
||||
{
|
||||
if (!file_exists($path)) {
|
||||
return;
|
||||
}
|
||||
|
||||
//Load the latest lines, guessing about 15x the number of log entries (for stack traces etc)
|
||||
$file = implode("", $this->tailFile($path, $this->lines));
|
||||
$basename = basename($path);
|
||||
|
||||
foreach ($this->getLogs($file) as $log) {
|
||||
$this->messages[] = [
|
||||
'message' => $log['header'] . $log['stack'],
|
||||
'label' => $log['level'],
|
||||
'time' => substr($log['header'], 1, 19),
|
||||
'collector' => $basename,
|
||||
'is_string' => false,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* By Ain Tohvri (ain)
|
||||
* http://tekkie.flashbit.net/php/tail-functionality-in-php
|
||||
* @param string $file
|
||||
* @param int $lines
|
||||
* @return array
|
||||
*/
|
||||
protected function tailFile($file, $lines)
|
||||
{
|
||||
$handle = fopen($file, "r");
|
||||
$linecounter = $lines;
|
||||
$pos = -2;
|
||||
$beginning = false;
|
||||
$text = [];
|
||||
while ($linecounter > 0) {
|
||||
$t = " ";
|
||||
while ($t != "\n") {
|
||||
if (fseek($handle, $pos, SEEK_END) == -1) {
|
||||
$beginning = true;
|
||||
break;
|
||||
}
|
||||
$t = fgetc($handle);
|
||||
$pos--;
|
||||
}
|
||||
$linecounter--;
|
||||
if ($beginning) {
|
||||
rewind($handle);
|
||||
}
|
||||
$text[$lines - $linecounter - 1] = fgets($handle);
|
||||
if ($beginning) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
fclose($handle);
|
||||
return array_reverse($text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Search a string for log entries
|
||||
* Based on https://github.com/mikemand/logviewer/blob/master/src/Kmd/Logviewer/Logviewer.php by mikemand
|
||||
*
|
||||
* @param $file
|
||||
* @return array
|
||||
*/
|
||||
public function getLogs($file)
|
||||
{
|
||||
$pattern = "/\[\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\].*/";
|
||||
|
||||
$log_levels = $this->getLevels();
|
||||
|
||||
// There has GOT to be a better way of doing this...
|
||||
preg_match_all($pattern, $file, $headings);
|
||||
$log_data = preg_split($pattern, $file);
|
||||
|
||||
$log = [];
|
||||
foreach ($headings as $h) {
|
||||
for ($i = 0, $j = count($h); $i < $j; $i++) {
|
||||
foreach ($log_levels as $ll) {
|
||||
if (strpos(strtolower($h[$i]), strtolower('.' . $ll))) {
|
||||
$log[] = ['level' => $ll, 'header' => $h[$i], 'stack' => $log_data[$i]];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $log;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getMessages()
|
||||
{
|
||||
return array_reverse(parent::getMessages());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the log levels from psr/log.
|
||||
* Based on https://github.com/mikemand/logviewer/blob/master/src/Kmd/Logviewer/Logviewer.php by mikemand
|
||||
*
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getLevels()
|
||||
{
|
||||
$class = new ReflectionClass(new LogLevel());
|
||||
return $class->getConstants();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
namespace Barryvdh\Debugbar\DataCollector;
|
||||
|
||||
use DebugBar\DataCollector\DataCollector;
|
||||
use DebugBar\DataCollector\DataCollectorInterface;
|
||||
use DebugBar\DataCollector\Renderable;
|
||||
use Illuminate\Contracts\Events\Dispatcher;
|
||||
|
||||
/**
|
||||
* Collector for Models.
|
||||
* @deprecated in favor of \DebugBar\DataCollector\ObjectCountCollector
|
||||
*/
|
||||
class ModelsCollector extends DataCollector implements DataCollectorInterface, Renderable
|
||||
{
|
||||
public $models = [];
|
||||
public $count = 0;
|
||||
|
||||
/**
|
||||
* @param Dispatcher $events
|
||||
*/
|
||||
public function __construct(Dispatcher $events)
|
||||
{
|
||||
$events->listen('eloquent.retrieved:*', function ($event, $models) {
|
||||
foreach (array_filter($models) as $model) {
|
||||
$class = get_class($model);
|
||||
$this->models[$class] = ($this->models[$class] ?? 0) + 1;
|
||||
$this->count++;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public function collect()
|
||||
{
|
||||
ksort($this->models, SORT_NUMERIC);
|
||||
|
||||
return ['data' => array_reverse($this->models), 'count' => $this->count];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'models';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getWidgets()
|
||||
{
|
||||
return [
|
||||
"models" => [
|
||||
"icon" => "cubes",
|
||||
"widget" => "PhpDebugBar.Widgets.HtmlVariableListWidget",
|
||||
"map" => "models.data",
|
||||
"default" => "{}"
|
||||
],
|
||||
'models:badge' => [
|
||||
'map' => 'models.count',
|
||||
'default' => 0
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,182 @@
|
||||
<?php
|
||||
|
||||
namespace Barryvdh\Debugbar\DataCollector;
|
||||
|
||||
use DebugBar\DataCollector\DataCollector;
|
||||
use DebugBar\DataCollector\Renderable;
|
||||
use Illuminate\Auth\Recaller;
|
||||
use Illuminate\Auth\SessionGuard;
|
||||
use Illuminate\Contracts\Auth\Authenticatable;
|
||||
use Illuminate\Contracts\Auth\Guard;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Contracts\Support\Arrayable;
|
||||
|
||||
/**
|
||||
* Collector for Laravel's Auth provider
|
||||
*/
|
||||
class MultiAuthCollector extends DataCollector implements Renderable
|
||||
{
|
||||
/** @var array $guards */
|
||||
protected $guards;
|
||||
|
||||
/** @var \Illuminate\Auth\AuthManager */
|
||||
protected $auth;
|
||||
|
||||
/** @var bool */
|
||||
protected $showName = false;
|
||||
|
||||
/** @var bool */
|
||||
protected $showGuardsData = true;
|
||||
|
||||
/**
|
||||
* @param \Illuminate\Auth\AuthManager $auth
|
||||
* @param array $guards
|
||||
*/
|
||||
public function __construct($auth, $guards)
|
||||
{
|
||||
$this->auth = $auth;
|
||||
$this->guards = $guards;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to show the users name/email
|
||||
* @param bool $showName
|
||||
*/
|
||||
public function setShowName($showName)
|
||||
{
|
||||
$this->showName = (bool) $showName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to hide the guards tab, and show only name
|
||||
* @param bool $showGuardsData
|
||||
*/
|
||||
public function setShowGuardsData($showGuardsData)
|
||||
{
|
||||
$this->showGuardsData = (bool) $showGuardsData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @{inheritDoc}
|
||||
*/
|
||||
public function collect()
|
||||
{
|
||||
$data = [
|
||||
'guards' => [],
|
||||
];
|
||||
$names = '';
|
||||
|
||||
foreach ($this->guards as $guardName => $config) {
|
||||
try {
|
||||
$guard = $this->auth->guard($guardName);
|
||||
if ($this->hasUser($guard)) {
|
||||
$user = $guard->user();
|
||||
|
||||
if (!is_null($user)) {
|
||||
$data['guards'][$guardName] = $this->getUserInformation($user);
|
||||
$names .= $guardName . ": " . $data['guards'][$guardName]['name'] . ', ';
|
||||
}
|
||||
} else {
|
||||
$data['guards'][$guardName] = null;
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($data['guards'] as $key => $var) {
|
||||
if (!is_string($data['guards'][$key])) {
|
||||
$data['guards'][$key] = $this->formatVar($var);
|
||||
}
|
||||
}
|
||||
|
||||
$data['names'] = rtrim($names, ', ');
|
||||
if (!$this->showGuardsData) {
|
||||
unset($data['guards']);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
private function hasUser(Guard $guard)
|
||||
{
|
||||
if (method_exists($guard, 'hasUser')) {
|
||||
return $guard->hasUser();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get displayed user information
|
||||
* @param \Illuminate\Auth\UserInterface $user
|
||||
* @return array
|
||||
*/
|
||||
protected function getUserInformation($user = null)
|
||||
{
|
||||
// Defaults
|
||||
if (is_null($user)) {
|
||||
return [
|
||||
'name' => 'Guest',
|
||||
'user' => ['guest' => true],
|
||||
];
|
||||
}
|
||||
|
||||
// The default auth identifer is the ID number, which isn't all that
|
||||
// useful. Try username, email and name.
|
||||
$identifier = $user instanceof Authenticatable ? $user->getAuthIdentifier() : $user->getKey();
|
||||
if (is_numeric($identifier) || Str::isUuid($identifier) || Str::isUlid($identifier)) {
|
||||
try {
|
||||
if (isset($user->username)) {
|
||||
$identifier = $user->username;
|
||||
} elseif (isset($user->email)) {
|
||||
$identifier = $user->email;
|
||||
} elseif (isset($user->name)) {
|
||||
$identifier = Str::limit($user->name, 24);
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'name' => $identifier,
|
||||
'user' => $user instanceof Arrayable ? $user->toArray() : $user,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @{inheritDoc}
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'auth';
|
||||
}
|
||||
|
||||
/**
|
||||
* @{inheritDoc}
|
||||
*/
|
||||
public function getWidgets()
|
||||
{
|
||||
$widgets = [];
|
||||
|
||||
if ($this->showGuardsData) {
|
||||
$widgets["auth"] = [
|
||||
"icon" => "lock",
|
||||
"widget" => "PhpDebugBar.Widgets.VariableListWidget",
|
||||
"map" => "auth.guards",
|
||||
"default" => "{}",
|
||||
];
|
||||
}
|
||||
|
||||
if ($this->showName) {
|
||||
$widgets['auth.name'] = [
|
||||
'icon' => 'user',
|
||||
'tooltip' => 'Auth status',
|
||||
'map' => 'auth.names',
|
||||
'default' => '',
|
||||
];
|
||||
}
|
||||
|
||||
return $widgets;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,685 @@
|
||||
<?php
|
||||
|
||||
namespace Barryvdh\Debugbar\DataCollector;
|
||||
|
||||
use DebugBar\DataCollector\PDO\PDOCollector;
|
||||
use DebugBar\DataCollector\TimeDataCollector;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* Collects data about SQL statements executed with PDO
|
||||
*/
|
||||
class QueryCollector extends PDOCollector
|
||||
{
|
||||
protected $timeCollector;
|
||||
protected $queries = [];
|
||||
protected $queryCount = 0;
|
||||
protected $softLimit = null;
|
||||
protected $hardLimit = null;
|
||||
protected $lastMemoryUsage;
|
||||
protected $renderSqlWithParams = false;
|
||||
protected $findSource = false;
|
||||
protected $middleware = [];
|
||||
protected $durationBackground = true;
|
||||
protected $explainQuery = false;
|
||||
protected $explainTypes = ['SELECT']; // ['SELECT', 'INSERT', 'UPDATE', 'DELETE']; for MySQL 5.6.3+
|
||||
protected $showHints = false;
|
||||
protected $showCopyButton = false;
|
||||
protected $reflection = [];
|
||||
protected $backtraceExcludePaths = [
|
||||
'/vendor/laravel/framework/src/Illuminate/Support',
|
||||
'/vendor/laravel/framework/src/Illuminate/Database',
|
||||
'/vendor/laravel/framework/src/Illuminate/Events',
|
||||
'/vendor/laravel/framework/src/Illuminate/Collections',
|
||||
'/vendor/october/rain',
|
||||
'/vendor/barryvdh/laravel-debugbar',
|
||||
];
|
||||
|
||||
/**
|
||||
* @param TimeDataCollector $timeCollector
|
||||
*/
|
||||
public function __construct(TimeDataCollector $timeCollector = null)
|
||||
{
|
||||
$this->timeCollector = $timeCollector;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int|null $softLimit After the soft limit, no parameters/backtrace are captured
|
||||
* @param int|null $hardLimit After the hard limit, queries are ignored
|
||||
* @return void
|
||||
*/
|
||||
public function setLimits(?int $softLimit, ?int $hardLimit): void
|
||||
{
|
||||
$this->softLimit = $softLimit;
|
||||
$this->hardLimit = $hardLimit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the SQL of traced statements with params embedded
|
||||
*
|
||||
* @param boolean $enabled
|
||||
* @param string $quotationChar NOT USED
|
||||
*/
|
||||
public function setRenderSqlWithParams($enabled = true, $quotationChar = "'")
|
||||
{
|
||||
$this->renderSqlWithParams = $enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show or hide the hints in the parameters
|
||||
*
|
||||
* @param boolean $enabled
|
||||
*/
|
||||
public function setShowHints($enabled = true)
|
||||
{
|
||||
$this->showHints = $enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show or hide copy button next to the queries
|
||||
*
|
||||
* @param boolean $enabled
|
||||
*/
|
||||
public function setShowCopyButton($enabled = true)
|
||||
{
|
||||
$this->showCopyButton = $enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable/disable finding the source
|
||||
*
|
||||
* @param bool|int $value
|
||||
* @param array $middleware
|
||||
*/
|
||||
public function setFindSource($value, array $middleware)
|
||||
{
|
||||
$this->findSource = $value;
|
||||
$this->middleware = $middleware;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set additional paths to exclude from the backtrace
|
||||
*
|
||||
* @param array $excludePaths Array of file paths to exclude from backtrace
|
||||
*/
|
||||
public function mergeBacktraceExcludePaths(array $excludePaths)
|
||||
{
|
||||
$this->backtraceExcludePaths = array_merge($this->backtraceExcludePaths, $excludePaths);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable/disable the shaded duration background on queries
|
||||
*
|
||||
* @param bool $enabled
|
||||
*/
|
||||
public function setDurationBackground($enabled = true)
|
||||
{
|
||||
$this->durationBackground = $enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable/disable the EXPLAIN queries
|
||||
*
|
||||
* @param bool $enabled
|
||||
* @param array|null $types Array of types to explain queries (select/insert/update/delete)
|
||||
*/
|
||||
public function setExplainSource($enabled, $types)
|
||||
{
|
||||
$this->explainQuery = $enabled;
|
||||
// workaround ['SELECT'] only. https://github.com/barryvdh/laravel-debugbar/issues/888
|
||||
// if($types){
|
||||
// $this->explainTypes = $types;
|
||||
// }
|
||||
}
|
||||
|
||||
public function startMemoryUsage()
|
||||
{
|
||||
$this->lastMemoryUsage = memory_get_usage(false);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param \Illuminate\Database\Events\QueryExecuted $query
|
||||
*/
|
||||
public function addQuery($query)
|
||||
{
|
||||
$this->queryCount++;
|
||||
|
||||
if ($this->hardLimit && $this->queryCount > $this->hardLimit) {
|
||||
return;
|
||||
}
|
||||
|
||||
$limited = $this->softLimit && $this->queryCount > $this->softLimit;
|
||||
|
||||
$sql = (string) $query->sql;
|
||||
$explainResults = [];
|
||||
$time = $query->time / 1000;
|
||||
$endTime = microtime(true);
|
||||
$startTime = $endTime - $time;
|
||||
$hints = $this->performQueryAnalysis($sql);
|
||||
|
||||
$pdo = null;
|
||||
try {
|
||||
$pdo = $query->connection->getPdo();
|
||||
} catch (\Throwable $e) {
|
||||
// ignore error for non-pdo laravel drivers
|
||||
}
|
||||
$bindings = $query->connection->prepareBindings($query->bindings);
|
||||
|
||||
// Run EXPLAIN on this query (if needed)
|
||||
if (!$limited && $this->explainQuery && $pdo && preg_match('/^\s*(' . implode('|', $this->explainTypes) . ') /i', $sql)) {
|
||||
$statement = $pdo->prepare('EXPLAIN ' . $sql);
|
||||
$statement->execute($bindings);
|
||||
$explainResults = $statement->fetchAll(\PDO::FETCH_CLASS);
|
||||
}
|
||||
|
||||
$bindings = $this->getDataFormatter()->checkBindings($bindings);
|
||||
if (!empty($bindings) && $this->renderSqlWithParams) {
|
||||
foreach ($bindings as $key => $binding) {
|
||||
// This regex matches placeholders only, not the question marks,
|
||||
// nested in quotes, while we iterate through the bindings
|
||||
// and substitute placeholders by suitable values.
|
||||
$regex = is_numeric($key)
|
||||
? "/(?<!\?)\?(?=(?:[^'\\\']*'[^'\\']*')*[^'\\\']*$)(?!\?)/"
|
||||
: "/:{$key}(?=(?:[^'\\\']*'[^'\\\']*')*[^'\\\']*$)/";
|
||||
|
||||
// Mimic bindValue and only quote non-integer and non-float data types
|
||||
if (!is_int($binding) && !is_float($binding)) {
|
||||
if ($pdo) {
|
||||
try {
|
||||
$binding = $pdo->quote((string) $binding);
|
||||
} catch (\Exception $e) {
|
||||
$binding = $this->emulateQuote($binding);
|
||||
}
|
||||
} else {
|
||||
$binding = $this->emulateQuote($binding);
|
||||
}
|
||||
}
|
||||
|
||||
$sql = preg_replace($regex, addcslashes($binding, '$'), $sql, 1);
|
||||
}
|
||||
}
|
||||
|
||||
$source = [];
|
||||
|
||||
if (!$limited && $this->findSource) {
|
||||
try {
|
||||
$source = $this->findSource();
|
||||
} catch (\Exception $e) {
|
||||
}
|
||||
}
|
||||
|
||||
$this->queries[] = [
|
||||
'query' => $sql,
|
||||
'type' => 'query',
|
||||
'bindings' => !$limited ? $this->getDataFormatter()->escapeBindings($bindings) : null,
|
||||
'start' => $startTime,
|
||||
'time' => $time,
|
||||
'memory' => $this->lastMemoryUsage ? memory_get_usage(false) - $this->lastMemoryUsage : 0,
|
||||
'source' => $source,
|
||||
'explain' => $explainResults,
|
||||
'connection' => $query->connection->getDatabaseName(),
|
||||
'driver' => $query->connection->getConfig('driver'),
|
||||
'hints' => ($this->showHints && !$limited) ? $hints : null,
|
||||
'show_copy' => $this->showCopyButton,
|
||||
];
|
||||
|
||||
if ($this->timeCollector !== null) {
|
||||
$this->timeCollector->addMeasure(Str::limit($sql, 100), $startTime, $endTime, [], 'db');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Mimic mysql_real_escape_string
|
||||
*
|
||||
* @param string $value
|
||||
* @return string
|
||||
*/
|
||||
protected function emulateQuote($value)
|
||||
{
|
||||
$search = ["\\", "\x00", "\n", "\r", "'", '"', "\x1a"];
|
||||
$replace = ["\\\\","\\0","\\n", "\\r", "\'", '\"', "\\Z"];
|
||||
|
||||
return "'" . str_replace($search, $replace, (string) $value) . "'";
|
||||
}
|
||||
|
||||
/**
|
||||
* Explainer::performQueryAnalysis()
|
||||
*
|
||||
* Perform simple regex analysis on the code
|
||||
*
|
||||
* @package xplain (https://github.com/rap2hpoutre/mysql-xplain-xplain)
|
||||
* @author e-doceo
|
||||
* @copyright 2014
|
||||
* @version $Id$
|
||||
* @access public
|
||||
* @param string $query
|
||||
* @return string[]
|
||||
*/
|
||||
protected function performQueryAnalysis($query)
|
||||
{
|
||||
// @codingStandardsIgnoreStart
|
||||
$hints = [];
|
||||
if (preg_match('/^\\s*SELECT\\s*`?[a-zA-Z0-9]*`?\\.?\\*/i', $query)) {
|
||||
$hints[] = 'Use <code>SELECT *</code> only if you need all columns from table';
|
||||
}
|
||||
if (preg_match('/ORDER BY RAND()/i', $query)) {
|
||||
$hints[] = '<code>ORDER BY RAND()</code> is slow, try to avoid if you can.
|
||||
You can <a href="https://stackoverflow.com/questions/2663710/how-does-mysqls-order-by-rand-work" target="_blank">read this</a>
|
||||
or <a href="https://stackoverflow.com/questions/1244555/how-can-i-optimize-mysqls-order-by-rand-function" target="_blank">this</a>';
|
||||
}
|
||||
if (strpos($query, '!=') !== false) {
|
||||
$hints[] = 'The <code>!=</code> operator is not standard. Use the <code><></code> operator to test for inequality instead.';
|
||||
}
|
||||
if (stripos($query, 'WHERE') === false && preg_match('/^(SELECT) /i', $query)) {
|
||||
$hints[] = 'The <code>SELECT</code> statement has no <code>WHERE</code> clause and could examine many more rows than intended';
|
||||
}
|
||||
if (preg_match('/LIMIT\\s/i', $query) && stripos($query, 'ORDER BY') === false) {
|
||||
$hints[] = '<code>LIMIT</code> without <code>ORDER BY</code> causes non-deterministic results, depending on the query execution plan';
|
||||
}
|
||||
if (preg_match('/LIKE\\s[\'"](%.*?)[\'"]/i', $query, $matches)) {
|
||||
$hints[] = 'An argument has a leading wildcard character: <code>' . $matches[1] . '</code>.
|
||||
The predicate with this argument is not sargable and cannot use an index if one exists.';
|
||||
}
|
||||
return $hints;
|
||||
|
||||
// @codingStandardsIgnoreEnd
|
||||
}
|
||||
|
||||
/**
|
||||
* Use a backtrace to search for the origins of the query.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function findSource()
|
||||
{
|
||||
$stack = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS | DEBUG_BACKTRACE_PROVIDE_OBJECT, app('config')->get('debugbar.debug_backtrace_limit', 50));
|
||||
|
||||
$sources = [];
|
||||
|
||||
foreach ($stack as $index => $trace) {
|
||||
$sources[] = $this->parseTrace($index, $trace);
|
||||
}
|
||||
|
||||
return array_slice(array_filter($sources), 0, is_int($this->findSource) ? $this->findSource : 5);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a trace element from the backtrace stack.
|
||||
*
|
||||
* @param int $index
|
||||
* @param array $trace
|
||||
* @return object|bool
|
||||
*/
|
||||
protected function parseTrace($index, array $trace)
|
||||
{
|
||||
$frame = (object) [
|
||||
'index' => $index,
|
||||
'namespace' => null,
|
||||
'name' => null,
|
||||
'file' => null,
|
||||
'line' => $trace['line'] ?? '1',
|
||||
];
|
||||
|
||||
if (isset($trace['function']) && $trace['function'] == 'substituteBindings') {
|
||||
$frame->name = 'Route binding';
|
||||
|
||||
return $frame;
|
||||
}
|
||||
|
||||
if (
|
||||
isset($trace['class']) &&
|
||||
isset($trace['file']) &&
|
||||
!$this->fileIsInExcludedPath($trace['file'])
|
||||
) {
|
||||
$frame->file = $trace['file'];
|
||||
|
||||
if (isset($trace['object']) && is_a($trace['object'], '\Twig\Template')) {
|
||||
list($frame->file, $frame->line) = $this->getTwigInfo($trace);
|
||||
} elseif (strpos($frame->file, storage_path()) !== false) {
|
||||
$hash = pathinfo($frame->file, PATHINFO_FILENAME);
|
||||
|
||||
if ($frame->name = $this->findViewFromHash($hash)) {
|
||||
$frame->file = $frame->name[1];
|
||||
$frame->name = $frame->name[0];
|
||||
} else {
|
||||
$frame->name = $hash;
|
||||
}
|
||||
|
||||
$frame->namespace = 'view';
|
||||
|
||||
return $frame;
|
||||
} elseif (strpos($frame->file, 'Middleware') !== false) {
|
||||
$frame->name = $this->findMiddlewareFromFile($frame->file);
|
||||
|
||||
if ($frame->name) {
|
||||
$frame->namespace = 'middleware';
|
||||
} else {
|
||||
$frame->name = $this->normalizeFilePath($frame->file);
|
||||
}
|
||||
|
||||
return $frame;
|
||||
}
|
||||
|
||||
$frame->name = $this->normalizeFilePath($frame->file);
|
||||
|
||||
return $frame;
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given file is to be excluded from analysis
|
||||
*
|
||||
* @param string $file
|
||||
* @return bool
|
||||
*/
|
||||
protected function fileIsInExcludedPath($file)
|
||||
{
|
||||
$normalizedPath = str_replace('\\', '/', $file);
|
||||
|
||||
foreach ($this->backtraceExcludePaths as $excludedPath) {
|
||||
if (strpos($normalizedPath, $excludedPath) !== false) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the middleware alias from the file.
|
||||
*
|
||||
* @param string $file
|
||||
* @return string|null
|
||||
*/
|
||||
protected function findMiddlewareFromFile($file)
|
||||
{
|
||||
$filename = pathinfo($file, PATHINFO_FILENAME);
|
||||
|
||||
foreach ($this->middleware as $alias => $class) {
|
||||
if (strpos($class, $filename) !== false) {
|
||||
return $alias;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the template name from the hash.
|
||||
*
|
||||
* @param string $hash
|
||||
* @return null|array
|
||||
*/
|
||||
protected function findViewFromHash($hash)
|
||||
{
|
||||
$finder = app('view')->getFinder();
|
||||
|
||||
if (isset($this->reflection['viewfinderViews'])) {
|
||||
$property = $this->reflection['viewfinderViews'];
|
||||
} else {
|
||||
$reflection = new \ReflectionClass($finder);
|
||||
$property = $reflection->getProperty('views');
|
||||
$property->setAccessible(true);
|
||||
$this->reflection['viewfinderViews'] = $property;
|
||||
}
|
||||
|
||||
$xxh128Exists = in_array('xxh128', hash_algos());
|
||||
|
||||
foreach ($property->getValue($finder) as $name => $path) {
|
||||
if (($xxh128Exists && hash('xxh128', 'v2' . $path) == $hash) || sha1('v2' . $path) == $hash) {
|
||||
return [$name, $path];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the filename/line from a Twig template trace
|
||||
*
|
||||
* @param array $trace
|
||||
* @return array The file and line
|
||||
*/
|
||||
protected function getTwigInfo($trace)
|
||||
{
|
||||
$file = $trace['object']->getTemplateName();
|
||||
|
||||
if (isset($trace['line'])) {
|
||||
foreach ($trace['object']->getDebugInfo() as $codeLine => $templateLine) {
|
||||
if ($codeLine <= $trace['line']) {
|
||||
return [$file, $templateLine];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return [$file, -1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Collect a database transaction event.
|
||||
* @param string $event
|
||||
* @param \Illuminate\Database\Connection $connection
|
||||
* @return array
|
||||
*/
|
||||
public function collectTransactionEvent($event, $connection)
|
||||
{
|
||||
$source = [];
|
||||
|
||||
if ($this->findSource) {
|
||||
try {
|
||||
$source = $this->findSource();
|
||||
} catch (\Exception $e) {
|
||||
}
|
||||
}
|
||||
|
||||
$this->queries[] = [
|
||||
'query' => $event,
|
||||
'type' => 'transaction',
|
||||
'bindings' => [],
|
||||
'start' => microtime(true),
|
||||
'time' => 0,
|
||||
'memory' => 0,
|
||||
'source' => $source,
|
||||
'explain' => [],
|
||||
'connection' => $connection->getDatabaseName(),
|
||||
'driver' => $connection->getConfig('driver'),
|
||||
'hints' => null,
|
||||
'show_copy' => false,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the queries.
|
||||
*/
|
||||
public function reset()
|
||||
{
|
||||
$this->queries = [];
|
||||
$this->queryCount = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function collect()
|
||||
{
|
||||
$totalTime = 0;
|
||||
$totalMemory = 0;
|
||||
$queries = $this->queries;
|
||||
|
||||
$statements = [];
|
||||
foreach ($queries as $query) {
|
||||
$source = reset($query['source']);
|
||||
$totalTime += $query['time'];
|
||||
$totalMemory += $query['memory'];
|
||||
|
||||
if (str_ends_with($query['connection'], '.sqlite')) {
|
||||
$query['connection'] = $this->normalizeFilePath($query['connection']);
|
||||
}
|
||||
|
||||
$statements[] = [
|
||||
'sql' => $this->getDataFormatter()->formatSql($query['query']),
|
||||
'type' => $query['type'],
|
||||
'params' => [],
|
||||
'bindings' => $query['bindings'],
|
||||
'hints' => $query['hints'],
|
||||
'show_copy' => $query['show_copy'],
|
||||
'backtrace' => array_values($query['source']),
|
||||
'start' => $query['start'] ?? null,
|
||||
'duration' => $query['time'],
|
||||
'duration_str' => ($query['type'] == 'transaction') ? '' : $this->formatDuration($query['time']),
|
||||
'memory' => $query['memory'],
|
||||
'memory_str' => $query['memory'] ? $this->getDataFormatter()->formatBytes($query['memory']) : null,
|
||||
'filename' => $this->getDataFormatter()->formatSource($source, true),
|
||||
'source' => $this->getDataFormatter()->formatSource($source),
|
||||
'xdebug_link' => is_object($source) ? $this->getXdebugLink($source->file ?: '', $source->line) : null,
|
||||
'connection' => $query['connection'],
|
||||
];
|
||||
|
||||
if ($query['explain']) {
|
||||
// Add the results from the EXPLAIN as new rows
|
||||
if ($query['driver'] === 'pgsql') {
|
||||
$explainer = trim(implode("\n", array_map(function ($explain) {
|
||||
return $explain->{'QUERY PLAN'};
|
||||
}, $query['explain'])));
|
||||
|
||||
if ($explainer) {
|
||||
$statements[] = [
|
||||
'sql' => " - EXPLAIN: {$explainer}",
|
||||
'type' => 'explain',
|
||||
];
|
||||
}
|
||||
} elseif ($query['driver'] === 'sqlite') {
|
||||
$vmi = '<table style="margin:-5px -11px !important;width: 100% !important">';
|
||||
$vmi .= "<thead><tr>
|
||||
<td>Address</td>
|
||||
<td>Opcode</td>
|
||||
<td>P1</td>
|
||||
<td>P2</td>
|
||||
<td>P3</td>
|
||||
<td>P4</td>
|
||||
<td>P5</td>
|
||||
<td>Comment</td>
|
||||
</tr></thead>";
|
||||
|
||||
foreach ($query['explain'] as $explain) {
|
||||
$vmi .= "<tr>
|
||||
<td>{$explain->addr}</td>
|
||||
<td>{$explain->opcode}</td>
|
||||
<td>{$explain->p1}</td>
|
||||
<td>{$explain->p2}</td>
|
||||
<td>{$explain->p3}</td>
|
||||
<td>{$explain->p4}</td>
|
||||
<td>{$explain->p5}</td>
|
||||
<td>{$explain->comment}</td>
|
||||
</tr>";
|
||||
}
|
||||
|
||||
$vmi .= '</table>';
|
||||
|
||||
$statements[] = [
|
||||
'sql' => " - EXPLAIN:",
|
||||
'type' => 'explain',
|
||||
'params' => [
|
||||
'Virtual Machine Instructions' => $vmi,
|
||||
]
|
||||
];
|
||||
} else {
|
||||
foreach ($query['explain'] as $explain) {
|
||||
$statements[] = [
|
||||
'sql' => " - EXPLAIN # {$explain->id}: `{$explain->table}` ({$explain->select_type})",
|
||||
'type' => 'explain',
|
||||
'params' => $explain,
|
||||
'row_count' => $explain->rows,
|
||||
'stmt_id' => $explain->id,
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->durationBackground) {
|
||||
if ($totalTime > 0) {
|
||||
// For showing background measure on Queries tab
|
||||
$start_percent = 0;
|
||||
|
||||
foreach ($statements as $i => $statement) {
|
||||
if (!isset($statement['duration'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$width_percent = $statement['duration'] / $totalTime * 100;
|
||||
|
||||
$statements[$i] = array_merge($statement, [
|
||||
'start_percent' => round($start_percent, 3),
|
||||
'width_percent' => round($width_percent, 3),
|
||||
]);
|
||||
|
||||
$start_percent += $width_percent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->softLimit && $this->hardLimit && ($this->queryCount > $this->softLimit && $this->queryCount > $this->hardLimit)) {
|
||||
array_unshift($statements, [
|
||||
'sql' => '# Query soft and hard limit for Debugbar are reached. Only the first ' . $this->softLimit . ' queries show details. Queries after the first ' . $this->hardLimit . ' are ignored. Limits can be raised in the config (debugbar.options.db.soft/hard_limit).',
|
||||
'type' => 'info',
|
||||
]);
|
||||
$statements[] = [
|
||||
'sql' => '... ' . ($this->queryCount - $this->hardLimit) . ' additional queries are executed but now shown because of Debugbar query limits. Limits can be raised in the config (debugbar.options.db.soft/hard_limit)',
|
||||
'type' => 'info',
|
||||
];
|
||||
} elseif ($this->hardLimit && $this->queryCount > $this->hardLimit) {
|
||||
array_unshift($statements, [
|
||||
'sql' => '# Query hard limit for Debugbar is reached after ' . $this->hardLimit . ' queries, additional ' . ($this->queryCount - $this->hardLimit) . ' queries are not shown.. Limits can be raised in the config (debugbar.options.db.hard_limit)',
|
||||
'type' => 'info',
|
||||
]);
|
||||
$statements[] = [
|
||||
'sql' => '... ' . ($this->queryCount - $this->hardLimit) . ' additional queries are executed but now shown because of Debugbar query limits. Limits can be raised in the config (debugbar.options.db.hard_limit)',
|
||||
'type' => 'info',
|
||||
];
|
||||
} elseif ($this->softLimit && $this->queryCount > $this->softLimit) {
|
||||
array_unshift($statements, [
|
||||
'sql' => '# Query soft limit for Debugbar is reached after ' . $this->softLimit . ' queries, additional ' . ($this->queryCount - $this->softLimit) . ' queries only show the query. Limit can be raised in the config. Limits can be raised in the config (debugbar.options.db.soft_limit)',
|
||||
'type' => 'info',
|
||||
]);
|
||||
}
|
||||
|
||||
$data = [
|
||||
'nb_statements' => $this->queryCount,
|
||||
'nb_failed_statements' => 0,
|
||||
'accumulated_duration' => $totalTime,
|
||||
'accumulated_duration_str' => $this->formatDuration($totalTime),
|
||||
'memory_usage' => $totalMemory,
|
||||
'memory_usage_str' => $totalMemory ? $this->getDataFormatter()->formatBytes($totalMemory) : null,
|
||||
'statements' => $statements
|
||||
];
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'queries';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getWidgets()
|
||||
{
|
||||
return [
|
||||
"queries" => [
|
||||
"icon" => "database",
|
||||
"widget" => "PhpDebugBar.Widgets.SQLQueriesWidget",
|
||||
"map" => "queries",
|
||||
"default" => "[]"
|
||||
],
|
||||
"queries:badge" => [
|
||||
"map" => "queries.nb_statements",
|
||||
"default" => 0
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,194 @@
|
||||
<?php
|
||||
|
||||
namespace Barryvdh\Debugbar\DataCollector;
|
||||
|
||||
use DebugBar\DataCollector\DataCollector;
|
||||
use DebugBar\DataCollector\DataCollectorInterface;
|
||||
use DebugBar\DataCollector\Renderable;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Str;
|
||||
use Laravel\Telescope\IncomingEntry;
|
||||
use Laravel\Telescope\Telescope;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
/**
|
||||
*
|
||||
* Based on \Symfony\Component\HttpKernel\DataCollector\RequestDataCollector by Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
*/
|
||||
class RequestCollector extends DataCollector implements DataCollectorInterface, Renderable
|
||||
{
|
||||
/** @var \Symfony\Component\HttpFoundation\Request $request */
|
||||
protected $request;
|
||||
/** @var \Symfony\Component\HttpFoundation\Request $response */
|
||||
protected $response;
|
||||
/** @var \Symfony\Component\HttpFoundation\Session\SessionInterface $session */
|
||||
protected $session;
|
||||
/** @var string|null */
|
||||
protected $currentRequestId;
|
||||
/** @var array */
|
||||
protected $hiddens;
|
||||
|
||||
/**
|
||||
* Create a new SymfonyRequestCollector
|
||||
*
|
||||
* @param \Symfony\Component\HttpFoundation\Request $request
|
||||
* @param \Symfony\Component\HttpFoundation\Response $response
|
||||
* @param \Symfony\Component\HttpFoundation\Session\SessionInterface $session
|
||||
* @param string|null $currentRequestId
|
||||
* @param array $hiddens
|
||||
*/
|
||||
public function __construct($request, $response, $session = null, $currentRequestId = null, $hiddens = [])
|
||||
{
|
||||
$this->request = $request;
|
||||
$this->response = $response;
|
||||
$this->session = $session;
|
||||
$this->currentRequestId = $currentRequestId;
|
||||
$this->hiddens = array_merge($hiddens, [
|
||||
'request_request.password',
|
||||
'request_headers.php-auth-pw.0',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'request';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getWidgets()
|
||||
{
|
||||
return [
|
||||
"request" => [
|
||||
"icon" => "tags",
|
||||
"widget" => "PhpDebugBar.Widgets.HtmlVariableListWidget",
|
||||
"map" => "request",
|
||||
"default" => "{}"
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function collect()
|
||||
{
|
||||
$request = $this->request;
|
||||
$response = $this->response;
|
||||
|
||||
$responseHeaders = $response->headers->all();
|
||||
$cookies = [];
|
||||
foreach ($response->headers->getCookies() as $cookie) {
|
||||
$cookies[] = $this->getCookieHeader(
|
||||
$cookie->getName(),
|
||||
$cookie->getValue(),
|
||||
$cookie->getExpiresTime(),
|
||||
$cookie->getPath(),
|
||||
$cookie->getDomain(),
|
||||
$cookie->isSecure(),
|
||||
$cookie->isHttpOnly()
|
||||
);
|
||||
}
|
||||
if (count($cookies) > 0) {
|
||||
$responseHeaders['Set-Cookie'] = $cookies;
|
||||
}
|
||||
|
||||
$statusCode = $response->getStatusCode();
|
||||
|
||||
$data = [
|
||||
'path_info' => $request->getPathInfo(),
|
||||
'status_code' => $statusCode,
|
||||
'status_text' => isset(Response::$statusTexts[$statusCode]) ? Response::$statusTexts[$statusCode] : '',
|
||||
'format' => $request->getRequestFormat(),
|
||||
'content_type' => $response->headers->get('Content-Type') ? $response->headers->get(
|
||||
'Content-Type'
|
||||
) : 'text/html',
|
||||
'request_query' => $request->query->all(),
|
||||
'request_request' => $request->request->all(),
|
||||
'request_headers' => $request->headers->all(),
|
||||
'request_cookies' => $request->cookies->all(),
|
||||
'response_headers' => $responseHeaders,
|
||||
];
|
||||
|
||||
if ($this->session) {
|
||||
$data['session_attributes'] = $this->session->all();
|
||||
}
|
||||
|
||||
if (isset($data['request_headers']['authorization'][0])) {
|
||||
$data['request_headers']['authorization'][0] = substr($data['request_headers']['authorization'][0], 0, 12) . '******';
|
||||
}
|
||||
|
||||
foreach ($this->hiddens as $key) {
|
||||
if (Arr::has($data, $key)) {
|
||||
Arr::set($data, $key, '******');
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($data as $key => $var) {
|
||||
if (!is_string($data[$key])) {
|
||||
$data[$key] = DataCollector::getDefaultVarDumper()->renderVar($var);
|
||||
} else {
|
||||
$data[$key] = e($data[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
$htmlData = [];
|
||||
if (class_exists(Telescope::class)) {
|
||||
$entry = IncomingEntry::make([
|
||||
'requestId' => $this->currentRequestId,
|
||||
])->type('debugbar');
|
||||
Telescope::$entriesQueue[] = $entry;
|
||||
$url = route('debugbar.telescope', [$entry->uuid]);
|
||||
$htmlData['telescope'] = '<a href="' . $url . '" target="_blank">View in Telescope</a>';
|
||||
}
|
||||
|
||||
return $htmlData + $data;
|
||||
}
|
||||
|
||||
private function getCookieHeader($name, $value, $expires, $path, $domain, $secure, $httponly)
|
||||
{
|
||||
$cookie = sprintf('%s=%s', $name, urlencode($value));
|
||||
|
||||
if (0 !== $expires) {
|
||||
if (is_numeric($expires)) {
|
||||
$expires = (int) $expires;
|
||||
} elseif ($expires instanceof \DateTime) {
|
||||
$expires = $expires->getTimestamp();
|
||||
} else {
|
||||
$expires = strtotime($expires);
|
||||
if (false === $expires || -1 == $expires) {
|
||||
throw new \InvalidArgumentException(
|
||||
sprintf('The "expires" cookie parameter is not valid.', $expires)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$cookie .= '; expires=' . substr(
|
||||
\DateTime::createFromFormat('U', $expires, new \DateTimeZone('UTC'))->format('D, d-M-Y H:i:s T'),
|
||||
0,
|
||||
-5
|
||||
);
|
||||
}
|
||||
|
||||
if ($domain) {
|
||||
$cookie .= '; domain=' . $domain;
|
||||
}
|
||||
|
||||
$cookie .= '; path=' . $path;
|
||||
|
||||
if ($secure) {
|
||||
$cookie .= '; secure';
|
||||
}
|
||||
|
||||
if ($httponly) {
|
||||
$cookie .= '; httponly';
|
||||
}
|
||||
|
||||
return $cookie;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,177 @@
|
||||
<?php
|
||||
|
||||
namespace Barryvdh\Debugbar\DataCollector;
|
||||
|
||||
use Closure;
|
||||
use DebugBar\DataCollector\DataCollector;
|
||||
use DebugBar\DataCollector\Renderable;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Routing\Route;
|
||||
use Illuminate\Routing\Router;
|
||||
use Illuminate\Support\Facades\Config;
|
||||
|
||||
/**
|
||||
* Based on Illuminate\Foundation\Console\RoutesCommand for Taylor Otwell
|
||||
* https://github.com/laravel/framework/blob/master/src/Illuminate/Foundation/Console/RoutesCommand.php
|
||||
*
|
||||
*/
|
||||
class RouteCollector extends DataCollector implements Renderable
|
||||
{
|
||||
/**
|
||||
* The router instance.
|
||||
*
|
||||
* @var \Illuminate\Routing\Router
|
||||
*/
|
||||
protected $router;
|
||||
|
||||
public function __construct(Router $router)
|
||||
{
|
||||
$this->router = $router;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function collect()
|
||||
{
|
||||
$route = $this->router->current();
|
||||
return $this->getRouteInformation($route);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the route information for a given route.
|
||||
*
|
||||
* @param \Illuminate\Routing\Route $route
|
||||
* @return array
|
||||
*/
|
||||
protected function getRouteInformation($route)
|
||||
{
|
||||
if (!is_a($route, 'Illuminate\Routing\Route')) {
|
||||
return [];
|
||||
}
|
||||
$uri = head($route->methods()) . ' ' . $route->uri();
|
||||
$action = $route->getAction();
|
||||
|
||||
$result = [
|
||||
'uri' => $uri ?: '-',
|
||||
];
|
||||
|
||||
$result = array_merge($result, $action);
|
||||
$uses = $action['uses'] ?? null;
|
||||
$controller = is_string($action['controller'] ?? null) ? $action['controller'] : '';
|
||||
|
||||
if (request()->hasHeader('X-Livewire')) {
|
||||
try {
|
||||
$component = request('components')[0];
|
||||
$name = json_decode($component['snapshot'], true)['memo']['name'];
|
||||
$method = $component['calls'][0]['method'];
|
||||
$class = app(\Livewire\Mechanisms\ComponentRegistry::class)->getClass($name);
|
||||
if (class_exists($class) && method_exists($class, $method)) {
|
||||
$controller = $class . '@' . $method;
|
||||
$result['controller'] = ltrim($controller, '\\');
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
//
|
||||
}
|
||||
}
|
||||
|
||||
if (str_contains($controller, '@')) {
|
||||
list($controller, $method) = explode('@', $controller);
|
||||
if (class_exists($controller) && method_exists($controller, $method)) {
|
||||
$reflector = new \ReflectionMethod($controller, $method);
|
||||
}
|
||||
unset($result['uses']);
|
||||
} elseif ($uses instanceof \Closure) {
|
||||
$reflector = new \ReflectionFunction($uses);
|
||||
$result['uses'] = $this->formatVar($uses);
|
||||
} elseif (is_string($uses) && str_contains($uses, '@__invoke')) {
|
||||
if (class_exists($controller) && method_exists($controller, 'render')) {
|
||||
$reflector = new \ReflectionMethod($controller, 'render');
|
||||
$result['controller'] = $controller . '@render';
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($reflector)) {
|
||||
$filename = $this->normalizeFilePath($reflector->getFileName());
|
||||
|
||||
if ($link = $this->getXdebugLink($reflector->getFileName(), $reflector->getStartLine())) {
|
||||
$result['file'] = sprintf(
|
||||
'<a href="%s" onclick="%s">%s:%s-%s</a>',
|
||||
$link['url'],
|
||||
$link['ajax'] ? 'event.preventDefault();$.ajax(this.href);' : '',
|
||||
$filename,
|
||||
$reflector->getStartLine(),
|
||||
$reflector->getEndLine()
|
||||
);
|
||||
} else {
|
||||
$result['file'] = sprintf('%s:%s-%s', $filename, $reflector->getStartLine(), $reflector->getEndLine());
|
||||
}
|
||||
}
|
||||
|
||||
if ($middleware = $this->getMiddleware($route)) {
|
||||
$result['middleware'] = $middleware;
|
||||
}
|
||||
|
||||
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get middleware
|
||||
*
|
||||
* @param \Illuminate\Routing\Route $route
|
||||
* @return string
|
||||
*/
|
||||
protected function getMiddleware($route)
|
||||
{
|
||||
return implode(', ', array_map(function ($middleware) {
|
||||
return $middleware instanceof Closure ? 'Closure' : $middleware;
|
||||
}, $route->gatherMiddleware()));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'route';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getWidgets()
|
||||
{
|
||||
$widgets = [
|
||||
"route" => [
|
||||
"icon" => "share",
|
||||
"widget" => "PhpDebugBar.Widgets.HtmlVariableListWidget",
|
||||
"map" => "route",
|
||||
"default" => "{}"
|
||||
]
|
||||
];
|
||||
if (Config::get('debugbar.options.route.label', true)) {
|
||||
$widgets['currentroute'] = [
|
||||
"icon" => "share",
|
||||
"tooltip" => "Route",
|
||||
"map" => "route.uri",
|
||||
"default" => ""
|
||||
];
|
||||
}
|
||||
return $widgets;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the route information on the console.
|
||||
*
|
||||
* @param array $routes
|
||||
* @return void
|
||||
*/
|
||||
protected function displayRoutes(array $routes)
|
||||
{
|
||||
$this->table->setHeaders($this->headers)->setRows($routes);
|
||||
|
||||
$this->table->render($this->getOutput());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
namespace Barryvdh\Debugbar\DataCollector;
|
||||
|
||||
use DebugBar\DataCollector\DataCollector;
|
||||
use DebugBar\DataCollector\DataCollectorInterface;
|
||||
use DebugBar\DataCollector\Renderable;
|
||||
use Illuminate\Support\Arr;
|
||||
|
||||
class SessionCollector extends DataCollector implements DataCollectorInterface, Renderable
|
||||
{
|
||||
/** @var \Symfony\Component\HttpFoundation\Session\SessionInterface|\Illuminate\Contracts\Session\Session $session */
|
||||
protected $session;
|
||||
/** @var array */
|
||||
protected $hiddens;
|
||||
|
||||
/**
|
||||
* Create a new SessionCollector
|
||||
*
|
||||
* @param \Symfony\Component\HttpFoundation\Session\SessionInterface|\Illuminate\Contracts\Session\Session $session
|
||||
* @param array $hiddens
|
||||
*/
|
||||
public function __construct($session, $hiddens = [])
|
||||
{
|
||||
$this->session = $session;
|
||||
$this->hiddens = $hiddens;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function collect()
|
||||
{
|
||||
$data = $this->session->all();
|
||||
|
||||
foreach ($this->hiddens as $key) {
|
||||
if (Arr::has($data, $key)) {
|
||||
Arr::set($data, $key, '******');
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($data as $key => $value) {
|
||||
$data[$key] = is_string($value) ? $value : $this->formatVar($value);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'session';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getWidgets()
|
||||
{
|
||||
return [
|
||||
"session" => [
|
||||
"icon" => "archive",
|
||||
"widget" => "PhpDebugBar.Widgets.VariableListWidget",
|
||||
"map" => "session",
|
||||
"default" => "{}"
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,199 @@
|
||||
<?php
|
||||
|
||||
namespace Barryvdh\Debugbar\DataCollector;
|
||||
|
||||
use Barryvdh\Debugbar\DataFormatter\SimpleFormatter;
|
||||
use DebugBar\DataCollector\AssetProvider;
|
||||
use DebugBar\DataCollector\DataCollector;
|
||||
use DebugBar\DataCollector\Renderable;
|
||||
use Illuminate\View\View;
|
||||
|
||||
class ViewCollector extends DataCollector implements Renderable, AssetProvider
|
||||
{
|
||||
protected $name;
|
||||
protected $templates = [];
|
||||
protected $collect_data;
|
||||
protected $exclude_paths;
|
||||
protected $group;
|
||||
|
||||
/**
|
||||
* Create a ViewCollector
|
||||
*
|
||||
* @param bool|string $collectData Collects view data when true
|
||||
* @param string[] $excludePaths Paths to exclude from collection
|
||||
* @param int|bool $group Group the same templates together
|
||||
* */
|
||||
public function __construct($collectData = true, $excludePaths = [], $group = true)
|
||||
{
|
||||
$this->setDataFormatter(new SimpleFormatter());
|
||||
$this->collect_data = $collectData;
|
||||
$this->templates = [];
|
||||
$this->exclude_paths = $excludePaths;
|
||||
$this->group = $group;
|
||||
}
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return 'views';
|
||||
}
|
||||
|
||||
public function getWidgets()
|
||||
{
|
||||
return [
|
||||
'views' => [
|
||||
'icon' => 'leaf',
|
||||
'widget' => 'PhpDebugBar.Widgets.TemplatesWidget',
|
||||
'map' => 'views',
|
||||
'default' => '[]'
|
||||
],
|
||||
'views:badge' => [
|
||||
'map' => 'views.nb_templates',
|
||||
'default' => 0
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getAssets()
|
||||
{
|
||||
return [
|
||||
'css' => 'widgets/templates/widget.css',
|
||||
'js' => 'widgets/templates/widget.js',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a View instance to the Collector
|
||||
*
|
||||
* @param \Illuminate\View\View $view
|
||||
*/
|
||||
public function addView(View $view)
|
||||
{
|
||||
$name = $view->getName();
|
||||
$type = null;
|
||||
$data = $view->getData();
|
||||
$path = $view->getPath();
|
||||
|
||||
if (class_exists('\Inertia\Inertia')) {
|
||||
list($name, $type, $data, $path) = $this->getInertiaView($name, $data, $path);
|
||||
}
|
||||
|
||||
if (is_object($path)) {
|
||||
$type = get_class($view);
|
||||
$path = null;
|
||||
}
|
||||
|
||||
if ($path) {
|
||||
if (!$type) {
|
||||
if (substr($path, -10) == '.blade.php') {
|
||||
$type = 'blade';
|
||||
} else {
|
||||
$type = pathinfo($path, PATHINFO_EXTENSION);
|
||||
}
|
||||
}
|
||||
|
||||
$shortPath = $this->normalizeFilePath($path);
|
||||
foreach ($this->exclude_paths as $excludePath) {
|
||||
if (str_starts_with($shortPath, $excludePath)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->addTemplate($name, $data, $type, $path);
|
||||
}
|
||||
|
||||
private function getInertiaView(string $name, array $data, ?string $path)
|
||||
{
|
||||
if (isset($data['page']) && is_array($data['page'])) {
|
||||
$data = $data['page'];
|
||||
}
|
||||
|
||||
if (isset($data['props'], $data['component'])) {
|
||||
$name = $data['component'];
|
||||
$data = $data['props'];
|
||||
|
||||
if ($files = glob(resource_path('js/Pages/' . $name . '.*'))) {
|
||||
$path = $files[0];
|
||||
$type = pathinfo($path, PATHINFO_EXTENSION);
|
||||
|
||||
if (in_array($type, ['js', 'jsx'])) {
|
||||
$type = 'react';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return [$name, $type ?? '', $data, $path];
|
||||
}
|
||||
|
||||
public function addInertiaAjaxView(array $data)
|
||||
{
|
||||
list($name, $type, $data, $path) = $this->getInertiaView('', $data, '');
|
||||
|
||||
if (! $name) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->addTemplate($name, $data, $type, $path);
|
||||
}
|
||||
|
||||
private function addTemplate(string $name, array $data, ?string $type, ?string $path)
|
||||
{
|
||||
// Prevent duplicates
|
||||
$hash = $type . $path . $name . ($this->collect_data ? implode(array_keys($data)) : '');
|
||||
|
||||
if ($this->collect_data === 'keys') {
|
||||
$params = array_keys($data);
|
||||
} elseif ($this->collect_data) {
|
||||
$params = array_map(
|
||||
fn ($value) => $this->getDataFormatter()->formatVar($value),
|
||||
$data
|
||||
);
|
||||
} else {
|
||||
$params = [];
|
||||
}
|
||||
|
||||
$template = [
|
||||
'name' => $name,
|
||||
'param_count' => $this->collect_data ? count($params) : null,
|
||||
'params' => $params,
|
||||
'start' => microtime(true),
|
||||
'type' => $type,
|
||||
'hash' => $hash,
|
||||
];
|
||||
|
||||
if ($path && $this->getXdebugLinkTemplate()) {
|
||||
$template['xdebug_link'] = $this->getXdebugLink($path);
|
||||
}
|
||||
|
||||
$this->templates[] = $template;
|
||||
}
|
||||
|
||||
public function collect()
|
||||
{
|
||||
if ($this->group === true || count($this->templates) > $this->group) {
|
||||
$templates = [];
|
||||
foreach ($this->templates as $template) {
|
||||
$hash = $template['hash'];
|
||||
if (!isset($templates[$hash])) {
|
||||
$template['render_count'] = 0;
|
||||
$template['name_original'] = $template['name'];
|
||||
$templates[$hash] = $template;
|
||||
}
|
||||
|
||||
$templates[$hash]['render_count']++;
|
||||
$templates[$hash]['name'] = $templates[$hash]['render_count'] . 'x ' . $templates[$hash]['name_original'];
|
||||
}
|
||||
$templates = array_values($templates);
|
||||
} else {
|
||||
$templates = $this->templates;
|
||||
}
|
||||
|
||||
return [
|
||||
'nb_templates' => count($this->templates),
|
||||
'templates' => $templates,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
namespace Barryvdh\Debugbar\DataFormatter;
|
||||
|
||||
use DebugBar\DataFormatter\DataFormatter;
|
||||
|
||||
#[\AllowDynamicProperties]
|
||||
class QueryFormatter extends DataFormatter
|
||||
{
|
||||
/**
|
||||
* Removes extra spaces at the beginning and end of the SQL query and its lines.
|
||||
*
|
||||
* @param string $sql
|
||||
* @return string
|
||||
*/
|
||||
public function formatSql($sql)
|
||||
{
|
||||
$sql = preg_replace("/\?(?=(?:[^'\\\']*'[^'\\']*')*[^'\\\']*$)(?:\?)/", '?', $sql);
|
||||
$sql = trim(preg_replace("/\s*\n\s*/", "\n", $sql));
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check bindings for illegal (non UTF-8) strings, like Binary data.
|
||||
*
|
||||
* @param $bindings
|
||||
* @return mixed
|
||||
*/
|
||||
public function checkBindings($bindings)
|
||||
{
|
||||
foreach ($bindings as &$binding) {
|
||||
if (is_string($binding) && !mb_check_encoding($binding, 'UTF-8')) {
|
||||
$binding = '[BINARY DATA]';
|
||||
}
|
||||
|
||||
if (is_array($binding)) {
|
||||
$binding = $this->checkBindings($binding);
|
||||
$binding = '[' . implode(',', $binding) . ']';
|
||||
}
|
||||
|
||||
if (is_object($binding)) {
|
||||
$binding = json_encode($binding);
|
||||
}
|
||||
}
|
||||
|
||||
return $bindings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the bindings safe for outputting.
|
||||
*
|
||||
* @param array $bindings
|
||||
* @return array
|
||||
*/
|
||||
public function escapeBindings($bindings)
|
||||
{
|
||||
foreach ($bindings as &$binding) {
|
||||
$binding = htmlentities((string) $binding, ENT_QUOTES, 'UTF-8', false);
|
||||
}
|
||||
|
||||
return $bindings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a source object.
|
||||
*
|
||||
* @param object|null $source If the backtrace is disabled, the $source will be null.
|
||||
* @return string
|
||||
*/
|
||||
public function formatSource($source, $short = false)
|
||||
{
|
||||
if (! is_object($source)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$parts = [];
|
||||
|
||||
if (!$short && $source->namespace) {
|
||||
$parts['namespace'] = $source->namespace . '::';
|
||||
}
|
||||
|
||||
$parts['name'] = $short ? basename($source->name) : $source->name;
|
||||
$parts['line'] = ':' . $source->line;
|
||||
|
||||
return implode($parts);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
<?php
|
||||
|
||||
namespace Barryvdh\Debugbar\DataFormatter;
|
||||
|
||||
use DebugBar\DataFormatter\DataFormatter;
|
||||
|
||||
/**
|
||||
* Simple DataFormatter based on the deprecated Symfony ValueExporter
|
||||
*
|
||||
* @see https://github.com/symfony/symfony/blob/v3.4.4/src/Symfony/Component/HttpKernel/DataCollector/Util/ValueExporter.php
|
||||
*/
|
||||
#[\AllowDynamicProperties]
|
||||
class SimpleFormatter extends DataFormatter
|
||||
{
|
||||
/**
|
||||
* @param $data
|
||||
* @return string
|
||||
*/
|
||||
public function formatVar($data)
|
||||
{
|
||||
return $this->exportValue($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a PHP value to a string.
|
||||
*
|
||||
* @param mixed $value The PHP value
|
||||
* @param int $depth Only for internal usage
|
||||
* @param bool $deep Only for internal usage
|
||||
*
|
||||
* @return string The string representation of the given value
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
private function exportValue($value, $depth = 1, $deep = false)
|
||||
{
|
||||
if ($value instanceof \__PHP_Incomplete_Class) {
|
||||
return sprintf('__PHP_Incomplete_Class(%s)', $this->getClassNameFromIncomplete($value));
|
||||
}
|
||||
|
||||
if (is_object($value)) {
|
||||
if ($value instanceof \DateTimeInterface) {
|
||||
return sprintf('Object(%s) - %s', get_class($value), $value->format(\DateTime::ATOM));
|
||||
}
|
||||
|
||||
return sprintf('Object(%s)', get_class($value));
|
||||
}
|
||||
|
||||
if (is_array($value)) {
|
||||
if (empty($value)) {
|
||||
return '[]';
|
||||
}
|
||||
|
||||
$indent = str_repeat(' ', $depth);
|
||||
|
||||
$a = [];
|
||||
foreach ($value as $k => $v) {
|
||||
if (is_array($v)) {
|
||||
$deep = true;
|
||||
}
|
||||
$a[] = sprintf('%s => %s', $k, $this->exportValue($v, $depth + 1, $deep));
|
||||
}
|
||||
|
||||
if ($deep) {
|
||||
$args = [$indent, implode(sprintf(", \n%s", $indent), $a), str_repeat(' ', $depth - 1)];
|
||||
return sprintf("[\n%s%s\n%s]", ...$args);
|
||||
}
|
||||
|
||||
$s = sprintf('[%s]', implode(', ', $a));
|
||||
|
||||
if (80 > strlen($s)) {
|
||||
return $s;
|
||||
}
|
||||
|
||||
return sprintf("[\n%s%s\n]", $indent, implode(sprintf(",\n%s", $indent), $a));
|
||||
}
|
||||
|
||||
if (is_resource($value)) {
|
||||
return sprintf('Resource(%s#%d)', get_resource_type($value), $value);
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
return 'null';
|
||||
}
|
||||
|
||||
if (false === $value) {
|
||||
return 'false';
|
||||
}
|
||||
|
||||
if (true === $value) {
|
||||
return 'true';
|
||||
}
|
||||
|
||||
return (string) $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \__PHP_Incomplete_Class $value
|
||||
* @return mixed
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
private function getClassNameFromIncomplete(\__PHP_Incomplete_Class $value)
|
||||
{
|
||||
$array = new \ArrayObject($value);
|
||||
|
||||
return $array['__PHP_Incomplete_Class_Name'];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Barryvdh\Debugbar;
|
||||
|
||||
use Illuminate\Contracts\View\Engine;
|
||||
|
||||
class DebugbarViewEngine implements Engine
|
||||
{
|
||||
/**
|
||||
* @var Engine
|
||||
*/
|
||||
protected $engine;
|
||||
|
||||
/**
|
||||
* @var LaravelDebugbar
|
||||
*/
|
||||
protected $laravelDebugbar;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $exclude_paths;
|
||||
|
||||
/**
|
||||
* @param Engine $engine
|
||||
* @param LaravelDebugbar $laravelDebugbar
|
||||
*/
|
||||
public function __construct(Engine $engine, LaravelDebugbar $laravelDebugbar)
|
||||
{
|
||||
$this->engine = $engine;
|
||||
$this->laravelDebugbar = $laravelDebugbar;
|
||||
$this->exclude_paths = app('config')->get('debugbar.options.views.exclude_paths', []);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param array $data
|
||||
* @return string
|
||||
*/
|
||||
public function get($path, array $data = [])
|
||||
{
|
||||
$basePath = base_path();
|
||||
$shortPath = @file_exists((string) $path) ? realpath($path) : $path;
|
||||
|
||||
if (str_starts_with($shortPath, $basePath)) {
|
||||
$shortPath = ltrim(
|
||||
str_replace('\\', '/', substr($shortPath, strlen($basePath))),
|
||||
'/'
|
||||
);
|
||||
}
|
||||
|
||||
foreach ($this->exclude_paths as $excludePath) {
|
||||
if (str_starts_with($shortPath, $excludePath)) {
|
||||
return $this->engine->get($path, $data);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->laravelDebugbar->measure($shortPath, function () use ($path, $data) {
|
||||
return $this->engine->get($path, $data);
|
||||
}, 'views');
|
||||
}
|
||||
|
||||
/**
|
||||
* NOTE: This is done to support other Engine swap (example: Livewire).
|
||||
* @param $name
|
||||
* @param $arguments
|
||||
* @return mixed
|
||||
*/
|
||||
public function __call($name, $arguments)
|
||||
{
|
||||
return $this->engine->$name(...$arguments);
|
||||
}
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace Barryvdh\Debugbar;
|
||||
|
||||
use DebugBar\DataCollector\DataCollectorInterface;
|
||||
|
||||
/**
|
||||
* @method static LaravelDebugbar addCollector(DataCollectorInterface $collector)
|
||||
* @method static void addMessage(mixed $message, string $label = 'info')
|
||||
* @method static void alert(mixed $message)
|
||||
* @method static void critical(mixed $message)
|
||||
* @method static void debug(mixed $message)
|
||||
* @method static void emergency(mixed $message)
|
||||
* @method static void error(mixed $message)
|
||||
* @method static LaravelDebugbar getCollector(string $name)
|
||||
* @method static bool hasCollector(string $name)
|
||||
* @method static void info(mixed $message)
|
||||
* @method static void log(mixed $message)
|
||||
* @method static void notice(mixed $message)
|
||||
* @method static void warning(mixed $message)
|
||||
* @method static mixed measure(string $label, \Closure $closure)
|
||||
*
|
||||
* @deprecated Renamed to \Barryvdh\Debugbar\Facades\Debugbar
|
||||
* @see \Barryvdh\Debugbar\Facades\Debugbar
|
||||
*
|
||||
* @see \Barryvdh\Debugbar\LaravelDebugbar
|
||||
*/
|
||||
class Facade extends \Barryvdh\Debugbar\Facades\Debugbar
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace Barryvdh\Debugbar\Facades;
|
||||
|
||||
use DebugBar\DataCollector\DataCollectorInterface;
|
||||
|
||||
/**
|
||||
* @method static LaravelDebugbar addCollector(DataCollectorInterface $collector)
|
||||
* @method static void addMessage(mixed $message, string $label = 'info')
|
||||
* @method static void alert(mixed $message)
|
||||
* @method static void critical(mixed $message)
|
||||
* @method static void debug(mixed $message)
|
||||
* @method static void emergency(mixed $message)
|
||||
* @method static void error(mixed $message)
|
||||
* @method static LaravelDebugbar getCollector(string $name)
|
||||
* @method static bool hasCollector(string $name)
|
||||
* @method static void info(mixed $message)
|
||||
* @method static void log(mixed $message)
|
||||
* @method static void notice(mixed $message)
|
||||
* @method static void warning(mixed $message)
|
||||
*
|
||||
* @see \Barryvdh\Debugbar\LaravelDebugbar
|
||||
*/
|
||||
class Debugbar extends \Illuminate\Support\Facades\Facade
|
||||
{
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected static function getFacadeAccessor()
|
||||
{
|
||||
return \Barryvdh\Debugbar\LaravelDebugbar::class;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
<?php
|
||||
|
||||
namespace Barryvdh\Debugbar;
|
||||
|
||||
use DebugBar\DebugBar;
|
||||
use DebugBar\JavascriptRenderer as BaseJavascriptRenderer;
|
||||
use Illuminate\Routing\UrlGenerator;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
class JavascriptRenderer extends BaseJavascriptRenderer
|
||||
{
|
||||
// Use XHR handler by default, instead of jQuery
|
||||
protected $ajaxHandlerBindToJquery = false;
|
||||
protected $ajaxHandlerBindToXHR = true;
|
||||
|
||||
public function __construct(DebugBar $debugBar, $baseUrl = null, $basePath = null)
|
||||
{
|
||||
parent::__construct($debugBar, $baseUrl, $basePath);
|
||||
|
||||
$this->cssFiles['laravel'] = __DIR__ . '/Resources/laravel-debugbar.css';
|
||||
$this->jsFiles['laravel-cache'] = __DIR__ . '/Resources/cache/widget.js';
|
||||
|
||||
$theme = config('debugbar.theme', 'auto');
|
||||
switch ($theme) {
|
||||
case 'dark':
|
||||
$this->cssFiles['laravel-dark'] = __DIR__ . '/Resources/laravel-debugbar-dark-mode.css';
|
||||
break;
|
||||
case 'auto':
|
||||
$this->cssFiles['laravel-dark-0'] = __DIR__ . '/Resources/laravel-debugbar-dark-mode-media-start.css';
|
||||
$this->cssFiles['laravel-dark-1'] = __DIR__ . '/Resources/laravel-debugbar-dark-mode.css';
|
||||
$this->cssFiles['laravel-dark-2'] = __DIR__ . '/Resources/laravel-debugbar-dark-mode-media-end.css';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the URL Generator
|
||||
*
|
||||
* @param \Illuminate\Routing\UrlGenerator $url
|
||||
* @deprecated
|
||||
*/
|
||||
public function setUrlGenerator($url)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function renderHead()
|
||||
{
|
||||
$cssRoute = preg_replace('/\Ahttps?:\/\/[^\/]+/', '', route('debugbar.assets.css', [
|
||||
'v' => $this->getModifiedTime('css'),
|
||||
'theme' => config('debugbar.theme', 'auto'),
|
||||
]));
|
||||
|
||||
$jsRoute = preg_replace('/\Ahttps?:\/\/[^\/]+/', '', route('debugbar.assets.js', [
|
||||
'v' => $this->getModifiedTime('js')
|
||||
]));
|
||||
|
||||
$nonce = $this->getNonceAttribute();
|
||||
|
||||
$html = "<link rel='stylesheet' type='text/css' property='stylesheet' href='{$cssRoute}' data-turbolinks-eval='false' data-turbo-eval='false'>";
|
||||
$html .= "<script{$nonce} src='{$jsRoute}' data-turbolinks-eval='false' data-turbo-eval='false'></script>";
|
||||
|
||||
if ($this->isJqueryNoConflictEnabled()) {
|
||||
$html .= "<script{$nonce} data-turbo-eval='false'>jQuery.noConflict(true);</script>" . "\n";
|
||||
}
|
||||
|
||||
$inlineHtml = $this->getInlineHtml();
|
||||
if ($nonce != '') {
|
||||
$inlineHtml = preg_replace("/<(script|style)>/", "<$1{$nonce}>", $inlineHtml);
|
||||
}
|
||||
$html .= $inlineHtml;
|
||||
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
protected function getInlineHtml()
|
||||
{
|
||||
$html = '';
|
||||
|
||||
foreach (['head', 'css', 'js'] as $asset) {
|
||||
foreach ($this->getAssets('inline_' . $asset) as $item) {
|
||||
$html .= $item . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
return $html;
|
||||
}
|
||||
/**
|
||||
* Get the last modified time of any assets.
|
||||
*
|
||||
* @param string $type 'js' or 'css'
|
||||
* @return int
|
||||
*/
|
||||
protected function getModifiedTime($type)
|
||||
{
|
||||
$files = $this->getAssets($type);
|
||||
|
||||
$latest = 0;
|
||||
foreach ($files as $file) {
|
||||
$mtime = filemtime($file);
|
||||
if ($mtime > $latest) {
|
||||
$latest = $mtime;
|
||||
}
|
||||
}
|
||||
return $latest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return assets as a string
|
||||
*
|
||||
* @param string $type 'js' or 'css'
|
||||
* @return string
|
||||
*/
|
||||
public function dumpAssetsToString($type)
|
||||
{
|
||||
$files = $this->getAssets($type);
|
||||
|
||||
$content = '';
|
||||
foreach ($files as $file) {
|
||||
$content .= file_get_contents($file) . "\n";
|
||||
}
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes a URI relative to another
|
||||
*
|
||||
* @param string|array $uri
|
||||
* @param string $root
|
||||
* @return string
|
||||
*/
|
||||
protected function makeUriRelativeTo($uri, $root)
|
||||
{
|
||||
if (!$root) {
|
||||
return $uri;
|
||||
}
|
||||
|
||||
if (is_array($uri)) {
|
||||
$uris = [];
|
||||
foreach ($uri as $u) {
|
||||
$uris[] = $this->makeUriRelativeTo($u, $root);
|
||||
}
|
||||
return $uris;
|
||||
}
|
||||
|
||||
if (substr($uri ?? '', 0, 1) === '/' || preg_match('/^([a-zA-Z]+:\/\/|[a-zA-Z]:\/|[a-zA-Z]:\\\)/', $uri ?? '')) {
|
||||
return $uri;
|
||||
}
|
||||
return rtrim($root, '/') . "/$uri";
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace Barryvdh\Debugbar;
|
||||
|
||||
use Laravel\Lumen\Application;
|
||||
|
||||
class LumenServiceProvider extends ServiceProvider
|
||||
{
|
||||
/** @var Application */
|
||||
protected $app;
|
||||
|
||||
/**
|
||||
* Get the active router.
|
||||
*
|
||||
* @return Application
|
||||
*/
|
||||
protected function getRouter()
|
||||
{
|
||||
return $this->app->router;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the config path
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getConfigPath()
|
||||
{
|
||||
return base_path('config/debugbar.php');
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the Debugbar Middleware
|
||||
*
|
||||
* @param string $middleware
|
||||
*/
|
||||
protected function registerMiddleware($middleware)
|
||||
{
|
||||
$this->app->middleware([$middleware]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the services provided by the provider.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function provides()
|
||||
{
|
||||
return ['debugbar', 'command.debugbar.clear'];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace Barryvdh\Debugbar\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
use Barryvdh\Debugbar\LaravelDebugbar;
|
||||
|
||||
class DebugbarEnabled
|
||||
{
|
||||
/**
|
||||
* The DebugBar instance
|
||||
*
|
||||
* @var LaravelDebugbar
|
||||
*/
|
||||
protected $debugbar;
|
||||
|
||||
/**
|
||||
* Create a new middleware instance.
|
||||
*
|
||||
* @param LaravelDebugbar $debugbar
|
||||
*/
|
||||
public function __construct(LaravelDebugbar $debugbar)
|
||||
{
|
||||
$this->debugbar = $debugbar;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Closure $next
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($request, Closure $next)
|
||||
{
|
||||
if (!$this->debugbar->isEnabled()) {
|
||||
abort(404);
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
<?php
|
||||
|
||||
namespace Barryvdh\Debugbar\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Exception;
|
||||
use Illuminate\Http\Request;
|
||||
use Barryvdh\Debugbar\LaravelDebugbar;
|
||||
use Illuminate\Contracts\Container\Container;
|
||||
use Illuminate\Contracts\Debug\ExceptionHandler;
|
||||
use Throwable;
|
||||
|
||||
class InjectDebugbar
|
||||
{
|
||||
/**
|
||||
* The App container
|
||||
*
|
||||
* @var Container
|
||||
*/
|
||||
protected $container;
|
||||
|
||||
/**
|
||||
* The DebugBar instance
|
||||
*
|
||||
* @var LaravelDebugbar
|
||||
*/
|
||||
protected $debugbar;
|
||||
|
||||
/**
|
||||
* The URIs that should be excluded.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $except = [];
|
||||
|
||||
/**
|
||||
* Create a new middleware instance.
|
||||
*
|
||||
* @param Container $container
|
||||
* @param LaravelDebugbar $debugbar
|
||||
*/
|
||||
public function __construct(Container $container, LaravelDebugbar $debugbar)
|
||||
{
|
||||
$this->container = $container;
|
||||
$this->debugbar = $debugbar;
|
||||
$this->except = config('debugbar.except') ?: [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Closure $next
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($request, Closure $next)
|
||||
{
|
||||
if (!$this->debugbar->isEnabled() || $this->inExceptArray($request)) {
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
$this->debugbar->boot();
|
||||
|
||||
try {
|
||||
/** @var \Illuminate\Http\Response $response */
|
||||
$response = $next($request);
|
||||
} catch (Throwable $e) {
|
||||
$response = $this->handleException($request, $e);
|
||||
}
|
||||
|
||||
// Modify the response to add the Debugbar
|
||||
$this->debugbar->modifyResponse($request, $response);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the given exception.
|
||||
*
|
||||
* (Copy from Illuminate\Routing\Pipeline by Taylor Otwell)
|
||||
*
|
||||
* @param $passable
|
||||
* @param Throwable $e
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function handleException($passable, $e)
|
||||
{
|
||||
if (! $this->container->bound(ExceptionHandler::class) || ! $passable instanceof Request) {
|
||||
throw $e;
|
||||
}
|
||||
|
||||
$handler = $this->container->make(ExceptionHandler::class);
|
||||
|
||||
$handler->report($e);
|
||||
|
||||
return $handler->render($passable, $e);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the request has a URI that should be ignored.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return bool
|
||||
*/
|
||||
protected function inExceptArray($request)
|
||||
{
|
||||
foreach ($this->except as $except) {
|
||||
if ($except !== '/') {
|
||||
$except = trim($except, '/');
|
||||
}
|
||||
|
||||
if ($request->is($except)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
(function ($) {
|
||||
|
||||
var csscls = PhpDebugBar.utils.makecsscls('phpdebugbar-widgets-');
|
||||
|
||||
/**
|
||||
* Widget for the displaying cache events
|
||||
*
|
||||
* Options:
|
||||
* - data
|
||||
*/
|
||||
var LaravelCacheWidget = PhpDebugBar.Widgets.LaravelCacheWidget = PhpDebugBar.Widgets.TimelineWidget.extend({
|
||||
|
||||
tagName: 'ul',
|
||||
|
||||
className: csscls('timeline cache'),
|
||||
|
||||
onForgetClick: function (e, el) {
|
||||
e.stopPropagation();
|
||||
|
||||
$.ajax({
|
||||
url: $(el).attr("data-url"),
|
||||
type: 'DELETE',
|
||||
success: function (result) {
|
||||
$(el).fadeOut(200);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
render: function () {
|
||||
LaravelCacheWidget.__super__.render.apply(this);
|
||||
|
||||
this.bindAttr('data', function (data) {
|
||||
|
||||
if (data.measures) {
|
||||
var self = this;
|
||||
var lines = this.$el.find('.' + csscls('measure'));
|
||||
|
||||
for (var i = 0; i < data.measures.length; i++) {
|
||||
var measure = data.measures[i];
|
||||
var m = lines[i];
|
||||
|
||||
if (measure.params && !$.isEmptyObject(measure.params)) {
|
||||
if (measure.params.delete && measure.params.key) {
|
||||
$('<a />')
|
||||
.addClass(csscls('forget'))
|
||||
.text('forget')
|
||||
.attr('data-url', measure.params.delete)
|
||||
.one('click', function (e) {
|
||||
self.onForgetClick(e, this); })
|
||||
.appendTo(m);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
})(PhpDebugBar.$);
|
||||
+1
@@ -0,0 +1 @@
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
@media (prefers-color-scheme: dark) {
|
||||
+355
@@ -0,0 +1,355 @@
|
||||
/* Dark mode */
|
||||
|
||||
div.phpdebugbar,
|
||||
div.phpdebugbar-openhandler {
|
||||
--color-gray-100: #F7FAFC;
|
||||
--color-gray-200: #EDF2F7;
|
||||
--color-gray-300: #E2E8F0;
|
||||
--color-gray-400: #CBD5E0;
|
||||
--color-gray-500: #A0AEC0;
|
||||
--color-gray-600: #718096;
|
||||
--color-gray-700: #4A5568;
|
||||
--color-gray-800: #252a37;
|
||||
--color-gray-900: #18181b;
|
||||
--color-red-vivid: #eb4432;
|
||||
}
|
||||
|
||||
div.phpdebugbar,
|
||||
div.phpdebugbar-widgets-dataset-history .phpdebugbar-widgets-dataset-actions,
|
||||
div.phpdebugbar-openhandler {
|
||||
background: var(--color-gray-800);
|
||||
}
|
||||
|
||||
div.phpdebugbar,
|
||||
div.phpdebugbar-openhandler,
|
||||
div.phpdebugbar div.phpdebugbar-header > div > *,
|
||||
div.phpdebugbar ul.phpdebugbar-widgets-timeline li span.phpdebugbar-widgets-label,
|
||||
div.phpdebugbar ul.phpdebugbar-widgets-timeline li span.phpdebugbar-widgets-collector,
|
||||
div.phpdebugbar ul.phpdebugbar-widgets-list li.phpdebugbar-widgets-list-item,
|
||||
div.phpdebugbar ul.phpdebugbar-widgets-list li span.phpdebugbar-widgets-label,
|
||||
div.phpdebugbar code.phpdebugbar-widgets-sql span.hljs-keyword,
|
||||
div.phpdebugbar-openhandler .phpdebugbar-openhandler-header,
|
||||
div.phpdebugbar-openhandler .phpdebugbar-openhandler-header a,
|
||||
div.phpdebugbar-panel .phpdebugbar-widgets-dataset-actions select {
|
||||
color: var(--color-gray-200);
|
||||
}
|
||||
|
||||
div.phpdebugbar ul.phpdebugbar-widgets-timeline li span.phpdebugbar-widgets-label {
|
||||
text-shadow: 1px 1px #000;
|
||||
}
|
||||
|
||||
div.phpdebugbar-openhandler,
|
||||
div.phpdebugbar div.phpdebugbar-widgets-messages div.phpdebugbar-widgets-toolbar,
|
||||
div.phpdebugbar div.phpdebugbar-widgets-exceptions li.phpdebugbar-widgets-list-item pre.phpdebugbar-widgets-file,
|
||||
div.phpdebugbar ul.phpdebugbar-widgets-list li.phpdebugbar-widgets-list-item table.phpdebugbar-widgets-params,
|
||||
div.phpdebugbar-openhandler .phpdebugbar-openhandler-actions > a,
|
||||
div.phpdebugbar-openhandler .phpdebugbar-openhandler-actions button,
|
||||
div.phpdebugbar-openhandler .phpdebugbar-openhandler-actions > form input,
|
||||
div.phpdebugbar-openhandler .phpdebugbar-openhandler-actions > form select,
|
||||
div.phpdebugbar-panel .phpdebugbar-widgets-dataset-actions select {
|
||||
border-color: var(--color-gray-600);
|
||||
}
|
||||
|
||||
div.phpdebugbar div.phpdebugbar-header,
|
||||
div.phpdebugbar div.phpdebugbar-panel div.phpdebugbar-widgets-status > span:first-child:before,
|
||||
div.phpdebugbar-openhandler table th,
|
||||
div.phpdebugbar-openhandler .phpdebugbar-openhandler-actions > a,
|
||||
div.phpdebugbar-openhandler .phpdebugbar-openhandler-actions button,
|
||||
div.phpdebugbar-openhandler .phpdebugbar-openhandler-actions > form input,
|
||||
div.phpdebugbar-openhandler .phpdebugbar-openhandler-actions > form select {
|
||||
text-shadow: 1px 1px var(--color-gray-700);
|
||||
}
|
||||
|
||||
div.phpdebugbar div.phpdebugbar-header > div > select,
|
||||
div.phpdebugbar ul.phpdebugbar-widgets-list li.phpdebugbar-widgets-list-item table.phpdebugbar-widgets-params,
|
||||
div.phpdebugbar-openhandler .phpdebugbar-openhandler-actions > form input,
|
||||
div.phpdebugbar-openhandler .phpdebugbar-openhandler-actions > form select,
|
||||
div.phpdebugbar-panel .phpdebugbar-widgets-dataset-actions select,
|
||||
div.phpdebugbar input[type='text'],
|
||||
div.phpdebugbar input[type='password'] {
|
||||
background-color: var(--color-gray-800);
|
||||
}
|
||||
|
||||
div.phpdebugbar div.phpdebugbar-header,
|
||||
div.phpdebugbar a.phpdebugbar-restore-btn,
|
||||
div.phpdebugbar-openhandler .phpdebugbar-openhandler-header,
|
||||
div.phpdebugbar dl.phpdebugbar-widgets-kvlist > :nth-child(4n-1),
|
||||
div.phpdebugbar dl.phpdebugbar-widgets-kvlist > :nth-child(4n),
|
||||
div.phpdebugbar ul.phpdebugbar-widgets-list li.phpdebugbar-widgets-list-item:nth-child(even),
|
||||
div.phpdebugbar .hljs,
|
||||
div.phpdebugbar div.phpdebugbar-widgets-sqlqueries table.phpdebugbar-widgets-params th,
|
||||
div.phpdebugbar-openhandler .phpdebugbar-openhandler-actions > a,
|
||||
div.phpdebugbar-openhandler .phpdebugbar-openhandler-actions button,
|
||||
div.phpdebugbar div.phpdebugbar-widgets-templates table.phpdebugbar-widgets-params th {
|
||||
background-color: var(--color-gray-900);
|
||||
}
|
||||
|
||||
div.phpdebugbar .phpdebugbar-widgets-mails ul.phpdebugbar-widgets-list li.phpdebugbar-widgets-list-item .phpdebugbar-widgets-headers,
|
||||
div.phpdebugbar ul.phpdebugbar-widgets-list li.phpdebugbar-widgets-list-item table.phpdebugbar-widgets-params {
|
||||
border-left-color: var(--color-gray-600);
|
||||
}
|
||||
|
||||
div.phpdebugbar a.phpdebugbar-tab:hover,
|
||||
div.phpdebugbar span.phpdebugbar-indicator:hover,
|
||||
div.phpdebugbar a.phpdebugbar-indicator:hover,
|
||||
div.phpdebugbar a.phpdebugbar-close-btn:hover,
|
||||
div.phpdebugbar a.phpdebugbar-minimize-btn:hover,
|
||||
div.phpdebugbar a.phpdebugbar-maximize-btn:hover,
|
||||
div.phpdebugbar a.phpdebugbar-open-btn:hover,
|
||||
div.phpdebugbar-openhandler table th,
|
||||
div.phpdebugbar-openhandler table tr:nth-child(2n),
|
||||
div.phpdebugbar div.phpdebugbar-widgets-messages div.phpdebugbar-widgets-toolbar {
|
||||
background-color: var(--color-gray-700);
|
||||
}
|
||||
|
||||
div.phpdebugbar .phpdebugbar-indicator span.phpdebugbar-tooltip,
|
||||
div.phpdebugbar div.phpdebugbar-mini-design a.phpdebugbar-tab:hover span.phpdebugbar-text,
|
||||
div.phpdebugbar pre.sf-dump,
|
||||
div.phpdebugbar .hljs,
|
||||
div.phpdebugbar code.phpdebugbar-widgets-sql span.hljs-operator {
|
||||
color: var(--color-gray-100);
|
||||
}
|
||||
|
||||
div.phpdebugbar pre.sf-dump .sf-dump-public,
|
||||
div.phpdebugbar pre.sf-dump .sf-dump-protected,
|
||||
div.phpdebugbar pre.sf-dump .sf-dump-private {
|
||||
color: var(--color-gray-100) !important;
|
||||
}
|
||||
|
||||
div.phpdebugbar div.phpdebugbar-panel div.phpdebugbar-widgets-status > span:first-child:before,
|
||||
div.phpdebugbar-openhandler a {
|
||||
color: var(--color-gray-500);
|
||||
}
|
||||
|
||||
div.phpdebugbar .phpdebugbar-indicator span.phpdebugbar-tooltip,
|
||||
div.phpdebugbar div.phpdebugbar-mini-design a.phpdebugbar-tab:hover span.phpdebugbar-text {
|
||||
background: var(--color-gray-900);
|
||||
}
|
||||
|
||||
div.phpdebugbar .hljs-tag .hljs-value,
|
||||
div.phpdebugbar .hljs-phpdoc,
|
||||
div.phpdebugbar .tex .hljs-formula,
|
||||
div.phpdebugbar div.phpdebugbar-widgets-exceptions li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-message {
|
||||
color: var(--color-red-vivid);
|
||||
}
|
||||
|
||||
div.phpdebugbar div.phpdebugbar-widgets-sqlqueries li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-database,
|
||||
div.phpdebugbar div.phpdebugbar-widgets-sqlqueries li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-duration,
|
||||
div.phpdebugbar div.phpdebugbar-widgets-sqlqueries li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-memory,
|
||||
div.phpdebugbar div.phpdebugbar-widgets-sqlqueries li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-row-count,
|
||||
div.phpdebugbar div.phpdebugbar-widgets-sqlqueries li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-copy-clipboard,
|
||||
div.phpdebugbar div.phpdebugbar-widgets-sqlqueries li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-stmt-id,
|
||||
div.phpdebugbar .phpdebugbar-widgets-callgraph pre,
|
||||
div.phpdebugbar .phpdebugbar-text-muted,
|
||||
div.phpdebugbar-openhandler .phpdebugbar-text-muted
|
||||
{
|
||||
color: var(--color-gray-600);
|
||||
}
|
||||
|
||||
li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-filename,
|
||||
li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-filename a.phpdebugbar-widgets-editor-link
|
||||
{
|
||||
color: #ddd;
|
||||
}
|
||||
div.phpdebugbar div.phpdebugbar-widgets-sqlqueries li.phpdebugbar-widgets-list-item.phpdebugbar-widgets-sql-duplicate {
|
||||
background-color: #473e00;
|
||||
}
|
||||
|
||||
div.phpdebugbar-widgets-messages li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-value:before {
|
||||
color: #7B7B7B;
|
||||
}
|
||||
|
||||
div.phpdebugbar pre.sf-dump .sf-dump-note {
|
||||
color: #8be9fd;
|
||||
}
|
||||
|
||||
div.phpdebugbar pre.sf-dump .sf-dump-num,
|
||||
div.phpdebugbar pre.sf-dump .sf-dump-const,
|
||||
div.phpdebugbar pre.sf-dump .sf-dump-index {
|
||||
color: #bd93f9;
|
||||
}
|
||||
|
||||
div.phpdebugbar pre.sf-dump .sf-dump-key,
|
||||
div.phpdebugbar pre.sf-dump .sf-dump-str {
|
||||
color: #f1fa8c;
|
||||
}
|
||||
|
||||
div.phpdebugbar-openhandler {
|
||||
border-top-color: var(--color-red-vivid);
|
||||
}
|
||||
|
||||
div.phpdebugbar div.phpdebugbar-header .phpdebugbar-tab {
|
||||
border-left-color: var(--color-gray-800);
|
||||
}
|
||||
|
||||
div.phpdebugbar div.phpdebugbar-body {
|
||||
border-top-color: var(--color-gray-800);
|
||||
}
|
||||
|
||||
div.phpdebugbar a.phpdebugbar-restore-btn {
|
||||
border-right-color: var(--color-gray-800) !important;
|
||||
}
|
||||
|
||||
div.phpdebugbar span.phpdebugbar-indicator,
|
||||
div.phpdebugbar a.phpdebugbar-indicator,
|
||||
div.phpdebugbar a.phpdebugbar-close-btn {
|
||||
border-right-color: var(--color-gray-800);
|
||||
}
|
||||
|
||||
div.phpdebugbar div.phpdebugbar-panel div.phpdebugbar-widgets-status {
|
||||
background-color: var(--color-gray-900) !important;
|
||||
border-bottom-color: var(--color-gray-800) !important;
|
||||
}
|
||||
|
||||
div.phpdebugbar div.phpdebugbar-widgets-templates div.phpdebugbar-widgets-status {
|
||||
background: var(--color-gray-900) !important;
|
||||
}
|
||||
|
||||
div.phpdebugbar div.phpdebugbar-panel div.phpdebugbar-widgets-status > * {
|
||||
color: var(--color-gray-200) !important;
|
||||
}
|
||||
|
||||
div.phpdebugbar div.phpdebugbar-widgets-templates span.phpdebugbar-widgets-render-time,
|
||||
div.phpdebugbar div.phpdebugbar-widgets-templates span.phpdebugbar-widgets-memory,
|
||||
div.phpdebugbar div.phpdebugbar-widgets-templates span.phpdebugbar-widgets-param-count,
|
||||
div.phpdebugbar div.phpdebugbar-widgets-templates span.phpdebugbar-widgets-type {
|
||||
color: var(--color-gray-600) !important;
|
||||
}
|
||||
|
||||
div.phpdebugbar div.phpdebugbar-widgets-sqlqueries table.phpdebugbar-widgets-params td {
|
||||
border-color: var(--color-gray-600) !important;
|
||||
}
|
||||
|
||||
div.phpdebugbar code,
|
||||
div.phpdebugbar pre {
|
||||
color: #f1fa8c;
|
||||
}
|
||||
|
||||
div.phpdebugbar-openhandler .phpdebugbar-openhandler-actions > a,
|
||||
div.phpdebugbar-openhandler .phpdebugbar-openhandler-actions button,
|
||||
div.phpdebugbar-openhandler .phpdebugbar-openhandler-actions > form input,
|
||||
div.phpdebugbar-openhandler .phpdebugbar-openhandler-actions > form select,
|
||||
div.phpdebugbar input[type='text'],
|
||||
div.phpdebugbar input[type='password'] {
|
||||
color: var(--color-gray-300);
|
||||
}
|
||||
|
||||
div.phpdebugbar div.phpdebugbar-widgets-exceptions li.phpdebugbar-widgets-list-item.phpdebugbar-widgets-sql-duplicate span.phpdebugbar-widgets-filename,
|
||||
div.phpdebugbar div.phpdebugbar-widgets-sqlqueries li.phpdebugbar-widgets-list-item.phpdebugbar-widgets-sql-duplicate span.phpdebugbar-widgets-database,
|
||||
div.phpdebugbar div.phpdebugbar-widgets-sqlqueries li.phpdebugbar-widgets-list-item.phpdebugbar-widgets-sql-duplicate span.phpdebugbar-widgets-duration,
|
||||
div.phpdebugbar div.phpdebugbar-widgets-sqlqueries li.phpdebugbar-widgets-list-item.phpdebugbar-widgets-sql-duplicate span.phpdebugbar-widgets-memory,
|
||||
div.phpdebugbar div.phpdebugbar-widgets-sqlqueries li.phpdebugbar-widgets-list-item.phpdebugbar-widgets-sql-duplicate span.phpdebugbar-widgets-row-count,
|
||||
div.phpdebugbar div.phpdebugbar-widgets-sqlqueries li.phpdebugbar-widgets-list-item.phpdebugbar-widgets-sql-duplicate span.phpdebugbar-widgets-copy-clipboard,
|
||||
div.phpdebugbar div.phpdebugbar-widgets-sqlqueries li.phpdebugbar-widgets-list-item.phpdebugbar-widgets-sql-duplicate span.phpdebugbar-widgets-stmt-id {
|
||||
color: var(--color-gray-500);
|
||||
}
|
||||
|
||||
div.phpdebugbar dl.phpdebugbar-widgets-kvlist > :nth-child(4n)::before {
|
||||
background-color: var(--color-gray-900);
|
||||
}
|
||||
|
||||
dt.phpdebugbar-widgets-key {
|
||||
background: var(--color-gray-800);
|
||||
}
|
||||
|
||||
a.phpdebugbar-minimize-btn {
|
||||
background:url(data:image/svg+xml,%3Csvg%20viewBox=%220%200%201792%201792%22%20fill=%22none%22%20xmlns=%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d=%22m1683%20653.5-742%20741c-12.667%2012.67-27.667%2019-45%2019s-32.333-6.33-45-19l-742-741c-12.667-12.667-19-27.833-19-45.5s6.333-32.833%2019-45.5l166-165c12.667-12.667%2027.667-19%2045-19s32.333%206.333%2045%2019l531%20531%20531-531c12.67-12.667%2027.67-19%2045-19s32.33%206.333%2045%2019l166%20165c12.67%2012.667%2019%2027.833%2019%2045.5s-6.33%2032.833-19%2045.5Z%22%20fill=%22%23EDF2F7%22%2F%3E%3C%2Fsvg%3E) no-repeat center / 14px 14px;
|
||||
}
|
||||
|
||||
a.phpdebugbar-maximize-btn {
|
||||
background: url(data:image/svg+xml,%3Csvg%20viewBox=%220%200%201792%201792%22%20fill=%22none%22%20xmlns=%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d=%22m1683%201229.5-166%20165c-12.67%2012.67-27.67%2019-45%2019s-32.33-6.33-45-19l-531-531-531%20531c-12.667%2012.67-27.667%2019-45%2019s-32.333-6.33-45-19l-166-165c-12.667-12.67-19-27.83-19-45.5s6.333-32.83%2019-45.5l742-741c12.667-12.667%2027.667-19%2045-19s32.333%206.333%2045%2019l742%20741c12.67%2012.67%2019%2027.83%2019%2045.5s-6.33%2032.83-19%2045.5Z%22%20fill=%22%23EDF2F7%22%2F%3E%3C%2Fsvg%3E) no-repeat center / 14px 14px;
|
||||
}
|
||||
|
||||
a.phpdebugbar-close-btn {
|
||||
background: url(data:image/svg+xml,%3Csvg%20viewBox=%220%200%201792%201792%22%20fill=%22none%22%20xmlns=%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d=%22M1490%201258c0%2026.67-9.33%2049.33-28%2068l-136%20136c-18.67%2018.67-41.33%2028-68%2028s-49.33-9.33-68-28l-294-294-294%20294c-18.667%2018.67-41.333%2028-68%2028s-49.333-9.33-68-28l-136-136c-18.667-18.67-28-41.33-28-68s9.333-49.33%2028-68l294-294-294-294c-18.667-18.667-28-41.333-28-68s9.333-49.333%2028-68l136-136c18.667-18.667%2041.333-28%2068-28s49.333%209.333%2068%2028l294%20294%20294-294c18.67-18.667%2041.33-28%2068-28s49.33%209.333%2068%2028l136%20136c18.67%2018.667%2028%2041.333%2028%2068s-9.33%2049.333-28%2068l-294%20294%20294%20294c18.67%2018.67%2028%2041.33%2028%2068Z%22%20fill=%22%23EDF2F7%22%2F%3E%3C%2Fsvg%3E) no-repeat center / 14px 14px;
|
||||
}
|
||||
|
||||
a.phpdebugbar-open-btn {
|
||||
background: url(data:image/svg+xml,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20fill%3D%22none%22%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%3E%3Cpath%20d%3D%22M1646%20991.797c0%2016.493-8.25%2034.063-24.75%2052.683l-268.22%20316.13c-22.89%2027.14-54.95%2050.16-96.2%2069.05S1177.4%201458%201142.27%201458H273.728c-18.095%200-34.194-3.46-48.297-10.38-14.104-6.92-21.155-18.36-21.155-34.32%200-16.5%208.249-34.06%2024.747-52.69l268.228-316.13c22.884-27.14%2054.949-50.155%2096.194-69.048%2041.246-18.893%2079.431-28.34%20114.556-28.34h868.549c18.09%200%2034.19%203.458%2048.3%2010.377%2014.1%206.918%2021.15%2018.362%2021.15%2034.328Zm-273.82-274.615V844.91H708.001c-50.027%200-102.448%2012.639-157.264%2037.918-54.817%2025.28-98.457%2057.078-130.921%2095.397L150.79%201294.35l-3.992%204.79c0-2.13-.133-5.46-.399-9.98-.266-4.52-.399-7.85-.399-9.98V512.818c0-48.962%2017.563-91.005%2052.688-126.13C233.813%20351.562%20275.856%20334%20324.819%20334h255.455c48.962%200%2091.005%2017.562%20126.13%2052.688%2035.126%2035.125%2052.688%2077.168%2052.688%20126.13v25.545h434.278c48.96%200%2091%2017.564%20126.13%2052.689%2035.12%2035.125%2052.68%2077.168%2052.68%20126.13Z%22%20fill%3D%22%23EDF2F7%22/%3E%3C/svg%3E) no-repeat center / 14px 14px;
|
||||
}
|
||||
|
||||
div.phpdebugbar code.language-php,
|
||||
div.phpdebugbar pre.language-php {
|
||||
color: #FFF;
|
||||
}
|
||||
|
||||
pre.phpdebugbar-widgets-code-block ul {
|
||||
background: none;
|
||||
}
|
||||
|
||||
/* Dracula Theme v1.2.5
|
||||
*
|
||||
* https://github.com/dracula/highlightjs
|
||||
*
|
||||
* Copyright 2016-present, All rights reserved
|
||||
*
|
||||
* Code licensed under the MIT license
|
||||
*
|
||||
* @author Denis Ciccale <dciccale@gmail.com>
|
||||
* @author Zeno Rocha <hi@zenorocha.com>
|
||||
*/
|
||||
|
||||
div.phpdebugbar .hljs-built_in,
|
||||
div.phpdebugbar .hljs-selector-tag,
|
||||
div.phpdebugbar .hljs-section,
|
||||
div.phpdebugbar .hljs-link {
|
||||
color: #8be9fd;
|
||||
}
|
||||
|
||||
div.phpdebugbar .hljs-keyword {
|
||||
color: #ff79c6;
|
||||
}
|
||||
|
||||
div.phpdebugbar .hljs,
|
||||
div.phpdebugbar .hljs-subst {
|
||||
color: #f8f8f2;
|
||||
}
|
||||
|
||||
div.phpdebugbar .hljs-title,
|
||||
div.phpdebugbar .hljs-meta-keyword {
|
||||
color: #50fa7b;
|
||||
}
|
||||
|
||||
div.phpdebugbar .hljs-string,
|
||||
div.phpdebugbar .hljs-meta,
|
||||
div.phpdebugbar .hljs-name,
|
||||
div.phpdebugbar .hljs-type,
|
||||
div.phpdebugbar .hljs-attr,
|
||||
div.phpdebugbar .hljs-symbol,
|
||||
div.phpdebugbar .hljs-bullet,
|
||||
div.phpdebugbar .hljs-addition,
|
||||
div.phpdebugbar .hljs-variable,
|
||||
div.phpdebugbar .hljs-template-tag,
|
||||
div.phpdebugbar .hljs-template-variable {
|
||||
color: #f1fa8c;
|
||||
}
|
||||
|
||||
div.phpdebugbar .hljs-comment,
|
||||
div.phpdebugbar .hljs-quote,
|
||||
div.phpdebugbar .hljs-deletion {
|
||||
color: #6272a4;
|
||||
}
|
||||
|
||||
div.phpdebugbar .hljs-strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
div.phpdebugbar .hljs-literal,
|
||||
div.phpdebugbar .hljs-number {
|
||||
color: #bd93f9;
|
||||
}
|
||||
|
||||
.phpdebugbar-widgets-dataset-history table tr.phpdebugbar-widgets-active {
|
||||
background-color: var(--color-gray-700);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.phpdebugbar-widgets-dataset-history table th,
|
||||
.phpdebugbar-widgets-dataset-history table td {
|
||||
border-color: var(--color-gray-600);
|
||||
}
|
||||
|
||||
ul.phpdebugbar-widgets-timeline table.phpdebugbar-widgets-params td {
|
||||
border-color: var(--color-gray-700);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,921 @@
|
||||
/* Force Laravel Whoops exception handler to be displayed under the debug bar */
|
||||
.Whoops.container {
|
||||
z-index: 5999999;
|
||||
}
|
||||
div.phpdebugbar,
|
||||
div.phpdebugbar-openhandler {
|
||||
--color-red-vivid: #eb4432;
|
||||
}
|
||||
|
||||
div.phpdebugbar {
|
||||
font-size: 13px;
|
||||
font-family: "Lucida Grande", "Lucida Sans Unicode", "Lucida Sans", Geneva, Verdana, sans-serif;
|
||||
direction: ltr;
|
||||
text-align: left;
|
||||
z-index: 6000000;
|
||||
}
|
||||
|
||||
div.phpdebugbar * {
|
||||
direction: ltr;
|
||||
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
div.phpdebugbar-openhandler-overlay {
|
||||
z-index: 6000001;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
div.phpdebugbar-openhandler {
|
||||
border: 1px solid #aaa;
|
||||
border-top: 3px solid var(--color-red-vivid);
|
||||
width: 80%;
|
||||
height: 70%;
|
||||
padding: 10px;
|
||||
border-radius: 5px;
|
||||
overflow-y: scroll;
|
||||
z-index: 6000002;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
div.phpdebugbar-openhandler .phpdebugbar-openhandler-actions > a,
|
||||
div.phpdebugbar-openhandler .phpdebugbar-openhandler-actions button {
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
margin: 5px;
|
||||
padding: 0px 12px 2px;
|
||||
border-radius: 3px;
|
||||
border: 1px solid #ddd;
|
||||
background-color: #f5f5f5;
|
||||
color: #000;
|
||||
text-shadow: 1px 1px #fff;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
div.phpdebugbar-openhandler .phpdebugbar-openhandler-actions > form {
|
||||
margin: 15px 0px 5px;
|
||||
text-transform: uppercase;
|
||||
font-size: 13px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
div.phpdebugbar-openhandler .phpdebugbar-openhandler-actions > form br {
|
||||
display: none;
|
||||
}
|
||||
|
||||
div.phpdebugbar-openhandler .phpdebugbar-openhandler-actions > form > b {
|
||||
display: none;
|
||||
}
|
||||
|
||||
div.phpdebugbar-openhandler .phpdebugbar-openhandler-actions > form input,
|
||||
div.phpdebugbar-openhandler .phpdebugbar-openhandler-actions > form select {
|
||||
margin: 0px 10px 10px 2px;
|
||||
border: 1px solid #aaa;
|
||||
border-radius: 3px;
|
||||
padding: 3px 6px 2px;
|
||||
line-height: 16px;
|
||||
}
|
||||
|
||||
@media (max-width: 720px) {
|
||||
div.phpdebugbar-openhandler .phpdebugbar-openhandler-actions > form select + br,
|
||||
div.phpdebugbar-openhandler .phpdebugbar-openhandler-actions > form input[name="uri"] + br {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
div.phpdebugbar-openhandler .phpdebugbar-openhandler-actions > form select {
|
||||
padding: 2px 5px 1px;
|
||||
}
|
||||
|
||||
div.phpdebugbar-openhandler .phpdebugbar-openhandler-actions input[name="uri"] {
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
div.phpdebugbar-openhandler .phpdebugbar-openhandler-actions input[name="ip"] {
|
||||
width: 90px;
|
||||
}
|
||||
|
||||
div.phpdebugbar-openhandler .phpdebugbar-openhandler-actions button {
|
||||
outline: none;
|
||||
margin: 0px 0px 10px 2px;
|
||||
padding: 5px 15px 4px;
|
||||
line-height: 12px;
|
||||
}
|
||||
|
||||
div.phpdebugbar-openhandler table {
|
||||
margin: 15px 0px 10px;
|
||||
table-layout: auto;
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
div.phpdebugbar-openhandler table td,
|
||||
div.phpdebugbar-openhandler table th {
|
||||
width: auto!important;
|
||||
text-align: left;
|
||||
border: 0px solid #bbb;
|
||||
padding: 2px 8px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
div.phpdebugbar-openhandler table th {
|
||||
text-shadow: 1px 1px #fff;
|
||||
font-size: 12px;
|
||||
text-transform: uppercase;
|
||||
padding: 5px 8px;
|
||||
}
|
||||
|
||||
div.phpdebugbar-openhandler table th,
|
||||
div.phpdebugbar-openhandler table tr:nth-child(2n) {
|
||||
background-color: #efefef;
|
||||
}
|
||||
|
||||
div.phpdebugbar-openhandler table th:nth-child(1), div.phpdebugbar-openhandler table td:nth-child(1), /* Date */
|
||||
div.phpdebugbar-openhandler table th:nth-child(2), div.phpdebugbar-openhandler table td:nth-child(2), /* Method */
|
||||
div.phpdebugbar-openhandler table th:nth-child(4), div.phpdebugbar-openhandler table td:nth-child(4), /* IP */
|
||||
div.phpdebugbar-openhandler table th:nth-child(5), div.phpdebugbar-openhandler table td:nth-child(5) { /* Filter */
|
||||
width: 5%!important;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
div.phpdebugbar-openhandler table th:nth-child(2), div.phpdebugbar-openhandler table td:nth-child(2), /* Method */
|
||||
div.phpdebugbar-openhandler table th:nth-child(4), div.phpdebugbar-openhandler table td:nth-child(4), /* IP */
|
||||
div.phpdebugbar-openhandler table th:nth-child(5), div.phpdebugbar-openhandler table td:nth-child(5) { /* Filter */
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
div.phpdebugbar-openhandler table th:nth-child(3) { /* URL */
|
||||
width: calc(100vw - 100% - 196px)!important;
|
||||
}
|
||||
|
||||
div.phpdebugbar-openhandler table td a {
|
||||
display: block;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
div.phpdebugbar-resize-handle {
|
||||
display: block!important;
|
||||
height: 3px;
|
||||
margin-top: -3px;
|
||||
width: 100%;
|
||||
background: none;
|
||||
cursor: ns-resize;
|
||||
border-top: none;
|
||||
border-bottom: 0px;
|
||||
background-color: var(--color-red-vivid);
|
||||
}
|
||||
|
||||
.phpdebugbar.phpdebugbar-minimized div.phpdebugbar-resize-handle {
|
||||
cursor: default!important;
|
||||
}
|
||||
|
||||
div.phpdebugbar-closed,
|
||||
div.phpdebugbar-minimized {
|
||||
border-top-color: #ddd;
|
||||
}
|
||||
|
||||
div.phpdebugbar code, div.phpdebugbar pre, div.phpdebugbar samp {
|
||||
background: none !important;
|
||||
font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
|
||||
font-size: 1em;
|
||||
border: 0 !important;
|
||||
padding: 0 !important;
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
div.phpdebugbar .hljs {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
div.phpdebugbar .phpdebugbar-widgets-messages .hljs > code {
|
||||
padding-bottom: 3px;
|
||||
}
|
||||
|
||||
div.phpdebugbar code, div.phpdebugbar pre {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
div.phpdebugbar-widgets-exceptions .phpdebugbar-widgets-filename {
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
div.phpdebugbar-widgets-exceptions li.phpdebugbar-widgets-list-item pre.phpdebugbar-widgets-file {
|
||||
border: 1px solid #d2d2d2;
|
||||
border-left: 2px solid #d2d2d2;
|
||||
}
|
||||
|
||||
div.phpdebugbar-widgets-exceptions li.phpdebugbar-widgets-list-item pre.phpdebugbar-widgets-file[style="display: block;"] ~ div {
|
||||
display: block;
|
||||
}
|
||||
|
||||
div.phpdebugbar pre.sf-dump {
|
||||
color: #000;
|
||||
outline: none;
|
||||
padding-left: 0px;
|
||||
}
|
||||
|
||||
div.phpdebugbar-body {
|
||||
border-top: 1px solid #ddd;
|
||||
}
|
||||
|
||||
div.phpdebugbar-header {
|
||||
min-height: 30px;
|
||||
line-height: 20px;
|
||||
text-shadow: 1px 1px #FFF;
|
||||
}
|
||||
|
||||
div.phpdebugbar-header span.phpdebugbar-text, div.phpdebugbar-header > div > span > span {
|
||||
transform: translateY(-1px) !important;
|
||||
}
|
||||
|
||||
a.phpdebugbar-restore-btn {
|
||||
background: url(data:image/svg+xml,%3Csvg%20viewBox%3D%220%200%2048%2048%22%20fill%3D%22none%22%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%3E%3Cpath%20fill-rule%3D%22evenodd%22%20clip-rule%3D%22evenodd%22%20d%3D%22M47.973%2010.859a.74.74%200%200%201%20.027.196v10.303a.735.735%200%200%201-.104.377.763.763%200%200%201-.285.275l-8.902%204.979v9.868a.75.75%200%200%201-.387.652L19.74%2047.9c-.043.023-.09.038-.135.054-.018.006-.034.016-.053.021a.801.801%200%200%201-.396%200c-.021-.006-.04-.017-.061-.024-.043-.015-.087-.029-.128-.051L.39%2037.509a.763.763%200%200%201-.285-.276.736.736%200%200%201-.104-.376V5.947c0-.067.01-.133.027-.196.006-.022.02-.042.027-.063.015-.04.028-.08.05-.117.014-.024.035-.044.053-.067.022-.03.042-.06.068-.087.022-.021.051-.037.077-.056.028-.023.053-.047.085-.065L9.677.1a.793.793%200%200%201%20.774%200l9.29%205.196h.002c.03.019.057.042.085.064.025.019.053.036.075.056.027.027.047.058.07.088.016.023.038.043.052.067.022.038.035.077.05.117.008.021.021.04.027.063a.74.74%200%200%201%20.027.197v19.305l7.742-4.33v-9.869c0-.066.01-.132.027-.195.006-.023.019-.042.027-.064.015-.04.029-.08.05-.116.014-.025.036-.045.052-.067.023-.03.043-.061.07-.087.022-.022.05-.038.075-.057.03-.022.054-.047.085-.065l9.292-5.195a.792.792%200%200%201%20.773%200l9.29%205.195c.033.02.058.043.087.064.025.02.053.036.075.057.027.027.046.058.07.088.017.022.038.042.052.067.022.036.034.077.05.116.009.022.021.041.027.064ZM46.45%2020.923v-8.567l-3.25%201.818-4.492%202.512v8.567l7.743-4.33Zm-9.29%2015.5v-8.574l-4.417%202.45-12.616%206.995v8.654l17.033-9.526ZM1.55%207.247v29.174l17.03%209.525v-8.653l-8.897-4.89-.003-.003-.003-.002c-.03-.017-.056-.041-.084-.062-.024-.018-.052-.033-.073-.054l-.002-.003c-.025-.023-.042-.053-.064-.079-.02-.025-.042-.047-.058-.073v-.003c-.018-.028-.029-.062-.041-.094-.013-.028-.03-.054-.037-.084-.01-.036-.012-.075-.016-.111-.003-.028-.011-.056-.011-.085V11.58L4.8%209.064%201.549%207.248Zm8.516-5.628-7.74%204.328%207.738%204.328%207.74-4.33-7.74-4.326h.002Zm4.026%2027.01%204.49-2.51V7.247L15.33%209.066l-4.492%202.512V30.45l3.253-1.819ZM37.935%206.727l-7.74%204.328%207.74%204.328%207.738-4.329-7.738-4.327Zm-.775%209.959-4.49-2.512-3.252-1.818v8.567l4.49%202.511%203.252%201.82v-8.568ZM19.353%2035.993l11.352-6.295%205.674-3.146-7.733-4.325-8.904%204.98-8.116%204.538%207.727%204.248Z%22%20fill%3D%22%23FF2D20%22/%3E%3C/svg%3E) no-repeat 11px center / 20px 20px !important;
|
||||
}
|
||||
|
||||
div.phpdebugbar-openhandler .phpdebugbar-openhandler-header {
|
||||
background: url(data:image/svg+xml,%3Csvg%20viewBox%3D%220%200%2048%2048%22%20fill%3D%22none%22%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%3E%3Cpath%20fill-rule%3D%22evenodd%22%20clip-rule%3D%22evenodd%22%20d%3D%22M47.973%2010.859a.74.74%200%200%201%20.027.196v10.303a.735.735%200%200%201-.104.377.763.763%200%200%201-.285.275l-8.902%204.979v9.868a.75.75%200%200%201-.387.652L19.74%2047.9c-.043.023-.09.038-.135.054-.018.006-.034.016-.053.021a.801.801%200%200%201-.396%200c-.021-.006-.04-.017-.061-.024-.043-.015-.087-.029-.128-.051L.39%2037.509a.763.763%200%200%201-.285-.276.736.736%200%200%201-.104-.376V5.947c0-.067.01-.133.027-.196.006-.022.02-.042.027-.063.015-.04.028-.08.05-.117.014-.024.035-.044.053-.067.022-.03.042-.06.068-.087.022-.021.051-.037.077-.056.028-.023.053-.047.085-.065L9.677.1a.793.793%200%200%201%20.774%200l9.29%205.196h.002c.03.019.057.042.085.064.025.019.053.036.075.056.027.027.047.058.07.088.016.023.038.043.052.067.022.038.035.077.05.117.008.021.021.04.027.063a.74.74%200%200%201%20.027.197v19.305l7.742-4.33v-9.869c0-.066.01-.132.027-.195.006-.023.019-.042.027-.064.015-.04.029-.08.05-.116.014-.025.036-.045.052-.067.023-.03.043-.061.07-.087.022-.022.05-.038.075-.057.03-.022.054-.047.085-.065l9.292-5.195a.792.792%200%200%201%20.773%200l9.29%205.195c.033.02.058.043.087.064.025.02.053.036.075.057.027.027.046.058.07.088.017.022.038.042.052.067.022.036.034.077.05.116.009.022.021.041.027.064ZM46.45%2020.923v-8.567l-3.25%201.818-4.492%202.512v8.567l7.743-4.33Zm-9.29%2015.5v-8.574l-4.417%202.45-12.616%206.995v8.654l17.033-9.526ZM1.55%207.247v29.174l17.03%209.525v-8.653l-8.897-4.89-.003-.003-.003-.002c-.03-.017-.056-.041-.084-.062-.024-.018-.052-.033-.073-.054l-.002-.003c-.025-.023-.042-.053-.064-.079-.02-.025-.042-.047-.058-.073v-.003c-.018-.028-.029-.062-.041-.094-.013-.028-.03-.054-.037-.084-.01-.036-.012-.075-.016-.111-.003-.028-.011-.056-.011-.085V11.58L4.8%209.064%201.549%207.248Zm8.516-5.628-7.74%204.328%207.738%204.328%207.74-4.33-7.74-4.326h.002Zm4.026%2027.01%204.49-2.51V7.247L15.33%209.066l-4.492%202.512V30.45l3.253-1.819ZM37.935%206.727l-7.74%204.328%207.74%204.328%207.738-4.329-7.738-4.327Zm-.775%209.959-4.49-2.512-3.252-1.818v8.567l4.49%202.511%203.252%201.82v-8.568ZM19.353%2035.993l11.352-6.295%205.674-3.146-7.733-4.325-8.904%204.98-8.116%204.538%207.727%204.248Z%22%20fill%3D%22%23FF2D20%22/%3E%3C/svg%3E) no-repeat 11px center / 20px 20px !important;
|
||||
padding: 4px 4px 6px 38px;
|
||||
margin: 0px !important;
|
||||
}
|
||||
|
||||
div.phpdebugbar-openhandler .phpdebugbar-openhandler-header a {
|
||||
display: flex;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
div.phpdebugbar-header,
|
||||
div.phpdebugbar-openhandler-header {
|
||||
background-size: 21px auto;
|
||||
background-position: 9px center;
|
||||
}
|
||||
|
||||
a.phpdebugbar-restore-btn {
|
||||
border-right-color: #ddd!important;
|
||||
height: 20px;
|
||||
width: 24px;
|
||||
background-position: center;
|
||||
background-size: 21px;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.phpdebugbar:not(.phpdebugbar-closed) a.phpdebugbar-restore-btn {
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
div.phpdebugbar-header > div > * {
|
||||
font-size: 13px;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
div.phpdebugbar-header .phpdebugbar-tab {
|
||||
padding: 5px 8px;
|
||||
border-left: 1px solid #ddd;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
a.phpdebugbar-tab.phpdebugbar-tab-history {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
div.phpdebugbar-header .phpdebugbar-header-left {
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
div.phpdebugbar .phpdebugbar-header select {
|
||||
margin: 0;
|
||||
padding: 2px 3px 3px 3px;
|
||||
border-radius: 3px;
|
||||
width: auto;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
dl.phpdebugbar-widgets-kvlist dt,
|
||||
dl.phpdebugbar-widgets-kvlist dd {
|
||||
min-height: 20px;
|
||||
line-height: 20px;
|
||||
padding: 4px 5px 5px;
|
||||
border-top: 0px;
|
||||
}
|
||||
|
||||
dl.phpdebugbar-widgets-kvlist dd.phpdebugbar-widgets-value.phpdebugbar-widgets-pretty .phpdebugbar-widgets-code-block {
|
||||
padding: 0px 0px;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
dl.phpdebugbar-widgets-kvlist dt {
|
||||
width: 25%;
|
||||
}
|
||||
|
||||
dl.phpdebugbar-widgets-kvlist dd {
|
||||
margin-left: 25%;
|
||||
}
|
||||
|
||||
ul.phpdebugbar-widgets-timeline li .phpdebugbar-widgets-measure {
|
||||
margin: 0 6px !important;
|
||||
height: 28px;
|
||||
line-height: 28px;
|
||||
border: none;
|
||||
}
|
||||
|
||||
ul.phpdebugbar-widgets-timeline li > .phpdebugbar-widgets-measure {
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
ul.phpdebugbar-widgets-timeline li span.phpdebugbar-widgets-value {
|
||||
height: 16px;
|
||||
background-color: #63abca;
|
||||
border-bottom: 2px solid #477e96;
|
||||
}
|
||||
|
||||
ul.phpdebugbar-widgets-timeline li span.phpdebugbar-widgets-label,
|
||||
ul.phpdebugbar-widgets-timeline li span.phpdebugbar-widgets-collector {
|
||||
top: 0px;
|
||||
color: #000;
|
||||
font-size: 11px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
max-width: 90%;
|
||||
}
|
||||
|
||||
ul.phpdebugbar-widgets-timeline li .phpdebugbar-widgets-value span.phpdebugbar-widgets-label {
|
||||
color: #fff;
|
||||
text-shadow: 1px 1px #000;
|
||||
}
|
||||
|
||||
ul.phpdebugbar-widgets-timeline table.phpdebugbar-widgets-params {
|
||||
font-size: 11px;
|
||||
margin-top: 20px !important;
|
||||
}
|
||||
|
||||
ul.phpdebugbar-widgets-timeline table.phpdebugbar-widgets-params td {
|
||||
border-left: none ;
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
ul.phpdebugbar-widgets-timeline table.phpdebugbar-widgets-params td:first-child {
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
div.phpdebugbar-widgets-messages div.phpdebugbar-widgets-toolbar {
|
||||
width: calc(100% - 20px);
|
||||
margin-left: 10px;
|
||||
padding: 4px 0px 4px;
|
||||
height: 20px;
|
||||
border-top: 1px solid #ddd;
|
||||
border-bottom: 0px;
|
||||
background-color: #e8e8e8;
|
||||
border-radius: 5px 5px 0px 0px;
|
||||
}
|
||||
|
||||
div.phpdebugbar-widgets-messages div.phpdebugbar-widgets-toolbar a.phpdebugbar-widgets-filter, div.phpdebugbar-widgets-messages div.phpdebugbar-widgets-toolbar a.phpdebugbar-widgets-filter.phpdebugbar-widgets-excluded {
|
||||
right: 3px;
|
||||
}
|
||||
|
||||
div.phpdebugbar-widgets-messages div.phpdebugbar-widgets-toolbar input {
|
||||
width: calc(100% - 48px);
|
||||
margin-left: 0px;
|
||||
border-radius: 3px;
|
||||
padding: 2px 6px;
|
||||
height: 15px;
|
||||
}
|
||||
|
||||
div.phpdebugbar-widgets-messages li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-label,
|
||||
div.phpdebugbar-widgets-messages li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-collector {
|
||||
padding: 1px 0px 0px 10px;
|
||||
margin: 0px;
|
||||
text-transform: uppercase;
|
||||
font-style: normal;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
div.phpdebugbar-widgets-messages li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-collector {
|
||||
text-transform: none;
|
||||
color: #888;
|
||||
}
|
||||
|
||||
.phpdebugbar-widgets-toolbar i.phpdebugbar-fa.phpdebugbar-fa-search {
|
||||
position: relative;
|
||||
top: -1px;
|
||||
padding: 0px 10px;
|
||||
}
|
||||
|
||||
div.phpdebugbar-widgets-messages div.phpdebugbar-widgets-toolbar a.phpdebugbar-widgets-filter,
|
||||
div.phpdebugbar-widgets-messages div.phpdebugbar-widgets-toolbar a.phpdebugbar-widgets-filter.phpdebugbar-widgets-excluded {
|
||||
position: relative;
|
||||
top: -48px;
|
||||
display: inline-block;
|
||||
background-color: #6d6d6d;
|
||||
margin-left: 3px;
|
||||
border-radius: 3px;
|
||||
padding: 5px 8px 4px;
|
||||
text-transform: uppercase;
|
||||
font-size: 10px;
|
||||
text-shadow: 1px 1px #585858;
|
||||
transition: background-color .25s linear 0s, color .25s linear 0s;
|
||||
color: #FFF;
|
||||
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
div.phpdebugbar-widgets-messages div.phpdebugbar-widgets-toolbar a.phpdebugbar-widgets-filter[rel="alert"],
|
||||
div.phpdebugbar-widgets-messages div.phpdebugbar-widgets-toolbar a.phpdebugbar-widgets-filter.phpdebugbar-widgets-excluded[rel="alert"],
|
||||
div.phpdebugbar-widgets-messages div.phpdebugbar-widgets-toolbar a.phpdebugbar-widgets-filter[rel="info"],
|
||||
div.phpdebugbar-widgets-messages div.phpdebugbar-widgets-toolbar a.phpdebugbar-widgets-filter.phpdebugbar-widgets-excluded[rel="info"] {
|
||||
background-color: #5896e2;
|
||||
}
|
||||
|
||||
div.phpdebugbar-widgets-messages div.phpdebugbar-widgets-toolbar a.phpdebugbar-widgets-filter[rel="debug"],
|
||||
div.phpdebugbar-widgets-messages div.phpdebugbar-widgets-toolbar a.phpdebugbar-widgets-filter.phpdebugbar-widgets-excluded[rel="debug"],
|
||||
div.phpdebugbar-widgets-messages div.phpdebugbar-widgets-toolbar a.phpdebugbar-widgets-filter[rel="success"],
|
||||
div.phpdebugbar-widgets-messages div.phpdebugbar-widgets-toolbar a.phpdebugbar-widgets-filter.phpdebugbar-widgets-excluded[rel="success"] {
|
||||
background-color: #45ab45;
|
||||
}
|
||||
|
||||
div.phpdebugbar-widgets-messages div.phpdebugbar-widgets-toolbar a.phpdebugbar-widgets-filter[rel="critical"],
|
||||
div.phpdebugbar-widgets-messages div.phpdebugbar-widgets-toolbar a.phpdebugbar-widgets-filter.phpdebugbar-widgets-excluded[rel="critical"],
|
||||
div.phpdebugbar-widgets-messages div.phpdebugbar-widgets-toolbar a.phpdebugbar-widgets-filter[rel="error"],
|
||||
div.phpdebugbar-widgets-messages div.phpdebugbar-widgets-toolbar a.phpdebugbar-widgets-filter.phpdebugbar-widgets-excluded[rel="error"] {
|
||||
background-color: var(--color-red-vivid);
|
||||
}
|
||||
|
||||
div.phpdebugbar-widgets-messages div.phpdebugbar-widgets-toolbar a.phpdebugbar-widgets-filter[rel="notice"],
|
||||
div.phpdebugbar-widgets-messages div.phpdebugbar-widgets-toolbar a.phpdebugbar-widgets-filter.phpdebugbar-widgets-excluded[rel="notice"],
|
||||
div.phpdebugbar-widgets-messages div.phpdebugbar-widgets-toolbar a.phpdebugbar-widgets-filter[rel="warning"],
|
||||
div.phpdebugbar-widgets-messages div.phpdebugbar-widgets-toolbar a.phpdebugbar-widgets-filter.phpdebugbar-widgets-excluded[rel="warning"] {
|
||||
background-color: #f99400;
|
||||
}
|
||||
|
||||
div.phpdebugbar-widgets-messages div.phpdebugbar-widgets-toolbar a.phpdebugbar-widgets-filter:hover {
|
||||
color: #FFF;
|
||||
opacity: 0.85;
|
||||
}
|
||||
|
||||
div.phpdebugbar-widgets-messages div.phpdebugbar-widgets-toolbar a.phpdebugbar-widgets-filter.phpdebugbar-widgets-excluded {
|
||||
opacity: 0.45;
|
||||
}
|
||||
|
||||
a.phpdebugbar-tab:hover,
|
||||
span.phpdebugbar-indicator:hover,
|
||||
a.phpdebugbar-indicator:hover,
|
||||
a.phpdebugbar-close-btn:hover,
|
||||
a.phpdebugbar-restore-btn:hover,
|
||||
a.phpdebugbar-minimize-btn:hover,
|
||||
a.phpdebugbar-maximize-btn:hover,
|
||||
a.phpdebugbar-open-btn:hover {
|
||||
background-color: #ebebeb;
|
||||
/* transition: background-color .25s linear 0s, color .25s linear 0s; */
|
||||
}
|
||||
|
||||
a.phpdebugbar-minimize-btn,
|
||||
a.phpdebugbar-maximize-btn {
|
||||
width: 28px!important;
|
||||
}
|
||||
|
||||
a.phpdebugbar-tab.phpdebugbar-active {
|
||||
background: var(--color-red-vivid);
|
||||
background-image: none;
|
||||
color: #fff !important;
|
||||
text-shadow: 1px 1px #bf3039;
|
||||
}
|
||||
|
||||
a.phpdebugbar-tab.phpdebugbar-active span.phpdebugbar-badge {
|
||||
background-color: white;
|
||||
color: var(--color-red-vivid);
|
||||
text-shadow: 1px 1px #ebebeb;
|
||||
}
|
||||
|
||||
a.phpdebugbar-tab span.phpdebugbar-badge {
|
||||
vertical-align: 0px;
|
||||
padding: 2px 8px;
|
||||
text-align: center;
|
||||
background: var(--color-red-vivid);
|
||||
font-size: 11px;
|
||||
font-family: monospace;
|
||||
color: #fff;
|
||||
text-shadow: 1px 1px #bf3039;
|
||||
border-radius: 10px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.phpdebugbar-indicator {
|
||||
cursor: text;
|
||||
}
|
||||
|
||||
.phpdebugbar-indicator span.phpdebugbar-tooltip,
|
||||
div.phpdebugbar-mini-design a.phpdebugbar-tab:hover span.phpdebugbar-text {
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
background: #f5f5f5;
|
||||
font-size: 12px;
|
||||
width: auto;
|
||||
white-space: nowrap;
|
||||
padding: 2px 18px;
|
||||
text-shadow: none;
|
||||
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
div.phpdebugbar-mini-design a.phpdebugbar-tab:hover span.phpdebugbar-text {
|
||||
left: 0px;
|
||||
right: auto;
|
||||
}
|
||||
|
||||
.phpdebugbar-widgets-toolbar > .fa {
|
||||
width: 25px;
|
||||
font-size: 15px;
|
||||
color: #555;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
ul.phpdebugbar-widgets-list li.phpdebugbar-widgets-list-item {
|
||||
padding: 7px 10px;
|
||||
border: none;
|
||||
font-family: inherit;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
ul.phpdebugbar-widgets-list li.phpdebugbar-widgets-list-item .phpdebugbar-widgets-sql {
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
ul.phpdebugbar-widgets-list li.phpdebugbar-widgets-list-item:hover,
|
||||
ul.phpdebugbar-widgets-timeline li:hover {
|
||||
background-color: initial;
|
||||
}
|
||||
|
||||
.phpdebugbar-widgets-sqlqueries ul.phpdebugbar-widgets-list li.phpdebugbar-widgets-list-item {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.phpdebugbar-widgets-templates ul.phpdebugbar-widgets-list li.phpdebugbar-widgets-list-item {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.phpdebugbar-widgets-templates ul.phpdebugbar-widgets-list li.phpdebugbar-widgets-list-item,
|
||||
.phpdebugbar-widgets-mails ul.phpdebugbar-widgets-list li.phpdebugbar-widgets-list-item {
|
||||
line-height: 15px;
|
||||
}
|
||||
|
||||
.phpdebugbar-widgets-mails ul.phpdebugbar-widgets-list li.phpdebugbar-widgets-list-item {
|
||||
cursor: pointer;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.phpdebugbar-widgets-mails ul.phpdebugbar-widgets-list li.phpdebugbar-widgets-list-item .phpdebugbar-widgets-subject {
|
||||
display: inline-block;
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
.phpdebugbar-widgets-mails ul.phpdebugbar-widgets-list li.phpdebugbar-widgets-list-item .phpdebugbar-widgets-headers {
|
||||
margin: 10px 0px;
|
||||
padding: 7px 10px;
|
||||
border-left: 2px solid #ddd;
|
||||
line-height: 17px;
|
||||
}
|
||||
|
||||
.phpdebugbar-widgets-sql.phpdebugbar-widgets-name {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
ul.phpdebugbar-widgets-list li.phpdebugbar-widgets-list-item .phpdebugbar-widgets-sql {
|
||||
flex: 1;
|
||||
margin-right: 5px;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
ul.phpdebugbar-widgets-list li.phpdebugbar-widgets-list-item .phpdebugbar-widgets-duration,
|
||||
ul.phpdebugbar-widgets-list li.phpdebugbar-widgets-list-item .phpdebugbar-widgets-stmt-id,
|
||||
ul.phpdebugbar-widgets-list li.phpdebugbar-widgets-list-item .phpdebugbar-widgets-memory {
|
||||
margin-left: auto;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
ul.phpdebugbar-widgets-list li.phpdebugbar-widgets-list-item .phpdebugbar-widgets-database {
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
ul.phpdebugbar-widgets-list li.phpdebugbar-widgets-list-item .phpdebugbar-widgets-stmt-id a {
|
||||
color: #888;
|
||||
}
|
||||
|
||||
ul.phpdebugbar-widgets-list li.phpdebugbar-widgets-list-item .phpdebugbar-widgets-stmt-id a:hover {
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
ul.phpdebugbar-widgets-list li.phpdebugbar-widgets-list-item table.phpdebugbar-widgets-params {
|
||||
background-color: #fdfdfd;
|
||||
margin: 10px 0px;
|
||||
font-size: 12px;
|
||||
border-left: 2px solid #cecece;
|
||||
}
|
||||
|
||||
div.phpdebugbar-widgets-templates table.phpdebugbar-widgets-params th,
|
||||
div.phpdebugbar-widgets-templates table.phpdebugbar-widgets-params td {
|
||||
padding: 1px 10px!important;
|
||||
}
|
||||
|
||||
div.phpdebugbar-widgets-templates table.phpdebugbar-widgets-params th {
|
||||
padding: 2px 10px!important;
|
||||
background-color: #efefef;
|
||||
}
|
||||
|
||||
div.phpdebugbar-widgets-sqlqueries table.phpdebugbar-widgets-params td.phpdebugbar-widgets-name {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
div.phpdebugbar-widgets-sqlqueries table.phpdebugbar-widgets-params td.phpdebugbar-widgets-name .phpdebugbar-fa {
|
||||
position: relative;
|
||||
top: 1px;
|
||||
margin-left: 3px;
|
||||
}
|
||||
|
||||
ul.phpdebugbar-widgets-list li.phpdebugbar-widgets-list-item:nth-child(even) {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
div.phpdebugbar-widgets-messages li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-value {
|
||||
display: inline-flex;
|
||||
}
|
||||
|
||||
div.phpdebugbar-widgets-messages li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-value:before {
|
||||
font-family: PhpDebugbarFontAwesome;
|
||||
content: "\f005";
|
||||
color: #333;
|
||||
font-size: 15px !important;
|
||||
margin-right: 8px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
div.phpdebugbar-widgets-messages li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-value.phpdebugbar-widgets-info {
|
||||
color: #1299DA;
|
||||
}
|
||||
|
||||
div.phpdebugbar-widgets-messages li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-value.phpdebugbar-widgets-info:before {
|
||||
content: "\f05a";
|
||||
color: #5896e2;
|
||||
}
|
||||
|
||||
div.phpdebugbar-widgets-messages li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-value.phpdebugbar-widgets-success:before {
|
||||
content: "\f058";
|
||||
color: #45ab45;
|
||||
}
|
||||
|
||||
div.phpdebugbar-widgets-messages li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-value.phpdebugbar-widgets-error {
|
||||
color: #e74c3c;
|
||||
}
|
||||
|
||||
div.phpdebugbar-widgets-messages li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-value.phpdebugbar-widgets-error:before {
|
||||
color: var(--color-red-vivid);
|
||||
}
|
||||
|
||||
div.phpdebugbar-widgets-messages li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-value.phpdebugbar-widgets-warning:before,
|
||||
div.phpdebugbar-widgets-messages .phpdebugbar-widgets-value.phpdebugbar-widgets-warning {
|
||||
color: #FF9800;
|
||||
}
|
||||
|
||||
div.phpdebugbar-widgets-messages li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-value.phpdebugbar-widgets-deprecation:before {
|
||||
content: "\f1f6";
|
||||
color: #FF9800;
|
||||
}
|
||||
|
||||
div.phpdebugbar-widgets-messages li.phpdebugbar-widgets-list-item pre.sf-dump {
|
||||
display: inline-block !important;
|
||||
position: relative;
|
||||
top: -1px;
|
||||
}
|
||||
|
||||
div.phpdebugbar-panel div.phpdebugbar-widgets-status {
|
||||
padding: 9px 10px !important;
|
||||
width: calc(100% - 20px);
|
||||
margin-top: 0px !important;
|
||||
line-height: 11px!important;
|
||||
font-weight: bold!important;
|
||||
background: #f5f5f5!important;
|
||||
border-bottom: 1px solid #cecece!important;
|
||||
}
|
||||
|
||||
div.phpdebugbar-panel div.phpdebugbar-widgets-status > * {
|
||||
color: #383838!important;
|
||||
}
|
||||
|
||||
div.phpdebugbar-panel div.phpdebugbar-widgets-status > span:first-child:before {
|
||||
font-family: PhpDebugbarFontAwesome;
|
||||
content: "\f05a";
|
||||
color: #737373;
|
||||
text-shadow: 1px 1px #fff;
|
||||
font-size: 14px;
|
||||
position: relative;
|
||||
top: 1px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
div.phpdebugbar-widgets-sqlqueries table.phpdebugbar-widgets-params th,
|
||||
div.phpdebugbar-widgets-sqlqueries table.phpdebugbar-widgets-params td {
|
||||
padding: 4px 10px;
|
||||
}
|
||||
|
||||
div.phpdebugbar-widgets-sqlqueries table.phpdebugbar-widgets-params th {
|
||||
background-color: #efefef;
|
||||
}
|
||||
|
||||
div.phpdebugbar-widgets-sqlqueries table.phpdebugbar-widgets-params td.phpdebugbar-widgets-name {
|
||||
text-align: right;
|
||||
vertical-align: top;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
div.phpdebugbar-widgets-sqlqueries table.phpdebugbar-widgets-params td.phpdebugbar-widgets-value {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
div.phpdebugbar-widgets-templates .phpdebugbar-widgets-list-item table.phpdebugbar-widgets-params {
|
||||
width: auto!important;
|
||||
}
|
||||
|
||||
ul.phpdebugbar-widgets-list ul.phpdebugbar-widgets-table-list {
|
||||
text-align: left;
|
||||
line-height: 150%;
|
||||
}
|
||||
|
||||
.phpdebugbar-text-muted {
|
||||
color: #888;
|
||||
}
|
||||
|
||||
ul.phpdebugbar-widgets-cache a.phpdebugbar-widgets-forget {
|
||||
float: right;
|
||||
font-size: 12px;
|
||||
padding: 0 4px;
|
||||
background: var(--color-red-vivid);
|
||||
margin: 0 2px;
|
||||
border-radius: 4px;
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
line-height: 1.5rem;
|
||||
}
|
||||
|
||||
a.phpdebugbar-tab i {
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
div.phpdebugbar-mini-design a.phpdebugbar-tab {
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
div.phpdebugbar-header-right {
|
||||
display:flex;
|
||||
flex-direction: row-reverse;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
div.phpdebugbar-header-right > a {
|
||||
height: 20px;
|
||||
background-position: center;
|
||||
}
|
||||
|
||||
div.phpdebugbar-header-right .phpdebugbar-indicator > i.phpdebugbar-fa {
|
||||
vertical-align: baseline;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
div.phpdebugbar-panel[data-collector="__datasets"] {
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
div.phpdebugbar-panel table {
|
||||
margin: 10px 0px!important;
|
||||
width: 100%!important;
|
||||
}
|
||||
|
||||
div.phpdebugbar-panel table .phpdebugbar-widgets-name {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
dl.phpdebugbar-widgets-kvlist > :nth-child(4n-1),
|
||||
dl.phpdebugbar-widgets-kvlist > :nth-child(4n) {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
.phpdebugbar pre.sf-dump:after {
|
||||
clear: none!important;
|
||||
}
|
||||
|
||||
div.phpdebugbar-widgets-exceptions li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-message {
|
||||
color: #dd1044;
|
||||
}
|
||||
|
||||
div.phpdebugbar-widgets-exceptions li.phpdebugbar-widgets-list-item > div {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
div.phpdebugbar-widgets-sqlqueries span.phpdebugbar-widgets-database:before,
|
||||
div.phpdebugbar-widgets-sqlqueries span.phpdebugbar-widgets-duration:before,
|
||||
div.phpdebugbar-widgets-sqlqueries span.phpdebugbar-widgets-memory:before,
|
||||
div.phpdebugbar-widgets-sqlqueries span.phpdebugbar-widgets-row-count:before,
|
||||
div.phpdebugbar-widgets-sqlqueries span.phpdebugbar-widgets-copy-clipboard:before,
|
||||
div.phpdebugbar-widgets-sqlqueries span.phpdebugbar-widgets-stmt-id:before,
|
||||
div.phpdebugbar-widgets-templates span.phpdebugbar-widgets-param-count:before {
|
||||
margin-right: 6px!important;
|
||||
}
|
||||
|
||||
.phpdebugbar-widgets-list-item .phpdebugbar-widgets-bg-measure {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.phpdebugbar-widgets-bg-measure .phpdebugbar-widgets-value {
|
||||
position: absolute;
|
||||
height: 1px !important;
|
||||
opacity: 1 !important;
|
||||
bottom: 0;
|
||||
background: #63abca !important;
|
||||
}
|
||||
|
||||
div.phpdebugbar dl.phpdebugbar-widgets-kvlist > :nth-child(4n)::before {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
dt.phpdebugbar-widgets-key {
|
||||
padding-left: 10px !important;
|
||||
}
|
||||
|
||||
dt.phpdebugbar-widgets-key {
|
||||
position: relative;
|
||||
background: white;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
dd.phpdebugbar-widgets-value {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
dd.phpdebugbar-widgets-value::before {
|
||||
content: " ";
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 33.33%;
|
||||
margin-left: -33.33%;
|
||||
}
|
||||
|
||||
dd.phpdebugbar-widgets-value pre.sf-dump {
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
ul.phpdebugbar-widgets-table-list {
|
||||
padding: 4px 0;
|
||||
}
|
||||
|
||||
ul.phpdebugbar-widgets-table-list li {
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
ul.phpdebugbar-widgets-table-list li:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
|
||||
pre.phpdebugbar-widgets-code-block ul.phpdebugbar-widgets-numbered-code li {
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
div.phpdebugbar .phpdebugbar-indicator span.phpdebugbar-tooltip,
|
||||
div.phpdebugbar div.phpdebugbar-mini-design a.phpdebugbar-tab:hover span.phpdebugbar-text,
|
||||
div.phpdebugbar pre.sf-dump,
|
||||
div.phpdebugbar .hljs,
|
||||
div.phpdebugbar code.phpdebugbar-widgets-sql span.hljs-operator {
|
||||
color: var(--color-gray-100) !important;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
<?php
|
||||
|
||||
namespace Barryvdh\Debugbar;
|
||||
|
||||
use Barryvdh\Debugbar\Middleware\DebugbarEnabled;
|
||||
use Barryvdh\Debugbar\Middleware\InjectDebugbar;
|
||||
use DebugBar\DataFormatter\DataFormatter;
|
||||
use DebugBar\DataFormatter\DataFormatterInterface;
|
||||
use Illuminate\Container\Container;
|
||||
use Illuminate\Contracts\View\Factory;
|
||||
use Illuminate\Contracts\Http\Kernel;
|
||||
use Illuminate\Routing\Router;
|
||||
use Illuminate\Session\SessionManager;
|
||||
use Illuminate\Support\Collection;
|
||||
use Barryvdh\Debugbar\Facade as DebugBar;
|
||||
|
||||
class ServiceProvider extends \Illuminate\Support\ServiceProvider
|
||||
{
|
||||
/**
|
||||
* Register the service provider.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
$configPath = __DIR__ . '/../config/debugbar.php';
|
||||
$this->mergeConfigFrom($configPath, 'debugbar');
|
||||
|
||||
$this->app->alias(
|
||||
DataFormatter::class,
|
||||
DataFormatterInterface::class
|
||||
);
|
||||
|
||||
$this->app->singleton(LaravelDebugbar::class, function ($app) {
|
||||
$debugbar = new LaravelDebugbar($app);
|
||||
|
||||
if ($app->bound(SessionManager::class)) {
|
||||
$sessionManager = $app->make(SessionManager::class);
|
||||
$httpDriver = new SymfonyHttpDriver($sessionManager);
|
||||
$debugbar->setHttpDriver($httpDriver);
|
||||
}
|
||||
|
||||
return $debugbar;
|
||||
});
|
||||
|
||||
$this->app->alias(LaravelDebugbar::class, 'debugbar');
|
||||
|
||||
$this->app->singleton(
|
||||
'command.debugbar.clear',
|
||||
function ($app) {
|
||||
return new Console\ClearCommand($app['debugbar']);
|
||||
}
|
||||
);
|
||||
|
||||
$this->app->extend(
|
||||
'view',
|
||||
function (Factory $factory, Container $application): Factory {
|
||||
$laravelDebugbar = $application->make(LaravelDebugbar::class);
|
||||
|
||||
$shouldTrackViewTime = $laravelDebugbar->isEnabled() &&
|
||||
$laravelDebugbar->shouldCollect('time', true) &&
|
||||
$laravelDebugbar->shouldCollect('views', true) &&
|
||||
$application['config']->get('debugbar.options.views.timeline', false);
|
||||
|
||||
if (! $shouldTrackViewTime) {
|
||||
/* Do not swap the engine to save performance */
|
||||
return $factory;
|
||||
}
|
||||
|
||||
$extensions = array_reverse($factory->getExtensions());
|
||||
$engines = array_flip($extensions);
|
||||
$enginesResolver = $application->make('view.engine.resolver');
|
||||
|
||||
foreach ($engines as $engine => $extension) {
|
||||
$resolved = $enginesResolver->resolve($engine);
|
||||
|
||||
$factory->addExtension($extension, $engine, function () use ($resolved, $laravelDebugbar) {
|
||||
return new DebugbarViewEngine($resolved, $laravelDebugbar);
|
||||
});
|
||||
}
|
||||
|
||||
// returns original order of extensions
|
||||
foreach ($extensions as $extension => $engine) {
|
||||
$factory->addExtension($extension, $engine);
|
||||
}
|
||||
|
||||
return $factory;
|
||||
}
|
||||
);
|
||||
|
||||
Collection::macro('debug', function () {
|
||||
debug($this);
|
||||
return $this;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Bootstrap the application events.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
$configPath = __DIR__ . '/../config/debugbar.php';
|
||||
$this->publishes([$configPath => $this->getConfigPath()], 'config');
|
||||
|
||||
$this->loadRoutesFrom(realpath(__DIR__ . '/debugbar-routes.php'));
|
||||
|
||||
$this->registerMiddleware(InjectDebugbar::class);
|
||||
|
||||
$this->commands(['command.debugbar.clear']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the active router.
|
||||
*
|
||||
* @return Router
|
||||
*/
|
||||
protected function getRouter()
|
||||
{
|
||||
return $this->app['router'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the config path
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getConfigPath()
|
||||
{
|
||||
return config_path('debugbar.php');
|
||||
}
|
||||
|
||||
/**
|
||||
* Publish the config file
|
||||
*
|
||||
* @param string $configPath
|
||||
*/
|
||||
protected function publishConfig($configPath)
|
||||
{
|
||||
$this->publishes([$configPath => config_path('debugbar.php')], 'config');
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the Debugbar Middleware
|
||||
*
|
||||
* @param string $middleware
|
||||
*/
|
||||
protected function registerMiddleware($middleware)
|
||||
{
|
||||
$kernel = $this->app[Kernel::class];
|
||||
$kernel->pushMiddleware($middleware);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
<?php
|
||||
|
||||
namespace Barryvdh\Debugbar\Storage;
|
||||
|
||||
use DebugBar\Storage\StorageInterface;
|
||||
use Illuminate\Filesystem\Filesystem;
|
||||
use Symfony\Component\Finder\Finder;
|
||||
|
||||
/**
|
||||
* Stores collected data into files
|
||||
*/
|
||||
class FilesystemStorage implements StorageInterface
|
||||
{
|
||||
protected $dirname;
|
||||
protected $files;
|
||||
protected $gc_lifetime = 24; // Hours to keep collected data;
|
||||
protected $gc_probability = 5; // Probability of GC being run on a save request. (5/100)
|
||||
|
||||
/**
|
||||
* @param \Illuminate\Filesystem\Filesystem $files The filesystem
|
||||
* @param string $dirname Directories where to store files
|
||||
*/
|
||||
public function __construct($files, $dirname)
|
||||
{
|
||||
$this->files = $files;
|
||||
$this->dirname = rtrim($dirname, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function save($id, $data)
|
||||
{
|
||||
if (!$this->files->isDirectory($this->dirname)) {
|
||||
if ($this->files->makeDirectory($this->dirname, 0777, true)) {
|
||||
$this->files->put($this->dirname . '.gitignore', "*\n!.gitignore\n");
|
||||
} else {
|
||||
throw new \Exception("Cannot create directory '$this->dirname'..");
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
$this->files->put($this->makeFilename($id), json_encode($data));
|
||||
} catch (\Exception $e) {
|
||||
//TODO; error handling
|
||||
}
|
||||
|
||||
// Randomly check if we should collect old files
|
||||
if (rand(1, 100) <= $this->gc_probability) {
|
||||
$this->garbageCollect();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the filename for the data, based on the id.
|
||||
*
|
||||
* @param $id
|
||||
* @return string
|
||||
*/
|
||||
public function makeFilename($id)
|
||||
{
|
||||
return $this->dirname . basename($id) . ".json";
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete files older than a certain age (gc_lifetime)
|
||||
*/
|
||||
protected function garbageCollect()
|
||||
{
|
||||
foreach (
|
||||
Finder::create()->files()->name('*.json')->date('< ' . $this->gc_lifetime . ' hour ago')->in(
|
||||
$this->dirname
|
||||
) as $file
|
||||
) {
|
||||
$this->files->delete($file->getRealPath());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function get($id)
|
||||
{
|
||||
return json_decode($this->files->get($this->makeFilename($id)), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function find(array $filters = [], $max = 20, $offset = 0)
|
||||
{
|
||||
// Sort by modified time, newest first
|
||||
$sort = function (\SplFileInfo $a, \SplFileInfo $b) {
|
||||
return strcmp($b->getMTime(), $a->getMTime());
|
||||
};
|
||||
|
||||
// Loop through .json files, filter the metadata and stop when max is found.
|
||||
$i = 0;
|
||||
$results = [];
|
||||
foreach (Finder::create()->files()->name('*.json')->in($this->dirname)->sort($sort) as $file) {
|
||||
if ($i++ < $offset && empty($filters)) {
|
||||
$results[] = null;
|
||||
continue;
|
||||
}
|
||||
$data = json_decode($file->getContents(), true);
|
||||
$meta = $data['__meta'];
|
||||
unset($data);
|
||||
if ($this->filter($meta, $filters)) {
|
||||
$results[] = $meta;
|
||||
}
|
||||
if (count($results) >= ($max + $offset)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return array_slice($results, $offset, $max);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter the metadata for matches.
|
||||
*
|
||||
* @param $meta
|
||||
* @param $filters
|
||||
* @return bool
|
||||
*/
|
||||
protected function filter($meta, $filters)
|
||||
{
|
||||
foreach ($filters as $key => $value) {
|
||||
if (!isset($meta[$key]) || fnmatch($value, $meta[$key]) === false) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function clear()
|
||||
{
|
||||
foreach (Finder::create()->files()->name('*.json')->in($this->dirname) as $file) {
|
||||
$this->files->delete($file->getRealPath());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
namespace Barryvdh\Debugbar\Storage;
|
||||
|
||||
use DebugBar\Storage\StorageInterface;
|
||||
|
||||
class SocketStorage implements StorageInterface
|
||||
{
|
||||
protected $hostname;
|
||||
protected $port;
|
||||
protected $socket;
|
||||
|
||||
/**
|
||||
* @param string $hostname The hostname to use for the socket
|
||||
* @param int $port The port to use for the socket
|
||||
*/
|
||||
public function __construct($hostname, $port)
|
||||
{
|
||||
$this->hostname = $hostname;
|
||||
$this->port = $port;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
function save($id, $data)
|
||||
{
|
||||
$socketIsFresh = !$this->socket;
|
||||
|
||||
if (!$this->socket = $this->socket ?: $this->createSocket()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$encodedPayload = json_encode([
|
||||
'id' => $id,
|
||||
'base_path' => base_path(),
|
||||
'app' => config('app.name'),
|
||||
'data' => $data,
|
||||
]);
|
||||
|
||||
$encodedPayload = strlen($encodedPayload) . '#' . $encodedPayload;
|
||||
|
||||
set_error_handler([self::class, 'nullErrorHandler']);
|
||||
try {
|
||||
if (-1 !== stream_socket_sendto($this->socket, $encodedPayload)) {
|
||||
return true;
|
||||
}
|
||||
if (!$socketIsFresh) {
|
||||
stream_socket_shutdown($this->socket, \STREAM_SHUT_RDWR);
|
||||
fclose($this->socket);
|
||||
$this->socket = $this->createSocket();
|
||||
}
|
||||
if (-1 !== stream_socket_sendto($this->socket, $encodedPayload)) {
|
||||
return true;
|
||||
}
|
||||
} finally {
|
||||
restore_error_handler();
|
||||
}
|
||||
}
|
||||
|
||||
private static function nullErrorHandler($t, $m)
|
||||
{
|
||||
// no-op
|
||||
}
|
||||
|
||||
protected function createSocket()
|
||||
{
|
||||
set_error_handler([self::class, 'nullErrorHandler']);
|
||||
try {
|
||||
return stream_socket_client("tcp://{$this->hostname}:{$this->port}");
|
||||
} finally {
|
||||
restore_error_handler();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
function get($id)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
function find(array $filters = [], $max = 20, $offset = 0)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
function clear()
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
<?php
|
||||
|
||||
namespace Barryvdh\Debugbar\Support\Clockwork;
|
||||
|
||||
use DebugBar\DataCollector\DataCollector;
|
||||
use DebugBar\DataCollector\DataCollectorInterface;
|
||||
use DebugBar\DataCollector\Renderable;
|
||||
use Illuminate\Support\Arr;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
/**
|
||||
*
|
||||
* Based on \Symfony\Component\HttpKernel\DataCollector\RequestDataCollector by Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
*/
|
||||
class ClockworkCollector extends DataCollector implements DataCollectorInterface, Renderable
|
||||
{
|
||||
/** @var \Symfony\Component\HttpFoundation\Request $request */
|
||||
protected $request;
|
||||
/** @var \Symfony\Component\HttpFoundation\Request $response */
|
||||
protected $response;
|
||||
/** @var \Symfony\Component\HttpFoundation\Session\SessionInterface $session */
|
||||
protected $session;
|
||||
/** @var array */
|
||||
protected $hiddens;
|
||||
|
||||
/**
|
||||
* Create a new SymfonyRequestCollector
|
||||
*
|
||||
* @param \Symfony\Component\HttpFoundation\Request $request
|
||||
* @param \Symfony\Component\HttpFoundation\Request $response
|
||||
* @param \Symfony\Component\HttpFoundation\Session\SessionInterface $session
|
||||
* @param array $hiddens
|
||||
*/
|
||||
public function __construct($request, $response, $session = null, $hiddens = [])
|
||||
{
|
||||
$this->request = $request;
|
||||
$this->response = $response;
|
||||
$this->session = $session;
|
||||
$this->hiddens = array_merge($hiddens, [
|
||||
'request_request.password',
|
||||
'request_request.PHP_AUTH_PW',
|
||||
'request_request.php-auth-pw',
|
||||
'request_headers.php-auth-pw.0',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'clockwork';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getWidgets()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function collect()
|
||||
{
|
||||
$request = $this->request;
|
||||
$response = $this->response;
|
||||
|
||||
$data = [
|
||||
'getData' => $request->query->all(),
|
||||
'postData' => $request->request->all(),
|
||||
'headers' => $request->headers->all(),
|
||||
'cookies' => $request->cookies->all(),
|
||||
'uri' => $request->getRequestUri(),
|
||||
'method' => $request->getMethod(),
|
||||
'responseStatus' => $response->getStatusCode(),
|
||||
];
|
||||
|
||||
if ($this->session) {
|
||||
$data['sessionData'] = $this->session->all();
|
||||
}
|
||||
|
||||
if (isset($data['headers']['authorization'][0])) {
|
||||
$data['headers']['authorization'][0] = substr($data['headers']['authorization'][0], 0, 12) . '******';
|
||||
}
|
||||
|
||||
$keyAlias = [
|
||||
'request_query' => 'getData',
|
||||
'request_request' => 'postData',
|
||||
'request_headers' => 'headers',
|
||||
'request_cookies' => 'cookies',
|
||||
'session_attributes' => 'sessionData',
|
||||
];
|
||||
foreach ($this->hiddens as $key) {
|
||||
$key = explode('.', $key);
|
||||
$key[0] = $keyAlias[$key[0]] ?? $key[0];
|
||||
$key = implode('.', $key);
|
||||
if (Arr::has($data, $key)) {
|
||||
Arr::set($data, $key, '******');
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
<?php
|
||||
|
||||
namespace Barryvdh\Debugbar\Support\Clockwork;
|
||||
|
||||
class Converter
|
||||
{
|
||||
/**
|
||||
* Convert the phpdebugbar data to Clockwork format.
|
||||
*
|
||||
* @param array $data
|
||||
* @return array
|
||||
*/
|
||||
public function convert($data)
|
||||
{
|
||||
$meta = $data['__meta'];
|
||||
|
||||
// Default output
|
||||
$output = [
|
||||
'id' => $meta['id'],
|
||||
'method' => $meta['method'],
|
||||
'uri' => $meta['uri'],
|
||||
'time' => $meta['utime'],
|
||||
'headers' => [],
|
||||
'cookies' => [],
|
||||
'emailsData' => [],
|
||||
'getData' => [],
|
||||
'log' => [],
|
||||
'postData' => [],
|
||||
'sessionData' => [],
|
||||
'timelineData' => [],
|
||||
'viewsData' => [],
|
||||
'controller' => null,
|
||||
'responseTime' => null,
|
||||
'responseStatus' => null,
|
||||
'responseDuration' => 0,
|
||||
];
|
||||
|
||||
if (isset($data['clockwork'])) {
|
||||
$output = array_merge($output, $data['clockwork']);
|
||||
}
|
||||
|
||||
if (isset($data['memory'])) {
|
||||
$output['memoryUsage'] = $data['memory']['peak_usage'];
|
||||
}
|
||||
|
||||
if (isset($data['time'])) {
|
||||
$time = $data['time'];
|
||||
$output['time'] = $time['start'];
|
||||
$output['responseTime'] = $time['end'];
|
||||
$output['responseDuration'] = $time['duration'] * 1000;
|
||||
foreach ($time['measures'] as $measure) {
|
||||
$output['timelineData'][] = [
|
||||
'data' => [],
|
||||
'description' => $measure['label'],
|
||||
'duration' => $measure['duration'] * 1000,
|
||||
'end' => $measure['end'],
|
||||
'start' => $measure['start'],
|
||||
'relative_start' => $measure['start'] - $time['start'],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($data['route'])) {
|
||||
$route = $data['route'];
|
||||
|
||||
$controller = null;
|
||||
if (isset($route['controller'])) {
|
||||
$controller = $route['controller'];
|
||||
} elseif (isset($route['uses'])) {
|
||||
$controller = $route['uses'];
|
||||
}
|
||||
|
||||
$output['controller'] = $controller;
|
||||
|
||||
list($method, $uri) = explode(' ', $route['uri'], 2);
|
||||
|
||||
$output['routes'][] = [
|
||||
'action' => $controller,
|
||||
'after' => isset($route['after']) ? $route['after'] : null,
|
||||
'before' => isset($route['before']) ? $route['before'] : null,
|
||||
'method' => $method,
|
||||
'name' => isset($route['as']) ? $route['as'] : null,
|
||||
'uri' => $uri,
|
||||
];
|
||||
}
|
||||
|
||||
if (isset($data['messages'])) {
|
||||
foreach ($data['messages']['messages'] as $message) {
|
||||
$output['log'][] = [
|
||||
'message' => $message['message'],
|
||||
'time' => $message['time'],
|
||||
'level' => $message['label'],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($data['queries'])) {
|
||||
$queries = $data['queries'];
|
||||
foreach ($queries['statements'] as $statement) {
|
||||
if ($statement['type'] === 'explain') {
|
||||
continue;
|
||||
}
|
||||
$output['databaseQueries'][] = [
|
||||
'query' => $statement['sql'],
|
||||
'bindings' => $statement['params'],
|
||||
'duration' => $statement['duration'] * 1000,
|
||||
'time' => $statement['start'] ?? null,
|
||||
'connection' => $statement['connection']
|
||||
];
|
||||
}
|
||||
|
||||
$output['databaseDuration'] = $queries['accumulated_duration'] * 1000;
|
||||
}
|
||||
|
||||
if (isset($data['models'])) {
|
||||
$output['modelsActions'] = [];
|
||||
$output['modelsCreated'] = [];
|
||||
$output['modelsUpdated'] = [];
|
||||
$output['modelsDeleted'] = [];
|
||||
$output['modelsRetrieved'] = $data['models']['data'];
|
||||
}
|
||||
|
||||
if (isset($data['views'])) {
|
||||
foreach ($data['views']['templates'] as $view) {
|
||||
$output['viewsData'][] = [
|
||||
'description' => 'Rendering a view',
|
||||
'duration' => 0,
|
||||
'end' => 0,
|
||||
'start' => $view['start'] ?? 0,
|
||||
'data' => [
|
||||
'name' => $view['name'],
|
||||
'data' => $view['params'],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($data['event'])) {
|
||||
foreach ($data['event']['measures'] as $event) {
|
||||
$event['data'] = [];
|
||||
$event['listeners'] = [];
|
||||
foreach ($event['params'] ?? [] as $key => $param) {
|
||||
$event[is_numeric($key) ? 'data' : 'listeners'] = $param;
|
||||
}
|
||||
$output['events'][] = [
|
||||
'event' => ['event' => $event['label']],
|
||||
'data' => $event['data'],
|
||||
'time' => $event['start'],
|
||||
'duration' => $event['duration'] * 1000,
|
||||
'listeners' => $event['listeners'],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($data['symfonymailer_mails'])) {
|
||||
foreach ($data['symfonymailer_mails']['mails'] as $mail) {
|
||||
$output['emailsData'][] = [
|
||||
'data' => [
|
||||
'to' => implode(', ', $mail['to']),
|
||||
'subject' => $mail['subject'],
|
||||
'headers' => isset($mail['headers']) ? explode("\n", $mail['headers']) : null,
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
namespace Barryvdh\Debugbar;
|
||||
|
||||
use DebugBar\HttpDriverInterface;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpFoundation\Session\Session;
|
||||
|
||||
/**
|
||||
* HTTP driver for Symfony Request/Session
|
||||
*/
|
||||
class SymfonyHttpDriver implements HttpDriverInterface
|
||||
{
|
||||
/** @var \Illuminate\Contracts\Session\Session|\Illuminate\Session\SessionManager */
|
||||
protected $session;
|
||||
|
||||
/** @var \Symfony\Component\HttpFoundation\Response */
|
||||
protected $response;
|
||||
|
||||
public function __construct($session, $response = null)
|
||||
{
|
||||
$this->session = $session;
|
||||
$this->response = $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function setHeaders(array $headers)
|
||||
{
|
||||
if (!is_null($this->response)) {
|
||||
$this->response->headers->add($headers);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function isSessionStarted()
|
||||
{
|
||||
if (!$this->session->isStarted()) {
|
||||
$this->session->start();
|
||||
}
|
||||
|
||||
return $this->session->isStarted();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function setSessionValue($name, $value)
|
||||
{
|
||||
$this->session->put($name, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function hasSessionValue($name)
|
||||
{
|
||||
return $this->session->has($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getSessionValue($name)
|
||||
{
|
||||
return $this->session->get($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function deleteSessionValue($name)
|
||||
{
|
||||
$this->session->remove($name);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace Barryvdh\Debugbar\Twig\Extension;
|
||||
|
||||
use DebugBar\Bridge\Twig\DebugTwigExtension;
|
||||
use Illuminate\Foundation\Application;
|
||||
use Twig\Environment;
|
||||
|
||||
/**
|
||||
* Access debugbar debug in your Twig templates.
|
||||
*/
|
||||
class Debug extends DebugTwigExtension
|
||||
{
|
||||
protected $app;
|
||||
|
||||
/**
|
||||
* Create a new debug extension.
|
||||
*
|
||||
* @param \Illuminate\Foundation\Application $app
|
||||
*/
|
||||
public function __construct(Application $app)
|
||||
{
|
||||
$this->app = $app;
|
||||
parent::__construct(null);
|
||||
}
|
||||
|
||||
public function debug(Environment $env, $context)
|
||||
{
|
||||
if ($this->app->bound('debugbar') && $this->app['debugbar']->hasCollector('messages')) {
|
||||
$this->messagesCollector = $this->app['debugbar']['messages'];
|
||||
}
|
||||
|
||||
return parent::debug($env, $context);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace Barryvdh\Debugbar\Twig\Extension;
|
||||
|
||||
use DebugBar\Bridge\Twig\DumpTwigExtension;
|
||||
|
||||
/**
|
||||
* Dump variables using the DataFormatter
|
||||
*/
|
||||
class Dump extends DumpTwigExtension
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
namespace Barryvdh\Debugbar\Twig\Extension;
|
||||
|
||||
use DebugBar\Bridge\Twig\MeasureTwigExtension;
|
||||
use DebugBar\Bridge\Twig\MeasureTwigTokenParser;
|
||||
use Illuminate\Foundation\Application;
|
||||
|
||||
/**
|
||||
* Access debugbar time measures in your Twig templates.
|
||||
* Based on Symfony\Bridge\Twig\Extension\StopwatchExtension
|
||||
*/
|
||||
class Stopwatch extends MeasureTwigExtension
|
||||
{
|
||||
/**
|
||||
* @var \Barryvdh\Debugbar\LaravelDebugbar
|
||||
*/
|
||||
protected $debugbar;
|
||||
|
||||
/**
|
||||
* Create a new time measure extension.
|
||||
*
|
||||
* @param \Illuminate\Foundation\Application $app
|
||||
*/
|
||||
public function __construct(Application $app)
|
||||
{
|
||||
if ($app->bound('debugbar')) {
|
||||
$this->debugbar = $app['debugbar'];
|
||||
}
|
||||
|
||||
parent::__construct(null, 'stopwatch');
|
||||
}
|
||||
|
||||
|
||||
public function getDebugbar()
|
||||
{
|
||||
return $this->debugbar;
|
||||
}
|
||||
|
||||
public function getTokenParsers()
|
||||
{
|
||||
return [
|
||||
/*
|
||||
* {% measure foo %}
|
||||
* Some stuff which will be recorded on the timeline
|
||||
* {% endmeasure %}
|
||||
*/
|
||||
new MeasureTwigTokenParser(!is_null($this->debugbar), $this->tagName, $this->getName()),
|
||||
];
|
||||
}
|
||||
|
||||
public function startMeasure(...$arg)
|
||||
{
|
||||
if (!$this->debugbar || !$this->debugbar->hasCollector('time')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->debugbar->getCollector('time')->startMeasure(...$arg);
|
||||
}
|
||||
|
||||
public function stopMeasure(...$arg)
|
||||
{
|
||||
if (!$this->debugbar || !$this->debugbar->hasCollector('time')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->debugbar->getCollector('time')->stopMeasure(...$arg);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
$routeConfig = [
|
||||
'namespace' => 'Barryvdh\Debugbar\Controllers',
|
||||
'prefix' => app('config')->get('debugbar.route_prefix'),
|
||||
'domain' => app('config')->get('debugbar.route_domain'),
|
||||
'middleware' => array_merge(app('config')->get('debugbar.route_middleware', []), [\Barryvdh\Debugbar\Middleware\DebugbarEnabled::class]),
|
||||
];
|
||||
|
||||
app('router')->group($routeConfig, function ($router) {
|
||||
$router->get('open', [
|
||||
'uses' => 'OpenHandlerController@handle',
|
||||
'as' => 'debugbar.openhandler',
|
||||
]);
|
||||
|
||||
$router->get('clockwork/{id}', [
|
||||
'uses' => 'OpenHandlerController@clockwork',
|
||||
'as' => 'debugbar.clockwork',
|
||||
]);
|
||||
|
||||
if (class_exists(\Laravel\Telescope\Telescope::class)) {
|
||||
$router->get('telescope/{id}', [
|
||||
'uses' => 'TelescopeController@show',
|
||||
'as' => 'debugbar.telescope',
|
||||
]);
|
||||
}
|
||||
|
||||
$router->get('assets/stylesheets', [
|
||||
'uses' => 'AssetController@css',
|
||||
'as' => 'debugbar.assets.css',
|
||||
]);
|
||||
|
||||
$router->get('assets/javascript', [
|
||||
'uses' => 'AssetController@js',
|
||||
'as' => 'debugbar.assets.js',
|
||||
]);
|
||||
|
||||
$router->delete('cache/{key}/{tags?}', [
|
||||
'uses' => 'CacheController@delete',
|
||||
'as' => 'debugbar.cache.delete',
|
||||
]);
|
||||
});
|
||||
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
if (!function_exists('debugbar')) {
|
||||
/**
|
||||
* Get the Debugbar instance
|
||||
*
|
||||
* @return \Barryvdh\Debugbar\LaravelDebugbar
|
||||
*/
|
||||
function debugbar()
|
||||
{
|
||||
return app(\Barryvdh\Debugbar\LaravelDebugbar::class);
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('debug')) {
|
||||
/**
|
||||
* Adds one or more messages to the MessagesCollector
|
||||
*
|
||||
* @param mixed ...$value
|
||||
* @return string
|
||||
*/
|
||||
function debug($value)
|
||||
{
|
||||
$debugbar = debugbar();
|
||||
foreach (func_get_args() as $value) {
|
||||
$debugbar->addMessage($value, 'debug');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('start_measure')) {
|
||||
/**
|
||||
* Starts a measure
|
||||
*
|
||||
* @param string $name Internal name, used to stop the measure
|
||||
* @param string $label Public name
|
||||
*/
|
||||
function start_measure($name, $label = null)
|
||||
{
|
||||
debugbar()->startMeasure($name, $label);
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('stop_measure')) {
|
||||
/**
|
||||
* Stop a measure
|
||||
*
|
||||
* @param string $name Internal name, used to stop the measure
|
||||
*/
|
||||
function stop_measure($name)
|
||||
{
|
||||
debugbar()->stopMeasure($name);
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('add_measure')) {
|
||||
/**
|
||||
* Adds a measure
|
||||
*
|
||||
* @param string $label
|
||||
* @param float $start
|
||||
* @param float $end
|
||||
*/
|
||||
function add_measure($label, $start, $end)
|
||||
{
|
||||
debugbar()->addMeasure($label, $start, $end);
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('measure')) {
|
||||
/**
|
||||
* Utility function to measure the execution of a Closure
|
||||
*
|
||||
* @param string $label
|
||||
* @param \Closure $closure
|
||||
* @return mixed
|
||||
*/
|
||||
function measure($label, \Closure $closure)
|
||||
{
|
||||
return debugbar()->measure($label, $closure);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user