1
0
mirror of https://github.com/maximebf/php-debugbar.git synced 2025-07-25 10:41:55 +02:00

Use xdebug links for messages, move to trait (#591)

* Use xdebug links for messages, move to trait

* Tweak view templates
This commit is contained in:
Barry vd. Heuvel
2024-02-10 21:02:28 +01:00
committed by GitHub
parent d6566027f1
commit 80ad07447f
6 changed files with 255 additions and 231 deletions

View File

@@ -11,190 +11,17 @@
namespace DebugBar\DataCollector;
use DebugBar\DataFormatter\HasDataFormatter;
use DebugBar\DataFormatter\HasXdebugLinks;
/**
* Abstract class for data collectors
*/
abstract class DataCollector implements DataCollectorInterface
{
use HasDataFormatter;
use HasDataFormatter, HasXdebugLinks;
public static $defaultDataFormatter;
public static $defaultVarDumper;
protected $xdebugLinkTemplate = '';
protected $xdebugShouldUseAjax = false;
protected $xdebugReplacements = array();
/**
* Shorten the file path by removing the xdebug path replacements
*
* @param string $file
* @return string
*/
public function normalizeFilePath($file)
{
if (empty($file)) {
return '';
}
if (@file_exists($file)) {
$file = realpath($file);
}
foreach (array_keys($this->xdebugReplacements) as $path) {
if (strpos($file, $path) === 0) {
$file = substr($file, strlen($path));
break;
}
}
return ltrim(str_replace('\\', '/', $file), '/');
}
/**
* Get an Xdebug Link to a file
*
* @param string $file
* @param int $line
*
* @return array {
* @var string $url
* @var bool $ajax should be used to open the url instead of a normal links
* }
*/
public function getXdebugLink($file, $line = 1)
{
if (empty($file)) {
return null;
}
if (@file_exists($file)) {
$file = realpath($file);
}
foreach ($this->xdebugReplacements as $path => $replacement) {
if (strpos($file, $path) === 0) {
$file = $replacement . substr($file, strlen($path));
break;
}
}
$url = strtr($this->getXdebugLinkTemplate(), [
'%f' => rawurlencode(str_replace('\\', '/', $file)),
'%l' => rawurlencode((string) $line),
]);
if ($url) {
return ['url' => $url, 'ajax' => $this->getXdebugShouldUseAjax()];
}
}
/**
* @return string
*/
public function getXdebugLinkTemplate()
{
if (empty($this->xdebugLinkTemplate) && !empty(ini_get('xdebug.file_link_format'))) {
$this->xdebugLinkTemplate = ini_get('xdebug.file_link_format');
}
return $this->xdebugLinkTemplate;
}
/**
* @param string $editor
*/
public function setEditorLinkTemplate($editor)
{
$editorLinkTemplates = array(
'sublime' => 'subl://open?url=file://%f&line=%l',
'textmate' => 'txmt://open?url=file://%f&line=%l',
'emacs' => 'emacs://open?url=file://%f&line=%l',
'macvim' => 'mvim://open/?url=file://%f&line=%l',
'phpstorm' => 'phpstorm://open?file=%f&line=%l',
'phpstorm-remote' => 'javascript:(()=>{let r=new XMLHttpRequest;' .
'r.open(\'get\',\'http://localhost:63342/api/file/%f:%l\');r.send();})()',
'idea' => 'idea://open?file=%f&line=%l',
'idea-remote' => 'javascript:(()=>{let r=new XMLHttpRequest;' .
'r.open(\'get\',\'http://localhost:63342/api/file/?file=%f&line=%l\');r.send();})()',
'vscode' => 'vscode://file/%f:%l',
'vscode-insiders' => 'vscode-insiders://file/%f:%l',
'vscode-remote' => 'vscode://vscode-remote/%f:%l',
'vscode-insiders-remote' => 'vscode-insiders://vscode-remote/%f:%l',
'vscodium' => 'vscodium://file/%f:%l',
'nova' => 'nova://core/open/file?filename=%f&line=%l',
'xdebug' => 'xdebug://%f@%l',
'atom' => 'atom://core/open/file?filename=%f&line=%l',
'espresso' => 'x-espresso://open?filepath=%f&lines=%l',
'netbeans' => 'netbeans://open/?f=%f:%l',
);
if (is_string($editor) && isset($editorLinkTemplates[$editor])) {
$this->setXdebugLinkTemplate($editorLinkTemplates[$editor]);
}
}
/**
* @param string $xdebugLinkTemplate
* @param bool $shouldUseAjax
*/
public function setXdebugLinkTemplate($xdebugLinkTemplate, $shouldUseAjax = false)
{
if ($xdebugLinkTemplate === 'idea') {
$this->xdebugLinkTemplate = 'http://localhost:63342/api/file/?file=%f&line=%l';
$this->xdebugShouldUseAjax = true;
} else {
$this->xdebugLinkTemplate = $xdebugLinkTemplate;
$this->xdebugShouldUseAjax = $shouldUseAjax;
}
}
/**
* @return bool
*/
public function getXdebugShouldUseAjax()
{
return $this->xdebugShouldUseAjax;
}
/**
* returns an array of filename-replacements
*
* this is useful f.e. when using vagrant or remote servers,
* where the path of the file is different between server and
* development environment
*
* @return array key-value-pairs of replacements, key = path on server, value = replacement
*/
public function getXdebugReplacements()
{
return $this->xdebugReplacements;
}
/**
* @param array $xdebugReplacements
*/
public function addXdebugReplacements($xdebugReplacements)
{
foreach ($xdebugReplacements as $serverPath => $replacement) {
$this->setXdebugReplacement($serverPath, $replacement);
}
}
/**
* @param array $xdebugReplacements
*/
public function setXdebugReplacements($xdebugReplacements)
{
$this->xdebugReplacements = $xdebugReplacements;
}
/**
* @param string $serverPath
* @param string $replacement
*/
public function setXdebugReplacement($serverPath, $replacement)
{
$this->xdebugReplacements[$serverPath] = $replacement;
}
}

View File

@@ -10,6 +10,7 @@
namespace DebugBar\DataCollector;
use DebugBar\DataFormatter\HasXdebugLinks;
use Psr\Log\AbstractLogger;
use DebugBar\DataFormatter\HasDataFormatter;
@@ -18,7 +19,7 @@ use DebugBar\DataFormatter\HasDataFormatter;
*/
class MessagesCollector extends AbstractLogger implements DataCollectorInterface, MessagesAggregateInterface, Renderable, AssetProvider
{
use HasDataFormatter;
use HasDataFormatter, HasXdebugLinks;
protected $name;
@@ -78,20 +79,14 @@ class MessagesCollector extends AbstractLogger implements DataCollectorInterface
}
}
if (!empty($stackItem)) {
$stackItem = [
'file_name' => $stackItem['file'],
'file_line' => $stackItem['line'],
];
}
$this->messages[] = array_merge(array(
$this->messages[] = array(
'message' => $messageText,
'message_html' => $messageHtml,
'is_string' => $isString,
'label' => $label,
'time' => microtime(true)
), $stackItem);
'time' => microtime(true),
'xdebug_link' => $stackItem ? $this->getXdebugLink($stackItem['file'], $stackItem['line']) : null,
);
}
/**

View File

@@ -0,0 +1,197 @@
<?php
/*
* This file is part of the DebugBar package.
*
* (c) 2013 Maxime Bouroumeau-Fuseau
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace DebugBar\DataFormatter;
use DebugBar\DataCollector\DataCollector;
trait HasXdebugLinks
{
protected $xdebugLinkTemplate = '';
protected $xdebugShouldUseAjax = false;
protected $xdebugReplacements = array();
/**
* Shorten the file path by removing the xdebug path replacements
*
* @param string $file
* @return string
*/
public function normalizeFilePath($file)
{
if (empty($file)) {
return '';
}
if (@file_exists($file)) {
$file = realpath($file);
}
foreach (array_keys($this->xdebugReplacements) as $path) {
if (strpos($file, $path) === 0) {
$file = substr($file, strlen($path));
break;
}
}
return ltrim(str_replace('\\', '/', $file), '/');
}
/**
* Get an Xdebug Link to a file
*
* @param string $file
* @param int $line
*
* @return array {
* @var string $url
* @var bool $ajax should be used to open the url instead of a normal links
* }
*/
public function getXdebugLink($file, $line = null)
{
if (empty($file)) {
return null;
}
if (@file_exists($file)) {
$file = realpath($file);
}
foreach ($this->xdebugReplacements as $path => $replacement) {
if (strpos($file, $path) === 0) {
$file = $replacement . substr($file, strlen($path));
break;
}
}
$url = strtr($this->getXdebugLinkTemplate(), [
'%f' => rawurlencode(str_replace('\\', '/', $file)),
'%l' => rawurlencode((string) $line ?: ''),
]);
if ($url) {
return [
'url' => $url,
'ajax' => $this->getXdebugShouldUseAjax(),
'filename' => basename($file),
'line' => (string) $line
];
}
}
/**
* @return string
*/
public function getXdebugLinkTemplate()
{
if (empty($this->xdebugLinkTemplate) && !empty(ini_get('xdebug.file_link_format'))) {
$this->xdebugLinkTemplate = ini_get('xdebug.file_link_format');
}
return $this->xdebugLinkTemplate;
}
/**
* @param string $editor
*/
public function setEditorLinkTemplate($editor)
{
$editorLinkTemplates = array(
'sublime' => 'subl://open?url=file://%f&line=%l',
'textmate' => 'txmt://open?url=file://%f&line=%l',
'emacs' => 'emacs://open?url=file://%f&line=%l',
'macvim' => 'mvim://open/?url=file://%f&line=%l',
'phpstorm' => 'phpstorm://open?file=%f&line=%l',
'phpstorm-remote' => 'javascript:(()=>{let r=new XMLHttpRequest;' .
'r.open(\'get\',\'http://localhost:63342/api/file/%f:%l\');r.send();})()',
'idea' => 'idea://open?file=%f&line=%l',
'idea-remote' => 'javascript:(()=>{let r=new XMLHttpRequest;' .
'r.open(\'get\',\'http://localhost:63342/api/file/?file=%f&line=%l\');r.send();})()',
'vscode' => 'vscode://file/%f:%l',
'vscode-insiders' => 'vscode-insiders://file/%f:%l',
'vscode-remote' => 'vscode://vscode-remote/%f:%l',
'vscode-insiders-remote' => 'vscode-insiders://vscode-remote/%f:%l',
'vscodium' => 'vscodium://file/%f:%l',
'nova' => 'nova://core/open/file?filename=%f&line=%l',
'xdebug' => 'xdebug://%f@%l',
'atom' => 'atom://core/open/file?filename=%f&line=%l',
'espresso' => 'x-espresso://open?filepath=%f&lines=%l',
'netbeans' => 'netbeans://open/?f=%f:%l',
);
if (is_string($editor) && isset($editorLinkTemplates[$editor])) {
$this->setXdebugLinkTemplate($editorLinkTemplates[$editor]);
}
}
/**
* @param string $xdebugLinkTemplate
* @param bool $shouldUseAjax
*/
public function setXdebugLinkTemplate($xdebugLinkTemplate, $shouldUseAjax = false)
{
if ($xdebugLinkTemplate === 'idea') {
$this->xdebugLinkTemplate = 'http://localhost:63342/api/file/?file=%f&line=%l';
$this->xdebugShouldUseAjax = true;
} else {
$this->xdebugLinkTemplate = $xdebugLinkTemplate;
$this->xdebugShouldUseAjax = $shouldUseAjax;
}
}
/**
* @return bool
*/
public function getXdebugShouldUseAjax()
{
return $this->xdebugShouldUseAjax;
}
/**
* returns an array of filename-replacements
*
* this is useful f.e. when using vagrant or remote servers,
* where the path of the file is different between server and
* development environment
*
* @return array key-value-pairs of replacements, key = path on server, value = replacement
*/
public function getXdebugReplacements()
{
return $this->xdebugReplacements;
}
/**
* @param array $xdebugReplacements
*/
public function addXdebugReplacements($xdebugReplacements)
{
foreach ($xdebugReplacements as $serverPath => $replacement) {
$this->setXdebugReplacement($serverPath, $replacement);
}
}
/**
* @param array $xdebugReplacements
*/
public function setXdebugReplacements($xdebugReplacements)
{
$this->xdebugReplacements = $xdebugReplacements;
}
/**
* @param string $serverPath
* @param string $replacement
*/
public function setXdebugReplacement($serverPath, $replacement)
{
$this->xdebugReplacements[$serverPath] = $replacement;
}
}

View File

@@ -31,6 +31,30 @@ pre.phpdebugbar-widgets-code-block {
text-align: right;
}
li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-filename {
display: block;
font-style: italic;
float: right;
margin-left: 8px;
color: #888;
}
li.phpdebugbar-widgets-list-item a.phpdebugbar-widgets-editor-link:hover {
color: #aaaaaa;
}
a.phpdebugbar-widgets-editor-link:before {
font-family: PhpDebugbarFontAwesome;
margin-right: 4px;
font-size: 12px;
font-style: normal;
}
a.phpdebugbar-widgets-editor-link:before {
content: "\f08e";
margin-left: 4px;
}
/* -------------------------------------- */
ul.phpdebugbar-widgets-list {
@@ -160,17 +184,6 @@ dl.phpdebugbar-widgets-kvlist {
cursor: pointer;
min-height: 17px;
}
.phpdebugbar-widgets-kvlist .phpdebugbar-widgets-editor-link {
margin-left: 8px;
color: #888;
}
.phpdebugbar-widgets-kvlist .phpdebugbar-widgets-editor-link:before {
content: "\f08e";
font-family: PhpDebugbarFontAwesome;
margin-left: 4px;
margin-right: 4px;
font-size: 12px;
}
/* -------------------------------------- */
@@ -251,16 +264,6 @@ div.phpdebugbar-widgets-exceptions li.phpdebugbar-widgets-list-item {
color: red;
}
div.phpdebugbar-widgets-exceptions li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-filename {
display: block;
font-style: italic;
color: #555;
}
div.phpdebugbar-widgets-exceptions li.phpdebugbar-widgets-list-item a.phpdebugbar-widgets-editor-link:hover {
color: #aaaaaa;
}
div.phpdebugbar-widgets-exceptions li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-type {
display: block;
position: absolute;
@@ -277,17 +280,9 @@ div.phpdebugbar-widgets-exceptions li.phpdebugbar-widgets-list-item {
font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
}
div.phpdebugbar-widgets-exceptions a.phpdebugbar-widgets-editor-link:before {
font-family: PhpDebugbarFontAwesome;
margin-right: 4px;
font-size: 12px;
font-style: normal;
}
div.phpdebugbar-widgets-exceptions a.phpdebugbar-widgets-editor-link:before {
content: "\f08e";
margin-left: 4px;
}
div.phpdebugbar-widgets-exceptions li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-filename {
float: none;
}
ul.phpdebugbar-widgets-timeline table.phpdebugbar-widgets-params {
display: table;

View File

@@ -327,10 +327,18 @@ if (typeof(PhpDebugBar) == 'undefined') {
});
}
}
if (value.file_name) {
$('<span />').addClass(csscls('label-called-from')).attr('title', value.file_name)
.text(value.file_name + ':' + value.file_line)
.prependTo(li);
if (value.xdebug_link) {
var header = $('<span />').addClass(csscls('filename')).text(value.xdebug_link.filename + ( value.xdebug_link.line ? "#" + value.xdebug_link.line : ''));
if (value.xdebug_link) {
if (value.xdebug_link.ajax) {
$('<a title="' + value.xdebug_link.url + '"></a>').on('click', function () {
$.ajax(value.xdebug_link.url);
}).addClass(csscls('editor-link')).appendTo(header);
} else {
$('<a href="' + value.xdebug_link.url + '"></a>').addClass(csscls('editor-link')).appendTo(header);
}
}
header.appendTo(li);
}
if (value.collector) {
$('<span />').addClass(csscls('collector')).text(value.collector).prependTo(li);

View File

@@ -19,17 +19,19 @@
$('<span />').addClass(csscls('name')).text(tpl.name).appendTo(li);
if (typeof tpl.xdebug_link !== 'undefined' && tpl.xdebug_link !== null) {
if (tpl.xdebug_link.ajax) {
$('<a title="' + tpl.xdebug_link.url + '"></a>').on('click', function (event) {
event.stopPropagation();
$.ajax(tpl.xdebug_link.url);
}).addClass(csscls('editor-link')).appendTo(li);
} else {
$('<a href="' + tpl.xdebug_link.url + '"></a>').on('click', function (event) {
event.stopPropagation();
}).addClass(csscls('editor-link')).appendTo(li);
var header = $('<span />').addClass(csscls('filename')).text(tpl.xdebug_link.filename + ( tpl.xdebug_link.line ? "#" + tpl.xdebug_link.line : ''));
if (tpl.xdebug_link) {
if (tpl.xdebug_link.ajax) {
$('<a title="' + tpl.xdebug_link.url + '"></a>').on('click', function () {
$.ajax(tpl.xdebug_link.url);
}).addClass(csscls('editor-link')).appendTo(header);
} else {
$('<a href="' + tpl.xdebug_link.url + '"></a>').addClass(csscls('editor-link')).appendTo(header);
}
}
header.appendTo(li);
}
if (tpl.render_time_str) {
$('<span title="Render time" />').addClass(csscls('render-time')).text(tpl.render_time_str).appendTo(li);
}