Skip to content

Commit 7a7315f

Browse files
authored
View Editor Link (#1359)
1 parent ea7695f commit 7a7315f

File tree

3 files changed

+168
-1
lines changed

3 files changed

+168
-1
lines changed

src/DataCollector/ViewCollector.php

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,38 @@
55
use Barryvdh\Debugbar\DataFormatter\SimpleFormatter;
66
use DebugBar\Bridge\Twig\TwigCollector;
77
use Illuminate\View\View;
8+
use InvalidArgumentException;
89

910
class ViewCollector extends TwigCollector
1011
{
1112
protected $templates = [];
1213
protected $collect_data;
1314
protected $exclude_paths;
1415

16+
/**
17+
* A list of known editor strings.
18+
*
19+
* @var array
20+
*/
21+
protected $editors = [
22+
'sublime' => 'subl://open?url=file://%file&line=%line',
23+
'textmate' => 'txmt://open?url=file://%file&line=%line',
24+
'emacs' => 'emacs://open?url=file://%file&line=%line',
25+
'macvim' => 'mvim://open/?url=file://%file&line=%line',
26+
'phpstorm' => 'phpstorm://open?file=%file&line=%line',
27+
'idea' => 'idea://open?file=%file&line=%line',
28+
'vscode' => 'vscode://file/%file:%line',
29+
'vscode-insiders' => 'vscode-insiders://file/%file:%line',
30+
'vscode-remote' => 'vscode://vscode-remote/%file:%line',
31+
'vscode-insiders-remote' => 'vscode-insiders://vscode-remote/%file:%line',
32+
'vscodium' => 'vscodium://file/%file:%line',
33+
'nova' => 'nova://core/open/file?filename=%file&line=%line',
34+
'xdebug' => 'xdebug://%file@%line',
35+
'atom' => 'atom://core/open/file?filename=%file&line=%line',
36+
'espresso' => 'x-espresso://open?filepath=%file&lines=%line',
37+
'netbeans' => 'netbeans://open/?f=%file:%line',
38+
];
39+
1540
/**
1641
* Create a ViewCollector
1742
*
@@ -36,7 +61,7 @@ public function getWidgets()
3661
return [
3762
'views' => [
3863
'icon' => 'leaf',
39-
'widget' => 'PhpDebugBar.Widgets.TemplatesWidget',
64+
'widget' => 'PhpDebugBar.Widgets.LaravelViewTemplatesWidget',
4065
'map' => 'views',
4166
'default' => '[]'
4267
],
@@ -47,6 +72,36 @@ public function getWidgets()
4772
];
4873
}
4974

75+
/**
76+
* Get the editor href for a given file and line, if available.
77+
*
78+
* @param string $filePath
79+
* @param int $line
80+
*
81+
* @throws InvalidArgumentException If editor resolver does not return a string
82+
*
83+
* @return null|string
84+
*/
85+
protected function getEditorHref($filePath, $line)
86+
{
87+
if (empty(config('debugbar.editor'))) {
88+
return null;
89+
}
90+
91+
if (empty($this->editors[config('debugbar.editor')])) {
92+
throw new InvalidArgumentException(
93+
'Unknown editor identifier: ' . config('debugbar.editor') . '. Known editors:' .
94+
implode(', ', array_keys($this->editors))
95+
);
96+
}
97+
98+
$filePath = $this->replaceSitesPath($filePath);
99+
100+
$url = str_replace(['%file', '%line'], [$filePath, $line], $this->editors[config('debugbar.editor')]);
101+
102+
return $url;
103+
}
104+
50105
/**
51106
* Add a View instance to the Collector
52107
*
@@ -93,6 +148,7 @@ public function addView(View $view)
93148
'param_count' => count($params),
94149
'params' => $params,
95150
'type' => $type,
151+
'editorLink' => $this->getEditorHref($view->getPath(), 0),
96152
];
97153

98154
if ($this->getXdebugLink($path)) {
@@ -111,4 +167,16 @@ public function collect()
111167
'templates' => $templates,
112168
];
113169
}
170+
171+
/**
172+
* Replace remote path
173+
*
174+
* @param string $filePath
175+
*
176+
* @return string
177+
*/
178+
protected function replaceSitesPath($filePath)
179+
{
180+
return str_replace(config('debugbar.remote_sites_path'), config('debugbar.local_sites_path'), $filePath);
181+
}
114182
}

src/JavascriptRenderer.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ public function __construct(DebugBar $debugBar, $baseUrl = null, $basePath = nul
2323
$this->cssVendors['fontawesome'] = __DIR__ . '/Resources/vendor/font-awesome/style.css';
2424
$this->jsFiles['laravel-sql'] = __DIR__ . '/Resources/sqlqueries/widget.js';
2525
$this->jsFiles['laravel-cache'] = __DIR__ . '/Resources/cache/widget.js';
26+
$this->jsFiles['laravel-view'] = __DIR__ . '/Resources/templates/widget.js';
2627

2728
$theme = config('debugbar.theme', 'auto');
2829
switch ($theme) {

src/Resources/templates/widget.js

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
(function($) {
2+
3+
var csscls = PhpDebugBar.utils.makecsscls('phpdebugbar-widgets-');
4+
5+
/**
6+
* Widget for the displaying templates data
7+
*
8+
* Options:
9+
* - data
10+
*/
11+
var TemplatesWidget = PhpDebugBar.Widgets.LaravelViewTemplatesWidget = PhpDebugBar.Widget.extend({
12+
13+
className: csscls('templates'),
14+
15+
render: function() {
16+
this.$status = $('<div />').addClass(csscls('status')).appendTo(this.$el);
17+
18+
this.$list = new PhpDebugBar.Widgets.ListWidget({ itemRenderer: function(li, tpl) {
19+
$('<span />').addClass(csscls('name')).text(tpl.name).appendTo(li);
20+
21+
if (typeof tpl.editorLink !== 'undefined' && tpl.editorLink !== null) {
22+
$('<a href="' + tpl.editorLink + '"></a>')
23+
.addClass(csscls('editor-link'))
24+
.on('click', function (event) {
25+
event.stopPropagation();
26+
})
27+
.appendTo(li);
28+
}
29+
if (typeof tpl.xdebug_link !== 'undefined' && tpl.xdebug_link !== null) {
30+
if (tpl.xdebug_link.ajax) {
31+
$('<a title="' + tpl.xdebug_link.url + '"></a>').on('click', function () {
32+
$.ajax(tpl.xdebug_link.url);
33+
}).addClass(csscls('editor-link')).appendTo(li);
34+
} else {
35+
$('<a href="' + tpl.xdebug_link.url + '"></a>').addClass(csscls('editor-link')).appendTo(li);
36+
}
37+
}
38+
if (tpl.render_time_str) {
39+
$('<span title="Render time" />').addClass(csscls('render-time')).text(tpl.render_time_str).appendTo(li);
40+
}
41+
if (tpl.memory_str) {
42+
$('<span title="Memory usage" />').addClass(csscls('memory')).text(tpl.memory_str).appendTo(li);
43+
}
44+
if (typeof(tpl.param_count) != 'undefined') {
45+
$('<span title="Parameter count" />').addClass(csscls('param-count')).text(tpl.param_count).appendTo(li);
46+
}
47+
if (typeof(tpl.type) != 'undefined' && tpl.type) {
48+
$('<span title="Type" />').addClass(csscls('type')).text(tpl.type).appendTo(li);
49+
}
50+
if (tpl.params && !$.isEmptyObject(tpl.params)) {
51+
var table = $('<table><tr><th colspan="2">Params</th></tr></table>').addClass(csscls('params')).appendTo(li);
52+
for (var key in tpl.params) {
53+
if (typeof tpl.params[key] !== 'function') {
54+
table.append('<tr><td class="' + csscls('name') + '">' + key + '</td><td class="' + csscls('value') +
55+
'"><pre><code>' + tpl.params[key] + '</code></pre></td></tr>');
56+
}
57+
}
58+
li.css('cursor', 'pointer').click(function() {
59+
if (table.is(':visible')) {
60+
table.hide();
61+
} else {
62+
table.show();
63+
}
64+
});
65+
}
66+
}});
67+
this.$list.$el.appendTo(this.$el);
68+
this.$callgraph = $('<div />').addClass(csscls('callgraph')).appendTo(this.$el);
69+
70+
this.bindAttr('data', function(data) {
71+
this.$list.set('data', data.templates);
72+
this.$status.empty();
73+
this.$callgraph.empty();
74+
75+
var sentence = data.sentence || "templates were rendered";
76+
$('<span />').text(data.nb_templates + " " + sentence).appendTo(this.$status);
77+
78+
if (data.accumulated_render_time_str) {
79+
this.$status.append($('<span title="Accumulated render time" />').addClass(csscls('render-time')).text(data.accumulated_render_time_str));
80+
}
81+
if (data.memory_usage_str) {
82+
this.$status.append($('<span title="Memory usage" />').addClass(csscls('memory')).text(data.memory_usage_str));
83+
}
84+
if (data.nb_blocks > 0) {
85+
$('<div />').text(data.nb_blocks + " blocks were rendered").appendTo(this.$status);
86+
}
87+
if (data.nb_macros > 0) {
88+
$('<div />').text(data.nb_macros + " macros were rendered").appendTo(this.$status);
89+
}
90+
if (typeof data.callgraph !== 'undefined') {
91+
this.$callgraph.html(data.callgraph);
92+
}
93+
});
94+
}
95+
96+
});
97+
98+
})(PhpDebugBar.$);

0 commit comments

Comments
 (0)