dependencies-upgrade

This commit is contained in:
RafficMohammed
2023-01-08 02:20:59 +05:30
parent 7870479b18
commit 49021a4497
1711 changed files with 74994 additions and 70803 deletions

View File

@@ -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..');
}
}
}

View File

@@ -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;
}
}

View File

@@ -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();
}
}
}
}

View File

@@ -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'));
}
}

View File

@@ -0,0 +1,49 @@
<?php
namespace Barryvdh\Debugbar\Controllers;
use Barryvdh\Debugbar\Support\Clockwork\Converter;
use DebugBar\OpenHandler;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
class OpenHandlerController extends BaseController
{
public function handle(Request $request)
{
$openHandler = new OpenHandler($this->debugbar);
$data = $openHandler->handle($request->input(), false, false);
return new Response(
$data,
200,
[
'Content-Type' => 'application/json'
]
);
}
/**
* Return Clockwork output
*
* @param $id
* @return mixed
* @throws \DebugBar\DebugBarException
*/
public function clockwork($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);
}
}

View File

@@ -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.path') . '/requests/' . $result->id);
}
}

View File

@@ -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',
],
];
}
}

View File

@@ -0,0 +1,116 @@
<?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;
public function __construct($requestStartTime = null)
{
parent::__construct($requestStartTime);
$this->previousTime = microtime(true);
$this->setDataFormatter(new SimpleFormatter());
}
public function onWildcardEvent($name = null, $data = [])
{
$params = $this->prepareParams($data);
$currentTime = microtime(true);
// 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,
],
];
}
}

View File

@@ -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 anyways.
'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';
}
}

View File

@@ -0,0 +1,54 @@
<?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);
});
}
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->id;
}
$label = $result ? 'success' : 'error';
// Response::allowed() was added in Laravel 6.x
if ($result instanceof Response && method_exists($result, 'allowed')) {
$label = $result->allowed() ? 'success' : 'error';
}
$this->addMessage([
'ability' => $ability,
'result' => $result,
$userKey => $userId,
'arguments' => $this->getDataFormatter()->formatVar($arguments),
], $label, false);
}
}

View File

@@ -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" => "",
],
];
}
}

View File

@@ -0,0 +1,82 @@
<?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;
/**
* 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 an unique name for each compoent
$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);
});
}
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
]
];
}
}

View File

@@ -0,0 +1,143 @@
<?php
namespace Barryvdh\Debugbar\DataCollector;
use DebugBar\DataCollector\MessagesCollector;
use Psr\Log\LogLevel;
use ReflectionClass;
class LogsCollector extends MessagesCollector
{
protected $lines = 124;
public function __construct($path = null, $name = 'logs')
{
parent::__construct($name);
$path = $path ?: $this->getLogsFile();
$this->getStorageLogs($path);
}
/**
* Get the path to the logs file
*
* @return string
*/
public function getLogsFile()
{
// default daily rotating logs (Laravel 5.0)
$path = storage_path() . '/logs/laravel-' . date('Y-m-d') . '.log';
// single file logs
if (!file_exists($path)) {
$path = storage_path() . '/logs/laravel.log';
}
return $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));
foreach ($this->getLogs($file) as $log) {
$this->addMessage($log['header'] . $log['stack'], $log['level'], 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]];
}
}
}
}
$log = array_reverse($log);
return $log;
}
/**
* 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();
}
}

View File

@@ -0,0 +1,65 @@
<?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.
*/
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
]
];
}
}

View File

@@ -0,0 +1,168 @@
<?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;
/**
* @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;
}
/**
* @{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, ', ');
return $data;
}
private function hasUser(Guard $guard)
{
if (method_exists($guard, 'hasUser')) {
return $guard->hasUser();
}
// For Laravel 5.5
if (method_exists($guard, 'alreadyAuthenticated')) {
return $guard->alreadyAuthenticated();
}
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 and email.
$identifier = $user instanceof Authenticatable ? $user->getAuthIdentifier() : $user->id;
if (is_numeric($identifier)) {
try {
if (isset($user->username)) {
$identifier = $user->username;
} elseif (isset($user->email)) {
$identifier = $user->email;
}
} catch (\Throwable $e) {
}
}
return [
'name' => $identifier,
'user' => $user instanceof Arrayable ? $user->toArray() : $user,
];
}
/**
* @{inheritDoc}
*/
public function getName()
{
return 'auth';
}
/**
* @{inheritDoc}
*/
public function getWidgets()
{
$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;
}
}

View File

@@ -0,0 +1,18 @@
<?php
namespace Barryvdh\Debugbar\DataCollector;
use DebugBar\DataCollector\PhpInfoCollector as DebugBarPhpInfoCollector;
class PhpInfoCollector extends DebugBarPhpInfoCollector
{
/**
* @inheritDoc
*/
public function getWidgets()
{
return tap(parent::getWidgets(), function (&$widgets) {
data_set($widgets, 'php_version.tooltip', 'PHP Version');
});
}
}

View File

@@ -0,0 +1,589 @@
<?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 $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/october/rain',
'/vendor/barryvdh/laravel-debugbar',
];
/**
* @param TimeDataCollector $timeCollector
*/
public function __construct(TimeDataCollector $timeCollector = null)
{
$this->timeCollector = $timeCollector;
}
/**
* 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 $value
* @param array $middleware
*/
public function setFindSource($value, array $middleware)
{
$this->findSource = (bool) $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)
{
$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;
// }
}
/**
*
* @param string $query
* @param array $bindings
* @param float $time
* @param \Illuminate\Database\Connection $connection
*/
public function addQuery($query, $bindings, $time, $connection)
{
$explainResults = [];
$time = $time / 1000;
$endTime = microtime(true);
$startTime = $endTime - $time;
$hints = $this->performQueryAnalysis($query);
$pdo = null;
try {
$pdo = $connection->getPdo();
} catch (\Exception $e) {
// ignore error for non-pdo laravel drivers
}
$bindings = $connection->prepareBindings($bindings);
// Run EXPLAIN on this query (if needed)
if ($this->explainQuery && $pdo && preg_match('/^\s*(' . implode('|', $this->explainTypes) . ') /i', $query)) {
$statement = $pdo->prepare('EXPLAIN ' . $query);
$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);
}
}
$query = preg_replace($regex, addcslashes($binding, '$'), $query, 1);
}
}
$source = [];
if ($this->findSource) {
try {
$source = array_slice($this->findSource(), 0, 5);
} catch (\Exception $e) {
}
}
$this->queries[] = [
'query' => $query,
'type' => 'query',
'bindings' => $this->getDataFormatter()->escapeBindings($bindings),
'time' => $time,
'source' => $source,
'explain' => $explainResults,
'connection' => $connection->getDatabaseName(),
'driver' => $connection->getConfig('driver'),
'hints' => $this->showHints ? $hints : null,
'show_copy' => $this->showCopyButton,
];
if ($this->timeCollector !== null) {
$this->timeCollector->addMeasure(Str::limit($query, 100), $startTime, $endTime);
}
}
/**
* 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="http://stackoverflow.com/questions/2663710/how-does-mysqls-order-by-rand-work" target="_blank">read this</a>
or <a href="http://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>&lt;&gt;</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_filter($sources);
}
/**
* 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,
'line' => isset($trace['line']) ? $trace['line'] : '?',
];
if (isset($trace['function']) && $trace['function'] == 'substituteBindings') {
$frame->name = 'Route binding';
return $frame;
}
if (
isset($trace['class']) &&
isset($trace['file']) &&
!$this->fileIsInExcludedPath($trace['file'])
) {
$file = $trace['file'];
if (isset($trace['object']) && is_a($trace['object'], 'Twig_Template')) {
list($file, $frame->line) = $this->getTwigInfo($trace);
} elseif (strpos($file, storage_path()) !== false) {
$hash = pathinfo($file, PATHINFO_FILENAME);
if (! $frame->name = $this->findViewFromHash($hash)) {
$frame->name = $hash;
}
$frame->namespace = 'view';
return $frame;
} elseif (strpos($file, 'Middleware') !== false) {
$frame->name = $this->findMiddlewareFromFile($file);
if ($frame->name) {
$frame->namespace = 'middleware';
} else {
$frame->name = $this->normalizeFilename($file);
}
return $frame;
}
$frame->name = $this->normalizeFilename($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|string
*/
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;
}
foreach ($property->getValue($finder) as $name => $path) {
if (sha1($path) == $hash || md5($path) == $hash) {
return $name;
}
}
}
/**
* 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];
}
/**
* Shorten the path by removing the relative links and base dir
*
* @param string $path
* @return string
*/
protected function normalizeFilename($path)
{
if (file_exists($path)) {
$path = realpath($path);
}
return str_replace(base_path(), '', $path);
}
/**
* 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' => [],
'time' => 0,
'source' => $source,
'explain' => [],
'connection' => $connection->getDatabaseName(),
'driver' => $connection->getConfig('driver'),
'hints' => null,
'show_copy' => false,
];
}
/**
* Reset the queries.
*/
public function reset()
{
$this->queries = [];
}
/**
* {@inheritDoc}
*/
public function collect()
{
$totalTime = 0;
$queries = $this->queries;
$statements = [];
foreach ($queries as $query) {
$totalTime += $query['time'];
$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']),
'duration' => $query['time'],
'duration_str' => ($query['type'] == 'transaction') ? '' : $this->formatDuration($query['time']),
'stmt_id' => $this->getDataFormatter()->formatSource(reset($query['source'])),
'connection' => $query['connection'],
];
// 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',
];
}
} 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;
}
}
}
$nb_statements = array_filter($queries, function ($query) {
return $query['type'] === 'query';
});
$data = [
'nb_statements' => count($nb_statements),
'nb_failed_statements' => 0,
'accumulated_duration' => $totalTime,
'accumulated_duration_str' => $this->formatDuration($totalTime),
'statements' => $statements
];
return $data;
}
/**
* {@inheritDoc}
*/
public function getName()
{
return 'queries';
}
/**
* {@inheritDoc}
*/
public function getWidgets()
{
return [
"queries" => [
"icon" => "database",
"widget" => "PhpDebugBar.Widgets.LaravelSQLQueriesWidget",
"map" => "queries",
"default" => "[]"
],
"queries:badge" => [
"map" => "queries.nb_statements",
"default" => 0
]
];
}
}

View File

@@ -0,0 +1,199 @@
<?php
namespace Barryvdh\Debugbar\DataCollector;
use DebugBar\DataCollector\DataCollector;
use DebugBar\DataCollector\DataCollectorInterface;
use DebugBar\DataCollector\Renderable;
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;
/**
* Create a new SymfonyRequestCollector
*
* @param \Symfony\Component\HttpFoundation\Request $request
* @param \Symfony\Component\HttpFoundation\Response $response
* @param \Symfony\Component\HttpFoundation\Session\SessionInterface $session
*/
public function __construct($request, $response, $session = null, $currentRequestId = null)
{
$this->request = $request;
$this->response = $response;
$this->session = $session;
$this->currentRequestId = $currentRequestId;
}
/**
* {@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_server' => $request->server->all(),
'request_cookies' => $request->cookies->all(),
'response_headers' => $responseHeaders,
];
if ($this->session) {
$sessionAttributes = [];
foreach ($this->session->all() as $key => $value) {
$sessionAttributes[$key] = $value;
}
$data['session_attributes'] = $sessionAttributes;
}
foreach ($data['request_server'] as $key => $value) {
if (
Str::is('*_KEY', $key) || Str::is('*_PASSWORD', $key)
|| Str::is('*_SECRET', $key) || Str::is('*_PW', $key)
|| Str::is('*_TOKEN', $key) || Str::is('*_PASS', $key)
) {
$data['request_server'][$key] = '******';
}
}
if (isset($data['request_headers']['php-auth-pw'])) {
$data['request_headers']['php-auth-pw'] = '******';
}
if (isset($data['request_server']['PHP_AUTH_PW'])) {
$data['request_server']['PHP_AUTH_PW'] = '******';
}
;
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;
}
}

View File

@@ -0,0 +1,220 @@
<?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;
use InvalidArgumentException;
/**
* 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;
/**
* A list of known editor strings.
*
* @var array
*/
protected $editors = [
'sublime' => 'subl://open?url=file://%file&line=%line',
'textmate' => 'txmt://open?url=file://%file&line=%line',
'emacs' => 'emacs://open?url=file://%file&line=%line',
'macvim' => 'mvim://open/?url=file://%file&line=%line',
'phpstorm' => 'phpstorm://open?file=%file&line=%line',
'idea' => 'idea://open?file=%file&line=%line',
'vscode' => 'vscode://file/%file:%line',
'vscode-insiders' => 'vscode-insiders://file/%file:%line',
'vscode-remote' => 'vscode://vscode-remote/%file:%line',
'vscode-insiders-remote' => 'vscode-insiders://vscode-remote/%file:%line',
'vscodium' => 'vscodium://file/%file:%line',
'nova' => 'nova://core/open/file?filename=%file&line=%line',
'xdebug' => 'xdebug://%file@%line',
'atom' => 'atom://core/open/file?filename=%file&line=%line',
'espresso' => 'x-espresso://open?filepath=%file&lines=%line',
'netbeans' => 'netbeans://open/?f=%file:%line',
];
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);
if (
isset($action['controller'])
&& is_string($action['controller'])
&& strpos($action['controller'], '@') !== false
) {
list($controller, $method) = explode('@', $action['controller']);
if (class_exists($controller) && method_exists($controller, $method)) {
$reflector = new \ReflectionMethod($controller, $method);
}
unset($result['uses']);
} elseif (isset($action['uses']) && $action['uses'] instanceof \Closure) {
$reflector = new \ReflectionFunction($action['uses']);
$result['uses'] = $this->formatVar($result['uses']);
}
if (isset($reflector)) {
$filename = ltrim(str_replace(base_path(), '', $reflector->getFileName()), '/');
if ($href = $this->getEditorHref($reflector->getFileName(), $reflector->getStartLine())) {
$result['file'] = sprintf('<a href="%s">%s:%s-%s</a>', $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->middleware()));
}
/**
* {@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());
}
/**
* Get the editor href for a given file and line, if available.
*
* @param string $filePath
* @param int $line
*
* @throws InvalidArgumentException If editor resolver does not return a string
*
* @return null|string
*/
protected function getEditorHref($filePath, $line)
{
if (empty(config('debugbar.editor'))) {
return null;
}
if (empty($this->editors[config('debugbar.editor')])) {
throw new InvalidArgumentException(
'Unknown editor identifier: ' . config('debugbar.editor') . '. Known editors:' .
implode(', ', array_keys($this->editors))
);
}
$filePath = $this->replaceSitesPath($filePath);
$url = str_replace(['%file', '%line'], [$filePath, $line], $this->editors[config('debugbar.editor')]);
return $url;
}
/**
* Replace remote path
*
* @param string $filePath
*
* @return string
*/
protected function replaceSitesPath($filePath)
{
return str_replace(config('debugbar.remote_sites_path'), config('debugbar.local_sites_path'), $filePath);
}
}

View File

@@ -0,0 +1,58 @@
<?php
namespace Barryvdh\Debugbar\DataCollector;
use DebugBar\DataCollector\DataCollector;
use DebugBar\DataCollector\DataCollectorInterface;
use DebugBar\DataCollector\Renderable;
class SessionCollector extends DataCollector implements DataCollectorInterface, Renderable
{
/** @var \Symfony\Component\HttpFoundation\Session\SessionInterface|\Illuminate\Contracts\Session\Session $session */
protected $session;
/**
* Create a new SessionCollector
*
* @param \Symfony\Component\HttpFoundation\Session\SessionInterface|\Illuminate\Contracts\Session\Session $session
*/
public function __construct($session)
{
$this->session = $session;
}
/**
* {@inheritdoc}
*/
public function collect()
{
$data = [];
foreach ($this->session->all() 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" => "{}"
]
];
}
}

View File

@@ -0,0 +1,107 @@
<?php
namespace Barryvdh\Debugbar\DataCollector;
use Barryvdh\Debugbar\DataFormatter\SimpleFormatter;
use DebugBar\Bridge\Twig\TwigCollector;
use Illuminate\View\View;
use Symfony\Component\VarDumper\Cloner\VarCloner;
class ViewCollector extends TwigCollector
{
protected $templates = [];
protected $collect_data;
/**
* Create a ViewCollector
*
* @param bool $collectData Collects view data when tru
*/
public function __construct($collectData = true)
{
$this->setDataFormatter(new SimpleFormatter());
$this->collect_data = $collectData;
$this->name = 'views';
$this->templates = [];
}
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
]
];
}
/**
* Add a View instance to the Collector
*
* @param \Illuminate\View\View $view
*/
public function addView(View $view)
{
$name = $view->getName();
$path = $view->getPath();
if (!is_object($path)) {
if ($path) {
$path = ltrim(str_replace(base_path(), '', realpath($path)), '/');
}
if (substr($path, -10) == '.blade.php') {
$type = 'blade';
} else {
$type = pathinfo($path, PATHINFO_EXTENSION);
}
} else {
$type = get_class($view);
$path = '';
}
if (!$this->collect_data) {
$params = array_keys($view->getData());
} else {
$data = [];
foreach ($view->getData() as $key => $value) {
$data[$key] = $this->getDataFormatter()->formatVar($value);
}
$params = $data;
}
$template = [
'name' => $path ? sprintf('%s (%s)', $name, $path) : $name,
'param_count' => count($params),
'params' => $params,
'type' => $type,
];
if ($this->getXdebugLink($path)) {
$template['xdebug_link'] = $this->getXdebugLink(realpath($view->getPath()));
}
$this->templates[] = $template;
}
public function collect()
{
$templates = $this->templates;
return [
'nb_templates' => count($templates),
'templates' => $templates,
];
}
}

View File

@@ -0,0 +1,87 @@
<?php
namespace Barryvdh\Debugbar\DataFormatter;
use DebugBar\DataFormatter\DataFormatter;
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)
{
if (! is_object($source)) {
return '';
}
$parts = [];
if ($source->namespace) {
$parts['namespace'] = $source->namespace . '::';
}
$parts['name'] = $source->name;
$parts['line'] = ':' . $source->line;
return implode($parts);
}
}

View File

@@ -0,0 +1,106 @@
<?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
*/
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 = array();
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'];
}
}

View File

@@ -0,0 +1,55 @@
<?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;
/**
* @param Engine $engine
* @param LaravelDebugbar $laravelDebugbar
*/
public function __construct(Engine $engine, LaravelDebugbar $laravelDebugbar)
{
$this->engine = $engine;
$this->laravelDebugbar = $laravelDebugbar;
}
/**
* @param string $path
* @param array $data
* @return string
*/
public function get($path, array $data = [])
{
$shortPath = ltrim(str_replace(base_path(), '', realpath($path)), '/');
return $this->laravelDebugbar->measure($shortPath, function () use ($path, $data) {
return $this->engine->get($path, $data);
});
}
/**
* 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);
}
}

View File

@@ -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
{
}

View File

@@ -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;
}
}

View File

@@ -0,0 +1,155 @@
<?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->cssVendors['fontawesome'] = __DIR__ . '/Resources/vendor/font-awesome/style.css';
$this->jsFiles['laravel-sql'] = __DIR__ . '/Resources/sqlqueries/widget.js';
$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 = route('debugbar.assets.css', [
'v' => $this->getModifiedTime('css'),
'theme' => config('debugbar.theme', 'auto'),
]);
$jsRoute = route('debugbar.assets.js', [
'v' => $this->getModifiedTime('js')
]);
$cssRoute = preg_replace('/\Ahttps?:/', '', $cssRoute);
$jsRoute = preg_replace('/\Ahttps?:/', '', $jsRoute);
$html = "<link rel='stylesheet' type='text/css' property='stylesheet' href='{$cssRoute}' data-turbolinks-eval='false' data-turbo-eval='false'>";
$html .= "<script src='{$jsRoute}' data-turbolinks-eval='false' data-turbo-eval='false'></script>";
if ($this->isJqueryNoConflictEnabled()) {
$html .= '<script data-turbo-eval="false">jQuery.noConflict(true);</script>' . "\n";
}
$html .= $this->getInlineHtml();
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

View File

@@ -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'];
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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.$);

View File

@@ -0,0 +1 @@
@media (prefers-color-scheme: dark) {

View File

@@ -0,0 +1,290 @@
/* 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: #2D3748;
--color-gray-900: #1A202C;
--color-red-vivid: #FF0040;
}
div.phpdebugbar,
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 code.phpdebugbar-widgets-sql span.hljs-keyword,
div.phpdebugbar-openhandler .phpdebugbar-openhandler-header,
div.phpdebugbar-openhandler .phpdebugbar-openhandler-header a {
color: var(--color-gray-200);
}
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 {
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 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-exceptions li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-filename,
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);
}
div.phpdebugbar div.phpdebugbar-widgets-sqlqueries li.phpdebugbar-widgets-list-item.phpdebugbar-widgets-sql-duplicate {
background-color: #6f6200;
}
div.phpdebugbar-widgets-messages li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-value:before {
color: #7B7B7B;
}
div.phpdebugbar-openhandler {
border-top-color: #fa5661;
}
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: #FFF;
}
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 a.phpdebugbar-minimize-btn {
background: url(data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%201792%201792%22%20id%3D%22chevron-down%22%3E%3Cpath%20d%3D%22M1683%20808l-742%20741q-19%2019-45%2019t-45-19l-742-741q-19-19-19-45.5t19-45.5l166-165q19-19%2045-19t45%2019l531%20531%20531-531q19-19%2045-19t45%2019l166%20165q19%2019%2019%2045.5t-19%2045.5z%22%20style%3D%22fill%3A%20%23EDF2F7%22%2F%3E%3C%2Fsvg%3E) no-repeat 6px 6px / 14px 14px;
}
div.phpdebugbar a.phpdebugbar-maximize-btn {
background: url(data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%201792%201792%22%20id%3D%22chevron-up%22%3E%3Cpath%20d%3D%22M1683%201331l-166%20165q-19%2019-45%2019t-45-19l-531-531-531%20531q-19%2019-45%2019t-45-19l-166-165q-19-19-19-45.5t19-45.5l742-741q19-19%2045-19t45%2019l742%20741q19%2019%2019%2045.5t-19%2045.5z%22%20style%3D%22fill%3A%20%23EDF2F7%22%2F%3E%3C%2Fsvg%3E) no-repeat 6px 6px / 14px 14px;
}
div.phpdebugbar a.phpdebugbar-open-btn {
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAOCAYAAADJ7fe0AAABL0lEQVQ4T63RvWqEQBAA4LkjdX46WQh5hoDpFnyAgGzKWKQJdgFfIT8vIKSwCSEQHyJN4AptomAlZMXAVRuxWAwibqMGBUVygdtAplmWmf1mmVnAP8RiNDjne0KINQDsz9wCIXSwrc+AMMa6tm0hz3PozzGWyyUoirJhIISm5n1yuIRh2G3rNs+rqvo7IoTIMMbnkthqXjf9JAiCO0LIR9d1T5JQXzbMbEA8z/vEGB9TSt/KsjyURZIkeTQM43JAHMe5JYS8Zlm2appG1gDXdbFt2/44IIVS+lCW5amswBh70XX9DADEuOIjzvlaCCFrgO/7F5ZlPU8rTtP0viiKK1mhqqpU07STfrATEsfxV13Xu7JIFEU3pmlej/XjTDAA7MgiAPAOANlP5A/vN0u/AXUIgA+u4l6FAAAAAElFTkSuQmCC) no-repeat 8px 6px;
}
div.phpdebugbar a.phpdebugbar-close-btn {
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAABUElEQVQ4T52SMUsDMRTH3xUPChHCxeko3YrUqeFGEexym3boJ9DBufhJpLODfoIbTrcuFcSxxMki3Uq5yZRAAweRVp70HdfWQZolb3i/l/x/iQd7Lm9PDjbA2Wz24HmerFarbSGEwaFaa57n+XC1WqlarXZNBxUgQsaYK+ccCCHeGWPn2GStfdFat3zfB875I8EFOBqNPpbLZRObsQnh9YktHIarUqmMoyg6wboApZTtfr9/zxhrEIw7QdbaSa/Xu1FKDTdAADiQUp6VYcpTgl4B4HsbhCRJjsIwfPN9/7hs2zn3mWXZabfb/dqRg/ZIBF2PmigzCiPbRcbpdKrQXjkTguXMKKxer8uNqw4Gg6cgCC7WT/ArAuty5vl8/hzH8eV2xmaapnec88baHooAEmaMmXQ6nVsAGO/IAQB8x0MAUGQPbSMPAAuC/gL//XV/ALsvnQ+MsaHgAAAAAElFTkSuQmCC) no-repeat 9px 6px;
}
/* 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 {
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-literal,
div.phpdebugbar .hljs-number {
color: #bd93f9;
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,274 @@
(function ($) {
var csscls = PhpDebugBar.utils.makecsscls('phpdebugbar-widgets-');
/**
* Widget for the displaying sql queries
*
* Options:
* - data
*/
var LaravelSQLQueriesWidget = PhpDebugBar.Widgets.LaravelSQLQueriesWidget = PhpDebugBar.Widget.extend({
className: csscls('sqlqueries'),
onFilterClick: function (el) {
$(el).toggleClass(csscls('excluded'));
var excludedLabels = [];
this.$toolbar.find(csscls('.filter') + csscls('.excluded')).each(function () {
excludedLabels.push(this.rel);
});
this.$list.$el.find("li[connection=" + $(el).attr("rel") + "]").toggle();
this.set('exclude', excludedLabels);
},
onCopyToClipboard: function (el) {
var code = $(el).parent('li').find('code').get(0);
var copy = function () {
try {
document.execCommand('copy');
alert('Query copied to the clipboard');
} catch (err) {
console.log('Oops, unable to copy');
}
};
var select = function (node) {
if (document.selection) {
var range = document.body.createTextRange();
range.moveToElementText(node);
range.select();
} else if (window.getSelection) {
var range = document.createRange();
range.selectNodeContents(node);
window.getSelection().removeAllRanges();
window.getSelection().addRange(range);
}
copy();
window.getSelection().removeAllRanges();
};
select(code);
},
render: function () {
this.$status = $('<div />').addClass(csscls('status')).appendTo(this.$el);
this.$toolbar = $('<div></div>').addClass(csscls('toolbar')).appendTo(this.$el);
var filters = [], self = this;
this.$list = new PhpDebugBar.Widgets.ListWidget({ itemRenderer: function (li, stmt) {
if (stmt.type === 'transaction') {
$('<strong />').addClass(csscls('sql')).addClass(csscls('name')).text(stmt.sql).appendTo(li);
} else {
$('<code />').addClass(csscls('sql')).html(PhpDebugBar.Widgets.highlight(stmt.sql, 'sql')).appendTo(li);
}
if (stmt.width_percent) {
$('<div></div>').addClass(csscls('bg-measure')).append(
$('<div></div>').addClass(csscls('value')).css({
left: stmt.start_percent + '%',
width: Math.max(stmt.width_percent, 0.01) + '%',
})
).appendTo(li);
}
if (stmt.duration_str) {
$('<span title="Duration" />').addClass(csscls('duration')).text(stmt.duration_str).appendTo(li);
}
if (stmt.memory_str) {
$('<span title="Memory usage" />').addClass(csscls('memory')).text(stmt.memory_str).appendTo(li);
}
if (typeof(stmt.row_count) != 'undefined') {
$('<span title="Row count" />').addClass(csscls('row-count')).text(stmt.row_count).appendTo(li);
}
if (typeof(stmt.stmt_id) != 'undefined' && stmt.stmt_id) {
$('<span title="Prepared statement ID" />').addClass(csscls('stmt-id')).text(stmt.stmt_id).appendTo(li);
}
if (stmt.connection) {
$('<span title="Connection" />').addClass(csscls('database')).text(stmt.connection).appendTo(li);
li.attr("connection",stmt.connection);
if ( $.inArray(stmt.connection, filters) == -1 ) {
filters.push(stmt.connection);
$('<a />')
.addClass(csscls('filter'))
.text(stmt.connection)
.attr('rel', stmt.connection)
.on('click', function () {
self.onFilterClick(this); })
.appendTo(self.$toolbar);
if (filters.length > 1) {
self.$toolbar.show();
self.$list.$el.css("margin-bottom","20px");
}
}
}
if (typeof(stmt.is_success) != 'undefined' && !stmt.is_success) {
li.addClass(csscls('error'));
li.append($('<span />').addClass(csscls('error')).text("[" + stmt.error_code + "] " + stmt.error_message));
}
if (stmt.show_copy) {
$('<span title="Copy to clipboard" />')
.addClass(csscls('copy-clipboard'))
.css('cursor', 'pointer')
.on('click', function (event) {
self.onCopyToClipboard(this);
event.stopPropagation();
})
.appendTo(li);
}
var table = $('<table><tr><th colspan="2">Metadata</th></tr></table>').addClass(csscls('params')).appendTo(li);
if (stmt.bindings && stmt.bindings.length) {
table.append(function () {
var icon = 'thumb-tack';
var $icon = '<i class="phpdebugbar-fa phpdebugbar-fa-' + icon + ' phpdebugbar-text-muted"></i>';
var $name = $('<td />').addClass(csscls('name')).html('Bindings ' + $icon);
var $value = $('<td />').addClass(csscls('value'));
var $span = $('<span />').addClass('phpdebugbar-text-muted');
var index = 0;
var $bindings = new PhpDebugBar.Widgets.ListWidget({ itemRenderer: function (li, binding) {
var $index = $span.clone().text(index++ + '.');
li.append($index, '&nbsp;', binding).removeClass(csscls('list-item')).addClass(csscls('table-list-item'));
}});
$bindings.set('data', stmt.bindings);
$bindings.$el
.removeClass(csscls('list'))
.addClass(csscls('table-list'))
.appendTo($value);
return $('<tr />').append($name, $value);
});
}
if (stmt.hints && stmt.hints.length) {
table.append(function () {
var icon = 'question-circle';
var $icon = '<i class="phpdebugbar-fa phpdebugbar-fa-' + icon + ' phpdebugbar-text-muted"></i>';
var $name = $('<td />').addClass(csscls('name')).html('Hints ' + $icon);
var $value = $('<td />').addClass(csscls('value'));
var $hints = new PhpDebugBar.Widgets.ListWidget({ itemRenderer: function (li, hint) {
li.append(hint).removeClass(csscls('list-item')).addClass(csscls('table-list-item'));
}});
$hints.set('data', stmt.hints);
$hints.$el
.removeClass(csscls('list'))
.addClass(csscls('table-list'))
.appendTo($value);
return $('<tr />').append($name, $value);
});
}
if (stmt.backtrace && stmt.backtrace.length) {
table.append(function () {
var icon = 'list-ul';
var $icon = '<i class="phpdebugbar-fa phpdebugbar-fa-' + icon + ' phpdebugbar-text-muted"></i>';
var $name = $('<td />').addClass(csscls('name')).html('Backtrace ' + $icon);
var $value = $('<td />').addClass(csscls('value'));
var $span = $('<span />').addClass('phpdebugbar-text-muted');
var $backtrace = new PhpDebugBar.Widgets.ListWidget({ itemRenderer: function (li, source) {
var $parts = [
$span.clone().text(source.index + '.'),
'&nbsp;',
];
if (source.namespace) {
$parts.push(source.namespace + '::');
}
$parts.push(source.name);
$parts.push($span.clone().text(':' + source.line));
li.append($parts).removeClass(csscls('list-item')).addClass(csscls('table-list-item'));
}});
$backtrace.set('data', stmt.backtrace);
$backtrace.$el
.removeClass(csscls('list'))
.addClass(csscls('table-list'))
.appendTo($value);
return $('<tr />').append($name, $value);
});
}
if (stmt.params && !$.isEmptyObject(stmt.params)) {
for (var key in stmt.params) {
if (typeof stmt.params[key] !== 'function') {
table.append('<tr><td class="' + csscls('name') + '">' + key + '</td><td class="' + csscls('value') +
'">' + stmt.params[key] + '</td></tr>');
}
}
}
li.css('cursor', 'pointer').click(function () {
if (table.is(':visible')) {
table.hide();
} else {
table.show();
}
});
}});
this.$list.$el.appendTo(this.$el);
this.bindAttr('data', function (data) {
this.$list.set('data', data.statements);
this.$status.empty();
var stmt;
// Search for duplicate statements.
for (var sql = {}, duplicate = 0, i = 0; i < data.statements.length; i++) {
if (data.statements[i].type === 'query') {
stmt = data.statements[i].sql;
if (data.statements[i].bindings && data.statements[i].bindings.length) {
stmt += JSON.stringify(data.statements[i].bindings);
}
if (data.statements[i].connection) {
stmt += '@' + data.statements[i].connection;
}
sql[stmt] = sql[stmt] || { keys: [] };
sql[stmt].keys.push(i);
}
}
// Add classes to all duplicate SQL statements.
for (stmt in sql) {
if (sql[stmt].keys.length > 1) {
duplicate += sql[stmt].keys.length;
for (i = 0; i < sql[stmt].keys.length; i++) {
this.$list.$el.find('.' + csscls('list-item')).eq(sql[stmt].keys[i])
.addClass(csscls('sql-duplicate'))
.addClass(csscls('sql-duplicate-' + duplicate));
}
}
}
var t = $('<span />').text(data.nb_statements + " statements were executed").appendTo(this.$status);
if (data.nb_failed_statements) {
t.append(", " + data.nb_failed_statements + " of which failed");
}
if (duplicate) {
t.append(", " + duplicate + " of which were duplicated");
t.append(", " + (data.nb_statements - duplicate) + " unique");
}
if (data.accumulated_duration_str) {
this.$status.append($('<span title="Accumulated duration" />').addClass(csscls('duration')).text(data.accumulated_duration_str));
}
if (data.memory_usage_str) {
this.$status.append($('<span title="Memory usage" />').addClass(csscls('memory')).text(data.memory_usage_str));
}
});
}
});
})(PhpDebugBar.$);

View File

@@ -0,0 +1,5 @@
# Font Squirrel Font-face Generator Configuration File
# Upload this file to the generator to recreate the settings
# you used to create these fonts.
{"mode":"expert","formats":["woff"],"tt_instructor":"keep","fallback":"none","fallback_custom":"100","options_subset":"none","subset_custom":"","subset_custom_range":"","subset_ot_features":"all","subset_ot_features_list":"","base64":"Y","css_stylesheet":"style.css","filename_suffix":"","emsquare":"2048","spacing_adjustment":"0","rememberme":"Y"}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,156 @@
<?php
namespace Barryvdh\Debugbar;
use Barryvdh\Debugbar\Middleware\DebugbarEnabled;
use Barryvdh\Debugbar\Middleware\InjectDebugbar;
use DebugBar\DataFormatter\DataFormatter;
use DebugBar\DataFormatter\DataFormatterInterface;
use Illuminate\Contracts\Http\Kernel;
use Illuminate\Foundation\Application;
use Illuminate\Routing\Router;
use Illuminate\Session\SessionManager;
use Illuminate\Support\Collection;
use Illuminate\View\Engines\EngineResolver;
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.engine.resolver',
function (EngineResolver $resolver, Application $application): EngineResolver {
$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 $resolver;
}
return new class ($resolver, $laravelDebugbar) extends EngineResolver {
private $laravelDebugbar;
public function __construct(EngineResolver $resolver, LaravelDebugbar $laravelDebugbar)
{
foreach ($resolver->resolvers as $engine => $resolver) {
$this->register($engine, $resolver);
}
$this->laravelDebugbar = $laravelDebugbar;
}
public function register($engine, \Closure $resolver)
{
parent::register($engine, function () use ($resolver) {
return new DebugbarViewEngine($resolver(), $this->laravelDebugbar);
});
}
};
}
);
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);
if ($this->app->runningInConsole()) {
$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);
}
}

View File

@@ -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 then 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());
}
}
}

View File

@@ -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 = array(), $max = 20, $offset = 0)
{
//
}
/**
* @inheritDoc
*/
function clear()
{
//
}
}

View File

@@ -0,0 +1,90 @@
<?php
namespace Barryvdh\Debugbar\Support\Clockwork;
use DebugBar\DataCollector\DataCollector;
use DebugBar\DataCollector\DataCollectorInterface;
use DebugBar\DataCollector\Renderable;
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;
/**
* Create a new SymfonyRequestCollector
*
* @param \Symfony\Component\HttpFoundation\Request $request
* @param \Symfony\Component\HttpFoundation\Request $response
* @param \Symfony\Component\HttpFoundation\Session\SessionInterface $session
*/
public function __construct($request, $response, $session = null)
{
$this->request = $request;
$this->response = $response;
$this->session = $session;
}
/**
* {@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) {
$sessionAttributes = [];
foreach ($this->session->all() as $key => $value) {
$sessionAttributes[$key] = $value;
}
$data['sessionData'] = $sessionAttributes;
}
if (isset($data['postData']['php-auth-pw'])) {
$data['postData']['php-auth-pw'] = '******';
}
if (isset($data['postData']['PHP_AUTH_PW'])) {
$data['postData']['PHP_AUTH_PW'] = '******';
}
return $data;
}
}

View File

@@ -0,0 +1,139 @@
<?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['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,
'connection' => $statement['connection']
];
}
$output['databaseDuration'] = $queries['accumulated_duration'] * 1000;
}
if (isset($data['views'])) {
foreach ($data['views']['templates'] as $view) {
$output['viewsData'][] = [
'description' => 'Rendering a view',
'duration' => 0,
'end' => 0,
'start' => 0,
'data' => [
'name' => $view['name'],
'data' => $view['params'],
],
];
}
}
if (isset($data['swiftmailer_mails'])) {
foreach ($data['swiftmailer_mails']['mails'] as $mail) {
$output['emailsData'][] = [
'data' => [
'to' => $mail['to'],
'subject' => $mail['subject'],
'headers' => isset($mail['headers']) ? explode("\n", $mail['headers']) : null,
],
];
}
}
return $output;
}
}

View File

@@ -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);
}
}

View File

@@ -0,0 +1,92 @@
<?php
namespace Barryvdh\Debugbar\Twig\Extension;
use Illuminate\Foundation\Application;
use Twig_Environment;
use Twig_Extension;
use Twig_SimpleFunction;
/**
* Access Laravels auth class in your Twig templates.
*/
class Debug extends Twig_Extension
{
/**
* @var \Barryvdh\Debugbar\LaravelDebugbar
*/
protected $debugbar;
/**
* Create a new auth extension.
*
* @param \Illuminate\Foundation\Application $app
*/
public function __construct(Application $app)
{
if ($app->bound('debugbar')) {
$this->debugbar = $app['debugbar'];
} else {
$this->debugbar = null;
}
}
/**
* {@inheritDoc}
*/
public function getName()
{
return 'Laravel_Debugbar_Debug';
}
/**
* {@inheritDoc}
*/
public function getFunctions()
{
return [
new Twig_SimpleFunction(
'debug',
[$this, 'debug'],
['needs_context' => true, 'needs_environment' => true]
),
];
}
/**
* Based on Twig_Extension_Debug / twig_var_dump
* (c) 2011 Fabien Potencier
*
* @param Twig_Environment $env
* @param $context
*/
public function debug(Twig_Environment $env, $context)
{
if (!$env->isDebug() || !$this->debugbar) {
return;
}
$count = func_num_args();
if (2 === $count) {
$data = [];
foreach ($context as $key => $value) {
if (is_object($value)) {
if (method_exists($value, 'toArray')) {
$data[$key] = $value->toArray();
} else {
$data[$key] = "Object (" . get_class($value) . ")";
}
} else {
$data[$key] = $value;
}
}
$this->debugbar->addMessage($data);
} else {
for ($i = 2; $i < $count; $i++) {
$this->debugbar->addMessage(func_get_arg($i));
}
}
return;
}
}

View File

@@ -0,0 +1,88 @@
<?php
namespace Barryvdh\Debugbar\Twig\Extension;
use DebugBar\DataFormatter\DataFormatterInterface;
use Twig_Environment;
use Twig_Extension;
use Twig_SimpleFunction;
/**
* Dump variables using the DataFormatter
*/
class Dump extends Twig_Extension
{
/**
* @var \DebugBar\DataFormatter\DataFormatter
*/
protected $formatter;
/**
* Create a new auth extension.
*
* @param \DebugBar\DataFormatter\DataFormatterInterface $formatter
*/
public function __construct(DataFormatterInterface $formatter)
{
$this->formatter = $formatter;
}
/**
* {@inheritDoc}
*/
public function getName()
{
return 'Laravel_Debugbar_Dump';
}
/**
* {@inheritDoc}
*/
public function getFunctions()
{
return [
new Twig_SimpleFunction(
'dump',
[$this, 'dump'],
['is_safe' => ['html'], 'needs_context' => true, 'needs_environment' => true]
),
];
}
/**
* Based on Twig_Extension_Debug / twig_var_dump
* (c) 2011 Fabien Potencier
*
* @param Twig_Environment $env
* @param $context
*
* @return string
*/
public function dump(Twig_Environment $env, $context)
{
$output = '';
$count = func_num_args();
if (2 === $count) {
$data = [];
foreach ($context as $key => $value) {
if (is_object($value)) {
if (method_exists($value, 'toArray')) {
$data[$key] = $value->toArray();
} else {
$data[$key] = "Object (" . get_class($value) . ")";
}
} else {
$data[$key] = $value;
}
}
$output .= $this->formatter->formatVar($data);
} else {
for ($i = 2; $i < $count; $i++) {
$output .= $this->formatter->formatVar(func_get_arg($i));
}
}
return '<pre>' . $output . '</pre>';
}
}

View File

@@ -0,0 +1,58 @@
<?php
namespace Barryvdh\Debugbar\Twig\Extension;
use Barryvdh\Debugbar\Twig\TokenParser\StopwatchTokenParser;
use Illuminate\Foundation\Application;
use Twig_Extension;
/**
* Access Laravels auth class in your Twig templates.
* Based on Symfony\Bridge\Twig\Extension\StopwatchExtension
*/
class Stopwatch extends Twig_Extension
{
/**
* @var \Barryvdh\Debugbar\LaravelDebugbar
*/
protected $debugbar;
/**
* Create a new auth extension.
*
* @param \Illuminate\Foundation\Application $app
*/
public function __construct(Application $app)
{
if ($app->bound('debugbar')) {
$this->debugbar = $app['debugbar'];
} else {
$this->debugbar = null;
}
}
/**
* {@inheritDoc}
*/
public function getName()
{
return 'stopwatch';
}
public function getTokenParsers()
{
return [
/*
* {% stopwatch foo %}
* Some stuff which will be recorded on the timeline
* {% endstopwatch %}
*/
new StopwatchTokenParser($this->debugbar !== null),
];
}
public function getDebugbar()
{
return $this->debugbar;
}
}

View File

@@ -0,0 +1,39 @@
<?php
namespace Barryvdh\Debugbar\Twig\Node;
/**
* Represents a stopwatch node. Based on Symfony\Bridge\Twig\Node\StopwatchNode
*
* @author Wouter J <wouter@wouterj.nl>
*/
class StopwatchNode extends \Twig_Node
{
public function __construct(
\Twig_NodeInterface $name,
$body,
\Twig_Node_Expression_AssignName $var,
$lineno = 0,
$tag = null
) {
parent::__construct(['body' => $body, 'name' => $name, 'var' => $var], [], $lineno, $tag);
}
public function compile(\Twig_Compiler $compiler)
{
$compiler
->addDebugInfo($this)
->write('')
->subcompile($this->getNode('var'))
->raw(' = ')
->subcompile($this->getNode('name'))
->write(";\n")
->write("\$this->env->getExtension('stopwatch')->getDebugbar()->startMeasure(")
->subcompile($this->getNode('var'))
->raw(");\n")
->subcompile($this->getNode('body'))
->write("\$this->env->getExtension('stopwatch')->getDebugbar()->stopMeasure(")
->subcompile($this->getNode('var'))
->raw(");\n");
}
}

View File

@@ -0,0 +1,57 @@
<?php
namespace Barryvdh\Debugbar\Twig\TokenParser;
use Barryvdh\Debugbar\Twig\Node\StopwatchNode;
/**
* Token Parser for the stopwatch tag. Based on Symfony\Bridge\Twig\TokenParser\StopwatchTokenParser;
*
* @author Wouter J <wouter@wouterj.nl>
*/
class StopwatchTokenParser extends \Twig_TokenParser
{
protected $debugbarAvailable;
public function __construct($debugbarAvailable)
{
$this->debugbarAvailable = $debugbarAvailable;
}
public function parse(\Twig_Token $token)
{
$lineno = $token->getLine();
$stream = $this->parser->getStream();
// {% stopwatch 'bar' %}
$name = $this->parser->getExpressionParser()->parseExpression();
$stream->expect(\Twig_Token::BLOCK_END_TYPE);
// {% endstopwatch %}
$body = $this->parser->subparse([$this, 'decideStopwatchEnd'], true);
$stream->expect(\Twig_Token::BLOCK_END_TYPE);
if ($this->debugbarAvailable) {
return new StopwatchNode(
$name,
$body,
new \Twig_Node_Expression_AssignName($this->parser->getVarName(), $token->getLine()),
$lineno,
$this->getTag()
);
}
return $body;
}
public function getTag()
{
return 'stopwatch';
}
public function decideStopwatchEnd(\Twig_Token $token)
{
return $token->test('endstopwatch');
}
}

View File

@@ -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' => [\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',
]);
});

View File

@@ -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);
}
}